This is an archive of the discontinued LLVM Phabricator instance.

[X86] Instrument Control Flow For Indirect Branch Tracking
ClosedPublic

Authored by oren_ben_simhon on Nov 27 2017, 3:18 AM.

Details

Summary

CET (Control-Flow Enforcement Technology) introduces a new mechanism called IBT (Indirect Branch Tracking).
According to IBT, each Indirect branch should land on dedicated ENDBR instruction (End Branch).

The new pass adds ENDBR instructions for every indirect jmp/call (including jumps using jump tables / switches).

For more information, please see the following:
https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf

Diff Detail

Repository
rL LLVM

Event Timeline

craig.topper added inline comments.Nov 29 2017, 12:12 AM
lib/Target/X86/CMakeLists.txt
61 ↗(On Diff #124331)

I think this list was supposed to be in alphabetical order. Looks like someone already messed it up with X86CallingConv.cpp, but we should try to keep the rest in order.

lib/Target/X86/X86.h
54 ↗(On Diff #124331)

Add "Pass" to the end of this for consistency.

lib/Target/X86/X86IndirectBranchTracking.cpp
12 ↗(On Diff #124331)

Should this be ENDBR not ENDBRANCH if that's the name of the instruction?

lib/Target/X86/X86TargetMachine.cpp
57 ↗(On Diff #124331)

Should this be in a non-x86 specific place? If the x86 target isn't being built this won't exist.

oren_ben_simhon marked 4 inline comments as done.Nov 29 2017, 7:47 AM

Implemented comments posted till 11/29 (Thanks Craig)

craig.topper added inline comments.Nov 29 2017, 12:29 PM
lib/Target/X86/X86TargetMachine.cpp
430 ↗(On Diff #124751)

I believe addPreEmitPass is only called once to build the pass pipeline. We don't rerun it for each function. So I think you're really only checking the command line option here and not the function attribute. So I think that means that this doesn't work from clang.

pcc added a subscriber: pcc.Nov 29 2017, 1:00 PM
pcc added inline comments.
include/llvm/Target/TargetOptions.h
221 ↗(On Diff #124751)

This doesn't seem like it needs to be a TargetOption. Can you test for the function attribute directly in your pass?

pcc added inline comments.Nov 29 2017, 1:04 PM
lib/Target/TargetMachine.cpp
76 ↗(On Diff #124751)

This name seems very generic and doesn't really describe what the attribute does. How about something like cet-compatible?

oren_ben_simhon marked an inline comment as done.Nov 30 2017, 6:16 AM
oren_ben_simhon added inline comments.
include/llvm/Target/TargetOptions.h
221 ↗(On Diff #124751)

Sure, I will add a check in the pass for the function attribute.
Still, I would like the user to be able to give the llc the command option "instrument-control-flow" so that it will be enabled even if the attribute is not set in the function.
Is there a better way to do that than TargetOption?

lib/Target/TargetMachine.cpp
76 ↗(On Diff #124751)

I wouldn't like this attribute to be target independent. cet-compatible refers to Intel specific way to protect against control flow attacks. Does "cf-protection" make more sense?

Implemented comments posted until 11/30 (Thank you Craig and Peter)

pcc added inline comments.Nov 30 2017, 11:55 AM
include/llvm/Target/TargetOptions.h
221 ↗(On Diff #124751)

Why do you need this capability?

lib/Target/TargetMachine.cpp
76 ↗(On Diff #124751)

I assume that by "wouldn't" you meant "would".

I'm afraid that the name "cf-protection" doesn't really make sense to me either. There are a variety of ways to protect against control flow attacks, both purely software based (e.g. -fsanitize=cfi) and using hardware features such as CET, and specifically in the case of CET there also needs to be support from the rest of the operating system (so a user shouldn't expect this feature to provide any protection unless their hardware and operating system specifically supports it). So I think it would be less confusing if the attribute refers to the specific technology used.

include/llvm/Target/TargetOptions.h
221 ↗(On Diff #124751)

To run the control flow pass in LLC for example for debug purposes.
Do you suggest to add it only to my pass? but then the flag will not be global for all architectures. right?

lib/Target/TargetMachine.cpp
76 ↗(On Diff #124751)

First, I am sorry, peter, for the delayed response. I was off for couple of days.
You are correct, I meant would.

I believe that it would be good to stay in sync with GCC and ICC by using the same target-independent flag name of -cf-protection.

I believe it is good to make a target independent flags for SW based solution (like-fsantize=..) and HW based solution (like -cf-protection). Does this make sense or i am missing something?

pcc added inline comments.Dec 7 2017, 2:01 PM
include/llvm/Target/TargetOptions.h
221 ↗(On Diff #124751)

Please add it to your pass. If it turns out that we need it on other architectures, we can always move it.

lib/Target/TargetMachine.cpp
76 ↗(On Diff #124751)

I don't think it makes sense to have a target-independent attribute for control flow protection, even just for hardware-based. The software-based solutions in Clang involve adding checks at the IR generation level, so it does not require attributes. The mechanism that you are introducing works at the backend level, so it requires an attribute in order to communicate with the backend. We can already see that there is variation between software and hardware, so I think it is premature to assume that all hardware-based control flow protections can be implemented using a single attribute.

And irrespective of what we end up calling the flag on the Clang side, we can at least give it a more descriptive name in IR.

oren_ben_simhon marked an inline comment as done.Dec 12 2017, 3:15 AM
oren_ben_simhon added inline comments.
lib/Target/TargetMachine.cpp
76 ↗(On Diff #124751)

cf-protection flag has several options: Branch, Return, Full and None.
I think that if other architectures have different flavors of cf-protection then we could had these new flavors.
Could you please give me an example of a more descriptive notation to the attribute in the IR?

pcc added inline comments.Dec 12 2017, 5:51 PM
lib/Target/TargetMachine.cpp
76 ↗(On Diff #124751)

I think that if other architectures have different flavors of cf-protection then we could had these new flavors.

Again, that's assuming that the other architectures would even use attributes. Even if other architectures gain attributes for control flow protection then we can just name them after whatever the protection is called in that architecture.

Could you please give me an example of a more descriptive notation to the attribute in the IR?

shstk-compatible and ibt-compatible seem like perfectly fine names to me.

Implemented some of the comments posted until 12/12 (Thanks Peter)

Implemented all comments posted until 12/14 (Thanks Peter).

oren_ben_simhon marked an inline comment as done.Dec 14 2017, 12:07 PM
oren_ben_simhon added a reviewer: pcc.

Updated attribute name

craig.topper added inline comments.Dec 21 2017, 9:57 AM
lib/Target/X86/X86IndirectBranchTracking.cpp
32 ↗(On Diff #127593)

Prefix the command line option name with "x86-" and mention X86 in the description.

75 ↗(On Diff #127593)

Move this initialization of X86IndirectBranchTrackingPass::ID out of the anonymous namespace. I think some passes are inconsistent on this, but I think outside would be correct by coding standards.

76 ↗(On Diff #127593)

Use "end anonymous namespace" I think that's more consistent.

125 ↗(On Diff #127593)

accessed* I think.

oren_ben_simhon marked 4 inline comments as done.Dec 25 2017, 6:13 AM

Implemented comments posted until 12/24 (Thanks Craig)

This revision is now accepted and ready to land.Jan 3 2018, 10:39 AM
This revision was automatically updated to reflect the committed changes.