1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2022 Facebook */ 3 4 #include <string.h> 5 #include <stdbool.h> 6 #include <linux/bpf.h> 7 #include <bpf/bpf_helpers.h> 8 #include <bpf/bpf_tracing.h> 9 #include "bpf_misc.h" 10 #include "bpf_kfuncs.h" 11 #include "errno.h" 12 13 char _license[] SEC("license") = "GPL"; 14 15 int pid, err, val; 16 17 struct sample { 18 int pid; 19 int seq; 20 long value; 21 char comm[16]; 22 }; 23 24 struct { 25 __uint(type, BPF_MAP_TYPE_RINGBUF); 26 __uint(max_entries, 4096); 27 } ringbuf SEC(".maps"); 28 29 struct { 30 __uint(type, BPF_MAP_TYPE_ARRAY); 31 __uint(max_entries, 1); 32 __type(key, __u32); 33 __type(value, __u32); 34 } array_map SEC(".maps"); 35 36 SEC("?tp/syscalls/sys_enter_nanosleep") 37 int test_read_write(void *ctx) 38 { 39 char write_data[64] = "hello there, world!!"; 40 char read_data[64] = {}; 41 struct bpf_dynptr ptr; 42 int i; 43 44 if (bpf_get_current_pid_tgid() >> 32 != pid) 45 return 0; 46 47 bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(write_data), 0, &ptr); 48 49 /* Write data into the dynptr */ 50 err = bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0); 51 52 /* Read the data that was written into the dynptr */ 53 err = err ?: bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0); 54 55 /* Ensure the data we read matches the data we wrote */ 56 for (i = 0; i < sizeof(read_data); i++) { 57 if (read_data[i] != write_data[i]) { 58 err = 1; 59 break; 60 } 61 } 62 63 bpf_ringbuf_discard_dynptr(&ptr, 0); 64 return 0; 65 } 66 67 SEC("?tp/syscalls/sys_enter_nanosleep") 68 int test_dynptr_data(void *ctx) 69 { 70 __u32 key = 0, val = 235, *map_val; 71 struct bpf_dynptr ptr; 72 __u32 map_val_size; 73 void *data; 74 75 map_val_size = sizeof(*map_val); 76 77 if (bpf_get_current_pid_tgid() >> 32 != pid) 78 return 0; 79 80 bpf_map_update_elem(&array_map, &key, &val, 0); 81 82 map_val = bpf_map_lookup_elem(&array_map, &key); 83 if (!map_val) { 84 err = 1; 85 return 0; 86 } 87 88 bpf_dynptr_from_mem(map_val, map_val_size, 0, &ptr); 89 90 /* Try getting a data slice that is out of range */ 91 data = bpf_dynptr_data(&ptr, map_val_size + 1, 1); 92 if (data) { 93 err = 2; 94 return 0; 95 } 96 97 /* Try getting more bytes than available */ 98 data = bpf_dynptr_data(&ptr, 0, map_val_size + 1); 99 if (data) { 100 err = 3; 101 return 0; 102 } 103 104 data = bpf_dynptr_data(&ptr, 0, sizeof(__u32)); 105 if (!data) { 106 err = 4; 107 return 0; 108 } 109 110 *(__u32 *)data = 999; 111 112 err = bpf_probe_read_kernel(&val, sizeof(val), data); 113 if (err) 114 return 0; 115 116 if (val != *(int *)data) 117 err = 5; 118 119 return 0; 120 } 121 122 static int ringbuf_callback(__u32 index, void *data) 123 { 124 struct sample *sample; 125 126 struct bpf_dynptr *ptr = (struct bpf_dynptr *)data; 127 128 sample = bpf_dynptr_data(ptr, 0, sizeof(*sample)); 129 if (!sample) 130 err = 2; 131 else 132 sample->pid += index; 133 134 return 0; 135 } 136 137 SEC("?tp/syscalls/sys_enter_nanosleep") 138 int test_ringbuf(void *ctx) 139 { 140 struct bpf_dynptr ptr; 141 struct sample *sample; 142 143 if (bpf_get_current_pid_tgid() >> 32 != pid) 144 return 0; 145 146 val = 100; 147 148 /* check that you can reserve a dynamic size reservation */ 149 err = bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr); 150 151 sample = err ? NULL : bpf_dynptr_data(&ptr, 0, sizeof(*sample)); 152 if (!sample) { 153 err = 1; 154 goto done; 155 } 156 157 sample->pid = 10; 158 159 /* Can pass dynptr to callback functions */ 160 bpf_loop(10, ringbuf_callback, &ptr, 0); 161 162 if (sample->pid != 55) 163 err = 2; 164 165 done: 166 bpf_ringbuf_discard_dynptr(&ptr, 0); 167 return 0; 168 } 169 170 SEC("?cgroup_skb/egress") 171 int test_skb_readonly(struct __sk_buff *skb) 172 { 173 __u8 write_data[2] = {1, 2}; 174 struct bpf_dynptr ptr; 175 int ret; 176 177 if (bpf_dynptr_from_skb(skb, 0, &ptr)) { 178 err = 1; 179 return 1; 180 } 181 182 /* since cgroup skbs are read only, writes should fail */ 183 ret = bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0); 184 if (ret != -EINVAL) { 185 err = 2; 186 return 1; 187 } 188 189 return 1; 190 } 191 192 SEC("?cgroup_skb/egress") 193 int test_dynptr_skb_data(struct __sk_buff *skb) 194 { 195 struct bpf_dynptr ptr; 196 __u64 *data; 197 198 if (bpf_dynptr_from_skb(skb, 0, &ptr)) { 199 err = 1; 200 return 1; 201 } 202 203 /* This should return NULL. Must use bpf_dynptr_slice API */ 204 data = bpf_dynptr_data(&ptr, 0, 1); 205 if (data) { 206 err = 2; 207 return 1; 208 } 209 210 return 1; 211 } 212 213 SEC("tp/syscalls/sys_enter_nanosleep") 214 int test_adjust(void *ctx) 215 { 216 struct bpf_dynptr ptr; 217 __u32 bytes = 64; 218 __u32 off = 10; 219 __u32 trim = 15; 220 221 if (bpf_get_current_pid_tgid() >> 32 != pid) 222 return 0; 223 224 err = bpf_ringbuf_reserve_dynptr(&ringbuf, bytes, 0, &ptr); 225 if (err) { 226 err = 1; 227 goto done; 228 } 229 230 if (bpf_dynptr_size(&ptr) != bytes) { 231 err = 2; 232 goto done; 233 } 234 235 /* Advance the dynptr by off */ 236 err = bpf_dynptr_adjust(&ptr, off, bpf_dynptr_size(&ptr)); 237 if (err) { 238 err = 3; 239 goto done; 240 } 241 242 if (bpf_dynptr_size(&ptr) != bytes - off) { 243 err = 4; 244 goto done; 245 } 246 247 /* Trim the dynptr */ 248 err = bpf_dynptr_adjust(&ptr, off, 15); 249 if (err) { 250 err = 5; 251 goto done; 252 } 253 254 /* Check that the size was adjusted correctly */ 255 if (bpf_dynptr_size(&ptr) != trim - off) { 256 err = 6; 257 goto done; 258 } 259 260 done: 261 bpf_ringbuf_discard_dynptr(&ptr, 0); 262 return 0; 263 } 264 265 SEC("tp/syscalls/sys_enter_nanosleep") 266 int test_adjust_err(void *ctx) 267 { 268 char write_data[45] = "hello there, world!!"; 269 struct bpf_dynptr ptr; 270 __u32 size = 64; 271 __u32 off = 20; 272 273 if (bpf_get_current_pid_tgid() >> 32 != pid) 274 return 0; 275 276 if (bpf_ringbuf_reserve_dynptr(&ringbuf, size, 0, &ptr)) { 277 err = 1; 278 goto done; 279 } 280 281 /* Check that start can't be greater than end */ 282 if (bpf_dynptr_adjust(&ptr, 5, 1) != -EINVAL) { 283 err = 2; 284 goto done; 285 } 286 287 /* Check that start can't be greater than size */ 288 if (bpf_dynptr_adjust(&ptr, size + 1, size + 1) != -ERANGE) { 289 err = 3; 290 goto done; 291 } 292 293 /* Check that end can't be greater than size */ 294 if (bpf_dynptr_adjust(&ptr, 0, size + 1) != -ERANGE) { 295 err = 4; 296 goto done; 297 } 298 299 if (bpf_dynptr_adjust(&ptr, off, size)) { 300 err = 5; 301 goto done; 302 } 303 304 /* Check that you can't write more bytes than available into the dynptr 305 * after you've adjusted it 306 */ 307 if (bpf_dynptr_write(&ptr, 0, &write_data, sizeof(write_data), 0) != -E2BIG) { 308 err = 6; 309 goto done; 310 } 311 312 /* Check that even after adjusting, submitting/discarding 313 * a ringbuf dynptr works 314 */ 315 bpf_ringbuf_submit_dynptr(&ptr, 0); 316 return 0; 317 318 done: 319 bpf_ringbuf_discard_dynptr(&ptr, 0); 320 return 0; 321 } 322 323 SEC("tp/syscalls/sys_enter_nanosleep") 324 int test_zero_size_dynptr(void *ctx) 325 { 326 char write_data = 'x', read_data; 327 struct bpf_dynptr ptr; 328 __u32 size = 64; 329 330 if (bpf_get_current_pid_tgid() >> 32 != pid) 331 return 0; 332 333 if (bpf_ringbuf_reserve_dynptr(&ringbuf, size, 0, &ptr)) { 334 err = 1; 335 goto done; 336 } 337 338 /* After this, the dynptr has a size of 0 */ 339 if (bpf_dynptr_adjust(&ptr, size, size)) { 340 err = 2; 341 goto done; 342 } 343 344 /* Test that reading + writing non-zero bytes is not ok */ 345 if (bpf_dynptr_read(&read_data, sizeof(read_data), &ptr, 0, 0) != -E2BIG) { 346 err = 3; 347 goto done; 348 } 349 350 if (bpf_dynptr_write(&ptr, 0, &write_data, sizeof(write_data), 0) != -E2BIG) { 351 err = 4; 352 goto done; 353 } 354 355 /* Test that reading + writing 0 bytes from a 0-size dynptr is ok */ 356 if (bpf_dynptr_read(&read_data, 0, &ptr, 0, 0)) { 357 err = 5; 358 goto done; 359 } 360 361 if (bpf_dynptr_write(&ptr, 0, &write_data, 0, 0)) { 362 err = 6; 363 goto done; 364 } 365 366 err = 0; 367 368 done: 369 bpf_ringbuf_discard_dynptr(&ptr, 0); 370 return 0; 371 } 372 373 SEC("tp/syscalls/sys_enter_nanosleep") 374 int test_dynptr_is_null(void *ctx) 375 { 376 struct bpf_dynptr ptr1; 377 struct bpf_dynptr ptr2; 378 __u64 size = 4; 379 380 if (bpf_get_current_pid_tgid() >> 32 != pid) 381 return 0; 382 383 /* Pass in invalid flags, get back an invalid dynptr */ 384 if (bpf_ringbuf_reserve_dynptr(&ringbuf, size, 123, &ptr1) != -EINVAL) { 385 err = 1; 386 goto exit_early; 387 } 388 389 /* Test that the invalid dynptr is null */ 390 if (!bpf_dynptr_is_null(&ptr1)) { 391 err = 2; 392 goto exit_early; 393 } 394 395 /* Get a valid dynptr */ 396 if (bpf_ringbuf_reserve_dynptr(&ringbuf, size, 0, &ptr2)) { 397 err = 3; 398 goto exit; 399 } 400 401 /* Test that the valid dynptr is not null */ 402 if (bpf_dynptr_is_null(&ptr2)) { 403 err = 4; 404 goto exit; 405 } 406 407 exit: 408 bpf_ringbuf_discard_dynptr(&ptr2, 0); 409 exit_early: 410 bpf_ringbuf_discard_dynptr(&ptr1, 0); 411 return 0; 412 } 413 414 SEC("cgroup_skb/egress") 415 int test_dynptr_is_rdonly(struct __sk_buff *skb) 416 { 417 struct bpf_dynptr ptr1; 418 struct bpf_dynptr ptr2; 419 struct bpf_dynptr ptr3; 420 421 /* Pass in invalid flags, get back an invalid dynptr */ 422 if (bpf_dynptr_from_skb(skb, 123, &ptr1) != -EINVAL) { 423 err = 1; 424 return 0; 425 } 426 427 /* Test that an invalid dynptr is_rdonly returns false */ 428 if (bpf_dynptr_is_rdonly(&ptr1)) { 429 err = 2; 430 return 0; 431 } 432 433 /* Get a read-only dynptr */ 434 if (bpf_dynptr_from_skb(skb, 0, &ptr2)) { 435 err = 3; 436 return 0; 437 } 438 439 /* Test that the dynptr is read-only */ 440 if (!bpf_dynptr_is_rdonly(&ptr2)) { 441 err = 4; 442 return 0; 443 } 444 445 /* Get a read-writeable dynptr */ 446 if (bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr3)) { 447 err = 5; 448 goto done; 449 } 450 451 /* Test that the dynptr is read-only */ 452 if (bpf_dynptr_is_rdonly(&ptr3)) { 453 err = 6; 454 goto done; 455 } 456 457 done: 458 bpf_ringbuf_discard_dynptr(&ptr3, 0); 459 return 0; 460 } 461 462 SEC("cgroup_skb/egress") 463 int test_dynptr_clone(struct __sk_buff *skb) 464 { 465 struct bpf_dynptr ptr1; 466 struct bpf_dynptr ptr2; 467 __u32 off = 2, size; 468 469 /* Get a dynptr */ 470 if (bpf_dynptr_from_skb(skb, 0, &ptr1)) { 471 err = 1; 472 return 0; 473 } 474 475 if (bpf_dynptr_adjust(&ptr1, off, bpf_dynptr_size(&ptr1))) { 476 err = 2; 477 return 0; 478 } 479 480 /* Clone the dynptr */ 481 if (bpf_dynptr_clone(&ptr1, &ptr2)) { 482 err = 3; 483 return 0; 484 } 485 486 size = bpf_dynptr_size(&ptr1); 487 488 /* Check that the clone has the same size and rd-only */ 489 if (bpf_dynptr_size(&ptr2) != size) { 490 err = 4; 491 return 0; 492 } 493 494 if (bpf_dynptr_is_rdonly(&ptr2) != bpf_dynptr_is_rdonly(&ptr1)) { 495 err = 5; 496 return 0; 497 } 498 499 /* Advance and trim the original dynptr */ 500 bpf_dynptr_adjust(&ptr1, 5, 5); 501 502 /* Check that only original dynptr was affected, and the clone wasn't */ 503 if (bpf_dynptr_size(&ptr2) != size) { 504 err = 6; 505 return 0; 506 } 507 508 return 0; 509 } 510 511 SEC("?cgroup_skb/egress") 512 int test_dynptr_skb_no_buff(struct __sk_buff *skb) 513 { 514 struct bpf_dynptr ptr; 515 __u64 *data; 516 517 if (bpf_dynptr_from_skb(skb, 0, &ptr)) { 518 err = 1; 519 return 1; 520 } 521 522 /* This may return NULL. SKB may require a buffer */ 523 data = bpf_dynptr_slice(&ptr, 0, NULL, 1); 524 525 return !!data; 526 } 527 528 SEC("?cgroup_skb/egress") 529 int test_dynptr_skb_strcmp(struct __sk_buff *skb) 530 { 531 struct bpf_dynptr ptr; 532 char *data; 533 534 if (bpf_dynptr_from_skb(skb, 0, &ptr)) { 535 err = 1; 536 return 1; 537 } 538 539 /* This may return NULL. SKB may require a buffer */ 540 data = bpf_dynptr_slice(&ptr, 0, NULL, 10); 541 if (data) { 542 bpf_strncmp(data, 10, "foo"); 543 return 1; 544 } 545 546 return 1; 547 } 548 549 SEC("tp_btf/kfree_skb") 550 int BPF_PROG(test_dynptr_skb_tp_btf, void *skb, void *location) 551 { 552 __u8 write_data[2] = {1, 2}; 553 struct bpf_dynptr ptr; 554 int ret; 555 556 if (bpf_dynptr_from_skb(skb, 0, &ptr)) { 557 err = 1; 558 return 1; 559 } 560 561 /* since tp_btf skbs are read only, writes should fail */ 562 ret = bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0); 563 if (ret != -EINVAL) { 564 err = 2; 565 return 1; 566 } 567 568 return 1; 569 } 570