Skip to content

Commit a6d066f

Browse files
mrutland-armwilldeacon
authored andcommitted
arm64/fpsimd: Clear PSTATE.SM during clone()
Currently arch_dup_task_struct() doesn't handle cases where the parent task has PSTATE.SM==1. Since syscall entry exits streaming mode, the parent will usually have PSTATE.SM==0, but this can be change by ptrace after syscall entry. When this happens, arch_dup_task_struct() will initialise the new task into an invalid state. The new task inherits the parent's configuration of PSTATE.SM, but fp_type is set to FP_STATE_FPSIMD, TIF_SVE and SME may be cleared, and both sve_state and sme_state may be set to NULL. This can result in a variety of problems whenever the new task's state is manipulated, including kernel NULL pointer dereferences and leaking of streaming mode state between tasks. When ptrace is not involved, the parent will have PSTATE.SM==0 as a result of syscall entry, and the documentation in Documentation/arch/arm64/sme.rst says: | On process creation (eg, clone()) the newly created process will have | PSTATE.SM cleared. ... so make this true by using task_smstop_sm() to exit streaming mode in the child task, avoiding the problems above. Fixes: 8bd7f91 ("arm64/sme: Implement traps and syscall handling for SME") Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Marc Zyngier <maz@kernel.org> Cc: Mark Brown <broonie@kernel.org> Cc: Will Deacon <will@kernel.org> Link: https://lore.kernel.org/r/20250508132644.1395904-13-mark.rutland@arm.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent e0cb0f2 commit a6d066f

File tree

1 file changed

+4
-9
lines changed

1 file changed

+4
-9
lines changed

arch/arm64/kernel/process.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -355,16 +355,13 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
355355
*dst = *src;
356356

357357
/*
358-
* Detach src's sve_state (if any) from dst so that it does not
359-
* get erroneously used or freed prematurely. dst's copies
360-
* will be allocated on demand later on if dst uses SVE.
361-
* For consistency, also clear TIF_SVE here: this could be done
362-
* later in copy_process(), but to avoid tripping up future
363-
* maintainers it is best not to leave TIF flags and buffers in
364-
* an inconsistent state, even temporarily.
358+
* Drop stale reference to src's sve_state and convert dst to
359+
* non-streaming FPSIMD mode.
365360
*/
361+
dst->thread.fp_type = FP_STATE_FPSIMD;
366362
dst->thread.sve_state = NULL;
367363
clear_tsk_thread_flag(dst, TIF_SVE);
364+
task_smstop_sm(dst);
368365

369366
/*
370367
* In the unlikely event that we create a new thread with ZA
@@ -393,8 +390,6 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
393390
clear_tsk_thread_flag(dst, TIF_SME);
394391
}
395392

396-
dst->thread.fp_type = FP_STATE_FPSIMD;
397-
398393
/* clear any pending asynchronous tag fault raised by the parent */
399394
clear_tsk_thread_flag(dst, TIF_MTE_ASYNC_FAULT);
400395

0 commit comments

Comments
 (0)