Commit af2ac3e1 authored by Alexei Starovoitov's avatar Alexei Starovoitov Committed by Daniel Borkmann

bpf: Prepare bpf syscall to be used from kernel and user space.

With the help from bpfptr_t prepare relevant bpf syscall commands
to be used from kernel and user space.
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20210514003623.28033-4-alexei.starovoitov@gmail.com
parent cdf7fb0a
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/sched/mm.h> #include <linux/sched/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/percpu-refcount.h> #include <linux/percpu-refcount.h>
#include <linux/bpfptr.h>
struct bpf_verifier_env; struct bpf_verifier_env;
struct bpf_verifier_log; struct bpf_verifier_log;
...@@ -1428,7 +1429,7 @@ struct bpf_iter__bpf_map_elem { ...@@ -1428,7 +1429,7 @@ struct bpf_iter__bpf_map_elem {
int bpf_iter_reg_target(const struct bpf_iter_reg *reg_info); int bpf_iter_reg_target(const struct bpf_iter_reg *reg_info);
void bpf_iter_unreg_target(const struct bpf_iter_reg *reg_info); void bpf_iter_unreg_target(const struct bpf_iter_reg *reg_info);
bool bpf_iter_prog_supported(struct bpf_prog *prog); bool bpf_iter_prog_supported(struct bpf_prog *prog);
int bpf_iter_link_attach(const union bpf_attr *attr, struct bpf_prog *prog); int bpf_iter_link_attach(const union bpf_attr *attr, bpfptr_t uattr, struct bpf_prog *prog);
int bpf_iter_new_fd(struct bpf_link *link); int bpf_iter_new_fd(struct bpf_link *link);
bool bpf_link_is_iter(struct bpf_link *link); bool bpf_link_is_iter(struct bpf_link *link);
struct bpf_prog *bpf_iter_get_info(struct bpf_iter_meta *meta, bool in_stop); struct bpf_prog *bpf_iter_get_info(struct bpf_iter_meta *meta, bool in_stop);
...@@ -1459,7 +1460,7 @@ int bpf_fd_htab_map_update_elem(struct bpf_map *map, struct file *map_file, ...@@ -1459,7 +1460,7 @@ int bpf_fd_htab_map_update_elem(struct bpf_map *map, struct file *map_file,
int bpf_fd_htab_map_lookup_elem(struct bpf_map *map, void *key, u32 *value); int bpf_fd_htab_map_lookup_elem(struct bpf_map *map, void *key, u32 *value);
int bpf_get_file_flag(int flags); int bpf_get_file_flag(int flags);
int bpf_check_uarg_tail_zero(void __user *uaddr, size_t expected_size, int bpf_check_uarg_tail_zero(bpfptr_t uaddr, size_t expected_size,
size_t actual_size); size_t actual_size);
/* memcpy that is used with 8-byte aligned pointers, power-of-8 size and /* memcpy that is used with 8-byte aligned pointers, power-of-8 size and
...@@ -1479,8 +1480,7 @@ static inline void bpf_long_memcpy(void *dst, const void *src, u32 size) ...@@ -1479,8 +1480,7 @@ static inline void bpf_long_memcpy(void *dst, const void *src, u32 size)
} }
/* verify correctness of eBPF program */ /* verify correctness of eBPF program */
int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, bpfptr_t uattr);
union bpf_attr __user *uattr);
#ifndef CONFIG_BPF_JIT_ALWAYS_ON #ifndef CONFIG_BPF_JIT_ALWAYS_ON
void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth); void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
......
...@@ -473,15 +473,16 @@ bool bpf_link_is_iter(struct bpf_link *link) ...@@ -473,15 +473,16 @@ bool bpf_link_is_iter(struct bpf_link *link)
return link->ops == &bpf_iter_link_lops; return link->ops == &bpf_iter_link_lops;
} }
int bpf_iter_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) int bpf_iter_link_attach(const union bpf_attr *attr, bpfptr_t uattr,
struct bpf_prog *prog)
{ {
union bpf_iter_link_info __user *ulinfo;
struct bpf_link_primer link_primer; struct bpf_link_primer link_primer;
struct bpf_iter_target_info *tinfo; struct bpf_iter_target_info *tinfo;
union bpf_iter_link_info linfo; union bpf_iter_link_info linfo;
struct bpf_iter_link *link; struct bpf_iter_link *link;
u32 prog_btf_id, linfo_len; u32 prog_btf_id, linfo_len;
bool existed = false; bool existed = false;
bpfptr_t ulinfo;
int err; int err;
if (attr->link_create.target_fd || attr->link_create.flags) if (attr->link_create.target_fd || attr->link_create.flags)
...@@ -489,18 +490,18 @@ int bpf_iter_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) ...@@ -489,18 +490,18 @@ int bpf_iter_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
memset(&linfo, 0, sizeof(union bpf_iter_link_info)); memset(&linfo, 0, sizeof(union bpf_iter_link_info));
ulinfo = u64_to_user_ptr(attr->link_create.iter_info); ulinfo = make_bpfptr(attr->link_create.iter_info, uattr.is_kernel);
linfo_len = attr->link_create.iter_info_len; linfo_len = attr->link_create.iter_info_len;
if (!ulinfo ^ !linfo_len) if (bpfptr_is_null(ulinfo) ^ !linfo_len)
return -EINVAL; return -EINVAL;
if (ulinfo) { if (!bpfptr_is_null(ulinfo)) {
err = bpf_check_uarg_tail_zero(ulinfo, sizeof(linfo), err = bpf_check_uarg_tail_zero(ulinfo, sizeof(linfo),
linfo_len); linfo_len);
if (err) if (err)
return err; return err;
linfo_len = min_t(u32, linfo_len, sizeof(linfo)); linfo_len = min_t(u32, linfo_len, sizeof(linfo));
if (copy_from_user(&linfo, ulinfo, linfo_len)) if (copy_from_bpfptr(&linfo, ulinfo, linfo_len))
return -EFAULT; return -EFAULT;
} }
......
This diff is collapsed.
...@@ -9436,7 +9436,7 @@ static int check_abnormal_return(struct bpf_verifier_env *env) ...@@ -9436,7 +9436,7 @@ static int check_abnormal_return(struct bpf_verifier_env *env)
static int check_btf_func(struct bpf_verifier_env *env, static int check_btf_func(struct bpf_verifier_env *env,
const union bpf_attr *attr, const union bpf_attr *attr,
union bpf_attr __user *uattr) bpfptr_t uattr)
{ {
const struct btf_type *type, *func_proto, *ret_type; const struct btf_type *type, *func_proto, *ret_type;
u32 i, nfuncs, urec_size, min_size; u32 i, nfuncs, urec_size, min_size;
...@@ -9445,7 +9445,7 @@ static int check_btf_func(struct bpf_verifier_env *env, ...@@ -9445,7 +9445,7 @@ static int check_btf_func(struct bpf_verifier_env *env,
struct bpf_func_info_aux *info_aux = NULL; struct bpf_func_info_aux *info_aux = NULL;
struct bpf_prog *prog; struct bpf_prog *prog;
const struct btf *btf; const struct btf *btf;
void __user *urecord; bpfptr_t urecord;
u32 prev_offset = 0; u32 prev_offset = 0;
bool scalar_return; bool scalar_return;
int ret = -ENOMEM; int ret = -ENOMEM;
...@@ -9473,7 +9473,7 @@ static int check_btf_func(struct bpf_verifier_env *env, ...@@ -9473,7 +9473,7 @@ static int check_btf_func(struct bpf_verifier_env *env,
prog = env->prog; prog = env->prog;
btf = prog->aux->btf; btf = prog->aux->btf;
urecord = u64_to_user_ptr(attr->func_info); urecord = make_bpfptr(attr->func_info, uattr.is_kernel);
min_size = min_t(u32, krec_size, urec_size); min_size = min_t(u32, krec_size, urec_size);
krecord = kvcalloc(nfuncs, krec_size, GFP_KERNEL | __GFP_NOWARN); krecord = kvcalloc(nfuncs, krec_size, GFP_KERNEL | __GFP_NOWARN);
...@@ -9491,13 +9491,15 @@ static int check_btf_func(struct bpf_verifier_env *env, ...@@ -9491,13 +9491,15 @@ static int check_btf_func(struct bpf_verifier_env *env,
/* set the size kernel expects so loader can zero /* set the size kernel expects so loader can zero
* out the rest of the record. * out the rest of the record.
*/ */
if (put_user(min_size, &uattr->func_info_rec_size)) if (copy_to_bpfptr_offset(uattr,
offsetof(union bpf_attr, func_info_rec_size),
&min_size, sizeof(min_size)))
ret = -EFAULT; ret = -EFAULT;
} }
goto err_free; goto err_free;
} }
if (copy_from_user(&krecord[i], urecord, min_size)) { if (copy_from_bpfptr(&krecord[i], urecord, min_size)) {
ret = -EFAULT; ret = -EFAULT;
goto err_free; goto err_free;
} }
...@@ -9549,7 +9551,7 @@ static int check_btf_func(struct bpf_verifier_env *env, ...@@ -9549,7 +9551,7 @@ static int check_btf_func(struct bpf_verifier_env *env,
} }
prev_offset = krecord[i].insn_off; prev_offset = krecord[i].insn_off;
urecord += urec_size; bpfptr_add(&urecord, urec_size);
} }
prog->aux->func_info = krecord; prog->aux->func_info = krecord;
...@@ -9581,14 +9583,14 @@ static void adjust_btf_func(struct bpf_verifier_env *env) ...@@ -9581,14 +9583,14 @@ static void adjust_btf_func(struct bpf_verifier_env *env)
static int check_btf_line(struct bpf_verifier_env *env, static int check_btf_line(struct bpf_verifier_env *env,
const union bpf_attr *attr, const union bpf_attr *attr,
union bpf_attr __user *uattr) bpfptr_t uattr)
{ {
u32 i, s, nr_linfo, ncopy, expected_size, rec_size, prev_offset = 0; u32 i, s, nr_linfo, ncopy, expected_size, rec_size, prev_offset = 0;
struct bpf_subprog_info *sub; struct bpf_subprog_info *sub;
struct bpf_line_info *linfo; struct bpf_line_info *linfo;
struct bpf_prog *prog; struct bpf_prog *prog;
const struct btf *btf; const struct btf *btf;
void __user *ulinfo; bpfptr_t ulinfo;
int err; int err;
nr_linfo = attr->line_info_cnt; nr_linfo = attr->line_info_cnt;
...@@ -9614,7 +9616,7 @@ static int check_btf_line(struct bpf_verifier_env *env, ...@@ -9614,7 +9616,7 @@ static int check_btf_line(struct bpf_verifier_env *env,
s = 0; s = 0;
sub = env->subprog_info; sub = env->subprog_info;
ulinfo = u64_to_user_ptr(attr->line_info); ulinfo = make_bpfptr(attr->line_info, uattr.is_kernel);
expected_size = sizeof(struct bpf_line_info); expected_size = sizeof(struct bpf_line_info);
ncopy = min_t(u32, expected_size, rec_size); ncopy = min_t(u32, expected_size, rec_size);
for (i = 0; i < nr_linfo; i++) { for (i = 0; i < nr_linfo; i++) {
...@@ -9622,14 +9624,15 @@ static int check_btf_line(struct bpf_verifier_env *env, ...@@ -9622,14 +9624,15 @@ static int check_btf_line(struct bpf_verifier_env *env,
if (err) { if (err) {
if (err == -E2BIG) { if (err == -E2BIG) {
verbose(env, "nonzero tailing record in line_info"); verbose(env, "nonzero tailing record in line_info");
if (put_user(expected_size, if (copy_to_bpfptr_offset(uattr,
&uattr->line_info_rec_size)) offsetof(union bpf_attr, line_info_rec_size),
&expected_size, sizeof(expected_size)))
err = -EFAULT; err = -EFAULT;
} }
goto err_free; goto err_free;
} }
if (copy_from_user(&linfo[i], ulinfo, ncopy)) { if (copy_from_bpfptr(&linfo[i], ulinfo, ncopy)) {
err = -EFAULT; err = -EFAULT;
goto err_free; goto err_free;
} }
...@@ -9681,7 +9684,7 @@ static int check_btf_line(struct bpf_verifier_env *env, ...@@ -9681,7 +9684,7 @@ static int check_btf_line(struct bpf_verifier_env *env,
} }
prev_offset = linfo[i].insn_off; prev_offset = linfo[i].insn_off;
ulinfo += rec_size; bpfptr_add(&ulinfo, rec_size);
} }
if (s != env->subprog_cnt) { if (s != env->subprog_cnt) {
...@@ -9703,7 +9706,7 @@ static int check_btf_line(struct bpf_verifier_env *env, ...@@ -9703,7 +9706,7 @@ static int check_btf_line(struct bpf_verifier_env *env,
static int check_btf_info(struct bpf_verifier_env *env, static int check_btf_info(struct bpf_verifier_env *env,
const union bpf_attr *attr, const union bpf_attr *attr,
union bpf_attr __user *uattr) bpfptr_t uattr)
{ {
struct btf *btf; struct btf *btf;
int err; int err;
...@@ -13275,8 +13278,7 @@ struct btf *bpf_get_btf_vmlinux(void) ...@@ -13275,8 +13278,7 @@ struct btf *bpf_get_btf_vmlinux(void)
return btf_vmlinux; return btf_vmlinux;
} }
int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr)
union bpf_attr __user *uattr)
{ {
u64 start_time = ktime_get_ns(); u64 start_time = ktime_get_ns();
struct bpf_verifier_env *env; struct bpf_verifier_env *env;
......
...@@ -409,7 +409,7 @@ static void *bpf_ctx_init(const union bpf_attr *kattr, u32 max_size) ...@@ -409,7 +409,7 @@ static void *bpf_ctx_init(const union bpf_attr *kattr, u32 max_size)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
if (data_in) { if (data_in) {
err = bpf_check_uarg_tail_zero(data_in, max_size, size); err = bpf_check_uarg_tail_zero(USER_BPFPTR(data_in), max_size, size);
if (err) { if (err) {
kfree(data); kfree(data);
return ERR_PTR(err); return ERR_PTR(err);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment