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 (!hash_empty(prog_table.table)) { 253 struct pinned_obj *obj; 254 255 jsonw_name(json_wtr, "pinned"); 256 jsonw_start_array(json_wtr); 257 hash_for_each_possible(prog_table.table, obj, hash, info->id) { 258 if (obj->id == info->id) 259 jsonw_string(json_wtr, obj->path); 260 } 261 jsonw_end_array(json_wtr); 262 } 263 264 jsonw_end_object(json_wtr); 265 } 266 267 static void print_prog_plain(struct bpf_prog_info *info, int fd) 268 { 269 char *memlock; 270 271 printf("%u: ", info->id); 272 if (info->type < ARRAY_SIZE(prog_type_name)) 273 printf("%s ", prog_type_name[info->type]); 274 else 275 printf("type %u ", info->type); 276 277 if (*info->name) 278 printf("name %s ", info->name); 279 280 printf("tag "); 281 fprint_hex(stdout, info->tag, BPF_TAG_SIZE, ""); 282 print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino); 283 printf("%s", info->gpl_compatible ? " gpl" : ""); 284 if (info->run_time_ns) 285 printf(" run_time_ns %lld run_cnt %lld", 286 info->run_time_ns, info->run_cnt); 287 printf("\n"); 288 289 if (info->load_time) { 290 char buf[32]; 291 292 print_boot_time(info->load_time, buf, sizeof(buf)); 293 294 /* Piggy back on load_time, since 0 uid is a valid one */ 295 printf("\tloaded_at %s uid %u\n", buf, info->created_by_uid); 296 } 297 298 printf("\txlated %uB", info->xlated_prog_len); 299 300 if (info->jited_prog_len) 301 printf(" jited %uB", info->jited_prog_len); 302 else 303 printf(" not jited"); 304 305 memlock = get_fdinfo(fd, "memlock"); 306 if (memlock) 307 printf(" memlock %sB", memlock); 308 free(memlock); 309 310 if (info->nr_map_ids) 311 show_prog_maps(fd, info->nr_map_ids); 312 313 if (!hash_empty(prog_table.table)) { 314 struct pinned_obj *obj; 315 316 hash_for_each_possible(prog_table.table, obj, hash, info->id) { 317 if (obj->id == info->id) 318 printf("\n\tpinned %s", obj->path); 319 } 320 } 321 322 printf("\n"); 323 } 324 325 static int show_prog(int fd) 326 { 327 struct bpf_prog_info info = {}; 328 __u32 len = sizeof(info); 329 int err; 330 331 err = bpf_obj_get_info_by_fd(fd, &info, &len); 332 if (err) { 333 p_err("can't get prog info: %s", strerror(errno)); 334 return -1; 335 } 336 337 if (json_output) 338 print_prog_json(&info, fd); 339 else 340 print_prog_plain(&info, fd); 341 342 return 0; 343 } 344 345 static int do_show(int argc, char **argv) 346 { 347 __u32 id = 0; 348 int err; 349 int fd; 350 351 if (show_pinned) 352 build_pinned_obj_table(&prog_table, BPF_OBJ_PROG); 353 354 if (argc == 2) { 355 fd = prog_parse_fd(&argc, &argv); 356 if (fd < 0) 357 return -1; 358 359 return show_prog(fd); 360 } 361 362 if (argc) 363 return BAD_ARG(); 364 365 if (json_output) 366 jsonw_start_array(json_wtr); 367 while (true) { 368 err = bpf_prog_get_next_id(id, &id); 369 if (err) { 370 if (errno == ENOENT) { 371 err = 0; 372 break; 373 } 374 p_err("can't get next program: %s%s", strerror(errno), 375 errno == EINVAL ? " -- kernel too old?" : ""); 376 err = -1; 377 break; 378 } 379 380 fd = bpf_prog_get_fd_by_id(id); 381 if (fd < 0) { 382 if (errno == ENOENT) 383 continue; 384 p_err("can't get prog by id (%u): %s", 385 id, strerror(errno)); 386 err = -1; 387 break; 388 } 389 390 err = show_prog(fd); 391 close(fd); 392 if (err) 393 break; 394 } 395 396 if (json_output) 397 jsonw_end_array(json_wtr); 398 399 return err; 400 } 401 402 static int do_dump(int argc, char **argv) 403 { 404 unsigned int finfo_rec_size, linfo_rec_size, jited_linfo_rec_size; 405 void *func_info = NULL, *linfo = NULL, *jited_linfo = NULL; 406 unsigned int nr_finfo, nr_linfo = 0, nr_jited_linfo = 0; 407 struct bpf_prog_linfo *prog_linfo = NULL; 408 unsigned long *func_ksyms = NULL; 409 struct bpf_prog_info info = {}; 410 unsigned int *func_lens = NULL; 411 const char *disasm_opt = NULL; 412 unsigned int nr_func_ksyms; 413 unsigned int nr_func_lens; 414 struct dump_data dd = {}; 415 __u32 len = sizeof(info); 416 struct btf *btf = NULL; 417 unsigned int buf_size; 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 *member_ptr; 426 ssize_t n; 427 int err; 428 int fd; 429 430 if (is_prefix(*argv, "jited")) { 431 if (disasm_init()) 432 return -1; 433 434 member_len = &info.jited_prog_len; 435 member_ptr = &info.jited_prog_insns; 436 } else if (is_prefix(*argv, "xlated")) { 437 member_len = &info.xlated_prog_len; 438 member_ptr = &info.xlated_prog_insns; 439 } else { 440 p_err("expected 'xlated' or 'jited', got: %s", *argv); 441 return -1; 442 } 443 NEXT_ARG(); 444 445 if (argc < 2) 446 usage(); 447 448 fd = prog_parse_fd(&argc, &argv); 449 if (fd < 0) 450 return -1; 451 452 if (is_prefix(*argv, "file")) { 453 NEXT_ARG(); 454 if (!argc) { 455 p_err("expected file path"); 456 return -1; 457 } 458 459 filepath = *argv; 460 NEXT_ARG(); 461 } else if (is_prefix(*argv, "opcodes")) { 462 opcodes = true; 463 NEXT_ARG(); 464 } else if (is_prefix(*argv, "visual")) { 465 visual = true; 466 NEXT_ARG(); 467 } else if (is_prefix(*argv, "linum")) { 468 linum = true; 469 NEXT_ARG(); 470 } 471 472 if (argc) { 473 usage(); 474 return -1; 475 } 476 477 err = bpf_obj_get_info_by_fd(fd, &info, &len); 478 if (err) { 479 p_err("can't get prog info: %s", strerror(errno)); 480 return -1; 481 } 482 483 if (!*member_len) { 484 p_info("no instructions returned"); 485 close(fd); 486 return 0; 487 } 488 489 buf_size = *member_len; 490 491 buf = malloc(buf_size); 492 if (!buf) { 493 p_err("mem alloc failed"); 494 close(fd); 495 return -1; 496 } 497 498 nr_func_ksyms = info.nr_jited_ksyms; 499 if (nr_func_ksyms) { 500 func_ksyms = malloc(nr_func_ksyms * sizeof(__u64)); 501 if (!func_ksyms) { 502 p_err("mem alloc failed"); 503 close(fd); 504 goto err_free; 505 } 506 } 507 508 nr_func_lens = info.nr_jited_func_lens; 509 if (nr_func_lens) { 510 func_lens = malloc(nr_func_lens * sizeof(__u32)); 511 if (!func_lens) { 512 p_err("mem alloc failed"); 513 close(fd); 514 goto err_free; 515 } 516 } 517 518 nr_finfo = info.nr_func_info; 519 finfo_rec_size = info.func_info_rec_size; 520 if (nr_finfo && finfo_rec_size) { 521 func_info = malloc(nr_finfo * finfo_rec_size); 522 if (!func_info) { 523 p_err("mem alloc failed"); 524 close(fd); 525 goto err_free; 526 } 527 } 528 529 linfo_rec_size = info.line_info_rec_size; 530 if (info.nr_line_info && linfo_rec_size && info.btf_id) { 531 nr_linfo = info.nr_line_info; 532 linfo = malloc(nr_linfo * linfo_rec_size); 533 if (!linfo) { 534 p_err("mem alloc failed"); 535 close(fd); 536 goto err_free; 537 } 538 } 539 540 jited_linfo_rec_size = info.jited_line_info_rec_size; 541 if (info.nr_jited_line_info && 542 jited_linfo_rec_size && 543 info.nr_jited_ksyms && 544 info.nr_jited_func_lens && 545 info.btf_id) { 546 nr_jited_linfo = info.nr_jited_line_info; 547 jited_linfo = malloc(nr_jited_linfo * jited_linfo_rec_size); 548 if (!jited_linfo) { 549 p_err("mem alloc failed"); 550 close(fd); 551 goto err_free; 552 } 553 } 554 555 memset(&info, 0, sizeof(info)); 556 557 *member_ptr = ptr_to_u64(buf); 558 *member_len = buf_size; 559 info.jited_ksyms = ptr_to_u64(func_ksyms); 560 info.nr_jited_ksyms = nr_func_ksyms; 561 info.jited_func_lens = ptr_to_u64(func_lens); 562 info.nr_jited_func_lens = nr_func_lens; 563 info.nr_func_info = nr_finfo; 564 info.func_info_rec_size = finfo_rec_size; 565 info.func_info = ptr_to_u64(func_info); 566 info.nr_line_info = nr_linfo; 567 info.line_info_rec_size = linfo_rec_size; 568 info.line_info = ptr_to_u64(linfo); 569 info.nr_jited_line_info = nr_jited_linfo; 570 info.jited_line_info_rec_size = jited_linfo_rec_size; 571 info.jited_line_info = ptr_to_u64(jited_linfo); 572 573 err = bpf_obj_get_info_by_fd(fd, &info, &len); 574 close(fd); 575 if (err) { 576 p_err("can't get prog info: %s", strerror(errno)); 577 goto err_free; 578 } 579 580 if (*member_len > buf_size) { 581 p_err("too many instructions returned"); 582 goto err_free; 583 } 584 585 if (info.nr_jited_ksyms > nr_func_ksyms) { 586 p_err("too many addresses returned"); 587 goto err_free; 588 } 589 590 if (info.nr_jited_func_lens > nr_func_lens) { 591 p_err("too many values returned"); 592 goto err_free; 593 } 594 595 if (info.nr_func_info != nr_finfo) { 596 p_err("incorrect nr_func_info %d vs. expected %d", 597 info.nr_func_info, nr_finfo); 598 goto err_free; 599 } 600 601 if (info.func_info_rec_size != finfo_rec_size) { 602 p_err("incorrect func_info_rec_size %d vs. expected %d", 603 info.func_info_rec_size, finfo_rec_size); 604 goto err_free; 605 } 606 607 if (linfo && info.nr_line_info != nr_linfo) { 608 p_err("incorrect nr_line_info %u vs. expected %u", 609 info.nr_line_info, nr_linfo); 610 goto err_free; 611 } 612 613 if (info.line_info_rec_size != linfo_rec_size) { 614 p_err("incorrect line_info_rec_size %u vs. expected %u", 615 info.line_info_rec_size, linfo_rec_size); 616 goto err_free; 617 } 618 619 if (jited_linfo && info.nr_jited_line_info != nr_jited_linfo) { 620 p_err("incorrect nr_jited_line_info %u vs. expected %u", 621 info.nr_jited_line_info, nr_jited_linfo); 622 goto err_free; 623 } 624 625 if (info.jited_line_info_rec_size != jited_linfo_rec_size) { 626 p_err("incorrect jited_line_info_rec_size %u vs. expected %u", 627 info.jited_line_info_rec_size, jited_linfo_rec_size); 628 goto err_free; 629 } 630 631 if ((member_len == &info.jited_prog_len && 632 info.jited_prog_insns == 0) || 633 (member_len == &info.xlated_prog_len && 634 info.xlated_prog_insns == 0)) { 635 p_err("error retrieving insn dump: kernel.kptr_restrict set?"); 636 goto err_free; 637 } 638 639 if (info.btf_id && btf__get_from_id(info.btf_id, &btf)) { 640 p_err("failed to get btf"); 641 goto err_free; 642 } 643 644 if (nr_linfo) { 645 prog_linfo = bpf_prog_linfo__new(&info); 646 if (!prog_linfo) 647 p_info("error in processing bpf_line_info. continue without it."); 648 } 649 650 if (filepath) { 651 fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600); 652 if (fd < 0) { 653 p_err("can't open file %s: %s", filepath, 654 strerror(errno)); 655 goto err_free; 656 } 657 658 n = write(fd, buf, *member_len); 659 close(fd); 660 if (n != *member_len) { 661 p_err("error writing output file: %s", 662 n < 0 ? strerror(errno) : "short write"); 663 goto err_free; 664 } 665 666 if (json_output) 667 jsonw_null(json_wtr); 668 } else if (member_len == &info.jited_prog_len) { 669 const char *name = NULL; 670 671 if (info.ifindex) { 672 name = ifindex_to_bfd_params(info.ifindex, 673 info.netns_dev, 674 info.netns_ino, 675 &disasm_opt); 676 if (!name) 677 goto err_free; 678 } 679 680 if (info.nr_jited_func_lens && info.jited_func_lens) { 681 struct kernel_sym *sym = NULL; 682 struct bpf_func_info *record; 683 char sym_name[SYM_MAX_NAME]; 684 unsigned char *img = buf; 685 __u64 *ksyms = NULL; 686 __u32 *lens; 687 __u32 i; 688 689 if (info.nr_jited_ksyms) { 690 kernel_syms_load(&dd); 691 ksyms = (__u64 *) info.jited_ksyms; 692 } 693 694 if (json_output) 695 jsonw_start_array(json_wtr); 696 697 lens = (__u32 *) info.jited_func_lens; 698 for (i = 0; i < info.nr_jited_func_lens; i++) { 699 if (ksyms) { 700 sym = kernel_syms_search(&dd, ksyms[i]); 701 if (sym) 702 sprintf(sym_name, "%s", sym->name); 703 else 704 sprintf(sym_name, "0x%016llx", ksyms[i]); 705 } else { 706 strcpy(sym_name, "unknown"); 707 } 708 709 if (func_info) { 710 record = func_info + i * finfo_rec_size; 711 btf_dumper_type_only(btf, record->type_id, 712 func_sig, 713 sizeof(func_sig)); 714 } 715 716 if (json_output) { 717 jsonw_start_object(json_wtr); 718 if (func_info && func_sig[0] != '\0') { 719 jsonw_name(json_wtr, "proto"); 720 jsonw_string(json_wtr, func_sig); 721 } 722 jsonw_name(json_wtr, "name"); 723 jsonw_string(json_wtr, sym_name); 724 jsonw_name(json_wtr, "insns"); 725 } else { 726 if (func_info && func_sig[0] != '\0') 727 printf("%s:\n", func_sig); 728 printf("%s:\n", sym_name); 729 } 730 731 disasm_print_insn(img, lens[i], opcodes, 732 name, disasm_opt, btf, 733 prog_linfo, ksyms[i], i, 734 linum); 735 736 img += lens[i]; 737 738 if (json_output) 739 jsonw_end_object(json_wtr); 740 else 741 printf("\n"); 742 } 743 744 if (json_output) 745 jsonw_end_array(json_wtr); 746 } else { 747 disasm_print_insn(buf, *member_len, opcodes, name, 748 disasm_opt, btf, NULL, 0, 0, false); 749 } 750 } else if (visual) { 751 if (json_output) 752 jsonw_null(json_wtr); 753 else 754 dump_xlated_cfg(buf, *member_len); 755 } else { 756 kernel_syms_load(&dd); 757 dd.nr_jited_ksyms = info.nr_jited_ksyms; 758 dd.jited_ksyms = (__u64 *) info.jited_ksyms; 759 dd.btf = btf; 760 dd.func_info = func_info; 761 dd.finfo_rec_size = finfo_rec_size; 762 dd.prog_linfo = prog_linfo; 763 764 if (json_output) 765 dump_xlated_json(&dd, buf, *member_len, opcodes, 766 linum); 767 else 768 dump_xlated_plain(&dd, buf, *member_len, opcodes, 769 linum); 770 kernel_syms_destroy(&dd); 771 } 772 773 free(buf); 774 free(func_ksyms); 775 free(func_lens); 776 free(func_info); 777 free(linfo); 778 free(jited_linfo); 779 bpf_prog_linfo__free(prog_linfo); 780 return 0; 781 782 err_free: 783 free(buf); 784 free(func_ksyms); 785 free(func_lens); 786 free(func_info); 787 free(linfo); 788 free(jited_linfo); 789 bpf_prog_linfo__free(prog_linfo); 790 return -1; 791 } 792 793 static int do_pin(int argc, char **argv) 794 { 795 int err; 796 797 err = do_pin_any(argc, argv, bpf_prog_get_fd_by_id); 798 if (!err && json_output) 799 jsonw_null(json_wtr); 800 return err; 801 } 802 803 struct map_replace { 804 int idx; 805 int fd; 806 char *name; 807 }; 808 809 static int map_replace_compar(const void *p1, const void *p2) 810 { 811 const struct map_replace *a = p1, *b = p2; 812 813 return a->idx - b->idx; 814 } 815 816 static int parse_attach_detach_args(int argc, char **argv, int *progfd, 817 enum bpf_attach_type *attach_type, 818 int *mapfd) 819 { 820 if (!REQ_ARGS(3)) 821 return -EINVAL; 822 823 *progfd = prog_parse_fd(&argc, &argv); 824 if (*progfd < 0) 825 return *progfd; 826 827 *attach_type = parse_attach_type(*argv); 828 if (*attach_type == __MAX_BPF_ATTACH_TYPE) { 829 p_err("invalid attach/detach type"); 830 return -EINVAL; 831 } 832 833 if (*attach_type == BPF_FLOW_DISSECTOR) { 834 *mapfd = -1; 835 return 0; 836 } 837 838 NEXT_ARG(); 839 if (!REQ_ARGS(2)) 840 return -EINVAL; 841 842 *mapfd = map_parse_fd(&argc, &argv); 843 if (*mapfd < 0) 844 return *mapfd; 845 846 return 0; 847 } 848 849 static int do_attach(int argc, char **argv) 850 { 851 enum bpf_attach_type attach_type; 852 int err, progfd; 853 int mapfd; 854 855 err = parse_attach_detach_args(argc, argv, 856 &progfd, &attach_type, &mapfd); 857 if (err) 858 return err; 859 860 err = bpf_prog_attach(progfd, mapfd, attach_type, 0); 861 if (err) { 862 p_err("failed prog attach to map"); 863 return -EINVAL; 864 } 865 866 if (json_output) 867 jsonw_null(json_wtr); 868 return 0; 869 } 870 871 static int do_detach(int argc, char **argv) 872 { 873 enum bpf_attach_type attach_type; 874 int err, progfd; 875 int mapfd; 876 877 err = parse_attach_detach_args(argc, argv, 878 &progfd, &attach_type, &mapfd); 879 if (err) 880 return err; 881 882 err = bpf_prog_detach2(progfd, mapfd, attach_type); 883 if (err) { 884 p_err("failed prog detach from map"); 885 return -EINVAL; 886 } 887 888 if (json_output) 889 jsonw_null(json_wtr); 890 return 0; 891 } 892 893 static int load_with_options(int argc, char **argv, bool first_prog_only) 894 { 895 enum bpf_attach_type expected_attach_type; 896 struct bpf_object_open_attr attr = { 897 .prog_type = BPF_PROG_TYPE_UNSPEC, 898 }; 899 struct map_replace *map_replace = NULL; 900 struct bpf_program *prog = NULL, *pos; 901 unsigned int old_map_fds = 0; 902 const char *pinmaps = NULL; 903 struct bpf_object *obj; 904 struct bpf_map *map; 905 const char *pinfile; 906 unsigned int i, j; 907 __u32 ifindex = 0; 908 int idx, err; 909 910 if (!REQ_ARGS(2)) 911 return -1; 912 attr.file = GET_ARG(); 913 pinfile = GET_ARG(); 914 915 while (argc) { 916 if (is_prefix(*argv, "type")) { 917 char *type; 918 919 NEXT_ARG(); 920 921 if (attr.prog_type != BPF_PROG_TYPE_UNSPEC) { 922 p_err("program type already specified"); 923 goto err_free_reuse_maps; 924 } 925 if (!REQ_ARGS(1)) 926 goto err_free_reuse_maps; 927 928 /* Put a '/' at the end of type to appease libbpf */ 929 type = malloc(strlen(*argv) + 2); 930 if (!type) { 931 p_err("mem alloc failed"); 932 goto err_free_reuse_maps; 933 } 934 *type = 0; 935 strcat(type, *argv); 936 strcat(type, "/"); 937 938 err = libbpf_prog_type_by_name(type, &attr.prog_type, 939 &expected_attach_type); 940 free(type); 941 if (err < 0) 942 goto err_free_reuse_maps; 943 944 NEXT_ARG(); 945 } else if (is_prefix(*argv, "map")) { 946 void *new_map_replace; 947 char *endptr, *name; 948 int fd; 949 950 NEXT_ARG(); 951 952 if (!REQ_ARGS(4)) 953 goto err_free_reuse_maps; 954 955 if (is_prefix(*argv, "idx")) { 956 NEXT_ARG(); 957 958 idx = strtoul(*argv, &endptr, 0); 959 if (*endptr) { 960 p_err("can't parse %s as IDX", *argv); 961 goto err_free_reuse_maps; 962 } 963 name = NULL; 964 } else if (is_prefix(*argv, "name")) { 965 NEXT_ARG(); 966 967 name = *argv; 968 idx = -1; 969 } else { 970 p_err("expected 'idx' or 'name', got: '%s'?", 971 *argv); 972 goto err_free_reuse_maps; 973 } 974 NEXT_ARG(); 975 976 fd = map_parse_fd(&argc, &argv); 977 if (fd < 0) 978 goto err_free_reuse_maps; 979 980 new_map_replace = reallocarray(map_replace, 981 old_map_fds + 1, 982 sizeof(*map_replace)); 983 if (!new_map_replace) { 984 p_err("mem alloc failed"); 985 goto err_free_reuse_maps; 986 } 987 map_replace = new_map_replace; 988 989 map_replace[old_map_fds].idx = idx; 990 map_replace[old_map_fds].name = name; 991 map_replace[old_map_fds].fd = fd; 992 old_map_fds++; 993 } else if (is_prefix(*argv, "dev")) { 994 NEXT_ARG(); 995 996 if (ifindex) { 997 p_err("offload device already specified"); 998 goto err_free_reuse_maps; 999 } 1000 if (!REQ_ARGS(1)) 1001 goto err_free_reuse_maps; 1002 1003 ifindex = if_nametoindex(*argv); 1004 if (!ifindex) { 1005 p_err("unrecognized netdevice '%s': %s", 1006 *argv, strerror(errno)); 1007 goto err_free_reuse_maps; 1008 } 1009 NEXT_ARG(); 1010 } else if (is_prefix(*argv, "pinmaps")) { 1011 NEXT_ARG(); 1012 1013 if (!REQ_ARGS(1)) 1014 goto err_free_reuse_maps; 1015 1016 pinmaps = GET_ARG(); 1017 } else { 1018 p_err("expected no more arguments, 'type', 'map' or 'dev', got: '%s'?", 1019 *argv); 1020 goto err_free_reuse_maps; 1021 } 1022 } 1023 1024 obj = __bpf_object__open_xattr(&attr, bpf_flags); 1025 if (IS_ERR_OR_NULL(obj)) { 1026 p_err("failed to open object file"); 1027 goto err_free_reuse_maps; 1028 } 1029 1030 bpf_object__for_each_program(pos, obj) { 1031 enum bpf_prog_type prog_type = attr.prog_type; 1032 1033 if (attr.prog_type == BPF_PROG_TYPE_UNSPEC) { 1034 const char *sec_name = bpf_program__title(pos, false); 1035 1036 err = libbpf_prog_type_by_name(sec_name, &prog_type, 1037 &expected_attach_type); 1038 if (err < 0) 1039 goto err_close_obj; 1040 } 1041 1042 bpf_program__set_ifindex(pos, ifindex); 1043 bpf_program__set_type(pos, prog_type); 1044 bpf_program__set_expected_attach_type(pos, expected_attach_type); 1045 } 1046 1047 qsort(map_replace, old_map_fds, sizeof(*map_replace), 1048 map_replace_compar); 1049 1050 /* After the sort maps by name will be first on the list, because they 1051 * have idx == -1. Resolve them. 1052 */ 1053 j = 0; 1054 while (j < old_map_fds && map_replace[j].name) { 1055 i = 0; 1056 bpf_object__for_each_map(map, obj) { 1057 if (!strcmp(bpf_map__name(map), map_replace[j].name)) { 1058 map_replace[j].idx = i; 1059 break; 1060 } 1061 i++; 1062 } 1063 if (map_replace[j].idx == -1) { 1064 p_err("unable to find map '%s'", map_replace[j].name); 1065 goto err_close_obj; 1066 } 1067 j++; 1068 } 1069 /* Resort if any names were resolved */ 1070 if (j) 1071 qsort(map_replace, old_map_fds, sizeof(*map_replace), 1072 map_replace_compar); 1073 1074 /* Set ifindex and name reuse */ 1075 j = 0; 1076 idx = 0; 1077 bpf_object__for_each_map(map, obj) { 1078 if (!bpf_map__is_offload_neutral(map)) 1079 bpf_map__set_ifindex(map, ifindex); 1080 1081 if (j < old_map_fds && idx == map_replace[j].idx) { 1082 err = bpf_map__reuse_fd(map, map_replace[j++].fd); 1083 if (err) { 1084 p_err("unable to set up map reuse: %d", err); 1085 goto err_close_obj; 1086 } 1087 1088 /* Next reuse wants to apply to the same map */ 1089 if (j < old_map_fds && map_replace[j].idx == idx) { 1090 p_err("replacement for map idx %d specified more than once", 1091 idx); 1092 goto err_close_obj; 1093 } 1094 } 1095 1096 idx++; 1097 } 1098 if (j < old_map_fds) { 1099 p_err("map idx '%d' not used", map_replace[j].idx); 1100 goto err_close_obj; 1101 } 1102 1103 set_max_rlimit(); 1104 1105 err = bpf_object__load(obj); 1106 if (err) { 1107 p_err("failed to load object file"); 1108 goto err_close_obj; 1109 } 1110 1111 err = mount_bpffs_for_pin(pinfile); 1112 if (err) 1113 goto err_close_obj; 1114 1115 if (first_prog_only) { 1116 prog = bpf_program__next(NULL, obj); 1117 if (!prog) { 1118 p_err("object file doesn't contain any bpf program"); 1119 goto err_close_obj; 1120 } 1121 1122 err = bpf_obj_pin(bpf_program__fd(prog), pinfile); 1123 if (err) { 1124 p_err("failed to pin program %s", 1125 bpf_program__title(prog, false)); 1126 goto err_close_obj; 1127 } 1128 } else { 1129 err = bpf_object__pin_programs(obj, pinfile); 1130 if (err) { 1131 p_err("failed to pin all programs"); 1132 goto err_close_obj; 1133 } 1134 } 1135 1136 if (pinmaps) { 1137 err = bpf_object__pin_maps(obj, pinmaps); 1138 if (err) { 1139 p_err("failed to pin all maps"); 1140 goto err_unpin; 1141 } 1142 } 1143 1144 if (json_output) 1145 jsonw_null(json_wtr); 1146 1147 bpf_object__close(obj); 1148 for (i = 0; i < old_map_fds; i++) 1149 close(map_replace[i].fd); 1150 free(map_replace); 1151 1152 return 0; 1153 1154 err_unpin: 1155 if (first_prog_only) 1156 unlink(pinfile); 1157 else 1158 bpf_object__unpin_programs(obj, pinfile); 1159 err_close_obj: 1160 bpf_object__close(obj); 1161 err_free_reuse_maps: 1162 for (i = 0; i < old_map_fds; i++) 1163 close(map_replace[i].fd); 1164 free(map_replace); 1165 return -1; 1166 } 1167 1168 static int do_load(int argc, char **argv) 1169 { 1170 return load_with_options(argc, argv, true); 1171 } 1172 1173 static int do_loadall(int argc, char **argv) 1174 { 1175 return load_with_options(argc, argv, false); 1176 } 1177 1178 static int do_help(int argc, char **argv) 1179 { 1180 if (json_output) { 1181 jsonw_null(json_wtr); 1182 return 0; 1183 } 1184 1185 fprintf(stderr, 1186 "Usage: %s %s { show | list } [PROG]\n" 1187 " %s %s dump xlated PROG [{ file FILE | opcodes | visual | linum }]\n" 1188 " %s %s dump jited PROG [{ file FILE | opcodes | linum }]\n" 1189 " %s %s pin PROG FILE\n" 1190 " %s %s { load | loadall } OBJ PATH \\\n" 1191 " [type TYPE] [dev NAME] \\\n" 1192 " [map { idx IDX | name NAME } MAP]\\\n" 1193 " [pinmaps MAP_DIR]\n" 1194 " %s %s attach PROG ATTACH_TYPE [MAP]\n" 1195 " %s %s detach PROG ATTACH_TYPE [MAP]\n" 1196 " %s %s tracelog\n" 1197 " %s %s help\n" 1198 "\n" 1199 " " HELP_SPEC_MAP "\n" 1200 " " HELP_SPEC_PROGRAM "\n" 1201 " TYPE := { socket | kprobe | kretprobe | classifier | action |\n" 1202 " tracepoint | raw_tracepoint | xdp | perf_event | cgroup/skb |\n" 1203 " cgroup/sock | cgroup/dev | lwt_in | lwt_out | lwt_xmit |\n" 1204 " lwt_seg6local | sockops | sk_skb | sk_msg | lirc_mode2 |\n" 1205 " sk_reuseport | flow_dissector |\n" 1206 " cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n" 1207 " cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n" 1208 " cgroup/sendmsg4 | cgroup/sendmsg6 }\n" 1209 " ATTACH_TYPE := { msg_verdict | stream_verdict | stream_parser |\n" 1210 " flow_dissector }\n" 1211 " " HELP_SPEC_OPTIONS "\n" 1212 "", 1213 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1214 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1215 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); 1216 1217 return 0; 1218 } 1219 1220 static const struct cmd cmds[] = { 1221 { "show", do_show }, 1222 { "list", do_show }, 1223 { "help", do_help }, 1224 { "dump", do_dump }, 1225 { "pin", do_pin }, 1226 { "load", do_load }, 1227 { "loadall", do_loadall }, 1228 { "attach", do_attach }, 1229 { "detach", do_detach }, 1230 { "tracelog", do_tracelog }, 1231 { 0 } 1232 }; 1233 1234 int do_prog(int argc, char **argv) 1235 { 1236 return cmd_select(cmds, argc, argv, do_help); 1237 } 1238