summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorEduard Zingerman <eddyz87@gmail.com>2026-10-09 03:48:01 -0700
committerAlexei Starovoitov <ast@kernel.org>2026-10-09 20:29:14 +0000
commite60fb9b6b5beabe9f5cd7475768b04b5abe4d37f (patch)
tree51fbccce1cd45e3ced8a89a45b815c88691500a2 /tools
parent75a46f59e0985dd53fe7d5b2c4f42fd5e44ff144 (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.c76
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);
+}