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