Files
linux/tools/testing
Jinjie Ruan 21e37da120 kselftest/arm64: Add testcase for SECCOMP_RET_TRACE orig_x0 bypass
Add a selftest that verifies the kernel re-evaluates a seccomp filter
with the correct (ptrace-modified) first argument after
a SECCOMP_RET_TRACE stop. On arm64, syscall_get_arguments() reads
the first argument from orig_x0, which may be stale if the tracer modified
regs->regs[0] but orig_x0 was not synced.  This can cause the filter to
see an old argument and incorrectly allow a syscall that it should
have rejected.

The child installs a filter that:
 - TRACEs write() when fd == 2
 - returns ERRNO(EPERM) when fd == 1

The parent catches the SECCOMP event, changes x0 (fd) from 2 to 1,
and resumes the child.

If the seccomp re-evaluation sees the stale orig_x0 (fd=2) the filter
returns TRACE again and the kernel (with recheck_after_trace=true)
allows the syscall to proceed – write succeeds and the child exits 0.
If the seccomp re-evaluation sees the new value (fd=1) the filter
returns ERRNO(EPERM), write fails and the child exits non-zero.
The test passes only when the write fails (child exit != 0).

Before the fix:
	# ./seccomp_ret_trace_x0_bypass
	TAP version 13
	1..1
	not ok 1 write succeeded, orig_x0 bypass likely
	# Totals: pass:0 fail:1 xfail:0 xpass:0 skip:0 error:0

After the fix:
	# ./seccomp_ret_trace_x0_bypass
	TAP version 13
	1..1
	ok 1 seccomp correctly denied modified syscall
	# Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0

Cc: Kees Cook <kees@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Link: https://lore.kernel.org/all/20260717182758.17111-1-will@kernel.org/
Link: https://lore.kernel.org/all/20260716120640.6590-1-will@kernel.org/
Link: https://lore.kernel.org/all/202607152004.DEA95D63@keescook/
Suggested-by: Kees Cook <kees@kernel.org>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Signed-off-by: Will Deacon <will@kernel.org>
2026-08-02 09:50:52 +00:00
..