diff options
| author | Eduard Zingerman <eddyz87@gmail.com> | 2026-10-09 03:48:01 -0700 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-10-09 20:29:14 +0000 |
| commit | e60fb9b6b5beabe9f5cd7475768b04b5abe4d37f (patch) | |
| tree | 51fbccce1cd45e3ced8a89a45b815c88691500a2 /tools | |
| parent | 75a46f59e0985dd53fe7d5b2c4f42fd5e44ff144 (diff) | |
selftests/bpf: Tests for map special cases in bpf_helper_stack_access_bytes()
Tests for helper arguments whose access size or read/write effects
depend on the map:
- helper_map_output_known_size checks that for a known map access
MEM_WRITE | MEM_UNINIT produces a must_write mark.
- helper_map_output_merged_sizes checks that when maps with different
value sizes merge, MEM_WRITE | MEM_UNINIT produces use and may_def
marks over the maximum value size, without a def mark.
- helper_bloom_peek_input checks that for bpf_map_peek_elem()
on a bloom filter the buffer is treated as an input.
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-43-bcba9bc53ac9@gmail.com
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/testing/selftests/bpf/progs/verifier_live_stack.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/progs/verifier_live_stack.c b/tools/testing/selftests/bpf/progs/verifier_live_stack.c index ae4c5062cfa6..0fbc43a5d4f4 100644 --- a/tools/testing/selftests/bpf/progs/verifier_live_stack.c +++ b/tools/testing/selftests/bpf/progs/verifier_live_stack.c @@ -3262,3 +3262,79 @@ __naked void helper_output_unknown_size(void) :: __imm(bpf_get_prandom_u32), __imm(bpf_probe_read_kernel) : __clobber_all); } + +struct { + __uint(type, BPF_MAP_TYPE_QUEUE); + __uint(max_entries, 1); + __type(value, __u64); +} queue_8b SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_QUEUE); + __uint(max_entries, 1); + __type(value, __u64[2]); +} queue_16b SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_BLOOM_FILTER); + __uint(max_entries, 16); + __type(value, __u64); +} bloom_8b SEC(".maps"); + +SEC("socket") +__success __log_level(2) +__msg("call bpf_map_pop_elem{{.*}}; def: fp0-16") +__naked void helper_map_output_known_size(void) +{ + asm volatile ( + "r1 = %[queue_8b] ll;" + "r2 = r10;" + "r2 += -16;" + "call %[bpf_map_pop_elem];" + "r0 = 0;" + "exit;" + :: __imm_addr(queue_8b), __imm(bpf_map_pop_elem) + : __clobber_all); +} + +/* The maximum map value size is not a guaranteed output extent. */ +SEC("socket") +__success __log_level(2) +__msg("call bpf_map_pop_elem{{.*}}; use: fp0-16 fp0-24 may_def: fp0-16 fp0-24{{$}}") +__naked void helper_map_output_merged_sizes(void) +{ + asm volatile ( + "*(u64 *)(r10 - 16) = 0;" + "*(u64 *)(r10 - 24) = 0;" + "call %[bpf_get_prandom_u32];" + "r1 = %[queue_8b] ll;" + "if r0 == 0 goto 1f;" + "r1 = %[queue_16b] ll;" +"1:" + "r2 = r10;" + "r2 += -24;" + "call %[bpf_map_pop_elem];" + "r0 = 0;" + "exit;" + :: __imm_addr(queue_8b), __imm_addr(queue_16b), + __imm(bpf_get_prandom_u32), __imm(bpf_map_pop_elem) + : __clobber_all); +} + +/* Bloom-filter peek treats buffer as an input despite the helper's output annotation. */ +SEC("socket") +__success __log_level(2) +__msg("call bpf_map_peek_elem{{.*}}; use: fp0-8{{$}}") +__naked void helper_bloom_peek_input(void) +{ + asm volatile ( + "*(u64 *)(r10 - 8) = 0;" + "r1 = %[bloom_8b] ll;" + "r2 = r10;" + "r2 += -8;" + "call %[bpf_map_peek_elem];" + "r0 = 0;" + "exit;" + :: __imm_addr(bloom_8b), __imm(bpf_map_peek_elem) + : __clobber_all); +} |
