Tested with a bunch of consumers on amd64, and lightly tested on sparc64 (me) and powerpc (cwen@).
51 lines
2.6 KiB
Plaintext
51 lines
2.6 KiB
Plaintext
$OpenBSD: patch-lib_Target_X86_X86InstrCompiler_td,v 1.5 2021/05/13 23:54:25 jca Exp $
|
|
|
|
- Add RETGUARD to clang for amd64. This security mechanism uses per-function
|
|
random cookies to protect access to function return instructions, with the
|
|
effect that the integrity of the return address is protected, and function
|
|
return instructions are harder to use in ROP gadgets.
|
|
|
|
On function entry the return address is combined with a per-function random
|
|
cookie and stored in the stack frame. The integrity of this value is verified
|
|
before function return, and if this check fails, the program aborts. In this way
|
|
RETGUARD is an improved stack protector, since the cookies are per-function. The
|
|
verification routine is constructed such that the binary space immediately
|
|
before each ret instruction is padded with int03 instructions, which makes these
|
|
return instructions difficult to use in ROP gadgets. In the kernel, this has the
|
|
effect of removing approximately 50% of total ROP gadgets, and 15% of unique
|
|
ROP gadgets compared to the 6.3 release kernel. Function epilogues are
|
|
essentially gadget free, leaving only the polymorphic gadgets that result from
|
|
jumping into the instruction stream partway through other instructions. Work to
|
|
remove these gadgets will continue through other mechanisms.
|
|
- Improve the X86FixupGadgets pass
|
|
|
|
Index: lib/Target/X86/X86InstrCompiler.td
|
|
--- lib/Target/X86/X86InstrCompiler.td.orig
|
|
+++ lib/Target/X86/X86InstrCompiler.td
|
|
@@ -268,6 +268,25 @@ def MORESTACK_RET_RESTORE_R10 : I<0, Pseudo, (outs), (
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
+// Pseudo instruction used by retguard
|
|
+
|
|
+// This is lowered to a JE 2; INT3; INT3. Prior to this pseudo should be a
|
|
+// compare instruction to ensure the retguard cookie is correct.
|
|
+// We use a pseudo here in order to avoid splitting the BB just before the return.
|
|
+// Splitting the BB and inserting a JE_1 over a new INT3 BB occasionally
|
|
+// resulted in incorrect code when a value from a byte register (CL) was
|
|
+// used as a return value. When emitted as a split BB, the single byte
|
|
+// register would sometimes be widened to 4 bytes, which would corrupt
|
|
+// the return value (ie mov %ecx, %eax instead of mov %cl, %al).
|
|
+let isCodeGenOnly = 1, Uses = [EFLAGS] in {
|
|
+def RETGUARD_JMP_TRAP: I<0, Pseudo, (outs), (ins), "", []>;
|
|
+}
|
|
+
|
|
+let isCodeGenOnly = 1 in {
|
|
+def JMP_TRAP: I<0, Pseudo, (outs), (ins), "", []>;
|
|
+}
|
|
+
|
|
+//===----------------------------------------------------------------------===//
|
|
// Alias Instructions
|
|
//===----------------------------------------------------------------------===//
|
|
|