diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2015-12-15 23:00:20 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2015-12-15 23:00:20 +0000 |
commit | fd6f92d5cb962a2b72c105dd8440ba831019964c (patch) | |
tree | 93571c9c74510077ebc664c91041741517ddcd21 /clang/docs | |
parent | 67849d56c3ce2459b8681da5e7935289018dcdbb (diff) | |
download | bcm5719-llvm-fd6f92d5cb962a2b72c105dd8440ba831019964c.tar.gz bcm5719-llvm-fd6f92d5cb962a2b72c105dd8440ba831019964c.zip |
Cross-DSO control flow integrity (Clang part).
Clang-side cross-DSO CFI.
* Adds a command line flag -f[no-]sanitize-cfi-cross-dso.
* Links a runtime library when enabled.
* Emits __cfi_slowpath calls is bitset test fails.
* Emits extra hash-based bitsets for external CFI checks.
* Sets a module flag to enable __cfi_check generation during LTO.
This mode does not yet support diagnostics.
llvm-svn: 255694
Diffstat (limited to 'clang/docs')
-rw-r--r-- | clang/docs/ControlFlowIntegrity.rst | 22 | ||||
-rw-r--r-- | clang/docs/ControlFlowIntegrityDesign.rst | 131 | ||||
-rw-r--r-- | clang/docs/UsersManual.rst | 6 |
3 files changed, 155 insertions, 4 deletions
diff --git a/clang/docs/ControlFlowIntegrity.rst b/clang/docs/ControlFlowIntegrity.rst index 3c76f0065ee..780ff882d0e 100644 --- a/clang/docs/ControlFlowIntegrity.rst +++ b/clang/docs/ControlFlowIntegrity.rst @@ -24,10 +24,14 @@ You can also enable a subset of available :ref:`schemes <cfi-schemes>`. As currently implemented, all schemes rely on link-time optimization (LTO); so it is required to specify ``-flto``, and the linker used must support LTO, for example via the `gold plugin`_. -To allow the checks to be implemented efficiently, the program must -be structured such that certain object files are compiled with CFI enabled, -and are statically linked into the program. This may preclude the use of -shared libraries in some cases. + +To allow the checks to be implemented efficiently, the program must be +structured such that certain object files are compiled with CFI +enabled, and are statically linked into the program. This may preclude +the use of shared libraries in some cases. Experimental support for +:ref:`cross-DSO control flow integrity <cfi-cross-dso>` exists that +does not have these requirements. This cross-DSO support has unstable +ABI at this time. .. _gold plugin: http://llvm.org/docs/GoldPlugin.html @@ -245,6 +249,16 @@ are typically defined outside of the linked program. # Ignore all types with a uuid attribute. type:attr:uuid +.. _cfi-cross-dso: + +Shared library support +====================== + +Use **-f[no-]sanitize-cfi-cross-dso** to enable the cross-DSO control +flow integrity mode, which allows all CFI schemes listed above to +apply across DSO boundaries. As in the regular CFI, each DSO must be +built with ``-flto``. + Design ====== diff --git a/clang/docs/ControlFlowIntegrityDesign.rst b/clang/docs/ControlFlowIntegrityDesign.rst index df25aad1a8c..b4aacd36567 100644 --- a/clang/docs/ControlFlowIntegrityDesign.rst +++ b/clang/docs/ControlFlowIntegrityDesign.rst @@ -366,3 +366,134 @@ Because the addresses of ``f``, ``g``, ``h`` are evenly spaced at a power of we can normally apply the `Alignment`_ and `Eliminating Bit Vector Checks for All-Ones Bit Vectors`_ optimizations thus simplifying the check at each call site to a range and alignment check. + +Shared library support +====================== + +**EXPERIMENTAL** + +The basic CFI mode described above assumes that the application is a +monolithic binary; at least that all possible virtual/indirect call +targets and the entire class hierarchy are known at link time. The +cross-DSO mode, enabled with **-f[no-]sanitize-cfi-cross-dso** relaxes +this requirement by allowing virtual and indirect calls to cross the +DSO boundary. + +Assuming the following setup: the binary consists of several +instrumented and several uninstrumented DSOs. Some of them may be +dlopen-ed/dlclose-d periodically, even frequently. + + - Calls made from uninstrumented DSOs are not checked and just work. + - Calls inside any instrumented DSO are fully protected. + - Calls between different instrumented DSOs are also protected, with + a performance penalty (in addition to the monolithic CFI + overhead). + - Calls from an instrumented DSO to an uninstrumented one are + unchecked and just work, with performance penalty. + - Calls from an instrumented DSO outside of any known DSO are + detected as CFI violations. + +In the monolithic scheme a call site is instrumented as + +.. code-block:: none + + if (!InlinedFastCheck(f)) + abort(); + call *f + +In the cross-DSO scheme it becomes + +.. code-block:: none + + if (!InlinedFastCheck(f)) + __cfi_slowpath(CallSiteTypeId, f); + call *f + +CallSiteTypeId +-------------- + +``CallSiteTypeId`` is a stable process-wide identifier of the +call-site type. For a virtual call site, the type in question is the class +type; for an indirect function call it is the function signature. The +mapping from a type to an identifier is an ABI detail. In the current, +experimental, implementation the identifier of type T is calculated as +follows: + + - Obtain the mangled name for "typeinfo name for T". + - Calculate MD5 hash of the name as a string. + - Reinterpret the first 8 bytes of the hash as a little-endian + 64-bit integer. + +It is possible, but unlikely, that collisions in the +``CallSiteTypeId`` hashing will result in weaker CFI checks that would +still be conservatively correct. + +CFI_Check +--------- + +In the general case, only the target DSO knows whether the call to +function ``f`` with type ``CallSiteTypeId`` is valid or not. To +export this information, every DSO implements + +.. code-block:: none + + void __cfi_check(uint64 CallSiteTypeId, void *TargetAddr) + +This function provides external modules with access to CFI checks for +the targets inside this DSO. For each known ``CallSiteTypeId``, this +functions performs an ``llvm.bitset.test`` with the corresponding bit +set. It aborts if the type is unknown, or if the check fails. + +The basic implementation is a large switch statement over all values +of CallSiteTypeId supported by this DSO, and each case is similar to +the InlinedFastCheck() in the basic CFI mode. + +CFI Shadow +---------- + +To route CFI checks to the target DSO's __cfi_check function, a +mapping from possible virtual / indirect call targets to +the corresponding __cfi_check functions is maintained. This mapping is +implemented as a sparse array of 2 bytes for every possible page (4096 +bytes) of memory. The table is kept readonly (FIXME: not yet) most of +the time. + +There are 3 types of shadow values: + + - Address in a CFI-instrumented DSO. + - Unchecked address (a “trusted” non-instrumented DSO). Encoded as + value 0xFFFF. + - Invalid address (everything else). Encoded as value 0. + +For a CFI-instrumented DSO, a shadow value encodes the address of the +__cfi_check function for all call targets in the corresponding memory +page. If Addr is the target address, and V is the shadow value, then +the address of __cfi_check is calculated as + +.. code-block:: none + + __cfi_check = AlignUpTo(Addr, 4096) - (V + 1) * 4096 + +This works as long as __cfi_check is aligned by 4096 bytes and located +below any call targets in its DSO, but not more than 256MB apart from +them. + +CFI_SlowPath +------------ + +The slow path check is implemented in compiler-rt library as + +.. code-block:: none + + void __cfi_slowpath(uint64 CallSiteTypeId, void *TargetAddr) + +This functions loads a shadow value for ``TargetAddr``, finds the +address of __cfi_check as described above and calls that. + +Position-independent executable requirement +------------------------------------------- + +Cross-DSO CFI mode requires that the main executable is built as PIE. +In non-PIE executables the address of an external function (taken from +the main executable) is the address of that function’s PLT record in +the main executable. This would break the CFI checks. diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index aa891c76304..2e259d205e8 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1042,6 +1042,12 @@ are listed below. Deprecated alias for ``-fsanitize-trap=undefined``. +.. option:: -fsanitize-cfi-cross-dso + + Enable cross-DSO control flow integrity checks. This flag modifies + the behavior of sanitizers in the ``cfi`` group to allow checking + of cross-DSO virtual and indirect calls. + .. option:: -fno-assume-sane-operator-new Don't assume that the C++'s new operator is sane. |