1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/value_or_null.c */
5 #include <bpf/bpf_helpers.h>
16 __uint(type, BPF_MAP_TYPE_HASH);
17 __uint(max_entries, 1);
18 __type(key, long long);
19 __type(value, struct test_val);
20 } map_hash_48b SEC(".maps");
23 __uint(type, BPF_MAP_TYPE_HASH);
24 __uint(max_entries, 1);
25 __type(key, long long);
26 __type(value, long long);
27 } map_hash_8b SEC(".maps");
30 __description("multiple registers share map_lookup_elem result")
32 __naked void share_map_lookup_elem_result(void)
36 *(u64*)(r10 - 8) = r1; \
39 r1 = %[map_hash_8b] ll; \
40 call %[bpf_map_lookup_elem]; \
42 if r0 == 0 goto l0_%=; \
44 *(u64*)(r4 + 0) = r1; \
47 : __imm(bpf_map_lookup_elem),
48 __imm_addr(map_hash_8b)
53 __description("alu ops on ptr_to_map_value_or_null, 1")
54 __failure __msg("R4 pointer arithmetic on map_value_or_null")
55 __naked void map_value_or_null_1(void)
59 *(u64*)(r10 - 8) = r1; \
62 r1 = %[map_hash_8b] ll; \
63 call %[bpf_map_lookup_elem]; \
67 if r0 == 0 goto l0_%=; \
69 *(u64*)(r4 + 0) = r1; \
72 : __imm(bpf_map_lookup_elem),
73 __imm_addr(map_hash_8b)
78 __description("alu ops on ptr_to_map_value_or_null, 2")
79 __failure __msg("R4 pointer arithmetic on map_value_or_null")
80 __naked void map_value_or_null_2(void)
84 *(u64*)(r10 - 8) = r1; \
87 r1 = %[map_hash_8b] ll; \
88 call %[bpf_map_lookup_elem]; \
91 if r0 == 0 goto l0_%=; \
93 *(u64*)(r4 + 0) = r1; \
96 : __imm(bpf_map_lookup_elem),
97 __imm_addr(map_hash_8b)
102 __description("alu ops on ptr_to_map_value_or_null, 3")
103 __failure __msg("R4 pointer arithmetic on map_value_or_null")
104 __naked void map_value_or_null_3(void)
108 *(u64*)(r10 - 8) = r1; \
111 r1 = %[map_hash_8b] ll; \
112 call %[bpf_map_lookup_elem]; \
115 if r0 == 0 goto l0_%=; \
117 *(u64*)(r4 + 0) = r1; \
120 : __imm(bpf_map_lookup_elem),
121 __imm_addr(map_hash_8b)
126 __description("invalid memory access with multiple map_lookup_elem calls")
127 __failure __msg("R4 !read_ok")
128 __naked void multiple_map_lookup_elem_calls(void)
132 *(u64*)(r10 - 8) = r1; \
135 r1 = %[map_hash_8b] ll; \
138 call %[bpf_map_lookup_elem]; \
142 call %[bpf_map_lookup_elem]; \
143 if r0 == 0 goto l0_%=; \
145 *(u64*)(r4 + 0) = r1; \
148 : __imm(bpf_map_lookup_elem),
149 __imm_addr(map_hash_8b)
154 __description("valid indirect map_lookup_elem access with 2nd lookup in branch")
155 __success __retval(0)
156 __naked void with_2nd_lookup_in_branch(void)
160 *(u64*)(r10 - 8) = r1; \
163 r1 = %[map_hash_8b] ll; \
166 call %[bpf_map_lookup_elem]; \
168 if r2 != 0 goto l0_%=; \
171 call %[bpf_map_lookup_elem]; \
173 if r0 == 0 goto l1_%=; \
175 *(u64*)(r4 + 0) = r1; \
178 : __imm(bpf_map_lookup_elem),
179 __imm_addr(map_hash_8b)
184 __description("invalid map access from else condition")
185 __failure __msg("R0 unbounded memory access")
186 __failure_unpriv __msg_unpriv("R0 leaks addr")
187 __flag(BPF_F_ANY_ALIGNMENT)
188 __naked void map_access_from_else_condition(void)
192 *(u64*)(r10 - 8) = r1; \
195 r1 = %[map_hash_48b] ll; \
196 call %[bpf_map_lookup_elem]; \
197 if r0 == 0 goto l0_%=; \
198 r1 = *(u32*)(r0 + 0); \
199 if r1 >= %[__imm_0] goto l1_%=; \
203 r1 = %[test_val_foo]; \
204 *(u64*)(r0 + 0) = r1; \
207 : __imm(bpf_map_lookup_elem),
208 __imm_addr(map_hash_48b),
209 __imm_const(__imm_0, MAX_ENTRIES-1),
210 __imm_const(test_val_foo, offsetof(struct test_val, foo))
215 __description("map lookup and null branch prediction")
216 __success __retval(0)
217 __naked void lookup_and_null_branch_prediction(void)
221 *(u64*)(r10 - 8) = r1; \
224 r1 = %[map_hash_8b] ll; \
225 call %[bpf_map_lookup_elem]; \
227 if r6 == 0 goto l0_%=; \
228 if r6 != 0 goto l0_%=; \
232 : __imm(bpf_map_lookup_elem),
233 __imm_addr(map_hash_8b)
238 __description("MAP_VALUE_OR_NULL check_ids() in regsafe()")
239 __failure __msg("R8 invalid mem access 'map_value_or_null'")
240 __failure_unpriv __msg_unpriv("")
241 __flag(BPF_F_TEST_STATE_FREQ)
242 __naked void null_check_ids_in_regsafe(void)
246 *(u64*)(r10 - 8) = r1; \
247 /* r9 = map_lookup_elem(...) */ \
250 r1 = %[map_hash_8b] ll; \
251 call %[bpf_map_lookup_elem]; \
253 /* r8 = map_lookup_elem(...) */ \
256 r1 = %[map_hash_8b] ll; \
257 call %[bpf_map_lookup_elem]; \
259 /* r7 = ktime_get_ns() */ \
260 call %[bpf_ktime_get_ns]; \
262 /* r6 = ktime_get_ns() */ \
263 call %[bpf_ktime_get_ns]; \
265 /* if r6 > r7 goto +1 ; no new information about the state is derived from\
266 * ; this check, thus produced verifier states differ\
267 * ; only in 'insn_idx' \
268 * r9 = r8 ; optionally share ID between r9 and r8\
270 if r6 > r7 goto l0_%=; \
272 l0_%=: /* if r9 == 0 goto <exit> */ \
273 if r9 == 0 goto l1_%=; \
274 /* read map value via r8, this is not always \
275 * safe because r8 might be not equal to r9. \
277 r0 = *(u64*)(r8 + 0); \
278 l1_%=: /* exit 0 */ \
282 : __imm(bpf_ktime_get_ns),
283 __imm(bpf_map_lookup_elem),
284 __imm_addr(map_hash_8b)
288 char _license[] SEC("license") = "GPL";