Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 40ca0ce5 authored by James Morse's avatar James Morse Committed by Will Deacon
Browse files

arm64: entry: SP Alignment Fault doesn't write to FAR_EL1



Comparing the arm-arm's  pseudocode for AArch64.PCAlignmentFault() with
AArch64.SPAlignmentFault() shows that SP faults don't copy the faulty-SP
to FAR_EL1, but this is where we read from, and the address we provide
to user-space with the BUS_ADRALN signal.

For user-space this value will be UNKNOWN due to the previous ERET to
user-space. If the last value is preserved, on systems with KASLR or KPTI
this will be the user-space link-register left in FAR_EL1 by tramp_exit().
Fix this to retrieve the original sp_el0 value, and pass this to
do_sp_pc_fault().

SP alignment faults from EL1 will cause us to take the fault again when
trying to store the pt_regs. This eventually takes us to the overflow
stack. Remove the ESR_ELx_EC_SP_ALIGN check as we will never make it
this far.

Fixes: 60ffc30d ("arm64: Exception handling")
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
[will: change label name and fleshed out comment]
Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent cbdf8a18
Loading
Loading
Loading
Loading
+13 −9
Original line number Diff line number Diff line
@@ -586,10 +586,8 @@ el1_sync:
	b.eq	el1_ia
	cmp	x24, #ESR_ELx_EC_SYS64		// configurable trap
	b.eq	el1_undef
	cmp	x24, #ESR_ELx_EC_SP_ALIGN	// stack alignment exception
	b.eq	el1_sp_pc
	cmp	x24, #ESR_ELx_EC_PC_ALIGN	// pc alignment exception
	b.eq	el1_sp_pc
	b.eq	el1_pc
	cmp	x24, #ESR_ELx_EC_UNKNOWN	// unknown exception in EL1
	b.eq	el1_undef
	cmp	x24, #ESR_ELx_EC_BREAKPT_CUR	// debug exception in EL1
@@ -611,9 +609,11 @@ el1_da:
	bl	do_mem_abort

	kernel_exit 1
el1_sp_pc:
el1_pc:
	/*
	 * Stack or PC alignment exception handling
	 * PC alignment exception handling. We don't handle SP alignment faults,
	 * since we will have hit a recursive exception when trying to push the
	 * initial pt_regs.
	 */
	mrs	x0, far_el1
	inherit_daif	pstate=x23, tmp=x2
@@ -732,9 +732,9 @@ el0_sync:
	ccmp	x24, #ESR_ELx_EC_WFx, #4, ne
	b.eq	el0_sys
	cmp	x24, #ESR_ELx_EC_SP_ALIGN	// stack alignment exception
	b.eq	el0_sp_pc
	b.eq	el0_sp
	cmp	x24, #ESR_ELx_EC_PC_ALIGN	// pc alignment exception
	b.eq	el0_sp_pc
	b.eq	el0_pc
	cmp	x24, #ESR_ELx_EC_UNKNOWN	// unknown exception in EL0
	b.eq	el0_undef
	cmp	x24, #ESR_ELx_EC_BREAKPT_LOW	// debug exception in EL0
@@ -758,7 +758,7 @@ el0_sync_compat:
	cmp	x24, #ESR_ELx_EC_FP_EXC32	// FP/ASIMD exception
	b.eq	el0_fpsimd_exc
	cmp	x24, #ESR_ELx_EC_PC_ALIGN	// pc alignment exception
	b.eq	el0_sp_pc
	b.eq	el0_pc
	cmp	x24, #ESR_ELx_EC_UNKNOWN	// unknown exception in EL0
	b.eq	el0_undef
	cmp	x24, #ESR_ELx_EC_CP15_32	// CP15 MRC/MCR trap
@@ -858,11 +858,15 @@ el0_fpsimd_exc:
	mov	x1, sp
	bl	do_fpsimd_exc
	b	ret_to_user
el0_sp:
	ldr	x26, [sp, #S_SP]
	b	el0_sp_pc
el0_pc:
	mrs	x26, far_el1
el0_sp_pc:
	/*
	 * Stack or PC alignment exception handling
	 */
	mrs	x26, far_el1
	gic_prio_kentry_setup tmp=x0
	enable_da_f
#ifdef CONFIG_TRACE_IRQFLAGS