xref: /linux/tools/testing/selftests/bpf/progs/verifier_raw_stack.c (revision 06d07429858317ded2db7986113a9e0129cd599b)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/raw_stack.c */
3 
4 #include <linux/bpf.h>
5 #include <bpf/bpf_helpers.h>
6 #include "bpf_misc.h"
7 
8 SEC("socket")
9 __description("raw_stack: no skb_load_bytes")
10 __success
11 __failure_unpriv __msg_unpriv("invalid read from stack R6 off=-8 size=8")
stack_no_skb_load_bytes(void)12 __naked void stack_no_skb_load_bytes(void)
13 {
14 	asm volatile ("					\
15 	r2 = 4;						\
16 	r6 = r10;					\
17 	r6 += -8;					\
18 	r3 = r6;					\
19 	r4 = 8;						\
20 	/* Call to skb_load_bytes() omitted. */		\
21 	r0 = *(u64*)(r6 + 0);				\
22 	exit;						\
23 "	::: __clobber_all);
24 }
25 
26 SEC("tc")
27 __description("raw_stack: skb_load_bytes, negative len")
28 __failure __msg("R4 min value is negative")
skb_load_bytes_negative_len(void)29 __naked void skb_load_bytes_negative_len(void)
30 {
31 	asm volatile ("					\
32 	r2 = 4;						\
33 	r6 = r10;					\
34 	r6 += -8;					\
35 	r3 = r6;					\
36 	r4 = -8;					\
37 	call %[bpf_skb_load_bytes];			\
38 	r0 = *(u64*)(r6 + 0);				\
39 	exit;						\
40 "	:
41 	: __imm(bpf_skb_load_bytes)
42 	: __clobber_all);
43 }
44 
45 SEC("tc")
46 __description("raw_stack: skb_load_bytes, negative len 2")
47 __failure __msg("R4 min value is negative")
load_bytes_negative_len_2(void)48 __naked void load_bytes_negative_len_2(void)
49 {
50 	asm volatile ("					\
51 	r2 = 4;						\
52 	r6 = r10;					\
53 	r6 += -8;					\
54 	r3 = r6;					\
55 	r4 = %[__imm_0];				\
56 	call %[bpf_skb_load_bytes];			\
57 	r0 = *(u64*)(r6 + 0);				\
58 	exit;						\
59 "	:
60 	: __imm(bpf_skb_load_bytes),
61 	  __imm_const(__imm_0, ~0)
62 	: __clobber_all);
63 }
64 
65 SEC("tc")
66 __description("raw_stack: skb_load_bytes, zero len")
67 __failure __msg("R4 invalid zero-sized read: u64=[0,0]")
skb_load_bytes_zero_len(void)68 __naked void skb_load_bytes_zero_len(void)
69 {
70 	asm volatile ("					\
71 	r2 = 4;						\
72 	r6 = r10;					\
73 	r6 += -8;					\
74 	r3 = r6;					\
75 	r4 = 0;						\
76 	call %[bpf_skb_load_bytes];			\
77 	r0 = *(u64*)(r6 + 0);				\
78 	exit;						\
79 "	:
80 	: __imm(bpf_skb_load_bytes)
81 	: __clobber_all);
82 }
83 
84 SEC("tc")
85 __description("raw_stack: skb_load_bytes, no init")
86 __success __retval(0)
skb_load_bytes_no_init(void)87 __naked void skb_load_bytes_no_init(void)
88 {
89 	asm volatile ("					\
90 	r2 = 4;						\
91 	r6 = r10;					\
92 	r6 += -8;					\
93 	r3 = r6;					\
94 	r4 = 8;						\
95 	call %[bpf_skb_load_bytes];			\
96 	r0 = *(u64*)(r6 + 0);				\
97 	exit;						\
98 "	:
99 	: __imm(bpf_skb_load_bytes)
100 	: __clobber_all);
101 }
102 
103 SEC("tc")
104 __description("raw_stack: skb_load_bytes, init")
105 __success __retval(0)
stack_skb_load_bytes_init(void)106 __naked void stack_skb_load_bytes_init(void)
107 {
108 	asm volatile ("					\
109 	r2 = 4;						\
110 	r6 = r10;					\
111 	r6 += -8;					\
112 	r3 = 0xcafe;					\
113 	*(u64*)(r6 + 0) = r3;				\
114 	r3 = r6;					\
115 	r4 = 8;						\
116 	call %[bpf_skb_load_bytes];			\
117 	r0 = *(u64*)(r6 + 0);				\
118 	exit;						\
119 "	:
120 	: __imm(bpf_skb_load_bytes)
121 	: __clobber_all);
122 }
123 
124 SEC("tc")
125 __description("raw_stack: skb_load_bytes, spilled regs around bounds")
126 __success __retval(0)
bytes_spilled_regs_around_bounds(void)127 __naked void bytes_spilled_regs_around_bounds(void)
128 {
129 	asm volatile ("					\
130 	r2 = 4;						\
131 	r6 = r10;					\
132 	r6 += -16;					\
133 	*(u64*)(r6 - 8) = r1;				\
134 	*(u64*)(r6 + 8) = r1;				\
135 	r3 = r6;					\
136 	r4 = 8;						\
137 	call %[bpf_skb_load_bytes];			\
138 	r0 = *(u64*)(r6 - 8);				\
139 	r2 = *(u64*)(r6 + 8);				\
140 	r0 = *(u32*)(r0 + %[__sk_buff_mark]);		\
141 	r2 = *(u32*)(r2 + %[__sk_buff_priority]);	\
142 	r0 += r2;					\
143 	exit;						\
144 "	:
145 	: __imm(bpf_skb_load_bytes),
146 	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)),
147 	  __imm_const(__sk_buff_priority, offsetof(struct __sk_buff, priority))
148 	: __clobber_all);
149 }
150 
151 SEC("tc")
152 __description("raw_stack: skb_load_bytes, spilled regs corruption")
153 __failure __msg("R0 invalid mem access 'scalar'")
__flag(BPF_F_ANY_ALIGNMENT)154 __flag(BPF_F_ANY_ALIGNMENT)
155 __naked void load_bytes_spilled_regs_corruption(void)
156 {
157 	asm volatile ("					\
158 	r2 = 4;						\
159 	r6 = r10;					\
160 	r6 += -8;					\
161 	*(u64*)(r6 + 0) = r1;				\
162 	r3 = r6;					\
163 	r4 = 8;						\
164 	call %[bpf_skb_load_bytes];			\
165 	r0 = *(u64*)(r6 + 0);				\
166 	r0 = *(u32*)(r0 + %[__sk_buff_mark]);		\
167 	exit;						\
168 "	:
169 	: __imm(bpf_skb_load_bytes),
170 	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark))
171 	: __clobber_all);
172 }
173 
174 SEC("tc")
175 __description("raw_stack: skb_load_bytes, spilled regs corruption 2")
176 __failure __msg("R3 invalid mem access 'scalar'")
__flag(BPF_F_ANY_ALIGNMENT)177 __flag(BPF_F_ANY_ALIGNMENT)
178 __naked void bytes_spilled_regs_corruption_2(void)
179 {
180 	asm volatile ("					\
181 	r2 = 4;						\
182 	r6 = r10;					\
183 	r6 += -16;					\
184 	*(u64*)(r6 - 8) = r1;				\
185 	*(u64*)(r6 + 0) = r1;				\
186 	*(u64*)(r6 + 8) = r1;				\
187 	r3 = r6;					\
188 	r4 = 8;						\
189 	call %[bpf_skb_load_bytes];			\
190 	r0 = *(u64*)(r6 - 8);				\
191 	r2 = *(u64*)(r6 + 8);				\
192 	r3 = *(u64*)(r6 + 0);				\
193 	r0 = *(u32*)(r0 + %[__sk_buff_mark]);		\
194 	r2 = *(u32*)(r2 + %[__sk_buff_priority]);	\
195 	r0 += r2;					\
196 	r3 = *(u32*)(r3 + %[__sk_buff_pkt_type]);	\
197 	r0 += r3;					\
198 	exit;						\
199 "	:
200 	: __imm(bpf_skb_load_bytes),
201 	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)),
202 	  __imm_const(__sk_buff_pkt_type, offsetof(struct __sk_buff, pkt_type)),
203 	  __imm_const(__sk_buff_priority, offsetof(struct __sk_buff, priority))
204 	: __clobber_all);
205 }
206 
207 SEC("tc")
208 __description("raw_stack: skb_load_bytes, spilled regs + data")
209 __success __retval(0)
load_bytes_spilled_regs_data(void)210 __naked void load_bytes_spilled_regs_data(void)
211 {
212 	asm volatile ("					\
213 	r2 = 4;						\
214 	r6 = r10;					\
215 	r6 += -16;					\
216 	*(u64*)(r6 - 8) = r1;				\
217 	*(u64*)(r6 + 0) = r1;				\
218 	*(u64*)(r6 + 8) = r1;				\
219 	r3 = r6;					\
220 	r4 = 8;						\
221 	call %[bpf_skb_load_bytes];			\
222 	r0 = *(u64*)(r6 - 8);				\
223 	r2 = *(u64*)(r6 + 8);				\
224 	r3 = *(u64*)(r6 + 0);				\
225 	r0 = *(u32*)(r0 + %[__sk_buff_mark]);		\
226 	r2 = *(u32*)(r2 + %[__sk_buff_priority]);	\
227 	r0 += r2;					\
228 	r0 += r3;					\
229 	exit;						\
230 "	:
231 	: __imm(bpf_skb_load_bytes),
232 	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)),
233 	  __imm_const(__sk_buff_priority, offsetof(struct __sk_buff, priority))
234 	: __clobber_all);
235 }
236 
237 SEC("tc")
238 __description("raw_stack: skb_load_bytes, invalid access 1")
239 __failure __msg("invalid indirect access to stack R3 off=-513 size=8")
load_bytes_invalid_access_1(void)240 __naked void load_bytes_invalid_access_1(void)
241 {
242 	asm volatile ("					\
243 	r2 = 4;						\
244 	r6 = r10;					\
245 	r6 += -513;					\
246 	r3 = r6;					\
247 	r4 = 8;						\
248 	call %[bpf_skb_load_bytes];			\
249 	r0 = *(u64*)(r6 + 0);				\
250 	exit;						\
251 "	:
252 	: __imm(bpf_skb_load_bytes)
253 	: __clobber_all);
254 }
255 
256 SEC("tc")
257 __description("raw_stack: skb_load_bytes, invalid access 2")
258 __failure __msg("invalid indirect access to stack R3 off=-1 size=8")
load_bytes_invalid_access_2(void)259 __naked void load_bytes_invalid_access_2(void)
260 {
261 	asm volatile ("					\
262 	r2 = 4;						\
263 	r6 = r10;					\
264 	r6 += -1;					\
265 	r3 = r6;					\
266 	r4 = 8;						\
267 	call %[bpf_skb_load_bytes];			\
268 	r0 = *(u64*)(r6 + 0);				\
269 	exit;						\
270 "	:
271 	: __imm(bpf_skb_load_bytes)
272 	: __clobber_all);
273 }
274 
275 SEC("tc")
276 __description("raw_stack: skb_load_bytes, invalid access 3")
277 __failure __msg("R4 min value is negative")
load_bytes_invalid_access_3(void)278 __naked void load_bytes_invalid_access_3(void)
279 {
280 	asm volatile ("					\
281 	r2 = 4;						\
282 	r6 = r10;					\
283 	r6 += 0xffffffff;				\
284 	r3 = r6;					\
285 	r4 = 0xffffffff;				\
286 	call %[bpf_skb_load_bytes];			\
287 	r0 = *(u64*)(r6 + 0);				\
288 	exit;						\
289 "	:
290 	: __imm(bpf_skb_load_bytes)
291 	: __clobber_all);
292 }
293 
294 SEC("tc")
295 __description("raw_stack: skb_load_bytes, invalid access 4")
296 __failure
297 __msg("R4 unbounded memory access, use 'var &= const' or 'if (var < const)'")
load_bytes_invalid_access_4(void)298 __naked void load_bytes_invalid_access_4(void)
299 {
300 	asm volatile ("					\
301 	r2 = 4;						\
302 	r6 = r10;					\
303 	r6 += -1;					\
304 	r3 = r6;					\
305 	r4 = 0x7fffffff;				\
306 	call %[bpf_skb_load_bytes];			\
307 	r0 = *(u64*)(r6 + 0);				\
308 	exit;						\
309 "	:
310 	: __imm(bpf_skb_load_bytes)
311 	: __clobber_all);
312 }
313 
314 SEC("tc")
315 __description("raw_stack: skb_load_bytes, invalid access 5")
316 __failure
317 __msg("R4 unbounded memory access, use 'var &= const' or 'if (var < const)'")
load_bytes_invalid_access_5(void)318 __naked void load_bytes_invalid_access_5(void)
319 {
320 	asm volatile ("					\
321 	r2 = 4;						\
322 	r6 = r10;					\
323 	r6 += -512;					\
324 	r3 = r6;					\
325 	r4 = 0x7fffffff;				\
326 	call %[bpf_skb_load_bytes];			\
327 	r0 = *(u64*)(r6 + 0);				\
328 	exit;						\
329 "	:
330 	: __imm(bpf_skb_load_bytes)
331 	: __clobber_all);
332 }
333 
334 SEC("tc")
335 __description("raw_stack: skb_load_bytes, invalid access 6")
336 __failure __msg("invalid zero-sized read")
load_bytes_invalid_access_6(void)337 __naked void load_bytes_invalid_access_6(void)
338 {
339 	asm volatile ("					\
340 	r2 = 4;						\
341 	r6 = r10;					\
342 	r6 += -512;					\
343 	r3 = r6;					\
344 	r4 = 0;						\
345 	call %[bpf_skb_load_bytes];			\
346 	r0 = *(u64*)(r6 + 0);				\
347 	exit;						\
348 "	:
349 	: __imm(bpf_skb_load_bytes)
350 	: __clobber_all);
351 }
352 
353 SEC("tc")
354 __description("raw_stack: skb_load_bytes, large access")
355 __success __retval(0)
skb_load_bytes_large_access(void)356 __naked void skb_load_bytes_large_access(void)
357 {
358 	asm volatile ("					\
359 	r2 = 4;						\
360 	r6 = r10;					\
361 	r6 += -512;					\
362 	r3 = r6;					\
363 	r4 = 512;					\
364 	call %[bpf_skb_load_bytes];			\
365 	r0 = *(u64*)(r6 + 0);				\
366 	exit;						\
367 "	:
368 	: __imm(bpf_skb_load_bytes)
369 	: __clobber_all);
370 }
371 
372 char _license[] SEC("license") = "GPL";
373