Ensure stack is aligned for kernel entries
Subsystems (3)
cover Ensure stack is aligned for kernel entries
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned. The entry code needs to make sure that the stack is aligned before using it to save the context.
This is only a concern when taking exception from an EL using the same SP_ELx as the handler. In other cases it can be assumed that the SP being picked up on exception entry is aligned under the condition that SP is always aligned when doing eret to an EL using a different SP.
On Juno I see a runtime difference <1% for hackbench. If I do not include the fast path@EL1 (patch 4) I see a diff of 1-2%.
For EL2 entries, a bit of clean up of stuff getting patched in the vector has been needed.
Cheers,
Julien
-->
Julien Thierry (7):
arm64: Add static check for pt_regs alignment
arm64: sdei: Always use sdei stack for sdei events
arm64: Align stack when taking exception from EL1
arm64: Add fast-path for stack alignment
arm64: Do not apply BP hardening for hyp entries from EL2
arm64: Do not apply vector harderning for hyp entries from EL2
arm64: kvm: Align stack for exception coming from EL2
arch/arm64/include/asm/assembler.h | 9 +++++ arch/arm64/include/asm/ptrace.h | 2 + arch/arm64/include/asm/sdei.h | 2 - arch/arm64/kernel/cpu_errata.c | 10 ++++- arch/arm64/kernel/entry.S | 43 +++++++++++++++++++-- arch/arm64/kernel/sdei.c | 23 ++++------- arch/arm64/kvm/hyp/hyp-entry.S | 78 +++++++++++++++++++++++++++++++------- drivers/firmware/Kconfig | 1 + 8 files changed, 132 insertions(+), 36 deletions(-)
--
1.9.1
PATCH 1/7 arm64: Add static check for pt_regs alignment
The pt_regs structure's size is required to be a multiple of 16 to maintain the stack alignment upon kernel entries.
Add a static check to ensure this is the case.
--- arch/arm64/include/asm/ptrace.h | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/include/asm/ptrace.h +2 -0
@@ -229,6 +229,8 @@ static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset)WARN_ON (offset &7 ); +BUILD_BUG_ON ((sizeof (struct pt_regs ) %16 !=0 )); + offset >>=3 ;switch (offset) { case 0 ... 30:
Signature · 1 line
1.9.1
PATCH 1/7 arm64: Add static check for pt_regs alignment
Quoted 15 lines · Julien Thierry
The
pt_regsstructure's size is required to be a multiple of 16 to maintain the stack alignment upon kernel entries.Add a static check to ensure this is the case.
Signed-off-by Julien Thierry <[email protected]>--- arch/arm64/include/asm/ptrace.h | 2 ++ 1 file changed, 2 insertions(+)arch/arm64/include/asm/ptrace.h +0
-0
arch/arm64/include/asm/ptrace.h static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset) · line 232
Quoted 4 lines
arch/arm64/include/asm/ptrace.h +1
-0@@ -229,6 +229,8 @@ static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset)WARN_ON (offset &7 ); +BUILD_BUG_ON ((sizeof (struct pt_regs ) %16 !=0 ));
This seems like a fairly random place to put this, and given that it's not dependent on context I reckon it would be better to put it in a C file rather than in a header that gets included multiple times. I still couldn't really find a good place though :/
Will
Mark Rutland
reviewerPATCH 1/7 arm64: Add static check for pt_regs alignment
Quoted 17 lines · Will Deacon
Quoted 16 lines · Julien Thierry
The
pt_regsstructure's size is required to be a multiple of 16 to maintain the stack alignment upon kernel entries.Add a static check to ensure this is the case.
Signed-off-by Julien Thierry <[email protected]>--- arch/arm64/include/asm/ptrace.h | 2 ++ 1 file changed, 2 insertions(+)arch/arm64/include/asm/ptrace.h +0
-0@@ -229,6 +229,8 @@ static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset)
Quoted 8 lines
arch/arm64/include/asm/ptrace.h static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset) · line 232
Quoted 3 lines
arch/arm64/include/asm/ptrace.h +1
-0WARN_ON (offset &7 ); +BUILD_BUG_ON ((sizeof (struct pt_regs ) %16 !=0 ));This seems like a fairly random place to put this, and given that it's not dependent on context I reckon it would be better to put it in a C file rather than in a header that gets included multiple times. I still couldn't really find a good place though :/
Perhaps asm-offsets.c, when we define S_FRAME_SIZE?
Thanks,
Mark.
PATCH 1/7 arm64: Add static check for pt_regs alignment
Quoted 20 lines · Mark Rutland
Quoted 19 lines · Will Deacon
Quoted 18 lines · Julien Thierry
The
pt_regsstructure's size is required to be a multiple of 16 to maintain the stack alignment upon kernel entries.Add a static check to ensure this is the case.
Signed-off-by Julien Thierry <[email protected]>--- arch/arm64/include/asm/ptrace.h | 2 ++ 1 file changed, 2 insertions(+)arch/arm64/include/asm/ptrace.h +0
-0@@ -229,6 +229,8 @@ static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset)WARN_ON (offset &7 );
Quoted 9 lines
Quoted 6 lines
arch/arm64/include/asm/ptrace.h static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset) · line 232
Quoted 1 line
arch/arm64/include/asm/ptrace.h +1
-0+BUILD_BUG_ON ((sizeof (struct pt_regs ) %16 !=0 ));This seems like a fairly random place to put this, and given that it's not dependent on context I reckon it would be better to put it in a C file rather than in a header that gets included multiple times. I still couldn't really find a good place though :/
Perhaps
asm-offsets.c, when we defineS_FRAME_SIZE?
That sounds like a good option to me. If Will thinks so as well I'll move that in asm-offsets.c.
Thanks,
Signature · 1 line
Julien Thierry
PATCH 1/7 arm64: Add static check for pt_regs alignment
Quoted 28 lines · Julien Thierry
Quoted 25 lines · Mark Rutland
Quoted 23 lines · Will Deacon
Quoted 15 lines · Julien Thierry
The
pt_regsstructure's size is required to be a multiple of 16 to maintain the stack alignment upon kernel entries.Add a static check to ensure this is the case.
Signed-off-by Julien Thierry <[email protected]>--- arch/arm64/include/asm/ptrace.h | 2 ++ 1 file changed, 2 insertions(+)arch/arm64/include/asm/ptrace.h +0
-0arch/arm64/include/asm/ptrace.h static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset) · line 230
Quoted 2 lines
arch/arm64/include/asm/ptrace.h +1
-0@@ -229,6 +229,8 @@ static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset)WARN_ON (offset &7 ); +BUILD_BUG_ON ((sizeof (struct pt_regs ) %16 !=0 ));This seems like a fairly random place to put this, and given that it's not dependent on context I reckon it would be better to put it in a C file rather than in a header that gets included multiple times. I still couldn't really find a good place though :/
Quoted 5 lines
Quoted 2 lines
Perhaps
asm-offsets.c, when we defineS_FRAME_SIZE?That sounds like a good option to me. If Will thinks so as well I'll move that in
asm-offsets.c.
Fine by me.
Will
PATCH 1/7 arm64: Add static check for pt_regs alignment
In reply to Julien ThierryQuoted 15 lines · Julien Thierry
The
pt_regsstructure's size is required to be a multiple of 16 to maintain the stack alignment upon kernel entries.Add a static check to ensure this is the case.
Signed-off-by Julien Thierry <[email protected]>--- arch/arm64/include/asm/ptrace.h | 2 ++ 1 file changed, 2 insertions(+)arch/arm64/include/asm/ptrace.h +0
-0
arch/arm64/include/asm/ptrace.h static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset) · line 232
Quoted 4 lines
arch/arm64/include/asm/ptrace.h +1
-0@@ -229,6 +229,8 @@ static inline u64 regs_get_register(struct pt_regs *regs, unsigned int offset)WARN_ON (offset &7 ); +BUILD_BUG_ON ((sizeof (struct pt_regs ) %16 !=0 ));
The parens inside BUILD_BUG_ON() are redundant (unless you move the closing one right after '16', which I would prefer)
Quoted 7 lines
arch/arm64/include/asm/ptrace.h +1
-1+ offset >>=3 ;switch (offset) { case 0 ... 30: --1.9.1
Wherever you manage to put this:
PATCH 2/7 arm64: sdei: Always use sdei stack for sdei events
In reply to Julien ThierrySDEI events can occur at any point, including when the stack pointer is not aligned. SP could be modified to respect alignment 16-byte alignement, but there is a need to deal with code using SP as scratch register.
Always reserve the SDEI stacks to handle its events.
Since stack allocation relies on VMAPed stacks, lets make SDEI depend on VMAP_STACK.
--- arch/arm64/include/asm/sdei.h | 2 -- arch/arm64/kernel/entry.S | 2 -- arch/arm64/kernel/sdei.c | 23 ++++++++--------------- drivers/firmware/Kconfig | 1 + 4 files changed, 9 insertions(+), 19 deletions(-)
arch/arm64/include/asm/sdei.h +0 -2
@@ -46,8 +46,6 @@ asmlinkage unsigned long __sdei_handler(struct pt_regs *regs,static inline bool on_sdei_stack (unsigned long sp,struct stack_info *info) { -if (!IS_ENABLED (CONFIG_VMAP_STACK )) -return false;if (!IS_ENABLED (CONFIG_ARM_SDE_INTERFACE ))return false;if (in_nmi ())
arch/arm64/kernel/entry.S +0 -2
@@ -1187,7 +1187,6 @@ ENTRY(__sdei_asm_handler) mov x19, x1 -#ifdef CONFIG_VMAP_STACK /* * entry.S may have been using sp as a scratch register, find whether * this is a normal or critical event and switch to the appropriate
@@ -1201,7 +1200,6 @@ ENTRY(__sdei_asm_handler) 2: mov x6, #SDEI_STACK_SIZE add x5, x5, x6 mov sp, x5 -#endif /* * We may have interrupted userspace, or a guest, or exit-from or
arch/arm64/kernel/sdei.c +8 -15
@@ -20,21 +20,16 @@unsigned long sdei_exit_mode;/* -* VMAP'd stacks checking for stack overflow on exception using sp as a scratch -* register, meaning SDEI has to switch to its own stack. We need two stacks as -* a critical event may interrupt a normal event that has just taken a -* synchronous exception, and is using sp as scratch register. For a critical -* event interrupting a normal event, we can't reliably tell if we were on the -* sdei stack. +* SDEI events could occur at a time where SP_EL1 is misaligned or invalid, a +* solution is to give SDEI its own stack. We need two stacks as a critical +* event may interrupt a normal event that has just taken a synchronous +* exception, and is using sp as scratch register. For a critical event +* interrupting a normal event, we can't reliably tell if we were on the sdei +* stack. * For now, we allocate stacks when the driver is probed. */ -DECLARE_PER_CPU(unsigned long *, sdei_stack_normal_ptr); -DECLARE_PER_CPU(unsigned long *, sdei_stack_critical_ptr); - -#ifdef CONFIG_VMAP_STACK DEFINE_PER_CPU(unsigned long *, sdei_stack_normal_ptr); DEFINE_PER_CPU(unsigned long *, sdei_stack_critical_ptr); -#endif static void _free_sdei_stack (unsigned long *__percpu *ptr,int cpu) {
@@ -150,10 +145,8 @@ unsigned long sdei_arch_get_entry_point(int conduit)return 0 ; } -if (IS_ENABLED (CONFIG_VMAP_STACK )) { -if (init_sdei_stacks ()) -return 0 ; - } +if (init_sdei_stacks ()) +return 0 ; sdei_exit_mode = (conduit ==CONDUIT_HVC ) ?SDEI_EXIT_HVC :SDEI_EXIT_SMC ;
drivers/firmware/Kconfig +1 -0
@@ -85,6 +85,7 @@ config ARM_SCPI_POWER_DOMAIN config ARM_SDE_INTERFACE bool "ARM Software Delegated Exception Interface (SDEI)" depends on ARM64 + depends on VMAP_STACK help The Software Delegated Exception Interface (SDEI) is an ARM standard for registering callbacks from the platform firmware
Signature · 1 line
1.9.1
PATCH 2/7 arm64: sdei: Always use sdei stack for sdei events
Quoted 9 lines · Julien Thierry
SDEI events can occur at any point, including when the stack pointer is not aligned. SP could be modified to respect alignment 16-byte alignement, but there is a need to deal with code using SP as scratch register.
Always reserve the SDEI stacks to handle its events.
Since stack allocation relies on VMAPed stacks, lets make SDEI depend on
VMAP_STACK.
Quoted 7 lines
Signed-off-by Julien Thierry <[email protected]>--- arch/arm64/include/asm/sdei.h | 2 -- arch/arm64/kernel/entry.S | 2 -- arch/arm64/kernel/sdei.c | 23 ++++++++--------------- drivers/firmware/Kconfig | 1 + 4 files changed, 9 insertions(+), 19 deletions(-)
One side-effect of this change is that SDEI cannot be enabled in conjunction with KASAN. James -- are you ok with that?
Will
PATCH 2/7 arm64: sdei: Always use sdei stack for sdei events
Hi guys,
Quoted 5 lines · Will Deacon
Quoted 4 lines · Julien Thierry
SDEI events can occur at any point, including when the stack pointer is not aligned. SP could be modified to respect alignment 16-byte alignement, but there is a need to deal with code using SP as scratch register.
Quoted 7 lines
Quoted 4 lines
Always reserve the SDEI stacks to handle its events.
Since stack allocation relies on VMAPed stacks, lets make SDEI depend on
VMAP_STACK.One side-effect of this change is that SDEI cannot be enabled in conjunction with KASAN. James -- are you ok with that?
So it does. I don't think this matters, the only SDEI users in the short-term can be exercised by other notifications.
I mean to make the stacks for this thing dynamically allocated (so its less of a memory hog), I can fix this KASAN hole at the same time.
Thanks,
James
PATCH 3/7 arm64: Align stack when taking exception from EL1
In reply to Julien ThierryArm64 SP needs to be aligned to 16 bytes before being used as base address for loads and stores. When taking some valid exceptions from EL1 (e.g. irq, dbg, data abort), there is no guarantee that SP_EL1 was aligned when taking the exception.
Pad the stack on EL1 entries when misaligned.
--- arch/arm64/include/asm/assembler.h | 9 +++++++++ arch/arm64/kernel/entry.S | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-)
arch/arm64/include/asm/assembler.h +9 -0
@@ -701,4 +701,13 @@ .Lyield_out_\@ : .endm +/* + * Echange content of register xt with sp. + */ + .macro xchg_sp xt + add sp, sp, \xt // sp' = sp + xt + sub \xt, sp, \xt // xt' = sp' - xt = sp + xt - xt = sp + sub sp, sp, \xt // sp'' = sp' - xt' = sp + xt - sp = xt + .endm + #endif /* __ASM_ASSEMBLER_H */
arch/arm64/kernel/entry.S +30 -2
@@ -59,6 +59,19 @@ .endr .endm + .macro force_stack_align + xchg_sp x0 + str x1, [x0] // store x1 far away from S_SP + + // aligned_sp[S_SP] = old_sp + bic x1, x0, #0xf // align down to 16-byte + str x0, [x1, #S_SP] + + ldr x1, [x0] + bic x0, x0, #0xf // x0 = aligned_sp + xchg_sp x0 + .endm + /* * Bad Abort numbers *-----------------
@@ -158,6 +171,10 @@ alternative_cb_end .if \regsize == 32 mov w0, w0 // zero upper 32 bits of x0 .endif + .if \el != 0 + force_stack_align + .endif + stp x0, x1, [sp, #16 * 0] stp x2, x3, [sp, #16 * 1] stp x4, x5, [sp, #16 * 2]
@@ -184,7 +201,8 @@ alternative_cb_end apply_ssbd 1, x22, x23 .else - add x21, sp, #S_FRAME_SIZE + ldr x21, [sp, #S_SP] + add x21, x21, #S_FRAME_SIZE // adjust stored sp get_thread_info tsk /* Save the task's original addr_limit and set USER_DS */ ldr x20, [tsk, #TSK_TI_ADDR_LIMIT]
@@ -327,7 +345,6 @@ alternative_else_nop_endif msr elr_el1, x21 // set up the return data msr spsr_el1, x22 - ldp x0, x1, [sp, #16 * 0] ldp x2, x3, [sp, #16 * 1] ldp x4, x5, [sp, #16 * 2] ldp x6, x7, [sp, #16 * 3]
@@ -343,7 +360,18 @@ alternative_else_nop_endif ldp x26, x27, [sp, #16 * 13] ldp x28, x29, [sp, #16 * 14] ldr lr, [sp, #S_LR] + + /* Restore x0, x1 and sp */ + .if \el != 0 + mov x1, sp + ldr x0, [sp, #S_SP] + mov sp, x0 + ldp x0, x1, [x1, #16 * 0] + .else + ldp x0, x1, [sp, #16 * 0] add sp, sp, #S_FRAME_SIZE // restore sp + .endif + /* * ARCH_HAS_MEMBARRIER_SYNC_CORE rely on eret context synchronization * when returning from IPI handler, and when returning to user-space.
Signature · 1 line
1.9.1
PATCH 3/7 arm64: Align stack when taking exception from EL1
Quoted 18 lines · Julien Thierry
Arm64 SP needs to be aligned to 16 bytes before being used as base address for loads and stores. When taking some valid exceptions from EL1 (e.g. irq, dbg, data abort), there is no guarantee that
SP_EL1was aligned when taking the exception.Pad the stack on EL1 entries when misaligned.
Signed-off-by Julien Thierry <[email protected]>--- arch/arm64/include/asm/assembler.h | 9 +++++++++ arch/arm64/kernel/entry.S | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-)arch/arm64/include/asm/assembler.h +0
-0
arch/arm64/include/asm/assembler.h line 705
Quoted 5 lines
arch/arm64/include/asm/assembler.h +2
-0@@ -701,4 +701,13 @@ .Lyield_out_\@ : .endm +/* +* Echange content of register xt with sp.
Exchange contents of register Xt with SP
arch/arm64/include/asm/assembler.h line 711
Quoted 6 lines
arch/arm64/include/asm/assembler.h +6
-0+*/ + .macro xchg_sp xt + add sp, sp, \xt // sp' = sp + xt + sub \xt, sp, \xt // xt' = sp' - xt = sp + xt - xt = sp + sub sp, sp, \xt // sp'' = sp' - xt' = sp + xt - sp = xt + .endm
Having said that, this is clearly inspired by the code in kernel_ventry for dealing with stack overflow, yet the macro you've got here cannot be reused there.
Maybe we're better off only macro-ising:
.macro sp_fetch_add xt add sp, sp, \xt sub \xt, sp, \xt .endm
and then letting the callers handle the rest, or build an swizzle_sp macro on top of it?
arch/arm64/kernel/entry.S line 64
Quoted 13 lines
arch/arm64/include/asm/assembler.h +1
-0+#endif /* __ASM_ASSEMBLER_H */ arch/arm64/kernel/entry.S +3
-0@@ -59,6 +59,19 @@ .endr .endm + .macro force_stack_align + xchg_sp x0 + str x1, [x0] // store x1 far away from S_SP
So this temporarily trashes pt_regs.regs[0] if the stack is already aligned, right? I think that's fine, but we should comment /that/ rather than vaguely saying it's far away from S_SP. In fact, having a block comment above this macro saying exactly what is clobbered would generally be a good idea (esp as you nobble the flags in your next patch).
Quoted 25 lines
arch/arm64/kernel/entry.S +14
-0+ + // aligned_sp[S_SP] = old_sp + bic x1, x0, #0xf // align down to 16-byte + str x0, [x1, #S_SP] + + ldr x1, [x0] + bic x0, x0, #0xf // x0 = aligned_sp + xchg_sp x0 + .endm + /* * Bad Abort numbers *-----------------@@ -158,6 +171,10 @@ alternative_cb_end .if \regsize == 32 mov w0, w0 // zero upper 32 bits of x0 .endif + .if \el != 0 + force_stack_align + .endif + stp x0, x1, [sp, #16 * 0] stp x2, x3, [sp, #16 * 1] stp x4, x5, [sp, #16 * 2]
arch/arm64/kernel/entry.S alternative_cb_end · line 205
Quoted 6 lines
arch/arm64/kernel/entry.S +2
-1@@ -184,7 +201,8 @@ alternative_cb_end apply_ssbd 1, x22, x23 .else - add x21, sp, #S_FRAME_SIZE + ldr x21, [sp, #S_SP] + add x21, x21, #S_FRAME_SIZE // adjust stored sp
Can we not just store the corrected SP in force_stack_align, rather than store something bogus and then have to add the frame size back here?
Will
PATCH 3/7 arm64: Align stack when taking exception from EL1
Quoted 40 lines · Will Deacon
Quoted 18 lines · Julien Thierry
Arm64 SP needs to be aligned to 16 bytes before being used as base address for loads and stores. When taking some valid exceptions from EL1 (e.g. irq, dbg, data abort), there is no guarantee that
SP_EL1was aligned when taking the exception.Pad the stack on EL1 entries when misaligned.
Signed-off-by Julien Thierry <[email protected]>--- arch/arm64/include/asm/assembler.h | 9 +++++++++ arch/arm64/kernel/entry.S | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-)arch/arm64/include/asm/assembler.h +0
-0arch/arm64/include/asm/assembler.h line 705
Quoted 5 lines
arch/arm64/include/asm/assembler.h +2
-0@@ -701,4 +701,13 @@ .Lyield_out_\@ : .endm +/* +* Echange content of register xt with sp. Exchange contents of register Xt with SP
arch/arm64/include/asm/assembler.h line 711
Quoted 6 lines
arch/arm64/include/asm/assembler.h +6
-0+*/ + .macro xchg_sp xt + add sp, sp, \xt // sp' = sp + xt + sub \xt, sp, \xt // xt' = sp' - xt = sp + xt - xt = sp + sub sp, sp, \xt // sp'' = sp' - xt' = sp + xt - sp = xt + .endmHaving said that, this is clearly inspired by the code in
kernel_ventryfor dealing with stack overflow, yet the macro you've got here cannot be reused there.Maybe we're better off only macro-ising:
Quoted 8 lines
.macro sp_fetch_add xt add sp, sp, \xt sub \xt, sp, \xt .endmand then letting the callers handle the rest, or build an
swizzle_spmacro on top of it?
Hmm, I'll try to do that and see how it looks.
Quoted 10 lines
Quoted 10 lines
arch/arm64/include/asm/assembler.h +1
-0+#endif /* __ASM_ASSEMBLER_H */ arch/arm64/kernel/entry.S +0
-0@@ -59,6 +59,19 @@ .endr .endm
Quoted 10 lines
arch/arm64/kernel/entry.S line 64
Quoted 3 lines
arch/arm64/kernel/entry.S +3
-0+ .macro force_stack_align + xchg_sp x0 + str x1, [x0] // store x1 far away from S_SPSo this temporarily trashes pt_regs.regs[0] if the stack is already aligned, right? I think that's fine, but we should comment /that/ rather than vaguely saying it's far away from
S_SP. In fact, having a block comment above this macro saying exactly what is clobbered would generally be a good idea (esp as you nobble the flags in your next patch).
Is it a big deal to trash pt_regs.regs[0] if the stack is already aligned? This is a freshly allocated stack frame, and we expect pt_regs.regs[0] to be overwritten afterwards.
I don't mind adding a comment about that, I'm just wondering about the relevance of it.
However, I do agree that I should add a comment about what this does with pt_regs.sp since the code using that macro needs to be aware of it.
Quoted 27 lines
Quoted 27 lines
arch/arm64/kernel/entry.S +14
-0+ + // aligned_sp[S_SP] = old_sp + bic x1, x0, #0xf // align down to 16-byte + str x0, [x1, #S_SP] + + ldr x1, [x0] + bic x0, x0, #0xf // x0 = aligned_sp + xchg_sp x0 + .endm + /* * Bad Abort numbers *-----------------@@ -158,6 +171,10 @@ alternative_cb_end .if \regsize == 32 mov w0, w0 // zero upper 32 bits of x0 .endif + .if \el != 0 + force_stack_align + .endif + stp x0, x1, [sp, #16 * 0] stp x2, x3, [sp, #16 * 1] stp x4, x5, [sp, #16 * 2]@@ -184,7 +201,8 @@ alternative_cb_end apply_ssbd 1, x22, x23
Quoted 7 lines
arch/arm64/kernel/entry.S alternative_cb_end · line 205
Quoted 4 lines
arch/arm64/kernel/entry.S +2
-1.else - add x21, sp, #S_FRAME_SIZE + ldr x21, [sp, #S_SP] + add x21, x21, #S_FRAME_SIZE // adjust stored spCan we not just store the corrected SP in
force_stack_align, rather than store something bogus and then have to add the frame size back here?
We can, it would add 2 instructions to the alignment macro. I think I mainly tried to keep the alignment stuff short in case we want to add the fast path from the next patch, but if we're keeping it anyway we might as well add the code to save the correct SP.
Thanks,
Signature · 1 line
Julien Thierry
PATCH 4/7 arm64: Add fast-path for stack alignment
In reply to Julien ThierryAvoiding stack alignment for already aligned stack can give a small performance boost.
Branch out of the aligning code when the stack is known to be aligned.
--- arch/arm64/kernel/entry.S | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/arm64/kernel/entry.S +9 -0
@@ -61,6 +61,10 @@ .macro force_stack_align xchg_sp x0 + + tst x0, #0xf + b.eq 0f + str x1, [x0] // store x1 far away from S_SP // aligned_sp[S_SP] = old_sp
@@ -69,6 +73,11 @@ ldr x1, [x0] bic x0, x0, #0xf // x0 = aligned_sp + b 1f + +0: + str x0, [x0, #S_SP] +1: xchg_sp x0 .endm
Signature · 1 line
1.9.1
PATCH 4/7 arm64: Add fast-path for stack alignment
Quoted 26 lines · Julien Thierry
Avoiding stack alignment for already aligned stack can give a small performance boost.
Branch out of the aligning code when the stack is known to be aligned.
Signed-off-by Julien Thierry <[email protected]>--- arch/arm64/kernel/entry.S | 9 +++++++++ 1 file changed, 9 insertions(+)arch/arm64/kernel/entry.S +4
-0@@ -61,6 +61,10 @@ .macro force_stack_align xchg_sp x0 + + tst x0, #0xf + b.eq 0f + str x1, [x0] // store x1 far away from S_SP // aligned_sp[S_SP] = old_sp
arch/arm64/kernel/entry.S line 80
Quoted 8 lines
arch/arm64/kernel/entry.S +5
-0@@ -69,6 +73,11 @@ ldr x1, [x0] bic x0, x0, #0xf // x0 = aligned_sp + b 1f + +0: + str x0, [x0, #S_SP] +1:
I couldn't figure out a better way to do this, but please remove the empty lines that you're adding here. With that:
Will
PATCH 4/7 arm64: Add fast-path for stack alignment
Quoted 28 lines · Will Deacon
Quoted 27 lines · Julien Thierry
Avoiding stack alignment for already aligned stack can give a small performance boost.
Branch out of the aligning code when the stack is known to be aligned.
Signed-off-by Julien Thierry <[email protected]>--- arch/arm64/kernel/entry.S | 9 +++++++++ 1 file changed, 9 insertions(+)arch/arm64/kernel/entry.S +4
-0@@ -61,6 +61,10 @@ .macro force_stack_align xchg_sp x0 + + tst x0, #0xf + b.eq 0f + str x1, [x0] // store x1 far away from S_SP // aligned_sp[S_SP] = old_sp@@ -69,6 +73,11 @@
Quoted 11 lines
arch/arm64/kernel/entry.S line 80
Quoted 7 lines
arch/arm64/kernel/entry.S +5
-0ldr x1, [x0] bic x0, x0, #0xf // x0 = aligned_sp + b 1f + +0: + str x0, [x0, #S_SP] +1:I couldn't figure out a better way to do this, but please remove the empty lines that you're adding here. With that:
Sure, I'll do that.
Quoted 2 lines
Acked-by Will Deacon <[email protected]>
Thanks,
Signature · 1 line
Julien Thierry
PATCH 5/7 arm64: Do not apply BP hardening for hyp entries from EL2
In reply to Julien ThierryWhen an EL2 entry of __kvm_hyp_vector is taken, it means an entry from a lower EL was previously taken to exit the guest. Taking that lower EL entry already applied BP hardening if it was needed, so there is no need to do it again.
Only apply BP hardening for exception coming from lower EL.
--- arch/arm64/kernel/cpu_errata.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
arch/arm64/kernel/cpu_errata.c +8 -2
@@ -103,10 +103,16 @@ static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,void *dst =lm_alias (__bp_harden_hyp_vecs_start + slot *SZ_2K );int i; -for (i =0 ; i <SZ_2K ; i +=0x80 ) +/* +* Only overwrite hyp entries for exceptions from lower EL. +* Exception vection vector is 2K bytes, first 1K bytes concern +* exception from EL2 (EL2t, EL2h), last 1K concert lower exception +* levels (ELx-64bits, ELx-32bits). +*/ +for (i =SZ_1K ; i <SZ_2K ; i +=0x80 )memcpy (dst + i, hyp_vecs_start, hyp_vecs_end - hyp_vecs_start); -__flush_icache_range ((uintptr_t )dst, (uintptr_t )dst +SZ_2K ); +__flush_icache_range ((uintptr_t )dst +SZ_1K , (uintptr_t )dst +SZ_2K ); } static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
--
1.9.1
Re: [PATCH 5/7] arm64: Do not apply BP hardening for hyp entries from EL2
Quoted 24 lines · Julien Thierry
When an EL2 entry of
__kvm_hyp_vectoris taken, it means an entry from a lower EL was previously taken to exit the guest. Taking that lower EL entry already applied BP hardening if it was needed, so there is no need to do it again.Only apply BP hardening for exception coming from lower EL.
Signed-off-by Julien Thierry <[email protected]>Cc kvmarm at lists.cs.columbia.edu--- arch/arm64/kernel/cpu_errata.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)arch/arm64/kernel/cpu_errata.c +2
-1@@ -103,10 +103,16 @@ static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,void *dst =lm_alias (__bp_harden_hyp_vecs_start + slot *SZ_2K );int i; -for (i =0 ; i <SZ_2K ; i +=0x80 ) +/* +* Only overwrite hyp entries for exceptions from lower EL.
arch/arm64/kernel/cpu_errata.c static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, · line 116
Quoted 10 lines
arch/arm64/kernel/cpu_errata.c +6
-1+* Exception vection vector is 2K bytes, first 1K bytes concern +* exception from EL2 (EL2t, EL2h), last 1K concert lower exception +* levels (ELx-64bits, ELx-32bits). +*/ +for (i =SZ_1K ; i <SZ_2K ; i +=0x80 )memcpy (dst + i, hyp_vecs_start, hyp_vecs_end - hyp_vecs_start); -__flush_icache_range ((uintptr_t )dst, (uintptr_t )dst +SZ_2K ); +__flush_icache_range ((uintptr_t )dst +SZ_1K , (uintptr_t )dst +SZ_2K ); }
I'd personally find this clearer if you did:
dst += SZ_1K;
before the for loop and with your comment above it. Then the for loop becomes:
for (i = 0; i < SZ_1K; i += 0x80)
and the range of the cache maintenance is [dst, dst + SZ_1K)
But I'll leave it up to Marc.
Will
Re: [PATCH 5/7] arm64: Do not apply BP hardening for hyp entries from EL2
Quoted 38 lines · Will Deacon
Quoted 24 lines · Julien Thierry
When an EL2 entry of
__kvm_hyp_vectoris taken, it means an entry from a lower EL was previously taken to exit the guest. Taking that lower EL entry already applied BP hardening if it was needed, so there is no need to do it again.Only apply BP hardening for exception coming from lower EL.
Signed-off-by Julien Thierry <[email protected]>Cc kvmarm at lists.cs.columbia.edu--- arch/arm64/kernel/cpu_errata.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)arch/arm64/kernel/cpu_errata.c +2
-1@@ -103,10 +103,16 @@ static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,void *dst =lm_alias (__bp_harden_hyp_vecs_start + slot *SZ_2K );int i; -for (i =0 ; i <SZ_2K ; i +=0x80 ) +/* +* Only overwrite hyp entries for exceptions from lower EL. arch/arm64/kernel/cpu_errata.c static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, · line 116
Quoted 10 lines
arch/arm64/kernel/cpu_errata.c +6
-1+* Exception vection vector is 2K bytes, first 1K bytes concern +* exception from EL2 (EL2t, EL2h), last 1K concert lower exception +* levels (ELx-64bits, ELx-32bits). +*/ +for (i =SZ_1K ; i <SZ_2K ; i +=0x80 )memcpy (dst + i, hyp_vecs_start, hyp_vecs_end - hyp_vecs_start); -__flush_icache_range ((uintptr_t )dst, (uintptr_t )dst +SZ_2K ); +__flush_icache_range ((uintptr_t )dst +SZ_1K , (uintptr_t )dst +SZ_2K ); }I'd personally find this clearer if you did:
Quoted 10 lines
dst += SZ_1K;before the for loop and with your comment above it. Then the for loop becomes:
for (i = 0; i < SZ_1K; i += 0x80)and the range of the cache maintenance is [dst, dst +
SZ_1K)Quoted 1 line
But I'll leave it up to Marc.
I'd say I agree with your suggestion, so unless Marc finds it better in the current state, I'll make the change.
Thanks,
Signature · 1 line
Julien Thierry
PATCH 6/7 arm64: Do not apply vector harderning for hyp entries from EL2
In reply to Julien ThierryWhen an EL2 entry of __kvm_hyp_vector is taken, it means an entry from a lower EL was previously taken to exit the guest. Taking that lower EL entry already applied vector hardening if needed, so there is no need to do it again.
Only apply vector hardening for exception coming from lower EL.
--- arch/arm64/kvm/hyp/hyp-entry.S | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
arch/arm64/kvm/hyp/hyp-entry.S +14 -3
@@ -257,7 +257,15 @@ ENTRY(__kvm_hyp_vector) ENDPROC(__kvm_hyp_vector) #ifdef CONFIG_KVM_INDIRECT_VECTORS -.macro hyp_ventry +.macro hyp_el2_ventry + .align 7 +1: b __kvm_hyp_vector + (1b - 0b) + .rept 31 + nop + .endr +.endm + +.macro hyp_el1_ventry .align 7 1: .rept 27 nop
@@ -290,8 +298,11 @@ alternative_cb_end .macro generate_vectors 0: - .rept 16 - hyp_ventry + .rept 8 + hyp_el2_ventry + .endr + .rept 8 + hyp_el1_ventry .endr .org 0b + SZ_2K // Safety measure .endm
--
1.9.1
Re: [PATCH 6/7] arm64: Do not apply vector harderning for hyp entries from EL2
arch/arm64/kvm/hyp/hyp-entry.S alternative_cb_end
Quoted 35 lines · Julien Thierry
When an EL2 entry of
__kvm_hyp_vectoris taken, it means an entry from a lower EL was previously taken to exit the guest. Taking that lower EL entry already applied vector hardening if needed, so there is no need to do it again.Only apply vector hardening for exception coming from lower EL.
Signed-off-by Julien Thierry <[email protected]>Cc kvmarm at lists.cs.columbia.edu--- arch/arm64/kvm/hyp/hyp-entry.S | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)arch/arm64/kvm/hyp/hyp-entry.S +9
-1@@ -257,7 +257,15 @@ ENTRY(__kvm_hyp_vector) ENDPROC(__kvm_hyp_vector) #ifdef CONFIG_KVM_INDIRECT_VECTORS -.macro hyp_ventry +.macro hyp_el2_ventry + .align 7 +1: b __kvm_hyp_vector + (1b - 0b) + .rept 31 + nop + .endr +.endm + +.macro hyp_el1_ventry .align 7 1: .rept 27 nop@@ -290,8 +298,11 @@ alternative_cb_end
I think it would be cleaner to take the EL as a macro parameter, but again, I defer to Marc and Christoffer.
Will
Re: [PATCH 6/7] arm64: Do not apply vector harderning for hyp entries from EL2
Quoted 31 lines · Will Deacon
Quoted 30 lines · Julien Thierry
When an EL2 entry of
__kvm_hyp_vectoris taken, it means an entry from a lower EL was previously taken to exit the guest. Taking that lower EL entry already applied vector hardening if needed, so there is no need to do it again.Only apply vector hardening for exception coming from lower EL.
Signed-off-by Julien Thierry <[email protected]>Cc kvmarm at lists.cs.columbia.edu--- arch/arm64/kvm/hyp/hyp-entry.S | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)arch/arm64/kvm/hyp/hyp-entry.S +8
-1@@ -257,7 +257,15 @@ ENTRY(__kvm_hyp_vector) ENDPROC(__kvm_hyp_vector) #ifdef CONFIG_KVM_INDIRECT_VECTORS -.macro hyp_ventry +.macro hyp_el2_ventry + .align 7 +1: b __kvm_hyp_vector + (1b - 0b) + .rept 31 + nop + .endr +.endm +
Quoted 8 lines
arch/arm64/kvm/hyp/hyp-entry.S alternative_cb_end
Quoted 5 lines
arch/arm64/kvm/hyp/hyp-entry.S +1
-0+.macro hyp_el1_ventry .align 7 1: .rept 27 nop@@ -290,8 +298,11 @@ alternative_cb_endI think it would be cleaner to take the EL as a macro parameter, but again, I defer to Marc and Christoffer.
I'd argue they don't have much in common here. Unless I put the branch for the el2 ventry after 27 nops like for the el1, we wouldn't gain much from putting the two in the same macro IMO.
I'll see what Marc and Christoffer think about it.
Thanks,
Signature · 1 line
Julien Thierry
PATCH 7/7 arm64: kvm: Align stack for exception coming from EL2
In reply to Julien ThierrySP needs to be 16-bytes aligned before accessing memory through it. When handling exceptions from EL2, there is no guarantee that SP is already aligned.
Ensure SP is aligned upon entries from EL2.
--- arch/arm64/kvm/hyp/hyp-entry.S | 63 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 11 deletions(-)
arch/arm64/kvm/hyp/hyp-entry.S +52 -11
@@ -184,6 +184,10 @@ el2_error: ccmp x0, x1, #4, ne b.ne __hyp_panic mov x0, #(1 << ARM_EXIT_WITH_SERROR_BIT) + + /* Restore the stack */ + ldr x1, [sp] + mov sp, x1 eret ENTRY(__hyp_do_panic)
@@ -221,29 +225,66 @@ ENDPROC(\label) .align 11 -.macro valid_vect target +/* + * Aligns the stack and stores the old sp value. This is what the stack + * looks like after this code: + * + * +--------+ + * | | + * |--------|--> old_sp (upon entry) + * | x1 |--> (only used for local save/restore) + * |--------|--> old_sp - 8 + * | |--> padding + * |--------|--> aligned_sp + 8 + * | old_sp | + * |--------|--> sp = aligned_sp + * | | + * +--------+ + */ +.macro align_sp_el2 + xchg_sp x0 + str x1, [x0, #-8] // save x1 + mov x1, x0 // x1 = old_sp + sub x0, x0, #0x10 // save space for x1 + old_sp + bic x0, x0, #0xf // align down to 16-bytes + xchg_sp x0 + str x1, [sp] // save old_sp + ldr x1, [x1, #-8] +.endm + +.macro valid_vect target, el=1 .align 7 + .if \el == 2 + align_sp_el2 + .endif + stp x0, x1, [sp, #-16]! b \target .endm -.macro invalid_vect target +.macro invalid_vect target, el=1 .align 7 + .if \el == 2 + align_sp_el2 + .endif + b \target + .if \el == 1 ldp x0, x1, [sp], #16 b \target + .endif .endm ENTRY(__kvm_hyp_vector) - invalid_vect el2t_sync_invalid // Synchronous EL2t - invalid_vect el2t_irq_invalid // IRQ EL2t - invalid_vect el2t_fiq_invalid // FIQ EL2t - invalid_vect el2t_error_invalid // Error EL2t - - invalid_vect el2h_sync_invalid // Synchronous EL2h - invalid_vect el2h_irq_invalid // IRQ EL2h - invalid_vect el2h_fiq_invalid // FIQ EL2h - valid_vect el2_error // Error EL2h + invalid_vect el2t_sync_invalid, 2 // Synchronous EL2t + invalid_vect el2t_irq_invalid, 2 // IRQ EL2t + invalid_vect el2t_fiq_invalid, 2 // FIQ EL2t + invalid_vect el2t_error_invalid, 2 // Error EL2t + + invalid_vect el2h_sync_invalid, 2 // Synchronous EL2h + invalid_vect el2h_irq_invalid, 2 // IRQ EL2h + invalid_vect el2h_fiq_invalid, 2 // FIQ EL2h + valid_vect el2_error, 2 // Error EL2h valid_vect el1_sync // Synchronous 64-bit EL1 valid_vect el1_irq // IRQ 64-bit EL1
--
1.9.1
cover Ensure stack is aligned for kernel entries
In reply to Julien ThierryGentle ping on this series.
Quoted 47 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned. The entry code needs to make sure that the stack is aligned before using it to save the context.
This is only a concern when taking exception from an EL using the same
SP_ELxas the handler. In other cases it can be assumed that the SP being picked up on exception entry is aligned under the condition that SP is always aligned when doing eret to an EL using a different SP.On Juno I see a runtime difference <1% for hackbench. If I do not include the fast path at EL1 (patch 4) I see a diff of 1-2%.
For EL2 entries, a bit of clean up of stuff getting patched in the vector has been needed.
Cheers,
Julien
-->
Julien Thierry (7):
arm64: Add static check forpt_regsalignment
arm64: sdei: Always use sdei stack for sdei events
arm64: Align stack when taking exception from EL1
arm64: Add fast-path for stack alignment
arm64: Do not apply BP hardening for hyp entries from EL2
arm64: Do not apply vector harderning for hyp entries from EL2
arm64: kvm: Align stack for exception coming from EL2arch/arm64/include/asm/assembler.h | 9 +++++ arch/arm64/include/asm/ptrace.h | 2 + arch/arm64/include/asm/sdei.h | 2 - arch/arm64/kernel/cpu_errata.c | 10 ++++- arch/arm64/kernel/entry.S | 43 +++++++++++++++++++-- arch/arm64/kernel/sdei.c | 23 ++++------- arch/arm64/kvm/hyp/hyp-entry.S | 78 +++++++++++++++++++++++++++++++------- drivers/firmware/Kconfig | 1 + 8 files changed, 132 insertions(+), 36 deletions(-)--
1.9.1
Signature · 1 line
Julien Thierry
cover Ensure stack is aligned for kernel entries
In reply to Julien ThierryHi Julien,
Quoted 5 lines · Julien Thierry
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned. The entry code needs to make sure that the stack is aligned before using it to save the context.
Do you know what we haven't had reports of this crashing? Is it because GCC tends to keep the SP aligned anyway, so we're getting away with it for the moment? Trying to work out whether this is a candidate for -stable.
Cheers,
Will
cover Ensure stack is aligned for kernel entries
Hi Will,
Quoted 9 lines · Will Deacon
Hi Julien,
Quoted 5 lines · Julien Thierry
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned. The entry code needs to make sure that the stack is aligned before using it to save the context.
Quoted 4 lines
Do you know what we haven't had reports of this crashing? Is it because GCC tends to keep the SP aligned anyway, so we're getting away with it for the moment? Trying to work out whether this is a candidate for -stable.
I think that GCC tends to keep the SP aligned anyway is the most likely explanation, yes.
I tried looking for specific options that could make this more likely, but all I could find was the option -mpreferred-stack-boundary only available for x86 and -mstack-alignment only provided by clang.
Couldn't find anything yet on the gcc arm64 side that would either guarantee we'd have an aligned stack nor that GCC would make it very very likely.
I can try to investigate a bit more.
Thanks,
Signature · 1 line
Julien Thierry
cover Ensure stack is aligned for kernel entries
In reply to Julien ThierryQuoted 5 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Quoted 47 lines
The
entry code needs to make sure that the stack is aligned before using it to save the context.This is only a concern when taking exception from an EL using the same
SP_ELxas the handler. In other cases it can be assumed that the SP being picked up on exception entry is aligned under the condition that SP is always aligned when doing eret to an EL using a different SP.On Juno I see a runtime difference <1% for hackbench. If I do not include the fast path at EL1 (patch 4) I see a diff of 1-2%.
For EL2 entries, a bit of clean up of stuff getting patched in the vector has been needed.
Cheers,
Julien
-->
Julien Thierry (7):
arm64: Add static check forpt_regsalignment
arm64: sdei: Always use sdei stack for sdei events
arm64: Align stack when taking exception from EL1
arm64: Add fast-path for stack alignment
arm64: Do not apply BP hardening for hyp entries from EL2
arm64: Do not apply vector harderning for hyp entries from EL2
arm64: kvm: Align stack for exception coming from EL2arch/arm64/include/asm/assembler.h | 9 +++++ arch/arm64/include/asm/ptrace.h | 2 + arch/arm64/include/asm/sdei.h | 2 - arch/arm64/kernel/cpu_errata.c | 10 ++++- arch/arm64/kernel/entry.S | 43 +++++++++++++++++++-- arch/arm64/kernel/sdei.c | 23 ++++------- arch/arm64/kvm/hyp/hyp-entry.S | 78 +++++++++++++++++++++++++++++++------- drivers/firmware/Kconfig | 1 + 8 files changed, 132 insertions(+), 36 deletions(-)--
1.9.1_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
cover Ensure stack is aligned for kernel entries
Quoted 12 lines · Ard Biesheuvel
Quoted 5 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Is there anything that actually gives us that guarantee from GCC? I agree that currently it looks like aarch64-<...>-gcc only manipulates SP aligned to 16 bytes, but I don't know whether that is certain.
The series can be dropped if there is enough confidence that this won't happen.
Thanks,
Quoted 48 lines
Quoted 48 lines
The
entry code needs to make sure that the stack is aligned before using it to save the context.This is only a concern when taking exception from an EL using the same
SP_ELxas the handler. In other cases it can be assumed that the SP being picked up on exception entry is aligned under the condition that SP is always aligned when doing eret to an EL using a different SP.On Juno I see a runtime difference <1% for hackbench. If I do not include the fast path at EL1 (patch 4) I see a diff of 1-2%.
For EL2 entries, a bit of clean up of stuff getting patched in the vector has been needed.
Cheers,
Julien
-->
Julien Thierry (7):
arm64: Add static check forpt_regsalignment
arm64: sdei: Always use sdei stack for sdei events
arm64: Align stack when taking exception from EL1
arm64: Add fast-path for stack alignment
arm64: Do not apply BP hardening for hyp entries from EL2
arm64: Do not apply vector harderning for hyp entries from EL2
arm64: kvm: Align stack for exception coming from EL2arch/arm64/include/asm/assembler.h | 9 +++++ arch/arm64/include/asm/ptrace.h | 2 + arch/arm64/include/asm/sdei.h | 2 - arch/arm64/kernel/cpu_errata.c | 10 ++++- arch/arm64/kernel/entry.S | 43 +++++++++++++++++++-- arch/arm64/kernel/sdei.c | 23 ++++------- arch/arm64/kvm/hyp/hyp-entry.S | 78 +++++++++++++++++++++++++++++++------- drivers/firmware/Kconfig | 1 + 8 files changed, 132 insertions(+), 36 deletions(-)--
1.9.1_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 1 line
Julien Thierry
cover Ensure stack is aligned for kernel entries
(+ Ramana)
Quoted 20 lines · Julien Thierry
Quoted 11 lines · Ard Biesheuvel
Quoted 6 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
Quoted 5 lines
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Quoted 4 lines
Is there anything that actually gives us that guarantee from GCC? I agree that currently it looks like aarch64-<...>-gcc only manipulates SP aligned to 16 bytes, but I don't know whether that is certain.
I think we should get that clarified then. I don't think it makes sense for GCC to have to reason about whether SP currently has a value that permits dereferencing.
Quoted 60 lines
The series can be dropped if there is enough confidence that this won't happen.
Thanks,
Quoted 43 lines
Quoted 43 lines
The
entry code needs to make sure that the stack is aligned before using it to
save the context.This is only a concern when taking exception from an EL using the same
SP_ELxas the handler. In other cases it can be assumed that the SP being picked up on exception entry is aligned under the condition that SP is always aligned when doing eret to an EL using a different SP.On Juno I see a runtime difference <1% for hackbench. If I do not include the fast path at EL1 (patch 4) I see a diff of 1-2%.
For EL2 entries, a bit of clean up of stuff getting patched in the vector has been needed.
Cheers,
Julien
-->
Julien Thierry (7):
arm64: Add static check forpt_regsalignment
arm64: sdei: Always use sdei stack for sdei events
arm64: Align stack when taking exception from EL1
arm64: Add fast-path for stack alignment
arm64: Do not apply BP hardening for hyp entries from EL2
arm64: Do not apply vector harderning for hyp entries from EL2
arm64: kvm: Align stack for exception coming from EL2arch/arm64/include/asm/assembler.h | 9 +++++ arch/arm64/include/asm/ptrace.h | 2 + arch/arm64/include/asm/sdei.h | 2 - arch/arm64/kernel/cpu_errata.c | 10 ++++- arch/arm64/kernel/entry.S | 43 +++++++++++++++++++-- arch/arm64/kernel/sdei.c | 23 ++++------- arch/arm64/kvm/hyp/hyp-entry.S | 78 +++++++++++++++++++++++++++++++------- drivers/firmware/Kconfig | 1 + 8 files changed, 132 insertions(+), 36 deletions(-)Quoted 7 lines
Quoted 7 lines
--
1.9.1_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel--
Julien Thierry
cover Ensure stack is aligned for kernel entries
Quoted 23 lines · Ard Biesheuvel
(+ Ramana)
Quoted 20 lines · Julien Thierry
Quoted 16 lines · Ard Biesheuvel
Quoted 6 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Quoted 8 lines
Quoted 4 lines
Is there anything that actually gives us that guarantee from GCC? I agree that currently it looks like aarch64-<...>-gcc only manipulates SP aligned to 16 bytes, but I don't know whether that is certain.
I think we should get that clarified then. I don't think it makes sense for GCC to have to reason about whether SP currently has a value that permits dereferencing.
The ABI gives that guarantee.
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
<quote>
5.2.2.1 Universal stack constraints
<...>
Additionally, at any point at which memory is accessed via SP, the hardware requires that SP mod 16 = 0. The stack must be quad-word aligned
</end quote>
regards
Ramana
cover Ensure stack is aligned for kernel entries
Quoted 41 lines · Ramana Radhakrishnan
Quoted 23 lines · Ard Biesheuvel
(+ Ramana)
Quoted 20 lines · Julien Thierry
Quoted 16 lines · Ard Biesheuvel
Quoted 6 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Quoted 8 lines
Quoted 4 lines
Is there anything that actually gives us that guarantee from GCC? I agree that currently it looks like aarch64-<...>-gcc only manipulates SP aligned to 16 bytes, but I don't know whether that is certain.
I think we should get that clarified then. I don't think it makes sense for GCC to have to reason about whether SP currently has a value that permits dereferencing.
The ABI gives that guarantee.
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
<quote>
5.2.2.1 Universal stack constraints
Quoted 8 lines
<...>
Additionally, at any point at which memory is accessed via SP, the hardware requires that SP mod 16 = 0. The stack must be quad-word aligned
</end quote>
Thanks Ramana. Sadly I don't think this clarifies things. The issue is that the guarantee is only that SP is aligned when we will use it to access memory, but still allows for a scenario like:
-> Updating SP with non 16bytes-aligned value (it's fine as long as the following code takes care to align it before accessing memory) -> IRQ is raised before SP gets aligned
-> Vector entry starts saving context on misaligned stack
-> Misaligned SP exception
The only thing that would avoid us the trouble is a guarantee that GCC never modifies SP in such a way that SP is not 16-bytes aligned.
Thanks,
Signature · 1 line
Julien Thierry
cover Ensure stack is aligned for kernel entries
Quoted 50 lines · Julien Thierry
Quoted 47 lines · Ramana Radhakrishnan
Quoted 23 lines · Ard Biesheuvel
(+ Ramana)
Quoted 20 lines · Julien Thierry
Quoted 16 lines · Ard Biesheuvel
Quoted 6 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Quoted 8 lines
Quoted 4 lines
Is there anything that actually gives us that guarantee from GCC? I agree that currently it looks like aarch64-<...>-gcc only manipulates SP aligned to 16 bytes, but I don't know whether that is certain.
I think we should get that clarified then. I don't think it makes sense for GCC to have to reason about whether SP currently has a value that permits dereferencing.
The ABI gives that guarantee.
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
<quote>
5.2.2.1 Universal stack constraints
<...>
Additionally, at any point at which memory is accessed via SP, the hardware requires that SP mod 16 = 0. The stack must be quad-word aligned
Quoted 6 lines
Quoted 2 lines
</end quote>
Thanks Ramana. Sadly I don't think this clarifies things. The issue is that the guarantee is only that SP is aligned when we will use it to access memory, but still allows for a scenario like:
That is certainly a correct interpretation of the ABI language.
Quoted 9 lines
-> Updating SP with non 16bytes-aligned value (it's fine as long as the following code takes care to align it before accessing memory) -> IRQ is raised before SP gets aligned
-> Vector entry starts saving context on misaligned stack
-> Misaligned SP exceptionThe only thing that would avoid us the trouble is a guarantee that GCC never modifies SP in such a way that SP is not 16-bytes aligned.
I think it sort of falls out in the implementation from what I remember and see (and empirically checked with a couple of colleagues).
I don't think there is an ABI requirement that SP should left 16 byte aligned even for intermediate calculations.
Whether GCC does this or not today is immaterial and for userland it's certainly not the only code generator in town for this sort of question. The question also arises with other jits and other code generators which may leave the stack temporarily not aligned at 16 bytes. So it does sound like the right thing to do in the kernel defensively.
regards
Ramana
Quoted 3 lines
Thanks,
cover Ensure stack is aligned for kernel entries
Quoted 75 lines · Ramana Radhakrishnan
Quoted 50 lines · Julien Thierry
Quoted 47 lines · Ramana Radhakrishnan
Quoted 23 lines · Ard Biesheuvel
(+ Ramana)
Quoted 20 lines · Julien Thierry
Quoted 16 lines · Ard Biesheuvel
Quoted 6 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Quoted 8 lines
Quoted 4 lines
Is there anything that actually gives us that guarantee from GCC? I agree that currently it looks like aarch64-<...>-gcc only manipulates SP aligned to 16 bytes, but I don't know whether that is certain.
I think we should get that clarified then. I don't think it makes sense for GCC to have to reason about whether SP currently has a value that permits dereferencing.
The ABI gives that guarantee.
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
<quote>
5.2.2.1 Universal stack constraints
<...>
Additionally, at any point at which memory is accessed via SP, the hardware requires that SP mod 16 = 0. The stack must be quad-word aligned
Quoted 6 lines
Quoted 2 lines
</end quote>
Thanks Ramana. Sadly I don't think this clarifies things. The issue is that the guarantee is only that SP is aligned when we will use it to access memory, but still allows for a scenario like:
That is certainly a correct interpretation of the ABI language.
Quoted 9 lines
-> Updating SP with non 16bytes-aligned value (it's fine as long as the following code takes care to align it before accessing memory) -> IRQ is raised before SP gets aligned
-> Vector entry starts saving context on misaligned stack
-> Misaligned SP exceptionThe only thing that would avoid us the trouble is a guarantee that GCC never modifies SP in such a way that SP is not 16-bytes aligned.
I think it sort of falls out in the implementation from what I remember and see (and empirically checked with a couple of colleagues).
Quoted 9 lines
I don't think there is an ABI requirement that SP should left 16 byte aligned even for intermediate calculations.
Whether GCC does this or not today is immaterial and for userland it's certainly not the only code generator in town for this sort of question. The question also arises with other jits and other code generators which may leave the stack temporarily not aligned at 16 bytes. So it does sound like the right thing to do in the kernel defensively.
I don't think we really mind about userland. EL1 can (and, in Linux, does) use it's own SP. So having an interrupt while EL0 has a misaligned SP is not an issue for the kernel.
The cases covered by this series in only for exceptions received at the same EL that will handle that exception.
Cheers,
Signature · 1 line
Julien Thierry
cover Ensure stack is aligned for kernel entries
In reply to Ramana RadhakrishnanQuoted 33 lines · Ramana Radhakrishnan
Quoted 23 lines · Ard Biesheuvel
(+ Ramana)
Quoted 20 lines · Julien Thierry
Quoted 16 lines · Ard Biesheuvel
Quoted 6 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Quoted 8 lines
Quoted 4 lines
Is there anything that actually gives us that guarantee from GCC? I agree that currently it looks like aarch64-<...>-gcc only manipulates SP aligned to 16 bytes, but I don't know whether that is certain.
I think we should get that clarified then. I don't think it makes sense for GCC to have to reason about whether SP currently has a value that permits dereferencing.
Quoted 5 lines
The ABI gives that guarantee.
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
<quote>
Surely This only applies at public interfaces?
We make be re-entering the kernel due to an exception taken in the middle of a function.
In theory, the compiler is allowed to temporarily misalign SP (i.e., the procedure call standard doesn't forbid that).
So, we'd need to be confident that GCC and LLVM and any other compiler we care about _guarantee_ never to do that. (And that there is not asm in the kernel that will do so.)
Cheers
---Dave
cover Ensure stack is aligned for kernel entries
Quoted 34 lines · Dave Martin
Quoted 33 lines · Ramana Radhakrishnan
Quoted 31 lines · Ard Biesheuvel
(+ Ramana)
Quoted 20 lines · Julien Thierry
Quoted 11 lines · Ard Biesheuvel
Quoted 6 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
Quoted 5 lines
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Quoted 4 lines
Is there anything that actually gives us that guarantee from GCC? I agree that currently it looks like aarch64-<...>-gcc only manipulates SP aligned to 16 bytes, but I don't know whether that is certain.
I think we should get that clarified then. I don't think it makes sense for GCC to have to reason about whether SP currently has a value that permits dereferencing.
Quoted 8 lines
Quoted 5 lines
The ABI gives that guarantee.
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
<quote>
Surely This only applies at public interfaces?
I don't think this has anything to do with public interfaces. If there is a trap with a 16byte misaligned access of the SP then it doesn't matter whether it's a public interface or not.
regards
Ramana
cover Ensure stack is aligned for kernel entries
Quoted 39 lines · Ramana Radhakrishnan
Quoted 38 lines · Dave Martin
Quoted 37 lines · Ramana Radhakrishnan
Quoted 23 lines · Ard Biesheuvel
(+ Ramana)
Quoted 20 lines · Julien Thierry
Quoted 16 lines · Ard Biesheuvel
Quoted 6 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Quoted 8 lines
Quoted 4 lines
Is there anything that actually gives us that guarantee from GCC? I agree that currently it looks like aarch64-<...>-gcc only manipulates SP aligned to 16 bytes, but I don't know whether that is certain.
I think we should get that clarified then. I don't think it makes sense for GCC to have to reason about whether SP currently has a value that permits dereferencing.
The ABI gives that guarantee.
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
<quote>
Surely This only applies at public interfaces?
I don't think this has anything to do with public interfaces. If there is a trap with a 16byte misaligned access of the SP then it doesn't matter whether it's a public interface or not.
We're not talking about SP alignment faults here particluarly.
We're talking about any exception that may be taken from EL1h to EL1h, which may happen on random instructions inside a function, for random reasons.
There was talk about running the kernel mostly in EL1t but I don't think we currently do this (somebody please put me right if I'm wrong here!)
Cheers
---Dave
cover Ensure stack is aligned for kernel entries
Quoted 49 lines · Dave Martin
Quoted 39 lines · Ramana Radhakrishnan
Quoted 38 lines · Dave Martin
Quoted 37 lines · Ramana Radhakrishnan
Quoted 23 lines · Ard Biesheuvel
(+ Ramana)
Quoted 20 lines · Julien Thierry
Quoted 16 lines · Ard Biesheuvel
Quoted 6 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned.
How is this possible? GCC clearly only manipulates the stack pointer in 16 byte multiples, and so if we do the same in our asm code (which I think we already do, given the lack of reports about this issue), is this handling really necessary?
Quoted 8 lines
Quoted 4 lines
Is there anything that actually gives us that guarantee from GCC? I agree that currently it looks like aarch64-<...>-gcc only manipulates SP aligned to 16 bytes, but I don't know whether that is certain.
I think we should get that clarified then. I don't think it makes sense for GCC to have to reason about whether SP currently has a value that permits dereferencing.
The ABI gives that guarantee.
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
<quote>
Surely This only applies at public interfaces?
I don't think this has anything to do with public interfaces. If there is a trap with a 16byte misaligned access of the SP then it doesn't matter whether it's a public interface or not.
Quoted 6 lines
We're not talking about SP alignment faults here particluarly.
We're talking about any exception that may be taken from EL1h to EL1h, which may happen on random instructions inside a function, for random reasons.
Indeed.
But my question remains how likely it is that the compiler we use for generating the kernel code (so we are not talking about userland JITs or other crazy stuff here) would play with SP like that, especially since it is no longer a general purpose register. To me, it would make sense to attempt to reach an agreement with the GCC folks that compiler generated code does not muck about with SP like that.
In asm, there is one notable exception, of course, where we swap x0 and sp temporarily in the entry path, but we can't get interrupted there anyway.
In any case, if people insist, I'm ok with it. To me, it just seems like unnecessary clutter for a theoretical issue.
cover Ensure stack is aligned for kernel entries
Quoted 10 lines
Indeed.
But my question remains how likely it is that the compiler we use for generating the kernel code (so we are not talking about userland JITs or other crazy stuff here) would play with SP like that, especially since it is no longer a general purpose register. To me, it would make sense to attempt to reach an agreement with the GCC folks that compiler generated code does not muck about with SP like that.
It falls out from the choice of instructions we use for this sort of thing and because frame sizes really get rounded up to 16 bytes.
In the explanation below assume the stack is aligned to 16 bytes on entry. Frame sizes are always a multiple of 16.
For frame sizes up to 240 bytes that's a stp fp, lr, [sp, #-<off>]!
For frame sizes up to 4k bytes, that's a single sub instruction. Again all frame sizes are 16 byte aligned and therefore it's all ok.
For frame sizes greater than this and up to 64k that's a mov to a temporary register with a 16 bit immediate followed by a single subtract, again not going to leave your stack frame misaligned.
From frame sizes above that we split this into a subtract with a
multiple of 4k (again 16 byte aligned) and the rest.
For frame size above 16MB we use a sequence of mov / movk's with a temporary register and then do a single subtract of SP and therefore that's also fine.
I think for the sake of this conversation with respect to compiling the kernel, I think we can safely say that GCC will end up leaving the stack 16 byte aligned even with the intermediate computations and that shouldn't be an issue from my reading of the AArch64 backend.
So, probably move on but if you really want to be defensive you may want to carry this patch. However there's nothing that I will say about hand-written assembly (and I say that in the interest of completeness).
regards
Ramana
cover Ensure stack is aligned for kernel entries
Quoted 27 lines · Ramana Radhakrishnan
Quoted 10 lines
Indeed.
But my question remains how likely it is that the compiler we use for generating the kernel code (so we are not talking about userland JITs or other crazy stuff here) would play with SP like that, especially since it is no longer a general purpose register. To me, it would make sense to attempt to reach an agreement with the GCC folks that compiler generated code does not muck about with SP like that.
It falls out from the choice of instructions we use for this sort of thing and because frame sizes really get rounded up to 16 bytes.
In the explanation below assume the stack is aligned to 16 bytes on entry. Frame sizes are always a multiple of 16.
For frame sizes up to 240 bytes that's a stp fp, lr, [sp, #-<off>]!
For frame sizes up to 4k bytes, that's a single sub instruction. Again all frame sizes are 16 byte aligned and therefore it's all ok.
For frame sizes greater than this and up to 64k that's a mov to a temporary register with a 16 bit immediate followed by a single subtract, again not going to leave your stack frame misaligned.
Quoted 7 lines
From frame sizes above that we split this into a subtract with a
multiple of 4k (again 16 byte aligned) and the rest.For frame size above 16MB we use a sequence of mov / movk's with a temporary register and then do a single subtract of SP and therefore that's also fine.
Thanks Ramana. In the kernel, stack frames are typically limited to ~1 KB in size, so most of these will never even be encountered in our case.
Quoted 9 lines
I think for the sake of this conversation with respect to compiling the kernel, I think we can safely say that GCC will end up leaving the stack 16 byte aligned even with the intermediate computations and that shouldn't be an issue from my reading of the AArch64 backend.
So, probably move on but if you really want to be defensive you may want to carry this patch. However there's nothing that I will say about hand-written assembly (and I say that in the interest of completeness).
indeed, hand written assembly is an entirely different matter, but that is a manageable quantity of code which is currenty clean in this regard, as far as we know.
cover Ensure stack is aligned for kernel entries
In reply to Julien ThierryHi,
Quoted 8 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned. The entry code needs to make sure that the stack is aligned before using it to save the context.
So, as discussed in this thread:
https://www.spinics.net/lists/arm-kernel/msg688342.html
We might have the compiler provide the guarantee that SP is kept at multiples of 16-bytes throughout C functions. If this is accepted, it avoids the complexity of this series.
There is just one case remaining, which is less important as it is mostly a debug concern. If we take an SP alignment fault from EL1 (due to bad implementation) we take recursive exceptions:
- Without CONFIG_VMAP_STACK, kernel just freezes always taking SP alignment faults
- With CONFIG_VMAP_STACK after taking a number of exceptions, we overflow the stack and the kernel switches to the overflow stack where it finally manages to display a kernel panic message
So the question is, do we care about doing something for the above case?
Thanks,
Signature · 1 line
Julien Thierry
cover Ensure stack is aligned for kernel entries
Quoted 13 lines · Julien Thierry
Hi,
Quoted 8 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned. The entry code needs to make sure that the stack is aligned before using it to save the context.
Quoted 7 lines
So, as discussed in this thread:
https://www.spinics.net/lists/arm-kernel/msg688342.htmlWe might have the compiler provide the guarantee that SP is kept at multiples of 16-bytes throughout C functions. If this is accepted, it avoids the complexity of this series.
Yes, but we still want the build time sizeof(pt_regs) check and perhaps other pieces of this series.
Quoted 4 lines
There is just one case remaining, which is less important as it is mostly a debug concern. If we take an SP alignment fault from EL1 (due to bad implementation) we take recursive exceptions:
Quoted 8 lines
- Without
CONFIG_VMAP_STACK, kernel just freezes always taking SP alignment faults
- WithCONFIG_VMAP_STACKafter taking a number of exceptions, we overflow the stack and the kernel switches to the overflow stack where it finally manages to display a kernel panic messageSo the question is, do we care about doing something for the above case?
So in the latter case, it is obvious from the debug output that the stack pointer was misaligned? I'd expect so, given that each recursively taken exception has the same cause, and so it would be clear what happened.
So I'm leaning towards just relying on that, given that CONFIG_VMAP_STACK is the default, although it is unfortunate that KASAN still disables it.
cover Ensure stack is aligned for kernel entries
Quoted 17 lines · Ard Biesheuvel
Quoted 16 lines · Julien Thierry
Hi,
Quoted 8 lines · Julien Thierry
Hi,
Having SCTLR_ELx.SA enabled requires the SP to be 16-bytes aligned before using it to access memory. When taking an exception, it is possible that the context during which the exception occured had SP mis-aligned. The entry code needs to make sure that the stack is aligned before using it to save the context.
So, as discussed in this thread:
https://www.spinics.net/lists/arm-kernel/msg688342.html
Quoted 8 lines
Quoted 4 lines
We might have the compiler provide the guarantee that SP is kept at multiples of 16-bytes throughout C functions. If this is accepted, it avoids the complexity of this series.
Yes, but we still want the build time
sizeof(pt_regs)check and perhaps other pieces of this series.
Good point.
Quoted 10 lines
Quoted 10 lines
There is just one case remaining, which is less important as it is mostly a debug concern. If we take an SP alignment fault from EL1 (due to bad implementation) we take recursive exceptions:
- Without
CONFIG_VMAP_STACK, kernel just freezes always taking SP alignment faults
- WithCONFIG_VMAP_STACKafter taking a number of exceptions, we overflow the stack and the kernel switches to the overflow stack where it finally manages to display a kernel panic message
Quoted 8 lines
Quoted 2 lines
So the question is, do we care about doing something for the above case?
So in the latter case, it is obvious from the debug output that the stack pointer was misaligned? I'd expect so, given that each recursively taken exception has the same cause, and so it would be clear what happened.
So, it is obvious that the error is a misaligned stack pointer as it is described in the ESR and as you said, we are always taking the same kind of exception.
However the ELR will get overwritten by the recursive exception and its last value will be the first instruction accessing memory through SP in the exception handler. Meaning we lost the address where the first misaligned stack access happened.
But then I don't know whether this case warrants adding complexity to the entry code just in case one day fiddles around with the SP and does not align it to 16-bytes before accessing memory (or does it while interrupts are enabled).
Quoted 3 lines
So I'm leaning towards just relying on that, given that
CONFIG_VMAP_STACKis the default, although it is unfortunate that KASAN still disables it.
Thanks,
Signature · 1 line
Julien Thierry
cover Ensure stack is aligned for kernel entries
In reply to Ard BiesheuvelQuoted 15 lines · Ard Biesheuvel
Quoted 5 lines · Julien Thierry
On 26/09/18 14:56, Julien Thierry wrote:
There is just one case remaining, which is less important as it is mostly a debug concern. If we take an SP alignment fault from EL1 (due to bad implementation) we take recursive exceptions:Quoted 8 lines
- Without
CONFIG_VMAP_STACK, kernel just freezes always taking SP alignment faults
- WithCONFIG_VMAP_STACKafter taking a number of exceptions, we overflow the stack and the kernel switches to the overflow stack where it finally manages to display a kernel panic messageSo the question is, do we care about doing something for the above case?
Quoted 8 lines
So in the latter case, it is obvious from the debug output that the stack pointer was misaligned? I'd expect so, given that each recursively taken exception has the same cause, and so it would be clear what happened.
So I'm leaning towards just relying on that, given that
CONFIG_VMAP_STACKis the default, although it is unfortunate that KASAN still disables it.
Whilst it's unfortunate, I don't think it's the end of the world as long as KASAN remains a debug-only feature. In that case, you'd only enable it if you were debugging a suspected use-after-free, and I think the splat you'd see from the overflow is clear enough that it's not one of those.
However, I really would like a written confirmation (i.e. in some documentation) from GCC that they won't misalign the SP in generated code before we drop the meat of this series.
Will