kernel: init: Use entropy API directly to initialize stack canary

Some sys_rand32_get() implementation will use shared state and protect
that using some synchronization primitive such as a mutex or a
semaphore.  It's too early in the boot process to use any of them,
which causes some issues.

Use the entropy API directly to set up the stack canaries.

This doesn't completely solve the problem, as some drivers will use the
same synchronization primitives anyway.  Some drivers (e.g.  the NRF5
entropy driver) provide an API to be used by ISRs that might be
suitable here, but not all drivers do that.

Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
This commit is contained in:
Leandro Pereira 2018-05-23 13:38:52 -07:00 committed by Andrew Boie
commit 389c36439a

View file

@ -375,9 +375,45 @@ static void switch_to_main_thread(void)
}
#ifdef CONFIG_STACK_CANARIES
extern void *__stack_chk_guard;
#include <entropy.h>
extern uintptr_t __stack_chk_guard;
static inline void _initialize_stack_canaries(void)
{
#ifdef CONFIG_ENTROPY_HAS_DRIVER
struct device *entropy = device_get_binding(CONFIG_ENTROPY_NAME);
int rc;
if (entropy == NULL) {
goto sys_rand32_fallback;
}
rc = entropy_get_entropy(entropy,
(u8_t *)&__stack_chk_guard,
sizeof(__stack_chk_guard));
if (rc == 0) {
return;
}
/* FIXME: rc could be -EAGAIN here, for cases where the entropy
* driver doesn't yet have the requested amount of entropy. In
* the meantime, just use the fallback with sys_rand32_get().
*/
sys_rand32_fallback:
#endif
/* FIXME: this assumes sys_rand32_get() won't use any synchronization
* primitive, like semaphores or mutexes. It's too early in the boot
* process to use any of them. Ideally, only the path where entropy
* devices are available should be built, this is only a fallback for
* those devices without a HWRNG entropy driver.
*/
__stack_chk_guard = (uintptr_t)sys_rand32_get();
}
#endif /* CONFIG_STACK_CANARIES */
/**
*
* @brief Initialize kernel
@ -418,10 +454,10 @@ FUNC_NORETURN void _Cstart(void)
_sys_device_do_config_level(_SYS_INIT_LEVEL_PRE_KERNEL_1);
_sys_device_do_config_level(_SYS_INIT_LEVEL_PRE_KERNEL_2);
/* initialize stack canaries */
#ifdef CONFIG_STACK_CANARIES
__stack_chk_guard = (void *)sys_rand32_get();
_initialize_stack_canaries();
#endif
prepare_multithreading(dummy_thread);
/* display boot banner */