summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel/process.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-30 09:46:29 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-30 09:46:29 -1000
commit6e07889d8fedf729282ed14ff202e06dbb67444b (patch)
tree24fe8a9ae9157959829d30592dcdda7445c9a3a9 /arch/arm64/kernel/process.c
parent780cb2a5fd64901444878cf5a40c0f2ec54837ce (diff)
parentf46be4da2cbb17574b5369517a9a1e1b414063b4 (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.c17
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;