diff --git a/samples/mpu_stack_guard_test/Makefile b/samples/mpu_stack_guard_test/Makefile new file mode 100644 index 00000000000..93f81237076 --- /dev/null +++ b/samples/mpu_stack_guard_test/Makefile @@ -0,0 +1,4 @@ +BOARD ?= v2m_beetle +CONF_FILE = prj.conf + +include ${ZEPHYR_BASE}/Makefile.test diff --git a/samples/mpu_stack_guard_test/README.rst b/samples/mpu_stack_guard_test/README.rst new file mode 100644 index 00000000000..24b7ecdae76 --- /dev/null +++ b/samples/mpu_stack_guard_test/README.rst @@ -0,0 +1,67 @@ +.. _mpu_stack_guard_test: + +MPU Stack Guard Test +#################### + +Overview +******** + +This is a simple application that demonstrates basic thread stack guarding on +the supported platforms. +A thread spawned by the main task recursively calls a function that fills the +thread stack up to where it overwrites a preposed canary. +If the MPU is enabled and the Stack Guard feature is present the test succeeds +because an MEM Faults exception prevents the canary from being overwritten. +If the MPU is disabled the test fails because the canary is overwritten. + +Building and Running +******************** + +This project outputs to the console. +To build the test with the MPU disabled: + +.. code-block:: console + + $ cd samples/mpu_stack_guard_test + $ make + +To build the test with the MPU enabled and the stack guard feature present: + +.. code-block:: console + + $ cd samples/mpu_stack_guard_test + $ make CONF_FILE=prj_stack_guard.conf + +Sample Output +============= + +With the MPU disabled: + +.. code-block:: console + + ***** BOOTING ZEPHYR OS v1.7.99 - BUILD: Mar 29 2017 11:07:09 ***** + MPU STACK GUARD Test + Canary Initial Value = 0xf0cacc1a + Canary = 0x200003a8 Test not passed. + ... + +With the MPU enabled and the stack guard feature present: + +.. code-block:: console + + ***** BOOTING ZEPHYR OS v1.7.99 - BUILD: Mar 29 2017 11:20:10 ***** + MPU STACK GUARD Test + Canary Initial Value = 0xf0cacc1a + [general] [DBG] arm_core_mpu_configure: Region info: 0x200003ac 0x400 + ***** MPU FAULT ***** + Executing thread ID (thread): 0x200003ac + Faulting instruction address: 0x0 + Stacking error + Fatal fault in thread 0x200003ac! Aborting. + ***** HARD FAULT ***** + Fault escalation (see below) + ***** MPU FAULT ***** + Executing thread ID (thread): 0x200003ac + Faulting instruction address: 0x8000466 + Stacking error + Fatal fault in ISR! Spinning... diff --git a/samples/mpu_stack_guard_test/prj.conf b/samples/mpu_stack_guard_test/prj.conf new file mode 100644 index 00000000000..8b042db5406 --- /dev/null +++ b/samples/mpu_stack_guard_test/prj.conf @@ -0,0 +1 @@ +CONFIG_STDOUT_CONSOLE=y diff --git a/samples/mpu_stack_guard_test/prj_stack_guard.conf b/samples/mpu_stack_guard_test/prj_stack_guard.conf new file mode 100644 index 00000000000..cdc1dbe8ddb --- /dev/null +++ b/samples/mpu_stack_guard_test/prj_stack_guard.conf @@ -0,0 +1,5 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_MPU_STACK_GUARD=y +CONFIG_SYS_LOG=y +CONFIG_SYS_LOG_DEFAULT_LEVEL=4 +CONFIG_SYS_LOG_OVERRIDE_LEVEL=4 diff --git a/samples/mpu_stack_guard_test/src/Makefile b/samples/mpu_stack_guard_test/src/Makefile new file mode 100644 index 00000000000..00066e15678 --- /dev/null +++ b/samples/mpu_stack_guard_test/src/Makefile @@ -0,0 +1 @@ +obj-y = main.o diff --git a/samples/mpu_stack_guard_test/src/main.c b/samples/mpu_stack_guard_test/src/main.c new file mode 100644 index 00000000000..2d45cfe71ee --- /dev/null +++ b/samples/mpu_stack_guard_test/src/main.c @@ -0,0 +1,70 @@ +/* main.c - Hello World demo */ + +/* + * Copyright (c) 2012-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* size of stack area used by each thread */ +#define STACKSIZE 1024 + +/* scheduling priority used by each thread */ +#define PRIORITY 7 + +/* delay between greetings (in ms) */ +#define SLEEPTIME 500 + +/* Focaccia tastes better than DEEDBEEF ;-) */ +#define STACK_GUARD_CANARY 0xF0CACC1A + +struct stack_guard_buffer { + /* Make sure canary is not optimized by the compiler */ + volatile u32_t canary; + u8_t stack[STACKSIZE]; +}; + +struct stack_guard_buffer buf; + +u32_t recursive_loop(u32_t counter) +{ + if (buf.canary != STACK_GUARD_CANARY) { + printk("Canary = 0x%08x\tTest not passed.\n", buf.canary); + + while (1) { + k_sleep(SLEEPTIME); + } + } + + counter++; + + return recursive_loop(counter) + recursive_loop(counter); +} + +/* stack_guard_thread is a dynamic thread */ +void stack_guard_thread(void *dummy1, void *dummy2, void *dummy3) +{ + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + ARG_UNUSED(dummy3); + + u32_t result = recursive_loop(0); + + /* We will never arrive here */ + printk("Result: %d", result); +} + +void main(void) +{ + buf.canary = STACK_GUARD_CANARY; + + printk("MPU STACK GUARD Test\n"); + printk("Canary Initial Value = 0x%x\n", buf.canary); + + /* spawn stack_guard_thread */ + k_thread_spawn(buf.stack, STACKSIZE, stack_guard_thread, NULL, NULL, + NULL, PRIORITY, 0, K_NO_WAIT); +} diff --git a/samples/mpu_stack_guard_test/testcase.ini b/samples/mpu_stack_guard_test/testcase.ini new file mode 100644 index 00000000000..1de64db74af --- /dev/null +++ b/samples/mpu_stack_guard_test/testcase.ini @@ -0,0 +1,10 @@ +[test] +build_only = true +tags = apps + +[test_stack_guard] +build_only = true +extra_args = CONF_FILE=prj_stack_guard.conf +tags = apps +arch_whitelist = arm +filter = CONFIG_MPU_STACK_GUARD and CONFIG_ARM_MPU diff --git a/samples/samples.rst b/samples/samples.rst index bc8ac861d2c..73e57783c1e 100644 --- a/samples/samples.rst +++ b/samples/samples.rst @@ -12,6 +12,7 @@ Samples and Demos basic/* subsys/subsys.rst mpu_test/* + mpu_stack_guard_test/* net/net.rst bluetooth/bluetooth.rst sensor/*