Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AArch64] Stack probing for function prologues #66524

Merged
merged 5 commits into from
Nov 30, 2023

Commits on Nov 30, 2023

  1. [AArch64] Stack probing for function prologues

    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,
      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 the page size.
    
    Change-Id: Ib31bc23d2806835bc6da822599f2bd2ecc18e4bf
    Co-authored-by: Oliver Stannard <[email protected]>
    momchil-velikov and ostannard committed Nov 30, 2023
    Configuration menu
    Copy the full SHA
    45213a1 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    2278dd2 View commit details
    Browse the repository at this point in the history
  3. Fix for a missing probe to the SVE callee-saved registers area

    In some cases a probe may be elided, resulting in more than 1024
    unprobed area at the top of the stack or decrement of the SP by more
    than a guard area size.
    momchil-velikov committed Nov 30, 2023
    Configuration menu
    Copy the full SHA
    94f8691 View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    603d90a View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    e28870b View commit details
    Browse the repository at this point in the history