diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/ControlFlowIntegrity.rst | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/docs/ControlFlowIntegrity.rst b/docs/ControlFlowIntegrity.rst index f57bdf5d2c..03e27d3ede 100644 --- a/docs/ControlFlowIntegrity.rst +++ b/docs/ControlFlowIntegrity.rst @@ -235,6 +235,54 @@ long as the qualifiers for the type they point to match. For example, ``char*``, ``-fsanitize-cfi-icall-generalize-pointers`` is not compatible with ``-fsanitize-cfi-cross-dso``. +.. _cfi-canonical-jump-tables: + +``-fsanitize-cfi-canonical-jump-tables`` +---------------------------------------- + +The default behavior of Clang's indirect function call checker will replace +the address of each CFI-checked function in the output file's symbol table +with the address of a jump table entry which will pass CFI checks. We refer +to this as making the jump table `canonical`. This property allows code that +was not compiled with ``-fsanitize=cfi-icall`` to take a CFI-valid address +of a function, but it comes with a couple of caveats that are especially +relevant for users of cross-DSO CFI: + +- There is a performance and code size overhead associated with each + exported function, because each such function must have an associated + jump table entry, which must be emitted even in the common case where the + function is never address-taken anywhere in the program, and must be used + even for direct calls between DSOs, in addition to the PLT overhead. + +- There is no good way to take a CFI-valid address of a function written in + assembly or a language not supported by Clang. The reason is that the code + generator would need to insert a jump table in order to form a CFI-valid + address for assembly functions, but there is no way in general for the + code generator to determine the language of the function. This may be + possible with LTO in the intra-DSO case, but in the cross-DSO case the only + information available is the function declaration. One possible solution + is to add a C wrapper for each assembly function, but these wrappers can + present a significant maintenance burden for heavy users of assembly in + addition to adding runtime overhead. + +For these reasons, we provide the option of making the jump table non-canonical +with the flag ``-fno-sanitize-cfi-canonical-jump-tables``. When the jump +table is made non-canonical, symbol table entries point directly to the +function body. Any instances of a function's address being taken in C will +be replaced with a jump table address. + +This scheme does have its own caveats, however. It does end up breaking +function address equality more aggressively than the default behavior, +especially in cross-DSO mode which normally preserves function address +equality entirely. + +Furthermore, it is occasionally necessary for code not compiled with +``-fsanitize=cfi-icall`` to take a function address that is valid +for CFI. For example, this is necessary when a function's address +is taken by assembly code and then called by CFI-checking C code. The +``__attribute__((cfi_canonical_jump_table))`` attribute may be used to make +the jump table entry of a specific function canonical so that the external +code will end up taking a address for the function that will pass CFI checks. ``-fsanitize=cfi-icall`` and ``-fsanitize=function`` ---------------------------------------------------- |