On Fri, Jun 26, 2026 at 10:34:44AM -0700, Xiang Mei wrote: > With CONFIG_VMAP_STACK, kernel stacks are allocated in the vmalloc area, > which an unprivileged user can surround with attacker-controlled data by > spraying vmap allocations adjacent to a target stack (for example via > XDP_UMEM_REG, though other vmalloc spray paths work too). Today each > guarded vmalloc allocation is followed by a single unmapped guard page. > > A single guard page is not enough to contain the x86_64 ENTER > instruction used as a one-instruction stack pivot. ENTER imm16, imm8 > builds a stack frame and lowers RSP by: > > imm16 + 8 * (L + 1), L = imm8 & 0x1f > > imm16 is an unsigned 16-bit operand (ENTER never raises RSP), and L is > in [0, 31], so the maximum displacement of a single ENTER is: > > 0xffff + 8 * 0x20 = 0x100ff bytes > > That is more than enough to step off the current stack, across the > one-page guard, and into the adjacent sprayed pages. When those pages > contain a return sled feeding a ROP chain, reaching any ENTER gadget > (opcode 0xc8, abundant as both intended and unintended gadgets) turns a > control-flow hijack into full ROP execution without any register control > at the hijack site, making it a one-gadget-style primitive that > significantly eases exploitation. The pivot happens after the control > transfer, so it is not constrained by CFI (kCFI/FineIBT). > > Widen the guard region from one page to VMAP_GUARD_PAGES (0x11 pages, > 0x11000 bytes), which is the smallest whole-page span exceeding the > 0x100ff-byte maximum single-ENTER pivot. A pivot off the top of the > stack now lands in the unmapped guard and faults, instead of in mapped, > attacker-controlled memory. RANDOMIZE_KSTACK_OFFSET only perturbs RSP by > a sub-page amount, so it does not change the required width.
What's so special about enter? Why do we need to design our guard pages around it? FWIW, I can't find enter instructions in any of my kernel builds, nor can I convince gcc (on godbolt) to generate an enter instruction. If it's just "this is a single instruction that adjusts RSP", why is e.g. sub imm32, %rsp ok? FTR, I think it's fine that you're proposing more guard pages; virtual address space is virtually free on 64-bit architectures (apart from lower page table density, which may take a little toll on memory usage and/or page table caching). I'm just wondering why enter is being used as the concrete target for this. -- Pedro

