[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240914092426.431066-1-yikai.lin@vivo.com>
Date: Sat, 14 Sep 2024 17:24:26 +0800
From: Lin Yikai <yikai.lin@...o.com>
To: bpf@...r.kernel.org
Cc: opensource.kernel@...o.com,
yikai.lin@...o.com,
Andrii Nakryiko <andrii@...nel.org>,
Eduard Zingerman <eddyz87@...il.com>,
Mykola Lysenko <mykolal@...com>,
Alexei Starovoitov <ast@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
Martin KaFai Lau <martin.lau@...ux.dev>,
Song Liu <song@...nel.org>,
Yonghong Song <yonghong.song@...ux.dev>,
John Fastabend <john.fastabend@...il.com>,
KP Singh <kpsingh@...nel.org>,
Stanislav Fomichev <sdf@...ichev.me>,
Hao Luo <haoluo@...gle.com>,
Jiri Olsa <jolsa@...nel.org>,
Shuah Khan <shuah@...nel.org>,
Nathan Chancellor <nathan@...nel.org>,
Nick Desaulniers <ndesaulniers@...gle.com>,
Bill Wendling <morbo@...gle.com>,
Justin Stitt <justinstitt@...gle.com>,
linux-kselftest@...r.kernel.org,
linux-kernel@...r.kernel.org,
llvm@...ts.linux.dev
Subject: [PATCH bpf-next v1] selftests/bpf:Enhance bpf ability to detect ksym read error by libcap
Ksym addr access is restricted
by ``kptr_restrict``(/proc/sys/kernel/kptr_restrict).
On some OS systems(like Android),
ksym addr access is not accessed because ``kptr_restrict=2`.
And it took me a long time to find the root case.
-When ``kptr_restrict==0``, addr is accessed.
# echo 0 > /proc/sys/kernel/kptr_restrict
# cat /proc/kallsyms | grep bpf_link_fops
ffffffd6bfd3fb60 d bpf_link_fops
-When ``kptr_restrict==2``, addr is replaced by ZERO.
# echo 2 > /proc/sys/kernel/kptr_restrict
# cat /proc/kallsyms | grep bpf_link_fops
0000000000000000 d bpf_link_fops
-When ``kptr_restrict==1``, addr is accessed for user having CAP_SYSLOG.
So we should perform a check to remind users for these conditions
before reading /proc/kallsyms.
[before]:
# echo 2 > /proc/sys/kernel/kptr_restrict
# ./test_progs -t ksyms
#133 ksyms:FAIL
[after]:
# echo 2 > /proc/sys/kernel/kptr_restrict
# ./test_progs -t ksym
ksyms restricted, please check /proc/sys/kernel/kptr_restrict
#133 ksyms:FAIL
Signed-off-by: Lin Yikai <yikai.lin@...o.com>
---
tools/testing/selftests/bpf/Makefile | 7 ++-
tools/testing/selftests/bpf/trace_helpers.c | 63 +++++++++++++++++++++
2 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 04716a5e43f1..369c5ad8fc4a 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -183,7 +183,7 @@ NON_CHECK_FEAT_TARGETS := clean docs-clean
CHECK_FEAT := $(filter-out $(NON_CHECK_FEAT_TARGETS),$(or $(MAKECMDGOALS), "none"))
ifneq ($(CHECK_FEAT),)
FEATURE_USER := .selftests
-FEATURE_TESTS := llvm
+FEATURE_TESTS := llvm libcap
FEATURE_DISPLAY := $(FEATURE_TESTS)
# Makefile.feature expects OUTPUT to end with a slash
@@ -208,6 +208,11 @@ ifeq ($(feature-llvm),1)
LLVM_LDFLAGS += $(shell $(LLVM_CONFIG) --ldflags)
endif
+ifeq ($(feature-libcap), 1)
+ CFLAGS += -DHAVE_LIBCAP_SUPPORT
+ LDLIBS += -lcap
+endif
+
SCRATCH_DIR := $(OUTPUT)/tools
BUILD_DIR := $(SCRATCH_DIR)/build
INCLUDE_DIR := $(SCRATCH_DIR)/include
diff --git a/tools/testing/selftests/bpf/trace_helpers.c b/tools/testing/selftests/bpf/trace_helpers.c
index 2d742fdac6b9..8d2f951464ff 100644
--- a/tools/testing/selftests/bpf/trace_helpers.c
+++ b/tools/testing/selftests/bpf/trace_helpers.c
@@ -17,6 +17,10 @@
#include <linux/limits.h>
#include <libelf.h>
#include <gelf.h>
+#include <stdbool.h>
+#include <linux/capability.h>
+#include <linux/compiler.h>
+#include <sys/types.h>
#include "bpf/libbpf_internal.h"
#define TRACEFS_PIPE "/sys/kernel/tracing/trace_pipe"
@@ -31,6 +35,55 @@ struct ksyms {
static struct ksyms *ksyms;
static pthread_mutex_t ksyms_mutex = PTHREAD_MUTEX_INITIALIZER;
+#ifdef HAVE_LIBCAP_SUPPORT
+#include <sys/capability.h>
+static bool bpf_cap__capable(cap_value_t cap)
+{
+ cap_flag_value_t val;
+ cap_t caps = cap_get_proc();
+
+ if (!caps)
+ return false;
+
+ if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &val) != 0)
+ val = CAP_CLEAR;
+
+ if (cap_free(caps) != 0)
+ return false;
+
+ return val == CAP_SET;
+}
+#else
+static inline bool bpf_cap__capable(int cap __maybe_unused)
+{
+ return geteuid() == 0;
+}
+#endif /* HAVE_LIBCAP_SUPPORT */
+
+/* For older systems */
+#ifndef CAP_SYSLOG
+#define CAP_SYSLOG 34
+#endif
+
+static bool ksyms__kptr_restrict(void)
+{
+ bool value = false;
+ FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r");
+
+ if (fp != NULL) {
+ char line[8];
+
+ if (fgets(line, sizeof(line), fp) != NULL)
+ value = bpf_cap__capable(CAP_SYSLOG) ?
+ (atoi(line) >= 2) :
+ (atoi(line) != 0);
+
+ fclose(fp);
+ }
+
+ return value;
+}
+
static int ksyms__add_symbol(struct ksyms *ksyms, const char *name,
unsigned long addr)
{
@@ -72,6 +125,11 @@ static struct ksyms *load_kallsyms_local_common(ksym_cmp_t cmp_cb)
int ret;
struct ksyms *ksyms;
+ if (ksyms__kptr_restrict()) {
+ printf("ksyms restricted, please check /proc/sys/kernel/kptr_restrict\n");
+ return NULL;
+ }
+
f = fopen("/proc/kallsyms", "r");
if (!f)
return NULL;
@@ -218,6 +276,11 @@ int kallsyms_find(const char *sym, unsigned long long *addr)
int err = 0;
FILE *f;
+ if (ksyms__kptr_restrict()) {
+ printf("ksyms restricted, please check /proc/sys/kernel/kptr_restrict\n");
+ return -EINVAL;
+ }
+
f = fopen("/proc/kallsyms", "r");
if (!f)
return -EINVAL;
--
2.34.1
Powered by blists - more mailing lists