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

Reply via email to