17330f729Sjoerg====================== 27330f729SjoergControl Flow Integrity 37330f729Sjoerg====================== 47330f729Sjoerg 57330f729Sjoerg.. toctree:: 67330f729Sjoerg :hidden: 77330f729Sjoerg 87330f729Sjoerg ControlFlowIntegrityDesign 97330f729Sjoerg 107330f729Sjoerg.. contents:: 117330f729Sjoerg :local: 127330f729Sjoerg 137330f729SjoergIntroduction 147330f729Sjoerg============ 157330f729Sjoerg 167330f729SjoergClang includes an implementation of a number of control flow integrity (CFI) 177330f729Sjoergschemes, which are designed to abort the program upon detecting certain forms 187330f729Sjoergof undefined behavior that can potentially allow attackers to subvert the 197330f729Sjoergprogram's control flow. These schemes have been optimized for performance, 207330f729Sjoergallowing developers to enable them in release builds. 217330f729Sjoerg 227330f729SjoergTo enable Clang's available CFI schemes, use the flag ``-fsanitize=cfi``. 237330f729SjoergYou can also enable a subset of available :ref:`schemes <cfi-schemes>`. 247330f729SjoergAs currently implemented, all schemes rely on link-time optimization (LTO); 257330f729Sjoergso it is required to specify ``-flto``, and the linker used must support LTO, 267330f729Sjoergfor example via the `gold plugin`_. 277330f729Sjoerg 287330f729SjoergTo allow the checks to be implemented efficiently, the program must 297330f729Sjoergbe structured such that certain object files are compiled with CFI 307330f729Sjoergenabled, and are statically linked into the program. This may preclude 317330f729Sjoergthe use of shared libraries in some cases. 327330f729Sjoerg 337330f729SjoergThe compiler will only produce CFI checks for a class if it can infer hidden 347330f729SjoergLTO visibility for that class. LTO visibility is a property of a class that 357330f729Sjoergis inferred from flags and attributes. For more details, see the documentation 367330f729Sjoergfor :doc:`LTO visibility <LTOVisibility>`. 377330f729Sjoerg 387330f729SjoergThe ``-fsanitize=cfi-{vcall,nvcall,derived-cast,unrelated-cast}`` flags 397330f729Sjoergrequire that a ``-fvisibility=`` flag also be specified. This is because the 407330f729Sjoergdefault visibility setting is ``-fvisibility=default``, which would disable 417330f729SjoergCFI checks for classes without visibility attributes. Most users will want 427330f729Sjoergto specify ``-fvisibility=hidden``, which enables CFI checks for such classes. 437330f729Sjoerg 447330f729SjoergExperimental support for :ref:`cross-DSO control flow integrity 457330f729Sjoerg<cfi-cross-dso>` exists that does not require classes to have hidden LTO 467330f729Sjoergvisibility. This cross-DSO support has unstable ABI at this time. 477330f729Sjoerg 487330f729Sjoerg.. _gold plugin: https://llvm.org/docs/GoldPlugin.html 497330f729Sjoerg 507330f729Sjoerg.. _cfi-schemes: 517330f729Sjoerg 527330f729SjoergAvailable schemes 537330f729Sjoerg================= 547330f729Sjoerg 557330f729SjoergAvailable schemes are: 567330f729Sjoerg 577330f729Sjoerg - ``-fsanitize=cfi-cast-strict``: Enables :ref:`strict cast checks 587330f729Sjoerg <cfi-strictness>`. 597330f729Sjoerg - ``-fsanitize=cfi-derived-cast``: Base-to-derived cast to the wrong 607330f729Sjoerg dynamic type. 617330f729Sjoerg - ``-fsanitize=cfi-unrelated-cast``: Cast from ``void*`` or another 627330f729Sjoerg unrelated type to the wrong dynamic type. 637330f729Sjoerg - ``-fsanitize=cfi-nvcall``: Non-virtual call via an object whose vptr is of 647330f729Sjoerg the wrong dynamic type. 657330f729Sjoerg - ``-fsanitize=cfi-vcall``: Virtual call via an object whose vptr is of the 667330f729Sjoerg wrong dynamic type. 677330f729Sjoerg - ``-fsanitize=cfi-icall``: Indirect call of a function with wrong dynamic 687330f729Sjoerg type. 697330f729Sjoerg - ``-fsanitize=cfi-mfcall``: Indirect call via a member function pointer with 707330f729Sjoerg wrong dynamic type. 717330f729Sjoerg 727330f729SjoergYou can use ``-fsanitize=cfi`` to enable all the schemes and use 737330f729Sjoerg``-fno-sanitize`` flag to narrow down the set of schemes as desired. 747330f729SjoergFor example, you can build your program with 757330f729Sjoerg``-fsanitize=cfi -fno-sanitize=cfi-nvcall,cfi-icall`` 767330f729Sjoergto use all schemes except for non-virtual member function call and indirect call 777330f729Sjoergchecking. 787330f729Sjoerg 79*e038c9c4SjoergRemember that you have to provide ``-flto`` or ``-flto=thin`` if at 80*e038c9c4Sjoergleast one CFI scheme is enabled. 817330f729Sjoerg 827330f729SjoergTrapping and Diagnostics 837330f729Sjoerg======================== 847330f729Sjoerg 857330f729SjoergBy default, CFI will abort the program immediately upon detecting a control 867330f729Sjoergflow integrity violation. You can use the :ref:`-fno-sanitize-trap= 877330f729Sjoerg<controlling-code-generation>` flag to cause CFI to print a diagnostic 887330f729Sjoergsimilar to the one below before the program aborts. 897330f729Sjoerg 907330f729Sjoerg.. code-block:: console 917330f729Sjoerg 927330f729Sjoerg bad-cast.cpp:109:7: runtime error: control flow integrity check for type 'B' failed during base-to-derived cast (vtable address 0x000000425a50) 937330f729Sjoerg 0x000000425a50: note: vtable is of type 'A' 947330f729Sjoerg 00 00 00 00 f0 f1 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 5a 42 00 957330f729Sjoerg ^ 967330f729Sjoerg 977330f729SjoergIf diagnostics are enabled, you can also configure CFI to continue program 987330f729Sjoergexecution instead of aborting by using the :ref:`-fsanitize-recover= 997330f729Sjoerg<controlling-code-generation>` flag. 1007330f729Sjoerg 1017330f729SjoergForward-Edge CFI for Virtual Calls 1027330f729Sjoerg================================== 1037330f729Sjoerg 1047330f729SjoergThis scheme checks that virtual calls take place using a vptr of the correct 1057330f729Sjoergdynamic type; that is, the dynamic type of the called object must be a 1067330f729Sjoergderived class of the static type of the object used to make the call. 1077330f729SjoergThis CFI scheme can be enabled on its own using ``-fsanitize=cfi-vcall``. 1087330f729Sjoerg 1097330f729SjoergFor this scheme to work, all translation units containing the definition 1107330f729Sjoergof a virtual member function (whether inline or not), other than members 111*e038c9c4Sjoergof :ref:`ignored <cfi-ignorelist>` types or types with public :doc:`LTO 1127330f729Sjoergvisibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin`` 1137330f729Sjoergenabled and be statically linked into the program. 1147330f729Sjoerg 1157330f729SjoergPerformance 1167330f729Sjoerg----------- 1177330f729Sjoerg 1187330f729SjoergA performance overhead of less than 1% has been measured by running the 1197330f729SjoergDromaeo benchmark suite against an instrumented version of the Chromium 1207330f729Sjoergweb browser. Another good performance benchmark for this mechanism is the 1217330f729Sjoergvirtual-call-heavy SPEC 2006 xalancbmk. 1227330f729Sjoerg 1237330f729SjoergNote that this scheme has not yet been optimized for binary size; an increase 1247330f729Sjoergof up to 15% has been observed for Chromium. 1257330f729Sjoerg 1267330f729SjoergBad Cast Checking 1277330f729Sjoerg================= 1287330f729Sjoerg 1297330f729SjoergThis scheme checks that pointer casts are made to an object of the correct 1307330f729Sjoergdynamic type; that is, the dynamic type of the object must be a derived class 1317330f729Sjoergof the pointee type of the cast. The checks are currently only introduced 1327330f729Sjoergwhere the class being casted to is a polymorphic class. 1337330f729Sjoerg 1347330f729SjoergBad casts are not in themselves control flow integrity violations, but they 1357330f729Sjoergcan also create security vulnerabilities, and the implementation uses many 1367330f729Sjoergof the same mechanisms. 1377330f729Sjoerg 1387330f729SjoergThere are two types of bad cast that may be forbidden: bad casts 1397330f729Sjoergfrom a base class to a derived class (which can be checked with 1407330f729Sjoerg``-fsanitize=cfi-derived-cast``), and bad casts from a pointer of 1417330f729Sjoergtype ``void*`` or another unrelated type (which can be checked with 1427330f729Sjoerg``-fsanitize=cfi-unrelated-cast``). 1437330f729Sjoerg 1447330f729SjoergThe difference between these two types of casts is that the first is defined 1457330f729Sjoergby the C++ standard to produce an undefined value, while the second is not 1467330f729Sjoergin itself undefined behavior (it is well defined to cast the pointer back 1477330f729Sjoergto its original type) unless the object is uninitialized and the cast is a 1487330f729Sjoerg``static_cast`` (see C++14 [basic.life]p5). 1497330f729Sjoerg 1507330f729SjoergIf a program as a matter of policy forbids the second type of cast, that 1517330f729Sjoergrestriction can normally be enforced. However it may in some cases be necessary 1527330f729Sjoergfor a function to perform a forbidden cast to conform with an external API 1537330f729Sjoerg(e.g. the ``allocate`` member function of a standard library allocator). Such 154*e038c9c4Sjoergfunctions may be :ref:`ignored <cfi-ignorelist>`. 1557330f729Sjoerg 1567330f729SjoergFor this scheme to work, all translation units containing the definition 1577330f729Sjoergof a virtual member function (whether inline or not), other than members 158*e038c9c4Sjoergof :ref:`ignored <cfi-ignorelist>` types or types with public :doc:`LTO 1597330f729Sjoergvisibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin`` 1607330f729Sjoergenabled and be statically linked into the program. 1617330f729Sjoerg 1627330f729SjoergNon-Virtual Member Function Call Checking 1637330f729Sjoerg========================================= 1647330f729Sjoerg 1657330f729SjoergThis scheme checks that non-virtual calls take place using an object of 1667330f729Sjoergthe correct dynamic type; that is, the dynamic type of the called object 1677330f729Sjoergmust be a derived class of the static type of the object used to make the 1687330f729Sjoergcall. The checks are currently only introduced where the object is of a 1697330f729Sjoergpolymorphic class type. This CFI scheme can be enabled on its own using 1707330f729Sjoerg``-fsanitize=cfi-nvcall``. 1717330f729Sjoerg 1727330f729SjoergFor this scheme to work, all translation units containing the definition 1737330f729Sjoergof a virtual member function (whether inline or not), other than members 174*e038c9c4Sjoergof :ref:`ignored <cfi-ignorelist>` types or types with public :doc:`LTO 1757330f729Sjoergvisibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin`` 1767330f729Sjoergenabled and be statically linked into the program. 1777330f729Sjoerg 1787330f729Sjoerg.. _cfi-strictness: 1797330f729Sjoerg 1807330f729SjoergStrictness 1817330f729Sjoerg---------- 1827330f729Sjoerg 1837330f729SjoergIf a class has a single non-virtual base and does not introduce or override 1847330f729Sjoergvirtual member functions or fields other than an implicitly defined virtual 1857330f729Sjoergdestructor, it will have the same layout and virtual function semantics as 1867330f729Sjoergits base. By default, casts to such classes are checked as if they were made 1877330f729Sjoergto the least derived such class. 1887330f729Sjoerg 1897330f729SjoergCasting an instance of a base class to such a derived class is technically 1907330f729Sjoergundefined behavior, but it is a relatively common hack for introducing 1917330f729Sjoergmember functions on class instances with specific properties that works under 1927330f729Sjoergmost compilers and should not have security implications, so we allow it by 1937330f729Sjoergdefault. It can be disabled with ``-fsanitize=cfi-cast-strict``. 1947330f729Sjoerg 1957330f729SjoergIndirect Function Call Checking 1967330f729Sjoerg=============================== 1977330f729Sjoerg 1987330f729SjoergThis scheme checks that function calls take place using a function of the 1997330f729Sjoergcorrect dynamic type; that is, the dynamic type of the function must match 2007330f729Sjoergthe static type used at the call. This CFI scheme can be enabled on its own 2017330f729Sjoergusing ``-fsanitize=cfi-icall``. 2027330f729Sjoerg 2037330f729SjoergFor this scheme to work, each indirect function call in the program, other 204*e038c9c4Sjoergthan calls in :ref:`ignored <cfi-ignorelist>` functions, must call a 2057330f729Sjoergfunction which was either compiled with ``-fsanitize=cfi-icall`` enabled, 2067330f729Sjoergor whose address was taken by a function in a translation unit compiled with 2077330f729Sjoerg``-fsanitize=cfi-icall``. 2087330f729Sjoerg 2097330f729SjoergIf a function in a translation unit compiled with ``-fsanitize=cfi-icall`` 2107330f729Sjoergtakes the address of a function not compiled with ``-fsanitize=cfi-icall``, 2117330f729Sjoergthat address may differ from the address taken by a function in a translation 2127330f729Sjoergunit not compiled with ``-fsanitize=cfi-icall``. This is technically a 2137330f729Sjoergviolation of the C and C++ standards, but it should not affect most programs. 2147330f729Sjoerg 2157330f729SjoergEach translation unit compiled with ``-fsanitize=cfi-icall`` must be 2167330f729Sjoergstatically linked into the program or shared library, and calls across 2177330f729Sjoergshared library boundaries are handled as if the callee was not compiled with 2187330f729Sjoerg``-fsanitize=cfi-icall``. 2197330f729Sjoerg 220*e038c9c4SjoergThis scheme is currently supported on a limited set of targets: x86, 221*e038c9c4Sjoergx86_64, arm, arch64 and wasm. 2227330f729Sjoerg 2237330f729Sjoerg``-fsanitize-cfi-icall-generalize-pointers`` 2247330f729Sjoerg-------------------------------------------- 2257330f729Sjoerg 2267330f729SjoergMismatched pointer types are a common cause of cfi-icall check failures. 2277330f729SjoergTranslation units compiled with the ``-fsanitize-cfi-icall-generalize-pointers`` 2287330f729Sjoergflag relax pointer type checking for call sites in that translation unit, 2297330f729Sjoergapplied across all functions compiled with ``-fsanitize=cfi-icall``. 2307330f729Sjoerg 2317330f729SjoergSpecifically, pointers in return and argument types are treated as equivalent as 2327330f729Sjoerglong as the qualifiers for the type they point to match. For example, ``char*``, 2337330f729Sjoerg``char**``, and ``int*`` are considered equivalent types. However, ``char*`` and 2347330f729Sjoerg``const char*`` are considered separate types. 2357330f729Sjoerg 2367330f729Sjoerg``-fsanitize-cfi-icall-generalize-pointers`` is not compatible with 2377330f729Sjoerg``-fsanitize-cfi-cross-dso``. 2387330f729Sjoerg 2397330f729Sjoerg.. _cfi-canonical-jump-tables: 2407330f729Sjoerg 2417330f729Sjoerg``-fsanitize-cfi-canonical-jump-tables`` 2427330f729Sjoerg---------------------------------------- 2437330f729Sjoerg 2447330f729SjoergThe default behavior of Clang's indirect function call checker will replace 2457330f729Sjoergthe address of each CFI-checked function in the output file's symbol table 2467330f729Sjoergwith the address of a jump table entry which will pass CFI checks. We refer 2477330f729Sjoergto this as making the jump table `canonical`. This property allows code that 2487330f729Sjoergwas not compiled with ``-fsanitize=cfi-icall`` to take a CFI-valid address 2497330f729Sjoergof a function, but it comes with a couple of caveats that are especially 2507330f729Sjoergrelevant for users of cross-DSO CFI: 2517330f729Sjoerg 2527330f729Sjoerg- There is a performance and code size overhead associated with each 2537330f729Sjoerg exported function, because each such function must have an associated 2547330f729Sjoerg jump table entry, which must be emitted even in the common case where the 2557330f729Sjoerg function is never address-taken anywhere in the program, and must be used 2567330f729Sjoerg even for direct calls between DSOs, in addition to the PLT overhead. 2577330f729Sjoerg 2587330f729Sjoerg- There is no good way to take a CFI-valid address of a function written in 2597330f729Sjoerg assembly or a language not supported by Clang. The reason is that the code 2607330f729Sjoerg generator would need to insert a jump table in order to form a CFI-valid 2617330f729Sjoerg address for assembly functions, but there is no way in general for the 2627330f729Sjoerg code generator to determine the language of the function. This may be 2637330f729Sjoerg possible with LTO in the intra-DSO case, but in the cross-DSO case the only 2647330f729Sjoerg information available is the function declaration. One possible solution 2657330f729Sjoerg is to add a C wrapper for each assembly function, but these wrappers can 2667330f729Sjoerg present a significant maintenance burden for heavy users of assembly in 2677330f729Sjoerg addition to adding runtime overhead. 2687330f729Sjoerg 2697330f729SjoergFor these reasons, we provide the option of making the jump table non-canonical 2707330f729Sjoergwith the flag ``-fno-sanitize-cfi-canonical-jump-tables``. When the jump 2717330f729Sjoergtable is made non-canonical, symbol table entries point directly to the 2727330f729Sjoergfunction body. Any instances of a function's address being taken in C will 2737330f729Sjoergbe replaced with a jump table address. 2747330f729Sjoerg 2757330f729SjoergThis scheme does have its own caveats, however. It does end up breaking 2767330f729Sjoergfunction address equality more aggressively than the default behavior, 2777330f729Sjoergespecially in cross-DSO mode which normally preserves function address 2787330f729Sjoergequality entirely. 2797330f729Sjoerg 2807330f729SjoergFurthermore, it is occasionally necessary for code not compiled with 2817330f729Sjoerg``-fsanitize=cfi-icall`` to take a function address that is valid 2827330f729Sjoergfor CFI. For example, this is necessary when a function's address 2837330f729Sjoergis taken by assembly code and then called by CFI-checking C code. The 2847330f729Sjoerg``__attribute__((cfi_canonical_jump_table))`` attribute may be used to make 2857330f729Sjoergthe jump table entry of a specific function canonical so that the external 286*e038c9c4Sjoergcode will end up taking an address for the function that will pass CFI checks. 2877330f729Sjoerg 2887330f729Sjoerg``-fsanitize=cfi-icall`` and ``-fsanitize=function`` 2897330f729Sjoerg---------------------------------------------------- 2907330f729Sjoerg 2917330f729SjoergThis tool is similar to ``-fsanitize=function`` in that both tools check 2927330f729Sjoergthe types of function calls. However, the two tools occupy different points 2937330f729Sjoergon the design space; ``-fsanitize=function`` is a developer tool designed 2947330f729Sjoergto find bugs in local development builds, whereas ``-fsanitize=cfi-icall`` 2957330f729Sjoergis a security hardening mechanism designed to be deployed in release builds. 2967330f729Sjoerg 2977330f729Sjoerg``-fsanitize=function`` has a higher space and time overhead due to a more 2987330f729Sjoergcomplex type check at indirect call sites, as well as a need for run-time 2997330f729Sjoergtype information (RTTI), which may make it unsuitable for deployment. Because 3007330f729Sjoergof the need for RTTI, ``-fsanitize=function`` can only be used with C++ 3017330f729Sjoergprograms, whereas ``-fsanitize=cfi-icall`` can protect both C and C++ programs. 3027330f729Sjoerg 3037330f729SjoergOn the other hand, ``-fsanitize=function`` conforms more closely with the C++ 3047330f729Sjoergstandard and user expectations around interaction with shared libraries; 3057330f729Sjoergthe identity of function pointers is maintained, and calls across shared 3067330f729Sjoerglibrary boundaries are no different from calls within a single program or 3077330f729Sjoergshared library. 3087330f729Sjoerg 3097330f729SjoergMember Function Pointer Call Checking 3107330f729Sjoerg===================================== 3117330f729Sjoerg 3127330f729SjoergThis scheme checks that indirect calls via a member function pointer 3137330f729Sjoergtake place using an object of the correct dynamic type. Specifically, we 3147330f729Sjoergcheck that the dynamic type of the member function referenced by the member 3157330f729Sjoergfunction pointer matches the "function pointer" part of the member function 3167330f729Sjoergpointer, and that the member function's class type is related to the base 3177330f729Sjoergtype of the member function. This CFI scheme can be enabled on its own using 3187330f729Sjoerg``-fsanitize=cfi-mfcall``. 3197330f729Sjoerg 3207330f729SjoergThe compiler will only emit a full CFI check if the member function pointer's 3217330f729Sjoergbase type is complete. This is because the complete definition of the base 3227330f729Sjoergtype contains information that is necessary to correctly compile the CFI 3237330f729Sjoergcheck. To ensure that the compiler always emits a full CFI check, it is 3247330f729Sjoergrecommended to also pass the flag ``-fcomplete-member-pointers``, which 3257330f729Sjoergenables a non-conforming language extension that requires member pointer 3267330f729Sjoergbase types to be complete if they may be used for a call. 3277330f729Sjoerg 3287330f729SjoergFor this scheme to work, all translation units containing the definition 3297330f729Sjoergof a virtual member function (whether inline or not), other than members 330*e038c9c4Sjoergof :ref:`ignored <cfi-ignorelist>` types or types with public :doc:`LTO 3317330f729Sjoergvisibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin`` 3327330f729Sjoergenabled and be statically linked into the program. 3337330f729Sjoerg 3347330f729SjoergThis scheme is currently not compatible with cross-DSO CFI or the 3357330f729SjoergMicrosoft ABI. 3367330f729Sjoerg 337*e038c9c4Sjoerg.. _cfi-ignorelist: 3387330f729Sjoerg 339*e038c9c4SjoergIgnorelist 340*e038c9c4Sjoerg========== 3417330f729Sjoerg 3427330f729SjoergA :doc:`SanitizerSpecialCaseList` can be used to relax CFI checks for certain 3437330f729Sjoergsource files, functions and types using the ``src``, ``fun`` and ``type`` 3447330f729Sjoergentity types. Specific CFI modes can be be specified using ``[section]`` 3457330f729Sjoergheaders. 3467330f729Sjoerg 3477330f729Sjoerg.. code-block:: bash 3487330f729Sjoerg 3497330f729Sjoerg # Suppress all CFI checking for code in a file. 3507330f729Sjoerg src:bad_file.cpp 3517330f729Sjoerg src:bad_header.h 3527330f729Sjoerg # Ignore all functions with names containing MyFooBar. 3537330f729Sjoerg fun:*MyFooBar* 3547330f729Sjoerg # Ignore all types in the standard library. 3557330f729Sjoerg type:std::* 3567330f729Sjoerg # Disable only unrelated cast checks for this function 3577330f729Sjoerg [cfi-unrelated-cast] 3587330f729Sjoerg fun:*UnrelatedCast* 3597330f729Sjoerg # Disable CFI call checks for this function without affecting cast checks 3607330f729Sjoerg [cfi-vcall|cfi-nvcall|cfi-icall] 3617330f729Sjoerg fun:*BadCall* 3627330f729Sjoerg 3637330f729Sjoerg 3647330f729Sjoerg.. _cfi-cross-dso: 3657330f729Sjoerg 3667330f729SjoergShared library support 3677330f729Sjoerg====================== 3687330f729Sjoerg 3697330f729SjoergUse **-f[no-]sanitize-cfi-cross-dso** to enable the cross-DSO control 3707330f729Sjoergflow integrity mode, which allows all CFI schemes listed above to 3717330f729Sjoergapply across DSO boundaries. As in the regular CFI, each DSO must be 372*e038c9c4Sjoergbuilt with ``-flto`` or ``-flto=thin``. 3737330f729Sjoerg 3747330f729SjoergNormally, CFI checks will only be performed for classes that have hidden LTO 3757330f729Sjoergvisibility. With this flag enabled, the compiler will emit cross-DSO CFI 376*e038c9c4Sjoergchecks for all classes, except for those which appear in the CFI ignorelist 3777330f729Sjoergor which use a ``no_sanitize`` attribute. 3787330f729Sjoerg 3797330f729SjoergDesign 3807330f729Sjoerg====== 3817330f729Sjoerg 3827330f729SjoergPlease refer to the :doc:`design document<ControlFlowIntegrityDesign>`. 3837330f729Sjoerg 3847330f729SjoergPublications 3857330f729Sjoerg============ 3867330f729Sjoerg 3877330f729Sjoerg`Control-Flow Integrity: Principles, Implementations, and Applications <https://research.microsoft.com/pubs/64250/ccs05.pdf>`_. 3887330f729SjoergMartin Abadi, Mihai Budiu, Úlfar Erlingsson, Jay Ligatti. 3897330f729Sjoerg 3907330f729Sjoerg`Enforcing Forward-Edge Control-Flow Integrity in GCC & LLVM <http://www.pcc.me.uk/~peter/acad/usenix14.pdf>`_. 3917330f729SjoergCaroline Tice, Tom Roeder, Peter Collingbourne, Stephen Checkoway, 3927330f729SjoergÚlfar Erlingsson, Luis Lozano, Geoff Pike. 393