On Fri, Oct 16, 2026 at 04:46:00PM -0300, Iván Ezequiel Rodriguez wrote: > Select HAVE_EXIT_THREAD and free the child's GCS from > exit_thread(). gcs_free() already ignores a cleared base and a > different mm, so the usual exit path (deactivate_mm() then this) is > a no-op the second time. copy_thread_gcs() zeros the inherited > tracking before a user-thread allocation, so an allocation error > still skips exit_thread() with nothing to unmap.
This makes sense and mirrors the handling on x86 which had an existing exit_thread(). There was a lot of pain finding the right places to hook in here, there's far too many routes through this code :/ . > A kthread copies the caller's GCS fields via arch_dup_task_struct(). > kernel_thread() uses CLONE_VM, so during a failed copy_process() > the child still shares the caller's mm and gcs_free()'s mm check > does not save us. Clear the inherited tracking as part of kthread > setup. I'm not spotting an equivalent path on x86, it's entirely possible I'm missing something here but if I'm not then I expect they need the same fix? They use a similar memcpy() for the arch data and I'm not seeing a reset anywhere. > @@ -503,6 +513,17 @@ 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; > +#ifdef CONFIG_ARM64_GCS > + /* > + * kernel_thread() uses CLONE_VM, so a failed > + * copy_process() still shares the caller's mm. > + * Inherited GCS tracking would then look like a > + * child mapping to gcs_free(). > + */ > + p->thread.gcs_base = 0; > + p->thread.gcs_size = 0; > + p->thread.gcspr_el0 = 0; > +#endif I think it'd be a bit more idiomatic to have a function to reset the GCS state that gets an empty stub with !CONFIG_GCS
signature.asc
Description: PGP signature
