Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: ensure ERET from kthread is illegal

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>

authored by

Mark Rutland and committed by
Catalin Marinas
f80d0340 e35123d8

+8 -9
+8 -9
arch/arm64/kernel/process.c
··· 422 422 if (clone_flags & CLONE_SETTLS) 423 423 p->thread.uw.tp_value = tls; 424 424 } else { 425 + /* 426 + * A kthread has no context to ERET to, so ensure any buggy 427 + * ERET is treated as an illegal exception return. 428 + * 429 + * When a user task is created from a kthread, childregs will 430 + * be initialized by start_thread() or start_compat_thread(). 431 + */ 425 432 memset(childregs, 0, sizeof(struct pt_regs)); 426 - childregs->pstate = PSR_MODE_EL1h; 427 - if (IS_ENABLED(CONFIG_ARM64_UAO) && 428 - cpus_have_const_cap(ARM64_HAS_UAO)) 429 - childregs->pstate |= PSR_UAO_BIT; 430 - 431 - spectre_v4_enable_task_mitigation(p); 432 - 433 - if (system_uses_irq_prio_masking()) 434 - childregs->pmr_save = GIC_PRIO_IRQON; 433 + childregs->pstate = PSR_MODE_EL1h | PSR_IL_BIT; 435 434 436 435 p->thread.cpu_context.x19 = stack_start; 437 436 p->thread.cpu_context.x20 = stk_sz;