base: safeguard entrypoint against double manage

This patch adds sanity checks to the RPC entrypoint that detect attempts
to manage or dissolve the same RPC object twice. This is not always a
bug. I.e., if RPC objects are implemented in the modern way where the
object manages/dissolves itself. As the generic framework code (in
particular root/component.h) cannot rely on this pattern, it has to
call manage/dissolve for session objects anyway. For modern session
objects, this double attempt would result in a serious error (double
insertion into the object pool's AVL tree).

Issue #2398
This commit is contained in:
Norman Feske 2017-05-08 12:52:23 +02:00 committed by Christian Helmuth
parent 843dd179d7
commit eea493a8ca
4 changed files with 26 additions and 1 deletions

View File

@ -36,6 +36,12 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
{
using namespace Nova;
/* don't manage RPC object twice */
if (obj->cap().valid()) {
warning("attempt to manage RPC object twice");
return obj->cap();
}
Untyped_capability ec_cap;
/* _ec_sel is invalid until thread gets started */
@ -60,6 +66,10 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
void Rpc_entrypoint::_dissolve(Rpc_object_base *obj)
{
/* don't dissolve RPC object twice */
if (!obj->cap().valid())
return;
/* de-announce object from cap_session */
_free_rpc_cap(_pd_session, obj->cap());

View File

@ -169,7 +169,12 @@ class Genode::Root_component : public Rpc_object<Typed_root<SESSION_TYPE> >,
throw Root::Unavailable();
}
_ep->manage(s);
/*
* Consider that the session-object constructor may already have
* called 'manage'.
*/
if (!s->cap().valid())
_ep->manage(s);
aquire_guard.ack = true;
return *s;

View File

@ -27,6 +27,12 @@ using namespace Genode;
Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
{
/* don't manage RPC object twice */
if (obj->cap().valid()) {
warning("attempt to manage RPC object twice");
return obj->cap();
}
Untyped_capability new_obj_cap = _alloc_rpc_cap(_pd_session, _cap);
/* add server object to object pool */

View File

@ -26,6 +26,10 @@ using namespace Genode;
void Rpc_entrypoint::_dissolve(Rpc_object_base *obj)
{
/* don't dissolve RPC object twice */
if (!obj->cap().valid())
return;
/* make sure nobody is able to find this object */
remove(obj);