Re: [PATCH v3 15/37] x86/mm: Check Shadow Stack page fault errors

Edgecombe, Rick P
2022-11-15T23:14:24Z

On Tue, 2022-11-15 at 22:07 +0100, Peter Zijlstra wrote:
> On Tue, Nov 15, 2022 at 08:03:06PM +0000, Edgecombe, Rick P wrote:
>
> > That's right. I think the assumption that needs to be broken in the
> > readers head is that you can satisfy a read fault with read-only
> > PTE.
> > This is kind of baked in all over the place with the zero-pfn, COW,
> > etc. Maybe I should try to start with that.
>
> Maybe something like:
>
> CoW -- pte_wrprotect() -- changes a SS page 'Write=0,Dirty=1' to
> 'Write=0,Dirty=0,CoW=1' which is a 'regular' RO page. A SS read from
> RET
> will #PF because it expects a SS page. Make sure to break the CoW so
> it
> can be restored to an SS page, as such force the write path and
> tickle
> pte_mkwrite().

Hmm, TBH I'm not sure it's more clear. I tried to take this and fill it
out more. Does it sound better?

When a page becomes COW it changes from a shadow stack permissioned
page (Write=0,Dirty=1) to (Write=0,Dirty=0,CoW=1), which is simply
read-only to the CPU. When shadow stack is enabled, a RET would
normally pop the shadow stack by reading it with a "shadow stack read"
access. However, in the COW case the shadow stack memory does not have
shadow stack permissions, it is read-only. So it will generate a fault.

For conventionally writable pages, a read can be serviced with a read
only PTE, and COW would not have to happen. But for shadow stack, there
isn't the concept of read-only shadow stack memory. If it is shadow
stack permissioned, it can be modified via CALL and RET instructions.
So COW needs to happen before any memory can be mapped with shadow
stack permissions.

Shadow stack accesses (read or write) need to be serviced with shadow
stack permissioned memory, so in the case of a shadow stack read
access, treat it as a WRITE fault so both COW will happen and the write
fault path will tickle maybe_mkwrite() and map the memory shadow stack.