1424 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Converted from tools/testing/selftests/bpf/verifier/value_ptr_arith.c */3 4#include <linux/bpf.h>5#include <bpf/bpf_helpers.h>6#include <errno.h>7#include "bpf_misc.h"8 9#define MAX_ENTRIES 1110 11struct test_val {12 unsigned int index;13 int foo[MAX_ENTRIES];14};15 16struct {17 __uint(type, BPF_MAP_TYPE_ARRAY);18 __uint(max_entries, 1);19 __type(key, int);20 __type(value, struct test_val);21} map_array_48b SEC(".maps");22 23struct other_val {24 long long foo;25 long long bar;26};27 28struct {29 __uint(type, BPF_MAP_TYPE_HASH);30 __uint(max_entries, 1);31 __type(key, long long);32 __type(value, struct other_val);33} map_hash_16b SEC(".maps");34 35struct {36 __uint(type, BPF_MAP_TYPE_HASH);37 __uint(max_entries, 1);38 __type(key, long long);39 __type(value, struct test_val);40} map_hash_48b SEC(".maps");41 42SEC("socket")43__description("map access: known scalar += value_ptr unknown vs const")44__success __failure_unpriv45__msg_unpriv("R1 tried to add from different maps, paths or scalars")46__retval(1)47__naked void value_ptr_unknown_vs_const(void)48{49 asm volatile (" \50 r0 = *(u32*)(r1 + %[__sk_buff_len]); \51 r1 = 0; \52 *(u64*)(r10 - 8) = r1; \53 r2 = r10; \54 r2 += -8; \55 if r0 == 1 goto l0_%=; \56 r1 = %[map_hash_16b] ll; \57 if r0 != 1 goto l1_%=; \58l0_%=: r1 = %[map_array_48b] ll; \59l1_%=: call %[bpf_map_lookup_elem]; \60 if r0 == 0 goto l2_%=; \61 r4 = *(u8*)(r0 + 0); \62 if r4 == 1 goto l3_%=; \63 r1 = 6; \64 r1 = -r1; \65 r1 &= 0x7; \66 goto l4_%=; \67l3_%=: r1 = 3; \68l4_%=: r1 += r0; \69 r0 = *(u8*)(r1 + 0); \70l2_%=: r0 = 1; \71 exit; \72" :73 : __imm(bpf_map_lookup_elem),74 __imm_addr(map_array_48b),75 __imm_addr(map_hash_16b),76 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))77 : __clobber_all);78}79 80SEC("socket")81__description("map access: known scalar += value_ptr const vs unknown")82__success __failure_unpriv83__msg_unpriv("R1 tried to add from different maps, paths or scalars")84__retval(1)85__naked void value_ptr_const_vs_unknown(void)86{87 asm volatile (" \88 r0 = *(u32*)(r1 + %[__sk_buff_len]); \89 r1 = 0; \90 *(u64*)(r10 - 8) = r1; \91 r2 = r10; \92 r2 += -8; \93 if r0 == 1 goto l0_%=; \94 r1 = %[map_hash_16b] ll; \95 if r0 != 1 goto l1_%=; \96l0_%=: r1 = %[map_array_48b] ll; \97l1_%=: call %[bpf_map_lookup_elem]; \98 if r0 == 0 goto l2_%=; \99 r4 = *(u8*)(r0 + 0); \100 if r4 == 1 goto l3_%=; \101 r1 = 3; \102 goto l4_%=; \103l3_%=: r1 = 6; \104 r1 = -r1; \105 r1 &= 0x7; \106l4_%=: r1 += r0; \107 r0 = *(u8*)(r1 + 0); \108l2_%=: r0 = 1; \109 exit; \110" :111 : __imm(bpf_map_lookup_elem),112 __imm_addr(map_array_48b),113 __imm_addr(map_hash_16b),114 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))115 : __clobber_all);116}117 118SEC("socket")119__description("map access: known scalar += value_ptr const vs const (ne)")120__success __failure_unpriv121__msg_unpriv("R1 tried to add from different maps, paths or scalars")122__retval(1)123__naked void ptr_const_vs_const_ne(void)124{125 asm volatile (" \126 r0 = *(u32*)(r1 + %[__sk_buff_len]); \127 r1 = 0; \128 *(u64*)(r10 - 8) = r1; \129 r2 = r10; \130 r2 += -8; \131 if r0 == 1 goto l0_%=; \132 r1 = %[map_hash_16b] ll; \133 if r0 != 1 goto l1_%=; \134l0_%=: r1 = %[map_array_48b] ll; \135l1_%=: call %[bpf_map_lookup_elem]; \136 if r0 == 0 goto l2_%=; \137 r4 = *(u8*)(r0 + 0); \138 if r4 == 1 goto l3_%=; \139 r1 = 3; \140 goto l4_%=; \141l3_%=: r1 = 5; \142l4_%=: r1 += r0; \143 r0 = *(u8*)(r1 + 0); \144l2_%=: r0 = 1; \145 exit; \146" :147 : __imm(bpf_map_lookup_elem),148 __imm_addr(map_array_48b),149 __imm_addr(map_hash_16b),150 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))151 : __clobber_all);152}153 154SEC("socket")155__description("map access: known scalar += value_ptr const vs const (eq)")156__success __success_unpriv __retval(1)157__naked void ptr_const_vs_const_eq(void)158{159 asm volatile (" \160 r0 = *(u32*)(r1 + %[__sk_buff_len]); \161 r1 = 0; \162 *(u64*)(r10 - 8) = r1; \163 r2 = r10; \164 r2 += -8; \165 if r0 == 1 goto l0_%=; \166 r1 = %[map_hash_16b] ll; \167 if r0 != 1 goto l1_%=; \168l0_%=: r1 = %[map_array_48b] ll; \169l1_%=: call %[bpf_map_lookup_elem]; \170 if r0 == 0 goto l2_%=; \171 r4 = *(u8*)(r0 + 0); \172 if r4 == 1 goto l3_%=; \173 r1 = 5; \174 goto l4_%=; \175l3_%=: r1 = 5; \176l4_%=: r1 += r0; \177 r0 = *(u8*)(r1 + 0); \178l2_%=: r0 = 1; \179 exit; \180" :181 : __imm(bpf_map_lookup_elem),182 __imm_addr(map_array_48b),183 __imm_addr(map_hash_16b),184 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))185 : __clobber_all);186}187 188SEC("socket")189__description("map access: known scalar += value_ptr unknown vs unknown (eq)")190__success __success_unpriv __retval(1)191__naked void ptr_unknown_vs_unknown_eq(void)192{193 asm volatile (" \194 r0 = *(u32*)(r1 + %[__sk_buff_len]); \195 r1 = 0; \196 *(u64*)(r10 - 8) = r1; \197 r2 = r10; \198 r2 += -8; \199 if r0 == 1 goto l0_%=; \200 r1 = %[map_hash_16b] ll; \201 if r0 != 1 goto l1_%=; \202l0_%=: r1 = %[map_array_48b] ll; \203l1_%=: call %[bpf_map_lookup_elem]; \204 if r0 == 0 goto l2_%=; \205 r4 = *(u8*)(r0 + 0); \206 if r4 == 1 goto l3_%=; \207 r1 = 6; \208 r1 = -r1; \209 r1 &= 0x7; \210 goto l4_%=; \211l3_%=: r1 = 6; \212 r1 = -r1; \213 r1 &= 0x7; \214l4_%=: r1 += r0; \215 r0 = *(u8*)(r1 + 0); \216l2_%=: r0 = 1; \217 exit; \218" :219 : __imm(bpf_map_lookup_elem),220 __imm_addr(map_array_48b),221 __imm_addr(map_hash_16b),222 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))223 : __clobber_all);224}225 226SEC("socket")227__description("map access: known scalar += value_ptr unknown vs unknown (lt)")228__success __failure_unpriv229__msg_unpriv("R1 tried to add from different maps, paths or scalars")230__retval(1)231__naked void ptr_unknown_vs_unknown_lt(void)232{233 asm volatile (" \234 r0 = *(u32*)(r1 + %[__sk_buff_len]); \235 r1 = 0; \236 *(u64*)(r10 - 8) = r1; \237 r2 = r10; \238 r2 += -8; \239 if r0 == 1 goto l0_%=; \240 r1 = %[map_hash_16b] ll; \241 if r0 != 1 goto l1_%=; \242l0_%=: r1 = %[map_array_48b] ll; \243l1_%=: call %[bpf_map_lookup_elem]; \244 if r0 == 0 goto l2_%=; \245 r4 = *(u8*)(r0 + 0); \246 if r4 == 1 goto l3_%=; \247 r1 = 6; \248 r1 = -r1; \249 r1 &= 0x3; \250 goto l4_%=; \251l3_%=: r1 = 6; \252 r1 = -r1; \253 r1 &= 0x7; \254l4_%=: r1 += r0; \255 r0 = *(u8*)(r1 + 0); \256l2_%=: r0 = 1; \257 exit; \258" :259 : __imm(bpf_map_lookup_elem),260 __imm_addr(map_array_48b),261 __imm_addr(map_hash_16b),262 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))263 : __clobber_all);264}265 266SEC("socket")267__description("map access: known scalar += value_ptr unknown vs unknown (gt)")268__success __failure_unpriv269__msg_unpriv("R1 tried to add from different maps, paths or scalars")270__retval(1)271__naked void ptr_unknown_vs_unknown_gt(void)272{273 asm volatile (" \274 r0 = *(u32*)(r1 + %[__sk_buff_len]); \275 r1 = 0; \276 *(u64*)(r10 - 8) = r1; \277 r2 = r10; \278 r2 += -8; \279 if r0 == 1 goto l0_%=; \280 r1 = %[map_hash_16b] ll; \281 if r0 != 1 goto l1_%=; \282l0_%=: r1 = %[map_array_48b] ll; \283l1_%=: call %[bpf_map_lookup_elem]; \284 if r0 == 0 goto l2_%=; \285 r4 = *(u8*)(r0 + 0); \286 if r4 == 1 goto l3_%=; \287 r1 = 6; \288 r1 = -r1; \289 r1 &= 0x7; \290 goto l4_%=; \291l3_%=: r1 = 6; \292 r1 = -r1; \293 r1 &= 0x3; \294l4_%=: r1 += r0; \295 r0 = *(u8*)(r1 + 0); \296l2_%=: r0 = 1; \297 exit; \298" :299 : __imm(bpf_map_lookup_elem),300 __imm_addr(map_array_48b),301 __imm_addr(map_hash_16b),302 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))303 : __clobber_all);304}305 306SEC("socket")307__description("map access: known scalar += value_ptr from different maps")308__success __success_unpriv __retval(1)309__naked void value_ptr_from_different_maps(void)310{311 asm volatile (" \312 r0 = *(u32*)(r1 + %[__sk_buff_len]); \313 r1 = 0; \314 *(u64*)(r10 - 8) = r1; \315 r2 = r10; \316 r2 += -8; \317 if r0 == 1 goto l0_%=; \318 r1 = %[map_hash_16b] ll; \319 if r0 != 1 goto l1_%=; \320l0_%=: r1 = %[map_array_48b] ll; \321l1_%=: call %[bpf_map_lookup_elem]; \322 if r0 == 0 goto l2_%=; \323 r1 = 4; \324 r1 += r0; \325 r0 = *(u8*)(r1 + 0); \326l2_%=: r0 = 1; \327 exit; \328" :329 : __imm(bpf_map_lookup_elem),330 __imm_addr(map_array_48b),331 __imm_addr(map_hash_16b),332 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))333 : __clobber_all);334}335 336SEC("socket")337__description("map access: value_ptr -= known scalar from different maps")338__success __failure_unpriv339__msg_unpriv("R0 min value is outside of the allowed memory range")340__retval(1)341__naked void known_scalar_from_different_maps(void)342{343 asm volatile (" \344 r0 = *(u32*)(r1 + %[__sk_buff_len]); \345 r1 = 0; \346 *(u64*)(r10 - 8) = r1; \347 r2 = r10; \348 r2 += -8; \349 if r0 == 1 goto l0_%=; \350 r1 = %[map_hash_16b] ll; \351 if r0 != 1 goto l1_%=; \352l0_%=: r1 = %[map_array_48b] ll; \353l1_%=: call %[bpf_map_lookup_elem]; \354 if r0 == 0 goto l2_%=; \355 r1 = 4; \356 r0 -= r1; \357 r0 += r1; \358 r0 = *(u8*)(r0 + 0); \359l2_%=: r0 = 1; \360 exit; \361" :362 : __imm(bpf_map_lookup_elem),363 __imm_addr(map_array_48b),364 __imm_addr(map_hash_16b),365 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))366 : __clobber_all);367}368 369SEC("socket")370__description("map access: known scalar += value_ptr from different maps, but same value properties")371__success __success_unpriv __retval(1)372__naked void maps_but_same_value_properties(void)373{374 asm volatile (" \375 r0 = *(u32*)(r1 + %[__sk_buff_len]); \376 r1 = 0; \377 *(u64*)(r10 - 8) = r1; \378 r2 = r10; \379 r2 += -8; \380 if r0 == 1 goto l0_%=; \381 r1 = %[map_hash_48b] ll; \382 if r0 != 1 goto l1_%=; \383l0_%=: r1 = %[map_array_48b] ll; \384l1_%=: call %[bpf_map_lookup_elem]; \385 if r0 == 0 goto l2_%=; \386 r1 = 4; \387 r1 += r0; \388 r0 = *(u8*)(r1 + 0); \389l2_%=: r0 = 1; \390 exit; \391" :392 : __imm(bpf_map_lookup_elem),393 __imm_addr(map_array_48b),394 __imm_addr(map_hash_48b),395 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))396 : __clobber_all);397}398 399SEC("socket")400__description("map access: mixing value pointer and scalar, 1")401__success __failure_unpriv __msg_unpriv("R2 pointer comparison prohibited")402__retval(0)403__naked void value_pointer_and_scalar_1(void)404{405 asm volatile (" \406 /* load map value pointer into r0 and r2 */ \407 r0 = 1; \408 r1 = %[map_array_48b] ll; \409 r2 = r10; \410 r2 += -16; \411 r6 = 0; \412 *(u64*)(r10 - 16) = r6; \413 call %[bpf_map_lookup_elem]; \414 if r0 != 0 goto l0_%=; \415 exit; \416l0_%=: /* load some number from the map into r1 */ \417 r1 = *(u8*)(r0 + 0); \418 /* depending on r1, branch: */ \419 if r1 != 0 goto l1_%=; \420 /* branch A */ \421 r2 = r0; \422 r3 = 0; \423 goto l2_%=; \424l1_%=: /* branch B */ \425 r2 = 0; \426 r3 = 0x100000; \427l2_%=: /* common instruction */ \428 r2 += r3; \429 /* depending on r1, branch: */ \430 if r1 != 0 goto l3_%=; \431 /* branch A */ \432 goto l4_%=; \433l3_%=: /* branch B */ \434 r0 = 0x13371337; \435 /* verifier follows fall-through */ \436 if r2 != 0x100000 goto l4_%=; \437 r0 = 0; \438 exit; \439l4_%=: /* fake-dead code; targeted from branch A to \440 * prevent dead code sanitization \441 */ \442 r0 = *(u8*)(r0 + 0); \443 r0 = 0; \444 exit; \445" :446 : __imm(bpf_map_lookup_elem),447 __imm_addr(map_array_48b)448 : __clobber_all);449}450 451SEC("socket")452__description("map access: mixing value pointer and scalar, 2")453__success __failure_unpriv __msg_unpriv("R0 invalid mem access 'scalar'")454__retval(0)455__naked void value_pointer_and_scalar_2(void)456{457 asm volatile (" \458 /* load map value pointer into r0 and r2 */ \459 r0 = 1; \460 r1 = %[map_array_48b] ll; \461 r2 = r10; \462 r2 += -16; \463 r6 = 0; \464 *(u64*)(r10 - 16) = r6; \465 call %[bpf_map_lookup_elem]; \466 if r0 != 0 goto l0_%=; \467 exit; \468l0_%=: /* load some number from the map into r1 */ \469 r1 = *(u8*)(r0 + 0); \470 /* depending on r1, branch: */ \471 if r1 == 0 goto l1_%=; \472 /* branch A */ \473 r2 = 0; \474 r3 = 0x100000; \475 goto l2_%=; \476l1_%=: /* branch B */ \477 r2 = r0; \478 r3 = 0; \479l2_%=: /* common instruction */ \480 r2 += r3; \481 /* depending on r1, branch: */ \482 if r1 != 0 goto l3_%=; \483 /* branch A */ \484 goto l4_%=; \485l3_%=: /* branch B */ \486 r0 = 0x13371337; \487 /* verifier follows fall-through */ \488 if r2 != 0x100000 goto l4_%=; \489 r0 = 0; \490 exit; \491l4_%=: /* fake-dead code; targeted from branch A to \492 * prevent dead code sanitization, rejected \493 * via branch B however \494 */ \495 r0 = *(u8*)(r0 + 0); \496 r0 = 0; \497 exit; \498" :499 : __imm(bpf_map_lookup_elem),500 __imm_addr(map_array_48b)501 : __clobber_all);502}503 504SEC("socket")505__description("sanitation: alu with different scalars 1")506__success __success_unpriv __retval(0x100000)507__naked void alu_with_different_scalars_1(void)508{509 asm volatile (" \510 r0 = 1; \511 r1 = %[map_array_48b] ll; \512 r2 = r10; \513 r2 += -16; \514 r6 = 0; \515 *(u64*)(r10 - 16) = r6; \516 call %[bpf_map_lookup_elem]; \517 if r0 != 0 goto l0_%=; \518 exit; \519l0_%=: r1 = *(u32*)(r0 + 0); \520 if r1 == 0 goto l1_%=; \521 r2 = 0; \522 r3 = 0x100000; \523 goto l2_%=; \524l1_%=: r2 = 42; \525 r3 = 0x100001; \526l2_%=: r2 += r3; \527 r0 = r2; \528 exit; \529" :530 : __imm(bpf_map_lookup_elem),531 __imm_addr(map_array_48b)532 : __clobber_all);533}534 535SEC("socket")536__description("sanitation: alu with different scalars 2")537__success __success_unpriv __retval(0)538__naked void alu_with_different_scalars_2(void)539{540 asm volatile (" \541 r0 = 1; \542 r1 = %[map_array_48b] ll; \543 r6 = r1; \544 r2 = r10; \545 r2 += -16; \546 r7 = 0; \547 *(u64*)(r10 - 16) = r7; \548 call %[bpf_map_delete_elem]; \549 r7 = r0; \550 r1 = r6; \551 r2 = r10; \552 r2 += -16; \553 call %[bpf_map_delete_elem]; \554 r6 = r0; \555 r8 = r6; \556 r8 += r7; \557 r0 = r8; \558 r0 += %[einval]; \559 r0 += %[einval]; \560 exit; \561" :562 : __imm(bpf_map_delete_elem),563 __imm_addr(map_array_48b),564 __imm_const(einval, EINVAL)565 : __clobber_all);566}567 568SEC("socket")569__description("sanitation: alu with different scalars 3")570__success __success_unpriv __retval(0)571__naked void alu_with_different_scalars_3(void)572{573 asm volatile (" \574 r0 = %[einval]; \575 r0 *= -1; \576 r7 = r0; \577 r0 = %[einval]; \578 r0 *= -1; \579 r6 = r0; \580 r8 = r6; \581 r8 += r7; \582 r0 = r8; \583 r0 += %[einval]; \584 r0 += %[einval]; \585 exit; \586" :587 : __imm_const(einval, EINVAL)588 : __clobber_all);589}590 591SEC("socket")592__description("map access: value_ptr += known scalar, upper oob arith, test 1")593__success __failure_unpriv594__msg_unpriv("R0 pointer arithmetic of map value goes out of range")595__retval(1)596__naked void upper_oob_arith_test_1(void)597{598 asm volatile (" \599 r1 = 0; \600 *(u64*)(r10 - 8) = r1; \601 r2 = r10; \602 r2 += -8; \603 r1 = %[map_array_48b] ll; \604 call %[bpf_map_lookup_elem]; \605 if r0 == 0 goto l0_%=; \606 r1 = 48; \607 r0 += r1; \608 r0 -= r1; \609 r0 = *(u8*)(r0 + 0); \610l0_%=: r0 = 1; \611 exit; \612" :613 : __imm(bpf_map_lookup_elem),614 __imm_addr(map_array_48b)615 : __clobber_all);616}617 618SEC("socket")619__description("map access: value_ptr += known scalar, upper oob arith, test 2")620__success __failure_unpriv621__msg_unpriv("R0 pointer arithmetic of map value goes out of range")622__retval(1)623__naked void upper_oob_arith_test_2(void)624{625 asm volatile (" \626 r1 = 0; \627 *(u64*)(r10 - 8) = r1; \628 r2 = r10; \629 r2 += -8; \630 r1 = %[map_array_48b] ll; \631 call %[bpf_map_lookup_elem]; \632 if r0 == 0 goto l0_%=; \633 r1 = 49; \634 r0 += r1; \635 r0 -= r1; \636 r0 = *(u8*)(r0 + 0); \637l0_%=: r0 = 1; \638 exit; \639" :640 : __imm(bpf_map_lookup_elem),641 __imm_addr(map_array_48b)642 : __clobber_all);643}644 645SEC("socket")646__description("map access: value_ptr += known scalar, upper oob arith, test 3")647__success __success_unpriv __retval(1)648__naked void upper_oob_arith_test_3(void)649{650 asm volatile (" \651 r1 = 0; \652 *(u64*)(r10 - 8) = r1; \653 r2 = r10; \654 r2 += -8; \655 r1 = %[map_array_48b] ll; \656 call %[bpf_map_lookup_elem]; \657 if r0 == 0 goto l0_%=; \658 r1 = 47; \659 r0 += r1; \660 r0 -= r1; \661 r0 = *(u8*)(r0 + 0); \662l0_%=: r0 = 1; \663 exit; \664" :665 : __imm(bpf_map_lookup_elem),666 __imm_addr(map_array_48b)667 : __clobber_all);668}669 670SEC("socket")671__description("map access: value_ptr -= known scalar, lower oob arith, test 1")672__failure __msg("R0 min value is outside of the allowed memory range")673__failure_unpriv674__msg_unpriv("R0 pointer arithmetic of map value goes out of range")675__naked void lower_oob_arith_test_1(void)676{677 asm volatile (" \678 r1 = 0; \679 *(u64*)(r10 - 8) = r1; \680 r2 = r10; \681 r2 += -8; \682 r1 = %[map_array_48b] ll; \683 call %[bpf_map_lookup_elem]; \684 if r0 == 0 goto l0_%=; \685 r1 = 47; \686 r0 += r1; \687 r1 = 48; \688 r0 -= r1; \689 r0 = *(u8*)(r0 + 0); \690l0_%=: r0 = 1; \691 exit; \692" :693 : __imm(bpf_map_lookup_elem),694 __imm_addr(map_array_48b)695 : __clobber_all);696}697 698SEC("socket")699__description("map access: value_ptr -= known scalar, lower oob arith, test 2")700__success __failure_unpriv701__msg_unpriv("R0 pointer arithmetic of map value goes out of range")702__retval(1)703__naked void lower_oob_arith_test_2(void)704{705 asm volatile (" \706 r1 = 0; \707 *(u64*)(r10 - 8) = r1; \708 r2 = r10; \709 r2 += -8; \710 r1 = %[map_array_48b] ll; \711 call %[bpf_map_lookup_elem]; \712 if r0 == 0 goto l0_%=; \713 r1 = 47; \714 r0 += r1; \715 r1 = 48; \716 r0 -= r1; \717 r1 = 1; \718 r0 += r1; \719 r0 = *(u8*)(r0 + 0); \720l0_%=: r0 = 1; \721 exit; \722" :723 : __imm(bpf_map_lookup_elem),724 __imm_addr(map_array_48b)725 : __clobber_all);726}727 728SEC("socket")729__description("map access: value_ptr -= known scalar, lower oob arith, test 3")730__success __success_unpriv __retval(1)731__naked void lower_oob_arith_test_3(void)732{733 asm volatile (" \734 r1 = 0; \735 *(u64*)(r10 - 8) = r1; \736 r2 = r10; \737 r2 += -8; \738 r1 = %[map_array_48b] ll; \739 call %[bpf_map_lookup_elem]; \740 if r0 == 0 goto l0_%=; \741 r1 = 47; \742 r0 += r1; \743 r1 = 47; \744 r0 -= r1; \745 r0 = *(u8*)(r0 + 0); \746l0_%=: r0 = 1; \747 exit; \748" :749 : __imm(bpf_map_lookup_elem),750 __imm_addr(map_array_48b)751 : __clobber_all);752}753 754SEC("socket")755__description("map access: known scalar += value_ptr")756__success __success_unpriv __retval(1)757__naked void access_known_scalar_value_ptr_1(void)758{759 asm volatile (" \760 r1 = 0; \761 *(u64*)(r10 - 8) = r1; \762 r2 = r10; \763 r2 += -8; \764 r1 = %[map_array_48b] ll; \765 call %[bpf_map_lookup_elem]; \766 if r0 == 0 goto l0_%=; \767 r1 = 4; \768 r1 += r0; \769 r0 = *(u8*)(r1 + 0); \770l0_%=: r0 = 1; \771 exit; \772" :773 : __imm(bpf_map_lookup_elem),774 __imm_addr(map_array_48b)775 : __clobber_all);776}777 778SEC("socket")779__description("map access: value_ptr += known scalar, 1")780__success __success_unpriv __retval(1)781__naked void value_ptr_known_scalar_1(void)782{783 asm volatile (" \784 r1 = 0; \785 *(u64*)(r10 - 8) = r1; \786 r2 = r10; \787 r2 += -8; \788 r1 = %[map_array_48b] ll; \789 call %[bpf_map_lookup_elem]; \790 if r0 == 0 goto l0_%=; \791 r1 = 4; \792 r0 += r1; \793 r1 = *(u8*)(r0 + 0); \794l0_%=: r0 = 1; \795 exit; \796" :797 : __imm(bpf_map_lookup_elem),798 __imm_addr(map_array_48b)799 : __clobber_all);800}801 802SEC("socket")803__description("map access: value_ptr += known scalar, 2")804__failure __msg("invalid access to map value")805__failure_unpriv806__naked void value_ptr_known_scalar_2_1(void)807{808 asm volatile (" \809 r1 = 0; \810 *(u64*)(r10 - 8) = r1; \811 r2 = r10; \812 r2 += -8; \813 r1 = %[map_array_48b] ll; \814 call %[bpf_map_lookup_elem]; \815 if r0 == 0 goto l0_%=; \816 r1 = 49; \817 r0 += r1; \818 r1 = *(u8*)(r0 + 0); \819l0_%=: r0 = 1; \820 exit; \821" :822 : __imm(bpf_map_lookup_elem),823 __imm_addr(map_array_48b)824 : __clobber_all);825}826 827SEC("socket")828__description("map access: value_ptr += known scalar, 3")829__failure __msg("invalid access to map value")830__failure_unpriv831__naked void value_ptr_known_scalar_3(void)832{833 asm volatile (" \834 r1 = 0; \835 *(u64*)(r10 - 8) = r1; \836 r2 = r10; \837 r2 += -8; \838 r1 = %[map_array_48b] ll; \839 call %[bpf_map_lookup_elem]; \840 if r0 == 0 goto l0_%=; \841 r1 = -1; \842 r0 += r1; \843 r1 = *(u8*)(r0 + 0); \844l0_%=: r0 = 1; \845 exit; \846" :847 : __imm(bpf_map_lookup_elem),848 __imm_addr(map_array_48b)849 : __clobber_all);850}851 852SEC("socket")853__description("map access: value_ptr += known scalar, 4")854__success __success_unpriv __retval(1)855__naked void value_ptr_known_scalar_4(void)856{857 asm volatile (" \858 r1 = 0; \859 *(u64*)(r10 - 8) = r1; \860 r2 = r10; \861 r2 += -8; \862 r1 = %[map_array_48b] ll; \863 call %[bpf_map_lookup_elem]; \864 if r0 == 0 goto l0_%=; \865 r1 = 5; \866 r0 += r1; \867 r1 = -2; \868 r0 += r1; \869 r1 = -1; \870 r0 += r1; \871 r1 = *(u8*)(r0 + 0); \872l0_%=: r0 = 1; \873 exit; \874" :875 : __imm(bpf_map_lookup_elem),876 __imm_addr(map_array_48b)877 : __clobber_all);878}879 880SEC("socket")881__description("map access: value_ptr += known scalar, 5")882__success __success_unpriv __retval(0xabcdef12)883__naked void value_ptr_known_scalar_5(void)884{885 asm volatile (" \886 r1 = 0; \887 *(u64*)(r10 - 8) = r1; \888 r2 = r10; \889 r2 += -8; \890 r1 = %[map_array_48b] ll; \891 call %[bpf_map_lookup_elem]; \892 if r0 == 0 goto l0_%=; \893 r1 = %[__imm_0]; \894 r1 += r0; \895 r0 = *(u32*)(r1 + 0); \896l0_%=: exit; \897" :898 : __imm(bpf_map_lookup_elem),899 __imm_addr(map_array_48b),900 __imm_const(__imm_0, (6 + 1) * sizeof(int))901 : __clobber_all);902}903 904SEC("socket")905__description("map access: value_ptr += known scalar, 6")906__success __success_unpriv __retval(0xabcdef12)907__naked void value_ptr_known_scalar_6(void)908{909 asm volatile (" \910 r1 = 0; \911 *(u64*)(r10 - 8) = r1; \912 r2 = r10; \913 r2 += -8; \914 r1 = %[map_array_48b] ll; \915 call %[bpf_map_lookup_elem]; \916 if r0 == 0 goto l0_%=; \917 r1 = %[__imm_0]; \918 r0 += r1; \919 r1 = %[__imm_1]; \920 r0 += r1; \921 r0 = *(u32*)(r0 + 0); \922l0_%=: exit; \923" :924 : __imm(bpf_map_lookup_elem),925 __imm_addr(map_array_48b),926 __imm_const(__imm_0, (3 + 1) * sizeof(int)),927 __imm_const(__imm_1, 3 * sizeof(int))928 : __clobber_all);929}930 931SEC("socket")932__description("map access: value_ptr += N, value_ptr -= N known scalar")933__success __success_unpriv __retval(0x12345678)934__naked void value_ptr_n_known_scalar(void)935{936 asm volatile (" \937 r1 = 0; \938 *(u64*)(r10 - 8) = r1; \939 r2 = r10; \940 r2 += -8; \941 r1 = %[map_array_48b] ll; \942 call %[bpf_map_lookup_elem]; \943 if r0 == 0 goto l0_%=; \944 w1 = 0x12345678; \945 *(u32*)(r0 + 0) = r1; \946 r0 += 2; \947 r1 = 2; \948 r0 -= r1; \949 r0 = *(u32*)(r0 + 0); \950l0_%=: exit; \951" :952 : __imm(bpf_map_lookup_elem),953 __imm_addr(map_array_48b)954 : __clobber_all);955}956 957SEC("socket")958__description("map access: unknown scalar += value_ptr, 1")959__success __success_unpriv __retval(1)960__naked void unknown_scalar_value_ptr_1(void)961{962 asm volatile (" \963 r1 = 0; \964 *(u64*)(r10 - 8) = r1; \965 r2 = r10; \966 r2 += -8; \967 r1 = %[map_array_48b] ll; \968 call %[bpf_map_lookup_elem]; \969 if r0 == 0 goto l0_%=; \970 r1 = *(u8*)(r0 + 0); \971 r1 &= 0xf; \972 r1 += r0; \973 r0 = *(u8*)(r1 + 0); \974l0_%=: r0 = 1; \975 exit; \976" :977 : __imm(bpf_map_lookup_elem),978 __imm_addr(map_array_48b)979 : __clobber_all);980}981 982SEC("socket")983__description("map access: unknown scalar += value_ptr, 2")984__success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)985__naked void unknown_scalar_value_ptr_2(void)986{987 asm volatile (" \988 r1 = 0; \989 *(u64*)(r10 - 8) = r1; \990 r2 = r10; \991 r2 += -8; \992 r1 = %[map_array_48b] ll; \993 call %[bpf_map_lookup_elem]; \994 if r0 == 0 goto l0_%=; \995 r1 = *(u32*)(r0 + 0); \996 r1 &= 31; \997 r1 += r0; \998 r0 = *(u32*)(r1 + 0); \999l0_%=: exit; \1000" :1001 : __imm(bpf_map_lookup_elem),1002 __imm_addr(map_array_48b)1003 : __clobber_all);1004}1005 1006SEC("socket")1007__description("map access: unknown scalar += value_ptr, 3")1008__success __failure_unpriv1009__msg_unpriv("R0 pointer arithmetic of map value goes out of range")1010__retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)1011__naked void unknown_scalar_value_ptr_3(void)1012{1013 asm volatile (" \1014 r1 = 0; \1015 *(u64*)(r10 - 8) = r1; \1016 r2 = r10; \1017 r2 += -8; \1018 r1 = %[map_array_48b] ll; \1019 call %[bpf_map_lookup_elem]; \1020 if r0 == 0 goto l0_%=; \1021 r1 = -1; \1022 r0 += r1; \1023 r1 = 1; \1024 r0 += r1; \1025 r1 = *(u32*)(r0 + 0); \1026 r1 &= 31; \1027 r1 += r0; \1028 r0 = *(u32*)(r1 + 0); \1029l0_%=: exit; \1030" :1031 : __imm(bpf_map_lookup_elem),1032 __imm_addr(map_array_48b)1033 : __clobber_all);1034}1035 1036SEC("socket")1037__description("map access: unknown scalar += value_ptr, 4")1038__failure __msg("R1 max value is outside of the allowed memory range")1039__msg_unpriv("R1 pointer arithmetic of map value goes out of range")1040__flag(BPF_F_ANY_ALIGNMENT)1041__naked void unknown_scalar_value_ptr_4(void)1042{1043 asm volatile (" \1044 r1 = 0; \1045 *(u64*)(r10 - 8) = r1; \1046 r2 = r10; \1047 r2 += -8; \1048 r1 = %[map_array_48b] ll; \1049 call %[bpf_map_lookup_elem]; \1050 if r0 == 0 goto l0_%=; \1051 r1 = 19; \1052 r0 += r1; \1053 r1 = *(u32*)(r0 + 0); \1054 r1 &= 31; \1055 r1 += r0; \1056 r0 = *(u32*)(r1 + 0); \1057l0_%=: exit; \1058" :1059 : __imm(bpf_map_lookup_elem),1060 __imm_addr(map_array_48b)1061 : __clobber_all);1062}1063 1064SEC("socket")1065__description("map access: value_ptr += unknown scalar, 1")1066__success __success_unpriv __retval(1)1067__naked void value_ptr_unknown_scalar_1(void)1068{1069 asm volatile (" \1070 r1 = 0; \1071 *(u64*)(r10 - 8) = r1; \1072 r2 = r10; \1073 r2 += -8; \1074 r1 = %[map_array_48b] ll; \1075 call %[bpf_map_lookup_elem]; \1076 if r0 == 0 goto l0_%=; \1077 r1 = *(u8*)(r0 + 0); \1078 r1 &= 0xf; \1079 r0 += r1; \1080 r1 = *(u8*)(r0 + 0); \1081l0_%=: r0 = 1; \1082 exit; \1083" :1084 : __imm(bpf_map_lookup_elem),1085 __imm_addr(map_array_48b)1086 : __clobber_all);1087}1088 1089SEC("socket")1090__description("map access: value_ptr += unknown scalar, 2")1091__success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)1092__naked void value_ptr_unknown_scalar_2_1(void)1093{1094 asm volatile (" \1095 r1 = 0; \1096 *(u64*)(r10 - 8) = r1; \1097 r2 = r10; \1098 r2 += -8; \1099 r1 = %[map_array_48b] ll; \1100 call %[bpf_map_lookup_elem]; \1101 if r0 == 0 goto l0_%=; \1102 r1 = *(u32*)(r0 + 0); \1103 r1 &= 31; \1104 r0 += r1; \1105 r0 = *(u32*)(r0 + 0); \1106l0_%=: exit; \1107" :1108 : __imm(bpf_map_lookup_elem),1109 __imm_addr(map_array_48b)1110 : __clobber_all);1111}1112 1113SEC("socket")1114__description("map access: value_ptr += unknown scalar, 3")1115__success __success_unpriv __retval(1)1116__naked void value_ptr_unknown_scalar_3(void)1117{1118 asm volatile (" \1119 r1 = 0; \1120 *(u64*)(r10 - 8) = r1; \1121 r2 = r10; \1122 r2 += -8; \1123 r1 = %[map_array_48b] ll; \1124 call %[bpf_map_lookup_elem]; \1125 if r0 == 0 goto l0_%=; \1126 r1 = *(u64*)(r0 + 0); \1127 r2 = *(u64*)(r0 + 8); \1128 r3 = *(u64*)(r0 + 16); \1129 r1 &= 0xf; \1130 r3 &= 1; \1131 r3 |= 1; \1132 if r2 > r3 goto l0_%=; \1133 r0 += r3; \1134 r0 = *(u8*)(r0 + 0); \1135 r0 = 1; \1136l1_%=: exit; \1137l0_%=: r0 = 2; \1138 goto l1_%=; \1139" :1140 : __imm(bpf_map_lookup_elem),1141 __imm_addr(map_array_48b)1142 : __clobber_all);1143}1144 1145SEC("socket")1146__description("map access: value_ptr += value_ptr")1147__failure __msg("R0 pointer += pointer prohibited")1148__failure_unpriv1149__naked void access_value_ptr_value_ptr_1(void)1150{1151 asm volatile (" \1152 r1 = 0; \1153 *(u64*)(r10 - 8) = r1; \1154 r2 = r10; \1155 r2 += -8; \1156 r1 = %[map_array_48b] ll; \1157 call %[bpf_map_lookup_elem]; \1158 if r0 == 0 goto l0_%=; \1159 r0 += r0; \1160 r1 = *(u8*)(r0 + 0); \1161l0_%=: r0 = 1; \1162 exit; \1163" :1164 : __imm(bpf_map_lookup_elem),1165 __imm_addr(map_array_48b)1166 : __clobber_all);1167}1168 1169SEC("socket")1170__description("map access: known scalar -= value_ptr")1171__failure __msg("R1 tried to subtract pointer from scalar")1172__failure_unpriv1173__naked void access_known_scalar_value_ptr_2(void)1174{1175 asm volatile (" \1176 r1 = 0; \1177 *(u64*)(r10 - 8) = r1; \1178 r2 = r10; \1179 r2 += -8; \1180 r1 = %[map_array_48b] ll; \1181 call %[bpf_map_lookup_elem]; \1182 if r0 == 0 goto l0_%=; \1183 r1 = 4; \1184 r1 -= r0; \1185 r0 = *(u8*)(r1 + 0); \1186l0_%=: r0 = 1; \1187 exit; \1188" :1189 : __imm(bpf_map_lookup_elem),1190 __imm_addr(map_array_48b)1191 : __clobber_all);1192}1193 1194SEC("socket")1195__description("map access: value_ptr -= known scalar")1196__failure __msg("R0 min value is outside of the allowed memory range")1197__failure_unpriv1198__naked void access_value_ptr_known_scalar(void)1199{1200 asm volatile (" \1201 r1 = 0; \1202 *(u64*)(r10 - 8) = r1; \1203 r2 = r10; \1204 r2 += -8; \1205 r1 = %[map_array_48b] ll; \1206 call %[bpf_map_lookup_elem]; \1207 if r0 == 0 goto l0_%=; \1208 r1 = 4; \1209 r0 -= r1; \1210 r1 = *(u8*)(r0 + 0); \1211l0_%=: r0 = 1; \1212 exit; \1213" :1214 : __imm(bpf_map_lookup_elem),1215 __imm_addr(map_array_48b)1216 : __clobber_all);1217}1218 1219SEC("socket")1220__description("map access: value_ptr -= known scalar, 2")1221__success __success_unpriv __retval(1)1222__naked void value_ptr_known_scalar_2_2(void)1223{1224 asm volatile (" \1225 r1 = 0; \1226 *(u64*)(r10 - 8) = r1; \1227 r2 = r10; \1228 r2 += -8; \1229 r1 = %[map_array_48b] ll; \1230 call %[bpf_map_lookup_elem]; \1231 if r0 == 0 goto l0_%=; \1232 r1 = 6; \1233 r2 = 4; \1234 r0 += r1; \1235 r0 -= r2; \1236 r1 = *(u8*)(r0 + 0); \1237l0_%=: r0 = 1; \1238 exit; \1239" :1240 : __imm(bpf_map_lookup_elem),1241 __imm_addr(map_array_48b)1242 : __clobber_all);1243}1244 1245SEC("socket")1246__description("map access: unknown scalar -= value_ptr")1247__failure __msg("R1 tried to subtract pointer from scalar")1248__failure_unpriv1249__naked void access_unknown_scalar_value_ptr(void)1250{1251 asm volatile (" \1252 r1 = 0; \1253 *(u64*)(r10 - 8) = r1; \1254 r2 = r10; \1255 r2 += -8; \1256 r1 = %[map_array_48b] ll; \1257 call %[bpf_map_lookup_elem]; \1258 if r0 == 0 goto l0_%=; \1259 r1 = *(u8*)(r0 + 0); \1260 r1 &= 0xf; \1261 r1 -= r0; \1262 r0 = *(u8*)(r1 + 0); \1263l0_%=: r0 = 1; \1264 exit; \1265" :1266 : __imm(bpf_map_lookup_elem),1267 __imm_addr(map_array_48b)1268 : __clobber_all);1269}1270 1271SEC("socket")1272__description("map access: value_ptr -= unknown scalar")1273__failure __msg("R0 min value is negative")1274__failure_unpriv1275__naked void access_value_ptr_unknown_scalar(void)1276{1277 asm volatile (" \1278 r1 = 0; \1279 *(u64*)(r10 - 8) = r1; \1280 r2 = r10; \1281 r2 += -8; \1282 r1 = %[map_array_48b] ll; \1283 call %[bpf_map_lookup_elem]; \1284 if r0 == 0 goto l0_%=; \1285 r1 = *(u8*)(r0 + 0); \1286 r1 &= 0xf; \1287 r0 -= r1; \1288 r1 = *(u8*)(r0 + 0); \1289l0_%=: r0 = 1; \1290 exit; \1291" :1292 : __imm(bpf_map_lookup_elem),1293 __imm_addr(map_array_48b)1294 : __clobber_all);1295}1296 1297SEC("socket")1298__description("map access: value_ptr -= unknown scalar, 2")1299__success __failure_unpriv1300__msg_unpriv("R0 pointer arithmetic of map value goes out of range")1301__retval(1)1302__naked void value_ptr_unknown_scalar_2_2(void)1303{1304 asm volatile (" \1305 r1 = 0; \1306 *(u64*)(r10 - 8) = r1; \1307 r2 = r10; \1308 r2 += -8; \1309 r1 = %[map_array_48b] ll; \1310 call %[bpf_map_lookup_elem]; \1311 if r0 == 0 goto l0_%=; \1312 r1 = *(u8*)(r0 + 0); \1313 r1 &= 0xf; \1314 r1 |= 0x7; \1315 r0 += r1; \1316 r1 = *(u8*)(r0 + 0); \1317 r1 &= 0x7; \1318 r0 -= r1; \1319 r1 = *(u8*)(r0 + 0); \1320l0_%=: r0 = 1; \1321 exit; \1322" :1323 : __imm(bpf_map_lookup_elem),1324 __imm_addr(map_array_48b)1325 : __clobber_all);1326}1327 1328SEC("socket")1329__description("map access: value_ptr -= value_ptr")1330__failure __msg("R0 invalid mem access 'scalar'")1331__msg_unpriv("R0 pointer -= pointer prohibited")1332__naked void access_value_ptr_value_ptr_2(void)1333{1334 asm volatile (" \1335 r1 = 0; \1336 *(u64*)(r10 - 8) = r1; \1337 r2 = r10; \1338 r2 += -8; \1339 r1 = %[map_array_48b] ll; \1340 call %[bpf_map_lookup_elem]; \1341 if r0 == 0 goto l0_%=; \1342 r0 -= r0; \1343 r1 = *(u8*)(r0 + 0); \1344l0_%=: r0 = 1; \1345 exit; \1346" :1347 : __imm(bpf_map_lookup_elem),1348 __imm_addr(map_array_48b)1349 : __clobber_all);1350}1351 1352SEC("socket")1353__description("map access: trying to leak tainted dst reg")1354__failure __msg("math between map_value pointer and 4294967295 is not allowed")1355__failure_unpriv1356__naked void to_leak_tainted_dst_reg(void)1357{1358 asm volatile (" \1359 r0 = 0; \1360 r1 = 0; \1361 *(u64*)(r10 - 8) = r1; \1362 r2 = r10; \1363 r2 += -8; \1364 r1 = %[map_array_48b] ll; \1365 call %[bpf_map_lookup_elem]; \1366 if r0 != 0 goto l0_%=; \1367 exit; \1368l0_%=: r2 = r0; \1369 w1 = 0xFFFFFFFF; \1370 w1 = w1; \1371 r2 -= r1; \1372 *(u64*)(r0 + 0) = r2; \1373 r0 = 0; \1374 exit; \1375" :1376 : __imm(bpf_map_lookup_elem),1377 __imm_addr(map_array_48b)1378 : __clobber_all);1379}1380 1381SEC("tc")1382__description("32bit pkt_ptr -= scalar")1383__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)1384__naked void _32bit_pkt_ptr_scalar(void)1385{1386 asm volatile (" \1387 r8 = *(u32*)(r1 + %[__sk_buff_data_end]); \1388 r7 = *(u32*)(r1 + %[__sk_buff_data]); \1389 r6 = r7; \1390 r6 += 40; \1391 if r6 > r8 goto l0_%=; \1392 w4 = w7; \1393 w6 -= w4; \1394l0_%=: r0 = 0; \1395 exit; \1396" :1397 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),1398 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))1399 : __clobber_all);1400}1401 1402SEC("tc")1403__description("32bit scalar -= pkt_ptr")1404__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)1405__naked void _32bit_scalar_pkt_ptr(void)1406{1407 asm volatile (" \1408 r8 = *(u32*)(r1 + %[__sk_buff_data_end]); \1409 r7 = *(u32*)(r1 + %[__sk_buff_data]); \1410 r6 = r7; \1411 r6 += 40; \1412 if r6 > r8 goto l0_%=; \1413 w4 = w6; \1414 w4 -= w7; \1415l0_%=: r0 = 0; \1416 exit; \1417" :1418 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),1419 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))1420 : __clobber_all);1421}1422 1423char _license[] SEC("license") = "GPL";1424