Page 1 of 1

RFC: Memory Protection Features

Posted: Thu Oct 09, 2014 4:05 pm
by jbrandmeyer
This is a request for comments and to see how much interest there is out there on these topics. I have written some modules that improve the penetration-resistance of my ChibiOS-enabled project, and I want to see how much interest there is in generalizing them for other users. My host processor is an STM32F4-series part.

I've added runtime support for the GCC stack canary (-fstack-protector). Very early in CRT startup (as a global constructor) the hardware random number generator is used to draw a random number for the stack canary. In the event that the RNG doesn't work in some way, the values \0, \r \f and (signed char)-1 are used, since they typically terminate the various C string handling functions.

I set up the Cortex-M MPU to enable W^X (write xor execute) support as well as make NULL inaccessible. In the absense of a specific flag telling GCC otherwise, GCC will assume that any accesses to NULL cause a fault, and may elliminate "dead" code based on that assumption. Of course, on STM32 (and possibly other Cortex-M processors) there is ordinary accessible data at NULL. A number of bugs in the Linux kernel were exploited due to this mismatch between hardware and the language model.

Finally, W^X works by making most of the general-purpose RAM non-executable on STM32. The CCM is already no-execute. A separate slice of RAM is marked executable and readable after loading it from a section called "ramtext", so that I can mix code in RAM with code in flash. Otherewise, the remainder is readable, writable, and non-executable.

Alas, most of my code at this point is highly processor-specific. W^X relies on programming the Cortex-M MPU, and stack protection relies entirely on the STM32F4 FWLIB and that part's hardware RNG. But these features aren't isolated to STM32, and other users may want it.

Re: RFC: Memory Protection Features

Posted: Thu Oct 09, 2014 4:19 pm
by Giovanni
This is very interesting, there are two possible places where MPU support could be implemented, at startup or within the ARMCMx port layer (which could make it more RTOS-aware potentially). The GCC stack protection feature is also interesting, I haven't had the time to look into it yet.

Let's collect feedback but this is something I am very willing to explore.

Giovanni

Re: RFC: Memory Protection Features

Posted: Thu Oct 09, 2014 5:31 pm
by jbrandmeyer
The stack protection runtime support is fairly straightforward. GCC expects libraries libssp.a and libssp_nonshared.a (depending on the exact link command) to be available at link time. The library must contain at least the following two symbols:

__stack_chk_guard: An integer of the native machine width. C libraries typically assign it void *. I used uintptr_t since it holds an integer and not a pointer. This integer stores the value used as the stack canary.
__stack_chk_fail: A function of type void (f)(void). This function is called in the event that a protected function's canary value differs from __stack_chk_guard immediately prior to returning. My implementation resets the processor with NVIC_SystemReset(), but a general implementation should give the user some choice of action. Maybe marking it weak is enough.

Actually, that's not entirely true. The symbols simply need to be available, they don't have to be in those particular libraries. So rather than hack the build system to compile my ssp.c into libssp.a, I created an empty archive and just added ssp.c into my project.

Yes, the folks running the Linux Standards Base really did omit vowels from one word, but not the other two in the symbol names.

Re: RFC: Memory Protection Features

Posted: Wed Oct 29, 2014 8:04 pm
by wdouglass
The normal stack-overflow detection in ChibiOS (CH_DBG_ENABLE_STACK_CHECK) has already saved my butt more then once...adding support for -fstack-protector will only make things better! I found this thread while searching for MPU support for ChibiOS, glad i'm not the only one thinking about this topic.

Re: RFC: Memory Protection Features

Posted: Sun Nov 16, 2014 4:21 pm
by barthess
Using MPU for stack overflow protection would be very nice, but I have no ideas how to realize it. And I have no ideas how to protect one thread from another because they are commonly need access to structures spread on whole memory space.

Re: RFC: Memory Protection Features

Posted: Wed Nov 19, 2014 12:17 pm
by tecnologic
Hi Together,

GCC Stackprotection and MPU features are very interessting for me as well.

On GCC -fstack-protector i have a question. In integrated it to my actual project for testing. Will this also Trigger on ChibiOS Tasks?
In my understanding it should be no difference for GCC cause RT sets SP on on entering the a Task. But how do i know which Task had the Stackoverflow? From Callstack?

regards

Tec

Re: RFC: Memory Protection Features

Posted: Wed Nov 19, 2014 12:38 pm
by Giovanni
The MPU support for full inter-thread protection is difficult because several reasons:

1) Stacks should be handled as thread-private but it is possible to pass pointers to variables to other threads and this would fail.
2) How to handle allocators? allocated data would need to be placed in a shared section.
3) Thread structures are placed inside the working area together with the stack. The stack should be private but the structure should be globally accessible. The kernel should be modified to separate the two but that could also require changes to chThdCreateStatic().
4) Macros defining accessibility of the declared variables should be introduced.

In my opinion full protection is not possible if not in the context of a specifically designed kernel. Realistically only stack protection using the MPU could be implemented by placing inaccessible guard pages on top and at bottom of each stack. This could be implemented as a new port or in the context of the existing ARMCMx port.

A specific security-oriented kernel is something I have been meditating for a while, features would be:
1) Full static, no allocation.
2) Fully protected.
3) Separate kernel and user spaces.
4) Kernel compiled and loaded separately from the application and including the bootloader for the application.
5) API called through a syscall interface.
6) Threads executed in user mode.
7) Threads can request the kernel to execute specific code in supervisor mode if permissions allow it.
8) Kernel able to be placed in ROM.
9) Forgot something?

It will be a post-3.0 project anyway.