|
11 | 11 | #include <net/sock.h> |
12 | 12 | #include <net/tcp.h> |
13 | 13 | #include <linux/error-injection.h> |
| 14 | +#include <linux/smp.h> |
14 | 15 |
|
15 | 16 | #define CREATE_TRACE_POINTS |
16 | 17 | #include <trace/events/bpf_test_run.h> |
@@ -204,6 +205,9 @@ int bpf_prog_test_run_tracing(struct bpf_prog *prog, |
204 | 205 | int b = 2, err = -EFAULT; |
205 | 206 | u32 retval = 0; |
206 | 207 |
|
| 208 | + if (kattr->test.flags || kattr->test.cpu) |
| 209 | + return -EINVAL; |
| 210 | + |
207 | 211 | switch (prog->expected_attach_type) { |
208 | 212 | case BPF_TRACE_FENTRY: |
209 | 213 | case BPF_TRACE_FEXIT: |
@@ -236,6 +240,87 @@ int bpf_prog_test_run_tracing(struct bpf_prog *prog, |
236 | 240 | return err; |
237 | 241 | } |
238 | 242 |
|
| 243 | +struct bpf_raw_tp_test_run_info { |
| 244 | + struct bpf_prog *prog; |
| 245 | + void *ctx; |
| 246 | + u32 retval; |
| 247 | +}; |
| 248 | + |
| 249 | +static void |
| 250 | +__bpf_prog_test_run_raw_tp(void *data) |
| 251 | +{ |
| 252 | + struct bpf_raw_tp_test_run_info *info = data; |
| 253 | + |
| 254 | + rcu_read_lock(); |
| 255 | + migrate_disable(); |
| 256 | + info->retval = BPF_PROG_RUN(info->prog, info->ctx); |
| 257 | + migrate_enable(); |
| 258 | + rcu_read_unlock(); |
| 259 | +} |
| 260 | + |
| 261 | +int bpf_prog_test_run_raw_tp(struct bpf_prog *prog, |
| 262 | + const union bpf_attr *kattr, |
| 263 | + union bpf_attr __user *uattr) |
| 264 | +{ |
| 265 | + void __user *ctx_in = u64_to_user_ptr(kattr->test.ctx_in); |
| 266 | + __u32 ctx_size_in = kattr->test.ctx_size_in; |
| 267 | + struct bpf_raw_tp_test_run_info info; |
| 268 | + int cpu = kattr->test.cpu, err = 0; |
| 269 | + |
| 270 | + /* doesn't support data_in/out, ctx_out, duration, or repeat */ |
| 271 | + if (kattr->test.data_in || kattr->test.data_out || |
| 272 | + kattr->test.ctx_out || kattr->test.duration || |
| 273 | + kattr->test.repeat) |
| 274 | + return -EINVAL; |
| 275 | + |
| 276 | + if (ctx_size_in < prog->aux->max_ctx_offset) |
| 277 | + return -EINVAL; |
| 278 | + |
| 279 | + if ((kattr->test.flags & BPF_F_TEST_RUN_ON_CPU) == 0 && cpu != 0) |
| 280 | + return -EINVAL; |
| 281 | + |
| 282 | + if (ctx_size_in) { |
| 283 | + info.ctx = kzalloc(ctx_size_in, GFP_USER); |
| 284 | + if (!info.ctx) |
| 285 | + return -ENOMEM; |
| 286 | + if (copy_from_user(info.ctx, ctx_in, ctx_size_in)) { |
| 287 | + err = -EFAULT; |
| 288 | + goto out; |
| 289 | + } |
| 290 | + } else { |
| 291 | + info.ctx = NULL; |
| 292 | + } |
| 293 | + |
| 294 | + info.prog = prog; |
| 295 | + |
| 296 | + if ((kattr->test.flags & BPF_F_TEST_RUN_ON_CPU) == 0 || |
| 297 | + cpu == smp_processor_id()) { |
| 298 | + __bpf_prog_test_run_raw_tp(&info); |
| 299 | + } else { |
| 300 | + /* smp_call_function_single() also checks cpu_online() |
| 301 | + * after csd_lock(). However, since cpu is from user |
| 302 | + * space, let's do an extra quick check to filter out |
| 303 | + * invalid value before smp_call_function_single(). |
| 304 | + */ |
| 305 | + if (cpu >= nr_cpu_ids || !cpu_online(cpu)) { |
| 306 | + err = -ENXIO; |
| 307 | + goto out; |
| 308 | + } |
| 309 | + |
| 310 | + err = smp_call_function_single(cpu, __bpf_prog_test_run_raw_tp, |
| 311 | + &info, 1); |
| 312 | + if (err) |
| 313 | + goto out; |
| 314 | + } |
| 315 | + |
| 316 | + if (copy_to_user(&uattr->test.retval, &info.retval, sizeof(u32))) |
| 317 | + err = -EFAULT; |
| 318 | + |
| 319 | +out: |
| 320 | + kfree(info.ctx); |
| 321 | + return err; |
| 322 | +} |
| 323 | + |
239 | 324 | static void *bpf_ctx_init(const union bpf_attr *kattr, u32 max_size) |
240 | 325 | { |
241 | 326 | void __user *data_in = u64_to_user_ptr(kattr->test.ctx_in); |
@@ -410,6 +495,9 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, |
410 | 495 | void *data; |
411 | 496 | int ret; |
412 | 497 |
|
| 498 | + if (kattr->test.flags || kattr->test.cpu) |
| 499 | + return -EINVAL; |
| 500 | + |
413 | 501 | data = bpf_test_init(kattr, size, NET_SKB_PAD + NET_IP_ALIGN, |
414 | 502 | SKB_DATA_ALIGN(sizeof(struct skb_shared_info))); |
415 | 503 | if (IS_ERR(data)) |
@@ -607,6 +695,9 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, |
607 | 695 | if (prog->type != BPF_PROG_TYPE_FLOW_DISSECTOR) |
608 | 696 | return -EINVAL; |
609 | 697 |
|
| 698 | + if (kattr->test.flags || kattr->test.cpu) |
| 699 | + return -EINVAL; |
| 700 | + |
610 | 701 | if (size < ETH_HLEN) |
611 | 702 | return -EINVAL; |
612 | 703 |
|
|
0 commit comments