Fiasco.OC: sanity-check cap insertion. (fix #166)

When constructing a thread object its capability is inserted into the
capability map. Normally this is done by the ipc-unmarshalling code, but
in this case the thread-capability isn't transfered via normal IPC, but in
a special form via the thread_state object. In contrast to the unmarshalling
code, the thread-startup code doesn't check, whether the capability-map
already contains a deprecated entry with the same capability id before
inserting the thread's capability. This commit add the necessary check.

Moreover, a check is added to the insertion methods of the capability-map
to verify that capability-allocation didn't failed.
This commit is contained in:
Stefan Kalkowski 2012-03-26 12:20:09 +02:00 committed by Norman Feske
parent 89db981280
commit 9a9f49b65c
2 changed files with 30 additions and 11 deletions

View File

@ -39,6 +39,10 @@ Genode::addr_t Genode::Cap_index::kcap() {
return cap_idx_alloc()->idx_to_kcap(this); }
/****************************
** Capability_map class **
****************************/
Genode::Cap_index* Genode::Capability_map::find(int id)
{
using namespace Genode;
@ -52,10 +56,6 @@ Genode::Cap_index* Genode::Capability_map::find(int id)
}
/****************************
** Capability_map class **
****************************/
Genode::Cap_index* Genode::Capability_map::insert(int id)
{
using namespace Genode;
@ -63,8 +63,10 @@ Genode::Cap_index* Genode::Capability_map::insert(int id)
Lock_guard<Spin_lock> guard(_lock);
Cap_index *i = cap_idx_alloc()->alloc(1);
if (i) {
i->id(id);
_tree.insert(i);
}
return i;
}
@ -76,8 +78,10 @@ Genode::Cap_index* Genode::Capability_map::insert(int id, addr_t kcap)
Lock_guard<Spin_lock> guard(_lock);
Cap_index *i = cap_idx_alloc()->alloc(kcap, 1);
if (i) {
i->id(id);
_tree.insert(i);
}
return i;
}

View File

@ -57,9 +57,24 @@ void Thread_base::start()
_tid = state.kcap;
_context->utcb = state.utcb;
/**
* If we've a dead capability in our database, which is already
* revoked, its id might be reused.
*/
Cap_index *i = cap_map()->find(state.id);
if (i) {
l4_msgtag_t tag = l4_task_cap_valid(L4_BASE_TASK_CAP, i->kcap());
if (!tag.label())
cap_map()->remove(i);
}
try {
l4_utcb_tcr_u(state.utcb)->user[UTCB_TCR_BADGE] = state.id;
l4_utcb_tcr_u(state.utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this;
cap_map()->insert(state.id, state.kcap);
} catch(Cap_index_allocator::Region_conflict) {
PERR("could not insert id %lx", state.id);
}
/* register initial IP and SP at core */
addr_t thread_sp = (addr_t)&_context->stack[-4];