This adds code to AArch64 function prologues to protect against stack
clash attacks by probing (writing to) the stack at regular enough
intervals to ensure that the guard page cannot be skipped over.
The patch depends on and maintains the following invariants:
- Upon function entry the caller guarantees that it has probed the stack (e.g. performed a store) at some address [sp, #N], where`0 <= N <= 1024`. This invariant comes from a requirement for compatibility with GCC.
- Any address range in the allocated stack, no smaller than stack-probe-size bytes contains at least one probe
- At any time the stack pointer is above or in the guard page
- Probes are performed in descreasing address order
The stack-probe-size is a function attribute that can be set by
a platform to correspond to the guard page size.
By default, the stack probe size is 4KiB, which is a safe default as
this is the smallest possible page size for AArch64. Linux uses a
64KiB guard for AArch64, so this can be overridden by the
stack-probe-size function attribute.
For small frames without a frame pointer (<= 240 bytes), no probes are
needed.
For larger frame sizes, LLVM always stores x29 to the stack. This
serves as an implicit stack probe. Thus, while allocating stack
objects the compiler assumes that the stack has been probed at [sp].
There are multiple probing sequences that can be emitted, depending on
the size of the stack allocation:
- A straight-line sequence of subtracts and stores, used when the allocation size is smaller than 5 guard pages.
- A loop allocating and probing one page size per iteration, plus at most a single probe to deal with the remainder, used when the allocation size is larger but still known at compile time.
- A loop which moves the SP down to the target value held in a register (or a loop, moving a scratch register to the target value help in SP), used when the allocation size is not known at compile-time, such as when allocating space for SVE values, or when over-aligning the stack. This is emitted in AArch64InstrInfo because it will also be used for dynamic allocas in a future patch.
- A single probe where the amount of stack adjustment is unknown, but is known to be less than or equal to a page size.
Co-authored-by: Oliver Stannard <oliver.stannard@linaro.org>
This comment doesn't sound right. Probing isn't just about making sure everything is probed before we leave the prologue; we also need to make sure probes are triggered in the correct order.