Skip to content

Commit f4b295a

Browse files
Yonghong SongAlexei Starovoitov
authored andcommitted
selftests/bpf: Add tracing prog private stack tests
Some private stack tests are added including: - main prog only with stack size greater than BPF_PSTACK_MIN_SIZE. - main prog only with stack size smaller than BPF_PSTACK_MIN_SIZE. - prog with one subprog having MAX_BPF_STACK stack size and another subprog having non-zero small stack size. - prog with callback function. - prog with exception in main prog or subprog. - prog with async callback without nesting - prog with async callback with possible nesting Signed-off-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 7d1cd70 commit f4b295a

File tree

2 files changed

+274
-0
lines changed

2 files changed

+274
-0
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include "verifier_or_jmp32_k.skel.h"
6262
#include "verifier_precision.skel.h"
6363
#include "verifier_prevent_map_lookup.skel.h"
64+
#include "verifier_private_stack.skel.h"
6465
#include "verifier_raw_stack.skel.h"
6566
#include "verifier_raw_tp_writable.skel.h"
6667
#include "verifier_reg_equal.skel.h"
@@ -188,6 +189,7 @@ void test_verifier_bpf_fastcall(void) { RUN(verifier_bpf_fastcall); }
188189
void test_verifier_or_jmp32_k(void) { RUN(verifier_or_jmp32_k); }
189190
void test_verifier_precision(void) { RUN(verifier_precision); }
190191
void test_verifier_prevent_map_lookup(void) { RUN(verifier_prevent_map_lookup); }
192+
void test_verifier_private_stack(void) { RUN(verifier_private_stack); }
191193
void test_verifier_raw_stack(void) { RUN(verifier_raw_stack); }
192194
void test_verifier_raw_tp_writable(void) { RUN(verifier_raw_tp_writable); }
193195
void test_verifier_reg_equal(void) { RUN(verifier_reg_equal); }
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <vmlinux.h>
4+
#include <bpf/bpf_helpers.h>
5+
#include "bpf_misc.h"
6+
#include "bpf_experimental.h"
7+
8+
/* From include/linux/filter.h */
9+
#define MAX_BPF_STACK 512
10+
11+
#if defined(__TARGET_ARCH_x86)
12+
13+
struct elem {
14+
struct bpf_timer t;
15+
char pad[256];
16+
};
17+
18+
struct {
19+
__uint(type, BPF_MAP_TYPE_ARRAY);
20+
__uint(max_entries, 1);
21+
__type(key, int);
22+
__type(value, struct elem);
23+
} array SEC(".maps");
24+
25+
SEC("kprobe")
26+
__description("Private stack, single prog")
27+
__success
28+
__arch_x86_64
29+
__jited(" movabsq $0x{{.*}}, %r9")
30+
__jited(" addq %gs:0x{{.*}}, %r9")
31+
__jited(" movl $0x2a, %edi")
32+
__jited(" movq %rdi, -0x100(%r9)")
33+
__naked void private_stack_single_prog(void)
34+
{
35+
asm volatile (" \
36+
r1 = 42; \
37+
*(u64 *)(r10 - 256) = r1; \
38+
r0 = 0; \
39+
exit; \
40+
" ::: __clobber_all);
41+
}
42+
43+
SEC("raw_tp")
44+
__description("No private stack")
45+
__success
46+
__arch_x86_64
47+
__jited(" subq $0x8, %rsp")
48+
__naked void no_private_stack_nested(void)
49+
{
50+
asm volatile (" \
51+
r1 = 42; \
52+
*(u64 *)(r10 - 8) = r1; \
53+
r0 = 0; \
54+
exit; \
55+
" ::: __clobber_all);
56+
}
57+
58+
__used
59+
__naked static void cumulative_stack_depth_subprog(void)
60+
{
61+
asm volatile (" \
62+
r1 = 41; \
63+
*(u64 *)(r10 - 32) = r1; \
64+
call %[bpf_get_smp_processor_id]; \
65+
exit; \
66+
" :
67+
: __imm(bpf_get_smp_processor_id)
68+
: __clobber_all);
69+
}
70+
71+
SEC("kprobe")
72+
__description("Private stack, subtree > MAX_BPF_STACK")
73+
__success
74+
__arch_x86_64
75+
/* private stack fp for the main prog */
76+
__jited(" movabsq $0x{{.*}}, %r9")
77+
__jited(" addq %gs:0x{{.*}}, %r9")
78+
__jited(" movl $0x2a, %edi")
79+
__jited(" movq %rdi, -0x200(%r9)")
80+
__jited(" pushq %r9")
81+
__jited(" callq 0x{{.*}}")
82+
__jited(" popq %r9")
83+
__jited(" xorl %eax, %eax")
84+
__naked void private_stack_nested_1(void)
85+
{
86+
asm volatile (" \
87+
r1 = 42; \
88+
*(u64 *)(r10 - %[max_bpf_stack]) = r1; \
89+
call cumulative_stack_depth_subprog; \
90+
r0 = 0; \
91+
exit; \
92+
" :
93+
: __imm_const(max_bpf_stack, MAX_BPF_STACK)
94+
: __clobber_all);
95+
}
96+
97+
__naked __noinline __used
98+
static unsigned long loop_callback(void)
99+
{
100+
asm volatile (" \
101+
call %[bpf_get_prandom_u32]; \
102+
r1 = 42; \
103+
*(u64 *)(r10 - 512) = r1; \
104+
call cumulative_stack_depth_subprog; \
105+
r0 = 0; \
106+
exit; \
107+
" :
108+
: __imm(bpf_get_prandom_u32)
109+
: __clobber_common);
110+
}
111+
112+
SEC("raw_tp")
113+
__description("Private stack, callback")
114+
__success
115+
__arch_x86_64
116+
/* for func loop_callback */
117+
__jited("func #1")
118+
__jited(" endbr64")
119+
__jited(" nopl (%rax,%rax)")
120+
__jited(" nopl (%rax)")
121+
__jited(" pushq %rbp")
122+
__jited(" movq %rsp, %rbp")
123+
__jited(" endbr64")
124+
__jited(" movabsq $0x{{.*}}, %r9")
125+
__jited(" addq %gs:0x{{.*}}, %r9")
126+
__jited(" pushq %r9")
127+
__jited(" callq")
128+
__jited(" popq %r9")
129+
__jited(" movl $0x2a, %edi")
130+
__jited(" movq %rdi, -0x200(%r9)")
131+
__jited(" pushq %r9")
132+
__jited(" callq")
133+
__jited(" popq %r9")
134+
__naked void private_stack_callback(void)
135+
{
136+
asm volatile (" \
137+
r1 = 1; \
138+
r2 = %[loop_callback]; \
139+
r3 = 0; \
140+
r4 = 0; \
141+
call %[bpf_loop]; \
142+
r0 = 0; \
143+
exit; \
144+
" :
145+
: __imm_ptr(loop_callback),
146+
__imm(bpf_loop)
147+
: __clobber_common);
148+
}
149+
150+
SEC("fentry/bpf_fentry_test9")
151+
__description("Private stack, exception in main prog")
152+
__success __retval(0)
153+
__arch_x86_64
154+
__jited(" pushq %r9")
155+
__jited(" callq")
156+
__jited(" popq %r9")
157+
int private_stack_exception_main_prog(void)
158+
{
159+
asm volatile (" \
160+
r1 = 42; \
161+
*(u64 *)(r10 - 512) = r1; \
162+
" ::: __clobber_common);
163+
164+
bpf_throw(0);
165+
return 0;
166+
}
167+
168+
__used static int subprog_exception(void)
169+
{
170+
bpf_throw(0);
171+
return 0;
172+
}
173+
174+
SEC("fentry/bpf_fentry_test9")
175+
__description("Private stack, exception in subprog")
176+
__success __retval(0)
177+
__arch_x86_64
178+
__jited(" movq %rdi, -0x200(%r9)")
179+
__jited(" pushq %r9")
180+
__jited(" callq")
181+
__jited(" popq %r9")
182+
int private_stack_exception_sub_prog(void)
183+
{
184+
asm volatile (" \
185+
r1 = 42; \
186+
*(u64 *)(r10 - 512) = r1; \
187+
call subprog_exception; \
188+
" ::: __clobber_common);
189+
190+
return 0;
191+
}
192+
193+
int glob;
194+
__noinline static void subprog2(int *val)
195+
{
196+
glob += val[0] * 2;
197+
}
198+
199+
__noinline static void subprog1(int *val)
200+
{
201+
int tmp[64] = {};
202+
203+
tmp[0] = *val;
204+
subprog2(tmp);
205+
}
206+
207+
__noinline static int timer_cb1(void *map, int *key, struct bpf_timer *timer)
208+
{
209+
subprog1(key);
210+
return 0;
211+
}
212+
213+
__noinline static int timer_cb2(void *map, int *key, struct bpf_timer *timer)
214+
{
215+
return 0;
216+
}
217+
218+
SEC("fentry/bpf_fentry_test9")
219+
__description("Private stack, async callback, not nested")
220+
__success __retval(0)
221+
__arch_x86_64
222+
__jited(" movabsq $0x{{.*}}, %r9")
223+
int private_stack_async_callback_1(void)
224+
{
225+
struct bpf_timer *arr_timer;
226+
int array_key = 0;
227+
228+
arr_timer = bpf_map_lookup_elem(&array, &array_key);
229+
if (!arr_timer)
230+
return 0;
231+
232+
bpf_timer_init(arr_timer, &array, 1);
233+
bpf_timer_set_callback(arr_timer, timer_cb2);
234+
bpf_timer_start(arr_timer, 0, 0);
235+
subprog1(&array_key);
236+
return 0;
237+
}
238+
239+
SEC("fentry/bpf_fentry_test9")
240+
__description("Private stack, async callback, potential nesting")
241+
__success __retval(0)
242+
__arch_x86_64
243+
__jited(" subq $0x100, %rsp")
244+
int private_stack_async_callback_2(void)
245+
{
246+
struct bpf_timer *arr_timer;
247+
int array_key = 0;
248+
249+
arr_timer = bpf_map_lookup_elem(&array, &array_key);
250+
if (!arr_timer)
251+
return 0;
252+
253+
bpf_timer_init(arr_timer, &array, 1);
254+
bpf_timer_set_callback(arr_timer, timer_cb1);
255+
bpf_timer_start(arr_timer, 0, 0);
256+
subprog1(&array_key);
257+
return 0;
258+
}
259+
260+
#else
261+
262+
SEC("kprobe")
263+
__description("private stack is not supported, use a dummy test")
264+
__success
265+
int dummy_test(void)
266+
{
267+
return 0;
268+
}
269+
270+
#endif
271+
272+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)