xref: /linux/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c (revision 022ac075088366b62e130da5e1b200bc93a47191)
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 	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)
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)
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 negative")
350 __retval(1)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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 negative")
687 __naked void lower_oob_arith_test_1(void)
688 {
689 	asm volatile ("					\
690 	r1 = 0;						\
691 	*(u64*)(r10 - 8) = r1;				\
692 	r2 = r10;					\
693 	r2 += -8;					\
694 	r1 = %[map_array_48b] ll;			\
695 	call %[bpf_map_lookup_elem];			\
696 	if r0 == 0 goto l0_%=;				\
697 	r1 = 47;					\
698 	r0 += r1;					\
699 	r1 = 48;					\
700 	r0 -= r1;					\
701 	r0 = *(u8*)(r0 + 0);				\
702 l0_%=:	r0 = 1;						\
703 	exit;						\
704 "	:
705 	: __imm(bpf_map_lookup_elem),
706 	  __imm_addr(map_array_48b)
707 	: __clobber_all);
708 }
709 
710 SEC("socket")
711 __description("map access: value_ptr -= known scalar, lower oob arith, test 2")
712 __success __failure_unpriv
713 __msg_unpriv("R0 pointer arithmetic of map value goes out of range")
714 __retval(1)
715 __naked void lower_oob_arith_test_2(void)
716 {
717 	asm volatile ("					\
718 	r1 = 0;						\
719 	*(u64*)(r10 - 8) = r1;				\
720 	r2 = r10;					\
721 	r2 += -8;					\
722 	r1 = %[map_array_48b] ll;			\
723 	call %[bpf_map_lookup_elem];			\
724 	if r0 == 0 goto l0_%=;				\
725 	r1 = 47;					\
726 	r0 += r1;					\
727 	r1 = 48;					\
728 	r0 -= r1;					\
729 	r1 = 1;						\
730 	r0 += r1;					\
731 	r0 = *(u8*)(r0 + 0);				\
732 l0_%=:	r0 = 1;						\
733 	exit;						\
734 "	:
735 	: __imm(bpf_map_lookup_elem),
736 	  __imm_addr(map_array_48b)
737 	: __clobber_all);
738 }
739 
740 SEC("socket")
741 __description("map access: value_ptr -= known scalar, lower oob arith, test 3")
742 __success __success_unpriv __retval(1)
743 __naked void lower_oob_arith_test_3(void)
744 {
745 	asm volatile ("					\
746 	r1 = 0;						\
747 	*(u64*)(r10 - 8) = r1;				\
748 	r2 = r10;					\
749 	r2 += -8;					\
750 	r1 = %[map_array_48b] ll;			\
751 	call %[bpf_map_lookup_elem];			\
752 	if r0 == 0 goto l0_%=;				\
753 	r1 = 47;					\
754 	r0 += r1;					\
755 	r1 = 47;					\
756 	r0 -= r1;					\
757 	r0 = *(u8*)(r0 + 0);				\
758 l0_%=:	r0 = 1;						\
759 	exit;						\
760 "	:
761 	: __imm(bpf_map_lookup_elem),
762 	  __imm_addr(map_array_48b)
763 	: __clobber_all);
764 }
765 
766 SEC("socket")
767 __description("map access: known scalar += value_ptr")
768 __success __success_unpriv __retval(1)
769 __naked void access_known_scalar_value_ptr_1(void)
770 {
771 	asm volatile ("					\
772 	r1 = 0;						\
773 	*(u64*)(r10 - 8) = r1;				\
774 	r2 = r10;					\
775 	r2 += -8;					\
776 	r1 = %[map_array_48b] ll;			\
777 	call %[bpf_map_lookup_elem];			\
778 	if r0 == 0 goto l0_%=;				\
779 	r1 = 4;						\
780 	r1 += r0;					\
781 	r0 = *(u8*)(r1 + 0);				\
782 l0_%=:	r0 = 1;						\
783 	exit;						\
784 "	:
785 	: __imm(bpf_map_lookup_elem),
786 	  __imm_addr(map_array_48b)
787 	: __clobber_all);
788 }
789 
790 SEC("socket")
791 __description("map access: value_ptr += known scalar, 1")
792 __success __success_unpriv __retval(1)
793 __naked void value_ptr_known_scalar_1(void)
794 {
795 	asm volatile ("					\
796 	r1 = 0;						\
797 	*(u64*)(r10 - 8) = r1;				\
798 	r2 = r10;					\
799 	r2 += -8;					\
800 	r1 = %[map_array_48b] ll;			\
801 	call %[bpf_map_lookup_elem];			\
802 	if r0 == 0 goto l0_%=;				\
803 	r1 = 4;						\
804 	r0 += r1;					\
805 	r1 = *(u8*)(r0 + 0);				\
806 l0_%=:	r0 = 1;						\
807 	exit;						\
808 "	:
809 	: __imm(bpf_map_lookup_elem),
810 	  __imm_addr(map_array_48b)
811 	: __clobber_all);
812 }
813 
814 SEC("socket")
815 __description("map access: value_ptr += known scalar, 2")
816 __failure __msg("invalid access to map value")
817 __failure_unpriv
818 __naked void value_ptr_known_scalar_2_1(void)
819 {
820 	asm volatile ("					\
821 	r1 = 0;						\
822 	*(u64*)(r10 - 8) = r1;				\
823 	r2 = r10;					\
824 	r2 += -8;					\
825 	r1 = %[map_array_48b] ll;			\
826 	call %[bpf_map_lookup_elem];			\
827 	if r0 == 0 goto l0_%=;				\
828 	r1 = 49;					\
829 	r0 += r1;					\
830 	r1 = *(u8*)(r0 + 0);				\
831 l0_%=:	r0 = 1;						\
832 	exit;						\
833 "	:
834 	: __imm(bpf_map_lookup_elem),
835 	  __imm_addr(map_array_48b)
836 	: __clobber_all);
837 }
838 
839 SEC("socket")
840 __description("map access: value_ptr += known scalar, 3")
841 __failure __msg("R0 min value is negative")
842 __failure_unpriv
843 __naked void value_ptr_known_scalar_3(void)
844 {
845 	asm volatile ("					\
846 	r1 = 0;						\
847 	*(u64*)(r10 - 8) = r1;				\
848 	r2 = r10;					\
849 	r2 += -8;					\
850 	r1 = %[map_array_48b] ll;			\
851 	call %[bpf_map_lookup_elem];			\
852 	if r0 == 0 goto l0_%=;				\
853 	r1 = -1;					\
854 	r0 += r1;					\
855 	r1 = *(u8*)(r0 + 0);				\
856 l0_%=:	r0 = 1;						\
857 	exit;						\
858 "	:
859 	: __imm(bpf_map_lookup_elem),
860 	  __imm_addr(map_array_48b)
861 	: __clobber_all);
862 }
863 
864 SEC("socket")
865 __description("map access: value_ptr += known scalar, 4")
866 __success __success_unpriv __retval(1)
867 __naked void value_ptr_known_scalar_4(void)
868 {
869 	asm volatile ("					\
870 	r1 = 0;						\
871 	*(u64*)(r10 - 8) = r1;				\
872 	r2 = r10;					\
873 	r2 += -8;					\
874 	r1 = %[map_array_48b] ll;			\
875 	call %[bpf_map_lookup_elem];			\
876 	if r0 == 0 goto l0_%=;				\
877 	r1 = 5;						\
878 	r0 += r1;					\
879 	r1 = -2;					\
880 	r0 += r1;					\
881 	r1 = -1;					\
882 	r0 += r1;					\
883 	r1 = *(u8*)(r0 + 0);				\
884 l0_%=:	r0 = 1;						\
885 	exit;						\
886 "	:
887 	: __imm(bpf_map_lookup_elem),
888 	  __imm_addr(map_array_48b)
889 	: __clobber_all);
890 }
891 
892 SEC("socket")
893 __description("map access: value_ptr += known scalar, 5")
894 __success __success_unpriv __retval(0xabcdef12)
895 __naked void value_ptr_known_scalar_5(void)
896 {
897 	asm volatile ("					\
898 	r1 = 0;						\
899 	*(u64*)(r10 - 8) = r1;				\
900 	r2 = r10;					\
901 	r2 += -8;					\
902 	r1 = %[map_array_48b] ll;			\
903 	call %[bpf_map_lookup_elem];			\
904 	if r0 == 0 goto l0_%=;				\
905 	r1 = %[__imm_0];				\
906 	r1 += r0;					\
907 	r0 = *(u32*)(r1 + 0);				\
908 l0_%=:	exit;						\
909 "	:
910 	: __imm(bpf_map_lookup_elem),
911 	  __imm_addr(map_array_48b),
912 	  __imm_const(__imm_0, (6 + 1) * sizeof(int))
913 	: __clobber_all);
914 }
915 
916 SEC("socket")
917 __description("map access: value_ptr += known scalar, 6")
918 __success __success_unpriv __retval(0xabcdef12)
919 __naked void value_ptr_known_scalar_6(void)
920 {
921 	asm volatile ("					\
922 	r1 = 0;						\
923 	*(u64*)(r10 - 8) = r1;				\
924 	r2 = r10;					\
925 	r2 += -8;					\
926 	r1 = %[map_array_48b] ll;			\
927 	call %[bpf_map_lookup_elem];			\
928 	if r0 == 0 goto l0_%=;				\
929 	r1 = %[__imm_0];				\
930 	r0 += r1;					\
931 	r1 = %[__imm_1];				\
932 	r0 += r1;					\
933 	r0 = *(u32*)(r0 + 0);				\
934 l0_%=:	exit;						\
935 "	:
936 	: __imm(bpf_map_lookup_elem),
937 	  __imm_addr(map_array_48b),
938 	  __imm_const(__imm_0, (3 + 1) * sizeof(int)),
939 	  __imm_const(__imm_1, 3 * sizeof(int))
940 	: __clobber_all);
941 }
942 
943 SEC("socket")
944 __description("map access: value_ptr += N, value_ptr -= N known scalar")
945 __success __success_unpriv __retval(0x12345678)
946 __naked void value_ptr_n_known_scalar(void)
947 {
948 	asm volatile ("					\
949 	r1 = 0;						\
950 	*(u64*)(r10 - 8) = r1;				\
951 	r2 = r10;					\
952 	r2 += -8;					\
953 	r1 = %[map_array_48b] ll;			\
954 	call %[bpf_map_lookup_elem];			\
955 	if r0 == 0 goto l0_%=;				\
956 	w1 = 0x12345678;				\
957 	*(u32*)(r0 + 0) = r1;				\
958 	r0 += 2;					\
959 	r1 = 2;						\
960 	r0 -= r1;					\
961 	r0 = *(u32*)(r0 + 0);				\
962 l0_%=:	exit;						\
963 "	:
964 	: __imm(bpf_map_lookup_elem),
965 	  __imm_addr(map_array_48b)
966 	: __clobber_all);
967 }
968 
969 SEC("socket")
970 __description("map access: unknown scalar += value_ptr, 1")
971 __success __success_unpriv __retval(1)
972 __naked void unknown_scalar_value_ptr_1(void)
973 {
974 	asm volatile ("					\
975 	r1 = 0;						\
976 	*(u64*)(r10 - 8) = r1;				\
977 	r2 = r10;					\
978 	r2 += -8;					\
979 	r1 = %[map_array_48b] ll;			\
980 	call %[bpf_map_lookup_elem];			\
981 	if r0 == 0 goto l0_%=;				\
982 	r1 = *(u8*)(r0 + 0);				\
983 	r1 &= 0xf;					\
984 	r1 += r0;					\
985 	r0 = *(u8*)(r1 + 0);				\
986 l0_%=:	r0 = 1;						\
987 	exit;						\
988 "	:
989 	: __imm(bpf_map_lookup_elem),
990 	  __imm_addr(map_array_48b)
991 	: __clobber_all);
992 }
993 
994 SEC("socket")
995 __description("map access: unknown scalar += value_ptr, 2")
996 __success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
997 __naked void unknown_scalar_value_ptr_2(void)
998 {
999 	asm volatile ("					\
1000 	r1 = 0;						\
1001 	*(u64*)(r10 - 8) = r1;				\
1002 	r2 = r10;					\
1003 	r2 += -8;					\
1004 	r1 = %[map_array_48b] ll;			\
1005 	call %[bpf_map_lookup_elem];			\
1006 	if r0 == 0 goto l0_%=;				\
1007 	r1 = *(u32*)(r0 + 0);				\
1008 	r1 &= 31;					\
1009 	r1 += r0;					\
1010 	r0 = *(u32*)(r1 + 0);				\
1011 l0_%=:	exit;						\
1012 "	:
1013 	: __imm(bpf_map_lookup_elem),
1014 	  __imm_addr(map_array_48b)
1015 	: __clobber_all);
1016 }
1017 
1018 SEC("socket")
1019 __description("map access: unknown scalar += value_ptr, 3")
1020 __success __failure_unpriv
1021 __msg_unpriv("R0 pointer arithmetic of map value goes out of range")
1022 __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
1023 __naked void unknown_scalar_value_ptr_3(void)
1024 {
1025 	asm volatile ("					\
1026 	r1 = 0;						\
1027 	*(u64*)(r10 - 8) = r1;				\
1028 	r2 = r10;					\
1029 	r2 += -8;					\
1030 	r1 = %[map_array_48b] ll;			\
1031 	call %[bpf_map_lookup_elem];			\
1032 	if r0 == 0 goto l0_%=;				\
1033 	r1 = -1;					\
1034 	r0 += r1;					\
1035 	r1 = 1;						\
1036 	r0 += r1;					\
1037 	r1 = *(u32*)(r0 + 0);				\
1038 	r1 &= 31;					\
1039 	r1 += r0;					\
1040 	r0 = *(u32*)(r1 + 0);				\
1041 l0_%=:	exit;						\
1042 "	:
1043 	: __imm(bpf_map_lookup_elem),
1044 	  __imm_addr(map_array_48b)
1045 	: __clobber_all);
1046 }
1047 
1048 SEC("socket")
1049 __description("map access: unknown scalar += value_ptr, 4")
1050 __failure __msg("R1 max value is outside of the allowed memory range")
1051 __msg_unpriv("R1 pointer arithmetic of map value goes out of range")
1052 __flag(BPF_F_ANY_ALIGNMENT)
1053 __naked void unknown_scalar_value_ptr_4(void)
1054 {
1055 	asm volatile ("					\
1056 	r1 = 0;						\
1057 	*(u64*)(r10 - 8) = r1;				\
1058 	r2 = r10;					\
1059 	r2 += -8;					\
1060 	r1 = %[map_array_48b] ll;			\
1061 	call %[bpf_map_lookup_elem];			\
1062 	if r0 == 0 goto l0_%=;				\
1063 	r1 = 19;					\
1064 	r0 += r1;					\
1065 	r1 = *(u32*)(r0 + 0);				\
1066 	r1 &= 31;					\
1067 	r1 += r0;					\
1068 	r0 = *(u32*)(r1 + 0);				\
1069 l0_%=:	exit;						\
1070 "	:
1071 	: __imm(bpf_map_lookup_elem),
1072 	  __imm_addr(map_array_48b)
1073 	: __clobber_all);
1074 }
1075 
1076 SEC("socket")
1077 __description("map access: value_ptr += unknown scalar, 1")
1078 __success __success_unpriv __retval(1)
1079 __naked void value_ptr_unknown_scalar_1(void)
1080 {
1081 	asm volatile ("					\
1082 	r1 = 0;						\
1083 	*(u64*)(r10 - 8) = r1;				\
1084 	r2 = r10;					\
1085 	r2 += -8;					\
1086 	r1 = %[map_array_48b] ll;			\
1087 	call %[bpf_map_lookup_elem];			\
1088 	if r0 == 0 goto l0_%=;				\
1089 	r1 = *(u8*)(r0 + 0);				\
1090 	r1 &= 0xf;					\
1091 	r0 += r1;					\
1092 	r1 = *(u8*)(r0 + 0);				\
1093 l0_%=:	r0 = 1;						\
1094 	exit;						\
1095 "	:
1096 	: __imm(bpf_map_lookup_elem),
1097 	  __imm_addr(map_array_48b)
1098 	: __clobber_all);
1099 }
1100 
1101 SEC("socket")
1102 __description("map access: value_ptr += unknown scalar, 2")
1103 __success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
1104 __naked void value_ptr_unknown_scalar_2_1(void)
1105 {
1106 	asm volatile ("					\
1107 	r1 = 0;						\
1108 	*(u64*)(r10 - 8) = r1;				\
1109 	r2 = r10;					\
1110 	r2 += -8;					\
1111 	r1 = %[map_array_48b] ll;			\
1112 	call %[bpf_map_lookup_elem];			\
1113 	if r0 == 0 goto l0_%=;				\
1114 	r1 = *(u32*)(r0 + 0);				\
1115 	r1 &= 31;					\
1116 	r0 += r1;					\
1117 	r0 = *(u32*)(r0 + 0);				\
1118 l0_%=:	exit;						\
1119 "	:
1120 	: __imm(bpf_map_lookup_elem),
1121 	  __imm_addr(map_array_48b)
1122 	: __clobber_all);
1123 }
1124 
1125 SEC("socket")
1126 __description("map access: value_ptr += unknown scalar, 3")
1127 __success __success_unpriv __retval(1)
1128 __naked void value_ptr_unknown_scalar_3(void)
1129 {
1130 	asm volatile ("					\
1131 	r1 = 0;						\
1132 	*(u64*)(r10 - 8) = r1;				\
1133 	r2 = r10;					\
1134 	r2 += -8;					\
1135 	r1 = %[map_array_48b] ll;			\
1136 	call %[bpf_map_lookup_elem];			\
1137 	if r0 == 0 goto l0_%=;				\
1138 	r1 = *(u64*)(r0 + 0);				\
1139 	r2 = *(u64*)(r0 + 8);				\
1140 	r3 = *(u64*)(r0 + 16);				\
1141 	r1 &= 0xf;					\
1142 	r3 &= 1;					\
1143 	r3 |= 1;					\
1144 	if r2 > r3 goto l0_%=;				\
1145 	r0 += r3;					\
1146 	r0 = *(u8*)(r0 + 0);				\
1147 	r0 = 1;						\
1148 l1_%=:	exit;						\
1149 l0_%=:	r0 = 2;						\
1150 	goto l1_%=;					\
1151 "	:
1152 	: __imm(bpf_map_lookup_elem),
1153 	  __imm_addr(map_array_48b)
1154 	: __clobber_all);
1155 }
1156 
1157 SEC("socket")
1158 __description("map access: value_ptr += value_ptr")
1159 __failure __msg("R0 pointer += pointer prohibited")
1160 __failure_unpriv
1161 __naked void access_value_ptr_value_ptr_1(void)
1162 {
1163 	asm volatile ("					\
1164 	r1 = 0;						\
1165 	*(u64*)(r10 - 8) = r1;				\
1166 	r2 = r10;					\
1167 	r2 += -8;					\
1168 	r1 = %[map_array_48b] ll;			\
1169 	call %[bpf_map_lookup_elem];			\
1170 	if r0 == 0 goto l0_%=;				\
1171 	r0 += r0;					\
1172 	r1 = *(u8*)(r0 + 0);				\
1173 l0_%=:	r0 = 1;						\
1174 	exit;						\
1175 "	:
1176 	: __imm(bpf_map_lookup_elem),
1177 	  __imm_addr(map_array_48b)
1178 	: __clobber_all);
1179 }
1180 
1181 SEC("socket")
1182 __description("map access: known scalar -= value_ptr")
1183 __failure __msg("R1 tried to subtract pointer from scalar")
1184 __failure_unpriv
1185 __naked void access_known_scalar_value_ptr_2(void)
1186 {
1187 	asm volatile ("					\
1188 	r1 = 0;						\
1189 	*(u64*)(r10 - 8) = r1;				\
1190 	r2 = r10;					\
1191 	r2 += -8;					\
1192 	r1 = %[map_array_48b] ll;			\
1193 	call %[bpf_map_lookup_elem];			\
1194 	if r0 == 0 goto l0_%=;				\
1195 	r1 = 4;						\
1196 	r1 -= r0;					\
1197 	r0 = *(u8*)(r1 + 0);				\
1198 l0_%=:	r0 = 1;						\
1199 	exit;						\
1200 "	:
1201 	: __imm(bpf_map_lookup_elem),
1202 	  __imm_addr(map_array_48b)
1203 	: __clobber_all);
1204 }
1205 
1206 SEC("socket")
1207 __description("map access: value_ptr -= known scalar")
1208 __failure __msg("R0 min value is negative")
1209 __failure_unpriv
1210 __naked void access_value_ptr_known_scalar(void)
1211 {
1212 	asm volatile ("					\
1213 	r1 = 0;						\
1214 	*(u64*)(r10 - 8) = r1;				\
1215 	r2 = r10;					\
1216 	r2 += -8;					\
1217 	r1 = %[map_array_48b] ll;			\
1218 	call %[bpf_map_lookup_elem];			\
1219 	if r0 == 0 goto l0_%=;				\
1220 	r1 = 4;						\
1221 	r0 -= r1;					\
1222 	r1 = *(u8*)(r0 + 0);				\
1223 l0_%=:	r0 = 1;						\
1224 	exit;						\
1225 "	:
1226 	: __imm(bpf_map_lookup_elem),
1227 	  __imm_addr(map_array_48b)
1228 	: __clobber_all);
1229 }
1230 
1231 SEC("socket")
1232 __description("map access: value_ptr -= known scalar, 2")
1233 __success __success_unpriv __retval(1)
1234 __naked void value_ptr_known_scalar_2_2(void)
1235 {
1236 	asm volatile ("					\
1237 	r1 = 0;						\
1238 	*(u64*)(r10 - 8) = r1;				\
1239 	r2 = r10;					\
1240 	r2 += -8;					\
1241 	r1 = %[map_array_48b] ll;			\
1242 	call %[bpf_map_lookup_elem];			\
1243 	if r0 == 0 goto l0_%=;				\
1244 	r1 = 6;						\
1245 	r2 = 4;						\
1246 	r0 += r1;					\
1247 	r0 -= r2;					\
1248 	r1 = *(u8*)(r0 + 0);				\
1249 l0_%=:	r0 = 1;						\
1250 	exit;						\
1251 "	:
1252 	: __imm(bpf_map_lookup_elem),
1253 	  __imm_addr(map_array_48b)
1254 	: __clobber_all);
1255 }
1256 
1257 SEC("socket")
1258 __description("map access: unknown scalar -= value_ptr")
1259 __failure __msg("R1 tried to subtract pointer from scalar")
1260 __failure_unpriv
1261 __naked void access_unknown_scalar_value_ptr(void)
1262 {
1263 	asm volatile ("					\
1264 	r1 = 0;						\
1265 	*(u64*)(r10 - 8) = r1;				\
1266 	r2 = r10;					\
1267 	r2 += -8;					\
1268 	r1 = %[map_array_48b] ll;			\
1269 	call %[bpf_map_lookup_elem];			\
1270 	if r0 == 0 goto l0_%=;				\
1271 	r1 = *(u8*)(r0 + 0);				\
1272 	r1 &= 0xf;					\
1273 	r1 -= r0;					\
1274 	r0 = *(u8*)(r1 + 0);				\
1275 l0_%=:	r0 = 1;						\
1276 	exit;						\
1277 "	:
1278 	: __imm(bpf_map_lookup_elem),
1279 	  __imm_addr(map_array_48b)
1280 	: __clobber_all);
1281 }
1282 
1283 SEC("socket")
1284 __description("map access: value_ptr -= unknown scalar")
1285 __failure __msg("R0 min value is negative")
1286 __failure_unpriv
1287 __naked void access_value_ptr_unknown_scalar(void)
1288 {
1289 	asm volatile ("					\
1290 	r1 = 0;						\
1291 	*(u64*)(r10 - 8) = r1;				\
1292 	r2 = r10;					\
1293 	r2 += -8;					\
1294 	r1 = %[map_array_48b] ll;			\
1295 	call %[bpf_map_lookup_elem];			\
1296 	if r0 == 0 goto l0_%=;				\
1297 	r1 = *(u8*)(r0 + 0);				\
1298 	r1 &= 0xf;					\
1299 	r0 -= r1;					\
1300 	r1 = *(u8*)(r0 + 0);				\
1301 l0_%=:	r0 = 1;						\
1302 	exit;						\
1303 "	:
1304 	: __imm(bpf_map_lookup_elem),
1305 	  __imm_addr(map_array_48b)
1306 	: __clobber_all);
1307 }
1308 
1309 SEC("socket")
1310 __description("map access: value_ptr -= unknown scalar, 2")
1311 __success __success_unpriv
1312 __retval(1)
1313 #ifdef SPEC_V1
1314 __xlated_unpriv("r1 &= 7")
1315 __xlated_unpriv("nospec") /* inserted to prevent `R0 pointer arithmetic of map value goes out of range` */
1316 __xlated_unpriv("r0 -= r1")
1317 #endif
1318 __naked void value_ptr_unknown_scalar_2_2(void)
1319 {
1320 	asm volatile ("					\
1321 	r1 = 0;						\
1322 	*(u64*)(r10 - 8) = r1;				\
1323 	r2 = r10;					\
1324 	r2 += -8;					\
1325 	r1 = %[map_array_48b] ll;			\
1326 	call %[bpf_map_lookup_elem];			\
1327 	if r0 == 0 goto l0_%=;				\
1328 	r1 = *(u8*)(r0 + 0);				\
1329 	r1 &= 0xf;					\
1330 	r1 |= 0x7;					\
1331 	r0 += r1;					\
1332 	r1 = *(u8*)(r0 + 0);				\
1333 	r1 &= 0x7;					\
1334 	r0 -= r1;					\
1335 	r1 = *(u8*)(r0 + 0);				\
1336 l0_%=:	r0 = 1;						\
1337 	exit;						\
1338 "	:
1339 	: __imm(bpf_map_lookup_elem),
1340 	  __imm_addr(map_array_48b)
1341 	: __clobber_all);
1342 }
1343 
1344 SEC("socket")
1345 __description("map access: value_ptr -= value_ptr")
1346 __failure __msg("R0 invalid mem access 'scalar'")
1347 __msg_unpriv("R0 pointer -= pointer prohibited")
1348 __naked void access_value_ptr_value_ptr_2(void)
1349 {
1350 	asm volatile ("					\
1351 	r1 = 0;						\
1352 	*(u64*)(r10 - 8) = r1;				\
1353 	r2 = r10;					\
1354 	r2 += -8;					\
1355 	r1 = %[map_array_48b] ll;			\
1356 	call %[bpf_map_lookup_elem];			\
1357 	if r0 == 0 goto l0_%=;				\
1358 	r0 -= r0;					\
1359 	r1 = *(u8*)(r0 + 0);				\
1360 l0_%=:	r0 = 1;						\
1361 	exit;						\
1362 "	:
1363 	: __imm(bpf_map_lookup_elem),
1364 	  __imm_addr(map_array_48b)
1365 	: __clobber_all);
1366 }
1367 
1368 SEC("socket")
1369 __description("map access: trying to leak tainted dst reg")
1370 __failure __msg("math between map_value pointer and 4294967295 is not allowed")
1371 __failure_unpriv
1372 __naked void to_leak_tainted_dst_reg(void)
1373 {
1374 	asm volatile ("					\
1375 	r0 = 0;						\
1376 	r1 = 0;						\
1377 	*(u64*)(r10 - 8) = r1;				\
1378 	r2 = r10;					\
1379 	r2 += -8;					\
1380 	r1 = %[map_array_48b] ll;			\
1381 	call %[bpf_map_lookup_elem];			\
1382 	if r0 != 0 goto l0_%=;				\
1383 	exit;						\
1384 l0_%=:	r2 = r0;					\
1385 	w1 = 0xFFFFFFFF;				\
1386 	w1 = w1;					\
1387 	r2 -= r1;					\
1388 	*(u64*)(r0 + 0) = r2;				\
1389 	r0 = 0;						\
1390 	exit;						\
1391 "	:
1392 	: __imm(bpf_map_lookup_elem),
1393 	  __imm_addr(map_array_48b)
1394 	: __clobber_all);
1395 }
1396 
1397 SEC("tc")
1398 __description("32bit pkt_ptr -= scalar")
1399 __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
1400 __naked void _32bit_pkt_ptr_scalar(void)
1401 {
1402 	asm volatile ("					\
1403 	r8 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
1404 	r7 = *(u32*)(r1 + %[__sk_buff_data]);		\
1405 	r6 = r7;					\
1406 	r6 += 40;					\
1407 	if r6 > r8 goto l0_%=;				\
1408 	w4 = w7;					\
1409 	w6 -= w4;					\
1410 l0_%=:	r0 = 0;						\
1411 	exit;						\
1412 "	:
1413 	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
1414 	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
1415 	: __clobber_all);
1416 }
1417 
1418 SEC("tc")
1419 __description("32bit scalar -= pkt_ptr")
1420 __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
1421 __naked void _32bit_scalar_pkt_ptr(void)
1422 {
1423 	asm volatile ("					\
1424 	r8 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
1425 	r7 = *(u32*)(r1 + %[__sk_buff_data]);		\
1426 	r6 = r7;					\
1427 	r6 += 40;					\
1428 	if r6 > r8 goto l0_%=;				\
1429 	w4 = w6;					\
1430 	w4 -= w7;					\
1431 l0_%=:	r0 = 0;						\
1432 	exit;						\
1433 "	:
1434 	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
1435 	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
1436 	: __clobber_all);
1437 }
1438 
1439 char _license[] SEC("license") = "GPL";
1440