485 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Converted from tools/testing/selftests/bpf/verifier/stack_ptr.c */3 4#include <linux/bpf.h>5#include <bpf/bpf_helpers.h>6#include <limits.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 23SEC("socket")24__description("PTR_TO_STACK store/load")25__success __success_unpriv __retval(0xfaceb00c)26__naked void ptr_to_stack_store_load(void)27{28 asm volatile (" \29 r1 = r10; \30 r1 += -10; \31 r0 = 0xfaceb00c; \32 *(u64*)(r1 + 2) = r0; \33 r0 = *(u64*)(r1 + 2); \34 exit; \35" ::: __clobber_all);36}37 38SEC("socket")39__description("PTR_TO_STACK store/load - bad alignment on off")40__failure __msg("misaligned stack access off 0+-8+2 size 8")41__failure_unpriv42__naked void load_bad_alignment_on_off(void)43{44 asm volatile (" \45 r1 = r10; \46 r1 += -8; \47 r0 = 0xfaceb00c; \48 *(u64*)(r1 + 2) = r0; \49 r0 = *(u64*)(r1 + 2); \50 exit; \51" ::: __clobber_all);52}53 54SEC("socket")55__description("PTR_TO_STACK store/load - bad alignment on reg")56__failure __msg("misaligned stack access off 0+-10+8 size 8")57__failure_unpriv58__naked void load_bad_alignment_on_reg(void)59{60 asm volatile (" \61 r1 = r10; \62 r1 += -10; \63 r0 = 0xfaceb00c; \64 *(u64*)(r1 + 8) = r0; \65 r0 = *(u64*)(r1 + 8); \66 exit; \67" ::: __clobber_all);68}69 70SEC("socket")71__description("PTR_TO_STACK store/load - out of bounds low")72__failure __msg("invalid write to stack R1 off=-79992 size=8")73__msg_unpriv("R1 stack pointer arithmetic goes out of range")74__naked void load_out_of_bounds_low(void)75{76 asm volatile (" \77 r1 = r10; \78 r1 += -80000; \79 r0 = 0xfaceb00c; \80 *(u64*)(r1 + 8) = r0; \81 r0 = *(u64*)(r1 + 8); \82 exit; \83" ::: __clobber_all);84}85 86SEC("socket")87__description("PTR_TO_STACK store/load - out of bounds high")88__failure __msg("invalid write to stack R1 off=0 size=8")89__failure_unpriv90__naked void load_out_of_bounds_high(void)91{92 asm volatile (" \93 r1 = r10; \94 r1 += -8; \95 r0 = 0xfaceb00c; \96 *(u64*)(r1 + 8) = r0; \97 r0 = *(u64*)(r1 + 8); \98 exit; \99" ::: __clobber_all);100}101 102SEC("socket")103__description("PTR_TO_STACK check high 1")104__success __success_unpriv __retval(42)105__naked void to_stack_check_high_1(void)106{107 asm volatile (" \108 r1 = r10; \109 r1 += -1; \110 r0 = 42; \111 *(u8*)(r1 + 0) = r0; \112 r0 = *(u8*)(r1 + 0); \113 exit; \114" ::: __clobber_all);115}116 117SEC("socket")118__description("PTR_TO_STACK check high 2")119__success __success_unpriv __retval(42)120__naked void to_stack_check_high_2(void)121{122 asm volatile (" \123 r1 = r10; \124 r0 = 42; \125 *(u8*)(r1 - 1) = r0; \126 r0 = *(u8*)(r1 - 1); \127 exit; \128" ::: __clobber_all);129}130 131SEC("socket")132__description("PTR_TO_STACK check high 3")133__success __failure_unpriv134__msg_unpriv("R1 stack pointer arithmetic goes out of range")135__retval(42)136__naked void to_stack_check_high_3(void)137{138 asm volatile (" \139 r1 = r10; \140 r1 += 0; \141 r0 = 42; \142 *(u8*)(r1 - 1) = r0; \143 r0 = *(u8*)(r1 - 1); \144 exit; \145" ::: __clobber_all);146}147 148SEC("socket")149__description("PTR_TO_STACK check high 4")150__failure __msg("invalid write to stack R1 off=0 size=1")151__msg_unpriv("R1 stack pointer arithmetic goes out of range")152__naked void to_stack_check_high_4(void)153{154 asm volatile (" \155 r1 = r10; \156 r1 += 0; \157 r0 = 42; \158 *(u8*)(r1 + 0) = r0; \159 r0 = *(u8*)(r1 + 0); \160 exit; \161" ::: __clobber_all);162}163 164SEC("socket")165__description("PTR_TO_STACK check high 5")166__failure __msg("invalid write to stack R1")167__msg_unpriv("R1 stack pointer arithmetic goes out of range")168__naked void to_stack_check_high_5(void)169{170 asm volatile (" \171 r1 = r10; \172 r1 += %[__imm_0]; \173 r0 = 42; \174 *(u8*)(r1 + 0) = r0; \175 r0 = *(u8*)(r1 + 0); \176 exit; \177" :178 : __imm_const(__imm_0, (1 << 29) - 1)179 : __clobber_all);180}181 182SEC("socket")183__description("PTR_TO_STACK check high 6")184__failure __msg("invalid write to stack")185__msg_unpriv("R1 stack pointer arithmetic goes out of range")186__naked void to_stack_check_high_6(void)187{188 asm volatile (" \189 r1 = r10; \190 r1 += %[__imm_0]; \191 r0 = 42; \192 *(u8*)(r1 + %[shrt_max]) = r0; \193 r0 = *(u8*)(r1 + %[shrt_max]); \194 exit; \195" :196 : __imm_const(__imm_0, (1 << 29) - 1),197 __imm_const(shrt_max, SHRT_MAX)198 : __clobber_all);199}200 201SEC("socket")202__description("PTR_TO_STACK check high 7")203__failure __msg("fp pointer offset")204__msg_unpriv("R1 stack pointer arithmetic goes out of range")205__naked void to_stack_check_high_7(void)206{207 asm volatile (" \208 r1 = r10; \209 r1 += %[__imm_0]; \210 r1 += %[__imm_0]; \211 r0 = 42; \212 *(u8*)(r1 + %[shrt_max]) = r0; \213 r0 = *(u8*)(r1 + %[shrt_max]); \214 exit; \215" :216 : __imm_const(__imm_0, (1 << 29) - 1),217 __imm_const(shrt_max, SHRT_MAX)218 : __clobber_all);219}220 221SEC("socket")222__description("PTR_TO_STACK check low 1")223__success __success_unpriv __retval(42)224__naked void to_stack_check_low_1(void)225{226 asm volatile (" \227 r1 = r10; \228 r1 += -512; \229 r0 = 42; \230 *(u8*)(r1 + 0) = r0; \231 r0 = *(u8*)(r1 + 0); \232 exit; \233" ::: __clobber_all);234}235 236SEC("socket")237__description("PTR_TO_STACK check low 2")238__success __failure_unpriv239__msg_unpriv("R1 stack pointer arithmetic goes out of range")240__retval(42)241__naked void to_stack_check_low_2(void)242{243 asm volatile (" \244 r1 = r10; \245 r1 += -513; \246 r0 = 42; \247 *(u8*)(r1 + 1) = r0; \248 r0 = *(u8*)(r1 + 1); \249 exit; \250" ::: __clobber_all);251}252 253SEC("socket")254__description("PTR_TO_STACK check low 3")255__failure __msg("invalid write to stack R1 off=-513 size=1")256__msg_unpriv("R1 stack pointer arithmetic goes out of range")257__naked void to_stack_check_low_3(void)258{259 asm volatile (" \260 r1 = r10; \261 r1 += -513; \262 r0 = 42; \263 *(u8*)(r1 + 0) = r0; \264 r0 = *(u8*)(r1 + 0); \265 exit; \266" ::: __clobber_all);267}268 269SEC("socket")270__description("PTR_TO_STACK check low 4")271__failure __msg("math between fp pointer")272__failure_unpriv273__naked void to_stack_check_low_4(void)274{275 asm volatile (" \276 r1 = r10; \277 r1 += %[int_min]; \278 r0 = 42; \279 *(u8*)(r1 + 0) = r0; \280 r0 = *(u8*)(r1 + 0); \281 exit; \282" :283 : __imm_const(int_min, INT_MIN)284 : __clobber_all);285}286 287SEC("socket")288__description("PTR_TO_STACK check low 5")289__failure __msg("invalid write to stack")290__msg_unpriv("R1 stack pointer arithmetic goes out of range")291__naked void to_stack_check_low_5(void)292{293 asm volatile (" \294 r1 = r10; \295 r1 += %[__imm_0]; \296 r0 = 42; \297 *(u8*)(r1 + 0) = r0; \298 r0 = *(u8*)(r1 + 0); \299 exit; \300" :301 : __imm_const(__imm_0, -((1 << 29) - 1))302 : __clobber_all);303}304 305SEC("socket")306__description("PTR_TO_STACK check low 6")307__failure __msg("invalid write to stack")308__msg_unpriv("R1 stack pointer arithmetic goes out of range")309__naked void to_stack_check_low_6(void)310{311 asm volatile (" \312 r1 = r10; \313 r1 += %[__imm_0]; \314 r0 = 42; \315 *(u8*)(r1 %[shrt_min]) = r0; \316 r0 = *(u8*)(r1 %[shrt_min]); \317 exit; \318" :319 : __imm_const(__imm_0, -((1 << 29) - 1)),320 __imm_const(shrt_min, SHRT_MIN)321 : __clobber_all);322}323 324SEC("socket")325__description("PTR_TO_STACK check low 7")326__failure __msg("fp pointer offset")327__msg_unpriv("R1 stack pointer arithmetic goes out of range")328__naked void to_stack_check_low_7(void)329{330 asm volatile (" \331 r1 = r10; \332 r1 += %[__imm_0]; \333 r1 += %[__imm_0]; \334 r0 = 42; \335 *(u8*)(r1 %[shrt_min]) = r0; \336 r0 = *(u8*)(r1 %[shrt_min]); \337 exit; \338" :339 : __imm_const(__imm_0, -((1 << 29) - 1)),340 __imm_const(shrt_min, SHRT_MIN)341 : __clobber_all);342}343 344SEC("socket")345__description("PTR_TO_STACK mixed reg/k, 1")346__success __success_unpriv __retval(42)347__naked void stack_mixed_reg_k_1(void)348{349 asm volatile (" \350 r1 = r10; \351 r1 += -3; \352 r2 = -3; \353 r1 += r2; \354 r0 = 42; \355 *(u8*)(r1 + 0) = r0; \356 r0 = *(u8*)(r1 + 0); \357 exit; \358" ::: __clobber_all);359}360 361SEC("socket")362__description("PTR_TO_STACK mixed reg/k, 2")363__success __success_unpriv __retval(42)364__naked void stack_mixed_reg_k_2(void)365{366 asm volatile (" \367 r0 = 0; \368 *(u64*)(r10 - 8) = r0; \369 r0 = 0; \370 *(u64*)(r10 - 16) = r0; \371 r1 = r10; \372 r1 += -3; \373 r2 = -3; \374 r1 += r2; \375 r0 = 42; \376 *(u8*)(r1 + 0) = r0; \377 r5 = r10; \378 r0 = *(u8*)(r5 - 6); \379 exit; \380" ::: __clobber_all);381}382 383SEC("socket")384__description("PTR_TO_STACK mixed reg/k, 3")385__success __success_unpriv __retval(-3)386__naked void stack_mixed_reg_k_3(void)387{388 asm volatile (" \389 r1 = r10; \390 r1 += -3; \391 r2 = -3; \392 r1 += r2; \393 r0 = 42; \394 *(u8*)(r1 + 0) = r0; \395 r0 = r2; \396 exit; \397" ::: __clobber_all);398}399 400SEC("socket")401__description("PTR_TO_STACK reg")402__success __success_unpriv __retval(42)403__naked void ptr_to_stack_reg(void)404{405 asm volatile (" \406 r1 = r10; \407 r2 = -3; \408 r1 += r2; \409 r0 = 42; \410 *(u8*)(r1 + 0) = r0; \411 r0 = *(u8*)(r1 + 0); \412 exit; \413" ::: __clobber_all);414}415 416SEC("socket")417__description("stack pointer arithmetic")418__success __success_unpriv __retval(0)419__naked void stack_pointer_arithmetic(void)420{421 asm volatile (" \422 r1 = 4; \423 goto l0_%=; \424l0_%=: r7 = r10; \425 r7 += -10; \426 r7 += -10; \427 r2 = r7; \428 r2 += r1; \429 r0 = 0; \430 *(u32*)(r2 + 4) = r0; \431 r2 = r7; \432 r2 += 8; \433 r0 = 0; \434 *(u32*)(r2 + 4) = r0; \435 r0 = 0; \436 exit; \437" ::: __clobber_all);438}439 440SEC("tc")441__description("store PTR_TO_STACK in R10 to array map using BPF_B")442__success __retval(42)443__naked void array_map_using_bpf_b(void)444{445 asm volatile (" \446 /* Load pointer to map. */ \447 r2 = r10; \448 r2 += -8; \449 r1 = 0; \450 *(u64*)(r2 + 0) = r1; \451 r1 = %[map_array_48b] ll; \452 call %[bpf_map_lookup_elem]; \453 if r0 != 0 goto l0_%=; \454 r0 = 2; \455 exit; \456l0_%=: r1 = r0; \457 /* Copy R10 to R9. */ \458 r9 = r10; \459 /* Pollute other registers with unaligned values. */\460 r2 = -1; \461 r3 = -1; \462 r4 = -1; \463 r5 = -1; \464 r6 = -1; \465 r7 = -1; \466 r8 = -1; \467 /* Store both R9 and R10 with BPF_B and read back. */\468 *(u8*)(r1 + 0) = r10; \469 r2 = *(u8*)(r1 + 0); \470 *(u8*)(r1 + 0) = r9; \471 r3 = *(u8*)(r1 + 0); \472 /* Should read back as same value. */ \473 if r2 == r3 goto l1_%=; \474 r0 = 1; \475 exit; \476l1_%=: r0 = 42; \477 exit; \478" :479 : __imm(bpf_map_lookup_elem),480 __imm_addr(map_array_48b)481 : __clobber_all);482}483 484char _license[] SEC("license") = "GPL";485