Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2022 Facebook */
0003 
0004 #include <errno.h>
0005 #include <string.h>
0006 #include <linux/bpf.h>
0007 #include <bpf/bpf_helpers.h>
0008 #include "bpf_misc.h"
0009 
0010 char _license[] SEC("license") = "GPL";
0011 
0012 struct test_info {
0013     int x;
0014     struct bpf_dynptr ptr;
0015 };
0016 
0017 struct {
0018     __uint(type, BPF_MAP_TYPE_ARRAY);
0019     __uint(max_entries, 1);
0020     __type(key, __u32);
0021     __type(value, struct bpf_dynptr);
0022 } array_map1 SEC(".maps");
0023 
0024 struct {
0025     __uint(type, BPF_MAP_TYPE_ARRAY);
0026     __uint(max_entries, 1);
0027     __type(key, __u32);
0028     __type(value, struct test_info);
0029 } array_map2 SEC(".maps");
0030 
0031 struct {
0032     __uint(type, BPF_MAP_TYPE_ARRAY);
0033     __uint(max_entries, 1);
0034     __type(key, __u32);
0035     __type(value, __u32);
0036 } array_map3 SEC(".maps");
0037 
0038 struct sample {
0039     int pid;
0040     long value;
0041     char comm[16];
0042 };
0043 
0044 struct {
0045     __uint(type, BPF_MAP_TYPE_RINGBUF);
0046 } ringbuf SEC(".maps");
0047 
0048 int err, val;
0049 
0050 static int get_map_val_dynptr(struct bpf_dynptr *ptr)
0051 {
0052     __u32 key = 0, *map_val;
0053 
0054     bpf_map_update_elem(&array_map3, &key, &val, 0);
0055 
0056     map_val = bpf_map_lookup_elem(&array_map3, &key);
0057     if (!map_val)
0058         return -ENOENT;
0059 
0060     bpf_dynptr_from_mem(map_val, sizeof(*map_val), 0, ptr);
0061 
0062     return 0;
0063 }
0064 
0065 /* Every bpf_ringbuf_reserve_dynptr call must have a corresponding
0066  * bpf_ringbuf_submit/discard_dynptr call
0067  */
0068 SEC("?raw_tp/sys_nanosleep")
0069 int ringbuf_missing_release1(void *ctx)
0070 {
0071     struct bpf_dynptr ptr;
0072 
0073     bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
0074 
0075     /* missing a call to bpf_ringbuf_discard/submit_dynptr */
0076 
0077     return 0;
0078 }
0079 
0080 SEC("?raw_tp/sys_nanosleep")
0081 int ringbuf_missing_release2(void *ctx)
0082 {
0083     struct bpf_dynptr ptr1, ptr2;
0084     struct sample *sample;
0085 
0086     bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr1);
0087     bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
0088 
0089     sample = bpf_dynptr_data(&ptr1, 0, sizeof(*sample));
0090     if (!sample) {
0091         bpf_ringbuf_discard_dynptr(&ptr1, 0);
0092         bpf_ringbuf_discard_dynptr(&ptr2, 0);
0093         return 0;
0094     }
0095 
0096     bpf_ringbuf_submit_dynptr(&ptr1, 0);
0097 
0098     /* missing a call to bpf_ringbuf_discard/submit_dynptr on ptr2 */
0099 
0100     return 0;
0101 }
0102 
0103 static int missing_release_callback_fn(__u32 index, void *data)
0104 {
0105     struct bpf_dynptr ptr;
0106 
0107     bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
0108 
0109     /* missing a call to bpf_ringbuf_discard/submit_dynptr */
0110 
0111     return 0;
0112 }
0113 
0114 /* Any dynptr initialized within a callback must have bpf_dynptr_put called */
0115 SEC("?raw_tp/sys_nanosleep")
0116 int ringbuf_missing_release_callback(void *ctx)
0117 {
0118     bpf_loop(10, missing_release_callback_fn, NULL, 0);
0119     return 0;
0120 }
0121 
0122 /* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */
0123 SEC("?raw_tp/sys_nanosleep")
0124 int ringbuf_release_uninit_dynptr(void *ctx)
0125 {
0126     struct bpf_dynptr ptr;
0127 
0128     /* this should fail */
0129     bpf_ringbuf_submit_dynptr(&ptr, 0);
0130 
0131     return 0;
0132 }
0133 
0134 /* A dynptr can't be used after it has been invalidated */
0135 SEC("?raw_tp/sys_nanosleep")
0136 int use_after_invalid(void *ctx)
0137 {
0138     struct bpf_dynptr ptr;
0139     char read_data[64];
0140 
0141     bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(read_data), 0, &ptr);
0142 
0143     bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
0144 
0145     bpf_ringbuf_submit_dynptr(&ptr, 0);
0146 
0147     /* this should fail */
0148     bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
0149 
0150     return 0;
0151 }
0152 
0153 /* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */
0154 SEC("?raw_tp/sys_nanosleep")
0155 int ringbuf_invalid_api(void *ctx)
0156 {
0157     struct bpf_dynptr ptr;
0158     struct sample *sample;
0159 
0160     bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
0161     sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
0162     if (!sample)
0163         goto done;
0164 
0165     sample->pid = 123;
0166 
0167     /* invalid API use. need to use dynptr API to submit/discard */
0168     bpf_ringbuf_submit(sample, 0);
0169 
0170 done:
0171     bpf_ringbuf_discard_dynptr(&ptr, 0);
0172     return 0;
0173 }
0174 
0175 /* Can't add a dynptr to a map */
0176 SEC("?raw_tp/sys_nanosleep")
0177 int add_dynptr_to_map1(void *ctx)
0178 {
0179     struct bpf_dynptr ptr;
0180     int key = 0;
0181 
0182     bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
0183 
0184     /* this should fail */
0185     bpf_map_update_elem(&array_map1, &key, &ptr, 0);
0186 
0187     bpf_ringbuf_submit_dynptr(&ptr, 0);
0188 
0189     return 0;
0190 }
0191 
0192 /* Can't add a struct with an embedded dynptr to a map */
0193 SEC("?raw_tp/sys_nanosleep")
0194 int add_dynptr_to_map2(void *ctx)
0195 {
0196     struct test_info x;
0197     int key = 0;
0198 
0199     bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &x.ptr);
0200 
0201     /* this should fail */
0202     bpf_map_update_elem(&array_map2, &key, &x, 0);
0203 
0204     bpf_ringbuf_submit_dynptr(&x.ptr, 0);
0205 
0206     return 0;
0207 }
0208 
0209 /* A data slice can't be accessed out of bounds */
0210 SEC("?raw_tp/sys_nanosleep")
0211 int data_slice_out_of_bounds_ringbuf(void *ctx)
0212 {
0213     struct bpf_dynptr ptr;
0214     void *data;
0215 
0216     bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
0217 
0218     data  = bpf_dynptr_data(&ptr, 0, 8);
0219     if (!data)
0220         goto done;
0221 
0222     /* can't index out of bounds of the data slice */
0223     val = *((char *)data + 8);
0224 
0225 done:
0226     bpf_ringbuf_submit_dynptr(&ptr, 0);
0227     return 0;
0228 }
0229 
0230 SEC("?raw_tp/sys_nanosleep")
0231 int data_slice_out_of_bounds_map_value(void *ctx)
0232 {
0233     __u32 key = 0, map_val;
0234     struct bpf_dynptr ptr;
0235     void *data;
0236 
0237     get_map_val_dynptr(&ptr);
0238 
0239     data  = bpf_dynptr_data(&ptr, 0, sizeof(map_val));
0240     if (!data)
0241         return 0;
0242 
0243     /* can't index out of bounds of the data slice */
0244     val = *((char *)data + (sizeof(map_val) + 1));
0245 
0246     return 0;
0247 }
0248 
0249 /* A data slice can't be used after it has been released */
0250 SEC("?raw_tp/sys_nanosleep")
0251 int data_slice_use_after_release(void *ctx)
0252 {
0253     struct bpf_dynptr ptr;
0254     struct sample *sample;
0255 
0256     bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
0257     sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
0258     if (!sample)
0259         goto done;
0260 
0261     sample->pid = 123;
0262 
0263     bpf_ringbuf_submit_dynptr(&ptr, 0);
0264 
0265     /* this should fail */
0266     val = sample->pid;
0267 
0268     return 0;
0269 
0270 done:
0271     bpf_ringbuf_discard_dynptr(&ptr, 0);
0272     return 0;
0273 }
0274 
0275 /* A data slice must be first checked for NULL */
0276 SEC("?raw_tp/sys_nanosleep")
0277 int data_slice_missing_null_check1(void *ctx)
0278 {
0279     struct bpf_dynptr ptr;
0280     void *data;
0281 
0282     bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
0283 
0284     data  = bpf_dynptr_data(&ptr, 0, 8);
0285 
0286     /* missing if (!data) check */
0287 
0288     /* this should fail */
0289     *(__u8 *)data = 3;
0290 
0291     bpf_ringbuf_submit_dynptr(&ptr, 0);
0292     return 0;
0293 }
0294 
0295 /* A data slice can't be dereferenced if it wasn't checked for null */
0296 SEC("?raw_tp/sys_nanosleep")
0297 int data_slice_missing_null_check2(void *ctx)
0298 {
0299     struct bpf_dynptr ptr;
0300     __u64 *data1, *data2;
0301 
0302     bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
0303 
0304     data1 = bpf_dynptr_data(&ptr, 0, 8);
0305     data2 = bpf_dynptr_data(&ptr, 0, 8);
0306     if (data1)
0307         /* this should fail */
0308         *data2 = 3;
0309 
0310 done:
0311     bpf_ringbuf_discard_dynptr(&ptr, 0);
0312     return 0;
0313 }
0314 
0315 /* Can't pass in a dynptr as an arg to a helper function that doesn't take in a
0316  * dynptr argument
0317  */
0318 SEC("?raw_tp/sys_nanosleep")
0319 int invalid_helper1(void *ctx)
0320 {
0321     struct bpf_dynptr ptr;
0322 
0323     get_map_val_dynptr(&ptr);
0324 
0325     /* this should fail */
0326     bpf_strncmp((const char *)&ptr, sizeof(ptr), "hello!");
0327 
0328     return 0;
0329 }
0330 
0331 /* A dynptr can't be passed into a helper function at a non-zero offset */
0332 SEC("?raw_tp/sys_nanosleep")
0333 int invalid_helper2(void *ctx)
0334 {
0335     struct bpf_dynptr ptr;
0336     char read_data[64];
0337 
0338     get_map_val_dynptr(&ptr);
0339 
0340     /* this should fail */
0341     bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0, 0);
0342 
0343     return 0;
0344 }
0345 
0346 /* A bpf_dynptr is invalidated if it's been written into */
0347 SEC("?raw_tp/sys_nanosleep")
0348 int invalid_write1(void *ctx)
0349 {
0350     struct bpf_dynptr ptr;
0351     void *data;
0352     __u8 x = 0;
0353 
0354     get_map_val_dynptr(&ptr);
0355 
0356     memcpy(&ptr, &x, sizeof(x));
0357 
0358     /* this should fail */
0359     data = bpf_dynptr_data(&ptr, 0, 1);
0360 
0361     return 0;
0362 }
0363 
0364 /*
0365  * A bpf_dynptr can't be used as a dynptr if it has been written into at a fixed
0366  * offset
0367  */
0368 SEC("?raw_tp/sys_nanosleep")
0369 int invalid_write2(void *ctx)
0370 {
0371     struct bpf_dynptr ptr;
0372     char read_data[64];
0373     __u8 x = 0;
0374 
0375     bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
0376 
0377     memcpy((void *)&ptr + 8, &x, sizeof(x));
0378 
0379     /* this should fail */
0380     bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
0381 
0382     bpf_ringbuf_submit_dynptr(&ptr, 0);
0383 
0384     return 0;
0385 }
0386 
0387 /*
0388  * A bpf_dynptr can't be used as a dynptr if it has been written into at a
0389  * non-const offset
0390  */
0391 SEC("?raw_tp/sys_nanosleep")
0392 int invalid_write3(void *ctx)
0393 {
0394     struct bpf_dynptr ptr;
0395     char stack_buf[16];
0396     unsigned long len;
0397     __u8 x = 0;
0398 
0399     bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
0400 
0401     memcpy(stack_buf, &val, sizeof(val));
0402     len = stack_buf[0] & 0xf;
0403 
0404     memcpy((void *)&ptr + len, &x, sizeof(x));
0405 
0406     /* this should fail */
0407     bpf_ringbuf_submit_dynptr(&ptr, 0);
0408 
0409     return 0;
0410 }
0411 
0412 static int invalid_write4_callback(__u32 index, void *data)
0413 {
0414     *(__u32 *)data = 123;
0415 
0416     return 0;
0417 }
0418 
0419 /* If the dynptr is written into in a callback function, it should
0420  * be invalidated as a dynptr
0421  */
0422 SEC("?raw_tp/sys_nanosleep")
0423 int invalid_write4(void *ctx)
0424 {
0425     struct bpf_dynptr ptr;
0426 
0427     bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
0428 
0429     bpf_loop(10, invalid_write4_callback, &ptr, 0);
0430 
0431     /* this should fail */
0432     bpf_ringbuf_submit_dynptr(&ptr, 0);
0433 
0434     return 0;
0435 }
0436 
0437 /* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */
0438 struct bpf_dynptr global_dynptr;
0439 SEC("?raw_tp/sys_nanosleep")
0440 int global(void *ctx)
0441 {
0442     /* this should fail */
0443     bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &global_dynptr);
0444 
0445     bpf_ringbuf_discard_dynptr(&global_dynptr, 0);
0446 
0447     return 0;
0448 }
0449 
0450 /* A direct read should fail */
0451 SEC("?raw_tp/sys_nanosleep")
0452 int invalid_read1(void *ctx)
0453 {
0454     struct bpf_dynptr ptr;
0455 
0456     bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
0457 
0458     /* this should fail */
0459     val = *(int *)&ptr;
0460 
0461     bpf_ringbuf_discard_dynptr(&ptr, 0);
0462 
0463     return 0;
0464 }
0465 
0466 /* A direct read at an offset should fail */
0467 SEC("?raw_tp/sys_nanosleep")
0468 int invalid_read2(void *ctx)
0469 {
0470     struct bpf_dynptr ptr;
0471     char read_data[64];
0472 
0473     get_map_val_dynptr(&ptr);
0474 
0475     /* this should fail */
0476     bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0, 0);
0477 
0478     return 0;
0479 }
0480 
0481 /* A direct read at an offset into the lower stack slot should fail */
0482 SEC("?raw_tp/sys_nanosleep")
0483 int invalid_read3(void *ctx)
0484 {
0485     struct bpf_dynptr ptr1, ptr2;
0486 
0487     bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr1);
0488     bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr2);
0489 
0490     /* this should fail */
0491     memcpy(&val, (void *)&ptr1 + 8, sizeof(val));
0492 
0493     bpf_ringbuf_discard_dynptr(&ptr1, 0);
0494     bpf_ringbuf_discard_dynptr(&ptr2, 0);
0495 
0496     return 0;
0497 }
0498 
0499 static int invalid_read4_callback(__u32 index, void *data)
0500 {
0501     /* this should fail */
0502     val = *(__u32 *)data;
0503 
0504     return 0;
0505 }
0506 
0507 /* A direct read within a callback function should fail */
0508 SEC("?raw_tp/sys_nanosleep")
0509 int invalid_read4(void *ctx)
0510 {
0511     struct bpf_dynptr ptr;
0512 
0513     bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
0514 
0515     bpf_loop(10, invalid_read4_callback, &ptr, 0);
0516 
0517     bpf_ringbuf_submit_dynptr(&ptr, 0);
0518 
0519     return 0;
0520 }
0521 
0522 /* Initializing a dynptr on an offset should fail */
0523 SEC("?raw_tp/sys_nanosleep")
0524 int invalid_offset(void *ctx)
0525 {
0526     struct bpf_dynptr ptr;
0527 
0528     /* this should fail */
0529     bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr + 1);
0530 
0531     bpf_ringbuf_discard_dynptr(&ptr, 0);
0532 
0533     return 0;
0534 }
0535 
0536 /* Can't release a dynptr twice */
0537 SEC("?raw_tp/sys_nanosleep")
0538 int release_twice(void *ctx)
0539 {
0540     struct bpf_dynptr ptr;
0541 
0542     bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
0543 
0544     bpf_ringbuf_discard_dynptr(&ptr, 0);
0545 
0546     /* this second release should fail */
0547     bpf_ringbuf_discard_dynptr(&ptr, 0);
0548 
0549     return 0;
0550 }
0551 
0552 static int release_twice_callback_fn(__u32 index, void *data)
0553 {
0554     /* this should fail */
0555     bpf_ringbuf_discard_dynptr(data, 0);
0556 
0557     return 0;
0558 }
0559 
0560 /* Test that releasing a dynptr twice, where one of the releases happens
0561  * within a calback function, fails
0562  */
0563 SEC("?raw_tp/sys_nanosleep")
0564 int release_twice_callback(void *ctx)
0565 {
0566     struct bpf_dynptr ptr;
0567 
0568     bpf_ringbuf_reserve_dynptr(&ringbuf, 32, 0, &ptr);
0569 
0570     bpf_ringbuf_discard_dynptr(&ptr, 0);
0571 
0572     bpf_loop(10, release_twice_callback_fn, &ptr, 0);
0573 
0574     return 0;
0575 }
0576 
0577 /* Reject unsupported local mem types for dynptr_from_mem API */
0578 SEC("?raw_tp/sys_nanosleep")
0579 int dynptr_from_mem_invalid_api(void *ctx)
0580 {
0581     struct bpf_dynptr ptr;
0582     int x = 0;
0583 
0584     /* this should fail */
0585     bpf_dynptr_from_mem(&x, sizeof(x), 0, &ptr);
0586 
0587     return 0;
0588 }