feature.c 30 KB

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