arm64: ptrace: Override SPSR.SS when single-stepping is enabled
authorWill Deacon <will@kernel.org>
Thu, 13 Feb 2020 12:06:26 +0000 (12:06 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Jul 2020 07:10:54 +0000 (09:10 +0200)
commitc5e7ebb29bc85fa77566163f0d11da62a0a25bfb
tree719c8bf508c0c6e485b3bc34d1469484fb90cf07
parentd090d02c06f812ed48dabdbce00e1af22c1a0774
arm64: ptrace: Override SPSR.SS when single-stepping is enabled

commit 3a5a4366cecc25daa300b9a9174f7fdd352b9068 upstream.

Luis reports that, when reverse debugging with GDB, single-step does not
function as expected on arm64:

  | I've noticed, under very specific conditions, that a PTRACE_SINGLESTEP
  | request by GDB won't execute the underlying instruction. As a consequence,
  | the PC doesn't move, but we return a SIGTRAP just like we would for a
  | regular successful PTRACE_SINGLESTEP request.

The underlying problem is that when the CPU register state is restored
as part of a reverse step, the SPSR.SS bit is cleared and so the hardware
single-step state can transition to the "active-pending" state, causing
an unexpected step exception to be taken immediately if a step operation
is attempted.

In hindsight, we probably shouldn't have exposed SPSR.SS in the pstate
accessible by the GPR regset, but it's a bit late for that now. Instead,
simply prevent userspace from configuring the bit to a value which is
inconsistent with the TIF_SINGLESTEP state for the task being traced.

Cc: <stable@vger.kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Keno Fischer <keno@juliacomputing.com>
Link: https://lore.kernel.org/r/1eed6d69-d53d-9657-1fc9-c089be07f98c@linaro.org
Reported-by: Luis Machado <luis.machado@linaro.org>
Tested-by: Luis Machado <luis.machado@linaro.org>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/include/asm/debug-monitors.h
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/ptrace.c