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

x86 LVI hardening #58

Merged
merged 8 commits into from
May 26, 2020
Merged

Commits on May 25, 2020

  1. Move RDF from Hexagon to Codegen

    RDF is designed to be target agnostic. Therefore it would be useful to have it available for other targets, such as X86.
    
    Based on a previous patch by Krzysztof Parzyszek
    
    Differential Revision: https://reviews.llvm.org/D75932
    scottconstable authored and Jethro Beekman committed May 25, 2020
    Configuration menu
    Copy the full SHA
    31537e6 View commit details
    Browse the repository at this point in the history
  2. [X86][NFC] Generalize the naming of "Retpoline Thunks" and related co…

    …de to "Indirect Thunks"
    
    There are applications for indirect call/branch thunks other than retpoline for Spectre v2, e.g.,
    
    https://software.intel.com/security-software-guidance/software-guidance/load-value-injection
    
    Therefore it makes sense to refactor X86RetpolineThunks as a more general capability.
    
    Differential Revision: https://reviews.llvm.org/D76810
    scottconstable authored and Jethro Beekman committed May 25, 2020
    Configuration menu
    Copy the full SHA
    a59d807 View commit details
    Browse the repository at this point in the history
  3. [X86] Refactor X86IndirectThunks.cpp to Accommodate Mitigations other…

    … than Retpoline
    
    Introduce a ThunkInserter CRTP base class from which new thunk types can inherit, e.g., thunks to mitigate https://software.intel.com/security-software-guidance/software-guidance/load-value-injection.
    
    Differential Revision: https://reviews.llvm.org/D76811
    scottconstable authored and Jethro Beekman committed May 25, 2020
    Configuration menu
    Copy the full SHA
    9003541 View commit details
    Browse the repository at this point in the history
  4. [X86] Add Indirect Thunk Support to X86 to mitigate Load Value Inject…

    …ion (LVI)
    
    This pass replaces each indirect call/jump with a direct call to a thunk that looks like:
    
    lfence
    jmpq *%r11
    
    This ensures that if the value in register %r11 was loaded from memory, then
    the value in %r11 is (architecturally) correct prior to the jump.
    Also adds a new target feature to X86: +lvi-cfi
    ("cfi" meaning control-flow integrity)
    The feature can be added via clang CLI using -mlvi-cfi.
    
    This is an alternate implementation to https://reviews.llvm.org/D75934 That merges the thunk insertion functionality with the existing X86 retpoline code.
    
    Differential Revision: https://reviews.llvm.org/D76812
    scottconstable authored and Jethro Beekman committed May 25, 2020
    Configuration menu
    Copy the full SHA
    6885c08 View commit details
    Browse the repository at this point in the history
  5. [X86] Add RET-hardening Support to mitigate Load Value Injection (LVI)

    Adding a pass that replaces every ret instruction with the sequence:
    
    pop <scratch-reg>
    lfence
    jmp *<scratch-reg>
    
    where <scratch-reg> is some available scratch register, according to the
    calling convention of the function being mitigated.
    
    Differential Revision: https://reviews.llvm.org/D75935
    scottconstable authored and Jethro Beekman committed May 25, 2020
    Configuration menu
    Copy the full SHA
    4ac04c2 View commit details
    Browse the repository at this point in the history
  6. [X86] Add a Pass that builds a Condensed CFG for Load Value Injection…

    … (LVI) Gadgets
    
    Adds a new data structure, ImmutableGraph, and uses RDF to find LVI gadgets and add them to a MachineGadgetGraph.
    
    More specifically, a new X86 machine pass finds Load Value Injection (LVI) gadgets consisting of a load from memory (i.e., SOURCE), and any operation that may transmit the value loaded from memory over a covert channel, or use the value loaded from memory to determine a branch/call target (i.e., SINK).
    
    Also adds a new target feature to X86: +lvi-load-hardening
    
    The feature can be added via the clang CLI using -mlvi-hardening.
    
    Differential Revision: https://reviews.llvm.org/D75936
    scottconstable authored and Jethro Beekman committed May 25, 2020
    Configuration menu
    Copy the full SHA
    96838f4 View commit details
    Browse the repository at this point in the history
  7. [X86] Add Support for Load Hardening to Mitigate Load Value Injection…

    … (LVI)
    
    After finding all such gadgets in a given function, the pass minimally inserts
    LFENCE instructions in such a manner that the following property is satisfied:
    for all SOURCE+SINK pairs, all paths in the CFG from SOURCE to SINK contain at
    least one LFENCE instruction. The algorithm that implements this minimal
    insertion is influenced by an academic paper that minimally inserts memory
    fences for high-performance concurrent programs:
    
    http://www.cs.ucr.edu/~lesani/companion/oopsla15/OOPSLA15.pdf
    
    The algorithm implemented in this pass is as follows:
    
    1. Build a condensed CFG (i.e., a GadgetGraph) consisting only of the following components:
      -SOURCE instructions (also includes function arguments)
      -SINK instructions
      -Basic block entry points
      -Basic block terminators
      -LFENCE instructions
    2. Analyze the GadgetGraph to determine which SOURCE+SINK pairs (i.e., gadgets) are already mitigated by existing LFENCEs. If all gadgets have been mitigated, go to step 6.
    3. Use a heuristic or plugin to approximate minimal LFENCE insertion.
    4. Insert one LFENCE along each CFG edge that was cut in step 3.
    5. Go to step 2.
    6. If any LFENCEs were inserted, return true from runOnFunction() to tell LLVM that the function was modified.
    
    By default, the heuristic used in Step 3 is a greedy heuristic that avoids
    inserting LFENCEs into loops unless absolutely necessary. There is also a
    CLI option to load a plugin that can provide even better optimization,
    inserting fewer fences, while still mitigating all of the LVI gadgets.
    The plugin can be found here: https://github.com/intel/lvi-llvm-optimization-plugin,
    and a description of the pass's behavior with the plugin can be found here:
    https://software.intel.com/security-software-guidance/insights/optimized-mitigation-approach-load-value-injection.
    
    Differential Revision: https://reviews.llvm.org/D75937
    scottconstable authored and Jethro Beekman committed May 25, 2020
    Configuration menu
    Copy the full SHA
    e54c3b9 View commit details
    Browse the repository at this point in the history
  8. [X86] Add inline assembly load hardening mitigation for Load Value In…

    …jection (LVI)
    
    Added code to X86AsmParser::emitInstruction() to add an LFENCE after each instruction that may load, and emit a warning if it encounters an instruction that may be vulnerable, but cannot be automatically mitigated.
    
    Differential Revision: https://reviews.llvm.org/D76158
    topperc authored and Jethro Beekman committed May 25, 2020
    Configuration menu
    Copy the full SHA
    fb13965 View commit details
    Browse the repository at this point in the history