Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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