patch submission: x86 trapsleds
Todd Mortimer via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 19 18:35:58 PDT 2017
Hello,
I have attached a patch that converts NOP padding emitted by
X86AsmBackend::writeNopData into a short JMP over a sequence of INT3
insructions. The idea is to remove potentially convenient NOP sleds
which may be used in ROP attacks. Programs which would have normally
executed through a NOP sled will now just JMP over the INT3s, but an
attacker hoping to hit the NOP sled on their way to some code will now
get a core dump.
This is similar in spirit to recent changes to lld:
https://reviews.llvm.org/D30886
This change doesn't appear to impact performance, and has been accepted
into llvm on OpenBSD.
This is my first patch submission to llvm, so if I have missed
something, just let me know and I will get it sorted out.
Thank you,
Todd
-------------- next part --------------
Index: lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
===================================================================
--- lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp (revision 308546)
+++ lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp (working copy)
@@ -325,28 +325,6 @@
/// bytes.
/// \return - true on success, false on failure
bool X86AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
- static const uint8_t Nops[10][10] = {
- // nop
- {0x90},
- // xchg %ax,%ax
- {0x66, 0x90},
- // nopl (%[re]ax)
- {0x0f, 0x1f, 0x00},
- // nopl 0(%[re]ax)
- {0x0f, 0x1f, 0x40, 0x00},
- // nopl 0(%[re]ax,%[re]ax,1)
- {0x0f, 0x1f, 0x44, 0x00, 0x00},
- // nopw 0(%[re]ax,%[re]ax,1)
- {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
- // nopl 0L(%[re]ax)
- {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
- // nopl 0L(%[re]ax,%[re]ax,1)
- {0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
- // nopw 0L(%[re]ax,%[re]ax,1)
- {0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
- // nopw %cs:0L(%[re]ax,%[re]ax,1)
- {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
- };
// This CPU doesn't support long nops. If needed add more.
// FIXME: Can we get this from the subtarget somehow?
@@ -357,16 +335,22 @@
return true;
}
- // 15 is the longest single nop instruction. Emit as many 15-byte nops as
- // needed, then emit a nop of the remaining length.
+ // Write 1 or 2 byte NOP sequences, or a longer trapsled, until
+ // we have written Count bytes
do {
- const uint8_t ThisNopLength = (uint8_t) std::min(Count, MaxNopLength);
- const uint8_t Prefixes = ThisNopLength <= 10 ? 0 : ThisNopLength - 10;
- for (uint8_t i = 0; i < Prefixes; i++)
- OW->write8(0x66);
- const uint8_t Rest = ThisNopLength - Prefixes;
- for (uint8_t i = 0; i < Rest; i++)
- OW->write8(Nops[Rest - 1][i]);
+ const uint8_t ThisNopLength = (uint8_t) std::min(Count, (uint64_t)127);
+ switch (ThisNopLength) {
+ case 0: break;
+ case 1: OW->write8(0x90);
+ break;
+ case 2: OW->write8(0x66);
+ OW->write8(0x90);
+ break;
+ default: OW->write8(0xEB);
+ OW->write8(ThisNopLength - 2);
+ for(uint8_t i = 2; i < ThisNopLength; ++i)
+ OW->write8(0xCC);
+ }
Count -= ThisNopLength;
} while (Count != 0);
More information about the llvm-commits
mailing list