Make RAM dataspaces read-only (sth similar to mprotect in Linux)

Norman Feske norman.feske at ...1...
Fri Mar 3 09:13:10 CET 2017


Hi David,

> As a solution to this we thought of adding the possibility to make a
> RAM dataspace read-only, something which is similar to „mprotect“ in
> Linux. With this feature we would not need to detach dataspaces but
> writing accesses would still produce faults which we could track in
> order to detect them.
> 
> 
> Is such an alteration of RAM dataspaces possible? If yes, how would
> you do it?
> 
> What kind of fault would be triggered if someone tries to write to a 
> read-only memory?
> 
> Are we able to get information about such a fault in Genode?

there exists actually an issue for this topic:

  https://github.com/genodelabs/genode/issues/1633

Right now, the information of whether a dataspace is read-only (RO) or
read-writable (RW) is stored solely in core's 'Dataspace_component'
objects and it is fixed at the creation time the dataspace. I am
actually planning to rework Genode's page-fault handling code this year
and as part of this work, I plan to address the problem. My current
ideas look roughly as follows:


Dataspace aliasing

At some point, we had the idea to allow the creation of a ROM-dataspace
from a given RAM-dataspace. So the owner of a RAM dataspace could create
a read-only alias for the same dataspace. However, we eventually
dismissed this idea for two reasons. First, it complicates core's
'Dataspace_component' implementation quite substantially. In fact, we
needed to have two component objects for each dataspace in order to
differentiate the capabilities. This raises the question when to create
the RO-alias, at dataspace-creation time or only when needed? The former
imposes overhead on each dataspace, the latter results in more complex
code and raises meta-data accounting questions. Second, by introducing
aliases for dataspaces, we would lose the nice property of Genode (from
an security assessment perspective) that each physical memory page is
present in not more than one dataspace at any time.


RO attach

In addition to the read/write permission as stored in the dataspace, we
may add the same property to 'Region' objects, which are created
whenever a dataspace is attached via 'Region_map::attach'. By specifying
that a dataspace should be attached read-only, the resulting mapping
will always be read-only regardless of whether the underlying dataspace
is writable. As far as I see, the implementation wouldn't be too hard.
When resolving page faults, the pager would logically-AND the r/w
conditions of the traversed region maps (they may be nested so the
downgrade from RW to RO could happen at any level) with the property of
the dataspace.

I think that this mechanism would fit your checkpointing scenario quite
well because your custom runtime virtualizes the region-map access
already, doesn't it? So whenever the monitored component performs a RW
'attach' your RM service could silently perform a RO attach and thereby
observe an RM fault as soon as the monitored component attempts to
write. It would then respond to the fault by detaching the RO region,
followed by temporarily attaching the dataspace as writable.


Permanent downgrading (sealing)

We observed that in the most common use case for turning a RAM dataspace
into a ROM dataspace, there is no need to write to the dataspace at
arbitrary times. In fact, usually, such a RAM dataspace is populated
with data only once (e.g., when loading a shared library from a file
system, one would load the code segement into a RAM dataspace, but after
loading, this content would never change until the destruction of the
dataspace). This observation led to the idea to add a
'Ram_session::seal' operation that permanently downgrades a RAM
dataspace to become RO. In contrast to the RAM/ROM aliases discussed
above, this approach would not come at the expense of any overhead in
terms on meta data or complexity. The only slightly tricky part is the
transition from RW to RO where all existing RW mappings must flushed.

You mentioned that you'd like to differentiate read from write faults.
This may actually be not needed if you follow the RO-attach approach
because your runtime knows where all dataspaces are attached and whether
it attached the dataspaces as read-only or writable. That said, I would
not object to add this information to the 'Region_map::State' either,
which could be requested whenever a RM fault is observed.

Cheers
Norman

-- 
Dr.-Ing. Norman Feske
Genode Labs

http://www.genode-labs.com · http://genode.org

Genode Labs GmbH · Amtsgericht Dresden · HRB 28424 · Sitz Dresden
Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth




More information about the users mailing list