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