Skip to content

mpu stack guard: fix stack alignement #500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

jamike
Copy link
Contributor

@jamike jamike commented Jun 15, 2017

-1- The mpu stack guard feature requires that stack base is 32 bytes aligned.
(ARM DUI0553.pdf : Cortex M4 generic User guide mentions this constraint)
-2- Mpu stack guard test does not use kthread_spawn api, because it is not
useable with mpu stack guard: this api allocates the kthread structure at
stack base address, and mpu stack guard does not allow any access
in the 32 bytes after stack base address.
-3- Mpu stack guard test has been modified to be able to detect above issue.

@jamike jamike force-pushed the fix_arm_mpu_guard_stack_alignement branch 2 times, most recently from 6e262be to 233d892 Compare June 15, 2017 11:31
@galak galak self-assigned this Jun 15, 2017
@@ -65,6 +66,5 @@ void main(void)
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);
k_thread_create(&buf.thread, buf.stack, STACKSIZE, stack_guard_thread, NULL,NULL, NULL, PRIORITY, 0, K_NO_WAIT);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was recently fixed in #478, but the arm branch hasn't been rebased yet to pick it up.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you rebase, we should pickup the fix now in the arm branch

@@ -1,5 +1,4 @@
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
CONFIG_MULTITHREADING=y
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to enable multithreading explicitly, it's enabled by default

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree

printk("Canary = 0x%08x\tTest not passed.\n", buf.canary);

