From 9a9f49b65c1e4a48029c7a3c9774932ddd0c3e14 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Mon, 26 Mar 2012 12:20:09 +0200 Subject: [PATCH] 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. --- base-foc/src/base/env/cap_map.cc | 20 ++++++++++++-------- base-foc/src/base/thread/thread_start.cc | 21 ++++++++++++++++++--- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/base-foc/src/base/env/cap_map.cc b/base-foc/src/base/env/cap_map.cc index db31ab107..93c660073 100644 --- a/base-foc/src/base/env/cap_map.cc +++ b/base-foc/src/base/env/cap_map.cc @@ -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 guard(_lock); Cap_index *i = cap_idx_alloc()->alloc(1); - i->id(id); - _tree.insert(i); + 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 guard(_lock); Cap_index *i = cap_idx_alloc()->alloc(kcap, 1); - i->id(id); - _tree.insert(i); + if (i) { + i->id(id); + _tree.insert(i); + } return i; } diff --git a/base-foc/src/base/thread/thread_start.cc b/base-foc/src/base/thread/thread_start.cc index f1109a7c2..1dfa0cae5 100644 --- a/base-foc/src/base/thread/thread_start.cc +++ b/base-foc/src/base/thread/thread_start.cc @@ -57,9 +57,24 @@ void Thread_base::start() _tid = state.kcap; _context->utcb = state.utcb; - 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); + /** + * 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];