12 ms·
D4D4
- nokeya 1y agoMay this be exploited?
- pm215 1y agoIf you can already subvert the flow of execution enough to jump somewhere you shouldn't be, you probably have better targets elsewhere in the binary than a conditional branch.
- Normal_gaussian 1y agoCertainly true if you control the entire value; but if you can only flip a bit or two then this does provide a trampoline to increase the exploits range. Probably more of a "stick it in the toolbox for automatic use" rather than building an exploit around it type of situation however.
- JdeBP 1y agoYou have almost, with that statement, figured out what this really is and why it is there. * https://news.ycombinator.com/item?id=44970832 https://news.ycombinator.com/item?id=44970832
- Aurornis 1y agoA common exploit technique is to use what’s called “Return Oriented Programming” to jump to different locations throughout the file to trigger little “ROP gadget” instruction combos to accomplish what you need to do.
- rokkamokka 1y agoGod I love blame for use cases like this
- rasz 1y agoTLDR: Linker is kicking up the 4d3d3d3.
- GuinansEyebrows 1y agoNow Tayne I can get into!
- davedx 1y agoSounds like this could cause some awful heisenbugs if the instruction was ever reached?
- chaboud 1y agoDo you want obfuscated supply-chain state-actor vulnerabilities? Because this is how you get obfuscated supply-chain state-actor vulnerabilities! (Unless someone stays up all night to find the bugs....)
- Normal_gaussian 1y agoThis is cool; and yes, fairly clearly a bug with the commit showing both the name (trap instruction) and INT3 (debug) being used for x86. I definitely wouldn't have got this far looking at this - I'd have quickly assumed it was a sentinel value being used for padding and moved on with my day. Good work.
- skrebbel 1y agoCool story! If I may rant off topic a bit though, it boggles my mind that people put stuff like this: > [This patch] fills holes in executable sections with 0xd4 (ARM) or 0xef (MIPS). These trap instructions were suggested by Theo de Raadt. into commit messages, but not in the code. What's the cost? What's the downside to having a 2 to 3 line comment above a constant in a C file? Why pretend like all this is super obvious when clearly it isn't? There seems to be some unwritten cultural rule, particularly in FOSS land, that you're supposed to write code as if you're an all-knowing oracle, as if everything is obvious, and so comments are for losers (as are descriptive variable names). I simply can't understand how and why that developed.
- Ghoelian 1y agoA lot of developers think code should be self-documenting, which I fully agree with. Unfortunately though I don't think I've ever worked on a project that was actually self-documented, even though that is what the leads wanted.
- thayne 1y agoIt's also not always feasible. How would you write self documenting code that explained what the commit message did?
- ahofmann 1y agoBut this works as intended? The code isn't cluttered with documentation, that doesn't necessarily makes sense when reading the code, but by reading the commit, one can understand why the code was written like that.
- Dylan16807 1y agoCluttered? A sentence describing a magic value is not clutter.
- lintfordpickle 1y ago
- JdeBP 1y agoIt's not exploitable. It's an exploit mitigation, in fact. It's not a bug; it's intentional that it works this way. And Nathan Michaels didn't think that if you want to find Theo de Raadt writing on some subject, better try OpenBSD discussion fora, not the LLVM mailing list. (-: This was put into OpenBSD back in 2017. It's not "trap instructions". It's "trapsleds". The idea is to trap the sleds (a.k.a. slides) of NOP instructions that linkers used to put in between compiled code for alignment, and which could be exploited with "return-oriented programming" where an attacker could cause execution to jump to any address in the padding range (possibly needing the inexactitude because of constraints upon byte substitutions) and slide along all of the NOPs to the target function. * https://undeadly.org/cgi?action=article;sid=20170622065629 https://undeadly.org/cgi?action=article;sid=20170622065629 * https://isopenbsdsecu.re/mitigations/trapsled/ https://isopenbsdsecu.re/mitigations/trapsled/
- vintagedave 1y agoThe article states that on ARM Thumb, the instruction meant to be interpreted as a trap does not trap but jumps, instead.
- JdeBP 1y ago[flagged]
- colanderman 1y agoYou are misunderstanding the purpose of the initial jump in a trap sled. It is to redirect code which expects to flow through the sled past the traps, while leaving the traps for anything else which lands in that range. The padding the article is talking about lives between functions. It is not meant to be executed, nothing is needed to jump over it. (The unconditional bx lr before it is the return at the end of the function.)
- JdeBP 1y ago[flagged]
- k33n 1y agoI think it’s just an artifact of objdump and not even real.
- terminalbraid 1y agoHow does someone reconcile your statement with the second part of the article where they find the LLVM source that's explicitly generating it with comments suggesting why?
- colanderman 1y agoHex D4xxxxxx is indeed (almost) BRK... on ARM64 [1]. Being ARM32, these should be BKPT (hex BExx). [2] [1] https://developer.arm.com/documentation/ddi0602/2025-06/Base-Instructions/BRK--Breakpoint-instruction- https://developer.arm.com/documentation/ddi0602/2025-06/Base... [2] https://developer.arm.com/documentation/ddi0597/2024-09/Base-Instructions/BKPT--Breakpoint- https://developer.arm.com/documentation/ddi0597/2024-09/Base...
- deleted 1y ago[deleted]
- EDEADLINK 1y agoDigging into this a bit the best mnenomic I have found for a trap on ARM is "udf #0" which works on all the arm's on godbolt (and with -mthumb). This saves us from selecting between BRK and BKPT. I have not found a single sequence of bytes that would work on thumb, armv7 and AARCH64.
- mprovost 1y agoThis reminds me of coding with AI where slightly changing the prompt gives you different code and you don't really understand why but you use it anyway. In this case it's not even the compiler that's adding the incorrect instructions - it's the linker. Someday we'll just trust the AI to spit out working code the same way we assume that the C toolchain produces reasonable assembler. And when it doesn't it's remarkable enough to warrant a blog post and HN discussion.
- Arnavion 1y agoOnly tangentially related, but RISC-V intentionally makes any instruction starting with 0x0000 an illegal instruction instead of a NOP, for exactly the reason to prevent NOP-sleds. The official NOPs are 0x0001 (compressed 16-bit instruction) and 0x00000013 (regular 32-bit instruction; instructions are LE so 0x13 is the first byte in memory), both equivalent to addi x0, x0, 0, though many other instructions can act as NOPs by virtue of writing to the zero register.
- nneonneo 1y agoI'm confused, because d4d4d4d4 doesn't look like a trap in 32-bit ARM either: 0x0000000000000000: D4 D4 D4 D4 ldrble sp, [r4], #0x4d4 (from https://shell-storm.org/online/Online-Assembler-and-Disassembler/?opcodes=d4d4d4d4&arch=arm&endianness=little&baddr=0x00000000&dis_with_addr=True&dis_with_raw=True&dis_with_ins=True#disassembly https://shell-storm.org/online/Online-Assembler-and-Disassem...) This is "load byte at [r4 + 0x4d4] into sp, then add 0x4d4 to r4, but only if the condition flags signal a comparison result of less-than-or-equal". It is unlikely to be a useful instruction, since it causes the stack pointer register SP to be less than 0x100 (if [r4+0x4d4] is even a valid address), but it sure as heck isn't a trap. And, if the condition flags are right, this is just a NOP instruction. As far as I can tell, 0xd4d4d4d4 is only invalid on AArch64, and only because it happens to not yet be a defined instruction. 0xd4 does in fact introduce an exception generation instruction, but 0xd4d4xxxx is invalid as it is an unallocated combination of bits. However, nothing prevents this from being a defined instruction in the future, which makes 0xd4d4d4d4 a really bad choice as it could turn out to be a valid instruction in the future that performs an unexpected operation. In all, 0xd4 looks like a terrible choice for a padding byte for any ARM architecture, so it's a real mystery why this specific choice was made.
- thayne 1y agoWhy do the compilation units need to be padded if the functions don't need to be aligned.
- syncsynchalt 1y agoI'm a pretty rusty on ARM asm but from what I remember the opcodes to efficiently load constants into registers are pretty inflexible so it's common to store larger constants inline with the code. I'm guessing you need to keep the code aligned to preserve the alignment of these constants.