docs/design/coreclr/jit/Stack Buffer Overflow Protection.md
This document describes mechanisms in the .NET code generator to guard against stack buffer overflows at runtime.
While .NET is primarily a type and memory safe "managed" programming platform, it also offers lower-level facilities to allow for interop with native code, as well as some constructs that cannot be proven safe.
Use of these potentially "unsafe" constructs can threaten the integrity of the .NET runtime stack, enabling modification of key information on a stack frame, like the values of code and data addresses.
The .NET code generator includes stack buffer overflow protection (aka Guard Stack or "GS") so that the integrity of the stack can be checked at key points during program execution—walking the stack for EH or GC, or returning from methods.
Stack buffer overflow protection is one part of a more comprehensive set of .NET runtime security mitigations.
GS is intended to detect buffer overruns from unsafe on-stack buffers that might corrupt vulnerable data on the stack.
Unsafe buffers include:
stackalloc in C# (aka localloc, in IL)System.Runtime.CompilerServices.UnsafeValueTypeAttribute.
For instance, C# fixed-sized buffers.Vulnerable data on the stack frame generally includes addresses of code and data.
GS protects this data in two ways:
The net effect is that the stack layout for methods with unsafe buffers is as follows (note stacks grow down, so any caller frames would be above and any callee frames below)
| Stack Frame |
|---|
| memory arguments |
| return address |
| saved frame pointer |
| callee save area |
| stack cookie |
| fixed-sized unsafe buffers (without pointers) |
| fixed-sized unsafe buffers (with pointers) |
| shadow copies of vulnerable memory arguments |
| local variables |
| dynamically allocated buffers (localloc) |
| outgoing arguments |
| (stack pointer points here) |
Vulnerable memory arguments are relocated to a shadow copy region below the unsafe fixed buffers. Within the fixed-sized buffer region, buffers are ordered so that buffers containing pointers are at lower addresses than buffers without pointers.
A buffer overrun that can corrupt vulnerable data will likely also corrupt the stack cookie. The cookie value is verified before the method returns (and also when the runtime triggers stack walks).
In addition, the return address may also be protected by hardware mechanisms like Control-flow Enforcement Technology (CET), when these facilities are available on the host machine.
A cookie verification failure leads to an immediate, uncatchable process exit (FailFast) since the integrity
of the process is in question.