Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'Remove libcap dependency from bpf selftests'

Martin KaFai Lau says:

====================

After upgrading to the newer libcap (>= 2.60),
the libcap commit aca076443591 ("Make cap_t operations thread safe.")
added a "__u8 mutex;" to the "struct _cap_struct". It caused a few byte
shift that breaks the assumption made in the "struct libcap" definition
in test_verifier.c.

This set is to remove the libcap dependency from the bpf selftests.

v2:
- Define CAP_PERFMON and CAP_BPF when the older <linux/capability.h>
does not have them. (Andrii)
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+122 -100
+5 -3
tools/testing/selftests/bpf/Makefile
··· 25 25 -I$(CURDIR) -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \ 26 26 -I$(TOOLSINCDIR) -I$(APIDIR) -I$(OUTPUT) 27 27 LDFLAGS += $(SAN_CFLAGS) 28 - LDLIBS += -lcap -lelf -lz -lrt -lpthread 28 + LDLIBS += -lelf -lz -lrt -lpthread 29 29 30 30 # Silence some warnings when compiled with clang 31 31 ifneq ($(LLVM),) ··· 195 195 CGROUP_HELPERS := $(OUTPUT)/cgroup_helpers.o 196 196 TESTING_HELPERS := $(OUTPUT)/testing_helpers.o 197 197 TRACE_HELPERS := $(OUTPUT)/trace_helpers.o 198 + CAP_HELPERS := $(OUTPUT)/cap_helpers.o 198 199 199 200 $(OUTPUT)/test_dev_cgroup: $(CGROUP_HELPERS) $(TESTING_HELPERS) 200 201 $(OUTPUT)/test_skb_cgroup_id_user: $(CGROUP_HELPERS) $(TESTING_HELPERS) ··· 212 211 $(OUTPUT)/xdping: $(TESTING_HELPERS) 213 212 $(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS) 214 213 $(OUTPUT)/test_maps: $(TESTING_HELPERS) 215 - $(OUTPUT)/test_verifier: $(TESTING_HELPERS) 214 + $(OUTPUT)/test_verifier: $(TESTING_HELPERS) $(CAP_HELPERS) 216 215 217 216 BPFTOOL ?= $(DEFAULT_BPFTOOL) 218 217 $(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \ ··· 480 479 TRUNNER_BPF_PROGS_DIR := progs 481 480 TRUNNER_EXTRA_SOURCES := test_progs.c cgroup_helpers.c trace_helpers.c \ 482 481 network_helpers.c testing_helpers.c \ 483 - btf_helpers.c flow_dissector_load.h 482 + btf_helpers.c flow_dissector_load.h \ 483 + cap_helpers.c 484 484 TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/bpf_testmod.ko \ 485 485 ima_setup.sh \ 486 486 $(wildcard progs/btf_dump_test_case_*.c)
+67
tools/testing/selftests/bpf/cap_helpers.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include "cap_helpers.h" 3 + 4 + /* Avoid including <sys/capability.h> from the libcap-devel package, 5 + * so directly declare them here and use them from glibc. 6 + */ 7 + int capget(cap_user_header_t header, cap_user_data_t data); 8 + int capset(cap_user_header_t header, const cap_user_data_t data); 9 + 10 + int cap_enable_effective(__u64 caps, __u64 *old_caps) 11 + { 12 + struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3]; 13 + struct __user_cap_header_struct hdr = { 14 + .version = _LINUX_CAPABILITY_VERSION_3, 15 + }; 16 + __u32 cap0 = caps; 17 + __u32 cap1 = caps >> 32; 18 + int err; 19 + 20 + err = capget(&hdr, data); 21 + if (err) 22 + return err; 23 + 24 + if (old_caps) 25 + *old_caps = (__u64)(data[1].effective) << 32 | data[0].effective; 26 + 27 + if ((data[0].effective & cap0) == cap0 && 28 + (data[1].effective & cap1) == cap1) 29 + return 0; 30 + 31 + data[0].effective |= cap0; 32 + data[1].effective |= cap1; 33 + err = capset(&hdr, data); 34 + if (err) 35 + return err; 36 + 37 + return 0; 38 + } 39 + 40 + int cap_disable_effective(__u64 caps, __u64 *old_caps) 41 + { 42 + struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3]; 43 + struct __user_cap_header_struct hdr = { 44 + .version = _LINUX_CAPABILITY_VERSION_3, 45 + }; 46 + __u32 cap0 = caps; 47 + __u32 cap1 = caps >> 32; 48 + int err; 49 + 50 + err = capget(&hdr, data); 51 + if (err) 52 + return err; 53 + 54 + if (old_caps) 55 + *old_caps = (__u64)(data[1].effective) << 32 | data[0].effective; 56 + 57 + if (!(data[0].effective & cap0) && !(data[1].effective & cap1)) 58 + return 0; 59 + 60 + data[0].effective &= ~cap0; 61 + data[1].effective &= ~cap1; 62 + err = capset(&hdr, data); 63 + if (err) 64 + return err; 65 + 66 + return 0; 67 + }
+19
tools/testing/selftests/bpf/cap_helpers.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __CAP_HELPERS_H 3 + #define __CAP_HELPERS_H 4 + 5 + #include <linux/types.h> 6 + #include <linux/capability.h> 7 + 8 + #ifndef CAP_PERFMON 9 + #define CAP_PERFMON 38 10 + #endif 11 + 12 + #ifndef CAP_BPF 13 + #define CAP_BPF 39 14 + #endif 15 + 16 + int cap_enable_effective(__u64 caps, __u64 *old_caps); 17 + int cap_disable_effective(__u64 caps, __u64 *old_caps); 18 + 19 + #endif
+8 -36
tools/testing/selftests/bpf/prog_tests/bind_perm.c
··· 4 4 #include <stdlib.h> 5 5 #include <sys/types.h> 6 6 #include <sys/socket.h> 7 - #include <sys/capability.h> 8 7 9 8 #include "test_progs.h" 9 + #include "cap_helpers.h" 10 10 #include "bind_perm.skel.h" 11 11 12 12 static int duration; ··· 49 49 close(fd); 50 50 } 51 51 52 - bool cap_net_bind_service(cap_flag_value_t flag) 53 - { 54 - const cap_value_t cap_net_bind_service = CAP_NET_BIND_SERVICE; 55 - cap_flag_value_t original_value; 56 - bool was_effective = false; 57 - cap_t caps; 58 - 59 - caps = cap_get_proc(); 60 - if (CHECK(!caps, "cap_get_proc", "errno %d", errno)) 61 - goto free_caps; 62 - 63 - if (CHECK(cap_get_flag(caps, CAP_NET_BIND_SERVICE, CAP_EFFECTIVE, 64 - &original_value), 65 - "cap_get_flag", "errno %d", errno)) 66 - goto free_caps; 67 - 68 - was_effective = (original_value == CAP_SET); 69 - 70 - if (CHECK(cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_net_bind_service, 71 - flag), 72 - "cap_set_flag", "errno %d", errno)) 73 - goto free_caps; 74 - 75 - if (CHECK(cap_set_proc(caps), "cap_set_proc", "errno %d", errno)) 76 - goto free_caps; 77 - 78 - free_caps: 79 - CHECK(cap_free(caps), "cap_free", "errno %d", errno); 80 - return was_effective; 81 - } 82 - 83 52 void test_bind_perm(void) 84 53 { 85 - bool cap_was_effective; 54 + const __u64 net_bind_svc_cap = 1ULL << CAP_NET_BIND_SERVICE; 86 55 struct bind_perm *skel; 56 + __u64 old_caps = 0; 87 57 int cgroup_fd; 88 58 89 59 if (create_netns()) ··· 75 105 if (!ASSERT_OK_PTR(skel, "bind_v6_prog")) 76 106 goto close_skeleton; 77 107 78 - cap_was_effective = cap_net_bind_service(CAP_CLEAR); 108 + ASSERT_OK(cap_disable_effective(net_bind_svc_cap, &old_caps), 109 + "cap_disable_effective"); 79 110 80 111 try_bind(AF_INET, 110, EACCES); 81 112 try_bind(AF_INET6, 110, EACCES); ··· 84 113 try_bind(AF_INET, 111, 0); 85 114 try_bind(AF_INET6, 111, 0); 86 115 87 - if (cap_was_effective) 88 - cap_net_bind_service(CAP_SET); 116 + if (old_caps & net_bind_svc_cap) 117 + ASSERT_OK(cap_enable_effective(net_bind_svc_cap, NULL), 118 + "cap_enable_effective"); 89 119 90 120 close_skeleton: 91 121 bind_perm__destroy(skel);
+23 -61
tools/testing/selftests/bpf/test_verifier.c
··· 22 22 #include <limits.h> 23 23 #include <assert.h> 24 24 25 - #include <sys/capability.h> 26 - 27 25 #include <linux/unistd.h> 28 26 #include <linux/filter.h> 29 27 #include <linux/bpf_perf_event.h> ··· 40 42 # define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1 41 43 # endif 42 44 #endif 45 + #include "cap_helpers.h" 43 46 #include "bpf_rand.h" 44 47 #include "bpf_util.h" 45 48 #include "test_btf.h" ··· 61 62 #define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0) 62 63 #define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1) 63 64 65 + /* need CAP_BPF, CAP_NET_ADMIN, CAP_PERFMON to load progs */ 66 + #define ADMIN_CAPS (1ULL << CAP_NET_ADMIN | \ 67 + 1ULL << CAP_PERFMON | \ 68 + 1ULL << CAP_BPF) 64 69 #define UNPRIV_SYSCTL "kernel/unprivileged_bpf_disabled" 65 70 static bool unpriv_disabled = false; 66 71 static int skips; ··· 976 973 977 974 static int set_admin(bool admin) 978 975 { 979 - cap_t caps; 980 - /* need CAP_BPF, CAP_NET_ADMIN, CAP_PERFMON to load progs */ 981 - const cap_value_t cap_net_admin = CAP_NET_ADMIN; 982 - const cap_value_t cap_sys_admin = CAP_SYS_ADMIN; 983 - struct libcap *cap; 984 - int ret = -1; 976 + int err; 985 977 986 - caps = cap_get_proc(); 987 - if (!caps) { 988 - perror("cap_get_proc"); 989 - return -1; 990 - } 991 - cap = (struct libcap *)caps; 992 - if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_sys_admin, CAP_CLEAR)) { 993 - perror("cap_set_flag clear admin"); 994 - goto out; 995 - } 996 - if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_net_admin, 997 - admin ? CAP_SET : CAP_CLEAR)) { 998 - perror("cap_set_flag set_or_clear net"); 999 - goto out; 1000 - } 1001 - /* libcap is likely old and simply ignores CAP_BPF and CAP_PERFMON, 1002 - * so update effective bits manually 1003 - */ 1004 978 if (admin) { 1005 - cap->data[1].effective |= 1 << (38 /* CAP_PERFMON */ - 32); 1006 - cap->data[1].effective |= 1 << (39 /* CAP_BPF */ - 32); 979 + err = cap_enable_effective(ADMIN_CAPS, NULL); 980 + if (err) 981 + perror("cap_enable_effective(ADMIN_CAPS)"); 1007 982 } else { 1008 - cap->data[1].effective &= ~(1 << (38 - 32)); 1009 - cap->data[1].effective &= ~(1 << (39 - 32)); 983 + err = cap_disable_effective(ADMIN_CAPS, NULL); 984 + if (err) 985 + perror("cap_disable_effective(ADMIN_CAPS)"); 1010 986 } 1011 - if (cap_set_proc(caps)) { 1012 - perror("cap_set_proc"); 1013 - goto out; 1014 - } 1015 - ret = 0; 1016 - out: 1017 - if (cap_free(caps)) 1018 - perror("cap_free"); 1019 - return ret; 987 + 988 + return err; 1020 989 } 1021 990 1022 991 static int do_prog_test_run(int fd_prog, bool unpriv, uint32_t expected_val, ··· 1266 1291 1267 1292 static bool is_admin(void) 1268 1293 { 1269 - cap_flag_value_t net_priv = CAP_CLEAR; 1270 - bool perfmon_priv = false; 1271 - bool bpf_priv = false; 1272 - struct libcap *cap; 1273 - cap_t caps; 1294 + __u64 caps; 1274 1295 1275 - #ifdef CAP_IS_SUPPORTED 1276 - if (!CAP_IS_SUPPORTED(CAP_SETFCAP)) { 1277 - perror("cap_get_flag"); 1296 + /* The test checks for finer cap as CAP_NET_ADMIN, 1297 + * CAP_PERFMON, and CAP_BPF instead of CAP_SYS_ADMIN. 1298 + * Thus, disable CAP_SYS_ADMIN at the beginning. 1299 + */ 1300 + if (cap_disable_effective(1ULL << CAP_SYS_ADMIN, &caps)) { 1301 + perror("cap_disable_effective(CAP_SYS_ADMIN)"); 1278 1302 return false; 1279 1303 } 1280 - #endif 1281 - caps = cap_get_proc(); 1282 - if (!caps) { 1283 - perror("cap_get_proc"); 1284 - return false; 1285 - } 1286 - cap = (struct libcap *)caps; 1287 - bpf_priv = cap->data[1].effective & (1 << (39/* CAP_BPF */ - 32)); 1288 - perfmon_priv = cap->data[1].effective & (1 << (38/* CAP_PERFMON */ - 32)); 1289 - if (cap_get_flag(caps, CAP_NET_ADMIN, CAP_EFFECTIVE, &net_priv)) 1290 - perror("cap_get_flag NET"); 1291 - if (cap_free(caps)) 1292 - perror("cap_free"); 1293 - return bpf_priv && perfmon_priv && net_priv == CAP_SET; 1304 + 1305 + return (caps & ADMIN_CAPS) == ADMIN_CAPS; 1294 1306 } 1295 1307 1296 1308 static void get_unpriv_disabled()