This is an archive of the discontinued LLVM Phabricator instance.

Implement CFI for indirect calls via a member function pointer.
ClosedPublic

Authored by pcc on May 30 2018, 7:43 PM.

Details

Summary

Similarly to CFI on virtual and indirect calls, this implementation
tries to use program type information to make the checks as precise
as possible. The basic way that it works is as follows, where C
is the name of the class being defined or the target of a call and
the function type is assumed to be void().

For virtual calls:

  • Attach type metadata to the addresses of function pointers in vtables (not the functions themselves) of type void (B::*)() for each B that is a recursive dynamic base class of C, including C itself. This type metadata has an annotation that the type is for virtual calls (to distinguish it from the non-virtual case).
  • At the call site, check that the computed address of the function pointer in the vtable has type void (C::*)().

For non-virtual calls:

  • Attach type metadata to each non-virtual member function whose address can be taken with a member function pointer. The type of a function in class C of type void() is each of the types void (B::*)() where B is a most-base class of C. A most-base class of C is defined as a recursive base class of C, including C itself, that does not have any bases.
  • At the call site, check that the function pointer has one of the types void (B::*)() where B is a most-base class of C.

Diff Detail

Repository
rC Clang

Event Timeline

pcc created this revision.May 30 2018, 7:43 PM
pcc updated this revision to Diff 151090.Jun 12 2018, 7:16 PM
  • Address TODOs
pcc retitled this revision from [wip] Implement CFI for indirect calls via a member function pointer. to Implement CFI for indirect calls via a member function pointer..Jun 12 2018, 7:16 PM
pcc edited the summary of this revision. (Show Details)
pcc updated this revision to Diff 151272.Jun 13 2018, 4:46 PM
  • Add some more documentation to ControlFlowIntegrity.rst

I think it would be clearer to replace uses of 'member function pointer' with 'pointer to member function'; however, a google search shows that the usage of both terms is basically the same so not this might be just be my own bias coming through.

clang/lib/CodeGen/CodeGenModule.cpp
1413 ↗(On Diff #151272)

It'd be nice to have a test that reaches this.

clang/lib/CodeGen/CodeGenModule.h
1256 ↗(On Diff #151272)

Could be helpful to have a comment here to ensure there is no confusion interpreting this as 'the most-base classes' and not 'most of the base classes'.

clang/lib/Driver/SanitizerArgs.cpp
233 ↗(On Diff #151272)

This will cause supplying both options to fail with clang: error: unsupported option '-fsanitize=cfi-mfcall' for target .... Having it error out the same way as type generalization below where it states that cfi-cross-dso is unsupported with cfi-mfcall seems like a more helpful error.

clang/test/CodeGenCXX/type-metadata.cpp
281 ↗(On Diff #151272)

Any reason not to include AF64/CF64/FAF16 here?

compiler-rt/lib/ubsan/ubsan_handlers.cc
645 ↗(On Diff #151272)

s/member/pointer to member/ ?

compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc
126 ↗(On Diff #151272)

s/member/pointer to member/ ?

This revision is now accepted and ready to land.Jun 25 2018, 12:41 PM
pcc added inline comments.Jun 25 2018, 1:04 PM
clang/lib/CodeGen/CodeGenModule.cpp
1413 ↗(On Diff #151272)

I'll add one.

clang/lib/CodeGen/CodeGenModule.h
1256 ↗(On Diff #151272)

Will do.

clang/lib/Driver/SanitizerArgs.cpp
233 ↗(On Diff #151272)

The issue with that is that it would cause the flag combination -fsanitize=cfi -fsanitize-cfi-cross-dso to fail with an unsupported error. So I think it would need to work in a similar way as with the supported sanitizers. I guess I could add something after line 293 below instead.

clang/test/CodeGenCXX/type-metadata.cpp
281 ↗(On Diff #151272)

No, I just forgot to add them. I'll do that.

compiler-rt/lib/ubsan/ubsan_handlers.cc
645 ↗(On Diff #151272)

Makes sense.

compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc
126 ↗(On Diff #151272)

Ditto

This revision was automatically updated to reflect the committed changes.