summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/bpf/progs
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2026-08-06 22:10:46 +0200
committerKumar Kartikeya Dwivedi <memxor@gmail.com>2026-08-07 14:57:13 +0200
commit007466d9e49738222054f1df87c111a945633ddd (patch)
tree75e3488db37fd87f47cef683c81a844241f6a830 /tools/testing/selftests/bpf/progs
parentaf22d273aa1f61fb86ec712b3ed785da73c3296e (diff)
downloadlinux-next-007466d9e49738222054f1df87c111a945633ddd.tar.gz
linux-next-007466d9e49738222054f1df87c111a945633ddd.zip
selftests/bpf: Add arena fault test for load-acquire
Add stream_arena_load_acquire_fault, which performs a load-acquire from an unmapped arena address, next to the existing read and write fault tests. The test covers both halves of the JIT bug that treated a load-acquire as a store when populating its exception table entry: - the fault has to be reported as a READ, and at the address held by the source register, which __stderr() and test_address() check, and - the destination register has to be cleared by the fault handler, which the program checks by poisoning it before the load-acquire and returning it, so __retval(0) fails if it is left untouched Note, load-acquire is open coded since linux/filter.h cannot be included alongside vmlinux.h. # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t stream_arena_fault_address [...] #462/1 stream_arena_fault_address/read_fault:OK #462/2 stream_arena_fault_address/write_fault:OK #462/3 stream_arena_fault_address/load_acquire_fault:OK #462 stream_arena_fault_address:OK Summary: 1/3 PASSED, 0 SKIPPED, 0 FAILED Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/bpf/20260806201047.333389-5-daniel@iogearbox.net Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Diffstat (limited to 'tools/testing/selftests/bpf/progs')
-rw-r--r--tools/testing/selftests/bpf/progs/stream.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/progs/stream.c b/tools/testing/selftests/bpf/progs/stream.c
index 8d8e53d37266..cf5533e11f39 100644
--- a/tools/testing/selftests/bpf/progs/stream.c
+++ b/tools/testing/selftests/bpf/progs/stream.c
@@ -185,6 +185,50 @@ int stream_arena_read_fault(void *ctx)
return 0;
}
+SEC("syscall")
+__arch_x86_64
+__arch_arm64
+__success __retval(0)
+__stderr("ERROR: Arena READ access at unmapped address 0x{{.*}}")
+__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}")
+__stderr("Call trace:\n"
+"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n"
+"|[ \t]+[^\n]+\n)*}}")
+int stream_arena_load_acquire_fault(void *ctx)
+{
+ static const struct bpf_insn load_acquire_insn = {
+ .code = 0xc3, /* BPF_STX | BPF_ATOMIC | BPF_W */
+ .dst_reg = 0, /* BPF_REG_0 */
+ .src_reg = 1, /* BPF_REG_1 */
+ .off = 0x7fff,
+ .imm = 0x100, /* BPF_LOAD_ACQ */
+ };
+ struct bpf_arena *ptr = (void *)&arena;
+ u64 user_vm_start, val;
+
+ /*
+ * Prevent GCC bounds warning: casting &arena to struct bpf_arena *
+ * triggers bounds checking since the map definition is smaller than
+ * struct bpf_arena. barrier_var() makes the pointer opaque to GCC,
+ * preventing the bounds analysis.
+ */
+ barrier_var(ptr);
+ user_vm_start = ptr->user_vm_start;
+ fault_addr = user_vm_start + 0x7fff;
+ bpf_addr_space_cast(user_vm_start, 0, 1);
+ asm volatile (
+ "r1 = %[user_vm_start];"
+ "r0 = 1;"
+ ".8byte %[load_acquire_insn];" /* r0 = load_acquire((u32 *)(r1 + 0x7fff)) */
+ "%[val] = r0;"
+ : [val] "=r" (val)
+ : [user_vm_start] "r" (user_vm_start),
+ __imm_insn(load_acquire_insn, load_acquire_insn)
+ : "r0", "r1"
+ );
+ return val;
+}
+
static __noinline void subprog(void)
{
int __arena *addr = (int __arena *)0xdeadbeef;