Securing Software
Run-time Enforcement
Goals
- Understand how Control-Flow Integrity (CFI) works
    - Analyze the strengths and weaknesses of CFI
- Construct basic control-flow graphs
 
- Type systems
    - Understand what type safety does (and does not) guarantee
- Assess whether a language is strongly typed
 
CFI
- What is the adversary model for CFI?
    - How does this compare to the adversary model for previous defenses we’ve seen (e.g., canaries)?
 
- What properties does CFI require to be sound?
- What guarantees does CFI give us?
    - How does this compare to previous defenses?
 
- 
    Why does CFI require a control-flow graph? 
- Control Flow Graphs (CFGs)
    - What is a basic block?
- How are CFGs defined?
- Building a CFG
        - What distinguishes a sensitive vs. an insensitive analysis?
- What properties might an analysis be sensitive to?
- Define soundness vs. completeness
 
 
- 
    Where and how does CFI instrument a binary? 
- 
    How can CFI instrumentation be verified? 
- 
    What’s the performance impact of CFI? 
- What kinds of attacks can bypass CFI?
Types
- Why do we need types?
- Why are types necessary for compilation?
- What kinds of properties can types provide?
    - Why don’t most type systems support verification?
 
- What does it mean for a language to be type safe?
- Why is C considered unsafe?
- Give some examples of untyped, weakly-typed, and strongly-typed languages
- 
    What elements do you need to prove that a language is type safe? 
- From safety to security
    - How can types be used to encode safety properties?
- What is non-interference? Why does it match our intuitive notion of secrecy?