bpf: convert bpf_token_create() to CLASS(fd, ...)
Keep file reference through the entire thing, don't bother with grabbing struct path reference and while we are at it, don't confuse the hell out of readers by random mix of path.dentry->d_sb and path.mnt->mnt_sb uses - these two are equal, so just put one of those into a local variable and use that. Reviewed-by: Christian Brauner <brauner@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
This commit is contained in:
parent
433d7ce2d8
commit
37d3dd663f
@ -116,67 +116,52 @@ int bpf_token_create(union bpf_attr *attr)
|
|||||||
struct user_namespace *userns;
|
struct user_namespace *userns;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
CLASS(fd, f)(attr->token_create.bpffs_fd);
|
||||||
struct path path;
|
struct path path;
|
||||||
struct fd f;
|
struct super_block *sb;
|
||||||
umode_t mode;
|
umode_t mode;
|
||||||
int err, fd;
|
int err, fd;
|
||||||
|
|
||||||
f = fdget(attr->token_create.bpffs_fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
path = fd_file(f)->f_path;
|
path = fd_file(f)->f_path;
|
||||||
path_get(&path);
|
sb = path.dentry->d_sb;
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
if (path.dentry != path.mnt->mnt_sb->s_root) {
|
if (path.dentry != sb->s_root)
|
||||||
err = -EINVAL;
|
return -EINVAL;
|
||||||
goto out_path;
|
if (sb->s_op != &bpf_super_ops)
|
||||||
}
|
return -EINVAL;
|
||||||
if (path.mnt->mnt_sb->s_op != &bpf_super_ops) {
|
|
||||||
err = -EINVAL;
|
|
||||||
goto out_path;
|
|
||||||
}
|
|
||||||
err = path_permission(&path, MAY_ACCESS);
|
err = path_permission(&path, MAY_ACCESS);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_path;
|
return err;
|
||||||
|
|
||||||
userns = path.dentry->d_sb->s_user_ns;
|
userns = sb->s_user_ns;
|
||||||
/*
|
/*
|
||||||
* Enforce that creators of BPF tokens are in the same user
|
* Enforce that creators of BPF tokens are in the same user
|
||||||
* namespace as the BPF FS instance. This makes reasoning about
|
* namespace as the BPF FS instance. This makes reasoning about
|
||||||
* permissions a lot easier and we can always relax this later.
|
* permissions a lot easier and we can always relax this later.
|
||||||
*/
|
*/
|
||||||
if (current_user_ns() != userns) {
|
if (current_user_ns() != userns)
|
||||||
err = -EPERM;
|
return -EPERM;
|
||||||
goto out_path;
|
if (!ns_capable(userns, CAP_BPF))
|
||||||
}
|
return -EPERM;
|
||||||
if (!ns_capable(userns, CAP_BPF)) {
|
|
||||||
err = -EPERM;
|
|
||||||
goto out_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Creating BPF token in init_user_ns doesn't make much sense. */
|
/* Creating BPF token in init_user_ns doesn't make much sense. */
|
||||||
if (current_user_ns() == &init_user_ns) {
|
if (current_user_ns() == &init_user_ns)
|
||||||
err = -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
goto out_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
mnt_opts = path.dentry->d_sb->s_fs_info;
|
mnt_opts = sb->s_fs_info;
|
||||||
if (mnt_opts->delegate_cmds == 0 &&
|
if (mnt_opts->delegate_cmds == 0 &&
|
||||||
mnt_opts->delegate_maps == 0 &&
|
mnt_opts->delegate_maps == 0 &&
|
||||||
mnt_opts->delegate_progs == 0 &&
|
mnt_opts->delegate_progs == 0 &&
|
||||||
mnt_opts->delegate_attachs == 0) {
|
mnt_opts->delegate_attachs == 0)
|
||||||
err = -ENOENT; /* no BPF token delegation is set up */
|
return -ENOENT; /* no BPF token delegation is set up */
|
||||||
goto out_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
mode = S_IFREG | ((S_IRUSR | S_IWUSR) & ~current_umask());
|
mode = S_IFREG | ((S_IRUSR | S_IWUSR) & ~current_umask());
|
||||||
inode = bpf_get_inode(path.mnt->mnt_sb, NULL, mode);
|
inode = bpf_get_inode(sb, NULL, mode);
|
||||||
if (IS_ERR(inode)) {
|
if (IS_ERR(inode))
|
||||||
err = PTR_ERR(inode);
|
return PTR_ERR(inode);
|
||||||
goto out_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
inode->i_op = &bpf_token_iops;
|
inode->i_op = &bpf_token_iops;
|
||||||
inode->i_fop = &bpf_token_fops;
|
inode->i_fop = &bpf_token_fops;
|
||||||
@ -185,8 +170,7 @@ int bpf_token_create(union bpf_attr *attr)
|
|||||||
file = alloc_file_pseudo(inode, path.mnt, BPF_TOKEN_INODE_NAME, O_RDWR, &bpf_token_fops);
|
file = alloc_file_pseudo(inode, path.mnt, BPF_TOKEN_INODE_NAME, O_RDWR, &bpf_token_fops);
|
||||||
if (IS_ERR(file)) {
|
if (IS_ERR(file)) {
|
||||||
iput(inode);
|
iput(inode);
|
||||||
err = PTR_ERR(file);
|
return PTR_ERR(file);
|
||||||
goto out_path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
token = kzalloc(sizeof(*token), GFP_USER);
|
token = kzalloc(sizeof(*token), GFP_USER);
|
||||||
@ -218,15 +202,12 @@ int bpf_token_create(union bpf_attr *attr)
|
|||||||
file->private_data = token;
|
file->private_data = token;
|
||||||
fd_install(fd, file);
|
fd_install(fd, file);
|
||||||
|
|
||||||
path_put(&path);
|
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
out_token:
|
out_token:
|
||||||
bpf_token_free(token);
|
bpf_token_free(token);
|
||||||
out_file:
|
out_file:
|
||||||
fput(file);
|
fput(file);
|
||||||
out_path:
|
|
||||||
path_put(&path);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user