2026-06-04
Before 2017, any user-space process could execute SGDT, SIDT, SLDT, STR, and SMSW — instructions that read the addresses of the Global Descriptor Table, Interrupt Descriptor Table, Local Descriptor Table, Task Register, and CR0. These aren't privileged. They were designed in the 286 era when "store" meant "save to memory for the OS to inspect," and Intel never bothered to gate them on CPL.
That's a problem. The kernel's GDT and IDT live at specific virtual addresses. KASLR randomizes those addresses precisely so an attacker who finds a write primitive doesn't know where to aim. But a one-instruction leak — sidt [rsp] — hands the IDT's virtual address to userspace and defeats KASLR entirely. This is exactly how the 2014 "Hacking Team" exploits located kernel structures.
UMIP (User-Mode Instruction Prevention) is Intel's fix, shipped in Goldmont (2016) and now standard on modern Core/Xeon. Setting CR4.UMIP (bit 11) causes those five instructions to #GP fault when executed at CPL > 0. The kernel turns it on at boot if the CPU supports it:
grep umip /proc/cpuinfo0x800arch/x86/kernel/cpu/common.c:setup_umip()Real-world wrinkle: Wine and DOSBox break under UMIP. Old Windows code uses SMSW to detect protected mode — a legitimate, ancient idiom. Linux handles this in the #GP fault handler: fixup_umip_exception() in arch/x86/kernel/umip.c emulates the instruction and returns a dummy value (e.g., GDT base = 0xfffffffffffe0000, a fixed bogus address). The process never knows it faulted; KASLR stays intact.
Try it:
unsigned char idtr[10];
asm volatile("sidt %0" : "=m"(idtr));
printf("IDT base: %lx\n", *(unsigned long*)(idtr+2));
On a pre-2017 CPU or with UMIP disabled, you'll see the real kernel IDT virtual address (something like 0xfffffe0000000000 + KASLR offset). On a modern Linux box, you'll see the fixup value — consistently — across every run, regardless of boot.
Rule of thumb: If an instruction was specified before 1995 and isn't gated by CPL, assume it leaks something the kernel didn't want leaked. UMIP, SMAP, SMEP, LASS, and CET are all retrofits closing CPL holes that 1980s ISA designers never imagined would matter.
The cost is essentially zero: ~5 instructions per boot to set the bit, plus the rare fixup path for legacy emulators. The KASLR-defeat surface it closes is enormous.
