[PATCH v18 01/14] arm64: ptrace: Fix redundant syscall exit stop for PTRACE_SYSEMU_SINGLESTEP
Jinjie Ruan
ruanjinjie at huawei.com
Wed Sep 2 02:55:24 PDT 2026
PTRACE_SYSEMU_SINGLESTEP sets both _TIF_SYSCALL_EMU and _TIF_SINGLESTEP.
arm64 currently reports a syscall exit stop whenever _TIF_SINGLESTEP is
set, regardless of emulation state.
This violates the ptrace man page (Syscall-stops section):
"If the tracee was restarted by PTRACE_SYSCALL or PTRACE_SYSEMU,
the tracee enters syscall-enter-stop just prior to entering any
system call (which will not be executed if the restart was using
PTRACE_SYSEMU, regardless of any change made to registers at this
point or how the tracee is restarted after this stop). ...
If the tracee is continued using any other method (including
PTRACE_SYSEMU), no syscall-exit-stop occurs. Note that all mentions
PTRACE_SYSEMU apply equally to PTRACE_SYSEMU_SINGLESTEP."
Fix by introducing report_single_step(), which returns false when
_TIF_SYSCALL_EMU is set, skipping the redundant exit stop.
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Will Deacon <will at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Fixes: ac2081cdc4d9 ("arm64: ptrace: Consistently use pseudo-singlestep exceptions")
Reviewed-by: Ada Couprie Diaz <ada.coupriediaz at arm.com>
Reviewed-by: Linus Walleij <linusw at kernel.org>
Reviewed-by: Yeoreum Yun <yeoreum.yun at arm.com>
Signed-off-by: Jinjie Ruan <ruanjinjie at huawei.com>
---
arch/arm64/kernel/ptrace.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index f743cbec1c3a..96462de75d4b 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -2482,16 +2482,26 @@ int syscall_trace_enter(struct pt_regs *regs)
return regs->syscallno;
}
+static inline bool report_single_step(unsigned long flags)
+{
+ if (flags & _TIF_SYSCALL_EMU)
+ return false;
+
+ return flags & _TIF_SINGLESTEP;
+}
+
void syscall_trace_exit(struct pt_regs *regs)
{
unsigned long flags = read_thread_flags();
+ bool step;
audit_syscall_exit(regs);
if (flags & _TIF_SYSCALL_TRACEPOINT)
trace_sys_exit(regs, syscall_get_return_value(current, regs));
- if (flags & (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP))
+ step = report_single_step(flags);
+ if (step || flags & _TIF_SYSCALL_TRACE)
report_syscall_exit(regs);
rseq_syscall(regs);
--
2.34.1
More information about the linux-arm-kernel
mailing list