Skip to content

Commit 90ad2b2

Browse files
Delyan KratunovKernel Patches Daemon
authored andcommitted
selftests/bpf: add tests for sleepable kprobes and uprobes
Add tests that ensure sleepable kprobe programs cannot attach. Also attach both sleepable and non-sleepable uprobe programs to the same location (i.e. same bpf_prog_array). Signed-off-by: Delyan Kratunov <delyank@fb.com>
1 parent 6e20ef0 commit 90ad2b2

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed

tools/testing/selftests/bpf/prog_tests/attach_probe.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ static void trigger_func2(void)
1717
asm volatile ("");
1818
}
1919

20+
/* attach point for byname sleepable uprobe */
21+
static void trigger_func3(void)
22+
{
23+
asm volatile ("");
24+
}
25+
26+
static char test_data[] = "test_data";
27+
2028
void test_attach_probe(void)
2129
{
2230
DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
@@ -27,6 +35,7 @@ void test_attach_probe(void)
2735
struct bpf_link *uprobe_err_link;
2836
bool legacy;
2937
char *mem;
38+
int kprobe_s_flags;
3039

3140
/* Check if new-style kprobe/uprobe API is supported.
3241
* Kernels that support new FD-based kprobe and uprobe BPF attachment
@@ -49,9 +58,18 @@ void test_attach_probe(void)
4958
if (!ASSERT_GE(ref_ctr_offset, 0, "ref_ctr_offset"))
5059
return;
5160

52-
skel = test_attach_probe__open_and_load();
61+
skel = test_attach_probe__open();
5362
if (!ASSERT_OK_PTR(skel, "skel_open"))
5463
return;
64+
65+
/* sleepable kprobe test case needs flags set before loading */
66+
kprobe_s_flags = bpf_program__flags(skel->progs.handle_kprobe_sleepable);
67+
if (!ASSERT_OK(bpf_program__set_flags(skel->progs.handle_kprobe_sleepable,
68+
kprobe_s_flags | BPF_F_SLEEPABLE), "kprobe_sleepable_flags"))
69+
goto cleanup;
70+
71+
if (!ASSERT_OK(test_attach_probe__load(skel), "skel_load"))
72+
goto cleanup;
5573
if (!ASSERT_OK_PTR(skel->bss, "check_bss"))
5674
goto cleanup;
5775

@@ -151,6 +169,30 @@ void test_attach_probe(void)
151169
if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname2, "attach_uretprobe_byname2"))
152170
goto cleanup;
153171

172+
/* sleepable kprobes should not attach successfully */
173+
skel->links.handle_kprobe_sleepable = bpf_program__attach(skel->progs.handle_kprobe_sleepable);
174+
if (!ASSERT_ERR_PTR(skel->links.handle_kprobe_sleepable, "attach_kprobe_sleepable"))
175+
goto cleanup;
176+
177+
/* test sleepable uprobe and uretprobe variants */
178+
skel->links.handle_uprobe_byname3_sleepable = bpf_program__attach(skel->progs.handle_uprobe_byname3_sleepable);
179+
if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname3_sleepable, "attach_uprobe_byname3_sleepable"))
180+
goto cleanup;
181+
182+
skel->links.handle_uprobe_byname3 = bpf_program__attach(skel->progs.handle_uprobe_byname3);
183+
if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname3, "attach_uprobe_byname3"))
184+
goto cleanup;
185+
186+
skel->links.handle_uretprobe_byname3_sleepable = bpf_program__attach(skel->progs.handle_uretprobe_byname3_sleepable);
187+
if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname3_sleepable, "attach_uretprobe_byname3_sleepable"))
188+
goto cleanup;
189+
190+
skel->links.handle_uretprobe_byname3 = bpf_program__attach(skel->progs.handle_uretprobe_byname3);
191+
if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname3, "attach_uretprobe_byname3"))
192+
goto cleanup;
193+
194+
skel->bss->user_ptr = test_data;
195+
154196
/* trigger & validate kprobe && kretprobe */
155197
usleep(1);
156198

@@ -164,6 +206,9 @@ void test_attach_probe(void)
164206
/* trigger & validate uprobe attached by name */
165207
trigger_func2();
166208

