Re: PKU usage improvements for threads

From: Stephen Röttger
Date: Tue Aug 23 2022 - 10:05:45 EST


Hey Dave,

> I'd love to hear more why this behavior is useful and how it will be used.

The background is that we want to build a way to temporarily isolate threads
from each other, which we then want to use for CFI for V8 (Chrome's
JavaScript engine).

One of the main challenges we have is to protect the JIT compiled code from
an attacker with an arbitrary read/write primitive. For that, we're
planning to use PKU
to have access to some trusted memory, i.e. memory that can't be
corrupted by the
attacker.
You can find more details on our plans here:
https://docs.google.com/document/d/1O2jwK4dxI3nRcOJuPYkonhTkNQfbmwdvxQMyXgeaRHo/edit?usp=sharing

While designing this mitigation, we came up with two attack vectors for which we
believe we need help from the kernel to fix them, which are the two cases Kees
mentioned:
1) an attacker controlling some argument to certain VMA operations
like munmap().
2) an attacker corrupting the saved signal context on a signal handler stack.

On Mon, Aug 22, 2022 at 11:11 PM Dave Hansen <dave.hansen@xxxxxxxxx> wrote:
>
> On 8/22/22 13:40, Kees Cook wrote:
> > 1) It appears to be a bug that a thread without the correct PK can make
> > VMAs covered by a separate PK, out from under other threads. (e.g. mmap
> > a new mapping to wipe out the defined PK for it.) It seems that PK checks
> > should be made when modifying VMAs.
>
> Hi Kees,
>
> Could you give an example of this? Is this something along the lines of
> a mmap(MAP_FIXED) wiping out an earlier mapping? Or, is it more subtle
> than that?

Yes, that's one example. And the same applies to other operations on the
VMA. E.g. another case we'd like to prevent would be munmap(addr) where
addr is covered by a pkey to which the calling thread doesn't have access
permissions to.
You can find more details in this doc:
https://docs.google.com/document/d/1qqVoVfRiF2nRylL3yjZyCQvzQaej1HRPh3f5wj1AS9I/edit?usp=sharing

> > 2) It would be very helpful to have a mechanism for the signal stack to
> > be PK aware, in the sense that the kernel would switch to a predefined
> > PK. i.e. having a new interface to sigaltstack() which includes a PK.
>
> Are you thinking that when switching to the sigaltstack that it would
> also pick up a specific PKRU value? Or, that it would ensure that PKRU
> allows access to the sigaltstack's pkey?

Either of those would work for us.

> Logically something like this:
>
> stack_t sas = {
> ss_sp = stack_ptr;
> ss_flags = ... flags;
> ss_size = ...;
> ss_pkey = 12;
> };
>
> Then the kernel would set up RSP to point to ss_sp, and do (logically):
>
> pkkru &= ~(3<<(12*2)); // clear Write and Access-disable for pkey-12
>
> before building the signal frame running the signal handler?

Yeah, that would work for our use case.
We also have a doc discussing this in more detail :) :
https://docs.google.com/document/d/1OlnJbR5TMoaOAJsf4hHOc-FdTmYK2aDUI7d2hfCZSOo/edit?usp=sharing&resourcekey=0-v9UJXONYsnG5PlCBbcYqIw

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature