diff options
| author | Alexei Starovoitov <ast@kernel.org> | 2022-03-16 15:07:49 -0700 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2022-03-16 15:07:50 -0700 |
| commit | aaccdf9c93a00cc5eec6f9d97046b44643c60800 (patch) | |
| tree | 687d9738a7fde05252f0f3d283692cba1c0af235 /tools/testing/selftests/bpf/cap_helpers.c | |
| parent | 6585abea98ae5f750358a6427f2ddf7715393f69 (diff) | |
| parent | 82cb2b30773e3ccbbd2ed4427d52a91862d4db6d (diff) | |
| download | linux-aaccdf9c93a00cc5eec6f9d97046b44643c60800.tar.gz linux-aaccdf9c93a00cc5eec6f9d97046b44643c60800.tar.bz2 linux-aaccdf9c93a00cc5eec6f9d97046b44643c60800.zip | |
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>
Diffstat (limited to 'tools/testing/selftests/bpf/cap_helpers.c')
| -rw-r--r-- | tools/testing/selftests/bpf/cap_helpers.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/cap_helpers.c b/tools/testing/selftests/bpf/cap_helpers.c new file mode 100644 index 000000000000..d5ac507401d7 --- /dev/null +++ b/tools/testing/selftests/bpf/cap_helpers.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "cap_helpers.h" + +/* Avoid including <sys/capability.h> from the libcap-devel package, + * so directly declare them here and use them from glibc. + */ +int capget(cap_user_header_t header, cap_user_data_t data); +int capset(cap_user_header_t header, const cap_user_data_t data); + +int cap_enable_effective(__u64 caps, __u64 *old_caps) +{ + struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3]; + struct __user_cap_header_struct hdr = { + .version = _LINUX_CAPABILITY_VERSION_3, + }; + __u32 cap0 = caps; + __u32 cap1 = caps >> 32; + int err; + + err = capget(&hdr, data); + if (err) + return err; + + if (old_caps) + *old_caps = (__u64)(data[1].effective) << 32 | data[0].effective; + + if ((data[0].effective & cap0) == cap0 && + (data[1].effective & cap1) == cap1) + return 0; + + data[0].effective |= cap0; + data[1].effective |= cap1; + err = capset(&hdr, data); + if (err) + return err; + + return 0; +} + +int cap_disable_effective(__u64 caps, __u64 *old_caps) +{ + struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3]; + struct __user_cap_header_struct hdr = { + .version = _LINUX_CAPABILITY_VERSION_3, + }; + __u32 cap0 = caps; + __u32 cap1 = caps >> 32; + int err; + + err = capget(&hdr, data); + if (err) + return err; + + if (old_caps) + *old_caps = (__u64)(data[1].effective) << 32 | data[0].effective; + + if (!(data[0].effective & cap0) && !(data[1].effective & cap1)) + return 0; + + data[0].effective &= ~cap0; + data[1].effective &= ~cap1; + err = capset(&hdr, data); + if (err) + return err; + + return 0; +} |