209+
/* trigger & validate sleepable uprobe attached by name */
210+
trigger_func3();
211+
167212
ASSERT_EQ(skel->bss->kprobe_res, 1, "check_kprobe_res");
168213
ASSERT_EQ(skel->bss->kprobe2_res, 11, "check_kprobe_auto_res");
169214
ASSERT_EQ(skel->bss->kretprobe_res, 2, "check_kretprobe_res");
@@ -174,6 +219,10 @@ void test_attach_probe(void)
174219
ASSERT_EQ(skel->bss->uretprobe_byname_res, 6, "check_uretprobe_byname_res");
175220
ASSERT_EQ(skel->bss->uprobe_byname2_res, 7, "check_uprobe_byname2_res");
176221
ASSERT_EQ(skel->bss->uretprobe_byname2_res, 8, "check_uretprobe_byname2_res");
222+
ASSERT_EQ(skel->bss->uprobe_byname3_sleepable_res, 9, "check_uprobe_byname3_sleepable_res");
223+
ASSERT_EQ(skel->bss->uprobe_byname3_res, 10, "check_uprobe_byname3_res");
224+
ASSERT_EQ(skel->bss->uretprobe_byname3_sleepable_res, 11, "check_uretprobe_byname3_sleepable_res");
225+
ASSERT_EQ(skel->bss->uretprobe_byname3_res, 12, "check_uretprobe_byname3_res");
177226

178227
cleanup:
179228
test_attach_probe__destroy(skel);

tools/testing/selftests/bpf/progs/test_attach_probe.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <linux/bpf.h>
66
#include <bpf/bpf_helpers.h>
77
#include <bpf/bpf_tracing.h>
8+
#include <stdbool.h>
89
#include "bpf_misc.h"
910

1011
int kprobe_res = 0;
@@ -17,6 +18,11 @@ int uprobe_byname_res = 0;
1718
int uretprobe_byname_res = 0;
1819
int uprobe_byname2_res = 0;
1920
int uretprobe_byname2_res = 0;
21+
int uprobe_byname3_sleepable_res = 0;
22+
int uprobe_byname3_res = 0;
23+
int uretprobe_byname3_sleepable_res = 0;
24+
int uretprobe_byname3_res = 0;
25+
void *user_ptr = 0;
2026

2127
SEC("kprobe")
2228
int handle_kprobe(struct pt_regs *ctx)
@@ -32,6 +38,17 @@ int BPF_KPROBE(handle_kprobe_auto)
3238
return 0;
3339
}
3440

41+
/**
42+
* This program will be manually made sleepable on the userspace side
43+
* and should thus be unattachable.
44+
*/
45+
SEC("kprobe/" SYS_PREFIX "sys_nanosleep")
46+
int handle_kprobe_sleepable(struct pt_regs *ctx)
47+
{
48+
kprobe_res = 2;
49+
return 0;
50+
}
51+
3552
SEC("kretprobe")
3653
int handle_kretprobe(struct pt_regs *ctx)
3754
{
@@ -93,4 +110,45 @@ int handle_uretprobe_byname2(struct pt_regs *ctx)
93110
return 0;
94111
}
95112

113+
static inline bool verify_sleepable_user_copy() {
114+
char data[9];
115+
bpf_copy_from_user(data, sizeof(data), user_ptr);
116+
return bpf_strncmp(data, sizeof(data), "test_data") == 0;
117+
}
118+
119+
SEC("uprobe.s//proc/self/exe:trigger_func3")
120+
int handle_uprobe_byname3_sleepable(struct pt_regs *ctx)
121+
{
122+
if (verify_sleepable_user_copy())
123+
uprobe_byname3_sleepable_res = 9;
124+
return 0;
125+
}
126+
127+
/**
128+
* same target as the uprobe.s above to force sleepable and non-sleepable
129+
* programs in the same bpf_prog_array
130+
*/
131+
SEC("uprobe//proc/self/exe:trigger_func3")
132+
int handle_uprobe_byname3(struct pt_regs *ctx)
133+
{
134+
uprobe_byname3_res = 10;
135+
return 0;
136+
}
137+
138+
SEC("uretprobe.s//proc/self/exe:trigger_func3")
139+
int handle_uretprobe_byname3_sleepable(struct pt_regs *ctx)
140+
{
141+
if (verify_sleepable_user_copy())
142+
uretprobe_byname3_sleepable_res = 11;
143+
return 0;
144+
}
145+
146+
SEC("uretprobe//proc/self/exe:trigger_func3")
147+
int handle_uretprobe_byname3(struct pt_regs *ctx)
148+
{
149+
uretprobe_byname3_res = 12;
150+
return 0;
151+
}
152+
153+
96154
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)