0001
0002
0003
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
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
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
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
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 };