예제 #1
0
static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
                                      struct nameidata *nd)
{
    struct ctl_table_header *head = grab_header(dir);
    struct ctl_table *table = PROC_I(dir)->sysctl_entry;
    struct ctl_table_header *h = NULL;
    struct qstr *name = &dentry->d_name;
    struct ctl_table *p;
    struct inode *inode;
    struct dentry *err = ERR_PTR(-ENOENT);

    if (IS_ERR(head))
        return ERR_CAST(head);

    if (table && !table->child) {
        WARN_ON(1);
        goto out;
    }

    table = table ? table->child : head->ctl_table;

    p = find_in_table(table, name);
    if (!p) {
        for (h = sysctl_head_next(NULL); h; h = sysctl_head_next(h)) {
            if (h->attached_to != table)
                continue;
            p = find_in_table(h->attached_by, name);
            if (p)
                break;
        }
    }

    if (!p)
        goto out;

    if (gr_handle_sysctl(p, MAY_EXEC))
        goto out;

    err = ERR_PTR(-ENOMEM);
    inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p);
    if (h)
        sysctl_head_finish(h);

    if (!inode)
        goto out;

    err = NULL;
    d_set_d_op(dentry, &proc_sys_dentry_operations);
    d_add(dentry, inode);

out:
    sysctl_head_finish(head);
    return err;
}
예제 #2
0
static int proc_sys_fill_cache(struct file *filp, void *dirent,
				filldir_t filldir,
				struct ctl_table_header *head,
				struct ctl_table *table)
{
	struct dentry *child, *dir = filp->f_path.dentry;
	struct inode *inode;
	struct qstr qname;
	ino_t ino = 0;
	unsigned type = DT_UNKNOWN;

	qname.name = table->procname;
	qname.len  = strlen(table->procname);
	qname.hash = full_name_hash(qname.name, qname.len);

	child = d_lookup(dir, &qname);
	if (!child) {
		child = d_alloc(dir, &qname);
		if (child) {
			inode = proc_sys_make_inode(dir->d_sb, head, table);
			if (!inode) {
				dput(child);
				return -ENOMEM;
			} else {
				d_set_d_op(child, &proc_sys_dentry_operations);
				d_add(child, inode);
			}
		} else {
			return -ENOMEM;
		}
	}
	inode = child->d_inode;
	ino  = inode->i_ino;
	type = inode->i_mode >> 12;
	dput(child);
	return !!filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type);
}