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