summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/bpf/cap_helpers.c
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2022-03-16 15:07:49 -0700
committerAlexei Starovoitov <ast@kernel.org>2022-03-16 15:07:50 -0700
commitaaccdf9c93a00cc5eec6f9d97046b44643c60800 (patch)
tree687d9738a7fde05252f0f3d283692cba1c0af235 /tools/testing/selftests/bpf/cap_helpers.c
parent6585abea98ae5f750358a6427f2ddf7715393f69 (diff)
parent82cb2b30773e3ccbbd2ed4427d52a91862d4db6d (diff)
downloadlinux-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.c67
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;
+}