[PATCH v17 01/15] arm64: ptrace: Skip syscall exit reporting for PTRACE_SYSEMU_SINGLESTEP
From: Jinjie Ruan
Date: Tue Jul 21 2026 - 04:27:39 EST
According to 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."
When a tracer uses PTRACE_SYSEMU_SINGLESTEP, both _TIF_SYSCALL_EMU
and _TIF_SINGLESTEP are set. Currently, arm64 unconditionally reports
a syscall exit stop whenever _TIF_SINGLESTEP is set, regardless of the
emulation state. This deviates from the documented behavior and breaks
consistency with x86, where PTRACE_SYSEMU_SINGLESTEP does not trigger
a redundant exit stop.
[Changes]
- Introduce report_single_step(): Returns false when _TIF_SYSCALL_EMU
is set, ensuring emulated syscalls do not trigger a duplicate report.
- Update syscall_exit_work(): Use the new helper instead of directly
checking _TIF_SINGLESTEP.
[Impact]
- PTRACE_SINGLESTEP: Continues to report exit stops for actual
instructions.
- PTRACE_SYSEMU: Continues to skip exit stops.
- PTRACE_SYSEMU_SINGLESTEP: Now correctly skips the redundant exit stop,
aligning arm64 with documentation and the generic entry infrastructure.
Cc: Mark Rutland <mark.rutland@xxxxxxx>
Cc: Will Deacon <will@xxxxxxxxxx>
Cc: Catalin Marinas <catalin.marinas@xxxxxxx>
Fixes: ac2081cdc4d9 ("arm64: ptrace: Consistently use pseudo-singlestep exceptions")
Reviewed-by: Ada Couprie Diaz <ada.coupriediaz@xxxxxxx>
Reviewed-by: Linus Walleij <linusw@xxxxxxxxxx>
Reviewed-by: Yeoreum Yun <yeoreum.yun@xxxxxxx>
Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
---
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 924805e0c8da..4e9c71d477a5 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