1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 /* Copyright (c) 2019 Netronome Systems, Inc. */ 3 4 #include <ctype.h> 5 #include <errno.h> 6 #include <fcntl.h> 7 #include <string.h> 8 #include <unistd.h> 9 #include <net/if.h> 10 #ifdef USE_LIBCAP 11 #include <sys/capability.h> 12 #endif 13 #include <sys/vfs.h> 14 15 #include <linux/filter.h> 16 #include <linux/limits.h> 17 18 #include <bpf/bpf.h> 19 #include <bpf/libbpf.h> 20 21 #include "main.h" 22 23 #ifndef PROC_SUPER_MAGIC 24 # define PROC_SUPER_MAGIC 0x9fa0 25 #endif 26 27 enum probe_component { 28 COMPONENT_UNSPEC, 29 COMPONENT_KERNEL, 30 COMPONENT_DEVICE, 31 }; 32 33 #define BPF_HELPER_MAKE_ENTRY(name) [BPF_FUNC_ ## name] = "bpf_" # name 34 static const char * const helper_name[] = { 35 __BPF_FUNC_MAPPER(BPF_HELPER_MAKE_ENTRY) 36 }; 37 38 #undef BPF_HELPER_MAKE_ENTRY 39 40 static bool full_mode; 41 #ifdef USE_LIBCAP 42 static bool run_as_unprivileged; 43 #endif 44 45 /* Miscellaneous utility functions */ 46 47 static bool grep(const char *buffer, const char *pattern) 48 { 49 return !!strstr(buffer, pattern); 50 } 51 52 static bool check_procfs(void) 53 { 54 struct statfs st_fs; 55 56 if (statfs("/proc", &st_fs) < 0) 57 return false; 58 if ((unsigned long)st_fs.f_type != PROC_SUPER_MAGIC) 59 return false; 60 61 return true; 62 } 63 64 static void uppercase(char *str, size_t len) 65 { 66 size_t i; 67 68 for (i = 0; i < len && str[i] != '\0'; i++) 69 str[i] = toupper(str[i]); 70 } 71 72 /* Printing utility functions */ 73 74 static void 75 print_bool_feature(const char *feat_name, const char *plain_name, 76 const char *define_name, bool res, const char *define_prefix) 77 { 78 if (json_output) 79 jsonw_bool_field(json_wtr, feat_name, res); 80 else if (define_prefix) 81 printf("#define %s%sHAVE_%s\n", define_prefix, 82 res ? "" : "NO_", define_name); 83 else 84 printf("%s is %savailable\n", plain_name, res ? "" : "NOT "); 85 } 86 87 static void print_kernel_option(const char *name, const char *value, 88 const char *define_prefix) 89 { 90 char *endptr; 91 int res; 92 93 if (json_output) { 94 if (!value) { 95 jsonw_null_field(json_wtr, name); 96 return; 97 } 98 errno = 0; 99 res = strtol(value, &endptr, 0); 100 if (!errno && *endptr == '\n') 101 jsonw_int_field(json_wtr, name, res); 102 else 103 jsonw_string_field(json_wtr, name, value); 104 } else if (define_prefix) { 105 if (value) 106 printf("#define %s%s %s\n", define_prefix, 107 name, value); 108 else 109 printf("/* %s%s is not set */\n", define_prefix, name); 110 } else { 111 if (value) 112 printf("%s is set to %s\n", name, value); 113 else 114 printf("%s is not set\n", name); 115 } 116 } 117 118 static void 119 print_start_section(const char *json_title, const char *plain_title, 120 const char *define_comment, const char *define_prefix) 121 { 122 if (json_output) { 123 jsonw_name(json_wtr, json_title); 124 jsonw_start_object(json_wtr); 125 } else if (define_prefix) { 126 printf("%s\n", define_comment); 127 } else { 128 printf("%s\n", plain_title); 129 } 130 } 131 132 static void print_end_section(void) 133 { 134 if (json_output) 135 jsonw_end_object(json_wtr); 136 else 137 printf("\n"); 138 } 139 140 /* Probing functions */ 141 142 static int get_vendor_id(int ifindex) 143 { 144 char ifname[IF_NAMESIZE], path[64], buf[8]; 145 ssize_t len; 146 int fd; 147 148 if (!if_indextoname(ifindex, ifname)) 149 return -1; 150 151 snprintf(path, sizeof(path), "/sys/class/net/%s/device/vendor", ifname); 152 153 fd = open(path, O_RDONLY | O_CLOEXEC); 154 if (fd < 0) 155 return -1; 156 157 len = read(fd, buf, sizeof(buf)); 158 close(fd); 159 if (len < 0) 160 return -1; 161 if (len >= (ssize_t)sizeof(buf)) 162 return -1; 163 buf[len] = '\0'; 164 165 return strtol(buf, NULL, 0); 166 } 167 168 static long read_procfs(const char *path) 169 { 170 char *endptr, *line = NULL; 171 size_t len = 0; 172 FILE *fd; 173 long res; 174 175 fd = fopen(path, "r"); 176 if (!fd) 177 return -1; 178 179 res = getline(&line, &len, fd); 180 fclose(fd); 181 if (res < 0) 182 return -1; 183 184 errno = 0; 185 res = strtol(line, &endptr, 10); 186 if (errno || *line == '\0' || *endptr != '\n') 187 res = -1; 188 free(line); 189 190 return res; 191 } 192 193 static void probe_unprivileged_disabled(void) 194 { 195 long res; 196 197 /* No support for C-style output */ 198 199 res = read_procfs("/proc/sys/kernel/unprivileged_bpf_disabled"); 200 if (json_output) { 201 jsonw_int_field(json_wtr, "unprivileged_bpf_disabled", res); 202 } else { 203 switch (res) { 204 case 0: 205 printf("bpf() syscall for unprivileged users is enabled\n"); 206 break; 207 case 1: 208 printf("bpf() syscall restricted to privileged users (without recovery)\n"); 209 break; 210 case 2: 211 printf("bpf() syscall restricted to privileged users (admin can change)\n"); 212 break; 213 case -1: 214 printf("Unable to retrieve required privileges for bpf() syscall\n"); 215 break; 216 default: 217 printf("bpf() syscall restriction has unknown value %ld\n", res); 218 } 219 } 220 } 221 222 static void probe_jit_enable(void) 223 { 224 long res; 225 226 /* No support for C-style output */ 227 228 res = read_procfs("/proc/sys/net/core/bpf_jit_enable"); 229 if (json_output) { 230 jsonw_int_field(json_wtr, "bpf_jit_enable", res); 231 } else { 232 switch (res) { 233 case 0: 234 printf("JIT compiler is disabled\n"); 235 break; 236 case 1: 237 printf("JIT compiler is enabled\n"); 238 break; 239 case 2: 240 printf("JIT compiler is enabled with debugging traces in kernel logs\n"); 241 break; 242 case -1: 243 printf("Unable to retrieve JIT-compiler status\n"); 244 break; 245 default: 246 printf("JIT-compiler status has unknown value %ld\n", 247 res); 248 } 249 } 250 } 251 252 static void probe_jit_harden(void) 253 { 254 long res; 255 256 /* No support for C-style output */ 257 258 res = read_procfs("/proc/sys/net/core/bpf_jit_harden"); 259 if (json_output) { 260 jsonw_int_field(json_wtr, "bpf_jit_harden", res); 261 } else { 262 switch (res) { 263 case 0: 264 printf("JIT compiler hardening is disabled\n"); 265 break; 266 case 1: 267 printf("JIT compiler hardening is enabled for unprivileged users\n"); 268 break; 269 case 2: 270 printf("JIT compiler hardening is enabled for all users\n"); 271 break; 272 case -1: 273 printf("Unable to retrieve JIT hardening status\n"); 274 break; 275 default: 276 printf("JIT hardening status has unknown value %ld\n", 277 res); 278 } 279 } 280 } 281 282 static void probe_jit_kallsyms(void) 283 { 284 long res; 285 286 /* No support for C-style output */ 287 288 res = read_procfs("/proc/sys/net/core/bpf_jit_kallsyms"); 289 if (json_output) { 290 jsonw_int_field(json_wtr, "bpf_jit_kallsyms", res); 291 } else { 292 switch (res) { 293 case 0: 294 printf("JIT compiler kallsyms exports are disabled\n"); 295 break; 296 case 1: 297 printf("JIT compiler kallsyms exports are enabled for root\n"); 298 break; 299 case -1: 300 printf("Unable to retrieve JIT kallsyms export status\n"); 301 break; 302 default: 303 printf("JIT kallsyms exports status has unknown value %ld\n", res); 304 } 305 } 306 } 307 308 static void probe_jit_limit(void) 309 { 310 long res; 311 312 /* No support for C-style output */ 313 314 res = read_procfs("/proc/sys/net/core/bpf_jit_limit"); 315 if (json_output) { 316 jsonw_int_field(json_wtr, "bpf_jit_limit", res); 317 } else { 318 switch (res) { 319 case -1: 320 printf("Unable to retrieve global memory limit for JIT compiler for unprivileged users\n"); 321 break; 322 default: 323 printf("Global memory limit for JIT compiler for unprivileged users is %ld bytes\n", res); 324 } 325 } 326 } 327 328 static void probe_kernel_image_config(const char *define_prefix) 329 { 330 struct kernel_config_option options[] = { 331 /* Enable BPF */ 332 { "CONFIG_BPF", }, 333 /* Enable bpf() syscall */ 334 { "CONFIG_BPF_SYSCALL", }, 335 /* Does selected architecture support eBPF JIT compiler */ 336 { "CONFIG_HAVE_EBPF_JIT", }, 337 /* Compile eBPF JIT compiler */ 338 { "CONFIG_BPF_JIT", }, 339 /* Avoid compiling eBPF interpreter (use JIT only) */ 340 { "CONFIG_BPF_JIT_ALWAYS_ON", }, 341 /* Kernel BTF debug information available */ 342 { "CONFIG_DEBUG_INFO_BTF", }, 343 /* Kernel module BTF debug information available */ 344 { "CONFIG_DEBUG_INFO_BTF_MODULES", }, 345 346 /* cgroups */ 347 { "CONFIG_CGROUPS", }, 348 /* BPF programs attached to cgroups */ 349 { "CONFIG_CGROUP_BPF", }, 350 /* bpf_get_cgroup_classid() helper */ 351 { "CONFIG_CGROUP_NET_CLASSID", }, 352 /* bpf_skb_{,ancestor_}cgroup_id() helpers */ 353 { "CONFIG_SOCK_CGROUP_DATA", }, 354 355 /* Tracing: attach BPF to kprobes, tracepoints, etc. */ 356 { "CONFIG_BPF_EVENTS", }, 357 /* Kprobes */ 358 { "CONFIG_KPROBE_EVENTS", }, 359 /* Uprobes */ 360 { "CONFIG_UPROBE_EVENTS", }, 361 /* Tracepoints */ 362 { "CONFIG_TRACING", }, 363 /* Syscall tracepoints */ 364 { "CONFIG_FTRACE_SYSCALLS", }, 365 /* bpf_override_return() helper support for selected arch */ 366 { "CONFIG_FUNCTION_ERROR_INJECTION", }, 367 /* bpf_override_return() helper */ 368 { "CONFIG_BPF_KPROBE_OVERRIDE", }, 369 370 /* Network */ 371 { "CONFIG_NET", }, 372 /* AF_XDP sockets */ 373 { "CONFIG_XDP_SOCKETS", }, 374 /* BPF_PROG_TYPE_LWT_* and related helpers */ 375 { "CONFIG_LWTUNNEL_BPF", }, 376 /* BPF_PROG_TYPE_SCHED_ACT, TC (traffic control) actions */ 377 { "CONFIG_NET_ACT_BPF", }, 378 /* BPF_PROG_TYPE_SCHED_CLS, TC filters */ 379 { "CONFIG_NET_CLS_BPF", }, 380 /* TC clsact qdisc */ 381 { "CONFIG_NET_CLS_ACT", }, 382 /* Ingress filtering with TC */ 383 { "CONFIG_NET_SCH_INGRESS", }, 384 /* bpf_skb_get_xfrm_state() helper */ 385 { "CONFIG_XFRM", }, 386 /* bpf_get_route_realm() helper */ 387 { "CONFIG_IP_ROUTE_CLASSID", }, 388 /* BPF_PROG_TYPE_LWT_SEG6_LOCAL and related helpers */ 389 { "CONFIG_IPV6_SEG6_BPF", }, 390 /* BPF_PROG_TYPE_LIRC_MODE2 and related helpers */ 391 { "CONFIG_BPF_LIRC_MODE2", }, 392 /* BPF stream parser and BPF socket maps */ 393 { "CONFIG_BPF_STREAM_PARSER", }, 394 /* xt_bpf module for passing BPF programs to netfilter */ 395 { "CONFIG_NETFILTER_XT_MATCH_BPF", }, 396 397 /* test_bpf module for BPF tests */ 398 { "CONFIG_TEST_BPF", }, 399 400 /* Misc configs useful in BPF C programs */ 401 /* jiffies <-> sec conversion for bpf_jiffies64() helper */ 402 { "CONFIG_HZ", true, } 403 }; 404 char *values[ARRAY_SIZE(options)] = { }; 405 size_t i; 406 407 if (read_kernel_config(options, ARRAY_SIZE(options), values, 408 define_prefix)) 409 return; 410 411 for (i = 0; i < ARRAY_SIZE(options); i++) { 412 if (define_prefix && !options[i].macro_dump) 413 continue; 414 print_kernel_option(options[i].name, values[i], define_prefix); 415 free(values[i]); 416 } 417 } 418 419 static bool probe_bpf_syscall(const char *define_prefix) 420 { 421 bool res; 422 423 bpf_prog_load(BPF_PROG_TYPE_UNSPEC, NULL, NULL, NULL, 0, NULL); 424 res = (errno != ENOSYS); 425 426 print_bool_feature("have_bpf_syscall", 427 "bpf() syscall", 428 "BPF_SYSCALL", 429 res, define_prefix); 430 431 return res; 432 } 433 434 static bool 435 probe_prog_load_ifindex(enum bpf_prog_type prog_type, 436 const struct bpf_insn *insns, size_t insns_cnt, 437 char *log_buf, size_t log_buf_sz, 438 __u32 ifindex) 439 { 440 LIBBPF_OPTS(bpf_prog_load_opts, opts, 441 .log_buf = log_buf, 442 .log_size = log_buf_sz, 443 .log_level = log_buf ? 1 : 0, 444 .prog_ifindex = ifindex, 445 ); 446 int fd; 447 448 errno = 0; 449 fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insns_cnt, &opts); 450 if (fd >= 0) 451 close(fd); 452 453 return fd >= 0 && errno != EINVAL && errno != EOPNOTSUPP; 454 } 455 456 static bool probe_prog_type_ifindex(enum bpf_prog_type prog_type, __u32 ifindex) 457 { 458 /* nfp returns -EINVAL on exit(0) with TC offload */ 459 struct bpf_insn insns[2] = { 460 BPF_MOV64_IMM(BPF_REG_0, 2), 461 BPF_EXIT_INSN() 462 }; 463 464 return probe_prog_load_ifindex(prog_type, insns, ARRAY_SIZE(insns), 465 NULL, 0, ifindex); 466 } 467 468 static void 469 probe_prog_type(enum bpf_prog_type prog_type, const char *prog_type_str, 470 bool *supported_types, const char *define_prefix, __u32 ifindex) 471 { 472 char feat_name[128], plain_desc[128], define_name[128]; 473 const char *plain_comment = "eBPF program_type "; 474 size_t maxlen; 475 bool res; 476 477 if (ifindex) { 478 switch (prog_type) { 479 case BPF_PROG_TYPE_SCHED_CLS: 480 case BPF_PROG_TYPE_XDP: 481 break; 482 default: 483 return; 484 } 485 486 res = probe_prog_type_ifindex(prog_type, ifindex); 487 } else { 488 res = libbpf_probe_bpf_prog_type(prog_type, NULL) > 0; 489 } 490 491 #ifdef USE_LIBCAP 492 /* Probe may succeed even if program load fails, for unprivileged users 493 * check that we did not fail because of insufficient permissions 494 */ 495 if (run_as_unprivileged && errno == EPERM) 496 res = false; 497 #endif 498 499 supported_types[prog_type] |= res; 500 501 maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1; 502 if (strlen(prog_type_str) > maxlen) { 503 p_info("program type name too long"); 504 return; 505 } 506 507 sprintf(feat_name, "have_%s_prog_type", prog_type_str); 508 sprintf(define_name, "%s_prog_type", prog_type_str); 509 uppercase(define_name, sizeof(define_name)); 510 sprintf(plain_desc, "%s%s", plain_comment, prog_type_str); 511 print_bool_feature(feat_name, plain_desc, define_name, res, 512 define_prefix); 513 } 514 515 static bool probe_map_type_ifindex(enum bpf_map_type map_type, __u32 ifindex) 516 { 517 LIBBPF_OPTS(bpf_map_create_opts, opts); 518 int key_size, value_size, max_entries; 519 int fd; 520 521 opts.map_ifindex = ifindex; 522 523 key_size = sizeof(__u32); 524 value_size = sizeof(__u32); 525 max_entries = 1; 526 527 fd = bpf_map_create(map_type, NULL, key_size, value_size, max_entries, 528 &opts); 529 if (fd >= 0) 530 close(fd); 531 532 return fd >= 0; 533 } 534 535 static void 536 probe_map_type(enum bpf_map_type map_type, char const *map_type_str, 537 const char *define_prefix, __u32 ifindex) 538 { 539 char feat_name[128], plain_desc[128], define_name[128]; 540 const char *plain_comment = "eBPF map_type "; 541 size_t maxlen; 542 bool res; 543 544 if (ifindex) { 545 switch (map_type) { 546 case BPF_MAP_TYPE_HASH: 547 case BPF_MAP_TYPE_ARRAY: 548 break; 549 default: 550 return; 551 } 552 553 res = probe_map_type_ifindex(map_type, ifindex); 554 } else { 555 res = libbpf_probe_bpf_map_type(map_type, NULL) > 0; 556 } 557 558 /* Probe result depends on the success of map creation, no additional 559 * check required for unprivileged users 560 */ 561 562 maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1; 563 if (strlen(map_type_str) > maxlen) { 564 p_info("map type name too long"); 565 return; 566 } 567 568 sprintf(feat_name, "have_%s_map_type", map_type_str); 569 sprintf(define_name, "%s_map_type", map_type_str); 570 uppercase(define_name, sizeof(define_name)); 571 sprintf(plain_desc, "%s%s", plain_comment, map_type_str); 572 print_bool_feature(feat_name, plain_desc, define_name, res, 573 define_prefix); 574 } 575 576 static bool 577 probe_helper_ifindex(enum bpf_func_id id, enum bpf_prog_type prog_type, 578 __u32 ifindex) 579 { 580 struct bpf_insn insns[2] = { 581 BPF_EMIT_CALL(id), 582 BPF_EXIT_INSN() 583 }; 584 char buf[4096] = {}; 585 bool res; 586 587 probe_prog_load_ifindex(prog_type, insns, ARRAY_SIZE(insns), buf, 588 sizeof(buf), ifindex); 589 res = !grep(buf, "invalid func ") && !grep(buf, "unknown func ") && 590 !grep(buf, "program of this type cannot use helper "); 591 592 switch (get_vendor_id(ifindex)) { 593 case 0x19ee: /* Netronome specific */ 594 res = res && !grep(buf, "not supported by FW") && 595 !grep(buf, "unsupported function id"); 596 break; 597 default: 598 break; 599 } 600 601 return res; 602 } 603 604 static bool 605 probe_helper_for_progtype(enum bpf_prog_type prog_type, bool supported_type, 606 const char *define_prefix, unsigned int id, 607 const char *ptype_name, __u32 ifindex) 608 { 609 bool res = false; 610 611 if (supported_type) { 612 if (ifindex) 613 res = probe_helper_ifindex(id, prog_type, ifindex); 614 else 615 res = libbpf_probe_bpf_helper(prog_type, id, NULL) > 0; 616 #ifdef USE_LIBCAP 617 /* Probe may succeed even if program load fails, for 618 * unprivileged users check that we did not fail because of 619 * insufficient permissions 620 */ 621 if (run_as_unprivileged && errno == EPERM) 622 res = false; 623 #endif 624 } 625 626 if (json_output) { 627 if (res) 628 jsonw_string(json_wtr, helper_name[id]); 629 } else if (define_prefix) { 630 printf("#define %sBPF__PROG_TYPE_%s__HELPER_%s %s\n", 631 define_prefix, ptype_name, helper_name[id], 632 res ? "1" : "0"); 633 } else { 634 if (res) 635 printf("\n\t- %s", helper_name[id]); 636 } 637 638 return res; 639 } 640 641 static void 642 probe_helpers_for_progtype(enum bpf_prog_type prog_type, 643 const char *prog_type_str, bool supported_type, 644 const char *define_prefix, __u32 ifindex) 645 { 646 char feat_name[128]; 647 unsigned int id; 648 bool probe_res = false; 649 650 if (ifindex) 651 /* Only test helpers for offload-able program types */ 652 switch (prog_type) { 653 case BPF_PROG_TYPE_SCHED_CLS: 654 case BPF_PROG_TYPE_XDP: 655 break; 656 default: 657 return; 658 } 659 660 if (json_output) { 661 sprintf(feat_name, "%s_available_helpers", prog_type_str); 662 jsonw_name(json_wtr, feat_name); 663 jsonw_start_array(json_wtr); 664 } else if (!define_prefix) { 665 printf("eBPF helpers supported for program type %s:", 666 prog_type_str); 667 } 668 669 for (id = 1; id < ARRAY_SIZE(helper_name); id++) { 670 /* Skip helper functions which emit dmesg messages when not in 671 * the full mode. 672 */ 673 switch (id) { 674 case BPF_FUNC_trace_printk: 675 case BPF_FUNC_trace_vprintk: 676 case BPF_FUNC_probe_write_user: 677 if (!full_mode) 678 continue; 679 fallthrough; 680 default: 681 probe_res |= probe_helper_for_progtype(prog_type, supported_type, 682 define_prefix, id, prog_type_str, 683 ifindex); 684 } 685 } 686 687 if (json_output) 688 jsonw_end_array(json_wtr); 689 else if (!define_prefix) { 690 printf("\n"); 691 if (!probe_res) { 692 if (!supported_type) 693 printf("\tProgram type not supported\n"); 694 else 695 printf("\tCould not determine which helpers are available\n"); 696 } 697 } 698 699 700 } 701 702 static void 703 probe_misc_feature(struct bpf_insn *insns, size_t len, 704 const char *define_prefix, __u32 ifindex, 705 const char *feat_name, const char *plain_name, 706 const char *define_name) 707 { 708 LIBBPF_OPTS(bpf_prog_load_opts, opts, 709 .prog_ifindex = ifindex, 710 ); 711 bool res; 712 int fd; 713 714 errno = 0; 715 fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", 716 insns, len, &opts); 717 res = fd >= 0 || !errno; 718 719 if (fd >= 0) 720 close(fd); 721 722 print_bool_feature(feat_name, plain_name, define_name, res, 723 define_prefix); 724 } 725 726 /* 727 * Probe for availability of kernel commit (5.3): 728 * 729 * c04c0d2b968a ("bpf: increase complexity limit and maximum program size") 730 */ 731 static void probe_large_insn_limit(const char *define_prefix, __u32 ifindex) 732 { 733 struct bpf_insn insns[BPF_MAXINSNS + 1]; 734 int i; 735 736 for (i = 0; i < BPF_MAXINSNS; i++) 737 insns[i] = BPF_MOV64_IMM(BPF_REG_0, 1); 738 insns[BPF_MAXINSNS] = BPF_EXIT_INSN(); 739 740 probe_misc_feature(insns, ARRAY_SIZE(insns), 741 define_prefix, ifindex, 742 "have_large_insn_limit", 743 "Large program size limit", 744 "LARGE_INSN_LIMIT"); 745 } 746 747 /* 748 * Probe for bounded loop support introduced in commit 2589726d12a1 749 * ("bpf: introduce bounded loops"). 750 */ 751 static void 752 probe_bounded_loops(const char *define_prefix, __u32 ifindex) 753 { 754 struct bpf_insn insns[4] = { 755 BPF_MOV64_IMM(BPF_REG_0, 10), 756 BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 1), 757 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, -2), 758 BPF_EXIT_INSN() 759 }; 760 761 probe_misc_feature(insns, ARRAY_SIZE(insns), 762 define_prefix, ifindex, 763 "have_bounded_loops", 764 "Bounded loop support", 765 "BOUNDED_LOOPS"); 766 } 767 768 /* 769 * Probe for the v2 instruction set extension introduced in commit 92b31a9af73b 770 * ("bpf: add BPF_J{LT,LE,SLT,SLE} instructions"). 771 */ 772 static void 773 probe_v2_isa_extension(const char *define_prefix, __u32 ifindex) 774 { 775 struct bpf_insn insns[4] = { 776 BPF_MOV64_IMM(BPF_REG_0, 0), 777 BPF_JMP_IMM(BPF_JLT, BPF_REG_0, 0, 1), 778 BPF_MOV64_IMM(BPF_REG_0, 1), 779 BPF_EXIT_INSN() 780 }; 781 782 probe_misc_feature(insns, ARRAY_SIZE(insns), 783 define_prefix, ifindex, 784 "have_v2_isa_extension", 785 "ISA extension v2", 786 "V2_ISA_EXTENSION"); 787 } 788 789 /* 790 * Probe for the v3 instruction set extension introduced in commit 092ed0968bb6 791 * ("bpf: verifier support JMP32"). 792 */ 793 static void 794 probe_v3_isa_extension(const char *define_prefix, __u32 ifindex) 795 { 796 struct bpf_insn insns[4] = { 797 BPF_MOV64_IMM(BPF_REG_0, 0), 798 BPF_JMP32_IMM(BPF_JLT, BPF_REG_0, 0, 1), 799 BPF_MOV64_IMM(BPF_REG_0, 1), 800 BPF_EXIT_INSN() 801 }; 802 803 probe_misc_feature(insns, ARRAY_SIZE(insns), 804 define_prefix, ifindex, 805 "have_v3_isa_extension", 806 "ISA extension v3", 807 "V3_ISA_EXTENSION"); 808 } 809 810 /* 811 * Probe for the v4 instruction set extension introduced in commit 1f9a1ea821ff 812 * ("bpf: Support new sign-extension load insns"). 813 */ 814 static void 815 probe_v4_isa_extension(const char *define_prefix, __u32 ifindex) 816 { 817 struct bpf_insn insns[5] = { 818 BPF_MOV64_IMM(BPF_REG_0, 0), 819 BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 1, 1), 820 BPF_JMP32_A(1), 821 BPF_MOV64_IMM(BPF_REG_0, 1), 822 BPF_EXIT_INSN() 823 }; 824 825 probe_misc_feature(insns, ARRAY_SIZE(insns), 826 define_prefix, ifindex, 827 "have_v4_isa_extension", 828 "ISA extension v4", 829 "V4_ISA_EXTENSION"); 830 } 831 832 static void 833 section_system_config(enum probe_component target, const char *define_prefix) 834 { 835 switch (target) { 836 case COMPONENT_KERNEL: 837 case COMPONENT_UNSPEC: 838 print_start_section("system_config", 839 "Scanning system configuration...", 840 "/*** Misc kernel config items ***/", 841 define_prefix); 842 if (!define_prefix) { 843 if (check_procfs()) { 844 probe_unprivileged_disabled(); 845 probe_jit_enable(); 846 probe_jit_harden(); 847 probe_jit_kallsyms(); 848 probe_jit_limit(); 849 } else { 850 p_info("/* procfs not mounted, skipping related probes */"); 851 } 852 } 853 probe_kernel_image_config(define_prefix); 854 print_end_section(); 855 break; 856 default: 857 break; 858 } 859 } 860 861 static bool section_syscall_config(const char *define_prefix) 862 { 863 bool res; 864 865 print_start_section("syscall_config", 866 "Scanning system call availability...", 867 "/*** System call availability ***/", 868 define_prefix); 869 res = probe_bpf_syscall(define_prefix); 870 print_end_section(); 871 872 return res; 873 } 874 875 static void 876 section_program_types(bool *supported_types, const char *define_prefix, 877 __u32 ifindex) 878 { 879 unsigned int prog_type = BPF_PROG_TYPE_UNSPEC; 880 const char *prog_type_str; 881 882 print_start_section("program_types", 883 "Scanning eBPF program types...", 884 "/*** eBPF program types ***/", 885 define_prefix); 886 887 while (true) { 888 prog_type++; 889 prog_type_str = libbpf_bpf_prog_type_str(prog_type); 890 /* libbpf will return NULL for variants unknown to it. */ 891 if (!prog_type_str) 892 break; 893 894 probe_prog_type(prog_type, prog_type_str, supported_types, define_prefix, 895 ifindex); 896 } 897 898 print_end_section(); 899 } 900 901 static void section_map_types(const char *define_prefix, __u32 ifindex) 902 { 903 unsigned int map_type = BPF_MAP_TYPE_UNSPEC; 904 const char *map_type_str; 905 906 print_start_section("map_types", 907 "Scanning eBPF map types...", 908 "/*** eBPF map types ***/", 909 define_prefix); 910 911 while (true) { 912 map_type++; 913 map_type_str = libbpf_bpf_map_type_str(map_type); 914 /* libbpf will return NULL for variants unknown to it. */ 915 if (!map_type_str) 916 break; 917 918 probe_map_type(map_type, map_type_str, define_prefix, ifindex); 919 } 920 921 print_end_section(); 922 } 923 924 static void 925 section_helpers(bool *supported_types, const char *define_prefix, __u32 ifindex) 926 { 927 unsigned int prog_type = BPF_PROG_TYPE_UNSPEC; 928 const char *prog_type_str; 929 930 print_start_section("helpers", 931 "Scanning eBPF helper functions...", 932 "/*** eBPF helper functions ***/", 933 define_prefix); 934 935 if (define_prefix) 936 printf("/*\n" 937 " * Use %sHAVE_PROG_TYPE_HELPER(prog_type_name, helper_name)\n" 938 " * to determine if <helper_name> is available for <prog_type_name>,\n" 939 " * e.g.\n" 940 " * #if %sHAVE_PROG_TYPE_HELPER(xdp, bpf_redirect)\n" 941 " * // do stuff with this helper\n" 942 " * #elif\n" 943 " * // use a workaround\n" 944 " * #endif\n" 945 " */\n" 946 "#define %sHAVE_PROG_TYPE_HELPER(prog_type, helper) \\\n" 947 " %sBPF__PROG_TYPE_ ## prog_type ## __HELPER_ ## helper\n", 948 define_prefix, define_prefix, define_prefix, 949 define_prefix); 950 while (true) { 951 prog_type++; 952 prog_type_str = libbpf_bpf_prog_type_str(prog_type); 953 /* libbpf will return NULL for variants unknown to it. */ 954 if (!prog_type_str) 955 break; 956 957 probe_helpers_for_progtype(prog_type, prog_type_str, 958 supported_types[prog_type], 959 define_prefix, 960 ifindex); 961 } 962 963 print_end_section(); 964 } 965 966 static void section_misc(const char *define_prefix, __u32 ifindex) 967 { 968 print_start_section("misc", 969 "Scanning miscellaneous eBPF features...", 970 "/*** eBPF misc features ***/", 971 define_prefix); 972 probe_large_insn_limit(define_prefix, ifindex); 973 probe_bounded_loops(define_prefix, ifindex); 974 probe_v2_isa_extension(define_prefix, ifindex); 975 probe_v3_isa_extension(define_prefix, ifindex); 976 probe_v4_isa_extension(define_prefix, ifindex); 977 print_end_section(); 978 } 979 980 #ifdef USE_LIBCAP 981 #define capability(c) { c, false, #c } 982 #define capability_msg(a, i) a[i].set ? "" : a[i].name, a[i].set ? "" : ", " 983 #endif 984 985 static int handle_perms(void) 986 { 987 #ifdef USE_LIBCAP 988 struct { 989 cap_value_t cap; 990 bool set; 991 char name[14]; /* strlen("CAP_SYS_ADMIN") */ 992 } bpf_caps[] = { 993 capability(CAP_SYS_ADMIN), 994 #ifdef CAP_BPF 995 capability(CAP_BPF), 996 capability(CAP_NET_ADMIN), 997 capability(CAP_PERFMON), 998 #endif 999 }; 1000 cap_value_t cap_list[ARRAY_SIZE(bpf_caps)]; 1001 unsigned int i, nb_bpf_caps = 0; 1002 bool cap_sys_admin_only = true; 1003 cap_flag_value_t val; 1004 int res = -1; 1005 cap_t caps; 1006 1007 caps = cap_get_proc(); 1008 if (!caps) { 1009 p_err("failed to get capabilities for process: %s", 1010 strerror(errno)); 1011 return -1; 1012 } 1013 1014 #ifdef CAP_BPF 1015 if (CAP_IS_SUPPORTED(CAP_BPF)) 1016 cap_sys_admin_only = false; 1017 #endif 1018 1019 for (i = 0; i < ARRAY_SIZE(bpf_caps); i++) { 1020 const char *cap_name = bpf_caps[i].name; 1021 cap_value_t cap = bpf_caps[i].cap; 1022 1023 if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &val)) { 1024 p_err("bug: failed to retrieve %s status: %s", cap_name, 1025 strerror(errno)); 1026 goto exit_free; 1027 } 1028 1029 if (val == CAP_SET) { 1030 bpf_caps[i].set = true; 1031 cap_list[nb_bpf_caps++] = cap; 1032 } 1033 1034 if (cap_sys_admin_only) 1035 /* System does not know about CAP_BPF, meaning that 1036 * CAP_SYS_ADMIN is the only capability required. We 1037 * just checked it, break. 1038 */ 1039 break; 1040 } 1041 1042 if ((run_as_unprivileged && !nb_bpf_caps) || 1043 (!run_as_unprivileged && nb_bpf_caps == ARRAY_SIZE(bpf_caps)) || 1044 (!run_as_unprivileged && cap_sys_admin_only && nb_bpf_caps)) { 1045 /* We are all good, exit now */ 1046 res = 0; 1047 goto exit_free; 1048 } 1049 1050 if (!run_as_unprivileged) { 1051 if (cap_sys_admin_only) 1052 p_err("missing %s, required for full feature probing; run as root or use 'unprivileged'", 1053 bpf_caps[0].name); 1054 else 1055 p_err("missing %s%s%s%s%s%s%s%srequired for full feature probing; run as root or use 'unprivileged'", 1056 capability_msg(bpf_caps, 0), 1057 #ifdef CAP_BPF 1058 capability_msg(bpf_caps, 1), 1059 capability_msg(bpf_caps, 2), 1060 capability_msg(bpf_caps, 3) 1061 #else 1062 "", "", "", "", "", "" 1063 #endif /* CAP_BPF */ 1064 ); 1065 goto exit_free; 1066 } 1067 1068 /* if (run_as_unprivileged && nb_bpf_caps > 0), drop capabilities. */ 1069 if (cap_set_flag(caps, CAP_EFFECTIVE, nb_bpf_caps, cap_list, 1070 CAP_CLEAR)) { 1071 p_err("bug: failed to clear capabilities: %s", strerror(errno)); 1072 goto exit_free; 1073 } 1074 1075 if (cap_set_proc(caps)) { 1076 p_err("failed to drop capabilities: %s", strerror(errno)); 1077 goto exit_free; 1078 } 1079 1080 res = 0; 1081 1082 exit_free: 1083 if (cap_free(caps) && !res) { 1084 p_err("failed to clear storage object for capabilities: %s", 1085 strerror(errno)); 1086 res = -1; 1087 } 1088 1089 return res; 1090 #else 1091 /* Detection assumes user has specific privileges. 1092 * We do not use libcap so let's approximate, and restrict usage to 1093 * root user only. 1094 */ 1095 if (geteuid()) { 1096 p_err("full feature probing requires root privileges"); 1097 return -1; 1098 } 1099 1100 return 0; 1101 #endif /* USE_LIBCAP */ 1102 } 1103 1104 static int do_probe(int argc, char **argv) 1105 { 1106 enum probe_component target = COMPONENT_UNSPEC; 1107 const char *define_prefix = NULL; 1108 bool supported_types[128] = {}; 1109 __u32 ifindex = 0; 1110 char *ifname; 1111 1112 set_max_rlimit(); 1113 1114 while (argc) { 1115 if (is_prefix(*argv, "kernel")) { 1116 if (target != COMPONENT_UNSPEC) { 1117 p_err("component to probe already specified"); 1118 return -1; 1119 } 1120 target = COMPONENT_KERNEL; 1121 NEXT_ARG(); 1122 } else if (is_prefix(*argv, "dev")) { 1123 NEXT_ARG(); 1124 1125 if (target != COMPONENT_UNSPEC || ifindex) { 1126 p_err("component to probe already specified"); 1127 return -1; 1128 } 1129 if (!REQ_ARGS(1)) 1130 return -1; 1131 1132 target = COMPONENT_DEVICE; 1133 ifname = GET_ARG(); 1134 ifindex = if_nametoindex(ifname); 1135 if (!ifindex) { 1136 p_err("unrecognized netdevice '%s': %s", ifname, 1137 strerror(errno)); 1138 return -1; 1139 } 1140 } else if (is_prefix(*argv, "full")) { 1141 full_mode = true; 1142 NEXT_ARG(); 1143 } else if (is_prefix(*argv, "macros") && !define_prefix) { 1144 define_prefix = ""; 1145 NEXT_ARG(); 1146 } else if (is_prefix(*argv, "prefix")) { 1147 if (!define_prefix) { 1148 p_err("'prefix' argument can only be use after 'macros'"); 1149 return -1; 1150 } 1151 if (strcmp(define_prefix, "")) { 1152 p_err("'prefix' already defined"); 1153 return -1; 1154 } 1155 NEXT_ARG(); 1156 1157 if (!REQ_ARGS(1)) 1158 return -1; 1159 define_prefix = GET_ARG(); 1160 } else if (is_prefix(*argv, "unprivileged")) { 1161 #ifdef USE_LIBCAP 1162 run_as_unprivileged = true; 1163 NEXT_ARG(); 1164 #else 1165 p_err("unprivileged run not supported, recompile bpftool with libcap"); 1166 return -1; 1167 #endif 1168 } else { 1169 p_err("expected no more arguments, 'kernel', 'dev', 'macros' or 'prefix', got: '%s'?", 1170 *argv); 1171 return -1; 1172 } 1173 } 1174 1175 /* Full feature detection requires specific privileges. 1176 * Let's approximate, and warn if user is not root. 1177 */ 1178 if (handle_perms()) 1179 return -1; 1180 1181 if (json_output) { 1182 define_prefix = NULL; 1183 jsonw_start_object(json_wtr); 1184 } 1185 1186 section_system_config(target, define_prefix); 1187 if (!section_syscall_config(define_prefix)) 1188 /* bpf() syscall unavailable, don't probe other BPF features */ 1189 goto exit_close_json; 1190 section_program_types(supported_types, define_prefix, ifindex); 1191 section_map_types(define_prefix, ifindex); 1192 section_helpers(supported_types, define_prefix, ifindex); 1193 section_misc(define_prefix, ifindex); 1194 1195 exit_close_json: 1196 if (json_output) 1197 /* End root object */ 1198 jsonw_end_object(json_wtr); 1199 1200 return 0; 1201 } 1202 1203 static const char *get_helper_name(unsigned int id) 1204 { 1205 if (id >= ARRAY_SIZE(helper_name)) 1206 return NULL; 1207 1208 return helper_name[id]; 1209 } 1210 1211 static int do_list_builtins(int argc, char **argv) 1212 { 1213 const char *(*get_name)(unsigned int id); 1214 unsigned int id = 0; 1215 1216 if (argc < 1) 1217 usage(); 1218 1219 if (is_prefix(*argv, "prog_types")) { 1220 get_name = (const char *(*)(unsigned int))libbpf_bpf_prog_type_str; 1221 } else if (is_prefix(*argv, "map_types")) { 1222 get_name = (const char *(*)(unsigned int))libbpf_bpf_map_type_str; 1223 } else if (is_prefix(*argv, "attach_types")) { 1224 get_name = (const char *(*)(unsigned int))libbpf_bpf_attach_type_str; 1225 } else if (is_prefix(*argv, "link_types")) { 1226 get_name = (const char *(*)(unsigned int))libbpf_bpf_link_type_str; 1227 } else if (is_prefix(*argv, "helpers")) { 1228 get_name = get_helper_name; 1229 } else { 1230 p_err("expected 'prog_types', 'map_types', 'attach_types', 'link_types' or 'helpers', got: %s", *argv); 1231 return -1; 1232 } 1233 1234 if (json_output) 1235 jsonw_start_array(json_wtr); /* root array */ 1236 1237 while (true) { 1238 const char *name; 1239 1240 name = get_name(id++); 1241 if (!name) 1242 break; 1243 if (json_output) 1244 jsonw_string(json_wtr, name); 1245 else 1246 printf("%s\n", name); 1247 } 1248 1249 if (json_output) 1250 jsonw_end_array(json_wtr); /* root array */ 1251 1252 return 0; 1253 } 1254 1255 static int do_help(int argc, char **argv) 1256 { 1257 if (json_output) { 1258 jsonw_null(json_wtr); 1259 return 0; 1260 } 1261 1262 fprintf(stderr, 1263 "Usage: %1$s %2$s probe [COMPONENT] [full] [unprivileged] [macros [prefix PREFIX]]\n" 1264 " %1$s %2$s list_builtins GROUP\n" 1265 " %1$s %2$s help\n" 1266 "\n" 1267 " COMPONENT := { kernel | dev NAME }\n" 1268 " GROUP := { prog_types | map_types | attach_types | link_types | helpers }\n" 1269 " " HELP_SPEC_OPTIONS " }\n" 1270 "", 1271 bin_name, argv[-2]); 1272 1273 return 0; 1274 } 1275 1276 static const struct cmd cmds[] = { 1277 { "probe", do_probe }, 1278 { "list_builtins", do_list_builtins }, 1279 { "help", do_help }, 1280 { 0 } 1281 }; 1282 1283 int do_feature(int argc, char **argv) 1284 { 1285 return cmd_select(cmds, argc, argv, do_help); 1286 } 1287