Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [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

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