xref: /linux/tools/testing/selftests/bpf/progs/verifier_helper_value_access.c (revision 06d07429858317ded2db7986113a9e0129cd599b)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/helper_value_access.c */
3 
4 #include <linux/bpf.h>
5 #include <bpf/bpf_helpers.h>
6 #include "bpf_misc.h"
7 
8 struct other_val {
9 	long long foo;
10 	long long bar;
11 };
12 
13 struct {
14 	__uint(type, BPF_MAP_TYPE_HASH);
15 	__uint(max_entries, 1);
16 	__type(key, long long);
17 	__type(value, struct other_val);
18 } map_hash_16b SEC(".maps");
19 
20 #define MAX_ENTRIES 11
21 
22 struct test_val {
23 	unsigned int index;
24 	int foo[MAX_ENTRIES];
25 };
26 
27 struct {
28 	__uint(type, BPF_MAP_TYPE_HASH);
29 	__uint(max_entries, 1);
30 	__type(key, long long);
31 	__type(value, struct test_val);
32 } map_hash_48b SEC(".maps");
33 
34 struct {
35 	__uint(type, BPF_MAP_TYPE_HASH);
36 	__uint(max_entries, 1);
37 	__type(key, long long);
38 	__type(value, long long);
39 } map_hash_8b SEC(".maps");
40 
41 SEC("tracepoint")
42 __description("helper access to map: full range")
43 __success
access_to_map_full_range(void)44 __naked void access_to_map_full_range(void)
45 {
46 	asm volatile ("					\
47 	r2 = r10;					\
48 	r2 += -8;					\
49 	r1 = 0;						\
50 	*(u64*)(r2 + 0) = r1;				\
51 	r1 = %[map_hash_48b] ll;			\
52 	call %[bpf_map_lookup_elem];			\
53 	if r0 == 0 goto l0_%=;				\
54 	r1 = r0;					\
55 	r2 = %[sizeof_test_val];			\
56 	r3 = 0;						\
57 	call %[bpf_probe_read_kernel];			\
58 l0_%=:	exit;						\
59 "	:
60 	: __imm(bpf_map_lookup_elem),
61 	  __imm(bpf_probe_read_kernel),
62 	  __imm_addr(map_hash_48b),
63 	  __imm_const(sizeof_test_val, sizeof(struct test_val))
64 	: __clobber_all);
65 }
66 
67 SEC("tracepoint")
68 __description("helper access to map: partial range")
69 __success
access_to_map_partial_range(void)70 __naked void access_to_map_partial_range(void)
71 {
72 	asm volatile ("					\
73 	r2 = r10;					\
74 	r2 += -8;					\
75 	r1 = 0;						\
76 	*(u64*)(r2 + 0) = r1;				\
77 	r1 = %[map_hash_48b] ll;			\
78 	call %[bpf_map_lookup_elem];			\
79 	if r0 == 0 goto l0_%=;				\
80 	r1 = r0;					\
81 	r2 = 8;						\
82 	r3 = 0;						\
83 	call %[bpf_probe_read_kernel];			\
84 l0_%=:	exit;						\
85 "	:
86 	: __imm(bpf_map_lookup_elem),
87 	  __imm(bpf_probe_read_kernel),
88 	  __imm_addr(map_hash_48b)
89 	: __clobber_all);
90 }
91 
92 /* Call a function taking a pointer and a size which doesn't allow the size to
93  * be zero (i.e. bpf_trace_printk() declares the second argument to be
94  * ARG_CONST_SIZE, not ARG_CONST_SIZE_OR_ZERO). We attempt to pass zero for the
95  * size and expect to fail.
96  */
97 SEC("tracepoint")
98 __description("helper access to map: empty range")
99 __failure __msg("R2 invalid zero-sized read: u64=[0,0]")
access_to_map_empty_range(void)100 __naked void access_to_map_empty_range(void)
101 {
102 	asm volatile ("					\
103 	r2 = r10;					\
104 	r2 += -8;					\
105 	r1 = 0;						\
106 	*(u64*)(r2 + 0) = r1;				\
107 	r1 = %[map_hash_48b] ll;			\
108 	call %[bpf_map_lookup_elem];			\
109 	if r0 == 0 goto l0_%=;				\
110 	r1 = r0;					\
111 	r2 = 0;						\
112 	call %[bpf_trace_printk];			\
113 l0_%=:	exit;						\
114 "	:
115 	: __imm(bpf_map_lookup_elem),
116 	  __imm(bpf_trace_printk),
117 	  __imm_addr(map_hash_48b)
118 	: __clobber_all);
119 }
120 
121 /* Like the test above, but this time the size register is not known to be zero;
122  * its lower-bound is zero though, which is still unacceptable.
123  */
124 SEC("tracepoint")
125 __description("helper access to map: possibly-empty ange")
126 __failure __msg("R2 invalid zero-sized read: u64=[0,4]")
access_to_map_possibly_empty_range(void)127 __naked void access_to_map_possibly_empty_range(void)
128 {
129 	asm volatile ("                                         \
130 	r2 = r10;                                               \
131 	r2 += -8;                                               \
132 	r1 = 0;                                                 \
133 	*(u64*)(r2 + 0) = r1;                                   \
134 	r1 = %[map_hash_48b] ll;                                \
135 	call %[bpf_map_lookup_elem];                            \
136 	if r0 == 0 goto l0_%=;                                  \
137 	r1 = r0;                                                \
138 	/* Read an unknown value */                             \
139 	r7 = *(u64*)(r0 + 0);                                   \
140 	/* Make it small and positive, to avoid other errors */ \
141 	r7 &= 4;                                                \
142 	r2 = 0;                                                 \
143 	r2 += r7;                                               \
144 	call %[bpf_trace_printk];                               \
145 l0_%=:	exit;                                               \
146 "	:
147 	: __imm(bpf_map_lookup_elem),
148 	  __imm(bpf_trace_printk),
149 	  __imm_addr(map_hash_48b)
150 	: __clobber_all);
151 }
152 
153 SEC("tracepoint")
154 __description("helper access to map: out-of-bound range")
155 __failure __msg("invalid access to map value, value_size=48 off=0 size=56")
map_out_of_bound_range(void)156 __naked void map_out_of_bound_range(void)
157 {
158 	asm volatile ("					\
159 	r2 = r10;					\
160 	r2 += -8;					\
161 	r1 = 0;						\
162 	*(u64*)(r2 + 0) = r1;				\
163 	r1 = %[map_hash_48b] ll;			\
164 	call %[bpf_map_lookup_elem];			\
165 	if r0 == 0 goto l0_%=;				\
166 	r1 = r0;					\
167 	r2 = %[__imm_0];				\
168 	r3 = 0;						\
169 	call %[bpf_probe_read_kernel];			\
170 l0_%=:	exit;						\
171 "	:
172 	: __imm(bpf_map_lookup_elem),
173 	  __imm(bpf_probe_read_kernel),
174 	  __imm_addr(map_hash_48b),
175 	  __imm_const(__imm_0, sizeof(struct test_val) + 8)
176 	: __clobber_all);
177 }
178 
179 SEC("tracepoint")
180 __description("helper access to map: negative range")
181 __failure __msg("R2 min value is negative")
access_to_map_negative_range(void)182 __naked void access_to_map_negative_range(void)
183 {
184 	asm volatile ("					\
185 	r2 = r10;					\
186 	r2 += -8;					\
187 	r1 = 0;						\
188 	*(u64*)(r2 + 0) = r1;				\
189 	r1 = %[map_hash_48b] ll;			\
190 	call %[bpf_map_lookup_elem];			\
191 	if r0 == 0 goto l0_%=;				\
192 	r1 = r0;					\
193 	r2 = -8;					\
194 	r3 = 0;						\
195 	call %[bpf_probe_read_kernel];			\
196 l0_%=:	exit;						\
197 "	:
198 	: __imm(bpf_map_lookup_elem),
199 	  __imm(bpf_probe_read_kernel),
200 	  __imm_addr(map_hash_48b)
201 	: __clobber_all);
202 }
203 
204 SEC("tracepoint")
205 __description("helper access to adjusted map (via const imm): full range")
206 __success
via_const_imm_full_range(void)207 __naked void via_const_imm_full_range(void)
208 {
209 	asm volatile ("					\
210 	r2 = r10;					\
211 	r2 += -8;					\
212 	r1 = 0;						\
213 	*(u64*)(r2 + 0) = r1;				\
214 	r1 = %[map_hash_48b] ll;			\
215 	call %[bpf_map_lookup_elem];			\
216 	if r0 == 0 goto l0_%=;				\
217 	r1 = r0;					\
218 	r1 += %[test_val_foo];				\
219 	r2 = %[__imm_0];				\
220 	r3 = 0;						\
221 	call %[bpf_probe_read_kernel];			\
222 l0_%=:	exit;						\
223 "	:
224 	: __imm(bpf_map_lookup_elem),
225 	  __imm(bpf_probe_read_kernel),
226 	  __imm_addr(map_hash_48b),
227 	  __imm_const(__imm_0, sizeof(struct test_val) - offsetof(struct test_val, foo)),
228 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
229 	: __clobber_all);
230 }
231 
232 SEC("tracepoint")
233 __description("helper access to adjusted map (via const imm): partial range")
234 __success
via_const_imm_partial_range(void)235 __naked void via_const_imm_partial_range(void)
236 {
237 	asm volatile ("					\
238 	r2 = r10;					\
239 	r2 += -8;					\
240 	r1 = 0;						\
241 	*(u64*)(r2 + 0) = r1;				\
242 	r1 = %[map_hash_48b] ll;			\
243 	call %[bpf_map_lookup_elem];			\
244 	if r0 == 0 goto l0_%=;				\
245 	r1 = r0;					\
246 	r1 += %[test_val_foo];				\
247 	r2 = 8;						\
248 	r3 = 0;						\
249 	call %[bpf_probe_read_kernel];			\
250 l0_%=:	exit;						\
251 "	:
252 	: __imm(bpf_map_lookup_elem),
253 	  __imm(bpf_probe_read_kernel),
254 	  __imm_addr(map_hash_48b),
255 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
256 	: __clobber_all);
257 }
258 
259 SEC("tracepoint")
260 __description("helper access to adjusted map (via const imm): empty range")
261 __failure __msg("R2 invalid zero-sized read")
via_const_imm_empty_range(void)262 __naked void via_const_imm_empty_range(void)
263 {
264 	asm volatile ("					\
265 	r2 = r10;					\
266 	r2 += -8;					\
267 	r1 = 0;						\
268 	*(u64*)(r2 + 0) = r1;				\
269 	r1 = %[map_hash_48b] ll;			\
270 	call %[bpf_map_lookup_elem];			\
271 	if r0 == 0 goto l0_%=;				\
272 	r1 = r0;					\
273 	r1 += %[test_val_foo];				\
274 	r2 = 0;						\
275 	call %[bpf_trace_printk];			\
276 l0_%=:	exit;						\
277 "	:
278 	: __imm(bpf_map_lookup_elem),
279 	  __imm(bpf_trace_printk),
280 	  __imm_addr(map_hash_48b),
281 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
282 	: __clobber_all);
283 }
284 
285 SEC("tracepoint")
286 __description("helper access to adjusted map (via const imm): out-of-bound range")
287 __failure __msg("invalid access to map value, value_size=48 off=4 size=52")
imm_out_of_bound_range(void)288 __naked void imm_out_of_bound_range(void)
289 {
290 	asm volatile ("					\
291 	r2 = r10;					\
292 	r2 += -8;					\
293 	r1 = 0;						\
294 	*(u64*)(r2 + 0) = r1;				\
295 	r1 = %[map_hash_48b] ll;			\
296 	call %[bpf_map_lookup_elem];			\
297 	if r0 == 0 goto l0_%=;				\
298 	r1 = r0;					\
299 	r1 += %[test_val_foo];				\
300 	r2 = %[__imm_0];				\
301 	r3 = 0;						\
302 	call %[bpf_probe_read_kernel];			\
303 l0_%=:	exit;						\
304 "	:
305 	: __imm(bpf_map_lookup_elem),
306 	  __imm(bpf_probe_read_kernel),
307 	  __imm_addr(map_hash_48b),
308 	  __imm_const(__imm_0, sizeof(struct test_val) - offsetof(struct test_val, foo) + 8),
309 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
310 	: __clobber_all);
311 }
312 
313 SEC("tracepoint")
314 __description("helper access to adjusted map (via const imm): negative range (> adjustment)")
315 __failure __msg("R2 min value is negative")
const_imm_negative_range_adjustment_1(void)316 __naked void const_imm_negative_range_adjustment_1(void)
317 {
318 	asm volatile ("					\
319 	r2 = r10;					\
320 	r2 += -8;					\
321 	r1 = 0;						\
322 	*(u64*)(r2 + 0) = r1;				\
323 	r1 = %[map_hash_48b] ll;			\
324 	call %[bpf_map_lookup_elem];			\
325 	if r0 == 0 goto l0_%=;				\
326 	r1 = r0;					\
327 	r1 += %[test_val_foo];				\
328 	r2 = -8;					\
329 	r3 = 0;						\
330 	call %[bpf_probe_read_kernel];			\
331 l0_%=:	exit;						\
332 "	:
333 	: __imm(bpf_map_lookup_elem),
334 	  __imm(bpf_probe_read_kernel),
335 	  __imm_addr(map_hash_48b),
336 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
337 	: __clobber_all);
338 }
339 
340 SEC("tracepoint")
341 __description("helper access to adjusted map (via const imm): negative range (< adjustment)")
342 __failure __msg("R2 min value is negative")
const_imm_negative_range_adjustment_2(void)343 __naked void const_imm_negative_range_adjustment_2(void)
344 {
345 	asm volatile ("					\
346 	r2 = r10;					\
347 	r2 += -8;					\
348 	r1 = 0;						\
349 	*(u64*)(r2 + 0) = r1;				\
350 	r1 = %[map_hash_48b] ll;			\
351 	call %[bpf_map_lookup_elem];			\
352 	if r0 == 0 goto l0_%=;				\
353 	r1 = r0;					\
354 	r1 += %[test_val_foo];				\
355 	r2 = -1;					\
356 	r3 = 0;						\
357 	call %[bpf_probe_read_kernel];			\
358 l0_%=:	exit;						\
359 "	:
360 	: __imm(bpf_map_lookup_elem),
361 	  __imm(bpf_probe_read_kernel),
362 	  __imm_addr(map_hash_48b),
363 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
364 	: __clobber_all);
365 }
366 
367 SEC("tracepoint")
368 __description("helper access to adjusted map (via const reg): full range")
369 __success
via_const_reg_full_range(void)370 __naked void via_const_reg_full_range(void)
371 {
372 	asm volatile ("					\
373 	r2 = r10;					\
374 	r2 += -8;					\
375 	r1 = 0;						\
376 	*(u64*)(r2 + 0) = r1;				\
377 	r1 = %[map_hash_48b] ll;			\
378 	call %[bpf_map_lookup_elem];			\
379 	if r0 == 0 goto l0_%=;				\
380 	r1 = r0;					\
381 	r3 = %[test_val_foo];				\
382 	r1 += r3;					\
383 	r2 = %[__imm_0];				\
384 	r3 = 0;						\
385 	call %[bpf_probe_read_kernel];			\
386 l0_%=:	exit;						\
387 "	:
388 	: __imm(bpf_map_lookup_elem),
389 	  __imm(bpf_probe_read_kernel),
390 	  __imm_addr(map_hash_48b),
391 	  __imm_const(__imm_0, sizeof(struct test_val) - offsetof(struct test_val, foo)),
392 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
393 	: __clobber_all);
394 }
395 
396 SEC("tracepoint")
397 __description("helper access to adjusted map (via const reg): partial range")
398 __success
via_const_reg_partial_range(void)399 __naked void via_const_reg_partial_range(void)
400 {
401 	asm volatile ("					\
402 	r2 = r10;					\
403 	r2 += -8;					\
404 	r1 = 0;						\
405 	*(u64*)(r2 + 0) = r1;				\
406 	r1 = %[map_hash_48b] ll;			\
407 	call %[bpf_map_lookup_elem];			\
408 	if r0 == 0 goto l0_%=;				\
409 	r1 = r0;					\
410 	r3 = %[test_val_foo];				\
411 	r1 += r3;					\
412 	r2 = 8;						\
413 	r3 = 0;						\
414 	call %[bpf_probe_read_kernel];			\
415 l0_%=:	exit;						\
416 "	:
417 	: __imm(bpf_map_lookup_elem),
418 	  __imm(bpf_probe_read_kernel),
419 	  __imm_addr(map_hash_48b),
420 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
421 	: __clobber_all);
422 }
423 
424 SEC("tracepoint")
425 __description("helper access to adjusted map (via const reg): empty range")
426 __failure __msg("R2 invalid zero-sized read")
via_const_reg_empty_range(void)427 __naked void via_const_reg_empty_range(void)
428 {
429 	asm volatile ("					\
430 	r2 = r10;					\
431 	r2 += -8;					\
432 	r1 = 0;						\
433 	*(u64*)(r2 + 0) = r1;				\
434 	r1 = %[map_hash_48b] ll;			\
435 	call %[bpf_map_lookup_elem];			\
436 	if r0 == 0 goto l0_%=;				\
437 	r1 = r0;					\
438 	r3 = 0;						\
439 	r1 += r3;					\
440 	r2 = 0;						\
441 	call %[bpf_trace_printk];			\
442 l0_%=:	exit;						\
443 "	:
444 	: __imm(bpf_map_lookup_elem),
445 	  __imm(bpf_trace_printk),
446 	  __imm_addr(map_hash_48b)
447 	: __clobber_all);
448 }
449 
450 SEC("tracepoint")
451 __description("helper access to adjusted map (via const reg): out-of-bound range")
452 __failure __msg("invalid access to map value, value_size=48 off=4 size=52")
reg_out_of_bound_range(void)453 __naked void reg_out_of_bound_range(void)
454 {
455 	asm volatile ("					\
456 	r2 = r10;					\
457 	r2 += -8;					\
458 	r1 = 0;						\
459 	*(u64*)(r2 + 0) = r1;				\
460 	r1 = %[map_hash_48b] ll;			\
461 	call %[bpf_map_lookup_elem];			\
462 	if r0 == 0 goto l0_%=;				\
463 	r1 = r0;					\
464 	r3 = %[test_val_foo];				\
465 	r1 += r3;					\
466 	r2 = %[__imm_0];				\
467 	r3 = 0;						\
468 	call %[bpf_probe_read_kernel];			\
469 l0_%=:	exit;						\
470 "	:
471 	: __imm(bpf_map_lookup_elem),
472 	  __imm(bpf_probe_read_kernel),
473 	  __imm_addr(map_hash_48b),
474 	  __imm_const(__imm_0, sizeof(struct test_val) - offsetof(struct test_val, foo) + 8),
475 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
476 	: __clobber_all);
477 }
478 
479 SEC("tracepoint")
480 __description("helper access to adjusted map (via const reg): negative range (> adjustment)")
481 __failure __msg("R2 min value is negative")
const_reg_negative_range_adjustment_1(void)482 __naked void const_reg_negative_range_adjustment_1(void)
483 {
484 	asm volatile ("					\
485 	r2 = r10;					\
486 	r2 += -8;					\
487 	r1 = 0;						\
488 	*(u64*)(r2 + 0) = r1;				\
489 	r1 = %[map_hash_48b] ll;			\
490 	call %[bpf_map_lookup_elem];			\
491 	if r0 == 0 goto l0_%=;				\
492 	r1 = r0;					\
493 	r3 = %[test_val_foo];				\
494 	r1 += r3;					\
495 	r2 = -8;					\
496 	r3 = 0;						\
497 	call %[bpf_probe_read_kernel];			\
498 l0_%=:	exit;						\
499 "	:
500 	: __imm(bpf_map_lookup_elem),
501 	  __imm(bpf_probe_read_kernel),
502 	  __imm_addr(map_hash_48b),
503 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
504 	: __clobber_all);
505 }
506 
507 SEC("tracepoint")
508 __description("helper access to adjusted map (via const reg): negative range (< adjustment)")
509 __failure __msg("R2 min value is negative")
const_reg_negative_range_adjustment_2(void)510 __naked void const_reg_negative_range_adjustment_2(void)
511 {
512 	asm volatile ("					\
513 	r2 = r10;					\
514 	r2 += -8;					\
515 	r1 = 0;						\
516 	*(u64*)(r2 + 0) = r1;				\
517 	r1 = %[map_hash_48b] ll;			\
518 	call %[bpf_map_lookup_elem];			\
519 	if r0 == 0 goto l0_%=;				\
520 	r1 = r0;					\
521 	r3 = %[test_val_foo];				\
522 	r1 += r3;					\
523 	r2 = -1;					\
524 	r3 = 0;						\
525 	call %[bpf_probe_read_kernel];			\
526 l0_%=:	exit;						\
527 "	:
528 	: __imm(bpf_map_lookup_elem),
529 	  __imm(bpf_probe_read_kernel),
530 	  __imm_addr(map_hash_48b),
531 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
532 	: __clobber_all);
533 }
534 
535 SEC("tracepoint")
536 __description("helper access to adjusted map (via variable): full range")
537 __success
map_via_variable_full_range(void)538 __naked void map_via_variable_full_range(void)
539 {
540 	asm volatile ("					\
541 	r2 = r10;					\
542 	r2 += -8;					\
543 	r1 = 0;						\
544 	*(u64*)(r2 + 0) = r1;				\
545 	r1 = %[map_hash_48b] ll;			\
546 	call %[bpf_map_lookup_elem];			\
547 	if r0 == 0 goto l0_%=;				\
548 	r1 = r0;					\
549 	r3 = *(u32*)(r0 + 0);				\
550 	if r3 > %[test_val_foo] goto l0_%=;		\
551 	r1 += r3;					\
552 	r2 = %[__imm_0];				\
553 	r3 = 0;						\
554 	call %[bpf_probe_read_kernel];			\
555 l0_%=:	exit;						\
556 "	:
557 	: __imm(bpf_map_lookup_elem),
558 	  __imm(bpf_probe_read_kernel),
559 	  __imm_addr(map_hash_48b),
560 	  __imm_const(__imm_0, sizeof(struct test_val) - offsetof(struct test_val, foo)),
561 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
562 	: __clobber_all);
563 }
564 
565 SEC("tracepoint")
566 __description("helper access to adjusted map (via variable): partial range")
567 __success
map_via_variable_partial_range(void)568 __naked void map_via_variable_partial_range(void)
569 {
570 	asm volatile ("					\
571 	r2 = r10;					\
572 	r2 += -8;					\
573 	r1 = 0;						\
574 	*(u64*)(r2 + 0) = r1;				\
575 	r1 = %[map_hash_48b] ll;			\
576 	call %[bpf_map_lookup_elem];			\
577 	if r0 == 0 goto l0_%=;				\
578 	r1 = r0;					\
579 	r3 = *(u32*)(r0 + 0);				\
580 	if r3 > %[test_val_foo] goto l0_%=;		\
581 	r1 += r3;					\
582 	r2 = 8;						\
583 	r3 = 0;						\
584 	call %[bpf_probe_read_kernel];			\
585 l0_%=:	exit;						\
586 "	:
587 	: __imm(bpf_map_lookup_elem),
588 	  __imm(bpf_probe_read_kernel),
589 	  __imm_addr(map_hash_48b),
590 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
591 	: __clobber_all);
592 }
593 
594 SEC("tracepoint")
595 __description("helper access to adjusted map (via variable): empty range")
596 __failure __msg("R2 invalid zero-sized read")
map_via_variable_empty_range(void)597 __naked void map_via_variable_empty_range(void)
598 {
599 	asm volatile ("					\
600 	r2 = r10;					\
601 	r2 += -8;					\
602 	r1 = 0;						\
603 	*(u64*)(r2 + 0) = r1;				\
604 	r1 = %[map_hash_48b] ll;			\
605 	call %[bpf_map_lookup_elem];			\
606 	if r0 == 0 goto l0_%=;				\
607 	r1 = r0;					\
608 	r3 = *(u32*)(r0 + 0);				\
609 	if r3 > %[test_val_foo] goto l0_%=;		\
610 	r1 += r3;					\
611 	r2 = 0;						\
612 	call %[bpf_trace_printk];			\
613 l0_%=:	exit;						\
614 "	:
615 	: __imm(bpf_map_lookup_elem),
616 	  __imm(bpf_trace_printk),
617 	  __imm_addr(map_hash_48b),
618 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
619 	: __clobber_all);
620 }
621 
622 SEC("tracepoint")
623 __description("helper access to adjusted map (via variable): no max check")
624 __failure __msg("R1 unbounded memory access")
via_variable_no_max_check_1(void)625 __naked void via_variable_no_max_check_1(void)
626 {
627 	asm volatile ("					\
628 	r2 = r10;					\
629 	r2 += -8;					\
630 	r1 = 0;						\
631 	*(u64*)(r2 + 0) = r1;				\
632 	r1 = %[map_hash_48b] ll;			\
633 	call %[bpf_map_lookup_elem];			\
634 	if r0 == 0 goto l0_%=;				\
635 	r1 = r0;					\
636 	r3 = *(u32*)(r0 + 0);				\
637 	r1 += r3;					\
638 	r2 = 1;						\
639 	r3 = 0;						\
640 	call %[bpf_probe_read_kernel];			\
641 l0_%=:	exit;						\
642 "	:
643 	: __imm(bpf_map_lookup_elem),
644 	  __imm(bpf_probe_read_kernel),
645 	  __imm_addr(map_hash_48b)
646 	: __clobber_all);
647 }
648 
649 SEC("tracepoint")
650 __description("helper access to adjusted map (via variable): wrong max check")
651 __failure __msg("invalid access to map value, value_size=48 off=4 size=45")
via_variable_wrong_max_check_1(void)652 __naked void via_variable_wrong_max_check_1(void)
653 {
654 	asm volatile ("					\
655 	r2 = r10;					\
656 	r2 += -8;					\
657 	r1 = 0;						\
658 	*(u64*)(r2 + 0) = r1;				\
659 	r1 = %[map_hash_48b] ll;			\
660 	call %[bpf_map_lookup_elem];			\
661 	if r0 == 0 goto l0_%=;				\
662 	r1 = r0;					\
663 	r3 = *(u32*)(r0 + 0);				\
664 	if r3 > %[test_val_foo] goto l0_%=;		\
665 	r1 += r3;					\
666 	r2 = %[__imm_0];				\
667 	r3 = 0;						\
668 	call %[bpf_probe_read_kernel];			\
669 l0_%=:	exit;						\
670 "	:
671 	: __imm(bpf_map_lookup_elem),
672 	  __imm(bpf_probe_read_kernel),
673 	  __imm_addr(map_hash_48b),
674 	  __imm_const(__imm_0, sizeof(struct test_val) - offsetof(struct test_val, foo) + 1),
675 	  __imm_const(test_val_foo, offsetof(struct test_val, foo))
676 	: __clobber_all);
677 }
678 
679 SEC("tracepoint")
680 __description("helper access to map: bounds check using <, good access")
681 __success
bounds_check_using_good_access_1(void)682 __naked void bounds_check_using_good_access_1(void)
683 {
684 	asm volatile ("					\
685 	r2 = r10;					\
686 	r2 += -8;					\
687 	r1 = 0;						\
688 	*(u64*)(r2 + 0) = r1;				\
689 	r1 = %[map_hash_48b] ll;			\
690 	call %[bpf_map_lookup_elem];			\
691 	if r0 == 0 goto l0_%=;				\
692 	r1 = r0;					\
693 	r3 = *(u32*)(r0 + 0);				\
694 	if r3 < 32 goto l1_%=;				\
695 	r0 = 0;						\
696 l0_%=:	exit;						\
697 l1_%=:	r1 += r3;					\
698 	r0 = 0;						\
699 	*(u8*)(r1 + 0) = r0;				\
700 	r0 = 0;						\
701 	exit;						\
702 "	:
703 	: __imm(bpf_map_lookup_elem),
704 	  __imm_addr(map_hash_48b)
705 	: __clobber_all);
706 }
707 
708 SEC("tracepoint")
709 __description("helper access to map: bounds check using <, bad access")
710 __failure __msg("R1 unbounded memory access")
bounds_check_using_bad_access_1(void)711 __naked void bounds_check_using_bad_access_1(void)
712 {
713 	asm volatile ("					\
714 	r2 = r10;					\
715 	r2 += -8;					\
716 	r1 = 0;						\
717 	*(u64*)(r2 + 0) = r1;				\
718 	r1 = %[map_hash_48b] ll;			\
719 	call %[bpf_map_lookup_elem];			\
720 	if r0 == 0 goto l0_%=;				\
721 	r1 = r0;					\
722 	r3 = *(u32*)(r0 + 0);				\
723 	if r3 < 32 goto l1_%=;				\
724 	r1 += r3;					\
725 l0_%=:	r0 = 0;						\
726 	*(u8*)(r1 + 0) = r0;				\
727 	r0 = 0;						\
728 	exit;						\
729 l1_%=:	r0 = 0;						\
730 	exit;						\
731 "	:
732 	: __imm(bpf_map_lookup_elem),
733 	  __imm_addr(map_hash_48b)
734 	: __clobber_all);
735 }
736 
737 SEC("tracepoint")
738 __description("helper access to map: bounds check using <=, good access")
739 __success
bounds_check_using_good_access_2(void)740 __naked void bounds_check_using_good_access_2(void)
741 {
742 	asm volatile ("					\
743 	r2 = r10;					\
744 	r2 += -8;					\
745 	r1 = 0;						\
746 	*(u64*)(r2 + 0) = r1;				\
747 	r1 = %[map_hash_48b] ll;			\
748 	call %[bpf_map_lookup_elem];			\
749 	if r0 == 0 goto l0_%=;				\
750 	r1 = r0;					\
751 	r3 = *(u32*)(r0 + 0);				\
752 	if r3 <= 32 goto l1_%=;				\
753 	r0 = 0;						\
754 l0_%=:	exit;						\
755 l1_%=:	r1 += r3;					\
756 	r0 = 0;						\
757 	*(u8*)(r1 + 0) = r0;				\
758 	r0 = 0;						\
759 	exit;						\
760 "	:
761 	: __imm(bpf_map_lookup_elem),
762 	  __imm_addr(map_hash_48b)
763 	: __clobber_all);
764 }
765 
766 SEC("tracepoint")
767 __description("helper access to map: bounds check using <=, bad access")
768 __failure __msg("R1 unbounded memory access")
bounds_check_using_bad_access_2(void)769 __naked void bounds_check_using_bad_access_2(void)
770 {
771 	asm volatile ("					\
772 	r2 = r10;					\
773 	r2 += -8;					\
774 	r1 = 0;						\
775 	*(u64*)(r2 + 0) = r1;				\
776 	r1 = %[map_hash_48b] ll;			\
777 	call %[bpf_map_lookup_elem];			\
778 	if r0 == 0 goto l0_%=;				\
779 	r1 = r0;					\
780 	r3 = *(u32*)(r0 + 0);				\
781 	if r3 <= 32 goto l1_%=;				\
782 	r1 += r3;					\
783 l0_%=:	r0 = 0;						\
784 	*(u8*)(r1 + 0) = r0;				\
785 	r0 = 0;						\
786 	exit;						\
787 l1_%=:	r0 = 0;						\
788 	exit;						\
789 "	:
790 	: __imm(bpf_map_lookup_elem),
791 	  __imm_addr(map_hash_48b)
792 	: __clobber_all);
793 }
794 
795 SEC("tracepoint")
796 __description("helper access to map: bounds check using s<, good access")
797 __success
check_using_s_good_access_1(void)798 __naked void check_using_s_good_access_1(void)
799 {
800 	asm volatile ("					\
801 	r2 = r10;					\
802 	r2 += -8;					\
803 	r1 = 0;						\
804 	*(u64*)(r2 + 0) = r1;				\
805 	r1 = %[map_hash_48b] ll;			\
806 	call %[bpf_map_lookup_elem];			\
807 	if r0 == 0 goto l0_%=;				\
808 	r1 = r0;					\
809 	r3 = *(u32*)(r0 + 0);				\
810 	if r3 s< 32 goto l1_%=;				\
811 l2_%=:	r0 = 0;						\
812 l0_%=:	exit;						\
813 l1_%=:	if r3 s< 0 goto l2_%=;				\
814 	r1 += r3;					\
815 	r0 = 0;						\
816 	*(u8*)(r1 + 0) = r0;				\
817 	r0 = 0;						\
818 	exit;						\
819 "	:
820 	: __imm(bpf_map_lookup_elem),
821 	  __imm_addr(map_hash_48b)
822 	: __clobber_all);
823 }
824 
825 SEC("tracepoint")
826 __description("helper access to map: bounds check using s<, good access 2")
827 __success
using_s_good_access_2_1(void)828 __naked void using_s_good_access_2_1(void)
829 {
830 	asm volatile ("					\
831 	r2 = r10;					\
832 	r2 += -8;					\
833 	r1 = 0;						\
834 	*(u64*)(r2 + 0) = r1;				\
835 	r1 = %[map_hash_48b] ll;			\
836 	call %[bpf_map_lookup_elem];			\
837 	if r0 == 0 goto l0_%=;				\
838 	r1 = r0;					\
839 	r3 = *(u32*)(r0 + 0);				\
840 	if r3 s< 32 goto l1_%=;				\
841 l2_%=:	r0 = 0;						\
842 l0_%=:	exit;						\
843 l1_%=:	if r3 s< -3 goto l2_%=;				\
844 	r1 += r3;					\
845 	r0 = 0;						\
846 	*(u8*)(r1 + 0) = r0;				\
847 	r0 = 0;						\
848 	exit;						\
849 "	:
850 	: __imm(bpf_map_lookup_elem),
851 	  __imm_addr(map_hash_48b)
852 	: __clobber_all);
853 }
854 
855 SEC("tracepoint")
856 __description("helper access to map: bounds check using s<, bad access")
857 __failure __msg("R1 min value is negative")
check_using_s_bad_access_1(void)858 __naked void check_using_s_bad_access_1(void)
859 {
860 	asm volatile ("					\
861 	r2 = r10;					\
862 	r2 += -8;					\
863 	r1 = 0;						\
864 	*(u64*)(r2 + 0) = r1;				\
865 	r1 = %[map_hash_48b] ll;			\
866 	call %[bpf_map_lookup_elem];			\
867 	if r0 == 0 goto l0_%=;				\
868 	r1 = r0;					\
869 	r3 = *(u64*)(r0 + 0);				\
870 	if r3 s< 32 goto l1_%=;				\
871 l2_%=:	r0 = 0;						\
872 l0_%=:	exit;						\
873 l1_%=:	if r3 s< -3 goto l2_%=;				\
874 	r1 += r3;					\
875 	r0 = 0;						\
876 	*(u8*)(r1 + 0) = r0;				\
877 	r0 = 0;						\
878 	exit;						\
879 "	:
880 	: __imm(bpf_map_lookup_elem),
881 	  __imm_addr(map_hash_48b)
882 	: __clobber_all);
883 }
884 
885 SEC("tracepoint")
886 __description("helper access to map: bounds check using s<=, good access")
887 __success
check_using_s_good_access_2(void)888 __naked void check_using_s_good_access_2(void)
889 {
890 	asm volatile ("					\
891 	r2 = r10;					\
892 	r2 += -8;					\
893 	r1 = 0;						\
894 	*(u64*)(r2 + 0) = r1;				\
895 	r1 = %[map_hash_48b] ll;			\
896 	call %[bpf_map_lookup_elem];			\
897 	if r0 == 0 goto l0_%=;				\
898 	r1 = r0;					\
899 	r3 = *(u32*)(r0 + 0);				\
900 	if r3 s<= 32 goto l1_%=;			\
901 l2_%=:	r0 = 0;						\
902 l0_%=:	exit;						\
903 l1_%=:	if r3 s<= 0 goto l2_%=;				\
904 	r1 += r3;					\
905 	r0 = 0;						\
906 	*(u8*)(r1 + 0) = r0;				\
907 	r0 = 0;						\
908 	exit;						\
909 "	:
910 	: __imm(bpf_map_lookup_elem),
911 	  __imm_addr(map_hash_48b)
912 	: __clobber_all);
913 }
914 
915 SEC("tracepoint")
916 __description("helper access to map: bounds check using s<=, good access 2")
917 __success
using_s_good_access_2_2(void)918 __naked void using_s_good_access_2_2(void)
919 {
920 	asm volatile ("					\
921 	r2 = r10;					\
922 	r2 += -8;					\
923 	r1 = 0;						\
924 	*(u64*)(r2 + 0) = r1;				\
925 	r1 = %[map_hash_48b] ll;			\
926 	call %[bpf_map_lookup_elem];			\
927 	if r0 == 0 goto l0_%=;				\
928 	r1 = r0;					\
929 	r3 = *(u32*)(r0 + 0);				\
930 	if r3 s<= 32 goto l1_%=;			\
931 l2_%=:	r0 = 0;						\
932 l0_%=:	exit;						\
933 l1_%=:	if r3 s<= -3 goto l2_%=;			\
934 	r1 += r3;					\
935 	r0 = 0;						\
936 	*(u8*)(r1 + 0) = r0;				\
937 	r0 = 0;						\
938 	exit;						\
939 "	:
940 	: __imm(bpf_map_lookup_elem),
941 	  __imm_addr(map_hash_48b)
942 	: __clobber_all);
943 }
944 
945 SEC("tracepoint")
946 __description("helper access to map: bounds check using s<=, bad access")
947 __failure __msg("R1 min value is negative")
check_using_s_bad_access_2(void)948 __naked void check_using_s_bad_access_2(void)
949 {
950 	asm volatile ("					\
951 	r2 = r10;					\
952 	r2 += -8;					\
953 	r1 = 0;						\
954 	*(u64*)(r2 + 0) = r1;				\
955 	r1 = %[map_hash_48b] ll;			\
956 	call %[bpf_map_lookup_elem];			\
957 	if r0 == 0 goto l0_%=;				\
958 	r1 = r0;					\
959 	r3 = *(u64*)(r0 + 0);				\
960 	if r3 s<= 32 goto l1_%=;			\
961 l2_%=:	r0 = 0;						\
962 l0_%=:	exit;						\
963 l1_%=:	if r3 s<= -3 goto l2_%=;			\
964 	r1 += r3;					\
965 	r0 = 0;						\
966 	*(u8*)(r1 + 0) = r0;				\
967 	r0 = 0;						\
968 	exit;						\
969 "	:
970 	: __imm(bpf_map_lookup_elem),
971 	  __imm_addr(map_hash_48b)
972 	: __clobber_all);
973 }
974 
975 SEC("tracepoint")
976 __description("map lookup helper access to map")
977 __success
lookup_helper_access_to_map(void)978 __naked void lookup_helper_access_to_map(void)
979 {
980 	asm volatile ("					\
981 	r2 = r10;					\
982 	r2 += -8;					\
983 	r1 = 0;						\
984 	*(u64*)(r2 + 0) = r1;				\
985 	r1 = %[map_hash_16b] ll;			\
986 	call %[bpf_map_lookup_elem];			\
987 	if r0 == 0 goto l0_%=;				\
988 	r2 = r0;					\
989 	r1 = %[map_hash_16b] ll;			\
990 	call %[bpf_map_lookup_elem];			\
991 l0_%=:	exit;						\
992 "	:
993 	: __imm(bpf_map_lookup_elem),
994 	  __imm_addr(map_hash_16b)
995 	: __clobber_all);
996 }
997 
998 SEC("tracepoint")
999 __description("map update helper access to map")
1000 __success
update_helper_access_to_map(void)1001 __naked void update_helper_access_to_map(void)
1002 {
1003 	asm volatile ("					\
1004 	r2 = r10;					\
1005 	r2 += -8;					\
1006 	r1 = 0;						\
1007 	*(u64*)(r2 + 0) = r1;				\
1008 	r1 = %[map_hash_16b] ll;			\
1009 	call %[bpf_map_lookup_elem];			\
1010 	if r0 == 0 goto l0_%=;				\
1011 	r4 = 0;						\
1012 	r3 = r0;					\
1013 	r2 = r0;					\
1014 	r1 = %[map_hash_16b] ll;			\
1015 	call %[bpf_map_update_elem];			\
1016 l0_%=:	exit;						\
1017 "	:
1018 	: __imm(bpf_map_lookup_elem),
1019 	  __imm(bpf_map_update_elem),
1020 	  __imm_addr(map_hash_16b)
1021 	: __clobber_all);
1022 }
1023 
1024 SEC("tracepoint")
1025 __description("map update helper access to map: wrong size")
1026 __failure __msg("invalid access to map value, value_size=8 off=0 size=16")
access_to_map_wrong_size(void)1027 __naked void access_to_map_wrong_size(void)
1028 {
1029 	asm volatile ("					\
1030 	r2 = r10;					\
1031 	r2 += -8;					\
1032 	r1 = 0;						\
1033 	*(u64*)(r2 + 0) = r1;				\
1034 	r1 = %[map_hash_8b] ll;				\
1035 	call %[bpf_map_lookup_elem];			\
1036 	if r0 == 0 goto l0_%=;				\
1037 	r4 = 0;						\
1038 	r3 = r0;					\
1039 	r2 = r0;					\
1040 	r1 = %[map_hash_16b] ll;			\
1041 	call %[bpf_map_update_elem];			\
1042 l0_%=:	exit;						\
1043 "	:
1044 	: __imm(bpf_map_lookup_elem),
1045 	  __imm(bpf_map_update_elem),
1046 	  __imm_addr(map_hash_16b),
1047 	  __imm_addr(map_hash_8b)
1048 	: __clobber_all);
1049 }
1050 
1051 SEC("tracepoint")
1052 __description("map helper access to adjusted map (via const imm)")
1053 __success
adjusted_map_via_const_imm(void)1054 __naked void adjusted_map_via_const_imm(void)
1055 {
1056 	asm volatile ("					\
1057 	r2 = r10;					\
1058 	r2 += -8;					\
1059 	r1 = 0;						\
1060 	*(u64*)(r2 + 0) = r1;				\
1061 	r1 = %[map_hash_16b] ll;			\
1062 	call %[bpf_map_lookup_elem];			\
1063 	if r0 == 0 goto l0_%=;				\
1064 	r2 = r0;					\
1065 	r2 += %[other_val_bar];				\
1066 	r1 = %[map_hash_16b] ll;			\
1067 	call %[bpf_map_lookup_elem];			\
1068 l0_%=:	exit;						\
1069 "	:
1070 	: __imm(bpf_map_lookup_elem),
1071 	  __imm_addr(map_hash_16b),
1072 	  __imm_const(other_val_bar, offsetof(struct other_val, bar))
1073 	: __clobber_all);
1074 }
1075 
1076 SEC("tracepoint")
1077 __description("map helper access to adjusted map (via const imm): out-of-bound 1")
1078 __failure __msg("invalid access to map value, value_size=16 off=12 size=8")
imm_out_of_bound_1(void)1079 __naked void imm_out_of_bound_1(void)
1080 {
1081 	asm volatile ("					\
1082 	r2 = r10;					\
1083 	r2 += -8;					\
1084 	r1 = 0;						\
1085 	*(u64*)(r2 + 0) = r1;				\
1086 	r1 = %[map_hash_16b] ll;			\
1087 	call %[bpf_map_lookup_elem];			\
1088 	if r0 == 0 goto l0_%=;				\
1089 	r2 = r0;					\
1090 	r2 += %[__imm_0];				\
1091 	r1 = %[map_hash_16b] ll;			\
1092 	call %[bpf_map_lookup_elem];			\
1093 l0_%=:	exit;						\
1094 "	:
1095 	: __imm(bpf_map_lookup_elem),
1096 	  __imm_addr(map_hash_16b),
1097 	  __imm_const(__imm_0, sizeof(struct other_val) - 4)
1098 	: __clobber_all);
1099 }
1100 
1101 SEC("tracepoint")
1102 __description("map helper access to adjusted map (via const imm): out-of-bound 2")
1103 __failure __msg("invalid access to map value, value_size=16 off=-4 size=8")
imm_out_of_bound_2(void)1104 __naked void imm_out_of_bound_2(void)
1105 {
1106 	asm volatile ("					\
1107 	r2 = r10;					\
1108 	r2 += -8;					\
1109 	r1 = 0;						\
1110 	*(u64*)(r2 + 0) = r1;				\
1111 	r1 = %[map_hash_16b] ll;			\
1112 	call %[bpf_map_lookup_elem];			\
1113 	if r0 == 0 goto l0_%=;				\
1114 	r2 = r0;					\
1115 	r2 += -4;					\
1116 	r1 = %[map_hash_16b] ll;			\
1117 	call %[bpf_map_lookup_elem];			\
1118 l0_%=:	exit;						\
1119 "	:
1120 	: __imm(bpf_map_lookup_elem),
1121 	  __imm_addr(map_hash_16b)
1122 	: __clobber_all);
1123 }
1124 
1125 SEC("tracepoint")
1126 __description("map helper access to adjusted map (via const reg)")
1127 __success
adjusted_map_via_const_reg(void)1128 __naked void adjusted_map_via_const_reg(void)
1129 {
1130 	asm volatile ("					\
1131 	r2 = r10;					\
1132 	r2 += -8;					\
1133 	r1 = 0;						\
1134 	*(u64*)(r2 + 0) = r1;				\
1135 	r1 = %[map_hash_16b] ll;			\
1136 	call %[bpf_map_lookup_elem];			\
1137 	if r0 == 0 goto l0_%=;				\
1138 	r2 = r0;					\
1139 	r3 = %[other_val_bar];				\
1140 	r2 += r3;					\
1141 	r1 = %[map_hash_16b] ll;			\
1142 	call %[bpf_map_lookup_elem];			\
1143 l0_%=:	exit;						\
1144 "	:
1145 	: __imm(bpf_map_lookup_elem),
1146 	  __imm_addr(map_hash_16b),
1147 	  __imm_const(other_val_bar, offsetof(struct other_val, bar))
1148 	: __clobber_all);
1149 }
1150 
1151 SEC("tracepoint")
1152 __description("map helper access to adjusted map (via const reg): out-of-bound 1")
1153 __failure __msg("invalid access to map value, value_size=16 off=12 size=8")
reg_out_of_bound_1(void)1154 __naked void reg_out_of_bound_1(void)
1155 {
1156 	asm volatile ("					\
1157 	r2 = r10;					\
1158 	r2 += -8;					\
1159 	r1 = 0;						\
1160 	*(u64*)(r2 + 0) = r1;				\
1161 	r1 = %[map_hash_16b] ll;			\
1162 	call %[bpf_map_lookup_elem];			\
1163 	if r0 == 0 goto l0_%=;				\
1164 	r2 = r0;					\
1165 	r3 = %[__imm_0];				\
1166 	r2 += r3;					\
1167 	r1 = %[map_hash_16b] ll;			\
1168 	call %[bpf_map_lookup_elem];			\
1169 l0_%=:	exit;						\
1170 "	:
1171 	: __imm(bpf_map_lookup_elem),
1172 	  __imm_addr(map_hash_16b),
1173 	  __imm_const(__imm_0, sizeof(struct other_val) - 4)
1174 	: __clobber_all);
1175 }
1176 
1177 SEC("tracepoint")
1178 __description("map helper access to adjusted map (via const reg): out-of-bound 2")
1179 __failure __msg("invalid access to map value, value_size=16 off=-4 size=8")
reg_out_of_bound_2(void)1180 __naked void reg_out_of_bound_2(void)
1181 {
1182 	asm volatile ("					\
1183 	r2 = r10;					\
1184 	r2 += -8;					\
1185 	r1 = 0;						\
1186 	*(u64*)(r2 + 0) = r1;				\
1187 	r1 = %[map_hash_16b] ll;			\
1188 	call %[bpf_map_lookup_elem];			\
1189 	if r0 == 0 goto l0_%=;				\
1190 	r2 = r0;					\
1191 	r3 = -4;					\
1192 	r2 += r3;					\
1193 	r1 = %[map_hash_16b] ll;			\
1194 	call %[bpf_map_lookup_elem];			\
1195 l0_%=:	exit;						\
1196 "	:
1197 	: __imm(bpf_map_lookup_elem),
1198 	  __imm_addr(map_hash_16b)
1199 	: __clobber_all);
1200 }
1201 
1202 SEC("tracepoint")
1203 __description("map helper access to adjusted map (via variable)")
1204 __success
to_adjusted_map_via_variable(void)1205 __naked void to_adjusted_map_via_variable(void)
1206 {
1207 	asm volatile ("					\
1208 	r2 = r10;					\
1209 	r2 += -8;					\
1210 	r1 = 0;						\
1211 	*(u64*)(r2 + 0) = r1;				\
1212 	r1 = %[map_hash_16b] ll;			\
1213 	call %[bpf_map_lookup_elem];			\
1214 	if r0 == 0 goto l0_%=;				\
1215 	r2 = r0;					\
1216 	r3 = *(u32*)(r0 + 0);				\
1217 	if r3 > %[other_val_bar] goto l0_%=;		\
1218 	r2 += r3;					\
1219 	r1 = %[map_hash_16b] ll;			\
1220 	call %[bpf_map_lookup_elem];			\
1221 l0_%=:	exit;						\
1222 "	:
1223 	: __imm(bpf_map_lookup_elem),
1224 	  __imm_addr(map_hash_16b),
1225 	  __imm_const(other_val_bar, offsetof(struct other_val, bar))
1226 	: __clobber_all);
1227 }
1228 
1229 SEC("tracepoint")
1230 __description("map helper access to adjusted map (via variable): no max check")
1231 __failure
1232 __msg("R2 unbounded memory access, make sure to bounds check any such access")
via_variable_no_max_check_2(void)1233 __naked void via_variable_no_max_check_2(void)
1234 {
1235 	asm volatile ("					\
1236 	r2 = r10;					\
1237 	r2 += -8;					\
1238 	r1 = 0;						\
1239 	*(u64*)(r2 + 0) = r1;				\
1240 	r1 = %[map_hash_16b] ll;			\
1241 	call %[bpf_map_lookup_elem];			\
1242 	if r0 == 0 goto l0_%=;				\
1243 	r2 = r0;					\
1244 	r3 = *(u32*)(r0 + 0);				\
1245 	r2 += r3;					\
1246 	r1 = %[map_hash_16b] ll;			\
1247 	call %[bpf_map_lookup_elem];			\
1248 l0_%=:	exit;						\
1249 "	:
1250 	: __imm(bpf_map_lookup_elem),
1251 	  __imm_addr(map_hash_16b)
1252 	: __clobber_all);
1253 }
1254 
1255 SEC("tracepoint")
1256 __description("map helper access to adjusted map (via variable): wrong max check")
1257 __failure __msg("invalid access to map value, value_size=16 off=9 size=8")
via_variable_wrong_max_check_2(void)1258 __naked void via_variable_wrong_max_check_2(void)
1259 {
1260 	asm volatile ("					\
1261 	r2 = r10;					\
1262 	r2 += -8;					\
1263 	r1 = 0;						\
1264 	*(u64*)(r2 + 0) = r1;				\
1265 	r1 = %[map_hash_16b] ll;			\
1266 	call %[bpf_map_lookup_elem];			\
1267 	if r0 == 0 goto l0_%=;				\
1268 	r2 = r0;					\
1269 	r3 = *(u32*)(r0 + 0);				\
1270 	if r3 > %[__imm_0] goto l0_%=;			\
1271 	r2 += r3;					\
1272 	r1 = %[map_hash_16b] ll;			\
1273 	call %[bpf_map_lookup_elem];			\
1274 l0_%=:	exit;						\
1275 "	:
1276 	: __imm(bpf_map_lookup_elem),
1277 	  __imm_addr(map_hash_16b),
1278 	  __imm_const(__imm_0, offsetof(struct other_val, bar) + 1)
1279 	: __clobber_all);
1280 }
1281 
1282 char _license[] SEC("license") = "GPL";
1283