blob: 9a847ac5734329e350968ca74af1017c4c3cfc70 [file] [log] [blame]
/*
* Copyright (c) 2012-2014 Wind River Systems, Inc.
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#define STACKSIZE (2048 + CONFIG_TEST_EXTRA_STACK_SIZE)
ZTEST_BMEM static int count;
ZTEST_BMEM static int ret = TC_PASS;
void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf)
{
if (reason != K_ERR_STACK_CHK_FAIL) {
printk("wrong error type\n");
k_fatal_halt(reason);
}
}
void check_input(const char *name, const char *input);
/**
*
* print_loop
*
* This function calls check_input 6 times with the input name and a short
* string, which is printed properly by check_input.
*
* @param name caller identification string
*
*/
void print_loop(const char *name)
{
while (count < 6) {
/* A short input string to check_input. It will pass. */
check_input(name, "Stack ok");
count++;
}
}
/**
*
* check_input
*
* This function copies the input string to a buffer of 16 characters and
* prints the name and buffer as a string. If the input string is longer
* than the buffer, an error condition is detected.
*
* When stack protection feature is enabled (see prj.conf file), the
* system error handler is invoked and reports a "Stack Check Fail" error.
* When stack protection feature is not enabled, the system crashes with
* error like: Trying to execute code outside RAM or ROM.
*
*/
void check_input(const char *name, const char *input)
{
/* Stack will overflow when input is more than 16 characters */
char buf[16];
strcpy(buf, input);
TC_PRINT("%s: %s\n", name, buf);
}
/**
*
* This thread passes a long string to check_input function. It terminates due
* to stack overflow and reports "Stack Check Fail" when stack protection
* feature is enabled. Hence it will not execute the print_loop function
* and will not set ret to TC_FAIL.
*
*/
void alternate_thread(void)
{
TC_PRINT("Starts %s\n", __func__);
check_input(__func__,
"Input string is too long and stack overflowed!\n");
/*
* Expect this thread to terminate due to stack check fail and will not
* execute pass here.
*/
print_loop(__func__);
ret = TC_FAIL;
}
K_THREAD_STACK_DEFINE(alt_thread_stack_area, STACKSIZE);
static struct k_thread alt_thread_data;
/**
* @brief test Stack Protector feature using canary
*
* @details This is the test program to test stack protection using canary.
* The main thread starts a second thread, which generates a stack check
* failure.
* By design, the second thread will not complete its execution and
* will not set ret to TC_FAIL.
* This is the entry point to the test stack protection feature.
* It starts the thread that tests stack protection, then prints out
* a few messages before terminating.
*
* @ingroup kernel_memprotect_tests
*/
ZTEST_USER(stackprot, test_stackprot)
{
zassert_true(ret == TC_PASS);
print_loop(__func__);
}
/**
* @brief Test optional mechanism to detect stack overflow
*
* @details Test that the system provides an optional mechanism to detect
* when supervisor threads overflow stack memory buffer.
*
* @ingroup kernel_memprotect_tests
*/
ZTEST(stackprot, test_create_alt_thread)
{
/* Start thread */
k_thread_create(&alt_thread_data, alt_thread_stack_area, STACKSIZE,
(k_thread_entry_t)alternate_thread, NULL, NULL, NULL,
K_PRIO_COOP(1), K_USER, K_NO_WAIT);
/* Note that this sleep is required on SMP platforms where
* that thread will execute asynchronously!
*/
k_sleep(K_MSEC(100));
}
ZTEST_SUITE(stackprot, NULL, NULL, NULL, NULL, NULL);