Clang++ Control Flow Integrity with shared_ptr crashes

Viewed 157

I'm trying to get control flow integrity to work with clang++ but I can't get the following code to run:

#include <memory>

struct X {
    X() {}
    virtual ~X() {};
};

int main() {
    std::shared_ptr<X> _asd = std::make_shared<X>();
    return 0;
}

If I compile and run this with

clang++ -fsanitize=cfi -fvisibility=hidden -flto -O2 -std=c++14 test.cpp
./a.out

the compiled program outputs:

[1]    45850 illegal hardware instruction (core dumped)  ./a.out

The resulting program crashes inside the make_shared function call - inside the standard library.

Some observations

When I make the destructor non-virtual it terminates successfully, so I initially thought it had something to do with cfi-vcall but it works flawlessly with the -fsanitize=cfi-vcall option.

The responsible compile flag seems to be -fsanitize=cfi-unrelated-cast - with all other available checks the application runs properly.

Looking at the disassembly it seems that the application is calling ~X() within make_shared (see also Additional Info below)?

unsure what's happening here

Questions

Is this a programming mistake? Is it in the compiler, standard library or in my code?

Is there a workaround to make it compile and run with CFI enabled?

Thanks a lot in advance!

Additional Info

here's the context (gef) one instruction before the invalid ud1 instruction.

[rbx+0x10] that rax is compared to is just zeros:

gef➤  x/1g $rbx + 0x10
0x557ec94ffec0: 0x0000000000000000

stack trace and surrounding code

1 instruction before ud1 instruction

0 Answers
Related