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:
Ioannis Glaropoulos 2018-10-08 15:48:49 +02:00 committed by Andrew Boie
commit d04cec97d5
3 changed files with 67 additions and 8 deletions

View file

@ -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}

View file

@ -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;

View file

@ -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