arch: arm: support built-in stack protection in user mode for ARMv8m
This commit extends the support of built-in thread stack protection (i.e. based on the stack pointer limit registers) in ARMv8-M, so that it works with user mode. The commit does the following: - enables and disables the stack limit checking on the privileged stack, inside thread system calls, and upon entering user mode, - does not enable stack limit checking in context switch, if the thread is in user mode. Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
This commit is contained in:
parent
b3ea738a84
commit
d04cec97d5
3 changed files with 67 additions and 8 deletions
|
@ -190,14 +190,6 @@ _thread_irq_disabled:
|
|||
pop {r2, lr}
|
||||
#endif /* CONFIG_MPU_STACK_GUARD */
|
||||
|
||||
#ifdef CONFIG_BUILTIN_STACK_GUARD
|
||||
/* r2 contains k_thread */
|
||||
add r0, r2, #0
|
||||
push {r2, lr}
|
||||
blx configure_builtin_stack_guard
|
||||
pop {r2, lr}
|
||||
#endif /* CONFIG_BUILTIN_STACK_GUARD */
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
/* restore mode */
|
||||
ldr r0, [r2, #_thread_offset_to_mode]
|
||||
|
@ -231,8 +223,24 @@ _thread_irq_disabled:
|
|||
#error Unknown ARM architecture
|
||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
||||
|
||||
#ifdef CONFIG_BUILTIN_STACK_GUARD
|
||||
/* clear stack pointer limit before setting the PSP */
|
||||
push {r3}
|
||||
mov r3, #0
|
||||
msr PSPLIM, r3
|
||||
pop {r3}
|
||||
#endif
|
||||
|
||||
msr PSP, ip
|
||||
|
||||
#ifdef CONFIG_BUILTIN_STACK_GUARD
|
||||
/* r2 contains k_thread */
|
||||
add r0, r2, #0
|
||||
push {r2, lr}
|
||||
blx configure_builtin_stack_guard
|
||||
pop {r2, lr}
|
||||
#endif /* CONFIG_BUILTIN_STACK_GUARD */
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
stm sp!,{r0-r3} /* Save regs r0 to r4 on stack */
|
||||
push {lr}
|
||||
|
|
|
@ -142,12 +142,21 @@ FUNC_NORETURN void _arch_user_mode_enter(k_thread_entry_t user_entry,
|
|||
*
|
||||
* This function configures per thread stack guards by reprogramming
|
||||
* the built-in Process Stack Pointer Limit Register (PSPLIM).
|
||||
* The functionality is meant to be used during context switch.
|
||||
*
|
||||
* @param thread thread info data structure.
|
||||
*/
|
||||
void configure_builtin_stack_guard(struct k_thread *thread)
|
||||
{
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
if (thread->arch.mode & CONTROL_nPRIV_Msk) {
|
||||
/* Only configure stack limit for threads in privileged mode
|
||||
* (i.e supervisor threads or user threads doing system call).
|
||||
* User threads executing in user mode do not require a stack
|
||||
* limit protection.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
u32_t guard_start = thread->arch.priv_stack_start ?
|
||||
(u32_t)thread->arch.priv_stack_start :
|
||||
(u32_t)thread->stack_obj;
|
||||
|
|
|
@ -56,9 +56,25 @@ SECTION_FUNC(TEXT,_arm_userspace_enter)
|
|||
ldr ip, =CONFIG_PRIVILEGED_STACK_SIZE
|
||||
add r0, r0, ip
|
||||
|
||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||
/* clear stack pointer limit before setting the PSP */
|
||||
push {r3}
|
||||
mov r3, #0
|
||||
msr PSPLIM, r3
|
||||
pop {r3}
|
||||
#endif
|
||||
|
||||
mov ip, sp
|
||||
msr PSP, r0
|
||||
|
||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||
/* set stack pointer limit to the start of the priv stack */
|
||||
ldr r0, =_kernel
|
||||
ldr r0, [r0, #_kernel_offset_to_current]
|
||||
ldr r0, [r0, #_thread_offset_to_priv_stack_start] /* priv stack ptr */
|
||||
msr PSPLIM, r0
|
||||
#endif
|
||||
|
||||
/* load up stack info from user stack */
|
||||
ldr r0, [ip]
|
||||
ldr ip, [ip, #4]
|
||||
|
@ -96,6 +112,14 @@ SECTION_FUNC(TEXT,_arm_userspace_enter)
|
|||
/* r0 contains user stack start, ip contains user stack size */
|
||||
add r0, r0, ip /* calculate top of stack */
|
||||
|
||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||
/* clear stack limit (stack protection not required in user mode) */
|
||||
push {r3}
|
||||
mov r3, #0
|
||||
msr PSPLIM, r3
|
||||
pop {r3}
|
||||
#endif
|
||||
|
||||
/* set stack to user stack */
|
||||
msr PSP, r0
|
||||
|
||||
|
@ -169,6 +193,16 @@ valid_syscall:
|
|||
/* switch to privileged stack */
|
||||
msr PSP, ip
|
||||
|
||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||
/* Set stack pointer limit (needed in privileged mode) */
|
||||
push {r6}
|
||||
ldr r6, =_kernel
|
||||
ldr r6, [r6, #_kernel_offset_to_current]
|
||||
ldr r6, [r6, #_thread_offset_to_priv_stack_start] /* priv stack ptr */
|
||||
msr PSPLIM, r6
|
||||
pop {r6}
|
||||
#endif
|
||||
|
||||
/* push args to complete stack frame */
|
||||
push {r4,r5}
|
||||
|
||||
|
@ -183,6 +217,14 @@ dispatch_syscall:
|
|||
/* restore LR */
|
||||
ldr lr, [sp,#12]
|
||||
|
||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||
/* clear stack limit (stack protection not required in user mode) */
|
||||
push {r3}
|
||||
mov r3, #0
|
||||
msr PSPLIM, r3
|
||||
pop {r3}
|
||||
#endif
|
||||
|
||||
/* set stack back to unprivileged stack */
|
||||
ldr ip, [sp,#8]
|
||||
msr PSP, ip
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue