mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-26 08:51:08 +00:00
foc: delete IPC gates on cap session destruction
To correctly delete all IPC gates created via a CAP session, all capabilities created have to be stored. Otherwise we leak kernel objects within Fiasco.OC permanently. Fix #702
This commit is contained in:
parent
acc46f70b7
commit
28fdc51a76
@ -84,13 +84,12 @@ Cap_mapping::Cap_mapping(Native_capability cap, Native_thread_id r)
|
||||
** Cap_session_component **
|
||||
*****************************/
|
||||
|
||||
Native_capability Cap_session_component::alloc(Cap_session_component *session,
|
||||
Native_capability ep)
|
||||
Native_capability Cap_session_component::alloc(Native_capability ep)
|
||||
{
|
||||
Native_capability cap;
|
||||
|
||||
if (!ep.valid()) {
|
||||
PWRN("Invalid cap!");
|
||||
PWRN("Invalid reference capability!");
|
||||
return cap;
|
||||
}
|
||||
|
||||
@ -108,7 +107,7 @@ Native_capability Cap_session_component::alloc(Cap_session_component *session,
|
||||
Core_cap_index* idx = static_cast<Core_cap_index*>(cap_map()->insert(id));
|
||||
|
||||
if (!idx) {
|
||||
PWRN("Out of capabilities!");
|
||||
PWRN("Out of capability indices!");
|
||||
platform_specific()->cap_id_alloc()->free(id);
|
||||
return cap;
|
||||
}
|
||||
@ -125,40 +124,51 @@ Native_capability Cap_session_component::alloc(Cap_session_component *session,
|
||||
/* set debugger-name of ipc-gate to thread's name */
|
||||
Fiasco::l4_debugger_set_object_name(idx->kcap(), ref->pt()->name());
|
||||
|
||||
idx->session(session);
|
||||
idx->session(this);
|
||||
idx->pt(ref->pt());
|
||||
idx->inc();
|
||||
cap = Native_capability(idx);
|
||||
} catch (Cap_id_allocator::Out_of_ids) {
|
||||
PERR("Out of IDs");
|
||||
PERR("Out of capability ids");
|
||||
}
|
||||
|
||||
/*
|
||||
* insert valid capabilities into the session's object pool to
|
||||
* be able to destroy them on session destruction.
|
||||
* For the construction of core's own threads the related cap session
|
||||
* doesn't have an allocator set. But this session gets never destroyed
|
||||
* so this is not an issue.
|
||||
*/
|
||||
if (cap.valid() && _md_alloc)
|
||||
_pool.insert(new (_md_alloc) Entry(cap));
|
||||
return cap;
|
||||
}
|
||||
|
||||
|
||||
Native_capability Cap_session_component::alloc(Native_capability ep)
|
||||
{
|
||||
return Cap_session_component::alloc(this, ep);
|
||||
}
|
||||
|
||||
|
||||
void Cap_session_component::free(Native_capability cap)
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
if (!cap.valid())
|
||||
return;
|
||||
if (!cap.valid()) return;
|
||||
|
||||
Core_cap_index* idx = static_cast<Core_cap_index*>(cap.idx());
|
||||
/* proof whether the capability was created by this cap_session */
|
||||
if (static_cast<Core_cap_index*>(cap.idx())->session() != this) return;
|
||||
|
||||
/*
|
||||
* check whether this cap_session has created the capability to delete.
|
||||
*/
|
||||
if (idx->session() != this)
|
||||
return;
|
||||
_pool.apply(cap, [this] (Entry *e) {
|
||||
if (e) {
|
||||
_pool.remove(e);
|
||||
destroy(_md_alloc, e);
|
||||
} else
|
||||
PWRN("Could not find capability to be deleted");
|
||||
});
|
||||
}
|
||||
|
||||
idx->dec();
|
||||
|
||||
Cap_session_component::~Cap_session_component()
|
||||
{
|
||||
_pool.remove_all([this] (Entry *e) {
|
||||
if (!e) return;
|
||||
destroy(_md_alloc, e);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -203,7 +213,6 @@ void Genode::Capability_map::remove(Genode::Cap_index* i)
|
||||
if (i) {
|
||||
Core_cap_index* e = static_cast<Core_cap_index*>(_tree.first() ? _tree.first()->find_by_id(i->id()) : 0);
|
||||
if (e == i) {
|
||||
|
||||
l4_msgtag_t tag = l4_task_unmap(L4_BASE_TASK_CAP,
|
||||
l4_obj_fpage(i->kcap(), 0, L4_FPAGE_RWX),
|
||||
L4_FP_ALL_SPACES | L4_FP_DELETE_OBJ);
|
||||
|
@ -17,23 +17,34 @@
|
||||
/* Genode includes */
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/allocator.h>
|
||||
#include <base/object_pool.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Cap_session_component : public Rpc_object<Cap_session>
|
||||
{
|
||||
private:
|
||||
|
||||
struct Entry : Object_pool<Entry>::Entry
|
||||
{
|
||||
Entry(Native_capability cap) : Object_pool<Entry>::Entry(cap) {}
|
||||
};
|
||||
|
||||
Object_pool<Entry> _pool;
|
||||
Allocator *_md_alloc;
|
||||
|
||||
public:
|
||||
|
||||
Cap_session_component(Allocator *md_alloc, const char *args) {}
|
||||
Cap_session_component(Allocator *md_alloc, const char *args)
|
||||
: _md_alloc(md_alloc) {}
|
||||
|
||||
~Cap_session_component();
|
||||
|
||||
void upgrade_ram_quota(size_t ram_quota) { }
|
||||
|
||||
Native_capability alloc(Native_capability ep);
|
||||
|
||||
void free(Native_capability cap);
|
||||
|
||||
static Native_capability alloc(Cap_session_component *session,
|
||||
Native_capability ep);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -226,8 +226,13 @@ void Platform_thread::_create_thread()
|
||||
if (l4_msgtag_has_error(tag))
|
||||
PERR("cannot create more thread kernel-objects!");
|
||||
|
||||
/* for core threads we can't use core_env, it is to early */
|
||||
static Cap_session_component core_thread_cap_session(0,"");
|
||||
Cap_session &csc = (_core_thread)
|
||||
? core_thread_cap_session : *core_env()->cap_session();
|
||||
|
||||
/* create initial gate for thread */
|
||||
_gate.local = Cap_session_component::alloc(0, _thread.local);
|
||||
_gate.local = csc.alloc(_thread.local);
|
||||
}
|
||||
|
||||
|
||||
@ -311,7 +316,7 @@ Platform_thread::Platform_thread(const char *name)
|
||||
|
||||
Platform_thread::~Platform_thread()
|
||||
{
|
||||
_gate.local.idx()->dec();
|
||||
core_env()->cap_session()->free(_gate.local);
|
||||
|
||||
/*
|
||||
* We inform our protection domain about thread destruction, which will end up in
|
||||
|
Loading…
Reference in New Issue
Block a user