OSDN Git Service

bpf_obj_do_pin(): switch to vfs_mkobj(), quit abusing ->mknod()
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 1 Dec 2017 22:22:19 +0000 (17:22 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 5 Jan 2018 16:54:33 +0000 (11:54 -0500)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
kernel/bpf/inode.c

index 01aaef1..2b75fac 100644 (file)
@@ -150,39 +150,29 @@ static int bpf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        return 0;
 }
 
-static int bpf_mkobj_ops(struct inode *dir, struct dentry *dentry,
-                        umode_t mode, const struct inode_operations *iops)
+static int bpf_mkobj_ops(struct dentry *dentry, umode_t mode, void *raw,
+                        const struct inode_operations *iops)
 {
-       struct inode *inode;
-
-       inode = bpf_get_inode(dir->i_sb, dir, mode | S_IFREG);
+       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *inode = bpf_get_inode(dir->i_sb, dir, mode);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
        inode->i_op = iops;
-       inode->i_private = dentry->d_fsdata;
+       inode->i_private = raw;
 
        bpf_dentry_finalize(dentry, inode, dir);
        return 0;
 }
 
-static int bpf_mkobj(struct inode *dir, struct dentry *dentry, umode_t mode,
-                    dev_t devt)
+static int bpf_mkprog(struct dentry *dentry, umode_t mode, void *arg)
 {
-       enum bpf_type type = MINOR(devt);
-
-       if (MAJOR(devt) != UNNAMED_MAJOR || !S_ISREG(mode) ||
-           dentry->d_fsdata == NULL)
-               return -EPERM;
+       return bpf_mkobj_ops(dentry, mode, arg, &bpf_prog_iops);
+}
 
-       switch (type) {
-       case BPF_TYPE_PROG:
-               return bpf_mkobj_ops(dir, dentry, mode, &bpf_prog_iops);
-       case BPF_TYPE_MAP:
-               return bpf_mkobj_ops(dir, dentry, mode, &bpf_map_iops);
-       default:
-               return -EPERM;
-       }
+static int bpf_mkmap(struct dentry *dentry, umode_t mode, void *arg)
+{
+       return bpf_mkobj_ops(dentry, mode, arg, &bpf_map_iops);
 }
 
 static struct dentry *
@@ -218,7 +208,6 @@ static int bpf_symlink(struct inode *dir, struct dentry *dentry,
 
 static const struct inode_operations bpf_dir_iops = {
        .lookup         = bpf_lookup,
-       .mknod          = bpf_mkobj,
        .mkdir          = bpf_mkdir,
        .symlink        = bpf_symlink,
        .rmdir          = simple_rmdir,
@@ -234,7 +223,6 @@ static int bpf_obj_do_pin(const struct filename *pathname, void *raw,
        struct inode *dir;
        struct path path;
        umode_t mode;
-       dev_t devt;
        int ret;
 
        dentry = kern_path_create(AT_FDCWD, pathname->name, &path, 0);
@@ -242,9 +230,8 @@ static int bpf_obj_do_pin(const struct filename *pathname, void *raw,
                return PTR_ERR(dentry);
 
        mode = S_IFREG | ((S_IRUSR | S_IWUSR) & ~current_umask());
-       devt = MKDEV(UNNAMED_MAJOR, type);
 
-       ret = security_path_mknod(&path, dentry, mode, devt);
+       ret = security_path_mknod(&path, dentry, mode, 0);
        if (ret)
                goto out;
 
@@ -254,9 +241,16 @@ static int bpf_obj_do_pin(const struct filename *pathname, void *raw,
                goto out;
        }
 
-       dentry->d_fsdata = raw;
-       ret = vfs_mknod(dir, dentry, mode, devt);
-       dentry->d_fsdata = NULL;
+       switch (type) {
+       case BPF_TYPE_PROG:
+               ret = vfs_mkobj(dentry, mode, bpf_mkprog, raw);
+               break;
+       case BPF_TYPE_MAP:
+               ret = vfs_mkobj(dentry, mode, bpf_mkmap, raw);
+               break;
+       default:
+               ret = -EPERM;
+       }
 out:
        done_path_create(&path, dentry);
        return ret;