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 |
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 |
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]" ) |
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]" ) |
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" ) |
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" ) |
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 |
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 |
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" ) |
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" ) |
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" ) |
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" ) |
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 |
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 |
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" ) |
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" ) |
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" ) |
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" ) |
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 |
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 |
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" ) |
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" ) |
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" ) |
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 |
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" ) |
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 |
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" ) |
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 |
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 |
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" ) |
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 |
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 |
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" ) |
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 |
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 |
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" ) |
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 |
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" ) |
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" ) |
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 |
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" ) |
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" ) |
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 |
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" ) |
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" ) |
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 | |