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}
|
pop {r2, lr}
|
||||||
#endif /* CONFIG_MPU_STACK_GUARD */
|
#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
|
#ifdef CONFIG_USERSPACE
|
||||||
/* restore mode */
|
/* restore mode */
|
||||||
ldr r0, [r2, #_thread_offset_to_mode]
|
ldr r0, [r2, #_thread_offset_to_mode]
|
||||||
|
@ -231,8 +223,24 @@ _thread_irq_disabled:
|
||||||
#error Unknown ARM architecture
|
#error Unknown ARM architecture
|
||||||
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
|
#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
|
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
|
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||||
stm sp!,{r0-r3} /* Save regs r0 to r4 on stack */
|
stm sp!,{r0-r3} /* Save regs r0 to r4 on stack */
|
||||||
push {lr}
|
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
|
* This function configures per thread stack guards by reprogramming
|
||||||
* the built-in Process Stack Pointer Limit Register (PSPLIM).
|
* 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.
|
* @param thread thread info data structure.
|
||||||
*/
|
*/
|
||||||
void configure_builtin_stack_guard(struct k_thread *thread)
|
void configure_builtin_stack_guard(struct k_thread *thread)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_USERSPACE)
|
#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 guard_start = thread->arch.priv_stack_start ?
|
||||||
(u32_t)thread->arch.priv_stack_start :
|
(u32_t)thread->arch.priv_stack_start :
|
||||||
(u32_t)thread->stack_obj;
|
(u32_t)thread->stack_obj;
|
||||||
|
|
|
@ -56,9 +56,25 @@ SECTION_FUNC(TEXT,_arm_userspace_enter)
|
||||||
ldr ip, =CONFIG_PRIVILEGED_STACK_SIZE
|
ldr ip, =CONFIG_PRIVILEGED_STACK_SIZE
|
||||||
add r0, r0, ip
|
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
|
mov ip, sp
|
||||||
msr PSP, r0
|
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 */
|
/* load up stack info from user stack */
|
||||||
ldr r0, [ip]
|
ldr r0, [ip]
|
||||||
ldr ip, [ip, #4]
|
ldr ip, [ip, #4]
|
||||||
|
@ -96,6 +112,14 @@ SECTION_FUNC(TEXT,_arm_userspace_enter)
|
||||||
/* r0 contains user stack start, ip contains user stack size */
|
/* r0 contains user stack start, ip contains user stack size */
|
||||||
add r0, r0, ip /* calculate top of stack */
|
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 */
|
/* set stack to user stack */
|
||||||
msr PSP, r0
|
msr PSP, r0
|
||||||
|
|
||||||
|
@ -169,6 +193,16 @@ valid_syscall:
|
||||||
/* switch to privileged stack */
|
/* switch to privileged stack */
|
||||||
msr PSP, ip
|
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 args to complete stack frame */
|
||||||
push {r4,r5}
|
push {r4,r5}
|
||||||
|
|
||||||
|
@ -183,6 +217,14 @@ dispatch_syscall:
|
||||||
/* restore LR */
|
/* restore LR */
|
||||||
ldr lr, [sp,#12]
|
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 */
|
/* set stack back to unprivileged stack */
|
||||||
ldr ip, [sp,#8]
|
ldr ip, [sp,#8]
|
||||||
msr PSP, ip
|
msr PSP, ip
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue