|
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