Fiasco.OC: check invoked capability (fix #341)

Let the Fiasco.OC base platform succeed the cap_integrity run-script meaning
that it is not feasible anymore to fake a capability by using a valid one
together with a guessed local_name.
This commit is contained in:
Stefan Kalkowski 2012-06-05 16:11:28 +02:00 committed by Norman Feske
parent c98a80251c
commit b71c1649d6
5 changed files with 109 additions and 46 deletions

View File

@ -58,6 +58,8 @@ namespace Genode {
*/
addr_t _rcv_cap_sel_cnt;
unsigned long _label;
char _msg_start[]; /* symbol marks start of message */
public:
@ -65,7 +67,8 @@ namespace Genode {
/**
* Constructor
*/
Msgbuf_base() : _rcv_idx_base(cap_idx_alloc()->alloc(MAX_CAP_ARGS))
Msgbuf_base()
: _rcv_idx_base(cap_idx_alloc()->alloc(MAX_CAP_ARGS)), _label(0)
{
rcv_reset();
snd_reset();
@ -137,6 +140,9 @@ namespace Genode {
*/
addr_t rcv_cap_sel() {
return rcv_cap_sel_base() + _rcv_cap_sel_cnt++ * Fiasco::L4_CAP_SIZE; }
void label(unsigned long label) { _label = label; }
unsigned long label() { return _label & (~0UL << 2); }
};

View File

@ -178,6 +178,9 @@ void Ipc_istream::_wait()
tag = l4_ipc_wait(l4_utcb(), &label, L4_IPC_NEVER);
} while (ipc_error(tag, DEBUG_MSG));
/* copy received label into message buffer */
_rcv_msg->label(label);
/* copy message from the UTCBs message registers to the receive buffer */
copy_utcb_to_msgbuf(tag, _rcv_msg);
@ -295,6 +298,9 @@ void Ipc_server::_reply_wait()
_wait();
} else {
/* copy received label into message buffer */
_rcv_msg->label(label);
/* copy request message from the UTCBs message registers */
copy_utcb_to_msgbuf(tag, _rcv_msg);
}

View File

@ -37,3 +37,54 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
/* return capability that uses the object id as badge */
return new_obj_cap;
}
void Rpc_entrypoint::entry()
{
Ipc_server srv(&_snd_buf, &_rcv_buf);
_ipc_server = &srv;
_cap = srv;
_cap_valid.unlock();
/*
* Now, the capability of the server activation is initialized
* an can be passed around. However, the processing of capability
* invocations should not happen until activation-using server
* is completely initialized. Thus, we wait until the activation
* gets explicitly unblocked by calling 'Rpc_entrypoint::activate()'.
*/
_delay_start.lock();
while (1) {
int opcode = 0;
srv >> IPC_REPLY_WAIT >> opcode;
/* set default return value */
srv.ret(ERR_INVALID_OBJECT);
/* check whether capability's label fits global id */
if (((unsigned long)srv.badge()) != _rcv_buf.label()) {
PWRN("somebody tries to fake us!");
continue;
}
/* atomically lookup and lock referenced object */
{
Lock::Guard lock_guard(_curr_obj_lock);
_curr_obj = obj_by_id(srv.badge());
if (!_curr_obj)
continue;
_curr_obj->lock();
}
/* dispatch request */
try { srv.ret(_curr_obj->dispatch(opcode, srv, srv)); }
catch (Blocking_canceled) { }
_curr_obj->unlock();
_curr_obj = 0;
}
}

View File

@ -39,51 +39,6 @@ void Rpc_entrypoint::_dissolve(Rpc_object_base *obj)
}
void Rpc_entrypoint::entry()
{
Ipc_server srv(&_snd_buf, &_rcv_buf);
_ipc_server = &srv;
_cap = srv;
_cap_valid.unlock();
/*
* Now, the capability of the server activation is initialized
* an can be passed around. However, the processing of capability
* invocations should not happen until activation-using server
* is completely initialized. Thus, we wait until the activation
* gets explicitly unblocked by calling 'Rpc_entrypoint::activate()'.
*/
_delay_start.lock();
while (1) {
int opcode = 0;
srv >> IPC_REPLY_WAIT >> opcode;
/* set default return value */
srv.ret(ERR_INVALID_OBJECT);
/* atomically lookup and lock referenced object */
{
Lock::Guard lock_guard(_curr_obj_lock);
_curr_obj = obj_by_id(srv.badge());
if (!_curr_obj)
continue;
_curr_obj->lock();
}
/* dispatch request */
try { srv.ret(_curr_obj->dispatch(opcode, srv, srv)); }
catch (Blocking_canceled) { }
_curr_obj->unlock();
_curr_obj = 0;
}
}
void Rpc_entrypoint::_leave_server_object(Rpc_object_base *obj)
{
Lock::Guard lock_guard(_curr_obj_lock);

View File

@ -37,3 +37,48 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
/* return capability that uses the object id as badge */
return new_obj_cap;
}
void Rpc_entrypoint::entry()
{
Ipc_server srv(&_snd_buf, &_rcv_buf);
_ipc_server = &srv;
_cap = srv;
_cap_valid.unlock();
/*
* Now, the capability of the server activation is initialized
* an can be passed around. However, the processing of capability
* invocations should not happen until activation-using server
* is completely initialized. Thus, we wait until the activation
* gets explicitly unblocked by calling 'Rpc_entrypoint::activate()'.
*/
_delay_start.lock();
while (1) {
int opcode = 0;
srv >> IPC_REPLY_WAIT >> opcode;
/* set default return value */
srv.ret(ERR_INVALID_OBJECT);
/* atomically lookup and lock referenced object */
{
Lock::Guard lock_guard(_curr_obj_lock);
_curr_obj = obj_by_id(srv.badge());
if (!_curr_obj)
continue;
_curr_obj->lock();
}
/* dispatch request */
try { srv.ret(_curr_obj->dispatch(opcode, srv, srv)); }
catch (Blocking_canceled) { }
_curr_obj->unlock();
_curr_obj = 0;
}
}