[PATCH RESEND] entry: Fix seccomp bypass after ptrace with TSYNC
From: Jinjie Ruan
Date: Thu Jul 09 2026 - 03:33:31 EST
Sashiko review pointed out the following issue[1].
If a thread is stopped in syscall_trace_enter() for ptrace, another
thread can install a seccomp filter with SECCOMP_FILTER_FLAG_TSYNC
(e.g., via seccomp_attach_filter()). This will successfully set
SYSCALL_WORK_SECCOMP on the stopped thread, but syscall_trace_enter()
evaluates a cached 'work' variable sampled on entry. Consequently,
the subsequent check for SYSCALL_WORK_SECCOMP misses the newly
assigned flag, and the filter is silently bypassed.
This race condition could allow an unprivileged process to execute
a prohibited system call (e.g., execve) that the newly installed filter
was intended to block, especially since the tracer might have modified
the system call number during the ptrace stop.
Fix this by replacing the cached seccomp check with a call to
seccomp_permit_syscall(), which re-reads the thread's up-to-date
TIF_SECCOMP flag and thus correctly observes the flag if it was set
during the ptrace stop.
Rebased on the rename of secure_computing() patch[2].
Cc: Kees Cook <kees@xxxxxxxxxx>
Cc: Thomas Gleixner <tglx@xxxxxxxxxx>
Cc: Andy Lutomirski <luto@xxxxxxxxxxxxxx>
Cc: Will Drewry <wad@xxxxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
[1]: https://lore.kernel.org/all/20260629132914.1135C1F000E9@xxxxxxxxxxxxxxx/
[2]: https://lore.kernel.org/all/20260707190254.230735780@xxxxxxxxxx/
Fixes: 142781e108b1 ("entry: Provide generic syscall entry functionality")
Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
---
include/linux/entry-common.h | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
index 4abfd7521d8b..ee6be8f3b56a 100644
--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -99,10 +99,8 @@ static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned l
}
/* Do seccomp after ptrace, to catch any tracer changes. */
- if (work & SYSCALL_WORK_SECCOMP) {
- if (!__seccomp_permit_syscall())
- return -1L;
- }
+ if (!seccomp_permit_syscall())
+ return -1L;
/* Either of the above might have changed the syscall number */
syscall = syscall_get_nr(current, regs);
--
2.34.1