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