From 1ccd71557770f9264e27468bd8aff13e7357b872 Mon Sep 17 00:00:00 2001 From: Leandro Pereira Date: Tue, 3 Apr 2018 09:47:41 -0700 Subject: [PATCH] kernel: thread: Consider stack pointer fuzz underflow When randomizing the stack pointer on thread creation (CONFIG_STACK_POINTER_RANDOM), the fuzz amount might exceed the stack size, causing an underflow. Ensure that this will never underflow by only adjusting the stack size if there's enough space. Signed-off-by: Leandro Pereira --- kernel/thread.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/kernel/thread.c b/kernel/thread.c index 5516e6d763..59fc89bb83 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -256,25 +256,44 @@ static void schedule_new_thread(struct k_thread *thread, s32_t delay) } #endif -void _setup_new_thread(struct k_thread *new_thread, - k_thread_stack_t *stack, size_t stack_size, - k_thread_entry_t entry, - void *p1, void *p2, void *p3, - int prio, u32_t options) +#if !CONFIG_STACK_POINTER_RANDOM +static inline size_t adjust_stack_size(size_t stack_size) +{ + return stack_size; +} +#else +static inline size_t adjust_stack_size(size_t stack_size) { -#if CONFIG_STACK_POINTER_RANDOM -#if defined(CONFIG_STACK_GROWS_UP) - /* This is so rare not bothering for now */ -#error "Stack pointer randomization not implemented for upward growing stacks" -#endif /* Don't need to worry about alignment of the size here, _new_thread() * is required to do it * * FIXME: Not the best way to get a random number in a range. * See #6493 */ - stack_size -= sys_rand32_get() % CONFIG_STACK_POINTER_RANDOM; + const size_t fuzz = sys_rand32_get() % CONFIG_STACK_POINTER_RANDOM; + + if (unlikely(fuzz * 2 > stack_size)) { + return stack_size; + } + + return stack_size - fuzz; +} + +#if defined(CONFIG_STACK_GROWS_UP) + /* This is so rare not bothering for now */ +#error "Stack pointer randomization not implemented for upward growing stacks" +#endif /* CONFIG_STACK_GROWS_UP */ + #endif /* CONFIG_STACK_POINTER_RANDOM */ + +void _setup_new_thread(struct k_thread *new_thread, + k_thread_stack_t *stack, size_t stack_size, + k_thread_entry_t entry, + void *p1, void *p2, void *p3, + int prio, u32_t options) +{ + stack_size = adjust_stack_size(stack_size); + _new_thread(new_thread, stack, stack_size, entry, p1, p2, p3, prio, options); #ifdef CONFIG_USERSPACE