Skip to content

Commit b427ca5

Browse files
eddyz87Alexei Starovoitov
authored andcommitted
selftests/bpf: verifier/lwt converted to inline assembly
Test verifier/lwt automatically converted to use inline assembly. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20230421174234.2391278-11-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent a6fc14d commit b427ca5

3 files changed

Lines changed: 236 additions & 189 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "verifier_ld_ind.skel.h"
3434
#include "verifier_leak_ptr.skel.h"
3535
#include "verifier_loops1.skel.h"
36+
#include "verifier_lwt.skel.h"
3637
#include "verifier_map_ptr.skel.h"
3738
#include "verifier_map_ret_val.skel.h"
3839
#include "verifier_masking.skel.h"
@@ -117,6 +118,7 @@ void test_verifier_jeq_infer_not_null(void) { RUN(verifier_jeq_infer_not_null)
117118
void test_verifier_ld_ind(void) { RUN(verifier_ld_ind); }
118119
void test_verifier_leak_ptr(void) { RUN(verifier_leak_ptr); }
119120
void test_verifier_loops1(void) { RUN(verifier_loops1); }
121+
void test_verifier_lwt(void) { RUN(verifier_lwt); }
120122
void test_verifier_map_ptr(void) { RUN(verifier_map_ptr); }
121123
void test_verifier_map_ret_val(void) { RUN(verifier_map_ret_val); }
122124
void test_verifier_masking(void) { RUN(verifier_masking); }
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Converted from tools/testing/selftests/bpf/verifier/lwt.c */
3+
4+
#include <linux/bpf.h>
5+
#include <bpf/bpf_helpers.h>
6+
#include "bpf_misc.h"
7+
8+
SEC("lwt_in")
9+
__description("invalid direct packet write for LWT_IN")
10+
__failure __msg("cannot write into packet")
11+
__naked void packet_write_for_lwt_in(void)
12+
{
13+
asm volatile (" \
14+
r2 = *(u32*)(r1 + %[__sk_buff_data]); \
15+
r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \
16+
r0 = r2; \
17+
r0 += 8; \
18+
if r0 > r3 goto l0_%=; \
19+
*(u8*)(r2 + 0) = r2; \
20+
l0_%=: r0 = 0; \
21+
exit; \
22+
" :
23+
: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
24+
__imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
25+
: __clobber_all);
26+
}
27+
28+
SEC("lwt_out")
29+
__description("invalid direct packet write for LWT_OUT")
30+
__failure __msg("cannot write into packet")
31+
__naked void packet_write_for_lwt_out(void)
32+
{
33+
asm volatile (" \
34+
r2 = *(u32*)(r1 + %[__sk_buff_data]); \
35+
r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \
36+
r0 = r2; \
37+
r0 += 8; \
38+
if r0 > r3 goto l0_%=; \
39+
*(u8*)(r2 + 0) = r2; \
40+
l0_%=: r0 = 0; \
41+
exit; \
42+
" :
43+
: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
44+
__imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
45+
: __clobber_all);
46+
}
47+
48+
SEC("lwt_xmit")
49+
__description("direct packet write for LWT_XMIT")
50+
__success __retval(0)
51+
__naked void packet_write_for_lwt_xmit(void)
52+
{
53+
asm volatile (" \
54+
r2 = *(u32*)(r1 + %[__sk_buff_data]); \
55+
r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \
56+
r0 = r2; \
57+
r0 += 8; \
58+
if r0 > r3 goto l0_%=; \
59+
*(u8*)(r2 + 0) = r2; \
60+
l0_%=: r0 = 0; \
61+
exit; \
62+
" :
63+
: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
64+
__imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
65+
: __clobber_all);
66+
}
67+
68+
SEC("lwt_in")
69+
__description("direct packet read for LWT_IN")
70+
__success __retval(0)
71+
__naked void packet_read_for_lwt_in(void)
72+
{
73+
asm volatile (" \
74+
r2 = *(u32*)(r1 + %[__sk_buff_data]); \
75+
r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \
76+
r0 = r2; \
77+
r0 += 8; \
78+
if r0 > r3 goto l0_%=; \
79+
r0 = *(u8*)(r2 + 0); \
80+
l0_%=: r0 = 0; \
81+
exit; \
82+
" :
83+
: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
84+
__imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
85+
: __clobber_all);
86+
}
87+
88+
SEC("lwt_out")
89+
__description("direct packet read for LWT_OUT")
90+
__success __retval(0)
91+
__naked void packet_read_for_lwt_out(void)
92+
{
93+
asm volatile (" \
94+
r2 = *(u32*)(r1 + %[__sk_buff_data]); \
95+
r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \
96+
r0 = r2; \
97+
r0 += 8; \
98+
if r0 > r3 goto l0_%=; \
99+
r0 = *(u8*)(r2 + 0); \
100+
l0_%=: r0 = 0; \
101+
exit; \
102+
" :
103+
: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
104+
__imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
105+
: __clobber_all);
106+
}
107+
108+
SEC("lwt_xmit")
109+
__description("direct packet read for LWT_XMIT")
110+
__success __retval(0)
111+
__naked void packet_read_for_lwt_xmit(void)
112+
{
113+
asm volatile (" \
114+
r2 = *(u32*)(r1 + %[__sk_buff_data]); \
115+
r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \
116+
r0 = r2; \
117+
r0 += 8; \
118+
if r0 > r3 goto l0_%=; \
119+
r0 = *(u8*)(r2 + 0); \
120+
l0_%=: r0 = 0; \
121+
exit; \
122+
" :
123+
: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
124+
__imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
125+
: __clobber_all);
126+
}
127+
128+
SEC("lwt_xmit")
129+
__description("overlapping checks for direct packet access")
130+
__success __retval(0)
131+
__naked void checks_for_direct_packet_access(void)
132+
{
133+
asm volatile (" \
134+
r2 = *(u32*)(r1 + %[__sk_buff_data]); \
135+
r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \
136+
r0 = r2; \
137+
r0 += 8; \
138+
if r0 > r3 goto l0_%=; \
139+
r1 = r2; \
140+
r1 += 6; \
141+
if r1 > r3 goto l0_%=; \
142+
r0 = *(u16*)(r2 + 6); \
143+
l0_%=: r0 = 0; \
144+
exit; \
145+
" :
146+
: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
147+
__imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
148+
: __clobber_all);
149+
}
150+
151+
SEC("lwt_xmit")
152+
__description("make headroom for LWT_XMIT")
153+
__success __retval(0)
154+
__naked void make_headroom_for_lwt_xmit(void)
155+
{
156+
asm volatile (" \
157+
r6 = r1; \
158+
r2 = 34; \
159+
r3 = 0; \
160+
call %[bpf_skb_change_head]; \
161+
/* split for s390 to succeed */ \
162+
r1 = r6; \
163+
r2 = 42; \
164+
r3 = 0; \
165+
call %[bpf_skb_change_head]; \
166+
r0 = 0; \
167+
exit; \
168+
" :
169+
: __imm(bpf_skb_change_head)
170+
: __clobber_all);
171+
}
172+
173+
SEC("socket")
174+
__description("invalid access of tc_classid for LWT_IN")
175+
__failure __msg("invalid bpf_context access")
176+
__failure_unpriv
177+
__naked void tc_classid_for_lwt_in(void)
178+
{
179+
asm volatile (" \
180+
r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \
181+
exit; \
182+
" :
183+
: __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))
184+
: __clobber_all);
185+
}
186+
187+
SEC("socket")
188+
__description("invalid access of tc_classid for LWT_OUT")
189+
__failure __msg("invalid bpf_context access")
190+
__failure_unpriv
191+
__naked void tc_classid_for_lwt_out(void)
192+
{
193+
asm volatile (" \
194+
r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \
195+
exit; \
196+
" :
197+
: __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))
198+
: __clobber_all);
199+
}
200+
201+
SEC("socket")
202+
__description("invalid access of tc_classid for LWT_XMIT")
203+
__failure __msg("invalid bpf_context access")
204+
__failure_unpriv
205+
__naked void tc_classid_for_lwt_xmit(void)
206+
{
207+
asm volatile (" \
208+
r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \
209+
exit; \
210+
" :
211+
: __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))
212+
: __clobber_all);
213+
}
214+
215+
SEC("lwt_in")
216+
__description("check skb->tc_classid half load not permitted for lwt prog")
217+
__failure __msg("invalid bpf_context access")
218+
__naked void not_permitted_for_lwt_prog(void)
219+
{
220+
asm volatile (
221+
"r0 = 0;"
222+
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
223+
"r0 = *(u16*)(r1 + %[__sk_buff_tc_classid]);"
224+
#else
225+
"r0 = *(u16*)(r1 + %[__imm_0]);"
226+
#endif
227+
"exit;"
228+
:
229+
: __imm_const(__imm_0, offsetof(struct __sk_buff, tc_classid) + 2),
230+
__imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))
231+
: __clobber_all);
232+
}
233+
234+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)