1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */ 3 4 #define _GNU_SOURCE 5 #include <errno.h> 6 #include <fcntl.h> 7 #include <stdarg.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <time.h> 12 #include <unistd.h> 13 #include <net/if.h> 14 #include <sys/types.h> 15 #include <sys/stat.h> 16 17 #include <linux/err.h> 18 19 #include <bpf.h> 20 #include <btf.h> 21 #include <libbpf.h> 22 23 #include "cfg.h" 24 #include "main.h" 25 #include "xlated_dumper.h" 26 27 static const char * const attach_type_strings[] = { 28 [BPF_SK_SKB_STREAM_PARSER] = "stream_parser", 29 [BPF_SK_SKB_STREAM_VERDICT] = "stream_verdict", 30 [BPF_SK_MSG_VERDICT] = "msg_verdict", 31 [BPF_FLOW_DISSECTOR] = "flow_dissector", 32 [__MAX_BPF_ATTACH_TYPE] = NULL, 33 }; 34 35 static enum bpf_attach_type parse_attach_type(const char *str) 36 { 37 enum bpf_attach_type type; 38 39 for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) { 40 if (attach_type_strings[type] && 41 is_prefix(str, attach_type_strings[type])) 42 return type; 43 } 44 45 return __MAX_BPF_ATTACH_TYPE; 46 } 47 48 static void print_boot_time(__u64 nsecs, char *buf, unsigned int size) 49 { 50 struct timespec real_time_ts, boot_time_ts; 51 time_t wallclock_secs; 52 struct tm load_tm; 53 54 buf[--size] = '\0'; 55 56 if (clock_gettime(CLOCK_REALTIME, &real_time_ts) || 57 clock_gettime(CLOCK_BOOTTIME, &boot_time_ts)) { 58 perror("Can't read clocks"); 59 snprintf(buf, size, "%llu", nsecs / 1000000000); 60 return; 61 } 62 63 wallclock_secs = (real_time_ts.tv_sec - boot_time_ts.tv_sec) + 64 (real_time_ts.tv_nsec - boot_time_ts.tv_nsec + nsecs) / 65 1000000000; 66 67 68 if (!localtime_r(&wallclock_secs, &load_tm)) { 69 snprintf(buf, size, "%llu", nsecs / 1000000000); 70 return; 71 } 72 73 if (json_output) 74 strftime(buf, size, "%s", &load_tm); 75 else 76 strftime(buf, size, "%FT%T%z", &load_tm); 77 } 78 79 static int prog_fd_by_tag(unsigned char *tag) 80 { 81 unsigned int id = 0; 82 int err; 83 int fd; 84 85 while (true) { 86 struct bpf_prog_info info = {}; 87 __u32 len = sizeof(info); 88 89 err = bpf_prog_get_next_id(id, &id); 90 if (err) { 91 p_err("%s", strerror(errno)); 92 return -1; 93 } 94 95 fd = bpf_prog_get_fd_by_id(id); 96 if (fd < 0) { 97 p_err("can't get prog by id (%u): %s", 98 id, strerror(errno)); 99 return -1; 100 } 101 102 err = bpf_obj_get_info_by_fd(fd, &info, &len); 103 if (err) { 104 p_err("can't get prog info (%u): %s", 105 id, strerror(errno)); 106 close(fd); 107 return -1; 108 } 109 110 if (!memcmp(tag, info.tag, BPF_TAG_SIZE)) 111 return fd; 112 113 close(fd); 114 } 115 } 116 117 int prog_parse_fd(int *argc, char ***argv) 118 { 119 int fd; 120 121 if (is_prefix(**argv, "id")) { 122 unsigned int id; 123 char *endptr; 124 125 NEXT_ARGP(); 126 127 id = strtoul(**argv, &endptr, 0); 128 if (*endptr) { 129 p_err("can't parse %s as ID", **argv); 130 return -1; 131 } 132 NEXT_ARGP(); 133 134 fd = bpf_prog_get_fd_by_id(id); 135 if (fd < 0) 136 p_err("get by id (%u): %s", id, strerror(errno)); 137 return fd; 138 } else if (is_prefix(**argv, "tag")) { 139 unsigned char tag[BPF_TAG_SIZE]; 140 141 NEXT_ARGP(); 142 143 if (sscanf(**argv, BPF_TAG_FMT, tag, tag + 1, tag + 2, 144 tag + 3, tag + 4, tag + 5, tag + 6, tag + 7) 145 != BPF_TAG_SIZE) { 146 p_err("can't parse tag"); 147 return -1; 148 } 149 NEXT_ARGP(); 150 151 return prog_fd_by_tag(tag); 152 } else if (is_prefix(**argv, "pinned")) { 153 char *path; 154 155 NEXT_ARGP(); 156 157 path = **argv; 158 NEXT_ARGP(); 159 160 return open_obj_pinned_any(path, BPF_OBJ_PROG); 161 } 162 163 p_err("expected 'id', 'tag' or 'pinned', got: '%s'?", **argv); 164 return -1; 165 } 166 167 static void show_prog_maps(int fd, u32 num_maps) 168 { 169 struct bpf_prog_info info = {}; 170 __u32 len = sizeof(info); 171 __u32 map_ids[num_maps]; 172 unsigned int i; 173 int err; 174 175 info.nr_map_ids = num_maps; 176 info.map_ids = ptr_to_u64(map_ids); 177 178 err = bpf_obj_get_info_by_fd(fd, &info, &len); 179 if (err || !info.nr_map_ids) 180 return; 181 182 if (json_output) { 183 jsonw_name(json_wtr, "map_ids"); 184 jsonw_start_array(json_wtr); 185 for (i = 0; i < info.nr_map_ids; i++) 186 jsonw_uint(json_wtr, map_ids[i]); 187 jsonw_end_array(json_wtr); 188 } else { 189 printf(" map_ids "); 190 for (i = 0; i < info.nr_map_ids; i++) 191 printf("%u%s", map_ids[i], 192 i == info.nr_map_ids - 1 ? "" : ","); 193 } 194 } 195 196 static void print_prog_json(struct bpf_prog_info *info, int fd) 197 { 198 char *memlock; 199 200 jsonw_start_object(json_wtr); 201 jsonw_uint_field(json_wtr, "id", info->id); 202 if (info->type < ARRAY_SIZE(prog_type_name)) 203 jsonw_string_field(json_wtr, "type", 204 prog_type_name[info->type]); 205 else 206 jsonw_uint_field(json_wtr, "type", info->type); 207 208 if (*info->name) 209 jsonw_string_field(json_wtr, "name", info->name); 210 211 jsonw_name(json_wtr, "tag"); 212 jsonw_printf(json_wtr, "\"" BPF_TAG_FMT "\"", 213 info->tag[0], info->tag[1], info->tag[2], info->tag[3], 214 info->tag[4], info->tag[5], info->tag[6], info->tag[7]); 215 216 jsonw_bool_field(json_wtr, "gpl_compatible", info->gpl_compatible); 217 if (info->run_time_ns) { 218 jsonw_uint_field(json_wtr, "run_time_ns", info->run_time_ns); 219 jsonw_uint_field(json_wtr, "run_cnt", info->run_cnt); 220 } 221 222 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino); 223 224 if (info->load_time) { 225 char buf[32]; 226 227 print_boot_time(info->load_time, buf, sizeof(buf)); 228 229 /* Piggy back on load_time, since 0 uid is a valid one */ 230 jsonw_name(json_wtr, "loaded_at"); 231 jsonw_printf(json_wtr, "%s", buf); 232 jsonw_uint_field(json_wtr, "uid", info->created_by_uid); 233 } 234 235 jsonw_uint_field(json_wtr, "bytes_xlated", info->xlated_prog_len); 236 237 if (info->jited_prog_len) { 238 jsonw_bool_field(json_wtr, "jited", true); 239 jsonw_uint_field(json_wtr, "bytes_jited", info->jited_prog_len); 240 } else { 241 jsonw_bool_field(json_wtr, "jited", false); 242 } 243 244 memlock = get_fdinfo(fd, "memlock"); 245 if (memlock) 246 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock)); 247 free(memlock); 248 249 if (info->nr_map_ids) 250 show_prog_maps(fd, info->nr_map_ids); 251 252 if (info->btf_id) 253 jsonw_int_field(json_wtr, "btf_id", info->btf_id); 254 255 if (!hash_empty(prog_table.table)) { 256 struct pinned_obj *obj; 257 258 jsonw_name(json_wtr, "pinned"); 259 jsonw_start_array(json_wtr); 260 hash_for_each_possible(prog_table.table, obj, hash, info->id) { 261 if (obj->id == info->id) 262 jsonw_string(json_wtr, obj->path); 263 } 264 jsonw_end_array(json_wtr); 265 } 266 267 jsonw_end_object(json_wtr); 268 } 269 270 static void print_prog_plain(struct bpf_prog_info *info, int fd) 271 { 272 char *memlock; 273 274 printf("%u: ", info->id); 275 if (info->type < ARRAY_SIZE(prog_type_name)) 276 printf("%s ", prog_type_name[info->type]); 277 else 278 printf("type %u ", info->type); 279 280 if (*info->name) 281 printf("name %s ", info->name); 282 283 printf("tag "); 284 fprint_hex(stdout, info->tag, BPF_TAG_SIZE, ""); 285 print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino); 286 printf("%s", info->gpl_compatible ? " gpl" : ""); 287 if (info->run_time_ns) 288 printf(" run_time_ns %lld run_cnt %lld", 289 info->run_time_ns, info->run_cnt); 290 printf("\n"); 291 292 if (info->load_time) { 293 char buf[32]; 294 295 print_boot_time(info->load_time, buf, sizeof(buf)); 296 297 /* Piggy back on load_time, since 0 uid is a valid one */ 298 printf("\tloaded_at %s uid %u\n", buf, info->created_by_uid); 299 } 300 301 printf("\txlated %uB", info->xlated_prog_len); 302 303 if (info->jited_prog_len) 304 printf(" jited %uB", info->jited_prog_len); 305 else 306 printf(" not jited"); 307 308 memlock = get_fdinfo(fd, "memlock"); 309 if (memlock) 310 printf(" memlock %sB", memlock); 311 free(memlock); 312 313 if (info->nr_map_ids) 314 show_prog_maps(fd, info->nr_map_ids); 315 316 if (!hash_empty(prog_table.table)) { 317 struct pinned_obj *obj; 318 319 hash_for_each_possible(prog_table.table, obj, hash, info->id) { 320 if (obj->id == info->id) 321 printf("\n\tpinned %s", obj->path); 322 } 323 } 324 325 if (info->btf_id) 326 printf("\n\tbtf_id %d", info->btf_id); 327 328 printf("\n"); 329 } 330 331 static int show_prog(int fd) 332 { 333 struct bpf_prog_info info = {}; 334 __u32 len = sizeof(info); 335 int err; 336 337 err = bpf_obj_get_info_by_fd(fd, &info, &len); 338 if (err) { 339 p_err("can't get prog info: %s", strerror(errno)); 340 return -1; 341 } 342 343 if (json_output) 344 print_prog_json(&info, fd); 345 else 346 print_prog_plain(&info, fd); 347 348 return 0; 349 } 350 351 static int do_show(int argc, char **argv) 352 { 353 __u32 id = 0; 354 int err; 355 int fd; 356 357 if (show_pinned) 358 build_pinned_obj_table(&prog_table, BPF_OBJ_PROG); 359 360 if (argc == 2) { 361 fd = prog_parse_fd(&argc, &argv); 362 if (fd < 0) 363 return -1; 364 365 return show_prog(fd); 366 } 367 368 if (argc) 369 return BAD_ARG(); 370 371 if (json_output) 372 jsonw_start_array(json_wtr); 373 while (true) { 374 err = bpf_prog_get_next_id(id, &id); 375 if (err) { 376 if (errno == ENOENT) { 377 err = 0; 378 break; 379 } 380 p_err("can't get next program: %s%s", strerror(errno), 381 errno == EINVAL ? " -- kernel too old?" : ""); 382 err = -1; 383 break; 384 } 385 386 fd = bpf_prog_get_fd_by_id(id); 387 if (fd < 0) { 388 if (errno == ENOENT) 389 continue; 390 p_err("can't get prog by id (%u): %s", 391 id, strerror(errno)); 392 err = -1; 393 break; 394 } 395 396 err = show_prog(fd); 397 close(fd); 398 if (err) 399 break; 400 } 401 402 if (json_output) 403 jsonw_end_array(json_wtr); 404 405 return err; 406 } 407 408 static int do_dump(int argc, char **argv) 409 { 410 struct bpf_prog_info_linear *info_linear; 411 struct bpf_prog_linfo *prog_linfo = NULL; 412 enum {DUMP_JITED, DUMP_XLATED} mode; 413 const char *disasm_opt = NULL; 414 struct bpf_prog_info *info; 415 struct dump_data dd = {}; 416 void *func_info = NULL; 417 struct btf *btf = NULL; 418 char *filepath = NULL; 419 bool opcodes = false; 420 bool visual = false; 421 char func_sig[1024]; 422 unsigned char *buf; 423 bool linum = false; 424 __u32 member_len; 425 __u64 arrays; 426 ssize_t n; 427 int fd; 428 429 if (is_prefix(*argv, "jited")) { 430 if (disasm_init()) 431 return -1; 432 mode = DUMP_JITED; 433 } else if (is_prefix(*argv, "xlated")) { 434 mode = DUMP_XLATED; 435 } else { 436 p_err("expected 'xlated' or 'jited', got: %s", *argv); 437 return -1; 438 } 439 NEXT_ARG(); 440 441 if (argc < 2) 442 usage(); 443 444 fd = prog_parse_fd(&argc, &argv); 445 if (fd < 0) 446 return -1; 447 448 if (is_prefix(*argv, "file")) { 449 NEXT_ARG(); 450 if (!argc) { 451 p_err("expected file path"); 452 return -1; 453 } 454 455 filepath = *argv; 456 NEXT_ARG(); 457 } else if (is_prefix(*argv, "opcodes")) { 458 opcodes = true; 459 NEXT_ARG(); 460 } else if (is_prefix(*argv, "visual")) { 461 visual = true; 462 NEXT_ARG(); 463 } else if (is_prefix(*argv, "linum")) { 464 linum = true; 465 NEXT_ARG(); 466 } 467 468 if (argc) { 469 usage(); 470 return -1; 471 } 472 473 if (mode == DUMP_JITED) 474 arrays = 1UL << BPF_PROG_INFO_JITED_INSNS; 475 else 476 arrays = 1UL << BPF_PROG_INFO_XLATED_INSNS; 477 478 arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS; 479 arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; 480 arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; 481 arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; 482 arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO; 483 484 info_linear = bpf_program__get_prog_info_linear(fd, arrays); 485 close(fd); 486 if (IS_ERR_OR_NULL(info_linear)) { 487 p_err("can't get prog info: %s", strerror(errno)); 488 return -1; 489 } 490 491 info = &info_linear->info; 492 if (mode == DUMP_JITED) { 493 if (info->jited_prog_len == 0) { 494 p_info("no instructions returned"); 495 goto err_free; 496 } 497 buf = (unsigned char *)(info->jited_prog_insns); 498 member_len = info->jited_prog_len; 499 } else { /* DUMP_XLATED */ 500 if (info->xlated_prog_len == 0) { 501 p_err("error retrieving insn dump: kernel.kptr_restrict set?"); 502 goto err_free; 503 } 504 buf = (unsigned char *)info->xlated_prog_insns; 505 member_len = info->xlated_prog_len; 506 } 507 508 if (info->btf_id && btf__get_from_id(info->btf_id, &btf)) { 509 p_err("failed to get btf"); 510 goto err_free; 511 } 512 513 func_info = (void *)info->func_info; 514 515 if (info->nr_line_info) { 516 prog_linfo = bpf_prog_linfo__new(info); 517 if (!prog_linfo) 518 p_info("error in processing bpf_line_info. continue without it."); 519 } 520 521 if (filepath) { 522 fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600); 523 if (fd < 0) { 524 p_err("can't open file %s: %s", filepath, 525 strerror(errno)); 526 goto err_free; 527 } 528 529 n = write(fd, buf, member_len); 530 close(fd); 531 if (n != member_len) { 532 p_err("error writing output file: %s", 533 n < 0 ? strerror(errno) : "short write"); 534 goto err_free; 535 } 536 537 if (json_output) 538 jsonw_null(json_wtr); 539 } else if (mode == DUMP_JITED) { 540 const char *name = NULL; 541 542 if (info->ifindex) { 543 name = ifindex_to_bfd_params(info->ifindex, 544 info->netns_dev, 545 info->netns_ino, 546 &disasm_opt); 547 if (!name) 548 goto err_free; 549 } 550 551 if (info->nr_jited_func_lens && info->jited_func_lens) { 552 struct kernel_sym *sym = NULL; 553 struct bpf_func_info *record; 554 char sym_name[SYM_MAX_NAME]; 555 unsigned char *img = buf; 556 __u64 *ksyms = NULL; 557 __u32 *lens; 558 __u32 i; 559 if (info->nr_jited_ksyms) { 560 kernel_syms_load(&dd); 561 ksyms = (__u64 *) info->jited_ksyms; 562 } 563 564 if (json_output) 565 jsonw_start_array(json_wtr); 566 567 lens = (__u32 *) info->jited_func_lens; 568 for (i = 0; i < info->nr_jited_func_lens; i++) { 569 if (ksyms) { 570 sym = kernel_syms_search(&dd, ksyms[i]); 571 if (sym) 572 sprintf(sym_name, "%s", sym->name); 573 else 574 sprintf(sym_name, "0x%016llx", ksyms[i]); 575 } else { 576 strcpy(sym_name, "unknown"); 577 } 578 579 if (func_info) { 580 record = func_info + i * info->func_info_rec_size; 581 btf_dumper_type_only(btf, record->type_id, 582 func_sig, 583 sizeof(func_sig)); 584 } 585 586 if (json_output) { 587 jsonw_start_object(json_wtr); 588 if (func_info && func_sig[0] != '\0') { 589 jsonw_name(json_wtr, "proto"); 590 jsonw_string(json_wtr, func_sig); 591 } 592 jsonw_name(json_wtr, "name"); 593 jsonw_string(json_wtr, sym_name); 594 jsonw_name(json_wtr, "insns"); 595 } else { 596 if (func_info && func_sig[0] != '\0') 597 printf("%s:\n", func_sig); 598 printf("%s:\n", sym_name); 599 } 600 601 disasm_print_insn(img, lens[i], opcodes, 602 name, disasm_opt, btf, 603 prog_linfo, ksyms[i], i, 604 linum); 605 606 img += lens[i]; 607 608 if (json_output) 609 jsonw_end_object(json_wtr); 610 else 611 printf("\n"); 612 } 613 614 if (json_output) 615 jsonw_end_array(json_wtr); 616 } else { 617 disasm_print_insn(buf, member_len, opcodes, name, 618 disasm_opt, btf, NULL, 0, 0, false); 619 } 620 } else if (visual) { 621 if (json_output) 622 jsonw_null(json_wtr); 623 else 624 dump_xlated_cfg(buf, member_len); 625 } else { 626 kernel_syms_load(&dd); 627 dd.nr_jited_ksyms = info->nr_jited_ksyms; 628 dd.jited_ksyms = (__u64 *) info->jited_ksyms; 629 dd.btf = btf; 630 dd.func_info = func_info; 631 dd.finfo_rec_size = info->func_info_rec_size; 632 dd.prog_linfo = prog_linfo; 633 634 if (json_output) 635 dump_xlated_json(&dd, buf, member_len, opcodes, 636 linum); 637 else 638 dump_xlated_plain(&dd, buf, member_len, opcodes, 639 linum); 640 kernel_syms_destroy(&dd); 641 } 642 643 free(info_linear); 644 return 0; 645 646 err_free: 647 free(info_linear); 648 return -1; 649 } 650 651 static int do_pin(int argc, char **argv) 652 { 653 int err; 654 655 err = do_pin_any(argc, argv, bpf_prog_get_fd_by_id); 656 if (!err && json_output) 657 jsonw_null(json_wtr); 658 return err; 659 } 660 661 struct map_replace { 662 int idx; 663 int fd; 664 char *name; 665 }; 666 667 static int map_replace_compar(const void *p1, const void *p2) 668 { 669 const struct map_replace *a = p1, *b = p2; 670 671 return a->idx - b->idx; 672 } 673 674 static int parse_attach_detach_args(int argc, char **argv, int *progfd, 675 enum bpf_attach_type *attach_type, 676 int *mapfd) 677 { 678 if (!REQ_ARGS(3)) 679 return -EINVAL; 680 681 *progfd = prog_parse_fd(&argc, &argv); 682 if (*progfd < 0) 683 return *progfd; 684 685 *attach_type = parse_attach_type(*argv); 686 if (*attach_type == __MAX_BPF_ATTACH_TYPE) { 687 p_err("invalid attach/detach type"); 688 return -EINVAL; 689 } 690 691 if (*attach_type == BPF_FLOW_DISSECTOR) { 692 *mapfd = -1; 693 return 0; 694 } 695 696 NEXT_ARG(); 697 if (!REQ_ARGS(2)) 698 return -EINVAL; 699 700 *mapfd = map_parse_fd(&argc, &argv); 701 if (*mapfd < 0) 702 return *mapfd; 703 704 return 0; 705 } 706 707 static int do_attach(int argc, char **argv) 708 { 709 enum bpf_attach_type attach_type; 710 int err, progfd; 711 int mapfd; 712 713 err = parse_attach_detach_args(argc, argv, 714 &progfd, &attach_type, &mapfd); 715 if (err) 716 return err; 717 718 err = bpf_prog_attach(progfd, mapfd, attach_type, 0); 719 if (err) { 720 p_err("failed prog attach to map"); 721 return -EINVAL; 722 } 723 724 if (json_output) 725 jsonw_null(json_wtr); 726 return 0; 727 } 728 729 static int do_detach(int argc, char **argv) 730 { 731 enum bpf_attach_type attach_type; 732 int err, progfd; 733 int mapfd; 734 735 err = parse_attach_detach_args(argc, argv, 736 &progfd, &attach_type, &mapfd); 737 if (err) 738 return err; 739 740 err = bpf_prog_detach2(progfd, mapfd, attach_type); 741 if (err) { 742 p_err("failed prog detach from map"); 743 return -EINVAL; 744 } 745 746 if (json_output) 747 jsonw_null(json_wtr); 748 return 0; 749 } 750 751 static int load_with_options(int argc, char **argv, bool first_prog_only) 752 { 753 enum bpf_attach_type expected_attach_type; 754 struct bpf_object_open_attr attr = { 755 .prog_type = BPF_PROG_TYPE_UNSPEC, 756 }; 757 struct map_replace *map_replace = NULL; 758 struct bpf_program *prog = NULL, *pos; 759 unsigned int old_map_fds = 0; 760 const char *pinmaps = NULL; 761 struct bpf_object *obj; 762 struct bpf_map *map; 763 const char *pinfile; 764 unsigned int i, j; 765 __u32 ifindex = 0; 766 int idx, err; 767 768 if (!REQ_ARGS(2)) 769 return -1; 770 attr.file = GET_ARG(); 771 pinfile = GET_ARG(); 772 773 while (argc) { 774 if (is_prefix(*argv, "type")) { 775 char *type; 776 777 NEXT_ARG(); 778 779 if (attr.prog_type != BPF_PROG_TYPE_UNSPEC) { 780 p_err("program type already specified"); 781 goto err_free_reuse_maps; 782 } 783 if (!REQ_ARGS(1)) 784 goto err_free_reuse_maps; 785 786 /* Put a '/' at the end of type to appease libbpf */ 787 type = malloc(strlen(*argv) + 2); 788 if (!type) { 789 p_err("mem alloc failed"); 790 goto err_free_reuse_maps; 791 } 792 *type = 0; 793 strcat(type, *argv); 794 strcat(type, "/"); 795 796 err = libbpf_prog_type_by_name(type, &attr.prog_type, 797 &expected_attach_type); 798 free(type); 799 if (err < 0) 800 goto err_free_reuse_maps; 801 802 NEXT_ARG(); 803 } else if (is_prefix(*argv, "map")) { 804 void *new_map_replace; 805 char *endptr, *name; 806 int fd; 807 808 NEXT_ARG(); 809 810 if (!REQ_ARGS(4)) 811 goto err_free_reuse_maps; 812 813 if (is_prefix(*argv, "idx")) { 814 NEXT_ARG(); 815 816 idx = strtoul(*argv, &endptr, 0); 817 if (*endptr) { 818 p_err("can't parse %s as IDX", *argv); 819 goto err_free_reuse_maps; 820 } 821 name = NULL; 822 } else if (is_prefix(*argv, "name")) { 823 NEXT_ARG(); 824 825 name = *argv; 826 idx = -1; 827 } else { 828 p_err("expected 'idx' or 'name', got: '%s'?", 829 *argv); 830 goto err_free_reuse_maps; 831 } 832 NEXT_ARG(); 833 834 fd = map_parse_fd(&argc, &argv); 835 if (fd < 0) 836 goto err_free_reuse_maps; 837 838 new_map_replace = reallocarray(map_replace, 839 old_map_fds + 1, 840 sizeof(*map_replace)); 841 if (!new_map_replace) { 842 p_err("mem alloc failed"); 843 goto err_free_reuse_maps; 844 } 845 map_replace = new_map_replace; 846 847 map_replace[old_map_fds].idx = idx; 848 map_replace[old_map_fds].name = name; 849 map_replace[old_map_fds].fd = fd; 850 old_map_fds++; 851 } else if (is_prefix(*argv, "dev")) { 852 NEXT_ARG(); 853 854 if (ifindex) { 855 p_err("offload device already specified"); 856 goto err_free_reuse_maps; 857 } 858 if (!REQ_ARGS(1)) 859 goto err_free_reuse_maps; 860 861 ifindex = if_nametoindex(*argv); 862 if (!ifindex) { 863 p_err("unrecognized netdevice '%s': %s", 864 *argv, strerror(errno)); 865 goto err_free_reuse_maps; 866 } 867 NEXT_ARG(); 868 } else if (is_prefix(*argv, "pinmaps")) { 869 NEXT_ARG(); 870 871 if (!REQ_ARGS(1)) 872 goto err_free_reuse_maps; 873 874 pinmaps = GET_ARG(); 875 } else { 876 p_err("expected no more arguments, 'type', 'map' or 'dev', got: '%s'?", 877 *argv); 878 goto err_free_reuse_maps; 879 } 880 } 881 882 set_max_rlimit(); 883 884 obj = __bpf_object__open_xattr(&attr, bpf_flags); 885 if (IS_ERR_OR_NULL(obj)) { 886 p_err("failed to open object file"); 887 goto err_free_reuse_maps; 888 } 889 890 bpf_object__for_each_program(pos, obj) { 891 enum bpf_prog_type prog_type = attr.prog_type; 892 893 if (attr.prog_type == BPF_PROG_TYPE_UNSPEC) { 894 const char *sec_name = bpf_program__title(pos, false); 895 896 err = libbpf_prog_type_by_name(sec_name, &prog_type, 897 &expected_attach_type); 898 if (err < 0) 899 goto err_close_obj; 900 } 901 902 bpf_program__set_ifindex(pos, ifindex); 903 bpf_program__set_type(pos, prog_type); 904 bpf_program__set_expected_attach_type(pos, expected_attach_type); 905 } 906 907 qsort(map_replace, old_map_fds, sizeof(*map_replace), 908 map_replace_compar); 909 910 /* After the sort maps by name will be first on the list, because they 911 * have idx == -1. Resolve them. 912 */ 913 j = 0; 914 while (j < old_map_fds && map_replace[j].name) { 915 i = 0; 916 bpf_object__for_each_map(map, obj) { 917 if (!strcmp(bpf_map__name(map), map_replace[j].name)) { 918 map_replace[j].idx = i; 919 break; 920 } 921 i++; 922 } 923 if (map_replace[j].idx == -1) { 924 p_err("unable to find map '%s'", map_replace[j].name); 925 goto err_close_obj; 926 } 927 j++; 928 } 929 /* Resort if any names were resolved */ 930 if (j) 931 qsort(map_replace, old_map_fds, sizeof(*map_replace), 932 map_replace_compar); 933 934 /* Set ifindex and name reuse */ 935 j = 0; 936 idx = 0; 937 bpf_object__for_each_map(map, obj) { 938 if (!bpf_map__is_offload_neutral(map)) 939 bpf_map__set_ifindex(map, ifindex); 940 941 if (j < old_map_fds && idx == map_replace[j].idx) { 942 err = bpf_map__reuse_fd(map, map_replace[j++].fd); 943 if (err) { 944 p_err("unable to set up map reuse: %d", err); 945 goto err_close_obj; 946 } 947 948 /* Next reuse wants to apply to the same map */ 949 if (j < old_map_fds && map_replace[j].idx == idx) { 950 p_err("replacement for map idx %d specified more than once", 951 idx); 952 goto err_close_obj; 953 } 954 } 955 956 idx++; 957 } 958 if (j < old_map_fds) { 959 p_err("map idx '%d' not used", map_replace[j].idx); 960 goto err_close_obj; 961 } 962 963 err = bpf_object__load(obj); 964 if (err) { 965 p_err("failed to load object file"); 966 goto err_close_obj; 967 } 968 969 err = mount_bpffs_for_pin(pinfile); 970 if (err) 971 goto err_close_obj; 972 973 if (first_prog_only) { 974 prog = bpf_program__next(NULL, obj); 975 if (!prog) { 976 p_err("object file doesn't contain any bpf program"); 977 goto err_close_obj; 978 } 979 980 err = bpf_obj_pin(bpf_program__fd(prog), pinfile); 981 if (err) { 982 p_err("failed to pin program %s", 983 bpf_program__title(prog, false)); 984 goto err_close_obj; 985 } 986 } else { 987 err = bpf_object__pin_programs(obj, pinfile); 988 if (err) { 989 p_err("failed to pin all programs"); 990 goto err_close_obj; 991 } 992 } 993 994 if (pinmaps) { 995 err = bpf_object__pin_maps(obj, pinmaps); 996 if (err) { 997 p_err("failed to pin all maps"); 998 goto err_unpin; 999 } 1000 } 1001 1002 if (json_output) 1003 jsonw_null(json_wtr); 1004 1005 bpf_object__close(obj); 1006 for (i = 0; i < old_map_fds; i++) 1007 close(map_replace[i].fd); 1008 free(map_replace); 1009 1010 return 0; 1011 1012 err_unpin: 1013 if (first_prog_only) 1014 unlink(pinfile); 1015 else 1016 bpf_object__unpin_programs(obj, pinfile); 1017 err_close_obj: 1018 bpf_object__close(obj); 1019 err_free_reuse_maps: 1020 for (i = 0; i < old_map_fds; i++) 1021 close(map_replace[i].fd); 1022 free(map_replace); 1023 return -1; 1024 } 1025 1026 static int do_load(int argc, char **argv) 1027 { 1028 return load_with_options(argc, argv, true); 1029 } 1030 1031 static int do_loadall(int argc, char **argv) 1032 { 1033 return load_with_options(argc, argv, false); 1034 } 1035 1036 static int do_help(int argc, char **argv) 1037 { 1038 if (json_output) { 1039 jsonw_null(json_wtr); 1040 return 0; 1041 } 1042 1043 fprintf(stderr, 1044 "Usage: %s %s { show | list } [PROG]\n" 1045 " %s %s dump xlated PROG [{ file FILE | opcodes | visual | linum }]\n" 1046 " %s %s dump jited PROG [{ file FILE | opcodes | linum }]\n" 1047 " %s %s pin PROG FILE\n" 1048 " %s %s { load | loadall } OBJ PATH \\\n" 1049 " [type TYPE] [dev NAME] \\\n" 1050 " [map { idx IDX | name NAME } MAP]\\\n" 1051 " [pinmaps MAP_DIR]\n" 1052 " %s %s attach PROG ATTACH_TYPE [MAP]\n" 1053 " %s %s detach PROG ATTACH_TYPE [MAP]\n" 1054 " %s %s tracelog\n" 1055 " %s %s help\n" 1056 "\n" 1057 " " HELP_SPEC_MAP "\n" 1058 " " HELP_SPEC_PROGRAM "\n" 1059 " TYPE := { socket | kprobe | kretprobe | classifier | action |\n" 1060 " tracepoint | raw_tracepoint | xdp | perf_event | cgroup/skb |\n" 1061 " cgroup/sock | cgroup/dev | lwt_in | lwt_out | lwt_xmit |\n" 1062 " lwt_seg6local | sockops | sk_skb | sk_msg | lirc_mode2 |\n" 1063 " sk_reuseport | flow_dissector | cgroup/sysctl |\n" 1064 " cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n" 1065 " cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n" 1066 " cgroup/sendmsg4 | cgroup/sendmsg6 | cgroup/recvmsg4 |\n" 1067 " cgroup/recvmsg6 }\n" 1068 " ATTACH_TYPE := { msg_verdict | stream_verdict | stream_parser |\n" 1069 " flow_dissector }\n" 1070 " " HELP_SPEC_OPTIONS "\n" 1071 "", 1072 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1073 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1074 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); 1075 1076 return 0; 1077 } 1078 1079 static const struct cmd cmds[] = { 1080 { "show", do_show }, 1081 { "list", do_show }, 1082 { "help", do_help }, 1083 { "dump", do_dump }, 1084 { "pin", do_pin }, 1085 { "load", do_load }, 1086 { "loadall", do_loadall }, 1087 { "attach", do_attach }, 1088 { "detach", do_detach }, 1089 { "tracelog", do_tracelog }, 1090 { 0 } 1091 }; 1092 1093 int do_prog(int argc, char **argv) 1094 { 1095 return cmd_select(cmds, argc, argv, do_help); 1096 } 1097