1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | #include <stddef.h> |
3 | #include <linux/bpf.h> |
4 | #include <bpf/bpf_helpers.h> |
5 | #include "bpf_misc.h" |
6 | |
7 | __noinline int foo(unsigned int *v) |
8 | { |
9 | if (v) |
10 | *v = bpf_get_prandom_u32(); |
11 | |
12 | return 0; |
13 | } |
14 | |
15 | SEC("cgroup_skb/ingress" ) |
16 | __failure __msg("At program exit the register R0 has " ) |
17 | int global_func15(struct __sk_buff *skb) |
18 | { |
19 | unsigned int v = 1; |
20 | |
21 | foo(&v); |
22 | |
23 | return v; |
24 | } |
25 | |
26 | SEC("cgroup_skb/ingress" ) |
27 | __log_level(2) __flag(BPF_F_TEST_STATE_FREQ) |
28 | __failure |
29 | /* check that fallthrough code path marks r0 as precise */ |
30 | __msg("mark_precise: frame0: regs=r0 stack= before 2: (b7) r0 = 1" ) |
31 | /* check that branch code path marks r0 as precise */ |
32 | __msg("mark_precise: frame0: regs=r0 stack= before 0: (85) call bpf_get_prandom_u32#7" ) |
33 | __msg("At program exit the register R0 has " ) |
34 | __naked int global_func15_tricky_pruning(void) |
35 | { |
36 | asm volatile ( |
37 | "call %[bpf_get_prandom_u32];" |
38 | "if r0 s> 1000 goto 1f;" |
39 | "r0 = 1;" |
40 | "1:" |
41 | "goto +0;" /* checkpoint */ |
42 | /* cgroup_skb/ingress program is expected to return [0, 1] |
43 | * values, so branch above makes sure that in a fallthrough |
44 | * case we have a valid 1 stored in R0 register, but in |
45 | * a branch case we assign some random value to R0. So if |
46 | * there is something wrong with precision tracking for R0 at |
47 | * program exit, we might erronenously prune branch case, |
48 | * because R0 in fallthrough case is imprecise (and thus any |
49 | * value is valid from POV of verifier is_state_equal() logic) |
50 | */ |
51 | "exit;" |
52 | : |
53 | : __imm(bpf_get_prandom_u32) |
54 | : __clobber_common |
55 | ); |
56 | } |
57 | |