diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2015-09-10 02:18:02 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2015-09-10 02:18:02 +0000 |
commit | 35c115c610e169f484148fe1689d0e9f69012411 (patch) | |
tree | 773b8974a332bacf796216a393dae614c5f7f2a4 | |
parent | 26dfddc93583e5c4cb9abfff3675d89aa193fb1f (diff) | |
download | compiler-rt-35c115c610e169f484148fe1689d0e9f69012411.tar.gz |
CFI: Add diagnostic handler and tests for indirect call checker.
Differential Revision: http://reviews.llvm.org/D11858
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@247239 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/ubsan/ubsan_handlers.cc | 32 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers.h | 8 | ||||
-rw-r--r-- | test/cfi/bad-signature.c | 27 | ||||
-rw-r--r-- | test/cfi/external-call.c | 23 | ||||
-rw-r--r-- | test/cfi/lit.cfg | 2 |
5 files changed, 91 insertions, 1 deletions
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index c175baa46..68a823966 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -473,4 +473,36 @@ void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) { Die(); } +static void handleCFIBadIcall(CFIBadIcallData *Data, ValueHandle Function, + ReportOptions Opts) { + SourceLocation Loc = Data->Loc.acquire(); + if (ignoreReport(Loc, Opts)) + return; + + ScopedReport R(Opts, Loc); + + Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " + "indirect function call") + << Data->Type; + + SymbolizedStackHolder FLoc(getSymbolizedLocation(Function)); + const char *FName = FLoc.get()->info.function; + if (!FName) + FName = "(unknown)"; + Diag(FLoc, DL_Note, "%0 defined here") << FName; +} + +void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *Data, + ValueHandle Function) { + GET_REPORT_OPTIONS(false); + handleCFIBadIcall(Data, Function, Opts); +} + +void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *Data, + ValueHandle Function) { + GET_REPORT_OPTIONS(true); + handleCFIBadIcall(Data, Function, Opts); + Die(); +} + #endif // CAN_SANITIZE_UB diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h index 25093d432..6f309cf9a 100644 --- a/lib/ubsan/ubsan_handlers.h +++ b/lib/ubsan/ubsan_handlers.h @@ -148,6 +148,14 @@ struct NonNullArgData { /// \brief Handle passing null pointer to function with nonnull attribute. RECOVERABLE(nonnull_arg, NonNullArgData *Data) +struct CFIBadIcallData { + SourceLocation Loc; + const TypeDescriptor &Type; +}; + +/// \brief Handle control flow integrity failure for indirect function calls. +RECOVERABLE(cfi_bad_icall, CFIBadIcallData *Data, ValueHandle Function) + } #endif // UBSAN_HANDLERS_H diff --git a/test/cfi/bad-signature.c b/test/cfi/bad-signature.c new file mode 100644 index 000000000..43de1178f --- /dev/null +++ b/test/cfi/bad-signature.c @@ -0,0 +1,27 @@ +// RUN: %clangxx -o %t1 %s +// RUN: %t1 2>&1 | FileCheck --check-prefix=NCFI %s + +// RUN: %clangxx_cfi -o %t2 %s +// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi_diag -g -o %t3 %s +// RUN: %t3 2>&1 | FileCheck --check-prefix=CFI-DIAG %s + +#include <stdio.h> + +void f() { +} + +int main() { + // CFI: 1 + // NCFI: 1 + fprintf(stderr, "1\n"); + + // CFI-DIAG: runtime error: control flow integrity check for type 'void (int)' failed during indirect function call + // CFI-DIAG: f() defined here + ((void (*)(int))f)(42); // UB here + + // CFI-NOT: 2 + // NCFI: 2 + fprintf(stderr, "2\n"); +} diff --git a/test/cfi/external-call.c b/test/cfi/external-call.c new file mode 100644 index 000000000..f9cfabf77 --- /dev/null +++ b/test/cfi/external-call.c @@ -0,0 +1,23 @@ +// RUN: %clangxx_cfi -o %t1 %s +// RUN: %t1 c 1 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %t1 s 2 2>&1 | FileCheck --check-prefix=CFI %s + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> + +int main(int argc, char **argv) { + // CFI: 1 + fprintf(stderr, "1\n"); + + double (*fn)(double); + if (argv[1][0] == 's') + fn = sin; + else + fn = cos; + + fn(atof(argv[2])); + + // CFI: 2 + fprintf(stderr, "2\n"); +} diff --git a/test/cfi/lit.cfg b/test/cfi/lit.cfg index a7973b986..a9b8992ea 100644 --- a/test/cfi/lit.cfg +++ b/test/cfi/lit.cfg @@ -2,7 +2,7 @@ import lit.formats import os config.name = 'cfi' -config.suffixes = ['.cpp', '.test'] +config.suffixes = ['.c', '.cpp', '.test'] config.test_source_root = os.path.dirname(__file__) clangxx = ' '.join([config.clang] + config.cxx_mode_flags) |