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