Other meanings of Shadow stack
Computer security
Shadow stack is a computer security mechanism that stores protected copies of function return addresses so an attacker cannot easily redirect execution by corrupting the ordinary call stack. It primarily defends the backward edge of control flow against stack-based control-flow hijacking, including return-oriented programming attacks.
A shadow stack protects function returns by keeping a second, integrity-protected record of return addresses. When a function call creates a return address on the ordinary stack, the mechanism records the same address in storage that normal program instructions cannot freely modify; on return, the two values are compared, and execution is stopped or diverted if they differ.1 This targets the backward edge of a program’s control-flow graph: transfers from a called function back to its caller. The ordinary stack remains necessary for local variables, arguments, saved registers, and other data, but its return-address copy is no longer trusted on its own.
Shadow stacks complement, rather than replace, defenses such as stack canaries, address-space layout randomization, and forward-edge control-flow integrity. A canary can reveal some stack corruption, whereas a shadow stack directly checks the control-flow datum most useful for return-oriented programming.
Shadow stacks can be implemented in software, by compiler-inserted instrumentation, or in hardware with protected memory and dedicated control-flow instructions. LLVM’s ShadowCallStack instrumentation maintains a separate call stack, while hardware-assisted designs reduce the amount of checking required in ordinary code.2 Intel Control-flow Enforcement Technology, commonly abbreviated CET, defines a hardware shadow stack for supported processors; its operating-system support includes mechanisms for enabling protection and handling violations. The Linux kernel documents user-mode shadow stacks on x86 under CET, including the write restrictions that distinguish shadow-stack memory from ordinary writable memory.3
Compatibility is a central engineering issue. Calls, returns, exceptions, signals, context switches, setjmp/longjmp paths, hand-written assembly, dynamic loaders, and foreign-language interfaces must preserve the protected stack’s logical state.
A shadow stack makes return-address substitution substantially harder, but it does not establish complete control-flow integrity by itself. It generally prevents an attacker from changing where a legitimate return instruction goes; it does not necessarily constrain indirect calls, indirect jumps, function pointers, or virtual dispatch. Those forward-edge transfers require separate controls, such as compiler-based CFI or hardware branch-target checks.1
The mechanism also depends on trustworthy privileged software and correct handling of exceptional control flow. An attacker who gains arbitrary code execution may still abuse legitimate call-and-return sequences, corrupt non-control data, exploit an unchecked forward edge, or attack an unprotected component. Shadow-stack violations therefore indicate a serious integrity failure, but their absence is not proof that a program is memory-safe. Hardware protection, privilege separation, and careful ABI design determine how strong the practical guarantee becomes.
The difficult cases are often outside the ordinary call-and-return path. Operating systems must coordinate shadow stacks with asynchronous signals, interrupt or exception entry, thread creation, debugging, process inheritance, and non-local transfers such as longjmp. Compiler documentation also warns that software shadow-call-stack schemes can impose calling-convention constraints and may require a reserved register, which can make them unsuitable for unrestricted interoperability.2
Protected storage need not be physically separate silicon: the defining property is that ordinary compromised code cannot rewrite the authoritative return-address records. Conversely, merely duplicating return addresses in another writable buffer is not a shadow stack in the security sense. Research on control-flow integrity placed shadow stacks within a broader family of policies that protect execution paths, while modern implementations combine them with memory permissions and operating-system support rather than treating them as a complete standalone defense.13
Terminology varies by platform: “shadow stack” commonly describes hardware-enforced protection, while “shadow call stack” often denotes compiler instrumentation.
Help improve the encyclopedia. Reports go straight to the site manager.