|
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> |
|
42 | 40 | # define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1 |
43 | 41 | # endif |
44 | 42 | #endif |
| 43 | +#include "cap_helpers.h" |
45 | 44 | #include "bpf_rand.h" |
46 | 45 | #include "bpf_util.h" |
47 | 46 | #include "test_btf.h" |
|
62 | 61 | #define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0) |
63 | 62 | #define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1) |
64 | 63 |
|
| 64 | +/* need CAP_BPF, CAP_NET_ADMIN, CAP_PERFMON to load progs */ |
| 65 | +#define ADMIN_CAPS (1ULL << CAP_NET_ADMIN | \ |
| 66 | + 1ULL << CAP_PERFMON | \ |
| 67 | + 1ULL << CAP_BPF) |
65 | 68 | #define UNPRIV_SYSCTL "kernel/unprivileged_bpf_disabled" |
66 | 69 | static bool unpriv_disabled = false; |
67 | 70 | static int skips; |
@@ -973,47 +976,19 @@ struct libcap { |
973 | 976 |
|
974 | 977 | static int set_admin(bool admin) |
975 | 978 | { |
976 | | - cap_t caps; |
977 | | - /* need CAP_BPF, CAP_NET_ADMIN, CAP_PERFMON to load progs */ |
978 | | - const cap_value_t cap_net_admin = CAP_NET_ADMIN; |
979 | | - const cap_value_t cap_sys_admin = CAP_SYS_ADMIN; |
980 | | - struct libcap *cap; |
981 | | - int ret = -1; |
982 | | - |
983 | | - caps = cap_get_proc(); |
984 | | - if (!caps) { |
985 | | - perror("cap_get_proc"); |
986 | | - return -1; |
987 | | - } |
988 | | - cap = (struct libcap *)caps; |
989 | | - if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_sys_admin, CAP_CLEAR)) { |
990 | | - perror("cap_set_flag clear admin"); |
991 | | - goto out; |
992 | | - } |
993 | | - if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_net_admin, |
994 | | - admin ? CAP_SET : CAP_CLEAR)) { |
995 | | - perror("cap_set_flag set_or_clear net"); |
996 | | - goto out; |
997 | | - } |
998 | | - /* libcap is likely old and simply ignores CAP_BPF and CAP_PERFMON, |
999 | | - * so update effective bits manually |
1000 | | - */ |
| 979 | + int err; |
| 980 | + |
1001 | 981 | if (admin) { |
1002 | | - cap->data[1].effective |= 1 << (38 /* CAP_PERFMON */ - 32); |
1003 | | - cap->data[1].effective |= 1 << (39 /* CAP_BPF */ - 32); |
| 982 | + err = cap_enable_effective(ADMIN_CAPS, NULL); |
| 983 | + if (err) |
| 984 | + perror("cap_enable_effective(ADMIN_CAPS)"); |
1004 | 985 | } else { |
1005 | | - cap->data[1].effective &= ~(1 << (38 - 32)); |
1006 | | - cap->data[1].effective &= ~(1 << (39 - 32)); |
1007 | | - } |
1008 | | - if (cap_set_proc(caps)) { |
1009 | | - perror("cap_set_proc"); |
1010 | | - goto out; |
| 986 | + err = cap_disable_effective(ADMIN_CAPS, NULL); |
| 987 | + if (err) |
| 988 | + perror("cap_disable_effective(ADMIN_CAPS)"); |
1011 | 989 | } |
1012 | | - ret = 0; |
1013 | | -out: |
1014 | | - if (cap_free(caps)) |
1015 | | - perror("cap_free"); |
1016 | | - return ret; |
| 990 | + |
| 991 | + return err; |
1017 | 992 | } |
1018 | 993 |
|
1019 | 994 | static int do_prog_test_run(int fd_prog, bool unpriv, uint32_t expected_val, |
@@ -1291,31 +1266,18 @@ static void do_test_single(struct bpf_test *test, bool unpriv, |
1291 | 1266 |
|
1292 | 1267 | static bool is_admin(void) |
1293 | 1268 | { |
1294 | | - cap_flag_value_t net_priv = CAP_CLEAR; |
1295 | | - bool perfmon_priv = false; |
1296 | | - bool bpf_priv = false; |
1297 | | - struct libcap *cap; |
1298 | | - cap_t caps; |
1299 | | - |
1300 | | -#ifdef CAP_IS_SUPPORTED |
1301 | | - if (!CAP_IS_SUPPORTED(CAP_SETFCAP)) { |
1302 | | - perror("cap_get_flag"); |
1303 | | - return false; |
1304 | | - } |
1305 | | -#endif |
1306 | | - caps = cap_get_proc(); |
1307 | | - if (!caps) { |
1308 | | - perror("cap_get_proc"); |
| 1269 | + __u64 caps; |
| 1270 | + |
| 1271 | + /* The test checks for finer cap as CAP_NET_ADMIN, |
| 1272 | + * CAP_PERFMON, and CAP_BPF instead of CAP_SYS_ADMIN. |
| 1273 | + * Thus, disable CAP_SYS_ADMIN at the beginning. |
| 1274 | + */ |
| 1275 | + if (cap_disable_effective(1ULL << CAP_SYS_ADMIN, &caps)) { |
| 1276 | + perror("cap_disable_effective(CAP_SYS_ADMIN)"); |
1309 | 1277 | return false; |
1310 | 1278 | } |
1311 | | - cap = (struct libcap *)caps; |
1312 | | - bpf_priv = cap->data[1].effective & (1 << (39/* CAP_BPF */ - 32)); |
1313 | | - perfmon_priv = cap->data[1].effective & (1 << (38/* CAP_PERFMON */ - 32)); |
1314 | | - if (cap_get_flag(caps, CAP_NET_ADMIN, CAP_EFFECTIVE, &net_priv)) |
1315 | | - perror("cap_get_flag NET"); |
1316 | | - if (cap_free(caps)) |
1317 | | - perror("cap_free"); |
1318 | | - return bpf_priv && perfmon_priv && net_priv == CAP_SET; |
| 1279 | + |
| 1280 | + return (caps & ADMIN_CAPS) == ADMIN_CAPS; |
1319 | 1281 | } |
1320 | 1282 |
|
1321 | 1283 | static void get_unpriv_disabled() |
|
0 commit comments