feature.c 31 KB

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