How do old CPUs execute the new ENDBR64 and ENDBR32 instructions?
Asked Answered
B

2

8

At some point, Intel will begin shipping CPUs that support CET(Control-flow Enforcement Technology), which adds two instructions ENDBR64 and ENDBR32.

These two will be encoded as

F3 0F 1E FA   for ENDBR64 and 
F3 0F 1E FB   for ENDBR32 respectively. 

How will these be executed on older x86 CPUs?
For instance, a Core i5 or even the vintage Pentium II?

Update:

F3 0F = prefix indicating newer instructions
1E = ENDBR
FA = ENDBR64
Briard answered 13/5, 2019 at 21:40 Comment(7)
The instruction set reference lists them as "reserved - NOP". However It's unclear to me whether the cpu would know to fetch the last byte too.Nainsook
@Nainsook They are documented to have a modr/m byte, so it should be fine.Imbricate
It's not clear to me that it is the case. 0F 1F is listed as NOP /0 Ev so that does have modrm. But 0F 1E is just NOP.Nainsook
If I had an older Pentium CPU I would try these on it, but I don't. Does anyone here by chance have one?Briard
Older Intel documentation (June 2014) has that blank in the opcode map, which is "reserved and must not be used." Newer docs (January 2019) has it listed as "Reserved - NOP" and does not list the ENDBR instructions. So it might be a NOP on newer CPUs and something else (Illegal instruction? Nop?) on older ones. Safest would be to check the CPUID flags to check for support before running them.Fin
Your update to your question is sub-optimal. Section 3.1.1.2 of the Intel Manual states that the byte sequence F3.0F can have several meanings.Cloudless
@Cloudless I cannot find a manual that is earlier than 2011 or so.Briard
M
11

Older GDB decodes F3 0F 1E FA ENDBR64 as repz nop edx.

Single-stepping it on a Core 2 (Merom) in 64-bit mode produces no change in architectural state, and no faults / exceptions. (Tested in GDB 7.10 on an old Ubuntu 15.10 install).


According to https://gist.github.com/Quasilyte/b60c94b9cb608d5b1a359d54f1be8aca,
0f 1e /r is a 2-byte opcode that takes a ModRM, NOP r/m32, r32, the same as the standard multi-byte 0f 1f NOP that Intel documents.

It says it was added with Pentium Pro, so any PII / PIII or later would be fine.

https://github.com/NationalSecurityAgency/ghidra/issues/197#issuecomment-472906147 says AMD documents these extra NOP opcodes; Intel lists them as "reserved".

rep prefixes are usually silently ignored for opcodes they don't apply to. This gives Intel/AMD the flexibility to use REP as part of the mandatory prefixes for future instructions to create encodings that won't fault on old CPUs.


CPUs older than PPro, e.g. original Pentium, would probably fault on it. Just like for 0f 1f long NOP.


BTW, your attempt at decoding it makes no sense. 0f is the "escape" byte for 2-byte opcodes, so 1e push ds is unrelated to how this will decode. That's how 1e decodes by itself, without a 0f escape byte. (Except in 64-bit mode where it's invalid.)

Monochloride answered 14/5, 2019 at 2:44 Comment(1)
More specifically, endbr64 is within what is labeled "HINT_NOP" space. These are redundant encodings of the official multi-byte NOP instruction. HINT_NOP is explicitly reserved space for future instructions, but with the proviso that current processors will interpret them as NOP. This way, some future instructions like endbr64 can be added in this space if ignoring the opcode is a safe action to do on older processors. A similar trick was done for pause before HINT_NOP was invented. (pause is encoded as if repz nop.)Renny
H
1

I've encountered a problem with the ENDBR32 instruction myself recently. VirtualBox version 6.0.14_Ubuntu r132055 incorrectly decodes ENDBR32 as a sequence of an illegal opcode and STI. This would produce all sorts of errors as I need interrupts disabled. The only solution I came up with is to invoke GCC with -fcf-protection=branch and -mmanual-endbr options enabled.

VirtualBox debug console on the top, Objdump on the bottom

Histone answered 6/12, 2019 at 19:24 Comment(1)
Was this fixed? Wow.Ng

© 2022 - 2024 — McMap. All rights reserved.