And I should have prefaced this with: the reason we have to use PKU is because it's the only way we can get a read-deny bit on Intel, that still allows instruction fetches. Otherwise, PROT_EXEC implies PROT_READ.
Dave Voutila <d...@sisu.io> writes: > Marc Espie <marc.espie.open...@gmail.com> writes: > >> I'm curious about the new enforcement strategies. Unfortunately I'm a bit >> lost in the 1000+ pages of the intel manual. > > The protection keys documentation is thin because it's just another > layer in the rules for paging. I'll try to summarize and I'm sure > someone will correct me if I'm wrong :) > > Its design was to allow userland the ability to change read-deny and > write-deny permissions without having to go back through a syscall to > manipulate the page table entries. You'd have the kernel tie a "key" (32 > bit number) to entries in the page table and userland can manage the > permissions assigned to each key via the PKRU register. > > We toss most of that noise out the window. > > Instead, we have the kernel enforce that all keys except key=0 (the > default) have read-deny and write-deny set. > > When the kernel needs to mark a pages as X-Only, it assigns a non-zero > key to the pke bits. (Each page can have at most 1 key assigned...no key > is effectively key=0.) > > A lot of effort went into minimizing the opportunity for userland to > change the permissions on keys, which was the whole point of the PKRU > being writable by non-supervisor processes. > > We can't close this window 100%, but since we start the userland program > with its .text x-only, we minimize the ability to find a gadget or > inject code to execute a WRPKRU instruction to modify the permissions on > the keys. Any trap into the kernel, we check that the program didn't > attempt this. If that register changed, we kill the program > defensively. > > There are some implementation details I'm glossing over, like how the > PKRU is per-cpu, but that's the gist. > > If you'd like to see an implementation of what Intel *wanted* people to > *do* with PKU, the Linux kernel describes its API pretty well: > > https://www.kernel.org/doc/html/latest/core-api/protection-keys.html > > -dv