18b08807dSDmitrii Banshchikov // SPDX-License-Identifier: GPL-2.0-only 28b08807dSDmitrii Banshchikov #include <stddef.h> 38b08807dSDmitrii Banshchikov #include <linux/bpf.h> 48b08807dSDmitrii Banshchikov #include <bpf/bpf_helpers.h> 595ebb376SAndrii Nakryiko #include "bpf_misc.h" 68b08807dSDmitrii Banshchikov foo(unsigned int * v)78b08807dSDmitrii Banshchikov__noinline int foo(unsigned int *v) 88b08807dSDmitrii Banshchikov { 98b08807dSDmitrii Banshchikov if (v) 108b08807dSDmitrii Banshchikov *v = bpf_get_prandom_u32(); 118b08807dSDmitrii Banshchikov 128b08807dSDmitrii Banshchikov return 0; 138b08807dSDmitrii Banshchikov } 148b08807dSDmitrii Banshchikov 158b08807dSDmitrii Banshchikov SEC("cgroup_skb/ingress") 16c871d0e0SAndrii Nakryiko __failure __msg("At program exit the register R0 has ") global_func15(struct __sk_buff * skb)1795ebb376SAndrii Nakryikoint global_func15(struct __sk_buff *skb) 188b08807dSDmitrii Banshchikov { 198b08807dSDmitrii Banshchikov unsigned int v = 1; 208b08807dSDmitrii Banshchikov 218b08807dSDmitrii Banshchikov foo(&v); 228b08807dSDmitrii Banshchikov 238b08807dSDmitrii Banshchikov return v; 248b08807dSDmitrii Banshchikov } 25*5c19e1d0SAndrii Nakryiko 26*5c19e1d0SAndrii Nakryiko SEC("cgroup_skb/ingress") __flag(BPF_F_TEST_STATE_FREQ)27*5c19e1d0SAndrii Nakryiko__log_level(2) __flag(BPF_F_TEST_STATE_FREQ) 28*5c19e1d0SAndrii Nakryiko __failure 29*5c19e1d0SAndrii Nakryiko /* check that fallthrough code path marks r0 as precise */ 30*5c19e1d0SAndrii Nakryiko __msg("mark_precise: frame0: regs=r0 stack= before 2: (b7) r0 = 1") 31*5c19e1d0SAndrii Nakryiko /* check that branch code path marks r0 as precise */ 32*5c19e1d0SAndrii Nakryiko __msg("mark_precise: frame0: regs=r0 stack= before 0: (85) call bpf_get_prandom_u32#7") 33*5c19e1d0SAndrii Nakryiko __msg("At program exit the register R0 has ") 34*5c19e1d0SAndrii Nakryiko __naked int global_func15_tricky_pruning(void) 35*5c19e1d0SAndrii Nakryiko { 36*5c19e1d0SAndrii Nakryiko asm volatile ( 37*5c19e1d0SAndrii Nakryiko "call %[bpf_get_prandom_u32];" 38*5c19e1d0SAndrii Nakryiko "if r0 s> 1000 goto 1f;" 39*5c19e1d0SAndrii Nakryiko "r0 = 1;" 40*5c19e1d0SAndrii Nakryiko "1:" 41*5c19e1d0SAndrii Nakryiko "goto +0;" /* checkpoint */ 42*5c19e1d0SAndrii Nakryiko /* cgroup_skb/ingress program is expected to return [0, 1] 43*5c19e1d0SAndrii Nakryiko * values, so branch above makes sure that in a fallthrough 44*5c19e1d0SAndrii Nakryiko * case we have a valid 1 stored in R0 register, but in 45*5c19e1d0SAndrii Nakryiko * a branch case we assign some random value to R0. So if 46*5c19e1d0SAndrii Nakryiko * there is something wrong with precision tracking for R0 at 47*5c19e1d0SAndrii Nakryiko * program exit, we might erroneously prune branch case, 48*5c19e1d0SAndrii Nakryiko * because R0 in fallthrough case is imprecise (and thus any 49*5c19e1d0SAndrii Nakryiko * value is valid from POV of verifier is_state_equal() logic) 50*5c19e1d0SAndrii Nakryiko */ 51*5c19e1d0SAndrii Nakryiko "exit;" 52*5c19e1d0SAndrii Nakryiko : 53*5c19e1d0SAndrii Nakryiko : __imm(bpf_get_prandom_u32) 54*5c19e1d0SAndrii Nakryiko : __clobber_common 55*5c19e1d0SAndrii Nakryiko ); 56*5c19e1d0SAndrii Nakryiko } 57