* [PATCH] ARM: ptrace: keep ARM_ORIG_r0 consistent with ARM_r0 after ptrace writes
@ 2026-07-25 9:14 Jinjie Ruan
2026-07-25 9:44 ` Russell King
0 siblings, 1 reply; 2+ messages in thread
From: Jinjie Ruan @ 2026-07-25 9:14 UTC (permalink / raw)
To: oleg, linux, wade_farnsworth, will, stevenrwalter,
linux-arm-kernel, linux-kernel
Cc: ruanjinjie
When ptrace modifies r0 during a syscall-entry stop via PTRACE_SETREGS or
PTRACE_POKEUSR, ARM_ORIG_r0 is not updated. This causes seccomp filters
and tracepoints to read stale arguments, which disagree with the actual
value dispatched by the kernel. This is particularly critical for the
SECCOMP_RET_TRACE re-evaluation path.
Fix it by synchronizing ARM_ORIG_r0 after every arch-level ptrace register
write. The update safely skips syscall-exit stops (where r0 holds the
return value) and NO_SYSCALL states to avoid corrupting non-syscall
contexts. And use ARM_ORIG_r0 in audit_syscall_entry to fix data
inconsistency with seccomp/tracepoints
Cc: stable@vger.kernel.org
Fixes: bf2c9f986692 ("ARM: 7373/1: add support for the generic syscall.h interface")
Link: https://lore.kernel.org/all/al98jdcleu-6tMDL@willie-the-truck/
Suggested-by: Will Deacon <will@kernel.org>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
arch/arm/kernel/ptrace.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 7951b2c06fec..99c2d594f81a 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -163,6 +163,25 @@ static inline long get_user_reg(struct task_struct *task, int offset)
return task_pt_regs(task)->uregs[offset];
}
+static void update_syscall_orig_r0_after_ptrace(struct task_struct *target)
+{
+ struct pt_regs *regs = task_pt_regs(target);
+ struct kernel_siginfo *info = target->last_siginfo;
+ struct thread_info *ti = task_thread_info(target);
+
+ if (!info)
+ return;
+
+ if (ti->abi_syscall == -1)
+ return;
+
+ if ((info->si_code & ~0x80) == SIGTRAP &&
+ target->ptrace_message == PTRACE_EVENTMSG_SYSCALL_EXIT)
+ return;
+
+ regs->ARM_ORIG_r0 = regs->ARM_r0;
+}
+
/*
* this routine will put a word on the processes privileged stack.
* the offset is how far from the base addr as stored in the THREAD.
@@ -180,6 +199,8 @@ put_user_reg(struct task_struct *task, int offset, long data)
if (valid_user_regs(&newregs)) {
regs->uregs[offset] = data;
+ if (offset == 0)
+ update_syscall_orig_r0_after_ptrace(task);
ret = 0;
}
@@ -566,6 +587,7 @@ static int gpr_set(struct task_struct *target,
return -EINVAL;
*task_pt_regs(target) = newregs;
+ update_syscall_orig_r0_after_ptrace(target);
return 0;
}
@@ -784,6 +806,12 @@ long arch_ptrace(struct task_struct *child, long request,
if (data != -1)
data &= __NR_SYSCALL_MASK;
task_thread_info(child)->abi_syscall = data;
+
+ /*
+ * Re-sync orig_r0 in case the syscall number has
+ * been changed from -1.
+ */
+ update_syscall_orig_r0_after_ptrace(child);
ret = 0;
break;
@@ -868,7 +896,7 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, scno);
- audit_syscall_entry(scno, regs->ARM_r0, regs->ARM_r1, regs->ARM_r2,
+ audit_syscall_entry(scno, regs->ARM_ORIG_r0, regs->ARM_r1, regs->ARM_r2,
regs->ARM_r3);
return scno;
--
2.34.1
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] ARM: ptrace: keep ARM_ORIG_r0 consistent with ARM_r0 after ptrace writes
2026-07-25 9:14 [PATCH] ARM: ptrace: keep ARM_ORIG_r0 consistent with ARM_r0 after ptrace writes Jinjie Ruan
@ 2026-07-25 9:44 ` Russell King
0 siblings, 0 replies; 2+ messages in thread
From: Russell King @ 2026-07-25 9:44 UTC (permalink / raw)
To: Jinjie Ruan
Cc: oleg, wade_farnsworth, will, stevenrwalter, linux-arm-kernel,
linux-kernel
On Sat, Jul 25, 2026 at 05:14:52PM +0800, Jinjie Ruan wrote:
> When ptrace modifies r0 during a syscall-entry stop via PTRACE_SETREGS or
> PTRACE_POKEUSR, ARM_ORIG_r0 is not updated. This causes seccomp filters
> and tracepoints to read stale arguments, which disagree with the actual
> value dispatched by the kernel. This is particularly critical for the
> SECCOMP_RET_TRACE re-evaluation path.
>
> Fix it by synchronizing ARM_ORIG_r0 after every arch-level ptrace register
> write. The update safely skips syscall-exit stops (where r0 holds the
> return value) and NO_SYSCALL states to avoid corrupting non-syscall
> contexts. And use ARM_ORIG_r0 in audit_syscall_entry to fix data
> inconsistency with seccomp/tracepoints
ARM_ORIG_r0 is intentionally not always the same as ARM_r0, just as
orig_eax is not always the same as eax in x86. These exist to allow
syscall restart as ARM_r0 / eax will be overwritten when a syscall
returns. I don't see arch/x86/kernel/ptrace.c::putreg32() needing
this kind of fixup, so why does ARM?
ARM_ORIG_r0 is set to the value of ARM_r0 when a syscall is entered,
otherwise it is set to ~0 as for other exception cases, the value is
meaningless (there is no syscall restart in that path.)
If one changes both ARM_ORIG_r0 and ARM_r0 during the syscall exit
path to e.g. -ERESTARTSYS and then raises a signal against the user
program, then is it not possible that do_signal() to then see that
case, and as regs->ARM_ORIG_r0 would now also contain -ERESTARTSYS,
call the syscall with the first argument set to -ERESTARTSYS rather
than the user's actual value?
Userspace has full access to both ARM_r0 and ARM_ORIG_r0, and can
decide what it wants to do in the same way that userspace has
access to eax and orig_eax on x86.
Please check how this is handled on x86.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-25 9:44 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-25 9:14 [PATCH] ARM: ptrace: keep ARM_ORIG_r0 consistent with ARM_r0 after ptrace writes Jinjie Ruan
2026-07-25 9:44 ` Russell King
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox