Skip to content

Commit c329fbe

Browse files
Lin YikaiKernel Patches Daemon
Lin Yikai
authored and
Kernel Patches Daemon
committed
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 <[email protected]>
1 parent 84c6119 commit c329fbe

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

tools/testing/selftests/bpf/Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ NON_CHECK_FEAT_TARGETS := clean docs-clean
183183
CHECK_FEAT := $(filter-out $(NON_CHECK_FEAT_TARGETS),$(or $(MAKECMDGOALS), "none"))
184184
ifneq ($(CHECK_FEAT),)
185185
FEATURE_USER := .selftests
186-
FEATURE_TESTS := llvm
186+
FEATURE_TESTS := llvm libcap
187187
FEATURE_DISPLAY := $(FEATURE_TESTS)
188188

189189
# Makefile.feature expects OUTPUT to end with a slash
@@ -208,6 +208,11 @@ ifeq ($(feature-llvm),1)
208208
LLVM_LDFLAGS += $(shell $(LLVM_CONFIG) --ldflags)
209209
endif
210210

211+
ifeq ($(feature-libcap), 1)
212+
CFLAGS += -DHAVE_LIBCAP_SUPPORT
213+
LDLIBS += -lcap
214+
endif
215+
211216
SCRATCH_DIR := $(OUTPUT)/tools
212217
BUILD_DIR := $(SCRATCH_DIR)/build
213218
INCLUDE_DIR := $(SCRATCH_DIR)/include

tools/testing/selftests/bpf/trace_helpers.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
#include <linux/limits.h>
1818
#include <libelf.h>
1919
#include <gelf.h>
20+
#include <stdbool.h>
21+
#include <linux/capability.h>
22+
#include <linux/compiler.h>
23+
#include <sys/types.h>
2024
#include "bpf/libbpf_internal.h"
2125

2226
#define TRACEFS_PIPE "/sys/kernel/tracing/trace_pipe"
@@ -31,6 +35,55 @@ struct ksyms {
3135
static struct ksyms *ksyms;
3236
static pthread_mutex_t ksyms_mutex = PTHREAD_MUTEX_INITIALIZER;
3337

38+
#ifdef HAVE_LIBCAP_SUPPORT
39+
#include <sys/capability.h>
40+
static bool bpf_cap__capable(cap_value_t cap)
41+
{
42+
cap_flag_value_t val;
43+
cap_t caps = cap_get_proc();
44+
45+
if (!caps)
46+
return false;
47+
48+
if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &val) != 0)
49+
val = CAP_CLEAR;
50+
51+
if (cap_free(caps) != 0)
52+
return false;
53+
54+
return val == CAP_SET;
55+
}
56+
#else
57+
static inline bool bpf_cap__capable(int cap __maybe_unused)
58+
{
59+
return geteuid() == 0;
60+
}
61+
#endif /* HAVE_LIBCAP_SUPPORT */
62+
63+
/* For older systems */
64+
#ifndef CAP_SYSLOG
65+
#define CAP_SYSLOG 34
66+
#endif
67+
68+
static bool ksyms__kptr_restrict(void)
69+
{
70+
bool value = false;
71+
FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r");
72+
73+
if (fp != NULL) {
74+
char line[8];
75+
76+
if (fgets(line, sizeof(line), fp) != NULL)
77+
value = bpf_cap__capable(CAP_SYSLOG) ?
78+
(atoi(line) >= 2) :
79+
(atoi(line) != 0);
80+
81+
fclose(fp);
82+
}
83+
84+
return value;
85+
}
86+
3487
static int ksyms__add_symbol(struct ksyms *ksyms, const char *name,
3588
unsigned long addr)
3689
{
@@ -72,6 +125,11 @@ static struct ksyms *load_kallsyms_local_common(ksym_cmp_t cmp_cb)
72125
int ret;
73126
struct ksyms *ksyms;
74127

128+
if (ksyms__kptr_restrict()) {
129+
printf("ksyms restricted, please check /proc/sys/kernel/kptr_restrict\n");
130+
return NULL;
131+
}
132+
75133
f = fopen("/proc/kallsyms", "r");
76134
if (!f)
77135
return NULL;
@@ -218,6 +276,11 @@ int kallsyms_find(const char *sym, unsigned long long *addr)
218276
int err = 0;
219277
FILE *f;
220278

279+
if (ksyms__kptr_restrict()) {
280+
printf("ksyms restricted, please check /proc/sys/kernel/kptr_restrict\n");
281+
return -EINVAL;
282+
}
283+
221284
f = fopen("/proc/kallsyms", "r");
222285
if (!f)
223286
return -EINVAL;

0 commit comments

Comments
 (0)