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.