Re: comments on PMP enhancements

Nick Kossifidis

Hello Jonathan,

On 2/18/20 6:08 AM, Jonathan Behrens wrote:
Coming from an operating systems background, the concern about locking
PMP entries being absolutely necessary for security comes across as
overblown. I've never heard of a platform that provided locking
functionality for page tables, yet no one says that all operating
systems are insecure because of that. And page tables are vastly easier
to modify: any store instruction in the entire text segment could be
targeted to overwrite a PTE.
Page tables aren't vastly easier to modify, we are talking about doing
page table walking, finding the pte you want to modify and then modify
the one used by the hardware and also the version used internaly by the
OS (e.g. for lazy binding). While doing that the OS may change the page
table e.g. to merge ptes in hugepages and I'm just getting started (in
one of our projects we had to keep two page tables in sync across
different systems for doing RDMA between applications, we did that at
the kernel level with all the privileges we wanted and it was still a
chalenge). In contrast modifying a PMP entry takes one instruction and
since it's per-hart no one else will access / monitor it while
performing an attack.

Also page tables are managed by the OS wich is one privilege level above
the application that page tables are used to restrict. Applications
can't modify the page table and I don't think you'll find any platform /
OS where this is possible. On RISC-V for example U mode is not allowed
to access satp. In this case we are talking about PMP rules used to
restrict M-mode. If M-mode is allowed to modify them then we are a few
instructions away from rendering this mechanism useless. We are not
talking about having all PMP rules being locked, just the rules used to
restrict M-mode since there is no one above M-mode to manage M-mode

Page tables were invented mainly for managing virtual memory mappings,
memory protections came later on and in many cases are not enough (we
can only set permissions per-page, there are many cases where we want to
set different permissions within a page, that's where things like memory
tagging come into play). Because of their functionality they can't be
locked, they are meant to be modified all the time and switched on every
context switch. We can't compare PMP which only handles memory
protection with page tables. Protecting page tables is an open issue and
there are many approaches used for ensuring their integrity, from
hypervisors to encrypted memory etc. Not having heard of OSes being
insecure because of attacks on page tables doesn't mean they are secure,
it's just hard to deal with this issue and if someone has the privilege
to modify page tables (that is running with OS privileges) there are
easier and far more effective attacks to perform.

By contrast, overwriting PMP entries
requires dedicated PMP CSR instructions which appear in a handful of
functions at most (if that!). Thinking about it, you could achieve
basically the same effect as locking just by configuring the PMP so that
all M-mode executable regions were read only and contained no PMP CSR
Not having any code on M-mode that touches PMP CSRs doesn't make much
sense. If M-mode doesn't configure PMP, who will ? No other privilege
mode has access to the PMP registers and there are many cases in which
we would want to modify PMP settings e.g. when switching between trusted
apps. Also not every attack works via ROP or modifying the control flow
to re-use some code from elsewere, there are attacks that inject code as
well, or executing code with higher privileges (that's the attack we are
trying to mitigate in our proposal by the way). Finaly even if we accept
that the threat model here is a control-flow based attack, it's not
about how many functions modify the rules, it's about how many functions
are calling them.

None of this is to say that we /shouldn't/ supported locked PMP regions,
just that it is important to be realistic about what benefit in practice
they'd carry over the write XOR execute unlocked regions. Similarly, it
is definitely worth trying to keep PMP as simple as possible while still
providing the necessary functionality.
Let me point out that the current spec only allows locked rules for
restricting M-mode, and for good reasons. We are not trying to change
that nor make the mechanism more complicated. What we are trying to do
is mitigate a specific attack, allow for better / cleaner isolation
between M-mode and S/U-mode, and do that in the least invasive way
possible. I think the group's proposal does the job and provides a good
base for other mechanisms to be defined in the future.


Join to automatically receive all group messages.