xref: /netbsd-src/external/apache2/llvm/dist/clang/docs/ControlFlowIntegrity.rst (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
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