diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-30 09:46:29 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-30 09:46:29 -1000 |
| commit | 6e07889d8fedf729282ed14ff202e06dbb67444b (patch) | |
| tree | 24fe8a9ae9157959829d30592dcdda7445c9a3a9 /arch/arm64/kernel/process.c | |
| parent | 780cb2a5fd64901444878cf5a40c0f2ec54837ce (diff) | |
| parent | f46be4da2cbb17574b5369517a9a1e1b414063b4 (diff) | |
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Catalin Marinas:
"Three fixes that turned up during the merging window: shadow stack not
freed during a failed fork or it is unmapped from parent when a worker
thread exits (same commit covers both); PTE_CONT set on PROT_NONE
entries but subsequently ignored by the unfolding code since
pte_valid() is false (pte_present() is true); an MPAM lock not
released on the error path.
Summary:
- Release the GCS on a failed fork.
copy_thread() can allocate a GCS for CLONE_VM threads but a later
copy_process() failure left the VMA in the parent's mm. Implement
exit_thread() to free it and stop kernel threads and user workers
inheriting the parent's GCS base/size. Add a kselftest for the
clone3() failure case
- Do not set PTE_CONT on invalid PTEs in contpte_set_ptes().
Batched set_ptes() of present-invalid entries (e.g. PROT_NONE)
created contpte groups that the single-PTE helpers did not unfold,
corrupting a neighbouring guard marker via
test_and_clear_young_ptes()
- Release the MPAM mon_sel lock on the mpam_save_mbwu_state() error
paths"
* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
selftests/arm64: GCS must not leak on a failed clone3
arm64/gcs: release GCS on failed fork
arm64/mm: restrict transparent contpte mappings to valid PTEs
arm_mpam: Release the mon_sel lock on mpam_save_mbwu_state() errors
Diffstat (limited to 'arch/arm64/kernel/process.c')
| -rw-r--r-- | arch/arm64/kernel/process.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 581f80e9b9b7..42b15b0c069f 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -320,9 +320,18 @@ static int copy_thread_gcs(struct task_struct *p, return 0; } +static void gcs_reset_thread(struct task_struct *task) +{ + task->thread.gcs_base = 0; + task->thread.gcs_size = 0; + task->thread.gcspr_el0 = 0; +} + #else static void flush_gcs(void) { } +static void gcs_reset_thread(struct task_struct *task) { } + static int copy_thread_gcs(struct task_struct *p, const struct kernel_clone_args *args) { @@ -341,6 +350,12 @@ void flush_thread(void) flush_gcs(); } +void exit_thread(struct task_struct *tsk) +{ + /* Failed fork after copy_thread(); deactivate_mm() does not run. */ + gcs_free(tsk); +} + void arch_release_task_struct(struct task_struct *tsk) { fpsimd_release_task(tsk); @@ -503,6 +518,8 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) p->thread.cpu_context.x19 = (unsigned long)args->fn; p->thread.cpu_context.x20 = (unsigned long)args->fn_arg; + /* Kernel threads sharing the parent's mm must not free its GCS. */ + gcs_reset_thread(p); if (system_supports_poe()) p->thread.por_el0 = POR_EL0_INIT; |
