tests: kernel: fatal: check stack overflow

For all arches except ARC, enable stack sentinel and test that
some common stack violations trigger exceptions.

For ARC, use the hardware stack checking feature.

Additional testcase.ini blocks may be added to do stack bounds checking
for MMU/MPU-based stack protection schemes.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-05-11 16:13:32 -07:00 committed by Anas Nashif
commit 636f609d66
4 changed files with 99 additions and 5 deletions

View file

@ -0,0 +1 @@
CONFIG_ARC_STACK_CHECKING=y

View file

@ -1,2 +1,2 @@
CONFIG_MAIN_THREAD_PRIORITY=7
CONFIG_STACK_SENTINEL=y

View file

@ -9,10 +9,19 @@
#include <kernel_structs.h>
#include <irq_offload.h>
#define STACKSIZE 1024
#define STACKSIZE 2048
#define MAIN_PRIORITY 7
#define PRIORITY 5
static char __noinit __stack alt_stack[STACKSIZE];
#ifdef CONFIG_STACK_SENTINEL
#define OVERFLOW_STACKSIZE 1024
static char *overflow_stack = alt_stack + (STACKSIZE - OVERFLOW_STACKSIZE);
#else
#define OVERFLOW_STACKSIZE STACKSIZE
#endif
static struct k_thread alt_thread;
volatile int rv;
@ -39,8 +48,44 @@ void alt_thread1(void)
void alt_thread2(void)
{
int key;
key = irq_lock();
k_oops();
rv = TC_FAIL;
irq_unlock(key);
}
void blow_up_stack(void)
{
char buf[OVERFLOW_STACKSIZE];
printk("posting %zu bytes of junk to stack...\n", sizeof(buf));
memset(buf, 0xbb, sizeof(buf));
}
void stack_thread1(void)
{
/* Test that stack overflow check due to timer interrupt works */
blow_up_stack();
printk("busy waiting...\n");
k_busy_wait(1024 * 1024);
printk("should never see this\n");
rv = TC_FAIL;
}
void stack_thread2(void)
{
int key = irq_lock();
/* Test that stack overflow check due to swap works */
blow_up_stack();
printk("swapping...\n");
_Swap(irq_lock());
printk("should never see this\n");
rv = TC_FAIL;
irq_unlock(key);
}
@ -50,8 +95,10 @@ void main(void)
TC_START("test_fatal");
k_thread_priority_set(_current, K_PRIO_PREEMPT(MAIN_PRIORITY));
printk("test alt thread 1: generic CPU exception\n");
k_thread_create(&alt_thread, alt_stack, STACKSIZE,
k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack),
(k_thread_entry_t)alt_thread1,
NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0,
K_NO_WAIT);
@ -63,7 +110,7 @@ void main(void)
}
printk("test alt thread 2: initiate kernel oops\n");
k_thread_create(&alt_thread, alt_stack, STACKSIZE,
k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack),
(k_thread_entry_t)alt_thread2,
NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0,
K_NO_WAIT);
@ -74,6 +121,43 @@ void main(void)
printk("PASS\n");
}
printk("test stack overflow - timer irq\n");
#ifdef CONFIG_STACK_SENTINEL
/* When testing stack sentinel feature, the overflow stack is a
* smaller section of alt_stack near the end.
* In this way when it gets overflowed by blow_up_stack() we don't
* corrupt anything else and prevent the test case from completing.
*/
k_thread_create(&alt_thread, overflow_stack, OVERFLOW_STACKSIZE,
#else
k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack),
#endif
(k_thread_entry_t)stack_thread1,
NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0,
K_NO_WAIT);
if (rv == TC_FAIL) {
printk("thread was not aborted\n");
goto out;
} else {
printk("PASS\n");
}
printk("test stack overflow - swap\n");
#ifdef CONFIG_STACK_SENTINEL
k_thread_create(&alt_thread, overflow_stack, OVERFLOW_STACKSIZE,
#else
k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack),
#endif
(k_thread_entry_t)stack_thread2,
NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0,
K_NO_WAIT);
if (rv == TC_FAIL) {
printk("thread was not aborted\n");
goto out;
} else {
printk("PASS\n");
}
out:
TC_END_RESULT(rv);
TC_END_REPORT(rv);

View file

@ -1,2 +1,11 @@
[test]
# Uses CONFIG_STACK_SENTINEL
[stack-sentinel]
tags = core ignore_faults
arch_exclude = arc
# Uses CONFIG_ARC_STACK_CHECKING
[arc-stack-checking]
tags = core ignore_faults
extra_args = CONF_FILE=prj-arc.conf
arch_whitelist = arc