]> git.ipfire.org Git - people/ms/linux.git/commitdiff
arm64: ensure ERET from kthread is illegal
authorMark Rutland <mark.rutland@arm.com>
Fri, 13 Nov 2020 12:49:21 +0000 (12:49 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Wed, 2 Dec 2020 19:44:02 +0000 (19:44 +0000)
For consistency, all tasks have a pt_regs reserved at the highest
portion of their task stack. Among other things, this ensures that a
task's SP is always pointing within its stack rather than pointing
immediately past the end.

While it is never legitimate to ERET from a kthread, we take pains to
initialize pt_regs for kthreads as if this were legitimate. As this is
never legitimate, the effects of an erroneous return are rarely tested.

Let's simplify things by initializing a kthread's pt_regs such that an
ERET is caught as an illegal exception return, and removing the explicit
initialization of other exception context. Note that as
spectre_v4_enable_task_mitigation() only manipulates the PSTATE within
the unused regs this is safe to remove.

As user tasks will have their exception context initialized via
start_thread() or start_compat_thread(), this should only impact cases
where something has gone very wrong and we'd like that to be clearly
indicated.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: James Morse <james.morse@arm.com>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20201113124937.20574-2-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/kernel/process.c

index 4784011cecac976f42725a8a22bfa1c5af678907..855137daafbfb440c4a0534eef70be7a52d7fdb2 100644 (file)
@@ -422,16 +422,15 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
                if (clone_flags & CLONE_SETTLS)
                        p->thread.uw.tp_value = tls;
        } else {
+               /*
+                * A kthread has no context to ERET to, so ensure any buggy
+                * ERET is treated as an illegal exception return.
+                *
+                * When a user task is created from a kthread, childregs will
+                * be initialized by start_thread() or start_compat_thread().
+                */
                memset(childregs, 0, sizeof(struct pt_regs));
-               childregs->pstate = PSR_MODE_EL1h;
-               if (IS_ENABLED(CONFIG_ARM64_UAO) &&
-                   cpus_have_const_cap(ARM64_HAS_UAO))
-                       childregs->pstate |= PSR_UAO_BIT;
-
-               spectre_v4_enable_task_mitigation(p);
-
-               if (system_uses_irq_prio_masking())
-                       childregs->pmr_save = GIC_PRIO_IRQON;
+               childregs->pstate = PSR_MODE_EL1h | PSR_IL_BIT;
 
                p->thread.cpu_context.x19 = stack_start;
                p->thread.cpu_context.x20 = stk_sz;