diff options
author | Will Deacon <will@kernel.org> | 2020-07-02 21:16:20 +0100 |
---|---|---|
committer | Will Deacon <will@kernel.org> | 2020-07-16 11:41:07 +0100 |
commit | ac2081cdc4d99c57f219c1a6171526e0fa0a6fff (patch) | |
tree | e611aa9681fd5665310f37a5585feba904584f6e /arch/arm64/kernel/syscall.c | |
parent | drivers/perf: Fix kernel panic when rmmod PMU modules during perf sampling (diff) | |
download | wireguard-linux-ac2081cdc4d99c57f219c1a6171526e0fa0a6fff.tar.xz wireguard-linux-ac2081cdc4d99c57f219c1a6171526e0fa0a6fff.zip |
arm64: ptrace: Consistently use pseudo-singlestep exceptions
Although the arm64 single-step state machine can be fast-forwarded in
cases where we wish to generate a SIGTRAP without actually executing an
instruction, this has two major limitations outside of simply skipping
an instruction due to emulation.
1. Stepping out of a ptrace signal stop into a signal handler where
SIGTRAP is blocked. Fast-forwarding the stepping state machine in
this case will result in a forced SIGTRAP, with the handler reset to
SIG_DFL.
2. The hardware implicitly fast-forwards the state machine when executing
an SVC instruction for issuing a system call. This can interact badly
with subsequent ptrace stops signalled during the execution of the
system call (e.g. SYSCALL_EXIT or seccomp traps), as they may corrupt
the stepping state by updating the PSTATE for the tracee.
Resolve both of these issues by injecting a pseudo-singlestep exception
on entry to a signal handler and also on return to userspace following a
system call.
Cc: <stable@vger.kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Tested-by: Luis Machado <luis.machado@linaro.org>
Reported-by: Keno Fischer <keno@juliacomputing.com>
Signed-off-by: Will Deacon <will@kernel.org>
Diffstat (limited to 'arch/arm64/kernel/syscall.c')
-rw-r--r-- | arch/arm64/kernel/syscall.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index 5f5b868292f5..7c14466a12af 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -139,7 +139,7 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) { local_daif_mask(); flags = current_thread_info()->flags; - if (!has_syscall_work(flags)) { + if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP)) { /* * We're off to userspace, where interrupts are * always enabled after we restore the flags from |