forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			94 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
			
		
		
	
	
			94 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
| ==============================================
 | |
| Control Flow Verification Tool Design Document
 | |
| ==============================================
 | |
| 
 | |
| .. contents::
 | |
|    :local:
 | |
| 
 | |
| Objective
 | |
| =========
 | |
| 
 | |
| This document provides an overview of an external tool to verify the protection
 | |
| mechanisms implemented by Clang's *Control Flow Integrity* (CFI) schemes
 | |
| (``-fsanitize=cfi``). This tool, provided a binary or DSO, should infer whether
 | |
| indirect control flow operations are protected by CFI, and should output these
 | |
| results in a human-readable form.
 | |
| 
 | |
| This tool should also be added as part of Clang's continuous integration testing
 | |
| framework, where modifications to the compiler ensure that CFI protection
 | |
| schemes are still present in the final binary.
 | |
| 
 | |
| Location
 | |
| ========
 | |
| 
 | |
| This tool will be present as a part of the LLVM toolchain, and will reside in
 | |
| the "/llvm/tools/llvm-cfi-verify" directory, relative to the LLVM trunk. It will
 | |
| be tested in two methods:
 | |
| 
 | |
| - Unit tests to validate code sections, present in
 | |
|   "/llvm/unittests/tools/llvm-cfi-verify".
 | |
| - Integration tests, present in "/llvm/tools/clang/test/LLVMCFIVerify". These
 | |
|   integration tests are part of clang as part of a continuous integration
 | |
|   framework, ensuring updates to the compiler that reduce CFI coverage on
 | |
|   indirect control flow instructions are identified.
 | |
| 
 | |
| Background
 | |
| ==========
 | |
| 
 | |
| This tool will continuously validate that CFI directives are properly
 | |
| implemented around all indirect control flows by analysing the output machine
 | |
| code. The analysis of machine code is important as it ensures that any bugs
 | |
| present in linker or compiler do not subvert CFI protections in the final
 | |
| shipped binary.
 | |
| 
 | |
| Unprotected indirect control flow instructions will be flagged for manual
 | |
| review. These unexpected control flows may simply have not been accounted for in
 | |
| the compiler implementation of CFI (e.g. indirect jumps to facilitate switch
 | |
| statements may not be fully protected).
 | |
| 
 | |
| It may be possible in the future to extend this tool to flag unnecessary CFI
 | |
| directives (e.g. CFI directives around a static call to a non-polymorphic base
 | |
| type). This type of directive has no security implications, but may present
 | |
| performance impacts.
 | |
| 
 | |
| Design Ideas
 | |
| ============
 | |
| 
 | |
| This tool will disassemble binaries and DSO's from their machine code format and
 | |
| analyse the disassembled machine code. The tool will inspect virtual calls and
 | |
| indirect function calls. This tool will also inspect indirect jumps, as inlined
 | |
| functions and jump tables should also be subject to CFI protections. Non-virtual
 | |
| calls (``-fsanitize=cfi-nvcall``) and cast checks (``-fsanitize=cfi-*cast*``)
 | |
| are not implemented due to a lack of information provided by the bytecode.
 | |
| 
 | |
| The tool would operate by searching for indirect control flow instructions in
 | |
| the disassembly. A control flow graph would be generated from a small buffer of
 | |
| the instructions surrounding the 'target' control flow instruction. If the
 | |
| target instruction is branched-to, the fallthrough of the branch should be the
 | |
| CFI trap (on x86, this is a ``ud2`` instruction). If the target instruction is
 | |
| the fallthrough (i.e. immediately succeeds) of a conditional jump, the
 | |
| conditional jump target should be the CFI trap. If an indirect control flow
 | |
| instruction does not conform to one of these formats, the target will be noted
 | |
| as being CFI-unprotected.
 | |
| 
 | |
| Note that in the second case outlined above (where the target instruction is the
 | |
| fallthrough of a conditional jump), if the target represents a vcall that takes
 | |
| arguments, these arguments may be pushed to the stack after the branch but
 | |
| before the target instruction. In these cases, a secondary 'spill graph' in
 | |
| constructed, to ensure the register argument used by the indirect jump/call is
 | |
| not spilled from the stack at any point in the interim period. If there are no
 | |
| spills that affect the target register, the target is marked as CFI-protected.
 | |
| 
 | |
| Other Design Notes
 | |
| ~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Only machine code sections that are marked as executable will be subject to this
 | |
| analysis. Non-executable sections do not require analysis as any execution
 | |
| present in these sections has already violated the control flow integrity.
 | |
| 
 | |
| Suitable extensions may be made at a later date to include analysis for indirect
 | |
| control flow operations across DSO boundaries. Currently, these CFI features are
 | |
| only experimental with an unstable ABI, making them unsuitable for analysis.
 | |
| 
 | |
| The tool currently only supports the x86, x86_64, and AArch64 architectures.
 |