[PATCH] D119296: KCFI sanitizer

Sami Tolvanen via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 8 15:30:44 PST 2022


samitolvanen created this revision.
Herald added subscribers: dexonsmith, dang, jdoerfert, cryptoad.
Herald added a reviewer: aaron.ballman.
samitolvanen requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The KCFI sanitizer, enabled with -fsanitize=kcfi, implements a
forward-edge control flow integrity scheme in Clang for indirect
calls. It uses LLVM prefix data to store a type identifier for each
function and injects verification code before indirect calls.

Unlike the current CFI schemes implemented in LLVM, KCFI does not
require LTO, does not alter function references to point to a jump
table, and never breaks function address equality. KCFI is intended
to be used in low-level code, such as operating system kernels,
where the existing schemes can cause undue complications because
of the aforementioned properties. However, unlike the existing
schemes, KCFI is limited to validating only indirect calls and is
not compatible with executable-only memory.

KCFI does not provide runtime support. Users of the scheme are
expected to implement an error handling function with the following
signature:

  void __kcfi_check_fail(uint64_t id, void *ptr);

The first argument is the expected type identifier, and the second
argument is the address of the indirect call. This function must not
return unless -fsanitize-recover=kcfi is passed to Clang, in which
case code execution may continue after the error handler.

A KCFI type identifier is the xxHash64 of a C++ mangled typename,
with the first two bytes replaced with 0x10CF to make it easier for
binary tooling to detect the identifiers in programs where not all
functions have one. If a program contains indirect calls to assembly
functions, they must be manually annotated with the expected type
identifiers to prevent errors. To make this easier, Clang generates
a __kcfi_typeid_ symbol for each address-taken function declaration,
which can be used to annotate functions in assembly:

  .c:
    int f(void);
    int (*p)(void) = f;
    p();
  
  .s:
    .quad __kcfi_typeid_f
    .global f
    f:
      ...

Note that if additional data has been injected between the KCFI
type identifier and the start of the function, e.g. by using
-fpatchable-function-entry, the offset in bytes must be specified
using -fsanitize-kcfi-offset=<value> to avoid errors. The offset
must be the same for all indirectly called functions in every
translation unit.

Similarly to other sanitizers, KCFI checking can be disabled for
a function with a no_sanitize("kcfi") function attribute, or by
using the sanitizer special case list. However, as this may not
be fine-grained enough in cases where want to disable checking
only for specific calls, we also add the kcfi_unchecked attribute
for function pointers and function pointer types, which disables
checking for indirect calls made using an annotated pointer.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D119296

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/Features.def
  clang/include/clang/Basic/Sanitizers.def
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/SanitizerArgs.h
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Driver/SanitizerArgs.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/kcfi.c
  clang/test/CodeGen/kcfi_unchecked.c
  clang/test/Driver/fsanitize.c
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/Sema/attr-kcfi_unchecked.c

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D119296.406999.patch
Type: text/x-patch
Size: 33575 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220208/c27c7b57/attachment-0001.bin>


More information about the cfe-commits mailing list