-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hello Udo,
do you see any issues to extend the revoke syscall by a protection domain (pd) parameter ? Currently implicitly the current protection domain of the caller is used. With the extension the caller would have to specify explicitly the pd where the revoke operation should apply to.
Genode core currently revokes all memory of the client pd subject to destruction. However core has no means to make sure that references to kernel objects are freed which creation has been issued by the client pd directly using the kernel syscalls. Additionally core can't make sure to revoke any mappings of memory, i/o ports and object capabilities which the client received via other channels (services/sessions provided not by core).
The same issue also applies to NUL[0], where sigma0 can't clean up the object space of the vancouvers subject to destruction.
With the remote revoke core and sigma0 in NUL would be able to make sure that all user level references inside a pd subject to destruction can be freed.
Cheers,
Alex.
[0] http://os.inf.tu-dresden.de/nul
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Fri, 20 Jul 2012 09:37:34 +0200 Alexander Boettcher (AB) wrote:
AB> do you see any issues to extend the revoke syscall by a protection AB> domain (pd) parameter ? Currently implicitly the current protection AB> domain of the caller is used. With the extension the caller would have AB> to specify explicitly the pd where the revoke operation should apply to.
Currently you don't need a PD capability to revoke capabilities from your own protection domain. And there are situations where you, rather than your parent, may want to revoke capabilities, e.g., cleaning up a receive window.
If you make revoke dependent on a PD capability, the consequence is that every PD needs to hold its own PD capability. There are 5 permission bits in a PD capability, all of which currently control creation of objects. We would have to redefine those bits to make room for a "revoke" permission.
The permissions of a PD capability could be used for any of the following: * creation of PD, EC, SC, PT, SM objects * revocation of memory, I/O, objects * more?
How would you assign those to the available 5 bits?
AB> Genode core currently revokes all memory of the client pd subject to AB> destruction. However core has no means to make sure that references to AB> kernel objects are freed which creation has been issued by the client AB> pd directly using the kernel syscalls. Additionally core can't make AB> sure to revoke any mappings of memory, i/o ports and object AB> capabilities which the client received via other channels AB> (services/sessions provided not by core). AB> AB> The same issue also applies to NUL[0], where sigma0 can't clean up the AB> object space of the vancouvers subject to destruction. AB> AB> With the remote revoke core and sigma0 in NUL would be able to make AB> sure that all user level references inside a pd subject to destruction AB> can be freed.
Is destruction of a PD the only case where you see a need for remote revocation?
Cheers, Udo
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 20.07.2012 11:45, Udo Steinberg wrote:
If you make revoke dependent on a PD capability, the consequence is that every PD needs to hold its own PD capability. There are 5 permission bits in
Yes, this is already the current situation. In Genode as NUL currently every PD has to hold its own PD cap for various other system calls.
a PD capability, all of which currently control creation of objects. We would have to redefine those bits to make room for a "revoke" permission.
The permissions of a PD capability could be used for any of the following: * creation of PD, EC, SC, PT, SM objects * revocation of memory, I/O, objects * more?
How would you assign those to the available 5 bits?
I would not re-assign any bits. Of course, extra right bits would be super generic to have it for the revoke operation, but it seems to be more a interface limitation problem than a hard design problem. (If there would be enough bits we would probably not discuss about it.)
If we look as how the PD cap is used currently, only the parent (Genode:core resp. NUL:sigma0) hold the PD cap with full rights. On the other hand the children have the PD cap (partially with restricted rights) solely to be able to invoke various system calls like create_sm, create_pt, create_ec, create_pd ... because it is required to have it.
Beside that there seems to be, at least in Genode as in NUL, no need nor use case to propagate the PD around in the system where all the additional right bits for revoke would be beneficial.
Or do you see such a use case for now?
To come back to the original problem. If you don't want that a child have to provide a cap for local revokes, then we just could stay with the current situation as it is currently.
* If the child provides _no_ or a NULL-CAP than the implicit available PD cap of the calling/local PD is used.
However,
* If the caller provides a valid PD cap, then the revoke operation is applied for the valid PD domain.
So, what I'm suggesting is:
* Those who have the PD cap are allowed to issue any kind of revoke operation. (I would rather have a bit for each right but it seems not be possible without redesign of the current interface)
AB> Genode core currently revokes all memory of the client pd subject to AB> destruction. However core has no means to make sure that references to AB> kernel objects are freed which creation has been issued by the client AB> pd directly using the kernel syscalls. Additionally core can't make AB> sure to revoke any mappings of memory, i/o ports and object AB> capabilities which the client received via other channels AB> (services/sessions provided not by core). AB> AB> The same issue also applies to NUL[0], where sigma0 can't clean up the AB> object space of the vancouvers subject to destruction. AB> AB> With the remote revoke core and sigma0 in NUL would be able to make AB> sure that all user level references inside a pd subject to destruction AB> can be freed.
Is destruction of a PD the only case where you see a need for remote revocation?
For now it is the only use case where I don't know of how to solve it with the current mechanism provided by the kernel. It would also make life easier to selectively revoke shared memory between children without revoking it from all children (as currently done in Genode according to Norman) or to have intermediate mappings in core to be able to revoke selectively (not done currently), however is not required.
The other option of course would be that the kernel takes care of the destruction of all objects when a PD should be killed, for example as soon as all user level available references to the PD object cap are revoked. Do you want to manage it rather in kernel instead at user level layer ?
Don't know what you rather prefer.
Cheers,
Alex.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Fri, 20 Jul 2012 15:55:44 +0200 Alexander Boettcher (AB) wrote:
AB> So, what I'm suggesting is: AB> AB> Those who have the PD cap are allowed to issue any kind of revoke AB> operation. (I would rather have a bit for each right but it seems not AB> be possible without redesign of the current interface)
So what I'm asking is the following...
Is there a use case where you want to selectively revoke stuff in a remote PD (as opposed to revoking everything in a remote PD). Currently you can remotely create objects in a PD for which you have a capability with adequate permissions. We could extend that interface to be able to remotely destruct objects the same way, using the same permission bits of the PD cap.
That would not cover remote revocation of memory and I/O ports though. And from an interface perspective, it is quite ugly if possession of a PD capability alone (with any combination of permission bits set) would allow for remote revocation of memory and/or I/O. Likewise, it's very ugly if you would specify a null capability for that purpose.
AB> The other option of course would be that the kernel takes care of the AB> destruction of all objects when a PD should be killed, for example as AB> soon as all user level available references to the PD object cap are AB> revoked. Do you want to manage it rather in kernel instead at user AB> level layer ?
I would go for the option of destroying the PD cap if you want to get rid of everything in a PD. If you want to selectively revoke stuff, then that's not going to be an option, because you obviously wouldn't want to destroy the whole PD.
Cheers, Udo
Hi Udo,
Is there a use case where you want to selectively revoke stuff in a remote PD (as opposed to revoking everything in a remote PD). Currently you can
from the top of my head I cannot think of any use case where a remote selective revoke of capabilities would be beneficial. But revoking everything within the PD when the PD is destroyed is desired.
That would not cover remote revocation of memory and I/O ports though. And from an interface perspective, it is quite ugly if possession of a PD
For memory and I/O, I would greatly appreciate a remote revoke function.
Just as an illustration, imagine that there is one ROM module handed out to many programs. (i.e., a shared library). Now, one program detaches the ROM dataspace from its local address space by invoking core's 'Rm_session::detach()'. In order to unmap the virtual pages from the program's address space where the ROM module was attached, core needs to determine the corresponding core-local address of the ROM module and then revoke that address range from core's address space. Now the recursive revoke of NOVA kicks in and revokes the mappings in the process. But unfortunately, it revokes the mapping in all other processes that use the same ROM module, too. So all other processes need to fault-in the ROM module again.
One possible solution would be to remap the ROM module for each client within core and hand out the remapped addresses when handling the client's respective page faults. But this would pollute the limited virtual address space of core.
The problem is further amplified when using nested dataspaces. When unmapping such nested dataspace on NOVA, core needs to traverse the (tree of) nested dataspaces to search for leaf dataspaces (physical memory objects) and revoke each single leaf individually. This is a complicated and potentially long-taking operation (and hence, not implemented as of now).
On kernels that feature remote revoke of memory such as OKL4, both scenarios are strikingly simple to come by: Simply unmap the virtual region in the process' address space. That's it.
A further benefit of a remote revoke of memory would be that core could hand out memory to processes directly from the physical address space (rather than core's virtual address space). The need to have all used memory mapped in core would simply vanish and the size of the virtual address space of core would not pose a limitation of the usable memory outside of core anymore. Right now, core cannot do that because it could not regain control over the resources once handed out. Remote revoke would be the key. Alleviating the core-local mapping of all memory objects might also have a positive effect for the consumption of kernel memory.
The bottom line is that the implementation of Genode's core on NOVA would greatly benefit from a remote-revoke facility for memory. For kernel objects other than memory and I/O, a selective remote revoke is not needed. Destructing a PD should implicitly revoke everything within the PD.
Cheers Norman
On Fri, 20 Jul 2012 17:54:18 +0200 Norman Feske (NF) wrote:
NF> Now the recursive revoke of NOVA kicks in and revokes the NF> mappings in the process. But unfortunately, it revokes the mapping in NF> all other processes that use the same ROM module, too. So all other NF> processes need to fault-in the ROM module again.
So you'd need something like a "directed revoke" feature. We had something like that in Fiasco-V2, where you could do an "unmap without self" and additionally specify a task number. Only child mappings for that task and its children would be removed. In the NOVA case, you'd specify a PD capability instead of a task number.
NF> One possible solution would be to remap the ROM module for each client NF> within core and hand out the remapped addresses when handling the NF> client's respective page faults. But this would pollute the limited NF> virtual address space of core.
Right.
NF> On kernels that feature remote revoke of memory such as OKL4, both NF> scenarios are strikingly simple to come by: Simply unmap the virtual NF> region in the process' address space. That's it.
This raises some security concerns though. Currently a [great][grand]parent can only revoke mappings that are in its own mapping tree. It cannot revoke anything from unrelated mapping trees and thus cannot interfere with other pagers. What you are suggesting is giving someone with a PD capability full control over the address-space of a remote PD. This makes the PD capability a very powerful token.
NF> The bottom line is that the implementation of Genode's core on NOVA NF> would greatly benefit from a remote-revoke facility for memory. For NF> kernel objects other than memory and I/O, a selective remote revoke is NF> not needed. Destructing a PD should implicitly revoke everything NF> within the PD.
No doubts about the benefits and I think it would not be too hard to add that feature. The question about the capability remains though. What exactly authorizes that operation: a PD capability with what permissions?
Would a "directed revoke" suffice for your purposes? Basically a "revoke the CRD and only in this child PD" operation.
Cheers, Udo
Hi Udo,
So you'd need something like a "directed revoke" feature. We had something like that in Fiasco-V2, where you could do an "unmap without self" and additionally specify a task number. Only child mappings for that task and its children would be removed. In the NOVA case, you'd specify a PD capability instead of a task number.
that's what I'm after.
This raises some security concerns though. Currently a [great][grand]parent can only revoke mappings that are in its own mapping tree. It cannot revoke anything from unrelated mapping trees and thus cannot interfere with other pagers. What you are suggesting is giving someone with a PD capability full control over the address-space of a remote PD. This makes the PD capability a very powerful token.
From Genode's point of view, this would be perfectly fine. The one who
possesses a PD capability is on power to control the PD. Only core should possess PD capabilities. There is no reason to hand out PD caps to other processes. However, in order to enable processes to revoke caps from their own PD (i.e., receive windows), core might hand out a limited (revoke-only) PD cap to the respective process. Alternatively, there could be a 'revoke_local' variant of the syscall that uses the caller's PD as implicit argument. Personally, I like the latter variant slightly better because it alleviates the need to attach permission bits to PD caps and spares core an interface for telling each process its corresponding PD cap.
No doubts about the benefits and I think it would not be too hard to add that feature. The question about the capability remains though. What exactly authorizes that operation: a PD capability with what permissions?
Would a "directed revoke" suffice for your purposes? Basically a "revoke the CRD and only in this child PD" operation.
Yes.
Cheers Norman
On Mon, 23 Jul 2012 14:19:31 +0200 Norman Feske (NF) wrote:
NF> > So you'd need something like a "directed revoke" feature. We had NF> > something like that in Fiasco-V2, where you could do an "unmap NF> > without self" and additionally specify a task number. Only child NF> > mappings for that task and its children would be removed. In the NF> > NOVA case, you'd specify a PD capability instead of a task number. NF> NF> that's what I'm after.
There are some subtle corner cases possible if revoke gets preempted. One is that if you do a revoke (range, PD-cap), the range obviously cannot go away, but the PD-cap can. This means if you do a directed revoke by specifying a PD-cap, and the PD-cap (or the PD) goes away in the middle of a preempted revoke, the remainder of the revoke would fail to look up the PD and do a full revoke of the range instead.
Alternatively you'd have to hold onto the PD-cap while a revoke with that PD-cap is ongoing, which is hardly any better.
Cheers, Udo
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hi Udo,
There are some subtle corner cases possible if revoke gets preempted. One is that if you do a revoke (range, PD-cap), the range obviously cannot go away, but the PD-cap can. This means if you do a directed revoke by specifying a PD-cap, and the PD-cap (or the PD) goes away in the middle of a preempted revoke, the remainder of the revoke would fail to look up the PD and do a full revoke of the range instead.
what do you mean by "full revoke of the range"?
If a PD cap goes away, won't this implicitly revoke everything from the PD anyway? (including the not-yet-finished range of the preempted revoke operation) If so, this looks like a non-issue to me. Or does the preempted revoke happen to yield to leaking resources in any way?
Alternatively you'd have to hold onto the PD-cap while a revoke with that PD-cap is ongoing, which is hardly any better.
I am not sure I fully comprehended your first paragraph. But either way, holding the PD cap until no partial revoke referring to the PD is in progress would be feasible as well. Core needs to deal with such life-time management problems already.
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
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Tue, 24 Jul 2012 21:44:10 +0200 Norman Feske (NF) wrote:
NF> what do you mean by "full revoke of the range"? NF> NF> If a PD cap goes away, won't this implicitly revoke everything from NF> the PD anyway? (including the not-yet-finished range of the preempted NF> revoke operation) If so, this looks like a non-issue to me. Or does NF> the preempted revoke happen to yield to leaking resources in any way?
What I'm saying is... an operation that starts out as a directed revoke will turn into a revoke on the entire subtree if the PD cap goes away while the revoke operation is preempted. Simply because at the time the revoke is restarted, the limitation "only this single PD" can no longer be applied.
Cheers, Udo
Hello again,
NF> what do you mean by "full revoke of the range"? NF> NF> If a PD cap goes away, won't this implicitly revoke everything from NF> the PD anyway? (including the not-yet-finished range of the preempted NF> revoke operation) If so, this looks like a non-issue to me. Or does NF> the preempted revoke happen to yield to leaking resources in any way?
What I'm saying is... an operation that starts out as a directed revoke will turn into a revoke on the entire subtree if the PD cap goes away while the revoke operation is preempted. Simply because at the time the revoke is restarted, the limitation "only this single PD" can no longer be applied.
it seems I slightly misunderstood your proposal. In your solution, the revoke CRD argument refers to the address space of the the caller, not the targeted PD, right? If so, your phrasing makes sense.
But couldn't the revoke syscall take a CRD referring to the targeted PD as argument instead? Why the need to have the to-be-revoked range mapped in the caller's PD at all?
Just in case you are worried about the preemption of a remote revocation in this case: This is no problem for Genode. A PD cap vanishes in core in the event of process destruction only. The corner case of an eventually occurring partial revocation will be taken care of by the destruction of the whole PD.
Cheers Norman
On Tue, 24 Jul 2012 23:39:47 +0200 Norman Feske (NF) wrote:
NF> it seems I slightly misunderstood your proposal. In your solution, the NF> revoke CRD argument refers to the address space of the the caller, not NF> the targeted PD, right? If so, your phrasing makes sense.
Correct.
NF> But couldn't the revoke syscall take a CRD referring to the targeted PD NF> as argument instead? Why the need to have the to-be-revoked range mapped NF> in the caller's PD at all?
It could, but it allows the holder of the PD cap to manipulate the address space of the PD at arbitrary locations. While this may not be a problem for Genode, due to the way PD capabilities are (not) distributed, I'm not sure it generalizes to other environments as well. With a directed revoke rooted in the PD of the invoker, you are guaranteed to be able to revoke only mappings that you established yourself.
Cheers, Udo
Hi Udo,
NF> But couldn't the revoke syscall take a CRD referring to the targeted PD NF> as argument instead? Why the need to have the to-be-revoked range mapped NF> in the caller's PD at all?
It could, but it allows the holder of the PD cap to manipulate the address space of the PD at arbitrary locations.
indeed. This is consistent with my stance that the possession of a PD cap equals to total power over the PD.
Can you come up with a scenario where anyone would hand out a PD cap to someone else who should not have such power over the referred PD? I can't think of any.
While this may not be a problem for Genode, due to the way PD capabilities are (not) distributed, I'm not sure it generalizes to other environments as well. With a directed revoke rooted in the PD of the invoker, you are guaranteed to be able to revoke only mappings that you established yourself.
If you are uncertain about non-Genode scenarios, a permission bit might do the trick. But think this bit is wasted. As far as I know, both NUL and Genode would leave it untouched. (I haven't looked into Nils' NRE though)
Cheers Norman