1283 lines · c
1// SPDX-License-Identifier: GPL-2.02/* 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 8struct other_val {9 long long foo;10 long long bar;11};12 13struct {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 1121 22struct test_val {23 unsigned int index;24 int foo[MAX_ENTRIES];25};26 27struct {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 34struct {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 41SEC("tracepoint")42__description("helper access to map: full range")43__success44__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]; \58l0_%=: 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 67SEC("tracepoint")68__description("helper access to map: partial range")69__success70__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]; \84l0_%=: 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 to93 * be zero (i.e. bpf_trace_printk() declares the second argument to be94 * ARG_CONST_SIZE, not ARG_CONST_SIZE_OR_ZERO). We attempt to pass zero for the95 * size and expect to fail.96 */97SEC("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]; \113l0_%=: 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 */124SEC("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]; \145l0_%=: exit; \146" :147 : __imm(bpf_map_lookup_elem),148 __imm(bpf_trace_printk),149 __imm_addr(map_hash_48b)150 : __clobber_all);151}152 153SEC("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]; \170l0_%=: 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 179SEC("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]; \196l0_%=: 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 204SEC("tracepoint")205__description("helper access to adjusted map (via const imm): full range")206__success207__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]; \222l0_%=: 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 232SEC("tracepoint")233__description("helper access to adjusted map (via const imm): partial range")234__success235__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]; \250l0_%=: 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 259SEC("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]; \276l0_%=: 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 285SEC("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]; \303l0_%=: 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 313SEC("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]; \331l0_%=: 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 340SEC("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]; \358l0_%=: 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 367SEC("tracepoint")368__description("helper access to adjusted map (via const reg): full range")369__success370__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]; \386l0_%=: 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 396SEC("tracepoint")397__description("helper access to adjusted map (via const reg): partial range")398__success399__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]; \415l0_%=: 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 424SEC("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]; \442l0_%=: exit; \443" :444 : __imm(bpf_map_lookup_elem),445 __imm(bpf_trace_printk),446 __imm_addr(map_hash_48b)447 : __clobber_all);448}449 450SEC("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]; \469l0_%=: 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 479SEC("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]; \498l0_%=: 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 507SEC("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]; \526l0_%=: 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 535SEC("tracepoint")536__description("helper access to adjusted map (via variable): full range")537__success538__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]; \555l0_%=: 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 565SEC("tracepoint")566__description("helper access to adjusted map (via variable): partial range")567__success568__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]; \585l0_%=: 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 594SEC("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]; \613l0_%=: 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 622SEC("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]; \641l0_%=: 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 649SEC("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]; \669l0_%=: 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 679SEC("tracepoint")680__description("helper access to map: bounds check using <, good access")681__success682__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; \696l0_%=: exit; \697l1_%=: 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 708SEC("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; \725l0_%=: r0 = 0; \726 *(u8*)(r1 + 0) = r0; \727 r0 = 0; \728 exit; \729l1_%=: r0 = 0; \730 exit; \731" :732 : __imm(bpf_map_lookup_elem),733 __imm_addr(map_hash_48b)734 : __clobber_all);735}736 737SEC("tracepoint")738__description("helper access to map: bounds check using <=, good access")739__success740__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; \754l0_%=: exit; \755l1_%=: 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 766SEC("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; \783l0_%=: r0 = 0; \784 *(u8*)(r1 + 0) = r0; \785 r0 = 0; \786 exit; \787l1_%=: r0 = 0; \788 exit; \789" :790 : __imm(bpf_map_lookup_elem),791 __imm_addr(map_hash_48b)792 : __clobber_all);793}794 795SEC("tracepoint")796__description("helper access to map: bounds check using s<, good access")797__success798__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_%=; \811l2_%=: r0 = 0; \812l0_%=: exit; \813l1_%=: 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 825SEC("tracepoint")826__description("helper access to map: bounds check using s<, good access 2")827__success828__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_%=; \841l2_%=: r0 = 0; \842l0_%=: exit; \843l1_%=: 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 855SEC("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_%=; \871l2_%=: r0 = 0; \872l0_%=: exit; \873l1_%=: 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 885SEC("tracepoint")886__description("helper access to map: bounds check using s<=, good access")887__success888__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_%=; \901l2_%=: r0 = 0; \902l0_%=: exit; \903l1_%=: 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 915SEC("tracepoint")916__description("helper access to map: bounds check using s<=, good access 2")917__success918__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_%=; \931l2_%=: r0 = 0; \932l0_%=: exit; \933l1_%=: 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 945SEC("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_%=; \961l2_%=: r0 = 0; \962l0_%=: exit; \963l1_%=: 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 975SEC("tracepoint")976__description("map lookup helper access to map")977__success978__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]; \991l0_%=: exit; \992" :993 : __imm(bpf_map_lookup_elem),994 __imm_addr(map_hash_16b)995 : __clobber_all);996}997 998SEC("tracepoint")999__description("map update helper access to map")1000__success1001__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]; \1016l0_%=: 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 1024SEC("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]; \1042l0_%=: 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 1051SEC("tracepoint")1052__description("map helper access to adjusted map (via const imm)")1053__success1054__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]; \1068l0_%=: 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 1076SEC("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]; \1093l0_%=: 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 1101SEC("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]; \1118l0_%=: exit; \1119" :1120 : __imm(bpf_map_lookup_elem),1121 __imm_addr(map_hash_16b)1122 : __clobber_all);1123}1124 1125SEC("tracepoint")1126__description("map helper access to adjusted map (via const reg)")1127__success1128__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]; \1143l0_%=: 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 1151SEC("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]; \1169l0_%=: 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 1177SEC("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]; \1195l0_%=: exit; \1196" :1197 : __imm(bpf_map_lookup_elem),1198 __imm_addr(map_hash_16b)1199 : __clobber_all);1200}1201 1202SEC("tracepoint")1203__description("map helper access to adjusted map (via variable)")1204__success1205__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]; \1221l0_%=: 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 1229SEC("tracepoint")1230__description("map helper access to adjusted map (via variable): no max check")1231__failure1232__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]; \1248l0_%=: exit; \1249" :1250 : __imm(bpf_map_lookup_elem),1251 __imm_addr(map_hash_16b)1252 : __clobber_all);1253}1254 1255SEC("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]; \1274l0_%=: 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 1282char _license[] SEC("license") = "GPL";1283