if (buf[num].canary != STACK_GUARD_CANARY) {
printk("Canary = 0x%08x\tTest not passed.\n", buf[num].canary);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried running this on frdm_k64f without stack guarding enabled and I don't hit this condition anymore.

Copy link
Contributor Author

@jamike jamike Jun 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your point is reproduced on nucleo_f401re.
If I moved struct k_thread thread before canary, the message test not passed occurs on nucleo_f401re (because canary gets corrupted before kthread structure get corrupted by stack overflow)
In this case , log is as follow:

STACK_ALIGN 4
MPU STACK GUARD Test
MPU STACK GUARD Test
MPU STACK GUARD Test
MPU STACK GUARD Test
Canary Initial Value = 0xf0cacc1a threads 0x20000b9c
Canary = 0xfffffff5 Test not passed.
***** MPU FAULT *****
Executing thread ID (thread): 0x20000b9c
Faulting instruction address: 0x80025b0
Data Access Violation
Address: 0x8000edb
Fatal fault in thread 0x20000b9c! Aborting.
***** HARD FAULT *****
Fault escalation (see below)
***** MPU FAULT *****
Executing thread ID (thread): 0x20000b9c
Faulting instruction address: 0x8001db6
Data Access Violation
Address: 0x8000edb
Fatal fault in ISR! Spinning...

On the other hand , the log present in README.rst is not describing a mpu guard working usecase: the instruction causing the initial MPU FAULT is at address 0x0, it should be a valid address showing that the MPU caught the instruction that has overflowed the stack.
=>i ll will update README.rst in next PR update

@galak
Copy link
Collaborator

galak commented Jun 15, 2017

I've updated the arm branch to be in sync with master to pull in the fix @MaureenHelm mentioned.

@galak galak requested a review from agross-oss June 16, 2017 13:14
@jamike jamike force-pushed the fix_arm_mpu_guard_stack_alignement branch from 233d892 to 13d8c7c Compare June 16, 2017 19:02
@jamike
Copy link
Contributor Author

jamike commented Jun 16, 2017

Comment taken into account and patch rebased.

Faulting instruction address: 0x8001db6
Data Access Violation
Address: 0x8000edb
Fatal fault in ISR! Spinning...

With the MPU enabled and the stack guard feature present:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might change "present" to "enabled" to parallel the previous heading

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed

Copy link
Contributor

@dbkinder dbkinder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one wording suggestion, but otherwise OK.

@andrewboie
Copy link
Contributor

You should consider implementing ARM versions of the stack definition macros, K_THREAD_STACK_DEFINE, etc. You can then reserve an additional 32-bytes at the beginning of the stack buffers for the guard area so that the effective stack size is the same as the user requested.

galak and others added 11 commits June 23, 2017 14:37
We define a variable to pickup a default for the bossa binary, however
we weren't using it.  Lets do so now.

Signed-off-by: Kumar Gala <[email protected]>
If we have more than one board of a given type we need to be able to
specify the board_id to select which specific board that the pyocd
command should target.  Introduce an environment variable PYOCD_BOARD_ID
to we can set that will get passed to the pyocd command that needs it.

Here's an example:

$ make -C samples/hello_world/ BOARD=frdm_k64f flash PYOCD_BOARD_ID=1234

Signed-off-by: Kumar Gala <[email protected]>
As there are multiple ways to flash or debug (pyOCD or openOCD) allow
the user to override the default.

Signed-off-by: Kumar Gala <[email protected]>
Allow to use an external debug adapter such as J-Link or ULINK
connected to a 20-pin JTAG header to flash the image. SWD is
the actual protocol used by the debug interface.

Signed-off-by: Piotr Mienkowski <[email protected]>
As other stm32 series support MPU, move common file in a file tree
useable by socs from other series

JIRA: ZEP-2220

Signed-off-by: Michel Jaouen <[email protected]>
Since all l4 socs support MPU, add MPU capability in KConfig.series

JIRA: ZEP-2220

Signed-off-by: Michel Jaouen <[email protected]>
Since not all socs from f3 series (i.e stm32f334x8 no MPU) have MPU
capability, add capability only for MPU capable socs in Kconfig.soc

JIRA: ZEP-2220

Signed-off-by: Michel Jaouen <[email protected]>
Add configuration and memory definitions to support STM32F103x8
Medium-density performance line SoC with 64 KB Flash.

Merge multiple files into single Kconfig.defconfig.stm32f103xx

Signed-off-by: Siddharth Chandrasekaran <[email protected]>
Following test changes, log info have changes and previous log info
with stack guard present shows an mpu error not caused by a stack
overflow caught by mpu stack guard feature.

Signed-off-by: Michel Jaouen <[email protected]>
@jamike jamike force-pushed the fix_arm_mpu_guard_stack_alignement branch from 9cec2ca to 1a620de Compare June 27, 2017 09:59
@jamike
Copy link
Contributor Author

jamike commented Jun 28, 2017

Are the changes fine for everybody?

@galak
Copy link
Collaborator

galak commented Jun 28, 2017

@MaureenHelm you good?

Copy link
Member

@MaureenHelm MaureenHelm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your point is reproduced on nucleo_f401re.
If I moved struct k_thread thread before canary, the message test not passed occurs on nucleo_f401re (because canary gets corrupted before kthread structure get corrupted by stack overflow)

Thanks, this fixes the frdm_k64f as well.

printk("MPU STACK GUARD Test\n");
printk("Canary Initial Value = 0x%x\n", buf.canary);
/* create stack_guard_thread */
k_thread_create(&buf[i].thread, buf[i].stack, STACKSIZE,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to use K_THREAD_STACK_SIZEOF instead of STACKSIZE

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah. That adjusts for the alignment adjustment. Otherwise you might get unlucky and bad things will happen. Good catch.

int i;
bool failed;

printk("STACK_ALIGN %x\n", STACK_ALIGN);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please prepend the value with 0x

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed

@galak galak force-pushed the arm branch 4 times, most recently from f95c1d6 to 4c01e1a Compare June 30, 2017 20:53
@@ -42,9 +42,98 @@ extern "C" {
#include <arch/arm/cortex_m/sys_io.h>
#include <arch/arm/cortex_m/nmi.h>
#endif
#if defined(CONFIG_MPU_STACK_GUARD)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late comment, but I found out that we need this regardless of whether or not the STACK_GUARD is set. The reason being that we need these in place to place the stacks in a specific place. Instead of noinit, we can set the location to a specific region during link.

How about just putting the STACK_SIZE in the #if def and set it to 32 or 4 based on the STACK_GUARD being set. The rest would always be defined.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stacks can really live anywhere that isn't in application memory space.
For stacks that are not defined as struct members, on x86 I put them in a special '.stacks' section which ends up in the kernel's "noinit".

@galak galak force-pushed the arm branch 3 times, most recently from 0f36cad to 1bc2fdc Compare July 7, 2017 15:32
Copy link
Contributor

@andrewboie andrewboie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The definition of the various K_THREAD_STACK_xxxx macros looks correct to me for the guard-type stack protection.

@agross-oss
Copy link
Collaborator

I reworked these patches and pushed to a new pull request. #987

@galak
Copy link
Collaborator

galak commented Aug 9, 2017

Merged #987, we can close this now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants