arch: arm: cortex-m: hw stack protection under no multi-threading

This commit adds the support for HW Stack Protection when
building Zephyr without support for multi-threading. The
single MPU guard (if the feature is enabled) is set to
guard the Main stack area. The stack fail check is also
updated.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
This commit is contained in:
Ioannis Glaropoulos 2020-08-03 13:23:37 +02:00 committed by Carles Cufí
parent 4338552175
commit fa04bf615c
2 changed files with 35 additions and 1 deletions

View file

@ -46,6 +46,10 @@ LOG_MODULE_REGISTER(mpu);
#define _MPU_DYNAMIC_REGIONS_AREA_SIZE ((uint32_t)&__kernel_ram_end - \
_MPU_DYNAMIC_REGIONS_AREA_START)
#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_MPU_STACK_GUARD)
extern K_THREAD_STACK_DEFINE(z_main_stack, CONFIG_MAIN_STACK_SIZE);
#endif
/**
* @brief Use the HW-specific MPU driver to program
* the static MPU regions.
@ -86,6 +90,21 @@ void z_arm_configure_static_mpu_regions(void)
};
#endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */
#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_MPU_STACK_GUARD)
/* Main stack MPU guard to detect overflow.
* Note:
* FPU_SHARING and USERSPACE are not supported features
* under CONFIG_MULTITHREADING=n, so the MPU guard (if
* exists) is reserved aside of CONFIG_MAIN_STACK_SIZE
* and there is no requirement for larger guard area (FP
* context is not stacked).
*/
const struct k_mem_partition main_stack_guard_region = {
.start = (uint32_t)z_main_stack,
.size = (uint32_t)MPU_GUARD_ALIGN_AND_SIZE,
.attr = K_MEM_PARTITION_P_RO_U_NA,
};
#endif /* !CONFIG_MULTITHREADING && CONFIG_MPU_STACK_GUARD */
/* Define a constant array of k_mem_partition objects
* to hold the configuration of the respective static
* MPU regions.
@ -97,6 +116,9 @@ void z_arm_configure_static_mpu_regions(void)
#if defined(CONFIG_NOCACHE_MEMORY)
&nocache_region,
#endif /* CONFIG_NOCACHE_MEMORY */
#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_MPU_STACK_GUARD)
&main_stack_guard_region,
#endif /* !CONFIG_MULTITHREADING && CONFIG_MPU_STACK_GUARD */
#if defined(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT)
&ramfunc_region
#endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */
@ -112,7 +134,8 @@ void z_arm_configure_static_mpu_regions(void)
(uint32_t)&_image_ram_start,
(uint32_t)&__kernel_ram_end);
#if defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS)
#if defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS) && \
defined(CONFIG_MULTITHREADING)
/* Define a constant array of k_mem_partition objects that holds the
* boundaries of the areas, inside which dynamic region programming
* is allowed. The information is passed to the underlying driver at

View file

@ -256,11 +256,13 @@ void configure_builtin_stack_guard(struct k_thread *thread)
*/
uint32_t z_check_thread_stack_fail(const uint32_t fault_addr, const uint32_t psp)
{
#if defined(CONFIG_MULTITHREADING)
const struct k_thread *thread = _current;
if (!thread) {
return 0;
}
#endif
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
uint32_t guard_len = (thread->base.user_options & K_FP_REGS) ?
@ -298,12 +300,21 @@ uint32_t z_check_thread_stack_fail(const uint32_t fault_addr, const uint32_t psp
}
}
#else /* CONFIG_USERSPACE */
#if defined(CONFIG_MULTITHREADING)
if (IS_MPU_GUARD_VIOLATION(thread->stack_info.start - guard_len,
guard_len,
fault_addr, psp)) {
/* Thread stack corruption */
return thread->stack_info.start;
}
#else
if (IS_MPU_GUARD_VIOLATION((uint32_t)z_main_stack,
guard_len,
fault_addr, psp)) {
/* Thread stack corruption */
return (uint32_t)Z_THREAD_STACK_BUFFER(z_main_stack);
}
#endif
#endif /* CONFIG_USERSPACE */
return 0;