diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-01-25 23:34:38 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-01-25 23:34:38 +0000 |
commit | a4225860cbaea66a30477500507710875fb84516 (patch) | |
tree | 82ce4808e09c768f47b91999583b6104bc688c2c /lib/ubsan | |
parent | 9f33bba73dfa49d4f4e0eac68a1768d13ea51642 (diff) |
[cfi] Cross-DSO CFI diagnostic mode (compiler-rt part)
* add __cfi_slowpath_diag with a 3rd parameter which is a pointer to
the diagnostic info for the ubsan handlers.
*__cfi_check gets a 3rd parameter as well.
* unify vcall/cast/etc and icall diagnostic info format, and merge
the handlers to have a single entry point (actually two points due
to abort/noabort variants).
* tests
Note that this comes with a tiny overhead in the non-diag mode:
cfi_slowpath must pass 0 as the 3rd argument to cfi_check.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@258744 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ubsan')
-rw-r--r-- | lib/ubsan/ubsan_handlers.cc | 29 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers.h | 17 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers_cxx.cc | 51 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers_cxx.h | 14 |
4 files changed, 62 insertions, 49 deletions
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index 5d82e9afc..d0dc6b569 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -523,8 +523,11 @@ void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) { Die(); } -static void handleCFIBadIcall(CFIBadIcallData *Data, ValueHandle Function, +static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function, ReportOptions Opts) { + if (Data->CheckKind != CFITCK_ICall) + Die(); + SourceLocation Loc = Data->Loc.acquire(); ErrorType ET = ErrorType::CFIBadType; @@ -544,16 +547,28 @@ static void handleCFIBadIcall(CFIBadIcallData *Data, ValueHandle Function, Diag(FLoc, DL_Note, "%0 defined here") << FName; } -void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *Data, - ValueHandle Function) { +namespace __ubsan { +SANITIZER_WEAK_ATTRIBUTE +void HandleCFIBadType(CFICheckFailData *Data, ValueHandle Vtable, + ReportOptions Opts); +} // namespace __ubsan + +void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data, + ValueHandle Value) { GET_REPORT_OPTIONS(false); - handleCFIBadIcall(Data, Function, Opts); + if (Data->CheckKind == CFITCK_ICall) + handleCFIBadIcall(Data, Value, Opts); + else + HandleCFIBadType(Data, Value, Opts); } -void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *Data, - ValueHandle Function) { +void __ubsan::__ubsan_handle_cfi_check_fail_abort(CFICheckFailData *Data, + ValueHandle Value) { GET_REPORT_OPTIONS(true); - handleCFIBadIcall(Data, Function, Opts); + if (Data->CheckKind == CFITCK_ICall) + handleCFIBadIcall(Data, Value, Opts); + else + HandleCFIBadType(Data, Value, Opts); Die(); } diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h index 6f309cf9a..1d4c41529 100644 --- a/lib/ubsan/ubsan_handlers.h +++ b/lib/ubsan/ubsan_handlers.h @@ -148,13 +148,24 @@ struct NonNullArgData { /// \brief Handle passing null pointer to function with nonnull attribute. RECOVERABLE(nonnull_arg, NonNullArgData *Data) -struct CFIBadIcallData { +/// \brief Known CFI check kinds. +/// Keep in sync with the enum of the same name in CodeGenFunction.h +enum CFITypeCheckKind : unsigned char { + CFITCK_VCall, + CFITCK_NVCall, + CFITCK_DerivedCast, + CFITCK_UnrelatedCast, + CFITCK_ICall, +}; + +struct CFICheckFailData { + CFITypeCheckKind CheckKind; SourceLocation Loc; const TypeDescriptor &Type; }; -/// \brief Handle control flow integrity failure for indirect function calls. -RECOVERABLE(cfi_bad_icall, CFIBadIcallData *Data, ValueHandle Function) +/// \brief Handle control flow integrity failures. +RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function) } diff --git a/lib/ubsan/ubsan_handlers_cxx.cc b/lib/ubsan/ubsan_handlers_cxx.cc index 3e81be671..739b4ca4a 100644 --- a/lib/ubsan/ubsan_handlers_cxx.cc +++ b/lib/ubsan/ubsan_handlers_cxx.cc @@ -15,6 +15,7 @@ #include "ubsan_platform.h" #if CAN_SANITIZE_UB +#include "ubsan_handlers.h" #include "ubsan_handlers_cxx.h" #include "ubsan_diag.h" #include "ubsan_type_hash.h" @@ -87,8 +88,9 @@ void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort( Die(); } -static void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable, - ReportOptions Opts) { +namespace __ubsan { +void HandleCFIBadType(CFICheckFailData *Data, ValueHandle Vtable, + ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); ErrorType ET = ErrorType::CFIBadType; @@ -96,18 +98,29 @@ static void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable, return; ScopedReport R(Opts, Loc, ET); - DynamicTypeInfo DTI = getDynamicTypeInfoFromVtable((void*)Vtable); - - static const char *TypeCheckKinds[] = { - "virtual call", - "non-virtual call", - "base-to-derived cast", - "cast to unrelated type", - }; + DynamicTypeInfo DTI = getDynamicTypeInfoFromVtable((void *)Vtable); + + const char *CheckKindStr; + switch (Data->CheckKind) { + case CFITCK_VCall: + CheckKindStr = "virtual call"; + break; + case CFITCK_NVCall: + CheckKindStr = "non-virtual call"; + break; + case CFITCK_DerivedCast: + CheckKindStr = "base-to-derived cast"; + break; + case CFITCK_UnrelatedCast: + CheckKindStr = "cast to unrelated type"; + break; + case CFITCK_ICall: + Die(); + } Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " "%1 (vtable address %2)") - << Data->Type << TypeCheckKinds[Data->TypeCheckKind] << (void *)Vtable; + << Data->Type << CheckKindStr << (void *)Vtable; // If possible, say what type it actually points to. if (!DTI.isValid()) @@ -116,18 +129,6 @@ static void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable, Diag(Vtable, DL_Note, "vtable is of type %0") << TypeName(DTI.getMostDerivedTypeName()); } +} // namespace __ubsan -void __ubsan::__ubsan_handle_cfi_bad_type(CFIBadTypeData *Data, - ValueHandle Vtable) { - GET_REPORT_OPTIONS(false); - HandleCFIBadType(Data, Vtable, Opts); -} - -void __ubsan::__ubsan_handle_cfi_bad_type_abort(CFIBadTypeData *Data, - ValueHandle Vtable) { - GET_REPORT_OPTIONS(true); - HandleCFIBadType(Data, Vtable, Opts); - Die(); -} - -#endif // CAN_SANITIZE_UB +#endif // CAN_SANITIZE_UB diff --git a/lib/ubsan/ubsan_handlers_cxx.h b/lib/ubsan/ubsan_handlers_cxx.h index 92050d99e..2ff014edf 100644 --- a/lib/ubsan/ubsan_handlers_cxx.h +++ b/lib/ubsan/ubsan_handlers_cxx.h @@ -25,12 +25,6 @@ struct DynamicTypeCacheMissData { unsigned char TypeCheckKind; }; -struct CFIBadTypeData { - SourceLocation Loc; - const TypeDescriptor &Type; - unsigned char TypeCheckKind; -}; - /// \brief Handle a runtime type check failure, caused by an incorrect vptr. /// When this handler is called, all we know is that the type was not in the /// cache; this does not necessarily imply the existence of a bug. @@ -40,14 +34,6 @@ void __ubsan_handle_dynamic_type_cache_miss( extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_handle_dynamic_type_cache_miss_abort( DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash); - -/// \brief Handle a control flow integrity check failure by printing a -/// diagnostic. -extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__ubsan_handle_cfi_bad_type(CFIBadTypeData *Data, ValueHandle Vtable); -extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__ubsan_handle_cfi_bad_type_abort(CFIBadTypeData *Data, ValueHandle Vtable); - } #endif // UBSAN_HANDLERS_H |