mirror of
git://git.openwrt.org/openwrt/openwrt.git
synced 2024-12-20 22:01:38 +00:00
04981c716a
Recent libcap versions (>= 2.60) cause problems with BPF kselftests, so backport an upstream patch that replaces libcap and drops the dependency. Signed-off-by: Tony Ambardar <itugrok@yahoo.com>
189 lines
6.1 KiB
Diff
189 lines
6.1 KiB
Diff
From 847a6b7ee906be874f0cae279c8de902a7d3f092 Mon Sep 17 00:00:00 2001
|
|
From: Martin KaFai Lau <kafai@fb.com>
|
|
Date: Wed, 16 Mar 2022 10:38:29 -0700
|
|
Subject: [PATCH 2/3] bpf: selftests: Remove libcap usage from test_verifier
|
|
|
|
This patch removes the libcap usage from test_verifier.
|
|
The cap_*_effective() helpers added in the earlier patch are
|
|
used instead.
|
|
|
|
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
|
|
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
|
|
Acked-by: John Fastabend <john.fastabend@gmail.com>
|
|
Link: https://lore.kernel.org/bpf/20220316173829.2038682-1-kafai@fb.com
|
|
---
|
|
tools/testing/selftests/bpf/Makefile | 31 +++++---
|
|
tools/testing/selftests/bpf/test_verifier.c | 88 ++++++---------------
|
|
2 files changed, 46 insertions(+), 73 deletions(-)
|
|
|
|
--- a/tools/testing/selftests/bpf/Makefile
|
|
+++ b/tools/testing/selftests/bpf/Makefile
|
|
@@ -189,16 +189,27 @@ TEST_GEN_PROGS_EXTENDED += $(DEFAULT_BPF
|
|
|
|
$(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED): $(OUTPUT)/test_stub.o $(BPFOBJ)
|
|
|
|
-$(OUTPUT)/test_dev_cgroup: cgroup_helpers.c
|
|
-$(OUTPUT)/test_skb_cgroup_id_user: cgroup_helpers.c
|
|
-$(OUTPUT)/test_sock: cgroup_helpers.c
|
|
-$(OUTPUT)/test_sock_addr: cgroup_helpers.c
|
|
-$(OUTPUT)/test_sockmap: cgroup_helpers.c
|
|
-$(OUTPUT)/test_tcpnotify_user: cgroup_helpers.c trace_helpers.c
|
|
-$(OUTPUT)/get_cgroup_id_user: cgroup_helpers.c
|
|
-$(OUTPUT)/test_cgroup_storage: cgroup_helpers.c
|
|
-$(OUTPUT)/test_sock_fields: cgroup_helpers.c
|
|
-$(OUTPUT)/test_sysctl: cgroup_helpers.c
|
|
+CGROUP_HELPERS := $(OUTPUT)/cgroup_helpers.o
|
|
+TESTING_HELPERS := $(OUTPUT)/testing_helpers.o
|
|
+TRACE_HELPERS := $(OUTPUT)/trace_helpers.o
|
|
+CAP_HELPERS := $(OUTPUT)/cap_helpers.o
|
|
+
|
|
+$(OUTPUT)/test_dev_cgroup: $(CGROUP_HELPERS) $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_skb_cgroup_id_user: $(CGROUP_HELPERS) $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_sock: $(CGROUP_HELPERS) $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_sock_addr: $(CGROUP_HELPERS) $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_sockmap: $(CGROUP_HELPERS) $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_tcpnotify_user: $(CGROUP_HELPERS) $(TESTING_HELPERS) $(TRACE_HELPERS)
|
|
+$(OUTPUT)/get_cgroup_id_user: $(CGROUP_HELPERS) $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_cgroup_storage: $(CGROUP_HELPERS) $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_sock_fields: $(CGROUP_HELPERS) $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_sysctl: $(CGROUP_HELPERS) $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_tag: $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_lirc_mode2_user: $(TESTING_HELPERS)
|
|
+$(OUTPUT)/xdping: $(TESTING_HELPERS)
|
|
+$(OUTPUT)/flow_dissector_load: $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_maps: $(TESTING_HELPERS)
|
|
+$(OUTPUT)/test_verifier: $(TESTING_HELPERS) $(CAP_HELPERS)
|
|
|
|
BPFTOOL ?= $(DEFAULT_BPFTOOL)
|
|
$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
|
|
--- a/tools/testing/selftests/bpf/test_verifier.c
|
|
+++ b/tools/testing/selftests/bpf/test_verifier.c
|
|
@@ -22,8 +22,6 @@
|
|
#include <limits.h>
|
|
#include <assert.h>
|
|
|
|
-#include <sys/capability.h>
|
|
-
|
|
#include <linux/unistd.h>
|
|
#include <linux/filter.h>
|
|
#include <linux/bpf_perf_event.h>
|
|
@@ -43,6 +41,7 @@
|
|
# endif
|
|
#endif
|
|
#include "bpf_rlimit.h"
|
|
+#include "cap_helpers.h"
|
|
#include "bpf_rand.h"
|
|
#include "bpf_util.h"
|
|
#include "test_btf.h"
|
|
@@ -59,6 +58,10 @@
|
|
#define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0)
|
|
#define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1)
|
|
|
|
+/* need CAP_BPF, CAP_NET_ADMIN, CAP_PERFMON to load progs */
|
|
+#define ADMIN_CAPS (1ULL << CAP_NET_ADMIN | \
|
|
+ 1ULL << CAP_PERFMON | \
|
|
+ 1ULL << CAP_BPF)
|
|
#define UNPRIV_SYSCTL "kernel/unprivileged_bpf_disabled"
|
|
static bool unpriv_disabled = false;
|
|
static int skips;
|
|
@@ -940,47 +943,19 @@ struct libcap {
|
|
|
|
static int set_admin(bool admin)
|
|
{
|
|
- cap_t caps;
|
|
- /* need CAP_BPF, CAP_NET_ADMIN, CAP_PERFMON to load progs */
|
|
- const cap_value_t cap_net_admin = CAP_NET_ADMIN;
|
|
- const cap_value_t cap_sys_admin = CAP_SYS_ADMIN;
|
|
- struct libcap *cap;
|
|
- int ret = -1;
|
|
-
|
|
- caps = cap_get_proc();
|
|
- if (!caps) {
|
|
- perror("cap_get_proc");
|
|
- return -1;
|
|
- }
|
|
- cap = (struct libcap *)caps;
|
|
- if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_sys_admin, CAP_CLEAR)) {
|
|
- perror("cap_set_flag clear admin");
|
|
- goto out;
|
|
- }
|
|
- if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_net_admin,
|
|
- admin ? CAP_SET : CAP_CLEAR)) {
|
|
- perror("cap_set_flag set_or_clear net");
|
|
- goto out;
|
|
- }
|
|
- /* libcap is likely old and simply ignores CAP_BPF and CAP_PERFMON,
|
|
- * so update effective bits manually
|
|
- */
|
|
+ int err;
|
|
+
|
|
if (admin) {
|
|
- cap->data[1].effective |= 1 << (38 /* CAP_PERFMON */ - 32);
|
|
- cap->data[1].effective |= 1 << (39 /* CAP_BPF */ - 32);
|
|
+ err = cap_enable_effective(ADMIN_CAPS, NULL);
|
|
+ if (err)
|
|
+ perror("cap_enable_effective(ADMIN_CAPS)");
|
|
} else {
|
|
- cap->data[1].effective &= ~(1 << (38 - 32));
|
|
- cap->data[1].effective &= ~(1 << (39 - 32));
|
|
+ err = cap_disable_effective(ADMIN_CAPS, NULL);
|
|
+ if (err)
|
|
+ perror("cap_disable_effective(ADMIN_CAPS)");
|
|
}
|
|
- if (cap_set_proc(caps)) {
|
|
- perror("cap_set_proc");
|
|
- goto out;
|
|
- }
|
|
- ret = 0;
|
|
-out:
|
|
- if (cap_free(caps))
|
|
- perror("cap_free");
|
|
- return ret;
|
|
+
|
|
+ return err;
|
|
}
|
|
|
|
static int do_prog_test_run(int fd_prog, bool unpriv, uint32_t expected_val,
|
|
@@ -1246,31 +1221,18 @@ fail_log:
|
|
|
|
static bool is_admin(void)
|
|
{
|
|
- cap_flag_value_t net_priv = CAP_CLEAR;
|
|
- bool perfmon_priv = false;
|
|
- bool bpf_priv = false;
|
|
- struct libcap *cap;
|
|
- cap_t caps;
|
|
-
|
|
-#ifdef CAP_IS_SUPPORTED
|
|
- if (!CAP_IS_SUPPORTED(CAP_SETFCAP)) {
|
|
- perror("cap_get_flag");
|
|
- return false;
|
|
- }
|
|
-#endif
|
|
- caps = cap_get_proc();
|
|
- if (!caps) {
|
|
- perror("cap_get_proc");
|
|
+ __u64 caps;
|
|
+
|
|
+ /* The test checks for finer cap as CAP_NET_ADMIN,
|
|
+ * CAP_PERFMON, and CAP_BPF instead of CAP_SYS_ADMIN.
|
|
+ * Thus, disable CAP_SYS_ADMIN at the beginning.
|
|
+ */
|
|
+ if (cap_disable_effective(1ULL << CAP_SYS_ADMIN, &caps)) {
|
|
+ perror("cap_disable_effective(CAP_SYS_ADMIN)");
|
|
return false;
|
|
}
|
|
- cap = (struct libcap *)caps;
|
|
- bpf_priv = cap->data[1].effective & (1 << (39/* CAP_BPF */ - 32));
|
|
- perfmon_priv = cap->data[1].effective & (1 << (38/* CAP_PERFMON */ - 32));
|
|
- if (cap_get_flag(caps, CAP_NET_ADMIN, CAP_EFFECTIVE, &net_priv))
|
|
- perror("cap_get_flag NET");
|
|
- if (cap_free(caps))
|
|
- perror("cap_free");
|
|
- return bpf_priv && perfmon_priv && net_priv == CAP_SET;
|
|
+
|
|
+ return (caps & ADMIN_CAPS) == ADMIN_CAPS;
|
|
}
|
|
|
|
static void get_unpriv_disabled()
|