Skip to content

Commit 97e63bf

Browse files
leitaogregkh
authored andcommitted
arm64/fpsimd: ptrace: zero target's fpsimd_state, not the tracer's
commit 5cbb61b upstream. sve_set_common() is the backend for PTRACE_SETREGSET(NT_ARM_SVE) and PTRACE_SETREGSET(NT_ARM_SSVE). Every write in the function operates on the tracee (target) - except a single memset that uses current instead, zeroing the tracer's saved V0-V31 / FPSR / FPCR shadow on every ptrace SETREGSET call. The memset is meant to give the tracee a defined zero register image before the user-supplied payload is copied in (for partial writes, header-only writes, and FPSIMD<->SVE format switches). Aiming it at current both denies the tracee that clean slate and silently corrupts the tracer. The corruption of the tracer's saved FPSIMD state is not always observable. Where the tracer's state is live on a CPU, this may be reused without loading the corrupted state from memory, and will eventually be written back over the corrupted state. Where the tracer's state is saved in SVE_PT_REGS_SVE format, only the FPSR and FPCR are clobbered, and the effective copy of the vectors is in the task's sve_state. Reproducible on an arm64 kernel with SVE: a single-threaded tracer that loads a known pattern into V0-V31, issues PTRACE_SETREGSET(NT_ARM_SVE) on a child, and reads V0-V31 back observes them all zeroed within tens of thousands of iterations when a sibling thread keeps stealing the FPSIMD CPU binding. Fixes: 316283f ("arm64/fpsimd: ptrace: Consistently handle partial writes to NT_ARM_(S)SVE") Cc: <stable@vger.kernel.org> Signed-off-by: Breno Leitao <leitao@debian.org> Acked-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 3147ddf commit 97e63bf

1 file changed

Lines changed: 2 additions & 2 deletions

File tree

arch/arm64/kernel/ptrace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -983,8 +983,8 @@ static int sve_set_common(struct task_struct *target,
983983
}
984984

985985
/* Always zero V regs, FPSR, and FPCR */
986-
memset(&current->thread.uw.fpsimd_state, 0,
987-
sizeof(current->thread.uw.fpsimd_state));
986+
memset(&target->thread.uw.fpsimd_state, 0,
987+
sizeof(target->thread.uw.fpsimd_state));
988988

989989
/* Registers: FPSIMD-only case */
990990

0 commit comments

Comments
 (0)