On Fri, Oct 22, 2021 at 03:55:10PM +0800, Hou Tao wrote: > --- /dev/null > +++ b/net/bpf/bpf_dummy_struct_ops.c > @@ -0,0 +1,203 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2021. Huawei Technologies Co., Ltd > + */ > +#include <linux/kernel.h> > +#include <linux/bpf_verifier.h> > +#include <linux/bpf.h> > +#include <linux/btf.h> > + > +extern struct bpf_struct_ops bpf_bpf_dummy_ops; > + > +/* A common type for test_N with return value in bpf_dummy_ops */ > +typedef int (*dummy_ops_test_ret_fn)(struct bpf_dummy_ops_state *state, ...); > + > +struct bpf_dummy_ops_test_args { > + u64 args[MAX_BPF_FUNC_ARGS]; > + struct bpf_dummy_ops_state state; > +}; > + > +static struct bpf_dummy_ops_test_args * > +dummy_ops_init_args(const union bpf_attr *kattr, unsigned int nr) > +{ > + __u32 size_in; > + struct bpf_dummy_ops_test_args *args; > + void __user *ctx_in; > + void __user *u_state; > + > + if (!nr || nr > MAX_BPF_FUNC_ARGS) These checks are unnecessary and can be removed. They had already been checked by the verifier during the bpf prog load time. Others lgtm. Acked-by: Martin KaFai Lau <kafai@xxxxxx> > + return ERR_PTR(-EINVAL); > + > + size_in = kattr->test.ctx_size_in; > + if (size_in != sizeof(u64) * nr) > + return ERR_PTR(-EINVAL); > + > + args = kzalloc(sizeof(*args), GFP_KERNEL); > + if (!args) > + return ERR_PTR(-ENOMEM); > + > + ctx_in = u64_to_user_ptr(kattr->test.ctx_in); > + if (copy_from_user(args->args, ctx_in, size_in)) > + goto out; > + > + /* args[0] is 0 means state argument of test_N will be NULL */ > + u_state = u64_to_user_ptr(args->args[0]); > + if (u_state && copy_from_user(&args->state, u_state, > + sizeof(args->state))) > + goto out; > + > + return args; > +out: > + kfree(args); > + return ERR_PTR(-EFAULT); > +} [ ... ] > +int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr, > + union bpf_attr __user *uattr) > +{ > + const struct bpf_struct_ops *st_ops = &bpf_bpf_dummy_ops; > + const struct btf_type *func_proto; > + struct bpf_dummy_ops_test_args *args; > + struct bpf_tramp_progs *tprogs; > + void *image = NULL; > + unsigned int op_idx; > + int prog_ret; > + int err; > + > + if (prog->aux->attach_btf_id != st_ops->type_id) > + return -EOPNOTSUPP; > + > + func_proto = prog->aux->attach_func_proto; > + args = dummy_ops_init_args(kattr, btf_type_vlen(func_proto)); > + if (IS_ERR(args)) > + return PTR_ERR(args);