Skip to main content

stack_scrub

Function stack_scrub 

Source
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 N bytes below the caller. A dead frame deeper than N keeps its bytes. N must 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.