This is an archive of the discontinued LLVM Phabricator instance.

Cross-DSO control flow integrity (LLVM part)
ClosedPublic

Authored by eugenis on Dec 8 2015, 5:37 PM.

Details

Reviewers
kcc
pcc
Summary

An LTO pass that inserts a __cfi_check() function that validates a call based on a hash of the call-site-known type and the target pointer.

Diff Detail

Repository
rL LLVM

Event Timeline

eugenis updated this revision to Diff 42257.Dec 8 2015, 5:37 PM
eugenis updated this revision to Diff 42258.
eugenis retitled this revision from to Cross-DSO control flow integrity (LLVM part).
eugenis updated this object.
eugenis added reviewers: pcc, kcc.
eugenis set the repository for this revision to rL LLVM.
eugenis added a subscriber: llvm-commits.
pcc edited edge metadata.Dec 9 2015, 11:41 AM

Please also add design documentation to docs/ControlFlowIntegrityDesign.rst.

include/llvm/Transforms/IPO/CrossDSOCFI.h
21 ↗(On Diff #42257)

Why is this in a header? Were you planning to add unit tests for this function?

lib/Transforms/IPO/CrossDSOCFI.cpp
2

module's

11

Please do.

49

This will yield a different result depending on the endianness of the host machine.

64

This function doesn't look like it is defined anywhere.

90

This is already happening, no?

101

This won't be necessary if we teach the clang frontend to not emit bitset entries for declarations when doing cross-DSO.

105

This isn't exactly right; MDNode::isDistinct() corresponds directly to whether the bitset entry has global scope. I would check isDistinct here and assert that the identifier is an MDString (since we don't support hashing anything else).

lib/Transforms/IPO/PassManagerBuilder.cpp
603

I'd prefer if this stated what the function does (i.e. "create function that ...").

test/Transforms/CrossDSOCFI/basic.ll
6

Probably should check for hash values here since we know what they're going to be.

37–44

The body of the test could be made a lot simpler. E.g. these don't need to be vtables.

pcc added inline comments.Dec 9 2015, 2:48 PM
include/llvm/Transforms/IPO/CrossDSOCFI.h
22 ↗(On Diff #42258)

Oh, I see that you need this in the frontend. I wonder if there's a better way to do this that doesn't involve the frontend and the pass conspiring to use the same hash values? Maybe the bitset identifiers should be hash values in cross-DSO mode?

eugenis updated this revision to Diff 42583.Dec 11 2015, 2:25 PM
eugenis edited edge metadata.
eugenis marked 6 inline comments as done.
eugenis added inline comments.
include/llvm/Transforms/IPO/CrossDSOCFI.h
22 ↗(On Diff #42258)

Switched to hash values in bitset identifiers. The frontend now emits 2 bitset entries for each function or vtable entry: one with a string identifier for local checks, and one with a hash value for cross-DSO checks. We don't use hash values for local checks because of possible hash function collisions that could weaken the checks.

lib/Transforms/IPO/CrossDSOCFI.cpp
50

Moved to clang (see D15367) and fixed.

91

You mean insertion at the end of the module? I think so, but I wonder if anything else can be done to ensure that nothing gets reordered later.
We will catch any such problem at runtime.

102

Moved to a separate function and replaced a "continue" with an assert, just in case.

106

This is gone.

pcc added inline comments.Dec 11 2015, 3:34 PM
lib/Transforms/IPO/CrossDSOCFI.cpp
85

Early return here.

92

Sure, so let's word the FIXME like that.

112

I think this will break if the ConstantInts are not of type i64. Can you handle this gracefully?

141

Isn't this non-deterministic? I think it will depend on the ConstantInt addresses.

test/Transforms/CrossDSOCFI/basic.ll
18

I think you can make these tests more specific once the non-determinism has been fixed in the code.

eugenis updated this revision to Diff 42611.Dec 11 2015, 5:06 PM
eugenis marked 3 inline comments as done.
eugenis added inline comments.
lib/Transforms/IPO/CrossDSOCFI.cpp
112

Do we really need to handle this case? Frontend never inserts constantints in the bitset metadata that are not i64, and we can make this a requirement.

141

Good catch. Fixed.

pcc added inline comments.Dec 11 2015, 6:09 PM
lib/Transforms/IPO/CrossDSOCFI.cpp
113

It can be a requirement but we shouldn't produce invalid IR if it happens. I think the easiest thing to do is to return nullptr from CrossDSOCFI::extractBitSetTypeId if the ConstantInt is not i64.

test/Transforms/CrossDSOCFI/basic.ll
6

You can test for the label names as well (here and below).

eugenis updated this revision to Diff 42763.Dec 14 2015, 1:32 PM
eugenis marked an inline comment as done.
pcc accepted this revision.Dec 14 2015, 3:01 PM
pcc edited edge metadata.

LGTM with nit.

lib/Transforms/IPO/CrossDSOCFI.cpp
98

Can return void

This revision is now accepted and ready to land.Dec 14 2015, 3:01 PM
eugenis updated this revision to Diff 42787.Dec 14 2015, 3:04 PM
eugenis edited edge metadata.
eugenis marked an inline comment as done.
pcc added a comment.Dec 14 2015, 4:02 PM

Sorry, a few other nits I noticed.

lib/Transforms/IPO/CrossDSOCFI.cpp
122

You don't need to cast this.

125

Same here.

145

Don't shadow TypeId.

eugenis updated this revision to Diff 42807.Dec 14 2015, 5:27 PM
eugenis marked 3 inline comments as done.
eugenis closed this revision.Dec 15 2015, 3:04 PM

r255693, thanks!