Skip to content

Commit

Permalink
CFI: Print DSO names for failed cross-DSO icalls
Browse files Browse the repository at this point in the history
Reviewers: pcc

Reviewed By: pcc

Subscribers: kubamracek, delcypher, llvm-commits, kcc, #sanitizers

Differential Revision: https://reviews.llvm.org/D48583

llvm-svn: 335644
  • Loading branch information
vlad902 committed Jun 26, 2018
1 parent c85ca4c commit e745cf9
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 8 deletions.
15 changes: 15 additions & 0 deletions compiler-rt/lib/ubsan/ubsan_handlers.cc
Expand Up @@ -660,6 +660,21 @@ static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function,
if (!FName)
FName = "(unknown)";
Diag(FLoc, DL_Note, ET, "%0 defined here") << FName;

// If the failure involved different DSOs for the check location and icall
// target, report the DSO names.
const char *DstModule = FLoc.get()->info.module;
if (!DstModule)
DstModule = "(unknown)";

const char *SrcModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Opts.pc);
if (!SrcModule)
SrcModule = "(unknown)";

if (internal_strcmp(SrcModule, DstModule))
Diag(Loc, DL_Note, ET,
"check failed in %0, destination function located in %1")
<< SrcModule << DstModule;
}

namespace __ubsan {
Expand Down
25 changes: 17 additions & 8 deletions compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc
Expand Up @@ -137,16 +137,25 @@ void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
<< Data->Type << CheckKindStr << (void *)Vtable;

// If possible, say what type it actually points to.
if (!DTI.isValid()) {
const char *module = Symbolizer::GetOrInit()->GetModuleNameForPc(Vtable);
if (module)
Diag(Vtable, DL_Note, ET, "invalid vtable in module %0") << module;
else
Diag(Vtable, DL_Note, ET, "invalid vtable");
} else {
if (!DTI.isValid())
Diag(Vtable, DL_Note, ET, "invalid vtable");
else
Diag(Vtable, DL_Note, ET, "vtable is of type %0")
<< TypeName(DTI.getMostDerivedTypeName());
}

// If the failure involved different DSOs for the check location and vtable,
// report the DSO names.
const char *DstModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Vtable);
if (!DstModule)
DstModule = "(unknown)";

const char *SrcModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Opts.pc);
if (!SrcModule)
SrcModule = "(unknown)";

if (internal_strcmp(SrcModule, DstModule))
Diag(Loc, DL_Note, ET, "check failed in %0, vtable located in %1")
<< SrcModule << DstModule;
}
} // namespace __ubsan

Expand Down
42 changes: 42 additions & 0 deletions compiler-rt/test/cfi/cross-dso-diagnostic.cpp
@@ -0,0 +1,42 @@
// Check that cross-DSO diagnostics print the names of both modules

// RUN: %clangxx_cfi_diag -g -DSHARED_LIB -fPIC -shared -o %t_dso_suffix %s
// RUN: %clangxx_cfi_diag -g -o %t_exe_suffix %s -ldl
// RUN: %t_exe_suffix %t_dso_suffix 2>&1 | FileCheck %s

// UNSUPPORTED: win32
// REQUIRES: cxxabi

#include <dlfcn.h>
#include <stdio.h>

struct S1 {
virtual void f1();
};

#ifdef SHARED_LIB

void S1::f1() {}

__attribute__((visibility("default"))) extern "C"
void* dso_symbol() { return new S1(); }

#else

int main(int argc, char *argv[]) {
void *handle = dlopen(argv[1], RTLD_NOW);

// CHECK: runtime error: control flow integrity check for type 'void *()' failed during indirect function call
// CHECK: dso_symbol defined here
// CHECK: check failed in {{.*}}_exe_suffix, destination function located in {{.*}}_dso_suffix
void* (*fp)(void) =
reinterpret_cast<void*(*)(void)>(dlsym(handle, "dso_symbol"));
void *S = fp(); // trigger cfi-icall failure

// CHECK: runtime error: control flow integrity check for type 'S1' failed during cast to unrelated type
// CHECK: invalid vtable
// CHECK: check failed in {{.*}}_exe_suffix, vtable located in {{.*}}_dso_suffix
S1 *Scast = reinterpret_cast<S1*>(S); // trigger cfi-unrelated-cast failure
}

#endif // SHARED_LIB

0 comments on commit e745cf9

Please sign in to comment.