Commit 980ca8ce authored by Eduard Zingerman's avatar Eduard Zingerman Committed by Alexei Starovoitov

bpf: check bpf_dummy_struct_ops program params for test runs

When doing BPF_PROG_TEST_RUN for bpf_dummy_struct_ops programs,
reject execution when NULL is passed for non-nullable params.
For programs with non-nullable params verifier assumes that
such params are never NULL and thus might optimize out NULL checks.
Suggested-by: default avatarKui-Feng Lee <sinquersw@gmail.com>
Signed-off-by: default avatarEduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20240424012821.595216-5-eddyz87@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent f612210d
...@@ -79,6 +79,51 @@ static int dummy_ops_call_op(void *image, struct bpf_dummy_ops_test_args *args) ...@@ -79,6 +79,51 @@ static int dummy_ops_call_op(void *image, struct bpf_dummy_ops_test_args *args)
args->args[3], args->args[4]); args->args[3], args->args[4]);
} }
static const struct bpf_ctx_arg_aux *find_ctx_arg_info(struct bpf_prog_aux *aux, int offset)
{
int i;
for (i = 0; i < aux->ctx_arg_info_size; i++)
if (aux->ctx_arg_info[i].offset == offset)
return &aux->ctx_arg_info[i];
return NULL;
}
/* There is only one check at the moment:
* - zero should not be passed for pointer parameters not marked as nullable.
*/
static int check_test_run_args(struct bpf_prog *prog, struct bpf_dummy_ops_test_args *args)
{
const struct btf_type *func_proto = prog->aux->attach_func_proto;
for (u32 arg_no = 0; arg_no < btf_type_vlen(func_proto) ; ++arg_no) {
const struct btf_param *param = &btf_params(func_proto)[arg_no];
const struct bpf_ctx_arg_aux *info;
const struct btf_type *t;
int offset;
if (args->args[arg_no] != 0)
continue;
/* Program is validated already, so there is no need
* to check if t is NULL.
*/
t = btf_type_skip_modifiers(bpf_dummy_ops_btf, param->type, NULL);
if (!btf_type_is_ptr(t))
continue;
offset = btf_ctx_arg_offset(bpf_dummy_ops_btf, func_proto, arg_no);
info = find_ctx_arg_info(prog->aux, offset);
if (info && (info->reg_type & PTR_MAYBE_NULL))
continue;
return -EINVAL;
}
return 0;
}
extern const struct bpf_link_ops bpf_struct_ops_link_lops; extern const struct bpf_link_ops bpf_struct_ops_link_lops;
int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr,
...@@ -87,7 +132,7 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, ...@@ -87,7 +132,7 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr,
const struct bpf_struct_ops *st_ops = &bpf_bpf_dummy_ops; const struct bpf_struct_ops *st_ops = &bpf_bpf_dummy_ops;
const struct btf_type *func_proto; const struct btf_type *func_proto;
struct bpf_dummy_ops_test_args *args; struct bpf_dummy_ops_test_args *args;
struct bpf_tramp_links *tlinks; struct bpf_tramp_links *tlinks = NULL;
struct bpf_tramp_link *link = NULL; struct bpf_tramp_link *link = NULL;
void *image = NULL; void *image = NULL;
unsigned int op_idx; unsigned int op_idx;
...@@ -109,6 +154,10 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, ...@@ -109,6 +154,10 @@ int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr,
if (IS_ERR(args)) if (IS_ERR(args))
return PTR_ERR(args); return PTR_ERR(args);
err = check_test_run_args(prog, args);
if (err)
goto out;
tlinks = kcalloc(BPF_TRAMP_MAX, sizeof(*tlinks), GFP_KERNEL); tlinks = kcalloc(BPF_TRAMP_MAX, sizeof(*tlinks), GFP_KERNEL);
if (!tlinks) { if (!tlinks) {
err = -ENOMEM; err = -ENOMEM;
......
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