Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2021. Huawei Technologies Co., Ltd
0004  */
0005 #include <linux/kernel.h>
0006 #include <linux/bpf_verifier.h>
0007 #include <linux/bpf.h>
0008 #include <linux/btf.h>
0009 
0010 extern struct bpf_struct_ops bpf_bpf_dummy_ops;
0011 
0012 /* A common type for test_N with return value in bpf_dummy_ops */
0013 typedef int (*dummy_ops_test_ret_fn)(struct bpf_dummy_ops_state *state, ...);
0014 
0015 struct bpf_dummy_ops_test_args {
0016     u64 args[MAX_BPF_FUNC_ARGS];
0017     struct bpf_dummy_ops_state state;
0018 };
0019 
0020 static struct bpf_dummy_ops_test_args *
0021 dummy_ops_init_args(const union bpf_attr *kattr, unsigned int nr)
0022 {
0023     __u32 size_in;
0024     struct bpf_dummy_ops_test_args *args;
0025     void __user *ctx_in;
0026     void __user *u_state;
0027 
0028     size_in = kattr->test.ctx_size_in;
0029     if (size_in != sizeof(u64) * nr)
0030         return ERR_PTR(-EINVAL);
0031 
0032     args = kzalloc(sizeof(*args), GFP_KERNEL);
0033     if (!args)
0034         return ERR_PTR(-ENOMEM);
0035 
0036     ctx_in = u64_to_user_ptr(kattr->test.ctx_in);
0037     if (copy_from_user(args->args, ctx_in, size_in))
0038         goto out;
0039 
0040     /* args[0] is 0 means state argument of test_N will be NULL */
0041     u_state = u64_to_user_ptr(args->args[0]);
0042     if (u_state && copy_from_user(&args->state, u_state,
0043                       sizeof(args->state)))
0044         goto out;
0045 
0046     return args;
0047 out:
0048     kfree(args);
0049     return ERR_PTR(-EFAULT);
0050 }
0051 
0052 static int dummy_ops_copy_args(struct bpf_dummy_ops_test_args *args)
0053 {
0054     void __user *u_state;
0055 
0056     u_state = u64_to_user_ptr(args->args[0]);
0057     if (u_state && copy_to_user(u_state, &args->state, sizeof(args->state)))
0058         return -EFAULT;
0059 
0060     return 0;
0061 }
0062 
0063 static int dummy_ops_call_op(void *image, struct bpf_dummy_ops_test_args *args)
0064 {
0065     dummy_ops_test_ret_fn test = (void *)image;
0066     struct bpf_dummy_ops_state *state = NULL;
0067 
0068     /* state needs to be NULL if args[0] is 0 */
0069     if (args->args[0])
0070         state = &args->state;
0071     return test(state, args->args[1], args->args[2],
0072             args->args[3], args->args[4]);
0073 }
0074 
0075 extern const struct bpf_link_ops bpf_struct_ops_link_lops;
0076 
0077 int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr,
0078                 union bpf_attr __user *uattr)
0079 {
0080     const struct bpf_struct_ops *st_ops = &bpf_bpf_dummy_ops;
0081     const struct btf_type *func_proto;
0082     struct bpf_dummy_ops_test_args *args;
0083     struct bpf_tramp_links *tlinks;
0084     struct bpf_tramp_link *link = NULL;
0085     void *image = NULL;
0086     unsigned int op_idx;
0087     int prog_ret;
0088     int err;
0089 
0090     if (prog->aux->attach_btf_id != st_ops->type_id)
0091         return -EOPNOTSUPP;
0092 
0093     func_proto = prog->aux->attach_func_proto;
0094     args = dummy_ops_init_args(kattr, btf_type_vlen(func_proto));
0095     if (IS_ERR(args))
0096         return PTR_ERR(args);
0097 
0098     tlinks = kcalloc(BPF_TRAMP_MAX, sizeof(*tlinks), GFP_KERNEL);
0099     if (!tlinks) {
0100         err = -ENOMEM;
0101         goto out;
0102     }
0103 
0104     image = bpf_jit_alloc_exec(PAGE_SIZE);
0105     if (!image) {
0106         err = -ENOMEM;
0107         goto out;
0108     }
0109     set_vm_flush_reset_perms(image);
0110 
0111     link = kzalloc(sizeof(*link), GFP_USER);
0112     if (!link) {
0113         err = -ENOMEM;
0114         goto out;
0115     }
0116     /* prog doesn't take the ownership of the reference from caller */
0117     bpf_prog_inc(prog);
0118     bpf_link_init(&link->link, BPF_LINK_TYPE_STRUCT_OPS, &bpf_struct_ops_link_lops, prog);
0119 
0120     op_idx = prog->expected_attach_type;
0121     err = bpf_struct_ops_prepare_trampoline(tlinks, link,
0122                         &st_ops->func_models[op_idx],
0123                         image, image + PAGE_SIZE);
0124     if (err < 0)
0125         goto out;
0126 
0127     set_memory_ro((long)image, 1);
0128     set_memory_x((long)image, 1);
0129     prog_ret = dummy_ops_call_op(image, args);
0130 
0131     err = dummy_ops_copy_args(args);
0132     if (err)
0133         goto out;
0134     if (put_user(prog_ret, &uattr->test.retval))
0135         err = -EFAULT;
0136 out:
0137     kfree(args);
0138     bpf_jit_free_exec(image);
0139     if (link)
0140         bpf_link_put(&link->link);
0141     kfree(tlinks);
0142     return err;
0143 }
0144 
0145 static int bpf_dummy_init(struct btf *btf)
0146 {
0147     return 0;
0148 }
0149 
0150 static bool bpf_dummy_ops_is_valid_access(int off, int size,
0151                       enum bpf_access_type type,
0152                       const struct bpf_prog *prog,
0153                       struct bpf_insn_access_aux *info)
0154 {
0155     return bpf_tracing_btf_ctx_access(off, size, type, prog, info);
0156 }
0157 
0158 static int bpf_dummy_ops_btf_struct_access(struct bpf_verifier_log *log,
0159                        const struct btf *btf,
0160                        const struct btf_type *t, int off,
0161                        int size, enum bpf_access_type atype,
0162                        u32 *next_btf_id,
0163                        enum bpf_type_flag *flag)
0164 {
0165     const struct btf_type *state;
0166     s32 type_id;
0167     int err;
0168 
0169     type_id = btf_find_by_name_kind(btf, "bpf_dummy_ops_state",
0170                     BTF_KIND_STRUCT);
0171     if (type_id < 0)
0172         return -EINVAL;
0173 
0174     state = btf_type_by_id(btf, type_id);
0175     if (t != state) {
0176         bpf_log(log, "only access to bpf_dummy_ops_state is supported\n");
0177         return -EACCES;
0178     }
0179 
0180     err = btf_struct_access(log, btf, t, off, size, atype, next_btf_id,
0181                 flag);
0182     if (err < 0)
0183         return err;
0184 
0185     return atype == BPF_READ ? err : NOT_INIT;
0186 }
0187 
0188 static const struct bpf_verifier_ops bpf_dummy_verifier_ops = {
0189     .is_valid_access = bpf_dummy_ops_is_valid_access,
0190     .btf_struct_access = bpf_dummy_ops_btf_struct_access,
0191 };
0192 
0193 static int bpf_dummy_init_member(const struct btf_type *t,
0194                  const struct btf_member *member,
0195                  void *kdata, const void *udata)
0196 {
0197     return -EOPNOTSUPP;
0198 }
0199 
0200 static int bpf_dummy_reg(void *kdata)
0201 {
0202     return -EOPNOTSUPP;
0203 }
0204 
0205 static void bpf_dummy_unreg(void *kdata)
0206 {
0207 }
0208 
0209 struct bpf_struct_ops bpf_bpf_dummy_ops = {
0210     .verifier_ops = &bpf_dummy_verifier_ops,
0211     .init = bpf_dummy_init,
0212     .init_member = bpf_dummy_init_member,
0213     .reg = bpf_dummy_reg,
0214     .unreg = bpf_dummy_unreg,
0215     .name = "bpf_dummy_ops",
0216 };