pub fn stack_scrub<const N: usize>()Expand description
Overwrites the N bytes of stack directly below the caller’s frame, at the
point of the call, with zeros. Best effort; defence in depth.
Call it from a function C after a deeper call chain below C has
returned. Those callees’ frames were allocated at the stack pointer C had
when it made its call, so the dead frames lie where stack_scrub now
lives: its own local buffer sits in the N bytes (plus its return address
and any alignment) immediately below C’s stack pointer, and the volatile
stores zero it. The idea is libsodium’s sodium_stackzero.
What it guarantees: the buffer’s N bytes are written with non-elidable
volatile stores and then a compiler fence, so they are zero when the
function returns, whatever the optimiser would otherwise do with a buffer
that is never read.
What it does not guarantee:
- It reaches only the
Nbytes below the caller. A dead frame deeper thanNkeeps its bytes.Nmust cover the deepest path from the caller that could have held the secret, with margin. - It relies on the dead frames having been in that region. A frame placed elsewhere (another caller’s stack, a heap copy) is not reached.
- It cannot reach registers. A secret left in a vector or general register is untouched.
- It is not a proof that no copy exists. Only the stack region the callees used is cleared; a copy the caller made, or one in a spill slot that a later call overwrote with other data, is not something this can see.
It is a hardening measure against later disclosure of dead stack memory. It is not a constant-time property and does not change any result.