Marc Espie <[email protected]> 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
