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