1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2020 Facebook */ 3 #include <test_progs.h> 4 #include "bpf_iter_ipv6_route.skel.h" 5 #include "bpf_iter_netlink.skel.h" 6 #include "bpf_iter_bpf_map.skel.h" 7 #include "bpf_iter_task.skel.h" 8 #include "bpf_iter_task_stack.skel.h" 9 #include "bpf_iter_task_file.skel.h" 10 #include "bpf_iter_task_vma.skel.h" 11 #include "bpf_iter_task_btf.skel.h" 12 #include "bpf_iter_tcp4.skel.h" 13 #include "bpf_iter_tcp6.skel.h" 14 #include "bpf_iter_udp4.skel.h" 15 #include "bpf_iter_udp6.skel.h" 16 #include "bpf_iter_unix.skel.h" 17 #include "bpf_iter_test_kern1.skel.h" 18 #include "bpf_iter_test_kern2.skel.h" 19 #include "bpf_iter_test_kern3.skel.h" 20 #include "bpf_iter_test_kern4.skel.h" 21 #include "bpf_iter_bpf_hash_map.skel.h" 22 #include "bpf_iter_bpf_percpu_hash_map.skel.h" 23 #include "bpf_iter_bpf_array_map.skel.h" 24 #include "bpf_iter_bpf_percpu_array_map.skel.h" 25 #include "bpf_iter_bpf_sk_storage_helpers.skel.h" 26 #include "bpf_iter_bpf_sk_storage_map.skel.h" 27 #include "bpf_iter_test_kern5.skel.h" 28 #include "bpf_iter_test_kern6.skel.h" 29 #include "bpf_iter_bpf_link.skel.h" 30 #include "bpf_iter_ksym.skel.h" 31 #include "bpf_iter_sockmap.skel.h" 32 33 static int duration; 34 35 static void test_btf_id_or_null(void) 36 { 37 struct bpf_iter_test_kern3 *skel; 38 39 skel = bpf_iter_test_kern3__open_and_load(); 40 if (!ASSERT_ERR_PTR(skel, "bpf_iter_test_kern3__open_and_load")) { 41 bpf_iter_test_kern3__destroy(skel); 42 return; 43 } 44 } 45 46 static void do_dummy_read(struct bpf_program *prog) 47 { 48 struct bpf_link *link; 49 char buf[16] = {}; 50 int iter_fd, len; 51 52 link = bpf_program__attach_iter(prog, NULL); 53 if (!ASSERT_OK_PTR(link, "attach_iter")) 54 return; 55 56 iter_fd = bpf_iter_create(bpf_link__fd(link)); 57 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 58 goto free_link; 59 60 /* not check contents, but ensure read() ends without error */ 61 while ((len = read(iter_fd, buf, sizeof(buf))) > 0) 62 ; 63 CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)); 64 65 close(iter_fd); 66 67 free_link: 68 bpf_link__destroy(link); 69 } 70 71 static void do_read_map_iter_fd(struct bpf_object_skeleton **skel, struct bpf_program *prog, 72 struct bpf_map *map) 73 { 74 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts); 75 union bpf_iter_link_info linfo; 76 struct bpf_link *link; 77 char buf[16] = {}; 78 int iter_fd, len; 79 80 memset(&linfo, 0, sizeof(linfo)); 81 linfo.map.map_fd = bpf_map__fd(map); 82 opts.link_info = &linfo; 83 opts.link_info_len = sizeof(linfo); 84 link = bpf_program__attach_iter(prog, &opts); 85 if (!ASSERT_OK_PTR(link, "attach_map_iter")) 86 return; 87 88 iter_fd = bpf_iter_create(bpf_link__fd(link)); 89 if (!ASSERT_GE(iter_fd, 0, "create_map_iter")) { 90 bpf_link__destroy(link); 91 return; 92 } 93 94 /* Close link and map fd prematurely */ 95 bpf_link__destroy(link); 96 bpf_object__destroy_skeleton(*skel); 97 *skel = NULL; 98 99 /* Try to let map free work to run first if map is freed */ 100 usleep(100); 101 /* Memory used by both sock map and sock local storage map are 102 * freed after two synchronize_rcu() calls, so wait for it 103 */ 104 kern_sync_rcu(); 105 kern_sync_rcu(); 106 107 /* Read after both map fd and link fd are closed */ 108 while ((len = read(iter_fd, buf, sizeof(buf))) > 0) 109 ; 110 ASSERT_GE(len, 0, "read_iterator"); 111 112 close(iter_fd); 113 } 114 115 static int read_fd_into_buffer(int fd, char *buf, int size) 116 { 117 int bufleft = size; 118 int len; 119 120 do { 121 len = read(fd, buf, bufleft); 122 if (len > 0) { 123 buf += len; 124 bufleft -= len; 125 } 126 } while (len > 0); 127 128 return len < 0 ? len : size - bufleft; 129 } 130 131 static void test_ipv6_route(void) 132 { 133 struct bpf_iter_ipv6_route *skel; 134 135 skel = bpf_iter_ipv6_route__open_and_load(); 136 if (!ASSERT_OK_PTR(skel, "bpf_iter_ipv6_route__open_and_load")) 137 return; 138 139 do_dummy_read(skel->progs.dump_ipv6_route); 140 141 bpf_iter_ipv6_route__destroy(skel); 142 } 143 144 static void test_netlink(void) 145 { 146 struct bpf_iter_netlink *skel; 147 148 skel = bpf_iter_netlink__open_and_load(); 149 if (!ASSERT_OK_PTR(skel, "bpf_iter_netlink__open_and_load")) 150 return; 151 152 do_dummy_read(skel->progs.dump_netlink); 153 154 bpf_iter_netlink__destroy(skel); 155 } 156 157 static void test_bpf_map(void) 158 { 159 struct bpf_iter_bpf_map *skel; 160 161 skel = bpf_iter_bpf_map__open_and_load(); 162 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_map__open_and_load")) 163 return; 164 165 do_dummy_read(skel->progs.dump_bpf_map); 166 167 bpf_iter_bpf_map__destroy(skel); 168 } 169 170 static void test_task(void) 171 { 172 struct bpf_iter_task *skel; 173 174 skel = bpf_iter_task__open_and_load(); 175 if (!ASSERT_OK_PTR(skel, "bpf_iter_task__open_and_load")) 176 return; 177 178 do_dummy_read(skel->progs.dump_task); 179 180 bpf_iter_task__destroy(skel); 181 } 182 183 static void test_task_sleepable(void) 184 { 185 struct bpf_iter_task *skel; 186 187 skel = bpf_iter_task__open_and_load(); 188 if (!ASSERT_OK_PTR(skel, "bpf_iter_task__open_and_load")) 189 return; 190 191 do_dummy_read(skel->progs.dump_task_sleepable); 192 193 ASSERT_GT(skel->bss->num_expected_failure_copy_from_user_task, 0, 194 "num_expected_failure_copy_from_user_task"); 195 ASSERT_GT(skel->bss->num_success_copy_from_user_task, 0, 196 "num_success_copy_from_user_task"); 197 198 bpf_iter_task__destroy(skel); 199 } 200 201 static void test_task_stack(void) 202 { 203 struct bpf_iter_task_stack *skel; 204 205 skel = bpf_iter_task_stack__open_and_load(); 206 if (!ASSERT_OK_PTR(skel, "bpf_iter_task_stack__open_and_load")) 207 return; 208 209 do_dummy_read(skel->progs.dump_task_stack); 210 do_dummy_read(skel->progs.get_task_user_stacks); 211 212 bpf_iter_task_stack__destroy(skel); 213 } 214 215 static void *do_nothing(void *arg) 216 { 217 pthread_exit(arg); 218 } 219 220 static void test_task_file(void) 221 { 222 struct bpf_iter_task_file *skel; 223 pthread_t thread_id; 224 void *ret; 225 226 skel = bpf_iter_task_file__open_and_load(); 227 if (!ASSERT_OK_PTR(skel, "bpf_iter_task_file__open_and_load")) 228 return; 229 230 skel->bss->tgid = getpid(); 231 232 if (!ASSERT_OK(pthread_create(&thread_id, NULL, &do_nothing, NULL), 233 "pthread_create")) 234 goto done; 235 236 do_dummy_read(skel->progs.dump_task_file); 237 238 if (!ASSERT_FALSE(pthread_join(thread_id, &ret) || ret != NULL, 239 "pthread_join")) 240 goto done; 241 242 ASSERT_EQ(skel->bss->count, 0, "check_count"); 243 244 done: 245 bpf_iter_task_file__destroy(skel); 246 } 247 248 #define TASKBUFSZ 32768 249 250 static char taskbuf[TASKBUFSZ]; 251 252 static int do_btf_read(struct bpf_iter_task_btf *skel) 253 { 254 struct bpf_program *prog = skel->progs.dump_task_struct; 255 struct bpf_iter_task_btf__bss *bss = skel->bss; 256 int iter_fd = -1, err; 257 struct bpf_link *link; 258 char *buf = taskbuf; 259 int ret = 0; 260 261 link = bpf_program__attach_iter(prog, NULL); 262 if (!ASSERT_OK_PTR(link, "attach_iter")) 263 return ret; 264 265 iter_fd = bpf_iter_create(bpf_link__fd(link)); 266 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 267 goto free_link; 268 269 err = read_fd_into_buffer(iter_fd, buf, TASKBUFSZ); 270 if (bss->skip) { 271 printf("%s:SKIP:no __builtin_btf_type_id\n", __func__); 272 ret = 1; 273 test__skip(); 274 goto free_link; 275 } 276 277 if (CHECK(err < 0, "read", "read failed: %s\n", strerror(errno))) 278 goto free_link; 279 280 ASSERT_HAS_SUBSTR(taskbuf, "(struct task_struct)", 281 "check for btf representation of task_struct in iter data"); 282 free_link: 283 if (iter_fd > 0) 284 close(iter_fd); 285 bpf_link__destroy(link); 286 return ret; 287 } 288 289 static void test_task_btf(void) 290 { 291 struct bpf_iter_task_btf__bss *bss; 292 struct bpf_iter_task_btf *skel; 293 int ret; 294 295 skel = bpf_iter_task_btf__open_and_load(); 296 if (!ASSERT_OK_PTR(skel, "bpf_iter_task_btf__open_and_load")) 297 return; 298 299 bss = skel->bss; 300 301 ret = do_btf_read(skel); 302 if (ret) 303 goto cleanup; 304 305 if (!ASSERT_NEQ(bss->tasks, 0, "no task iteration, did BPF program run?")) 306 goto cleanup; 307 308 ASSERT_EQ(bss->seq_err, 0, "check for unexpected err"); 309 310 cleanup: 311 bpf_iter_task_btf__destroy(skel); 312 } 313 314 static void test_tcp4(void) 315 { 316 struct bpf_iter_tcp4 *skel; 317 318 skel = bpf_iter_tcp4__open_and_load(); 319 if (!ASSERT_OK_PTR(skel, "bpf_iter_tcp4__open_and_load")) 320 return; 321 322 do_dummy_read(skel->progs.dump_tcp4); 323 324 bpf_iter_tcp4__destroy(skel); 325 } 326 327 static void test_tcp6(void) 328 { 329 struct bpf_iter_tcp6 *skel; 330 331 skel = bpf_iter_tcp6__open_and_load(); 332 if (!ASSERT_OK_PTR(skel, "bpf_iter_tcp6__open_and_load")) 333 return; 334 335 do_dummy_read(skel->progs.dump_tcp6); 336 337 bpf_iter_tcp6__destroy(skel); 338 } 339 340 static void test_udp4(void) 341 { 342 struct bpf_iter_udp4 *skel; 343 344 skel = bpf_iter_udp4__open_and_load(); 345 if (!ASSERT_OK_PTR(skel, "bpf_iter_udp4__open_and_load")) 346 return; 347 348 do_dummy_read(skel->progs.dump_udp4); 349 350 bpf_iter_udp4__destroy(skel); 351 } 352 353 static void test_udp6(void) 354 { 355 struct bpf_iter_udp6 *skel; 356 357 skel = bpf_iter_udp6__open_and_load(); 358 if (!ASSERT_OK_PTR(skel, "bpf_iter_udp6__open_and_load")) 359 return; 360 361 do_dummy_read(skel->progs.dump_udp6); 362 363 bpf_iter_udp6__destroy(skel); 364 } 365 366 static void test_unix(void) 367 { 368 struct bpf_iter_unix *skel; 369 370 skel = bpf_iter_unix__open_and_load(); 371 if (!ASSERT_OK_PTR(skel, "bpf_iter_unix__open_and_load")) 372 return; 373 374 do_dummy_read(skel->progs.dump_unix); 375 376 bpf_iter_unix__destroy(skel); 377 } 378 379 /* The expected string is less than 16 bytes */ 380 static int do_read_with_fd(int iter_fd, const char *expected, 381 bool read_one_char) 382 { 383 int len, read_buf_len, start; 384 char buf[16] = {}; 385 386 read_buf_len = read_one_char ? 1 : 16; 387 start = 0; 388 while ((len = read(iter_fd, buf + start, read_buf_len)) > 0) { 389 start += len; 390 if (CHECK(start >= 16, "read", "read len %d\n", len)) 391 return -1; 392 read_buf_len = read_one_char ? 1 : 16 - start; 393 } 394 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno))) 395 return -1; 396 397 if (!ASSERT_STREQ(buf, expected, "read")) 398 return -1; 399 400 return 0; 401 } 402 403 static void test_anon_iter(bool read_one_char) 404 { 405 struct bpf_iter_test_kern1 *skel; 406 struct bpf_link *link; 407 int iter_fd, err; 408 409 skel = bpf_iter_test_kern1__open_and_load(); 410 if (!ASSERT_OK_PTR(skel, "bpf_iter_test_kern1__open_and_load")) 411 return; 412 413 err = bpf_iter_test_kern1__attach(skel); 414 if (!ASSERT_OK(err, "bpf_iter_test_kern1__attach")) { 415 goto out; 416 } 417 418 link = skel->links.dump_task; 419 iter_fd = bpf_iter_create(bpf_link__fd(link)); 420 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 421 goto out; 422 423 do_read_with_fd(iter_fd, "abcd", read_one_char); 424 close(iter_fd); 425 426 out: 427 bpf_iter_test_kern1__destroy(skel); 428 } 429 430 static int do_read(const char *path, const char *expected) 431 { 432 int err, iter_fd; 433 434 iter_fd = open(path, O_RDONLY); 435 if (CHECK(iter_fd < 0, "open", "open %s failed: %s\n", 436 path, strerror(errno))) 437 return -1; 438 439 err = do_read_with_fd(iter_fd, expected, false); 440 close(iter_fd); 441 return err; 442 } 443 444 static void test_file_iter(void) 445 { 446 const char *path = "/sys/fs/bpf/bpf_iter_test1"; 447 struct bpf_iter_test_kern1 *skel1; 448 struct bpf_iter_test_kern2 *skel2; 449 struct bpf_link *link; 450 int err; 451 452 skel1 = bpf_iter_test_kern1__open_and_load(); 453 if (!ASSERT_OK_PTR(skel1, "bpf_iter_test_kern1__open_and_load")) 454 return; 455 456 link = bpf_program__attach_iter(skel1->progs.dump_task, NULL); 457 if (!ASSERT_OK_PTR(link, "attach_iter")) 458 goto out; 459 460 /* unlink this path if it exists. */ 461 unlink(path); 462 463 err = bpf_link__pin(link, path); 464 if (CHECK(err, "pin_iter", "pin_iter to %s failed: %d\n", path, err)) 465 goto free_link; 466 467 err = do_read(path, "abcd"); 468 if (err) 469 goto unlink_path; 470 471 /* file based iterator seems working fine. Let us a link update 472 * of the underlying link and `cat` the iterator again, its content 473 * should change. 474 */ 475 skel2 = bpf_iter_test_kern2__open_and_load(); 476 if (!ASSERT_OK_PTR(skel2, "bpf_iter_test_kern2__open_and_load")) 477 goto unlink_path; 478 479 err = bpf_link__update_program(link, skel2->progs.dump_task); 480 if (!ASSERT_OK(err, "update_prog")) 481 goto destroy_skel2; 482 483 do_read(path, "ABCD"); 484 485 destroy_skel2: 486 bpf_iter_test_kern2__destroy(skel2); 487 unlink_path: 488 unlink(path); 489 free_link: 490 bpf_link__destroy(link); 491 out: 492 bpf_iter_test_kern1__destroy(skel1); 493 } 494 495 static void test_overflow(bool test_e2big_overflow, bool ret1) 496 { 497 __u32 map_info_len, total_read_len, expected_read_len; 498 int err, iter_fd, map1_fd, map2_fd, len; 499 struct bpf_map_info map_info = {}; 500 struct bpf_iter_test_kern4 *skel; 501 struct bpf_link *link; 502 __u32 iter_size; 503 char *buf; 504 505 skel = bpf_iter_test_kern4__open(); 506 if (!ASSERT_OK_PTR(skel, "bpf_iter_test_kern4__open")) 507 return; 508 509 /* create two maps: bpf program will only do bpf_seq_write 510 * for these two maps. The goal is one map output almost 511 * fills seq_file buffer and then the other will trigger 512 * overflow and needs restart. 513 */ 514 map1_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, 4, 8, 1, NULL); 515 if (CHECK(map1_fd < 0, "bpf_map_create", 516 "map_creation failed: %s\n", strerror(errno))) 517 goto out; 518 map2_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, 4, 8, 1, NULL); 519 if (CHECK(map2_fd < 0, "bpf_map_create", 520 "map_creation failed: %s\n", strerror(errno))) 521 goto free_map1; 522 523 /* bpf_seq_printf kernel buffer is 8 pages, so one map 524 * bpf_seq_write will mostly fill it, and the other map 525 * will partially fill and then trigger overflow and need 526 * bpf_seq_read restart. 527 */ 528 iter_size = sysconf(_SC_PAGE_SIZE) << 3; 529 530 if (test_e2big_overflow) { 531 skel->rodata->print_len = (iter_size + 8) / 8; 532 expected_read_len = 2 * (iter_size + 8); 533 } else if (!ret1) { 534 skel->rodata->print_len = (iter_size - 8) / 8; 535 expected_read_len = 2 * (iter_size - 8); 536 } else { 537 skel->rodata->print_len = 1; 538 expected_read_len = 2 * 8; 539 } 540 skel->rodata->ret1 = ret1; 541 542 if (!ASSERT_OK(bpf_iter_test_kern4__load(skel), 543 "bpf_iter_test_kern4__load")) 544 goto free_map2; 545 546 /* setup filtering map_id in bpf program */ 547 map_info_len = sizeof(map_info); 548 err = bpf_obj_get_info_by_fd(map1_fd, &map_info, &map_info_len); 549 if (CHECK(err, "get_map_info", "get map info failed: %s\n", 550 strerror(errno))) 551 goto free_map2; 552 skel->bss->map1_id = map_info.id; 553 554 err = bpf_obj_get_info_by_fd(map2_fd, &map_info, &map_info_len); 555 if (CHECK(err, "get_map_info", "get map info failed: %s\n", 556 strerror(errno))) 557 goto free_map2; 558 skel->bss->map2_id = map_info.id; 559 560 link = bpf_program__attach_iter(skel->progs.dump_bpf_map, NULL); 561 if (!ASSERT_OK_PTR(link, "attach_iter")) 562 goto free_map2; 563 564 iter_fd = bpf_iter_create(bpf_link__fd(link)); 565 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 566 goto free_link; 567 568 buf = malloc(expected_read_len); 569 if (!buf) 570 goto close_iter; 571 572 /* do read */ 573 total_read_len = 0; 574 if (test_e2big_overflow) { 575 while ((len = read(iter_fd, buf, expected_read_len)) > 0) 576 total_read_len += len; 577 578 CHECK(len != -1 || errno != E2BIG, "read", 579 "expected ret -1, errno E2BIG, but get ret %d, error %s\n", 580 len, strerror(errno)); 581 goto free_buf; 582 } else if (!ret1) { 583 while ((len = read(iter_fd, buf, expected_read_len)) > 0) 584 total_read_len += len; 585 586 if (CHECK(len < 0, "read", "read failed: %s\n", 587 strerror(errno))) 588 goto free_buf; 589 } else { 590 do { 591 len = read(iter_fd, buf, expected_read_len); 592 if (len > 0) 593 total_read_len += len; 594 } while (len > 0 || len == -EAGAIN); 595 596 if (CHECK(len < 0, "read", "read failed: %s\n", 597 strerror(errno))) 598 goto free_buf; 599 } 600 601 if (!ASSERT_EQ(total_read_len, expected_read_len, "read")) 602 goto free_buf; 603 604 if (!ASSERT_EQ(skel->bss->map1_accessed, 1, "map1_accessed")) 605 goto free_buf; 606 607 if (!ASSERT_EQ(skel->bss->map2_accessed, 2, "map2_accessed")) 608 goto free_buf; 609 610 ASSERT_EQ(skel->bss->map2_seqnum1, skel->bss->map2_seqnum2, "map2_seqnum"); 611 612 free_buf: 613 free(buf); 614 close_iter: 615 close(iter_fd); 616 free_link: 617 bpf_link__destroy(link); 618 free_map2: 619 close(map2_fd); 620 free_map1: 621 close(map1_fd); 622 out: 623 bpf_iter_test_kern4__destroy(skel); 624 } 625 626 static void test_bpf_hash_map(void) 627 { 628 __u32 expected_key_a = 0, expected_key_b = 0; 629 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts); 630 struct bpf_iter_bpf_hash_map *skel; 631 int err, i, len, map_fd, iter_fd; 632 union bpf_iter_link_info linfo; 633 __u64 val, expected_val = 0; 634 struct bpf_link *link; 635 struct key_t { 636 int a; 637 int b; 638 int c; 639 } key; 640 char buf[64]; 641 642 skel = bpf_iter_bpf_hash_map__open(); 643 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_hash_map__open")) 644 return; 645 646 skel->bss->in_test_mode = true; 647 648 err = bpf_iter_bpf_hash_map__load(skel); 649 if (!ASSERT_OK(err, "bpf_iter_bpf_hash_map__load")) 650 goto out; 651 652 /* iterator with hashmap2 and hashmap3 should fail */ 653 memset(&linfo, 0, sizeof(linfo)); 654 linfo.map.map_fd = bpf_map__fd(skel->maps.hashmap2); 655 opts.link_info = &linfo; 656 opts.link_info_len = sizeof(linfo); 657 link = bpf_program__attach_iter(skel->progs.dump_bpf_hash_map, &opts); 658 if (!ASSERT_ERR_PTR(link, "attach_iter")) 659 goto out; 660 661 linfo.map.map_fd = bpf_map__fd(skel->maps.hashmap3); 662 link = bpf_program__attach_iter(skel->progs.dump_bpf_hash_map, &opts); 663 if (!ASSERT_ERR_PTR(link, "attach_iter")) 664 goto out; 665 666 /* hashmap1 should be good, update map values here */ 667 map_fd = bpf_map__fd(skel->maps.hashmap1); 668 for (i = 0; i < bpf_map__max_entries(skel->maps.hashmap1); i++) { 669 key.a = i + 1; 670 key.b = i + 2; 671 key.c = i + 3; 672 val = i + 4; 673 expected_key_a += key.a; 674 expected_key_b += key.b; 675 expected_val += val; 676 677 err = bpf_map_update_elem(map_fd, &key, &val, BPF_ANY); 678 if (!ASSERT_OK(err, "map_update")) 679 goto out; 680 } 681 682 /* Sleepable program is prohibited for hash map iterator */ 683 linfo.map.map_fd = map_fd; 684 link = bpf_program__attach_iter(skel->progs.sleepable_dummy_dump, &opts); 685 if (!ASSERT_ERR_PTR(link, "attach_sleepable_prog_to_iter")) 686 goto out; 687 688 linfo.map.map_fd = map_fd; 689 link = bpf_program__attach_iter(skel->progs.dump_bpf_hash_map, &opts); 690 if (!ASSERT_OK_PTR(link, "attach_iter")) 691 goto out; 692 693 iter_fd = bpf_iter_create(bpf_link__fd(link)); 694 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 695 goto free_link; 696 697 /* do some tests */ 698 while ((len = read(iter_fd, buf, sizeof(buf))) > 0) 699 ; 700 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno))) 701 goto close_iter; 702 703 /* test results */ 704 if (!ASSERT_EQ(skel->bss->key_sum_a, expected_key_a, "key_sum_a")) 705 goto close_iter; 706 if (!ASSERT_EQ(skel->bss->key_sum_b, expected_key_b, "key_sum_b")) 707 goto close_iter; 708 if (!ASSERT_EQ(skel->bss->val_sum, expected_val, "val_sum")) 709 goto close_iter; 710 711 close_iter: 712 close(iter_fd); 713 free_link: 714 bpf_link__destroy(link); 715 out: 716 bpf_iter_bpf_hash_map__destroy(skel); 717 } 718 719 static void test_bpf_percpu_hash_map(void) 720 { 721 __u32 expected_key_a = 0, expected_key_b = 0; 722 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts); 723 struct bpf_iter_bpf_percpu_hash_map *skel; 724 int err, i, j, len, map_fd, iter_fd; 725 union bpf_iter_link_info linfo; 726 __u32 expected_val = 0; 727 struct bpf_link *link; 728 struct key_t { 729 int a; 730 int b; 731 int c; 732 } key; 733 char buf[64]; 734 void *val; 735 736 skel = bpf_iter_bpf_percpu_hash_map__open(); 737 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_percpu_hash_map__open")) 738 return; 739 740 skel->rodata->num_cpus = bpf_num_possible_cpus(); 741 val = malloc(8 * bpf_num_possible_cpus()); 742 743 err = bpf_iter_bpf_percpu_hash_map__load(skel); 744 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_percpu_hash_map__load")) 745 goto out; 746 747 /* update map values here */ 748 map_fd = bpf_map__fd(skel->maps.hashmap1); 749 for (i = 0; i < bpf_map__max_entries(skel->maps.hashmap1); i++) { 750 key.a = i + 1; 751 key.b = i + 2; 752 key.c = i + 3; 753 expected_key_a += key.a; 754 expected_key_b += key.b; 755 756 for (j = 0; j < bpf_num_possible_cpus(); j++) { 757 *(__u32 *)(val + j * 8) = i + j; 758 expected_val += i + j; 759 } 760 761 err = bpf_map_update_elem(map_fd, &key, val, BPF_ANY); 762 if (!ASSERT_OK(err, "map_update")) 763 goto out; 764 } 765 766 memset(&linfo, 0, sizeof(linfo)); 767 linfo.map.map_fd = map_fd; 768 opts.link_info = &linfo; 769 opts.link_info_len = sizeof(linfo); 770 link = bpf_program__attach_iter(skel->progs.dump_bpf_percpu_hash_map, &opts); 771 if (!ASSERT_OK_PTR(link, "attach_iter")) 772 goto out; 773 774 iter_fd = bpf_iter_create(bpf_link__fd(link)); 775 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 776 goto free_link; 777 778 /* do some tests */ 779 while ((len = read(iter_fd, buf, sizeof(buf))) > 0) 780 ; 781 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno))) 782 goto close_iter; 783 784 /* test results */ 785 if (!ASSERT_EQ(skel->bss->key_sum_a, expected_key_a, "key_sum_a")) 786 goto close_iter; 787 if (!ASSERT_EQ(skel->bss->key_sum_b, expected_key_b, "key_sum_b")) 788 goto close_iter; 789 if (!ASSERT_EQ(skel->bss->val_sum, expected_val, "val_sum")) 790 goto close_iter; 791 792 close_iter: 793 close(iter_fd); 794 free_link: 795 bpf_link__destroy(link); 796 out: 797 bpf_iter_bpf_percpu_hash_map__destroy(skel); 798 free(val); 799 } 800 801 static void test_bpf_array_map(void) 802 { 803 __u64 val, expected_val = 0, res_first_val, first_val = 0; 804 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts); 805 __u32 expected_key = 0, res_first_key; 806 struct bpf_iter_bpf_array_map *skel; 807 union bpf_iter_link_info linfo; 808 int err, i, map_fd, iter_fd; 809 struct bpf_link *link; 810 char buf[64] = {}; 811 int len, start; 812 813 skel = bpf_iter_bpf_array_map__open_and_load(); 814 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_array_map__open_and_load")) 815 return; 816 817 map_fd = bpf_map__fd(skel->maps.arraymap1); 818 for (i = 0; i < bpf_map__max_entries(skel->maps.arraymap1); i++) { 819 val = i + 4; 820 expected_key += i; 821 expected_val += val; 822 823 if (i == 0) 824 first_val = val; 825 826 err = bpf_map_update_elem(map_fd, &i, &val, BPF_ANY); 827 if (!ASSERT_OK(err, "map_update")) 828 goto out; 829 } 830 831 memset(&linfo, 0, sizeof(linfo)); 832 linfo.map.map_fd = map_fd; 833 opts.link_info = &linfo; 834 opts.link_info_len = sizeof(linfo); 835 link = bpf_program__attach_iter(skel->progs.dump_bpf_array_map, &opts); 836 if (!ASSERT_OK_PTR(link, "attach_iter")) 837 goto out; 838 839 iter_fd = bpf_iter_create(bpf_link__fd(link)); 840 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 841 goto free_link; 842 843 /* do some tests */ 844 start = 0; 845 while ((len = read(iter_fd, buf + start, sizeof(buf) - start)) > 0) 846 start += len; 847 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno))) 848 goto close_iter; 849 850 /* test results */ 851 res_first_key = *(__u32 *)buf; 852 res_first_val = *(__u64 *)(buf + sizeof(__u32)); 853 if (CHECK(res_first_key != 0 || res_first_val != first_val, 854 "bpf_seq_write", 855 "seq_write failure: first key %u vs expected 0, " 856 " first value %llu vs expected %llu\n", 857 res_first_key, res_first_val, first_val)) 858 goto close_iter; 859 860 if (!ASSERT_EQ(skel->bss->key_sum, expected_key, "key_sum")) 861 goto close_iter; 862 if (!ASSERT_EQ(skel->bss->val_sum, expected_val, "val_sum")) 863 goto close_iter; 864 865 for (i = 0; i < bpf_map__max_entries(skel->maps.arraymap1); i++) { 866 err = bpf_map_lookup_elem(map_fd, &i, &val); 867 if (!ASSERT_OK(err, "map_lookup")) 868 goto out; 869 if (!ASSERT_EQ(i, val, "invalid_val")) 870 goto out; 871 } 872 873 close_iter: 874 close(iter_fd); 875 free_link: 876 bpf_link__destroy(link); 877 out: 878 bpf_iter_bpf_array_map__destroy(skel); 879 } 880 881 static void test_bpf_array_map_iter_fd(void) 882 { 883 struct bpf_iter_bpf_array_map *skel; 884 885 skel = bpf_iter_bpf_array_map__open_and_load(); 886 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_array_map__open_and_load")) 887 return; 888 889 do_read_map_iter_fd(&skel->skeleton, skel->progs.dump_bpf_array_map, 890 skel->maps.arraymap1); 891 892 bpf_iter_bpf_array_map__destroy(skel); 893 } 894 895 static void test_bpf_percpu_array_map(void) 896 { 897 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts); 898 struct bpf_iter_bpf_percpu_array_map *skel; 899 __u32 expected_key = 0, expected_val = 0; 900 union bpf_iter_link_info linfo; 901 int err, i, j, map_fd, iter_fd; 902 struct bpf_link *link; 903 char buf[64]; 904 void *val; 905 int len; 906 907 skel = bpf_iter_bpf_percpu_array_map__open(); 908 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_percpu_array_map__open")) 909 return; 910 911 skel->rodata->num_cpus = bpf_num_possible_cpus(); 912 val = malloc(8 * bpf_num_possible_cpus()); 913 914 err = bpf_iter_bpf_percpu_array_map__load(skel); 915 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_percpu_array_map__load")) 916 goto out; 917 918 /* update map values here */ 919 map_fd = bpf_map__fd(skel->maps.arraymap1); 920 for (i = 0; i < bpf_map__max_entries(skel->maps.arraymap1); i++) { 921 expected_key += i; 922 923 for (j = 0; j < bpf_num_possible_cpus(); j++) { 924 *(__u32 *)(val + j * 8) = i + j; 925 expected_val += i + j; 926 } 927 928 err = bpf_map_update_elem(map_fd, &i, val, BPF_ANY); 929 if (!ASSERT_OK(err, "map_update")) 930 goto out; 931 } 932 933 memset(&linfo, 0, sizeof(linfo)); 934 linfo.map.map_fd = map_fd; 935 opts.link_info = &linfo; 936 opts.link_info_len = sizeof(linfo); 937 link = bpf_program__attach_iter(skel->progs.dump_bpf_percpu_array_map, &opts); 938 if (!ASSERT_OK_PTR(link, "attach_iter")) 939 goto out; 940 941 iter_fd = bpf_iter_create(bpf_link__fd(link)); 942 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 943 goto free_link; 944 945 /* do some tests */ 946 while ((len = read(iter_fd, buf, sizeof(buf))) > 0) 947 ; 948 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno))) 949 goto close_iter; 950 951 /* test results */ 952 if (!ASSERT_EQ(skel->bss->key_sum, expected_key, "key_sum")) 953 goto close_iter; 954 if (!ASSERT_EQ(skel->bss->val_sum, expected_val, "val_sum")) 955 goto close_iter; 956 957 close_iter: 958 close(iter_fd); 959 free_link: 960 bpf_link__destroy(link); 961 out: 962 bpf_iter_bpf_percpu_array_map__destroy(skel); 963 free(val); 964 } 965 966 /* An iterator program deletes all local storage in a map. */ 967 static void test_bpf_sk_storage_delete(void) 968 { 969 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts); 970 struct bpf_iter_bpf_sk_storage_helpers *skel; 971 union bpf_iter_link_info linfo; 972 int err, len, map_fd, iter_fd; 973 struct bpf_link *link; 974 int sock_fd = -1; 975 __u32 val = 42; 976 char buf[64]; 977 978 skel = bpf_iter_bpf_sk_storage_helpers__open_and_load(); 979 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_sk_storage_helpers__open_and_load")) 980 return; 981 982 map_fd = bpf_map__fd(skel->maps.sk_stg_map); 983 984 sock_fd = socket(AF_INET6, SOCK_STREAM, 0); 985 if (!ASSERT_GE(sock_fd, 0, "socket")) 986 goto out; 987 err = bpf_map_update_elem(map_fd, &sock_fd, &val, BPF_NOEXIST); 988 if (!ASSERT_OK(err, "map_update")) 989 goto out; 990 991 memset(&linfo, 0, sizeof(linfo)); 992 linfo.map.map_fd = map_fd; 993 opts.link_info = &linfo; 994 opts.link_info_len = sizeof(linfo); 995 link = bpf_program__attach_iter(skel->progs.delete_bpf_sk_storage_map, 996 &opts); 997 if (!ASSERT_OK_PTR(link, "attach_iter")) 998 goto out; 999 1000 iter_fd = bpf_iter_create(bpf_link__fd(link)); 1001 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 1002 goto free_link; 1003 1004 /* do some tests */ 1005 while ((len = read(iter_fd, buf, sizeof(buf))) > 0) 1006 ; 1007 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno))) 1008 goto close_iter; 1009 1010 /* test results */ 1011 err = bpf_map_lookup_elem(map_fd, &sock_fd, &val); 1012 if (CHECK(!err || errno != ENOENT, "bpf_map_lookup_elem", 1013 "map value wasn't deleted (err=%d, errno=%d)\n", err, errno)) 1014 goto close_iter; 1015 1016 close_iter: 1017 close(iter_fd); 1018 free_link: 1019 bpf_link__destroy(link); 1020 out: 1021 if (sock_fd >= 0) 1022 close(sock_fd); 1023 bpf_iter_bpf_sk_storage_helpers__destroy(skel); 1024 } 1025 1026 /* This creates a socket and its local storage. It then runs a task_iter BPF 1027 * program that replaces the existing socket local storage with the tgid of the 1028 * only task owning a file descriptor to this socket, this process, prog_tests. 1029 * It then runs a tcp socket iterator that negates the value in the existing 1030 * socket local storage, the test verifies that the resulting value is -pid. 1031 */ 1032 static void test_bpf_sk_storage_get(void) 1033 { 1034 struct bpf_iter_bpf_sk_storage_helpers *skel; 1035 int err, map_fd, val = -1; 1036 int sock_fd = -1; 1037 1038 skel = bpf_iter_bpf_sk_storage_helpers__open_and_load(); 1039 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_sk_storage_helpers__open_and_load")) 1040 return; 1041 1042 sock_fd = socket(AF_INET6, SOCK_STREAM, 0); 1043 if (!ASSERT_GE(sock_fd, 0, "socket")) 1044 goto out; 1045 1046 err = listen(sock_fd, 1); 1047 if (!ASSERT_OK(err, "listen")) 1048 goto close_socket; 1049 1050 map_fd = bpf_map__fd(skel->maps.sk_stg_map); 1051 1052 err = bpf_map_update_elem(map_fd, &sock_fd, &val, BPF_NOEXIST); 1053 if (!ASSERT_OK(err, "bpf_map_update_elem")) 1054 goto close_socket; 1055 1056 do_dummy_read(skel->progs.fill_socket_owner); 1057 1058 err = bpf_map_lookup_elem(map_fd, &sock_fd, &val); 1059 if (CHECK(err || val != getpid(), "bpf_map_lookup_elem", 1060 "map value wasn't set correctly (expected %d, got %d, err=%d)\n", 1061 getpid(), val, err)) 1062 goto close_socket; 1063 1064 do_dummy_read(skel->progs.negate_socket_local_storage); 1065 1066 err = bpf_map_lookup_elem(map_fd, &sock_fd, &val); 1067 CHECK(err || val != -getpid(), "bpf_map_lookup_elem", 1068 "map value wasn't set correctly (expected %d, got %d, err=%d)\n", 1069 -getpid(), val, err); 1070 1071 close_socket: 1072 close(sock_fd); 1073 out: 1074 bpf_iter_bpf_sk_storage_helpers__destroy(skel); 1075 } 1076 1077 static void test_bpf_sk_stoarge_map_iter_fd(void) 1078 { 1079 struct bpf_iter_bpf_sk_storage_map *skel; 1080 1081 skel = bpf_iter_bpf_sk_storage_map__open_and_load(); 1082 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_sk_storage_map__open_and_load")) 1083 return; 1084 1085 do_read_map_iter_fd(&skel->skeleton, skel->progs.rw_bpf_sk_storage_map, 1086 skel->maps.sk_stg_map); 1087 1088 bpf_iter_bpf_sk_storage_map__destroy(skel); 1089 } 1090 1091 static void test_bpf_sk_storage_map(void) 1092 { 1093 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts); 1094 int err, i, len, map_fd, iter_fd, num_sockets; 1095 struct bpf_iter_bpf_sk_storage_map *skel; 1096 union bpf_iter_link_info linfo; 1097 int sock_fd[3] = {-1, -1, -1}; 1098 __u32 val, expected_val = 0; 1099 struct bpf_link *link; 1100 char buf[64]; 1101 1102 skel = bpf_iter_bpf_sk_storage_map__open_and_load(); 1103 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_sk_storage_map__open_and_load")) 1104 return; 1105 1106 map_fd = bpf_map__fd(skel->maps.sk_stg_map); 1107 num_sockets = ARRAY_SIZE(sock_fd); 1108 for (i = 0; i < num_sockets; i++) { 1109 sock_fd[i] = socket(AF_INET6, SOCK_STREAM, 0); 1110 if (!ASSERT_GE(sock_fd[i], 0, "socket")) 1111 goto out; 1112 1113 val = i + 1; 1114 expected_val += val; 1115 1116 err = bpf_map_update_elem(map_fd, &sock_fd[i], &val, 1117 BPF_NOEXIST); 1118 if (!ASSERT_OK(err, "map_update")) 1119 goto out; 1120 } 1121 1122 memset(&linfo, 0, sizeof(linfo)); 1123 linfo.map.map_fd = map_fd; 1124 opts.link_info = &linfo; 1125 opts.link_info_len = sizeof(linfo); 1126 link = bpf_program__attach_iter(skel->progs.oob_write_bpf_sk_storage_map, &opts); 1127 err = libbpf_get_error(link); 1128 if (!ASSERT_EQ(err, -EACCES, "attach_oob_write_iter")) { 1129 if (!err) 1130 bpf_link__destroy(link); 1131 goto out; 1132 } 1133 1134 link = bpf_program__attach_iter(skel->progs.rw_bpf_sk_storage_map, &opts); 1135 if (!ASSERT_OK_PTR(link, "attach_iter")) 1136 goto out; 1137 1138 iter_fd = bpf_iter_create(bpf_link__fd(link)); 1139 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 1140 goto free_link; 1141 1142 skel->bss->to_add_val = time(NULL); 1143 /* do some tests */ 1144 while ((len = read(iter_fd, buf, sizeof(buf))) > 0) 1145 ; 1146 if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno))) 1147 goto close_iter; 1148 1149 /* test results */ 1150 if (!ASSERT_EQ(skel->bss->ipv6_sk_count, num_sockets, "ipv6_sk_count")) 1151 goto close_iter; 1152 1153 if (!ASSERT_EQ(skel->bss->val_sum, expected_val, "val_sum")) 1154 goto close_iter; 1155 1156 for (i = 0; i < num_sockets; i++) { 1157 err = bpf_map_lookup_elem(map_fd, &sock_fd[i], &val); 1158 if (!ASSERT_OK(err, "map_lookup") || 1159 !ASSERT_EQ(val, i + 1 + skel->bss->to_add_val, "check_map_value")) 1160 break; 1161 } 1162 1163 close_iter: 1164 close(iter_fd); 1165 free_link: 1166 bpf_link__destroy(link); 1167 out: 1168 for (i = 0; i < num_sockets; i++) { 1169 if (sock_fd[i] >= 0) 1170 close(sock_fd[i]); 1171 } 1172 bpf_iter_bpf_sk_storage_map__destroy(skel); 1173 } 1174 1175 static void test_rdonly_buf_out_of_bound(void) 1176 { 1177 DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts); 1178 struct bpf_iter_test_kern5 *skel; 1179 union bpf_iter_link_info linfo; 1180 struct bpf_link *link; 1181 1182 skel = bpf_iter_test_kern5__open_and_load(); 1183 if (!ASSERT_OK_PTR(skel, "bpf_iter_test_kern5__open_and_load")) 1184 return; 1185 1186 memset(&linfo, 0, sizeof(linfo)); 1187 linfo.map.map_fd = bpf_map__fd(skel->maps.hashmap1); 1188 opts.link_info = &linfo; 1189 opts.link_info_len = sizeof(linfo); 1190 link = bpf_program__attach_iter(skel->progs.dump_bpf_hash_map, &opts); 1191 if (!ASSERT_ERR_PTR(link, "attach_iter")) 1192 bpf_link__destroy(link); 1193 1194 bpf_iter_test_kern5__destroy(skel); 1195 } 1196 1197 static void test_buf_neg_offset(void) 1198 { 1199 struct bpf_iter_test_kern6 *skel; 1200 1201 skel = bpf_iter_test_kern6__open_and_load(); 1202 if (!ASSERT_ERR_PTR(skel, "bpf_iter_test_kern6__open_and_load")) 1203 bpf_iter_test_kern6__destroy(skel); 1204 } 1205 1206 static void test_link_iter(void) 1207 { 1208 struct bpf_iter_bpf_link *skel; 1209 1210 skel = bpf_iter_bpf_link__open_and_load(); 1211 if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_link__open_and_load")) 1212 return; 1213 1214 do_dummy_read(skel->progs.dump_bpf_link); 1215 1216 bpf_iter_bpf_link__destroy(skel); 1217 } 1218 1219 static void test_ksym_iter(void) 1220 { 1221 struct bpf_iter_ksym *skel; 1222 1223 skel = bpf_iter_ksym__open_and_load(); 1224 if (!ASSERT_OK_PTR(skel, "bpf_iter_ksym__open_and_load")) 1225 return; 1226 1227 do_dummy_read(skel->progs.dump_ksym); 1228 1229 bpf_iter_ksym__destroy(skel); 1230 } 1231 1232 #define CMP_BUFFER_SIZE 1024 1233 static char task_vma_output[CMP_BUFFER_SIZE]; 1234 static char proc_maps_output[CMP_BUFFER_SIZE]; 1235 1236 /* remove \0 and \t from str, and only keep the first line */ 1237 static void str_strip_first_line(char *str) 1238 { 1239 char *dst = str, *src = str; 1240 1241 do { 1242 if (*src == ' ' || *src == '\t') 1243 src++; 1244 else 1245 *(dst++) = *(src++); 1246 1247 } while (*src != '\0' && *src != '\n'); 1248 1249 *dst = '\0'; 1250 } 1251 1252 static void test_task_vma(void) 1253 { 1254 int err, iter_fd = -1, proc_maps_fd = -1; 1255 struct bpf_iter_task_vma *skel; 1256 int len, read_size = 4; 1257 char maps_path[64]; 1258 1259 skel = bpf_iter_task_vma__open(); 1260 if (!ASSERT_OK_PTR(skel, "bpf_iter_task_vma__open")) 1261 return; 1262 1263 skel->bss->pid = getpid(); 1264 1265 err = bpf_iter_task_vma__load(skel); 1266 if (!ASSERT_OK(err, "bpf_iter_task_vma__load")) 1267 goto out; 1268 1269 skel->links.proc_maps = bpf_program__attach_iter( 1270 skel->progs.proc_maps, NULL); 1271 1272 if (!ASSERT_OK_PTR(skel->links.proc_maps, "bpf_program__attach_iter")) { 1273 skel->links.proc_maps = NULL; 1274 goto out; 1275 } 1276 1277 iter_fd = bpf_iter_create(bpf_link__fd(skel->links.proc_maps)); 1278 if (!ASSERT_GE(iter_fd, 0, "create_iter")) 1279 goto out; 1280 1281 /* Read CMP_BUFFER_SIZE (1kB) from bpf_iter. Read in small chunks 1282 * to trigger seq_file corner cases. 1283 */ 1284 len = 0; 1285 while (len < CMP_BUFFER_SIZE) { 1286 err = read_fd_into_buffer(iter_fd, task_vma_output + len, 1287 MIN(read_size, CMP_BUFFER_SIZE - len)); 1288 if (!err) 1289 break; 1290 if (!ASSERT_GE(err, 0, "read_iter_fd")) 1291 goto out; 1292 len += err; 1293 } 1294 1295 /* read CMP_BUFFER_SIZE (1kB) from /proc/pid/maps */ 1296 snprintf(maps_path, 64, "/proc/%u/maps", skel->bss->pid); 1297 proc_maps_fd = open(maps_path, O_RDONLY); 1298 if (!ASSERT_GE(proc_maps_fd, 0, "open_proc_maps")) 1299 goto out; 1300 err = read_fd_into_buffer(proc_maps_fd, proc_maps_output, CMP_BUFFER_SIZE); 1301 if (!ASSERT_GE(err, 0, "read_prog_maps_fd")) 1302 goto out; 1303 1304 /* strip and compare the first line of the two files */ 1305 str_strip_first_line(task_vma_output); 1306 str_strip_first_line(proc_maps_output); 1307 1308 ASSERT_STREQ(task_vma_output, proc_maps_output, "compare_output"); 1309 out: 1310 close(proc_maps_fd); 1311 close(iter_fd); 1312 bpf_iter_task_vma__destroy(skel); 1313 } 1314 1315 void test_bpf_sockmap_map_iter_fd(void) 1316 { 1317 struct bpf_iter_sockmap *skel; 1318 1319 skel = bpf_iter_sockmap__open_and_load(); 1320 if (!ASSERT_OK_PTR(skel, "bpf_iter_sockmap__open_and_load")) 1321 return; 1322 1323 do_read_map_iter_fd(&skel->skeleton, skel->progs.copy, skel->maps.sockmap); 1324 1325 bpf_iter_sockmap__destroy(skel); 1326 } 1327 1328 void test_bpf_iter(void) 1329 { 1330 if (test__start_subtest("btf_id_or_null")) 1331 test_btf_id_or_null(); 1332 if (test__start_subtest("ipv6_route")) 1333 test_ipv6_route(); 1334 if (test__start_subtest("netlink")) 1335 test_netlink(); 1336 if (test__start_subtest("bpf_map")) 1337 test_bpf_map(); 1338 if (test__start_subtest("task")) 1339 test_task(); 1340 if (test__start_subtest("task_sleepable")) 1341 test_task_sleepable(); 1342 if (test__start_subtest("task_stack")) 1343 test_task_stack(); 1344 if (test__start_subtest("task_file")) 1345 test_task_file(); 1346 if (test__start_subtest("task_vma")) 1347 test_task_vma(); 1348 if (test__start_subtest("task_btf")) 1349 test_task_btf(); 1350 if (test__start_subtest("tcp4")) 1351 test_tcp4(); 1352 if (test__start_subtest("tcp6")) 1353 test_tcp6(); 1354 if (test__start_subtest("udp4")) 1355 test_udp4(); 1356 if (test__start_subtest("udp6")) 1357 test_udp6(); 1358 if (test__start_subtest("unix")) 1359 test_unix(); 1360 if (test__start_subtest("anon")) 1361 test_anon_iter(false); 1362 if (test__start_subtest("anon-read-one-char")) 1363 test_anon_iter(true); 1364 if (test__start_subtest("file")) 1365 test_file_iter(); 1366 if (test__start_subtest("overflow")) 1367 test_overflow(false, false); 1368 if (test__start_subtest("overflow-e2big")) 1369 test_overflow(true, false); 1370 if (test__start_subtest("prog-ret-1")) 1371 test_overflow(false, true); 1372 if (test__start_subtest("bpf_hash_map")) 1373 test_bpf_hash_map(); 1374 if (test__start_subtest("bpf_percpu_hash_map")) 1375 test_bpf_percpu_hash_map(); 1376 if (test__start_subtest("bpf_array_map")) 1377 test_bpf_array_map(); 1378 if (test__start_subtest("bpf_array_map_iter_fd")) 1379 test_bpf_array_map_iter_fd(); 1380 if (test__start_subtest("bpf_percpu_array_map")) 1381 test_bpf_percpu_array_map(); 1382 if (test__start_subtest("bpf_sk_storage_map")) 1383 test_bpf_sk_storage_map(); 1384 if (test__start_subtest("bpf_sk_storage_map_iter_fd")) 1385 test_bpf_sk_stoarge_map_iter_fd(); 1386 if (test__start_subtest("bpf_sk_storage_delete")) 1387 test_bpf_sk_storage_delete(); 1388 if (test__start_subtest("bpf_sk_storage_get")) 1389 test_bpf_sk_storage_get(); 1390 if (test__start_subtest("rdonly-buf-out-of-bound")) 1391 test_rdonly_buf_out_of_bound(); 1392 if (test__start_subtest("buf-neg-offset")) 1393 test_buf_neg_offset(); 1394 if (test__start_subtest("link-iter")) 1395 test_link_iter(); 1396 if (test__start_subtest("ksym")) 1397 test_ksym_iter(); 1398 if (test__start_subtest("bpf_sockmap_map_iter_fd")) 1399 test_bpf_sockmap_map_iter_fd(); 1400 } 1401