This is an archive of the discontinued LLVM Phabricator instance.

[X86][CET] Shadow stack fix for setjmp/longjmp
ClosedPublic

Authored by mike.dvoretsky on May 24 2018, 12:57 AM.

Details

Summary

This is the new version of D46181, allowing setjmp/longjmp to work correctly with the Intel CET shadow stack by storing SSP on setjmp and fixing it on longjmp. The patch has been updated to use the cf-protection-return module flag instead of HasSHSTK, and the bug that caused D46181 to be reverted has been fixed with the test expanded to track that fix.

Diff Detail

Repository
rL LLVM

Event Timeline

Can you say more about the bug and what the fix was so I know where to focus?

The bug was in the emitLongJmpShadowStackFix and emitEHSjLjLongJmp. The longjmp builtin call is not a terminator, so it's followed by an "unreachable" IR instruction. The previous patch put the register restoration and the indirect branch at the end of the final basic block of the resulting code. It produced correct code on Linux, but on Mac where "unreachable" produces ud2 instructions this lead to a crash because the ud2 was left in place and ended up being before the longjmp code, regardless of whether the shadow stack fix was present. This patch moves the longjmp pseudo-instruction and the ud2 (if present) to the final basic block of the produced code and emits the longjmp logic before them, so the ud2 is correctly placed at the end of longjmp and is properly unreachable.

The code to pay attention to is the BuildMI calls in emitEHSjLjLongJmp and the code under this comment in emitLongJmpShadowStackFix (line 27894):
// Transfer the remainder of BB and its successor edges to sinkMBB.

The test has been updated to check for this bug as well, with the Mac triple and autogeneration ensuring that the ud2's position is seen in the test.

This revision is now accepted and ready to land.May 28 2018, 4:29 PM
This revision was automatically updated to reflect the committed changes.