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