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