Now bpf syscall prog is able to pin bpf objects into bpffs and get a pinned object from file system. Combining the previous patch that introduced the helpers for creating and deleting directories in bpffs, syscall prog can now persist bpf objects and organize them in a directory hierarchy. Signed-off-by: Hao Luo <haoluo@xxxxxxxxxx> --- include/linux/bpf.h | 4 ++-- kernel/bpf/inode.c | 24 ++++++++++++++++++------ kernel/bpf/syscall.c | 21 ++++++++++++++------- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index fce5e26179f5..c36eeced3838 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1585,8 +1585,8 @@ struct file *bpf_link_new_file(struct bpf_link *link, int *reserved_fd); struct bpf_link *bpf_link_get_from_fd(u32 ufd); bool bpf_path_is_bpf_dir(const struct path *path); -int bpf_obj_pin_user(u32 ufd, const char __user *pathname); -int bpf_obj_get_user(const char __user *pathname, int flags); +int bpf_obj_pin_path(u32 ufd, bpfptr_t pathname); +int bpf_obj_get_path(bpfptr_t pathname, int flags); #define BPF_ITER_FUNC_PREFIX "bpf_iter_" #define DEFINE_BPF_ITER_FUNC(target, args...) \ diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index 3aca00e9e950..6c2db54a2ff9 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c @@ -440,7 +440,7 @@ static int bpf_iter_link_pin_kernel(struct dentry *parent, return ret; } -static int bpf_obj_do_pin(const char __user *pathname, void *raw, +static int bpf_obj_do_pin(bpfptr_t pathname, void *raw, enum bpf_type type) { struct dentry *dentry; @@ -448,7 +448,13 @@ static int bpf_obj_do_pin(const char __user *pathname, void *raw, umode_t mode; int ret; - dentry = user_path_create(AT_FDCWD, pathname, &path, 0); + if (bpfptr_is_null(pathname)) + return -EINVAL; + + if (bpfptr_is_kernel(pathname)) + dentry = kern_path_create(AT_FDCWD, pathname.kernel, &path, 0); + else + dentry = user_path_create(AT_FDCWD, pathname.user, &path, 0); if (IS_ERR(dentry)) return PTR_ERR(dentry); @@ -481,7 +487,7 @@ static int bpf_obj_do_pin(const char __user *pathname, void *raw, return ret; } -int bpf_obj_pin_user(u32 ufd, const char __user *pathname) +int bpf_obj_pin_path(u32 ufd, bpfptr_t pathname) { enum bpf_type type; void *raw; @@ -498,7 +504,7 @@ int bpf_obj_pin_user(u32 ufd, const char __user *pathname) return ret; } -static void *bpf_obj_do_get(const char __user *pathname, +static void *bpf_obj_do_get(bpfptr_t pathname, enum bpf_type *type, int flags) { struct inode *inode; @@ -506,7 +512,13 @@ static void *bpf_obj_do_get(const char __user *pathname, void *raw; int ret; - ret = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW, &path); + if (bpfptr_is_null(pathname)) + return ERR_PTR(-EINVAL); + + if (bpfptr_is_kernel(pathname)) + ret = kern_path(pathname.kernel, LOOKUP_FOLLOW, &path); + else + ret = user_path_at(AT_FDCWD, pathname.user, LOOKUP_FOLLOW, &path); if (ret) return ERR_PTR(ret); @@ -530,7 +542,7 @@ static void *bpf_obj_do_get(const char __user *pathname, return ERR_PTR(ret); } -int bpf_obj_get_user(const char __user *pathname, int flags) +int bpf_obj_get_path(bpfptr_t pathname, int flags) { enum bpf_type type = BPF_TYPE_UNSPEC; int f_flags; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 07683b791733..9e6d8d0c8af5 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -2402,22 +2402,27 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr) #define BPF_OBJ_LAST_FIELD file_flags -static int bpf_obj_pin(const union bpf_attr *attr) +static int bpf_obj_pin(const union bpf_attr *attr, bpfptr_t uattr) { + bpfptr_t pathname; + if (CHECK_ATTR(BPF_OBJ) || attr->file_flags != 0) return -EINVAL; - return bpf_obj_pin_user(attr->bpf_fd, u64_to_user_ptr(attr->pathname)); + pathname = make_bpfptr(attr->pathname, bpfptr_is_kernel(uattr)); + return bpf_obj_pin_path(attr->bpf_fd, pathname); } -static int bpf_obj_get(const union bpf_attr *attr) +static int bpf_obj_get(const union bpf_attr *attr, bpfptr_t uattr) { + bpfptr_t pathname; + if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0 || attr->file_flags & ~BPF_OBJ_FLAG_MASK) return -EINVAL; - return bpf_obj_get_user(u64_to_user_ptr(attr->pathname), - attr->file_flags); + pathname = make_bpfptr(attr->pathname, bpfptr_is_kernel(uattr)); + return bpf_obj_get_path(pathname, attr->file_flags); } void bpf_link_init(struct bpf_link *link, enum bpf_link_type type, @@ -4648,10 +4653,10 @@ static int __sys_bpf(int cmd, bpfptr_t uattr, unsigned int size) err = bpf_prog_load(&attr, uattr); break; case BPF_OBJ_PIN: - err = bpf_obj_pin(&attr); + err = bpf_obj_pin(&attr, uattr); break; case BPF_OBJ_GET: - err = bpf_obj_get(&attr); + err = bpf_obj_get(&attr, uattr); break; case BPF_PROG_ATTACH: err = bpf_prog_attach(&attr); @@ -4776,6 +4781,8 @@ BPF_CALL_3(bpf_sys_bpf, int, cmd, union bpf_attr *, attr, u32, attr_size) case BPF_BTF_LOAD: case BPF_LINK_CREATE: case BPF_RAW_TRACEPOINT_OPEN: + case BPF_OBJ_PIN: + case BPF_OBJ_GET: break; #ifdef CONFIG_BPF_JIT /* __bpf_prog_enter_sleepable used by trampoline and JIT */ case BPF_PROG_TEST_RUN: -- 2.35.1.574.g5d30c73bfb-goog