xref: /linux/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c (revision 0a91336e287ca2557fead5221d2c79e0effd034e)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/value_ptr_arith.c */
3 
4 #include <linux/bpf.h>
5 #include <bpf/bpf_helpers.h>
6 #include <errno.h>
7 #include "bpf_misc.h"
8 
9 #define MAX_ENTRIES 11
10 
11 struct test_val {
12 	unsigned int index;
13 	int foo[MAX_ENTRIES];
14 };
15 
16 struct {
17 	__uint(type, BPF_MAP_TYPE_ARRAY);
18 	__uint(max_entries, 1);
19 	__type(key, int);
20 	__type(value, struct test_val);
21 } map_array_48b SEC(".maps");
22 
23 struct other_val {
24 	long long foo;
25 	long long bar;
26 };
27 
28 struct {
29 	__uint(type, BPF_MAP_TYPE_HASH);
30 	__uint(max_entries, 1);
31 	__type(key, long long);
32 	__type(value, struct other_val);
33 } map_hash_16b SEC(".maps");
34 
35 struct {
36 	__uint(type, BPF_MAP_TYPE_HASH);
37 	__uint(max_entries, 1);
38 	__type(key, long long);
39 	__type(value, struct test_val);
40 } map_hash_48b SEC(".maps");
41 
42 SEC("socket")
43 __description("map access: known scalar += value_ptr unknown vs const")
44 __success __failure_unpriv
45 __msg_unpriv("R1 tried to add from different maps, paths or scalars")
46 __retval(1)
value_ptr_unknown_vs_const(void)47 __naked void value_ptr_unknown_vs_const(void)
48 {
49 	asm volatile ("					\
50 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
51 	r1 = 0;						\
52 	*(u64*)(r10 - 8) = r1;				\
53 	r2 = r10;					\
54 	r2 += -8;					\
55 	if r0 == 1 goto l0_%=;				\
56 	r1 = %[map_hash_16b] ll;			\
57 	if r0 != 1 goto l1_%=;				\
58 l0_%=:	r1 = %[map_array_48b] ll;			\
59 l1_%=:	call %[bpf_map_lookup_elem];			\
60 	if r0 == 0 goto l2_%=;				\
61 	r4 = *(u8*)(r0 + 0);				\
62 	if r4 == 1 goto l3_%=;				\
63 	r1 = 6;						\
64 	r1 = -r1;					\
65 	r1 &= 0x7;					\
66 	goto l4_%=;					\
67 l3_%=:	r1 = 3;						\
68 l4_%=:	r1 += r0;					\
69 	r0 = *(u8*)(r1 + 0);				\
70 l2_%=:	r0 = 1;						\
71 	exit;						\
72 "	:
73 	: __imm(bpf_map_lookup_elem),
74 	  __imm_addr(map_array_48b),
75 	  __imm_addr(map_hash_16b),
76 	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
77 	: __clobber_all);
78 }
79 
80 SEC("socket")
81 __description("map access: known scalar += value_ptr const vs unknown")
82 __success __failure_unpriv
83 __msg_unpriv("R1 tried to add from different maps, paths or scalars")
84 __retval(1)
value_ptr_const_vs_unknown(void)85 __naked void value_ptr_const_vs_unknown(void)
86 {
87 	asm volatile ("					\
88 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
89 	r1 = 0;						\
90 	*(u64*)(r10 - 8) = r1;				\
91 	r2 = r10;					\
92 	r2 += -8;					\
93 	if r0 == 1 goto l0_%=;				\
94 	r1 = %[map_hash_16b] ll;			\
95 	if r0 != 1 goto l1_%=;				\
96 l0_%=:	r1 = %[map_array_48b] ll;			\
97 l1_%=:	call %[bpf_map_lookup_elem];			\
98 	if r0 == 0 goto l2_%=;				\
99 	r4 = *(u8*)(r0 + 0);				\
100 	if r4 == 1 goto l3_%=;				\
101 	r1 = 3;						\
102 	goto l4_%=;					\
103 l3_%=:	r1 = 6;						\
104 	r1 = -r1;					\
105 	r1 &= 0x7;					\
106 l4_%=:	r1 += r0;					\
107 	r0 = *(u8*)(r1 + 0);				\
108 l2_%=:	r0 = 1;						\
109 	exit;						\
110 "	:
111 	: __imm(bpf_map_lookup_elem),
112 	  __imm_addr(map_array_48b),
113 	  __imm_addr(map_hash_16b),
114 	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
115 	: __clobber_all);
116 }
117 
118 SEC("socket")
119 __description("map access: known scalar += value_ptr const vs const (ne)")
120 __success __failure_unpriv
121 __msg_unpriv("R1 tried to add from different maps, paths or scalars")
122 __retval(1)
ptr_const_vs_const_ne(void)123 __naked void ptr_const_vs_const_ne(void)
124 {
125 	asm volatile ("					\
126 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
127 	r1 = 0;						\
128 	*(u64*)(r10 - 8) = r1;				\
129 	r2 = r10;					\
130 	r2 += -8;					\
131 	if r0 == 1 goto l0_%=;				\
132 	r1 = %[map_hash_16b] ll;			\
133 	if r0 != 1 goto l1_%=;				\
134 l0_%=:	r1 = %[map_array_48b] ll;			\
135 l1_%=:	call %[bpf_map_lookup_elem];			\
136 	if r0 == 0 goto l2_%=;				\
137 	r4 = *(u8*)(r0 + 0);				\
138 	if r4 == 1 goto l3_%=;				\
139 	r1 = 3;						\
140 	goto l4_%=;					\
141 l3_%=:	r1 = 5;						\
142 l4_%=:	r1 += r0;					\
143 	r0 = *(u8*)(r1 + 0);				\
144 l2_%=:	r0 = 1;						\
145 	exit;						\
146 "	:
147 	: __imm(bpf_map_lookup_elem),
148 	  __imm_addr(map_array_48b),
149 	  __imm_addr(map_hash_16b),
150 	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
151 	: __clobber_all);
152 }
153 
154 SEC("socket")
155 __description("map access: known scalar += value_ptr const vs const (eq)")
156 __success __success_unpriv __retval(1)
ptr_const_vs_const_eq(void)157 __naked void ptr_const_vs_const_eq(void)
158 {
159 	asm volatile ("					\
160 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
161 	r1 = 0;						\
162 	*(u64*)(r10 - 8) = r1;				\
163 	r2 = r10;					\
164 	r2 += -8;					\
165 	if r0 == 1 goto l0_%=;				\
166 	r1 = %[map_hash_16b] ll;			\
167 	if r0 != 1 goto l1_%=;				\
168 l0_%=:	r1 = %[map_array_48b] ll;			\
169 l1_%=:	call %[bpf_map_lookup_elem];			\
170 	if r0 == 0 goto l2_%=;				\
171 	r4 = *(u8*)(r0 + 0);				\
172 	if r4 == 1 goto l3_%=;				\
173 	r1 = 5;						\
174 	goto l4_%=;					\
175 l3_%=:	r1 = 5;						\
176 l4_%=:	r1 += r0;					\
177 	r0 = *(u8*)(r1 + 0);				\
178 l2_%=:	r0 = 1;						\
179 	exit;						\
180 "	:
181 	: __imm(bpf_map_lookup_elem),
182 	  __imm_addr(map_array_48b),
183 	  __imm_addr(map_hash_16b),
184 	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
185 	: __clobber_all);
186 }
187 
188 SEC("socket")
189 __description("map access: known scalar += value_ptr unknown vs unknown (eq)")
190 __success __success_unpriv __retval(1)
ptr_unknown_vs_unknown_eq(void)191 __naked void ptr_unknown_vs_unknown_eq(void)
192 {
193 	asm volatile ("					\
194 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
195 	r1 = 0;						\
196 	*(u64*)(r10 - 8) = r1;				\
197 	r2 = r10;					\
198 	r2 += -8;					\
199 	if r0 == 1 goto l0_%=;				\
200 	r1 = %[map_hash_16b] ll;			\
201 	if r0 != 1 goto l1_%=;				\
202 l0_%=:	r1 = %[map_array_48b] ll;			\
203 l1_%=:	call %[bpf_map_lookup_elem];			\
204 	if r0 == 0 goto l2_%=;				\
205 	r4 = *(u8*)(r0 + 0);				\
206 	if r4 == 1 goto l3_%=;				\
207 	r1 = 6;						\
208 	r1 = -r1;					\
209 	r1 &= 0x7;					\
210 	goto l4_%=;					\
211 l3_%=:	r1 = 6;						\
212 	r1 = -r1;					\
213 	r1 &= 0x7;					\
214 l4_%=:	r1 += r0;					\
215 	r0 = *(u8*)(r1 + 0);				\
216 l2_%=:	r0 = 1;						\
217 	exit;						\
218 "	:
219 	: __imm(bpf_map_lookup_elem),
220 	  __imm_addr(map_array_48b),
221 	  __imm_addr(map_hash_16b),
222 	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
223 	: __clobber_all);
224 }
225 
226 SEC("socket")
227 __description("map access: known scalar += value_ptr unknown vs unknown (lt)")
228 __success __failure_unpriv
229 __msg_unpriv("R1 tried to add from different maps, paths or scalars")
230 __retval(1)
ptr_unknown_vs_unknown_lt(void)231 __naked void ptr_unknown_vs_unknown_lt(void)
232 {
233 	asm volatile ("					\
234 	r8 = r1;					\
235 	call %[bpf_get_prandom_u32];			\
236 	r9 = r0;					\
237 	r1 = r8;					\
238 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
239 	r1 = 0;						\
240 	*(u64*)(r10 - 8) = r1;				\
241 	r2 = r10;					\
242 	r2 += -8;					\
243 	if r0 == 1 goto l0_%=;				\
244 	r1 = %[map_hash_16b] ll;			\
245 	if r0 != 1 goto l1_%=;				\
246 l0_%=:	r1 = %[map_array_48b] ll;			\
247 l1_%=:	call %[bpf_map_lookup_elem];			\
248 	if r0 == 0 goto l2_%=;				\
249 	r4 = *(u8*)(r0 + 0);				\
250 	if r4 == 1 goto l3_%=;				\
251 	r1 = 6;						\
252 	r1 = r9;					\
253 	r1 &= 0x3;					\
254 	goto l4_%=;					\
255 l3_%=:	r1 = 6;						\
256 	r1 = r9;					\
257 	r1 &= 0x7;					\
258 l4_%=:	r1 += r0;					\
259 	r0 = *(u8*)(r1 + 0);				\
260 l2_%=:	r0 = 1;						\
261 	exit;						\
262 "	:
263 	: __imm(bpf_map_lookup_elem),
264 	  __imm_addr(map_array_48b),
265 	  __imm_addr(map_hash_16b),
266 	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)),
267 	  __imm(bpf_get_prandom_u32)
268 	: __clobber_all);
269 }
270 
271 SEC("socket")
272 __description("map access: known scalar += value_ptr unknown vs unknown (gt)")
273 __success __failure_unpriv
274 __msg_unpriv("R1 tried to add from different maps, paths or scalars")
275 __retval(1)
ptr_unknown_vs_unknown_gt(void)276 __naked void ptr_unknown_vs_unknown_gt(void)
277 {
278 	asm volatile ("					\
279 	r8 = r1;					\
280 	call %[bpf_get_prandom_u32];			\
281 	r9 = r0;					\
282 	r1 = r8;					\
283 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
284 	r1 = 0;						\
285 	*(u64*)(r10 - 8) = r1;				\
286 	r2 = r10;					\
287 	r2 += -8;					\
288 	if r0 == 1 goto l0_%=;				\
289 	r1 = %[map_hash_16b] ll;			\
290 	if r0 != 1 goto l1_%=;				\
291 l0_%=:	r1 = %[map_array_48b] ll;			\
292 l1_%=:	call %[bpf_map_lookup_elem];			\
293 	if r0 == 0 goto l2_%=;				\
294 	r4 = *(u8*)(r0 + 0);				\
295 	if r4 == 1 goto l3_%=;				\
296 	r1 = 6;						\
297 	r1 = r9;					\
298 	r1 &= 0x7;					\
299 	goto l4_%=;					\
300 l3_%=:	r1 = 6;						\
301 	r1 = r9;					\
302 	r1 &= 0x3;					\
303 l4_%=:	r1 += r0;					\
304 	r0 = *(u8*)(r1 + 0);				\
305 l2_%=:	r0 = 1;						\
306 	exit;						\
307 "	:
308 	: __imm(bpf_map_lookup_elem),
309 	  __imm_addr(map_array_48b),
310 	  __imm_addr(map_hash_16b),
311 	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)),
312 	  __imm(bpf_get_prandom_u32)
313 	: __clobber_all);
314 }
315 
316 SEC("socket")
317 __description("map access: known scalar += value_ptr from different maps")
318 __success __success_unpriv __retval(1)
value_ptr_from_different_maps(void)319 __naked void value_ptr_from_different_maps(void)
320 {
321 	asm volatile ("					\
322 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
323 	r1 = 0;						\
324 	*(u64*)(r10 - 8) = r1;				\
325 	r2 = r10;					\
326 	r2 += -8;					\
327 	if r0 == 1 goto l0_%=;				\
328 	r1 = %[map_hash_16b] ll;			\
329 	if r0 != 1 goto l1_%=;				\
330 l0_%=:	r1 = %[map_array_48b] ll;			\
331 l1_%=:	call %[bpf_map_lookup_elem];			\
332 	if r0 == 0 goto l2_%=;				\
333 	r1 = 4;						\
334 	r1 += r0;					\
335 	r0 = *(u8*)(r1 + 0);				\
336 l2_%=:	r0 = 1;						\
337 	exit;						\
338 "	:
339 	: __imm(bpf_map_lookup_elem),
340 	  __imm_addr(map_array_48b),
341 	  __imm_addr(map_hash_16b),
342 	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
343 	: __clobber_all);
344 }
345 
346 SEC("socket")
347 __description("map access: value_ptr -= known scalar from different maps")
348 __success __failure_unpriv
349 __msg_unpriv("R0 min value is outside of the allowed memory range")
350 __retval(1)
known_scalar_from_different_maps(void)351 __naked void known_scalar_from_different_maps(void)
352 {
353 	asm volatile ("					\
354 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
355 	r1 = 0;						\
356 	*(u64*)(r10 - 8) = r1;				\
357 	r2 = r10;					\
358 	r2 += -8;					\
359 	if r0 == 1 goto l0_%=;				\
360 	r1 = %[map_hash_16b] ll;			\
361 	if r0 != 1 goto l1_%=;				\
362 l0_%=:	r1 = %[map_array_48b] ll;			\
363 l1_%=:	call %[bpf_map_lookup_elem];			\
364 	if r0 == 0 goto l2_%=;				\
365 	r1 = 4;						\
366 	r0 -= r1;					\
367 	r0 += r1;					\
368 	r0 = *(u8*)(r0 + 0);				\
369 l2_%=:	r0 = 1;						\
370 	exit;						\
371 "	:
372 	: __imm(bpf_map_lookup_elem),
373 	  __imm_addr(map_array_48b),
374 	  __imm_addr(map_hash_16b),
375 	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
376 	: __clobber_all);
377 }
378 
379 SEC("socket")
380 __description("map access: known scalar += value_ptr from different maps, but same value properties")
381 __success __success_unpriv __retval(1)
maps_but_same_value_properties(void)382 __naked void maps_but_same_value_properties(void)
383 {
384 	asm volatile ("					\
385 	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
386 	r1 = 0;						\
387 	*(u64*)(r10 - 8) = r1;				\
388 	r2 = r10;					\
389 	r2 += -8;					\
390 	if r0 == 1 goto l0_%=;				\
391 	r1 = %[map_hash_48b] ll;			\
392 	if r0 != 1 goto l1_%=;				\
393 l0_%=:	r1 = %[map_array_48b] ll;			\
394 l1_%=:	call %[bpf_map_lookup_elem];			\
395 	if r0 == 0 goto l2_%=;				\
396 	r1 = 4;						\
397 	r1 += r0;					\
398 	r0 = *(u8*)(r1 + 0);				\
399 l2_%=:	r0 = 1;						\
400 	exit;						\
401 "	:
402 	: __imm(bpf_map_lookup_elem),
403 	  __imm_addr(map_array_48b),
404 	  __imm_addr(map_hash_48b),
405 	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
406 	: __clobber_all);
407 }
408 
409 SEC("socket")
410 __description("map access: mixing value pointer and scalar, 1")
411 __success __failure_unpriv
412 __msg_unpriv("R2 tried to add from different maps, paths or scalars, pointer arithmetic with it prohibited for !root")
413 __retval(0)
value_pointer_and_scalar_1(void)414 __naked void value_pointer_and_scalar_1(void)
415 {
416 	asm volatile ("					\
417 	/* load map value pointer into r0 and r2 */	\
418 	r0 = 1;						\
419 	r1 = %[map_array_48b] ll;			\
420 	r2 = r10;					\
421 	r2 += -16;					\
422 	r6 = 0;						\
423 	*(u64*)(r10 - 16) = r6;				\
424 	call %[bpf_map_lookup_elem];			\
425 	if r0 != 0 goto l0_%=;				\
426 	exit;						\
427 l0_%=:	/* load some number from the map into r1 */	\
428 	r1 = *(u8*)(r0 + 0);				\
429 	/* depending on r1, branch: */			\
430 	if r1 != 0 goto l1_%=;				\
431 	/* branch A */					\
432 	r2 = r0;					\
433 	r3 = 0;						\
434 	goto l2_%=;					\
435 l1_%=:	/* branch B */					\
436 	r2 = 0;						\
437 	r3 = 0x100000;					\
438 l2_%=:	/* common instruction */			\
439 	r2 += r3;					\
440 	/* depending on r1, branch: */			\
441 	if r1 != 0 goto l3_%=;				\
442 	/* branch A */					\
443 	goto l4_%=;					\
444 l3_%=:	/* branch B */					\
445 	r0 = 0x13371337;				\
446 	/* verifier follows fall-through */		\
447 	/* unpriv: nospec (inserted to prevent `R2 pointer comparison prohibited`) */\
448 	if r2 != 0x100000 goto l4_%=;			\
449 	r0 = 0;						\
450 	exit;						\
451 l4_%=:	/* fake-dead code; targeted from branch A to	\
452 	 * prevent dead code sanitization		\
453 	 */						\
454 	r0 = *(u8*)(r0 + 0);				\
455 	r0 = 0;						\
456 	exit;						\
457 "	:
458 	: __imm(bpf_map_lookup_elem),
459 	  __imm_addr(map_array_48b)
460 	: __clobber_all);
461 }
462 
463 SEC("socket")
464 __description("map access: mixing value pointer and scalar, 2")
465 __success __failure_unpriv
466 __msg_unpriv("R2 tried to add from different maps, paths or scalars, pointer arithmetic with it prohibited for !root")
467 __retval(0)
value_pointer_and_scalar_2(void)468 __naked void value_pointer_and_scalar_2(void)
469 {
470 	asm volatile ("					\
471 	/* load map value pointer into r0 and r2 */	\
472 	r0 = 1;						\
473 	r1 = %[map_array_48b] ll;			\
474 	r2 = r10;					\
475 	r2 += -16;					\
476 	r6 = 0;						\
477 	*(u64*)(r10 - 16) = r6;				\
478 	call %[bpf_map_lookup_elem];			\
479 	if r0 != 0 goto l0_%=;				\
480 	exit;						\
481 l0_%=:	/* load some number from the map into r1 */	\
482 	r1 = *(u8*)(r0 + 0);				\
483 	/* depending on r1, branch: */			\
484 	if r1 == 0 goto l1_%=;				\
485 	/* branch A */					\
486 	r2 = 0;						\
487 	r3 = 0x100000;					\
488 	goto l2_%=;					\
489 l1_%=:	/* branch B */					\
490 	r2 = r0;					\
491 	r3 = 0;						\
492 l2_%=:	/* common instruction */			\
493 	r2 += r3;					\
494 	/* depending on r1, branch: */			\
495 	if r1 != 0 goto l3_%=;				\
496 	/* branch A */					\
497 	goto l4_%=;					\
498 l3_%=:	/* branch B */					\
499 	r0 = 0x13371337;				\
500 	/* verifier follows fall-through */		\
501 	if r2 != 0x100000 goto l4_%=;			\
502 	r0 = 0;						\
503 	exit;						\
504 l4_%=:	/* fake-dead code; targeted from branch A to	\
505 	 * prevent dead code sanitization, rejected	\
506 	 * via branch B however				\
507 	 */						\
508 	/* unpriv: nospec (inserted to prevent `R0 invalid mem access 'scalar'`) */\
509 	r0 = *(u8*)(r0 + 0);				\
510 	r0 = 0;						\
511 	exit;						\
512 "	:
513 	: __imm(bpf_map_lookup_elem),
514 	  __imm_addr(map_array_48b)
515 	: __clobber_all);
516 }
517 
518 SEC("socket")
519 __description("sanitation: alu with different scalars 1")
520 __success __success_unpriv __retval(0x100000)
alu_with_different_scalars_1(void)521 __naked void alu_with_different_scalars_1(void)
522 {
523 	asm volatile ("					\
524 	r0 = 1;						\
525 	r1 = %[map_array_48b] ll;			\
526 	r2 = r10;					\
527 	r2 += -16;					\
528 	r6 = 0;						\
529 	*(u64*)(r10 - 16) = r6;				\
530 	call %[bpf_map_lookup_elem];			\
531 	if r0 != 0 goto l0_%=;				\
532 	exit;						\
533 l0_%=:	r1 = *(u32*)(r0 + 0);				\
534 	if r1 == 0 goto l1_%=;				\
535 	r2 = 0;						\
536 	r3 = 0x100000;					\
537 	goto l2_%=;					\
538 l1_%=:	r2 = 42;					\
539 	r3 = 0x100001;					\
540 l2_%=:	r2 += r3;					\
541 	r0 = r2;					\
542 	exit;						\
543 "	:
544 	: __imm(bpf_map_lookup_elem),
545 	  __imm_addr(map_array_48b)
546 	: __clobber_all);
547 }
548 
549 SEC("socket")
550 __description("sanitation: alu with different scalars 2")
551 __success __success_unpriv __retval(0)
alu_with_different_scalars_2(void)552 __naked void alu_with_different_scalars_2(void)
553 {
554 	asm volatile ("					\
555 	r0 = 1;						\
556 	r1 = %[map_array_48b] ll;			\
557 	r6 = r1;					\
558 	r2 = r10;					\
559 	r2 += -16;					\
560 	r7 = 0;						\
561 	*(u64*)(r10 - 16) = r7;				\
562 	call %[bpf_map_delete_elem];			\
563 	r7 = r0;					\
564 	r1 = r6;					\
565 	r2 = r10;					\
566 	r2 += -16;					\
567 	call %[bpf_map_delete_elem];			\
568 	r6 = r0;					\
569 	r8 = r6;					\
570 	r8 += r7;					\
571 	r0 = r8;					\
572 	r0 += %[einval];				\
573 	r0 += %[einval];				\
574 	exit;						\
575 "	:
576 	: __imm(bpf_map_delete_elem),
577 	  __imm_addr(map_array_48b),
578 	  __imm_const(einval, EINVAL)
579 	: __clobber_all);
580 }
581 
582 SEC("socket")
583 __description("sanitation: alu with different scalars 3")
584 __success __success_unpriv __retval(0)
alu_with_different_scalars_3(void)585 __naked void alu_with_different_scalars_3(void)
586 {
587 	asm volatile ("					\
588 	r0 = %[einval];					\
589 	r0 *= -1;					\
590 	r7 = r0;					\
591 	r0 = %[einval];					\
592 	r0 *= -1;					\
593 	r6 = r0;					\
594 	r8 = r6;					\
595 	r8 += r7;					\
596 	r0 = r8;					\
597 	r0 += %[einval];				\
598 	r0 += %[einval];				\
599 	exit;						\
600 "	:
601 	: __imm_const(einval, EINVAL)
602 	: __clobber_all);
603 }
604 
605 SEC("socket")
606 __description("map access: value_ptr += known scalar, upper oob arith, test 1")
607 __success __failure_unpriv
608 __msg_unpriv("R0 pointer arithmetic of map value goes out of range")
609 __retval(1)
upper_oob_arith_test_1(void)610 __naked void upper_oob_arith_test_1(void)
611 {
612 	asm volatile ("					\
613 	r1 = 0;						\
614 	*(u64*)(r10 - 8) = r1;				\
615 	r2 = r10;					\
616 	r2 += -8;					\
617 	r1 = %[map_array_48b] ll;			\
618 	call %[bpf_map_lookup_elem];			\
619 	if r0 == 0 goto l0_%=;				\
620 	r1 = 48;					\
621 	r0 += r1;					\
622 	r0 -= r1;					\
623 	r0 = *(u8*)(r0 + 0);				\
624 l0_%=:	r0 = 1;						\
625 	exit;						\
626 "	:
627 	: __imm(bpf_map_lookup_elem),
628 	  __imm_addr(map_array_48b)
629 	: __clobber_all);
630 }
631 
632 SEC("socket")
633 __description("map access: value_ptr += known scalar, upper oob arith, test 2")
634 __success __failure_unpriv
635 __msg_unpriv("R0 pointer arithmetic of map value goes out of range")
636 __retval(1)
upper_oob_arith_test_2(void)637 __naked void upper_oob_arith_test_2(void)
638 {
639 	asm volatile ("					\
640 	r1 = 0;						\
641 	*(u64*)(r10 - 8) = r1;				\
642 	r2 = r10;					\
643 	r2 += -8;					\
644 	r1 = %[map_array_48b] ll;			\
645 	call %[bpf_map_lookup_elem];			\
646 	if r0 == 0 goto l0_%=;				\
647 	r1 = 49;					\
648 	r0 += r1;					\
649 	r0 -= r1;					\
650 	r0 = *(u8*)(r0 + 0);				\
651 l0_%=:	r0 = 1;						\
652 	exit;						\
653 "	:
654 	: __imm(bpf_map_lookup_elem),
655 	  __imm_addr(map_array_48b)
656 	: __clobber_all);
657 }
658 
659 SEC("socket")
660 __description("map access: value_ptr += known scalar, upper oob arith, test 3")
661 __success __success_unpriv __retval(1)
upper_oob_arith_test_3(void)662 __naked void upper_oob_arith_test_3(void)
663 {
664 	asm volatile ("					\
665 	r1 = 0;						\
666 	*(u64*)(r10 - 8) = r1;				\
667 	r2 = r10;					\
668 	r2 += -8;					\
669 	r1 = %[map_array_48b] ll;			\
670 	call %[bpf_map_lookup_elem];			\
671 	if r0 == 0 goto l0_%=;				\
672 	r1 = 47;					\
673 	r0 += r1;					\
674 	r0 -= r1;					\
675 	r0 = *(u8*)(r0 + 0);				\
676 l0_%=:	r0 = 1;						\
677 	exit;						\
678 "	:
679 	: __imm(bpf_map_lookup_elem),
680 	  __imm_addr(map_array_48b)
681 	: __clobber_all);
682 }
683 
684 SEC("socket")
685 __description("map access: value_ptr -= known scalar, lower oob arith, test 1")
686 __failure __msg("R0 min value is outside of the allowed memory range")
687 __failure_unpriv
688 __msg_unpriv("R0 pointer arithmetic of map value goes out of range")
lower_oob_arith_test_1(void)689 __naked void lower_oob_arith_test_1(void)
690 {
691 	asm volatile ("					\
692 	r1 = 0;						\
693 	*(u64*)(r10 - 8) = r1;				\
694 	r2 = r10;					\
695 	r2 += -8;					\
696 	r1 = %[map_array_48b] ll;			\
697 	call %[bpf_map_lookup_elem];			\
698 	if r0 == 0 goto l0_%=;				\
699 	r1 = 47;					\
700 	r0 += r1;					\
701 	r1 = 48;					\
702 	r0 -= r1;					\
703 	r0 = *(u8*)(r0 + 0);				\
704 l0_%=:	r0 = 1;						\
705 	exit;						\
706 "	:
707 	: __imm(bpf_map_lookup_elem),
708 	  __imm_addr(map_array_48b)
709 	: __clobber_all);
710 }
711 
712 SEC("socket")
713 __description("map access: value_ptr -= known scalar, lower oob arith, test 2")
714 __success __failure_unpriv
715 __msg_unpriv("R0 pointer arithmetic of map value goes out of range")
716 __retval(1)
lower_oob_arith_test_2(void)717 __naked void lower_oob_arith_test_2(void)
718 {
719 	asm volatile ("					\
720 	r1 = 0;						\
721 	*(u64*)(r10 - 8) = r1;				\
722 	r2 = r10;					\
723 	r2 += -8;					\
724 	r1 = %[map_array_48b] ll;			\
725 	call %[bpf_map_lookup_elem];			\
726 	if r0 == 0 goto l0_%=;				\
727 	r1 = 47;					\
728 	r0 += r1;					\
729 	r1 = 48;					\
730 	r0 -= r1;					\
731 	r1 = 1;						\
732 	r0 += r1;					\
733 	r0 = *(u8*)(r0 + 0);				\
734 l0_%=:	r0 = 1;						\
735 	exit;						\
736 "	:
737 	: __imm(bpf_map_lookup_elem),
738 	  __imm_addr(map_array_48b)
739 	: __clobber_all);
740 }
741 
742 SEC("socket")
743 __description("map access: value_ptr -= known scalar, lower oob arith, test 3")
744 __success __success_unpriv __retval(1)
lower_oob_arith_test_3(void)745 __naked void lower_oob_arith_test_3(void)
746 {
747 	asm volatile ("					\
748 	r1 = 0;						\
749 	*(u64*)(r10 - 8) = r1;				\
750 	r2 = r10;					\
751 	r2 += -8;					\
752 	r1 = %[map_array_48b] ll;			\
753 	call %[bpf_map_lookup_elem];			\
754 	if r0 == 0 goto l0_%=;				\
755 	r1 = 47;					\
756 	r0 += r1;					\
757 	r1 = 47;					\
758 	r0 -= r1;					\
759 	r0 = *(u8*)(r0 + 0);				\
760 l0_%=:	r0 = 1;						\
761 	exit;						\
762 "	:
763 	: __imm(bpf_map_lookup_elem),
764 	  __imm_addr(map_array_48b)
765 	: __clobber_all);
766 }
767 
768 SEC("socket")
769 __description("map access: known scalar += value_ptr")
770 __success __success_unpriv __retval(1)
access_known_scalar_value_ptr_1(void)771 __naked void access_known_scalar_value_ptr_1(void)
772 {
773 	asm volatile ("					\
774 	r1 = 0;						\
775 	*(u64*)(r10 - 8) = r1;				\
776 	r2 = r10;					\
777 	r2 += -8;					\
778 	r1 = %[map_array_48b] ll;			\
779 	call %[bpf_map_lookup_elem];			\
780 	if r0 == 0 goto l0_%=;				\
781 	r1 = 4;						\
782 	r1 += r0;					\
783 	r0 = *(u8*)(r1 + 0);				\
784 l0_%=:	r0 = 1;						\
785 	exit;						\
786 "	:
787 	: __imm(bpf_map_lookup_elem),
788 	  __imm_addr(map_array_48b)
789 	: __clobber_all);
790 }
791 
792 SEC("socket")
793 __description("map access: value_ptr += known scalar, 1")
794 __success __success_unpriv __retval(1)
value_ptr_known_scalar_1(void)795 __naked void value_ptr_known_scalar_1(void)
796 {
797 	asm volatile ("					\
798 	r1 = 0;						\
799 	*(u64*)(r10 - 8) = r1;				\
800 	r2 = r10;					\
801 	r2 += -8;					\
802 	r1 = %[map_array_48b] ll;			\
803 	call %[bpf_map_lookup_elem];			\
804 	if r0 == 0 goto l0_%=;				\
805 	r1 = 4;						\
806 	r0 += r1;					\
807 	r1 = *(u8*)(r0 + 0);				\
808 l0_%=:	r0 = 1;						\
809 	exit;						\
810 "	:
811 	: __imm(bpf_map_lookup_elem),
812 	  __imm_addr(map_array_48b)
813 	: __clobber_all);
814 }
815 
816 SEC("socket")
817 __description("map access: value_ptr += known scalar, 2")
818 __failure __msg("invalid access to map value")
819 __failure_unpriv
value_ptr_known_scalar_2_1(void)820 __naked void value_ptr_known_scalar_2_1(void)
821 {
822 	asm volatile ("					\
823 	r1 = 0;						\
824 	*(u64*)(r10 - 8) = r1;				\
825 	r2 = r10;					\
826 	r2 += -8;					\
827 	r1 = %[map_array_48b] ll;			\
828 	call %[bpf_map_lookup_elem];			\
829 	if r0 == 0 goto l0_%=;				\
830 	r1 = 49;					\
831 	r0 += r1;					\
832 	r1 = *(u8*)(r0 + 0);				\
833 l0_%=:	r0 = 1;						\
834 	exit;						\
835 "	:
836 	: __imm(bpf_map_lookup_elem),
837 	  __imm_addr(map_array_48b)
838 	: __clobber_all);
839 }
840 
841 SEC("socket")
842 __description("map access: value_ptr += known scalar, 3")
843 __failure __msg("invalid access to map value")
844 __failure_unpriv
value_ptr_known_scalar_3(void)845 __naked void value_ptr_known_scalar_3(void)
846 {
847 	asm volatile ("					\
848 	r1 = 0;						\
849 	*(u64*)(r10 - 8) = r1;				\
850 	r2 = r10;					\
851 	r2 += -8;					\
852 	r1 = %[map_array_48b] ll;			\
853 	call %[bpf_map_lookup_elem];			\
854 	if r0 == 0 goto l0_%=;				\
855 	r1 = -1;					\
856 	r0 += r1;					\
857 	r1 = *(u8*)(r0 + 0);				\
858 l0_%=:	r0 = 1;						\
859 	exit;						\
860 "	:
861 	: __imm(bpf_map_lookup_elem),
862 	  __imm_addr(map_array_48b)
863 	: __clobber_all);
864 }
865 
866 SEC("socket")
867 __description("map access: value_ptr += known scalar, 4")
868 __success __success_unpriv __retval(1)
value_ptr_known_scalar_4(void)869 __naked void value_ptr_known_scalar_4(void)
870 {
871 	asm volatile ("					\
872 	r1 = 0;						\
873 	*(u64*)(r10 - 8) = r1;				\
874 	r2 = r10;					\
875 	r2 += -8;					\
876 	r1 = %[map_array_48b] ll;			\
877 	call %[bpf_map_lookup_elem];			\
878 	if r0 == 0 goto l0_%=;				\
879 	r1 = 5;						\
880 	r0 += r1;					\
881 	r1 = -2;					\
882 	r0 += r1;					\
883 	r1 = -1;					\
884 	r0 += r1;					\
885 	r1 = *(u8*)(r0 + 0);				\
886 l0_%=:	r0 = 1;						\
887 	exit;						\
888 "	:
889 	: __imm(bpf_map_lookup_elem),
890 	  __imm_addr(map_array_48b)
891 	: __clobber_all);
892 }
893 
894 SEC("socket")
895 __description("map access: value_ptr += known scalar, 5")
896 __success __success_unpriv __retval(0xabcdef12)
value_ptr_known_scalar_5(void)897 __naked void value_ptr_known_scalar_5(void)
898 {
899 	asm volatile ("					\
900 	r1 = 0;						\
901 	*(u64*)(r10 - 8) = r1;				\
902 	r2 = r10;					\
903 	r2 += -8;					\
904 	r1 = %[map_array_48b] ll;			\
905 	call %[bpf_map_lookup_elem];			\
906 	if r0 == 0 goto l0_%=;				\
907 	r1 = %[__imm_0];				\
908 	r1 += r0;					\
909 	r0 = *(u32*)(r1 + 0);				\
910 l0_%=:	exit;						\
911 "	:
912 	: __imm(bpf_map_lookup_elem),
913 	  __imm_addr(map_array_48b),
914 	  __imm_const(__imm_0, (6 + 1) * sizeof(int))
915 	: __clobber_all);
916 }
917 
918 SEC("socket")
919 __description("map access: value_ptr += known scalar, 6")
920 __success __success_unpriv __retval(0xabcdef12)
value_ptr_known_scalar_6(void)921 __naked void value_ptr_known_scalar_6(void)
922 {
923 	asm volatile ("					\
924 	r1 = 0;						\
925 	*(u64*)(r10 - 8) = r1;				\
926 	r2 = r10;					\
927 	r2 += -8;					\
928 	r1 = %[map_array_48b] ll;			\
929 	call %[bpf_map_lookup_elem];			\
930 	if r0 == 0 goto l0_%=;				\
931 	r1 = %[__imm_0];				\
932 	r0 += r1;					\
933 	r1 = %[__imm_1];				\
934 	r0 += r1;					\
935 	r0 = *(u32*)(r0 + 0);				\
936 l0_%=:	exit;						\
937 "	:
938 	: __imm(bpf_map_lookup_elem),
939 	  __imm_addr(map_array_48b),
940 	  __imm_const(__imm_0, (3 + 1) * sizeof(int)),
941 	  __imm_const(__imm_1, 3 * sizeof(int))
942 	: __clobber_all);
943 }
944 
945 SEC("socket")
946 __description("map access: value_ptr += N, value_ptr -= N known scalar")
947 __success __success_unpriv __retval(0x12345678)
value_ptr_n_known_scalar(void)948 __naked void value_ptr_n_known_scalar(void)
949 {
950 	asm volatile ("					\
951 	r1 = 0;						\
952 	*(u64*)(r10 - 8) = r1;				\
953 	r2 = r10;					\
954 	r2 += -8;					\
955 	r1 = %[map_array_48b] ll;			\
956 	call %[bpf_map_lookup_elem];			\
957 	if r0 == 0 goto l0_%=;				\
958 	w1 = 0x12345678;				\
959 	*(u32*)(r0 + 0) = r1;				\
960 	r0 += 2;					\
961 	r1 = 2;						\
962 	r0 -= r1;					\
963 	r0 = *(u32*)(r0 + 0);				\
964 l0_%=:	exit;						\
965 "	:
966 	: __imm(bpf_map_lookup_elem),
967 	  __imm_addr(map_array_48b)
968 	: __clobber_all);
969 }
970 
971 SEC("socket")
972 __description("map access: unknown scalar += value_ptr, 1")
973 __success __success_unpriv __retval(1)
unknown_scalar_value_ptr_1(void)974 __naked void unknown_scalar_value_ptr_1(void)
975 {
976 	asm volatile ("					\
977 	r1 = 0;						\
978 	*(u64*)(r10 - 8) = r1;				\
979 	r2 = r10;					\
980 	r2 += -8;					\
981 	r1 = %[map_array_48b] ll;			\
982 	call %[bpf_map_lookup_elem];			\
983 	if r0 == 0 goto l0_%=;				\
984 	r1 = *(u8*)(r0 + 0);				\
985 	r1 &= 0xf;					\
986 	r1 += r0;					\
987 	r0 = *(u8*)(r1 + 0);				\
988 l0_%=:	r0 = 1;						\
989 	exit;						\
990 "	:
991 	: __imm(bpf_map_lookup_elem),
992 	  __imm_addr(map_array_48b)
993 	: __clobber_all);
994 }
995 
996 SEC("socket")
997 __description("map access: unknown scalar += value_ptr, 2")
__flag(BPF_F_ANY_ALIGNMENT)998 __success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
999 __naked void unknown_scalar_value_ptr_2(void)
1000 {
1001 	asm volatile ("					\
1002 	r1 = 0;						\
1003 	*(u64*)(r10 - 8) = r1;				\
1004 	r2 = r10;					\
1005 	r2 += -8;					\
1006 	r1 = %[map_array_48b] ll;			\
1007 	call %[bpf_map_lookup_elem];			\
1008 	if r0 == 0 goto l0_%=;				\
1009 	r1 = *(u32*)(r0 + 0);				\
1010 	r1 &= 31;					\
1011 	r1 += r0;					\
1012 	r0 = *(u32*)(r1 + 0);				\
1013 l0_%=:	exit;						\
1014 "	:
1015 	: __imm(bpf_map_lookup_elem),
1016 	  __imm_addr(map_array_48b)
1017 	: __clobber_all);
1018 }
1019 
1020 SEC("socket")
1021 __description("map access: unknown scalar += value_ptr, 3")
1022 __success __failure_unpriv
1023 __msg_unpriv("R0 pointer arithmetic of map value goes out of range")
__flag(BPF_F_ANY_ALIGNMENT)1024 __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
1025 __naked void unknown_scalar_value_ptr_3(void)
1026 {
1027 	asm volatile ("					\
1028 	r1 = 0;						\
1029 	*(u64*)(r10 - 8) = r1;				\
1030 	r2 = r10;					\
1031 	r2 += -8;					\
1032 	r1 = %[map_array_48b] ll;			\
1033 	call %[bpf_map_lookup_elem];			\
1034 	if r0 == 0 goto l0_%=;				\
1035 	r1 = -1;					\
1036 	r0 += r1;					\
1037 	r1 = 1;						\
1038 	r0 += r1;					\
1039 	r1 = *(u32*)(r0 + 0);				\
1040 	r1 &= 31;					\
1041 	r1 += r0;					\
1042 	r0 = *(u32*)(r1 + 0);				\
1043 l0_%=:	exit;						\
1044 "	:
1045 	: __imm(bpf_map_lookup_elem),
1046 	  __imm_addr(map_array_48b)
1047 	: __clobber_all);
1048 }
1049 
1050 SEC("socket")
1051 __description("map access: unknown scalar += value_ptr, 4")
1052 __failure __msg("R1 max value is outside of the allowed memory range")
1053 __msg_unpriv("R1 pointer arithmetic of map value goes out of range")
__flag(BPF_F_ANY_ALIGNMENT)1054 __flag(BPF_F_ANY_ALIGNMENT)
1055 __naked void unknown_scalar_value_ptr_4(void)
1056 {
1057 	asm volatile ("					\
1058 	r1 = 0;						\
1059 	*(u64*)(r10 - 8) = r1;				\
1060 	r2 = r10;					\
1061 	r2 += -8;					\
1062 	r1 = %[map_array_48b] ll;			\
1063 	call %[bpf_map_lookup_elem];			\
1064 	if r0 == 0 goto l0_%=;				\
1065 	r1 = 19;					\
1066 	r0 += r1;					\
1067 	r1 = *(u32*)(r0 + 0);				\
1068 	r1 &= 31;					\
1069 	r1 += r0;					\
1070 	r0 = *(u32*)(r1 + 0);				\
1071 l0_%=:	exit;						\
1072 "	:
1073 	: __imm(bpf_map_lookup_elem),
1074 	  __imm_addr(map_array_48b)
1075 	: __clobber_all);
1076 }
1077 
1078 SEC("socket")
1079 __description("map access: value_ptr += unknown scalar, 1")
1080 __success __success_unpriv __retval(1)
value_ptr_unknown_scalar_1(void)1081 __naked void value_ptr_unknown_scalar_1(void)
1082 {
1083 	asm volatile ("					\
1084 	r1 = 0;						\
1085 	*(u64*)(r10 - 8) = r1;				\
1086 	r2 = r10;					\
1087 	r2 += -8;					\
1088 	r1 = %[map_array_48b] ll;			\
1089 	call %[bpf_map_lookup_elem];			\
1090 	if r0 == 0 goto l0_%=;				\
1091 	r1 = *(u8*)(r0 + 0);				\
1092 	r1 &= 0xf;					\
1093 	r0 += r1;					\
1094 	r1 = *(u8*)(r0 + 0);				\
1095 l0_%=:	r0 = 1;						\
1096 	exit;						\
1097 "	:
1098 	: __imm(bpf_map_lookup_elem),
1099 	  __imm_addr(map_array_48b)
1100 	: __clobber_all);
1101 }
1102 
1103 SEC("socket")
1104 __description("map access: value_ptr += unknown scalar, 2")
__flag(BPF_F_ANY_ALIGNMENT)1105 __success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
1106 __naked void value_ptr_unknown_scalar_2_1(void)
1107 {
1108 	asm volatile ("					\
1109 	r1 = 0;						\
1110 	*(u64*)(r10 - 8) = r1;				\
1111 	r2 = r10;					\
1112 	r2 += -8;					\
1113 	r1 = %[map_array_48b] ll;			\
1114 	call %[bpf_map_lookup_elem];			\
1115 	if r0 == 0 goto l0_%=;				\
1116 	r1 = *(u32*)(r0 + 0);				\
1117 	r1 &= 31;					\
1118 	r0 += r1;					\
1119 	r0 = *(u32*)(r0 + 0);				\
1120 l0_%=:	exit;						\
1121 "	:
1122 	: __imm(bpf_map_lookup_elem),
1123 	  __imm_addr(map_array_48b)
1124 	: __clobber_all);
1125 }
1126 
1127 SEC("socket")
1128 __description("map access: value_ptr += unknown scalar, 3")
1129 __success __success_unpriv __retval(1)
value_ptr_unknown_scalar_3(void)1130 __naked void value_ptr_unknown_scalar_3(void)
1131 {
1132 	asm volatile ("					\
1133 	r1 = 0;						\
1134 	*(u64*)(r10 - 8) = r1;				\
1135 	r2 = r10;					\
1136 	r2 += -8;					\
1137 	r1 = %[map_array_48b] ll;			\
1138 	call %[bpf_map_lookup_elem];			\
1139 	if r0 == 0 goto l0_%=;				\
1140 	r1 = *(u64*)(r0 + 0);				\
1141 	r2 = *(u64*)(r0 + 8);				\
1142 	r3 = *(u64*)(r0 + 16);				\
1143 	r1 &= 0xf;					\
1144 	r3 &= 1;					\
1145 	r3 |= 1;					\
1146 	if r2 > r3 goto l0_%=;				\
1147 	r0 += r3;					\
1148 	r0 = *(u8*)(r0 + 0);				\
1149 	r0 = 1;						\
1150 l1_%=:	exit;						\
1151 l0_%=:	r0 = 2;						\
1152 	goto l1_%=;					\
1153 "	:
1154 	: __imm(bpf_map_lookup_elem),
1155 	  __imm_addr(map_array_48b)
1156 	: __clobber_all);
1157 }
1158 
1159 SEC("socket")
1160 __description("map access: value_ptr += value_ptr")
1161 __failure __msg("R0 pointer += pointer prohibited")
1162 __failure_unpriv
access_value_ptr_value_ptr_1(void)1163 __naked void access_value_ptr_value_ptr_1(void)
1164 {
1165 	asm volatile ("					\
1166 	r1 = 0;						\
1167 	*(u64*)(r10 - 8) = r1;				\
1168 	r2 = r10;					\
1169 	r2 += -8;					\
1170 	r1 = %[map_array_48b] ll;			\
1171 	call %[bpf_map_lookup_elem];			\
1172 	if r0 == 0 goto l0_%=;				\
1173 	r0 += r0;					\
1174 	r1 = *(u8*)(r0 + 0);				\
1175 l0_%=:	r0 = 1;						\
1176 	exit;						\
1177 "	:
1178 	: __imm(bpf_map_lookup_elem),
1179 	  __imm_addr(map_array_48b)
1180 	: __clobber_all);
1181 }
1182 
1183 SEC("socket")
1184 __description("map access: known scalar -= value_ptr")
1185 __failure __msg("R1 tried to subtract pointer from scalar")
1186 __failure_unpriv
access_known_scalar_value_ptr_2(void)1187 __naked void access_known_scalar_value_ptr_2(void)
1188 {
1189 	asm volatile ("					\
1190 	r1 = 0;						\
1191 	*(u64*)(r10 - 8) = r1;				\
1192 	r2 = r10;					\
1193 	r2 += -8;					\
1194 	r1 = %[map_array_48b] ll;			\
1195 	call %[bpf_map_lookup_elem];			\
1196 	if r0 == 0 goto l0_%=;				\
1197 	r1 = 4;						\
1198 	r1 -= r0;					\
1199 	r0 = *(u8*)(r1 + 0);				\
1200 l0_%=:	r0 = 1;						\
1201 	exit;						\
1202 "	:
1203 	: __imm(bpf_map_lookup_elem),
1204 	  __imm_addr(map_array_48b)
1205 	: __clobber_all);
1206 }
1207 
1208 SEC("socket")
1209 __description("map access: value_ptr -= known scalar")
1210 __failure __msg("R0 min value is outside of the allowed memory range")
1211 __failure_unpriv
access_value_ptr_known_scalar(void)1212 __naked void access_value_ptr_known_scalar(void)
1213 {
1214 	asm volatile ("					\
1215 	r1 = 0;						\
1216 	*(u64*)(r10 - 8) = r1;				\
1217 	r2 = r10;					\
1218 	r2 += -8;					\
1219 	r1 = %[map_array_48b] ll;			\
1220 	call %[bpf_map_lookup_elem];			\
1221 	if r0 == 0 goto l0_%=;				\
1222 	r1 = 4;						\
1223 	r0 -= r1;					\
1224 	r1 = *(u8*)(r0 + 0);				\
1225 l0_%=:	r0 = 1;						\
1226 	exit;						\
1227 "	:
1228 	: __imm(bpf_map_lookup_elem),
1229 	  __imm_addr(map_array_48b)
1230 	: __clobber_all);
1231 }
1232 
1233 SEC("socket")
1234 __description("map access: value_ptr -= known scalar, 2")
1235 __success __success_unpriv __retval(1)
value_ptr_known_scalar_2_2(void)1236 __naked void value_ptr_known_scalar_2_2(void)
1237 {
1238 	asm volatile ("					\
1239 	r1 = 0;						\
1240 	*(u64*)(r10 - 8) = r1;				\
1241 	r2 = r10;					\
1242 	r2 += -8;					\
1243 	r1 = %[map_array_48b] ll;			\
1244 	call %[bpf_map_lookup_elem];			\
1245 	if r0 == 0 goto l0_%=;				\
1246 	r1 = 6;						\
1247 	r2 = 4;						\
1248 	r0 += r1;					\
1249 	r0 -= r2;					\
1250 	r1 = *(u8*)(r0 + 0);				\
1251 l0_%=:	r0 = 1;						\
1252 	exit;						\
1253 "	:
1254 	: __imm(bpf_map_lookup_elem),
1255 	  __imm_addr(map_array_48b)
1256 	: __clobber_all);
1257 }
1258 
1259 SEC("socket")
1260 __description("map access: unknown scalar -= value_ptr")
1261 __failure __msg("R1 tried to subtract pointer from scalar")
1262 __failure_unpriv
access_unknown_scalar_value_ptr(void)1263 __naked void access_unknown_scalar_value_ptr(void)
1264 {
1265 	asm volatile ("					\
1266 	r1 = 0;						\
1267 	*(u64*)(r10 - 8) = r1;				\
1268 	r2 = r10;					\
1269 	r2 += -8;					\
1270 	r1 = %[map_array_48b] ll;			\
1271 	call %[bpf_map_lookup_elem];			\
1272 	if r0 == 0 goto l0_%=;				\
1273 	r1 = *(u8*)(r0 + 0);				\
1274 	r1 &= 0xf;					\
1275 	r1 -= r0;					\
1276 	r0 = *(u8*)(r1 + 0);				\
1277 l0_%=:	r0 = 1;						\
1278 	exit;						\
1279 "	:
1280 	: __imm(bpf_map_lookup_elem),
1281 	  __imm_addr(map_array_48b)
1282 	: __clobber_all);
1283 }
1284 
1285 SEC("socket")
1286 __description("map access: value_ptr -= unknown scalar")
1287 __failure __msg("R0 min value is negative")
1288 __failure_unpriv
access_value_ptr_unknown_scalar(void)1289 __naked void access_value_ptr_unknown_scalar(void)
1290 {
1291 	asm volatile ("					\
1292 	r1 = 0;						\
1293 	*(u64*)(r10 - 8) = r1;				\
1294 	r2 = r10;					\
1295 	r2 += -8;					\
1296 	r1 = %[map_array_48b] ll;			\
1297 	call %[bpf_map_lookup_elem];			\
1298 	if r0 == 0 goto l0_%=;				\
1299 	r1 = *(u8*)(r0 + 0);				\
1300 	r1 &= 0xf;					\
1301 	r0 -= r1;					\
1302 	r1 = *(u8*)(r0 + 0);				\
1303 l0_%=:	r0 = 1;						\
1304 	exit;						\
1305 "	:
1306 	: __imm(bpf_map_lookup_elem),
1307 	  __imm_addr(map_array_48b)
1308 	: __clobber_all);
1309 }
1310 
1311 SEC("socket")
1312 __description("map access: value_ptr -= unknown scalar, 2")
1313 __success __success_unpriv
1314 __retval(1)
1315 #ifdef SPEC_V1
1316 __xlated_unpriv("r1 &= 7")
1317 __xlated_unpriv("nospec") /* inserted to prevent `R0 pointer arithmetic of map value goes out of range` */
1318 __xlated_unpriv("r0 -= r1")
1319 #endif
value_ptr_unknown_scalar_2_2(void)1320 __naked void value_ptr_unknown_scalar_2_2(void)
1321 {
1322 	asm volatile ("					\
1323 	r1 = 0;						\
1324 	*(u64*)(r10 - 8) = r1;				\
1325 	r2 = r10;					\
1326 	r2 += -8;					\
1327 	r1 = %[map_array_48b] ll;			\
1328 	call %[bpf_map_lookup_elem];			\
1329 	if r0 == 0 goto l0_%=;				\
1330 	r1 = *(u8*)(r0 + 0);				\
1331 	r1 &= 0xf;					\
1332 	r1 |= 0x7;					\
1333 	r0 += r1;					\
1334 	r1 = *(u8*)(r0 + 0);				\
1335 	r1 &= 0x7;					\
1336 	r0 -= r1;					\
1337 	r1 = *(u8*)(r0 + 0);				\
1338 l0_%=:	r0 = 1;						\
1339 	exit;						\
1340 "	:
1341 	: __imm(bpf_map_lookup_elem),
1342 	  __imm_addr(map_array_48b)
1343 	: __clobber_all);
1344 }
1345 
1346 SEC("socket")
1347 __description("map access: value_ptr -= value_ptr")
1348 __failure __msg("R0 invalid mem access 'scalar'")
1349 __msg_unpriv("R0 pointer -= pointer prohibited")
access_value_ptr_value_ptr_2(void)1350 __naked void access_value_ptr_value_ptr_2(void)
1351 {
1352 	asm volatile ("					\
1353 	r1 = 0;						\
1354 	*(u64*)(r10 - 8) = r1;				\
1355 	r2 = r10;					\
1356 	r2 += -8;					\
1357 	r1 = %[map_array_48b] ll;			\
1358 	call %[bpf_map_lookup_elem];			\
1359 	if r0 == 0 goto l0_%=;				\
1360 	r0 -= r0;					\
1361 	r1 = *(u8*)(r0 + 0);				\
1362 l0_%=:	r0 = 1;						\
1363 	exit;						\
1364 "	:
1365 	: __imm(bpf_map_lookup_elem),
1366 	  __imm_addr(map_array_48b)
1367 	: __clobber_all);
1368 }
1369 
1370 SEC("socket")
1371 __description("map access: trying to leak tainted dst reg")
1372 __failure __msg("math between map_value pointer and 4294967295 is not allowed")
1373 __failure_unpriv
to_leak_tainted_dst_reg(void)1374 __naked void to_leak_tainted_dst_reg(void)
1375 {
1376 	asm volatile ("					\
1377 	r0 = 0;						\
1378 	r1 = 0;						\
1379 	*(u64*)(r10 - 8) = r1;				\
1380 	r2 = r10;					\
1381 	r2 += -8;					\
1382 	r1 = %[map_array_48b] ll;			\
1383 	call %[bpf_map_lookup_elem];			\
1384 	if r0 != 0 goto l0_%=;				\
1385 	exit;						\
1386 l0_%=:	r2 = r0;					\
1387 	w1 = 0xFFFFFFFF;				\
1388 	w1 = w1;					\
1389 	r2 -= r1;					\
1390 	*(u64*)(r0 + 0) = r2;				\
1391 	r0 = 0;						\
1392 	exit;						\
1393 "	:
1394 	: __imm(bpf_map_lookup_elem),
1395 	  __imm_addr(map_array_48b)
1396 	: __clobber_all);
1397 }
1398 
1399 SEC("tc")
1400 __description("32bit pkt_ptr -= scalar")
__flag(BPF_F_ANY_ALIGNMENT)1401 __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
1402 __naked void _32bit_pkt_ptr_scalar(void)
1403 {
1404 	asm volatile ("					\
1405 	r8 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
1406 	r7 = *(u32*)(r1 + %[__sk_buff_data]);		\
1407 	r6 = r7;					\
1408 	r6 += 40;					\
1409 	if r6 > r8 goto l0_%=;				\
1410 	w4 = w7;					\
1411 	w6 -= w4;					\
1412 l0_%=:	r0 = 0;						\
1413 	exit;						\
1414 "	:
1415 	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
1416 	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
1417 	: __clobber_all);
1418 }
1419 
1420 SEC("tc")
1421 __description("32bit scalar -= pkt_ptr")
__flag(BPF_F_ANY_ALIGNMENT)1422 __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
1423 __naked void _32bit_scalar_pkt_ptr(void)
1424 {
1425 	asm volatile ("					\
1426 	r8 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
1427 	r7 = *(u32*)(r1 + %[__sk_buff_data]);		\
1428 	r6 = r7;					\
1429 	r6 += 40;					\
1430 	if r6 > r8 goto l0_%=;				\
1431 	w4 = w6;					\
1432 	w4 -= w7;					\
1433 l0_%=:	r0 = 0;						\
1434 	exit;						\
1435 "	:
1436 	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
1437 	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
1438 	: __clobber_all);
1439 }
1440 
1441 char _license[] SEC("license") = "GPL";
1442