kernel: introduce initial stack randomization
This is a component of address space layout randomization that we can implement even though we have a physical address space. Support for upward-growing stacks omitted for now, it's not done currently on any of our current or planned architectures. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
a967915e52
commit
83752c1cfe
6 changed files with 109 additions and 0 deletions
|
@ -564,6 +564,26 @@ config EXECUTE_XOR_WRITE
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config STACK_POINTER_RANDOM
|
||||
int
|
||||
prompt "Initial stack pointer randomization bounds"
|
||||
depends on !STACK_GROWS_UP
|
||||
default 0
|
||||
help
|
||||
This option performs a limited form of Address Space Layout
|
||||
Randomization by offsetting some random value to a thread's
|
||||
initial stack pointer upon creation. This hinders some types of
|
||||
security attacks by making the location of any given stack frame
|
||||
non-deterministic.
|
||||
|
||||
This feature can waste up to the specified size in bytes the stack
|
||||
region, which is carved out of the total size of the stack region.
|
||||
A reasonable minimum value would be around 100 bytes if this can
|
||||
be spared.
|
||||
|
||||
This is currently only implemented for systems whose stack pointers
|
||||
grow towards lower memory addresses.
|
||||
|
||||
endmenu
|
||||
|
||||
config MAX_DOMAIN_PARTITIONS
|
||||
|
|
|
@ -270,6 +270,19 @@ void _setup_new_thread(struct k_thread *new_thread,
|
|||
void *p1, void *p2, void *p3,
|
||||
int prio, u32_t options)
|
||||
{
|
||||
#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;
|
||||
#endif /* CONFIG_STACK_POINTER_RANDOM */
|
||||
_new_thread(new_thread, stack, stack_size, entry, p1, p2, p3,
|
||||
prio, options);
|
||||
#ifdef CONFIG_USERSPACE
|
||||
|
|
5
tests/kernel/mem_protect/stack_random/CMakeLists.txt
Normal file
5
tests/kernel/mem_protect/stack_random/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(NONE)
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
4
tests/kernel/mem_protect/stack_random/prj.conf
Normal file
4
tests/kernel/mem_protect/stack_random/prj.conf
Normal file
|
@ -0,0 +1,4 @@
|
|||
CONFIG_TEST=y
|
||||
CONFIG_STACK_POINTER_RANDOM=64
|
||||
CONFIG_ENTROPY_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
63
tests/kernel/mem_protect/stack_random/src/main.c
Normal file
63
tests/kernel/mem_protect/stack_random/src/main.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include <tc_util.h>
|
||||
#include <zephyr.h>
|
||||
|
||||
#define STACKSIZE 2048
|
||||
#define THREAD_COUNT 64
|
||||
#define VERBOSE 0
|
||||
|
||||
void *last_sp = (void *)0xFFFFFFFF;
|
||||
unsigned int changed;
|
||||
|
||||
void alternate_thread(void)
|
||||
{
|
||||
int i;
|
||||
void *sp_val;
|
||||
|
||||
/* If the stack isn't being randomized then sp_val will never change */
|
||||
sp_val = &i;
|
||||
|
||||
#if VERBOSE
|
||||
printk("stack pointer: %p last: %p\n", sp_val, last_sp);
|
||||
#endif
|
||||
|
||||
if (last_sp != (void *)0xFFFFFFFF && sp_val != last_sp) {
|
||||
changed++;
|
||||
}
|
||||
last_sp = sp_val;
|
||||
}
|
||||
|
||||
|
||||
K_THREAD_STACK_DEFINE(alt_thread_stack_area, STACKSIZE);
|
||||
static struct k_thread alt_thread_data;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int i, ret = TC_FAIL;
|
||||
|
||||
TC_START("Test Stack pointer randomization\n");
|
||||
|
||||
/* Start thread */
|
||||
for (i = 0; i < THREAD_COUNT; i++) {
|
||||
k_thread_create(&alt_thread_data, alt_thread_stack_area,
|
||||
STACKSIZE, (k_thread_entry_t)alternate_thread,
|
||||
NULL, NULL, NULL, K_HIGHEST_THREAD_PRIO, 0,
|
||||
K_NO_WAIT);
|
||||
}
|
||||
|
||||
printk("stack pointer changed %d times out of %d tests\n",
|
||||
changed, THREAD_COUNT);
|
||||
|
||||
if (changed) {
|
||||
ret = TC_PASS;
|
||||
}
|
||||
|
||||
TC_END_RESULT(ret);
|
||||
TC_END_REPORT(ret);
|
||||
}
|
4
tests/kernel/mem_protect/stack_random/testcase.yaml
Normal file
4
tests/kernel/mem_protect/stack_random/testcase.yaml
Normal file
|
@ -0,0 +1,4 @@
|
|||
tests:
|
||||
kernel.memory_protection.stack_random:
|
||||
arch_exclude: posix
|
||||
tags: core
|
Loading…
Add table
Add a link
Reference in a new issue