Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

arm64/fpsimd: ptrace: Fix SVE writes on !SME systems

When SVE is supported but SME is not supported, a ptrace write to the
NT_ARM_SVE regset can place the tracee into an invalid state where
(non-streaming) SVE register data is stored in FP_STATE_SVE format but
TIF_SVE is clear. This can result in a later warning from
fpsimd_restore_current_state(), e.g.

WARNING: CPU: 0 PID: 7214 at arch/arm64/kernel/fpsimd.c:383 fpsimd_restore_current_state+0x50c/0x748

When this happens, fpsimd_restore_current_state() will set TIF_SVE,
placing the task into the correct state. This occurs before any other
check of TIF_SVE can possibly occur, as other checks of TIF_SVE only
happen while the FPSIMD/SVE/SME state is live. Thus, aside from the
warning, there is no functional issue.

This bug was introduced during rework to error handling in commit:

9f8bf718f2923 ("arm64/fpsimd: ptrace: Gracefully handle errors")

... where the setting of TIF_SVE was moved into a block which is only
executed when system_supports_sme() is true.

Fix this by removing the system_supports_sme() check. This ensures that
TIF_SVE is set for (SVE-formatted) writes to NT_ARM_SVE, at the cost of
unconditionally manipulating the tracee's saved svcr value. The
manipulation of svcr is benign and inexpensive, and we already do
similar elsewhere (e.g. during signal handling), so I don't think it's
worth guarding this with system_supports_sme() checks.

Aside from the above, there is no functional change. The 'type' argument
to sve_set_common() is only set to ARM64_VEC_SME (in ssve_set())) when
system_supports_sme(), so the ARM64_VEC_SME case in the switch statement
is still unreachable when !system_supports_sme(). When
CONFIG_ARM64_SME=n, the only caller of sve_set_common() is sve_set(),
and the compiler can constant-fold for the case where type is
ARM64_VEC_SVE, removing the logic for other cases.

Reported-by: syzbot+d4ab35af21e99d07ce67@syzkaller.appspotmail.com
Fixes: 9f8bf718f292 ("arm64/fpsimd: ptrace: Gracefully handle errors")
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: <stable@vger.kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Mark Rutland and committed by
Catalin Marinas
128a7494 b9f5c38e

+12 -14
+12 -14
arch/arm64/kernel/ptrace.c
··· 968 968 vq = sve_vq_from_vl(task_get_vl(target, type)); 969 969 970 970 /* Enter/exit streaming mode */ 971 - if (system_supports_sme()) { 972 - switch (type) { 973 - case ARM64_VEC_SVE: 974 - target->thread.svcr &= ~SVCR_SM_MASK; 975 - set_tsk_thread_flag(target, TIF_SVE); 976 - break; 977 - case ARM64_VEC_SME: 978 - target->thread.svcr |= SVCR_SM_MASK; 979 - set_tsk_thread_flag(target, TIF_SME); 980 - break; 981 - default: 982 - WARN_ON_ONCE(1); 983 - return -EINVAL; 984 - } 971 + switch (type) { 972 + case ARM64_VEC_SVE: 973 + target->thread.svcr &= ~SVCR_SM_MASK; 974 + set_tsk_thread_flag(target, TIF_SVE); 975 + break; 976 + case ARM64_VEC_SME: 977 + target->thread.svcr |= SVCR_SM_MASK; 978 + set_tsk_thread_flag(target, TIF_SME); 979 + break; 980 + default: 981 + WARN_ON_ONCE(1); 982 + return -EINVAL; 985 983 } 986 984 987 985 /* Always zero V regs, FPSR, and FPCR */