1.. _cfi: 2 3============================ 4Control-Flow Integrity (CFI) 5============================ 6 7This document describes the current control-flow integrity (CFI) mechanism in 8QEMU. How it can be enabled, its benefits and deficiencies, and how it affects 9new and existing code in QEMU 10 11Basics 12------ 13 14CFI is a hardening technique that focusing on guaranteeing that indirect 15function calls have not been altered by an attacker. 16The type used in QEMU is a forward-edge control-flow integrity that ensures 17function calls performed through function pointers, always call a "compatible" 18function. A compatible function is a function with the same signature of the 19function pointer declared in the source code. 20 21This type of CFI is entirely compiler-based and relies on the compiler knowing 22the signature of every function and every function pointer used in the code. 23As of now, the only compiler that provides support for CFI is Clang. 24 25CFI is best used on production binaries, to protect against unknown attack 26vectors. 27 28In case of a CFI violation (i.e. call to a non-compatible function) QEMU will 29terminate abruptly, to stop the possible attack. 30 31Building with CFI 32----------------- 33 34NOTE: CFI requires the use of link-time optimization. Therefore, when CFI is 35selected, LTO will be automatically enabled. 36 37To build with CFI, the minimum requirement is Clang 6+. If you 38are planning to also enable fuzzing, then Clang 11+ is needed (more on this 39later). 40 41Given the use of LTO, a version of AR that supports LLVM IR is required. 42The easies way of doing this is by selecting the AR provided by LLVM:: 43 44 AR=llvm-ar-9 CC=clang-9 CXX=clang++-9 /path/to/configure --enable-cfi 45 46CFI is enabled on every binary produced. 47 48If desired, an additional flag to increase the verbosity of the output in case 49of a CFI violation is offered (``--enable-debug-cfi``). 50 51Using QEMU built with CFI 52------------------------- 53 54A binary with CFI will work exactly like a standard binary. In case of a CFI 55violation, the binary will terminate with an illegal instruction signal. 56 57Incompatible code with CFI 58-------------------------- 59 60As mentioned above, CFI is entirely compiler-based and therefore relies on 61compile-time knowledge of the code. This means that, while generally supported 62for most code, some specific use pattern can break CFI compatibility, and 63create false-positives. The two main patterns that can cause issues are: 64 65* Just-in-time compiled code: since such code is created at runtime, the jump 66 to the buffer containing JIT code will fail. 67 68* Libraries loaded dynamically, e.g. with dlopen/dlsym, since the library was 69 not known at compile time. 70 71Current areas of QEMU that are not entirely compatible with CFI are: 72 731. TCG, since the idea of TCG is to pre-compile groups of instructions at 74 runtime to speed-up interpretation, quite similarly to a JIT compiler 75 762. TCI, where the interpreter has to interpret the generic *call* operation 77 783. Plugins, since a plugin is implemented as an external library 79 804. Modules, since they are implemented as an external library 81 825. Directly calling signal handlers from the QEMU source code, since the 83 signal handler may have been provided by an external library or even plugged 84 at runtime. 85 86Disabling CFI for a specific function 87------------------------------------- 88 89If you are working on function that is performing a call using an 90incompatible way, as described before, you can selectively disable CFI checks 91for such function by using the decorator ``QEMU_DISABLE_CFI`` at function 92definition, and add an explanation on why the function is not compatible 93with CFI. An example of the use of ``QEMU_DISABLE_CFI`` is provided here:: 94 95 /* 96 * Disable CFI checks. 97 * TCG creates binary blobs at runtime, with the transformed code. 98 * A TB is a blob of binary code, created at runtime and called with an 99 * indirect function call. Since such function did not exist at compile time, 100 * the CFI runtime has no way to verify its signature and would fail. 101 * TCG is not considered a security-sensitive part of QEMU so this does not 102 * affect the impact of CFI in environment with high security requirements 103 */ 104 QEMU_DISABLE_CFI 105 static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb) 106 107NOTE: CFI needs to be disabled at the **caller** function, (i.e. a compatible 108cfi function that calls a non-compatible one), since the check is performed 109when the function call is performed. 110 111CFI and fuzzing 112--------------- 113 114There is generally no advantage of using CFI and fuzzing together, because 115they target different environments (production for CFI, debug for fuzzing). 116 117CFI could be used in conjunction with fuzzing to identify a broader set of 118bugs that may not end immediately in a segmentation fault or triggering 119an assertion. However, other sanitizers such as address and ub sanitizers 120can identify such bugs in a more precise way than CFI. 121 122There is, however, an interesting use case in using CFI in conjunction with 123fuzzing, that is to make sure that CFI is not triggering any false positive 124in remote-but-possible parts of the code. 125 126CFI can be enabled with fuzzing, but with some caveats: 1271. Fuzzing relies on the linker performing function wrapping at link-time. 128The standard BFD linker does not support function wrapping when LTO is 129also enabled. The workaround is to use LLVM's lld linker. 1302. Fuzzing also relies on a custom linker script, which is only supported by 131lld with version 11+. 132 133In other words, to compile with fuzzing and CFI, clang 11+ is required, and 134lld needs to be used as a linker:: 135 136 AR=llvm-ar-11 CC=clang-11 CXX=clang++-11 /path/to/configure --enable-cfi \ 137 -enable-fuzzing --extra-ldflags="-fuse-ld=lld" 138 139and then, compile the fuzzers as usual. 140