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 **
|
** Cap_session_component **
|
||||||
*****************************/
|
*****************************/
|
||||||
|
|
||||||
Native_capability Cap_session_component::alloc(Cap_session_component *session,
|
Native_capability Cap_session_component::alloc(Native_capability ep)
|
||||||
Native_capability ep)
|
|
||||||
{
|
{
|
||||||
Native_capability cap;
|
Native_capability cap;
|
||||||
|
|
||||||
if (!ep.valid()) {
|
if (!ep.valid()) {
|
||||||
PWRN("Invalid cap!");
|
PWRN("Invalid reference capability!");
|
||||||
return cap;
|
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));
|
Core_cap_index* idx = static_cast<Core_cap_index*>(cap_map()->insert(id));
|
||||||
|
|
||||||
if (!idx) {
|
if (!idx) {
|
||||||
PWRN("Out of capabilities!");
|
PWRN("Out of capability indices!");
|
||||||
platform_specific()->cap_id_alloc()->free(id);
|
platform_specific()->cap_id_alloc()->free(id);
|
||||||
return cap;
|
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 */
|
/* set debugger-name of ipc-gate to thread's name */
|
||||||
Fiasco::l4_debugger_set_object_name(idx->kcap(), ref->pt()->name());
|
Fiasco::l4_debugger_set_object_name(idx->kcap(), ref->pt()->name());
|
||||||
|
|
||||||
idx->session(session);
|
idx->session(this);
|
||||||
idx->pt(ref->pt());
|
idx->pt(ref->pt());
|
||||||
idx->inc();
|
|
||||||
cap = Native_capability(idx);
|
cap = Native_capability(idx);
|
||||||
} catch (Cap_id_allocator::Out_of_ids) {
|
} 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;
|
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)
|
void Cap_session_component::free(Native_capability cap)
|
||||||
{
|
{
|
||||||
using namespace Fiasco;
|
using namespace Fiasco;
|
||||||
|
|
||||||
if (!cap.valid())
|
if (!cap.valid()) return;
|
||||||
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;
|
||||||
|
|
||||||
/*
|
_pool.apply(cap, [this] (Entry *e) {
|
||||||
* check whether this cap_session has created the capability to delete.
|
if (e) {
|
||||||
*/
|
_pool.remove(e);
|
||||||
if (idx->session() != this)
|
destroy(_md_alloc, e);
|
||||||
return;
|
} 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) {
|
if (i) {
|
||||||
Core_cap_index* e = static_cast<Core_cap_index*>(_tree.first() ? _tree.first()->find_by_id(i->id()) : 0);
|
Core_cap_index* e = static_cast<Core_cap_index*>(_tree.first() ? _tree.first()->find_by_id(i->id()) : 0);
|
||||||
if (e == i) {
|
if (e == i) {
|
||||||
|
|
||||||
l4_msgtag_t tag = l4_task_unmap(L4_BASE_TASK_CAP,
|
l4_msgtag_t tag = l4_task_unmap(L4_BASE_TASK_CAP,
|
||||||
l4_obj_fpage(i->kcap(), 0, L4_FPAGE_RWX),
|
l4_obj_fpage(i->kcap(), 0, L4_FPAGE_RWX),
|
||||||
L4_FP_ALL_SPACES | L4_FP_DELETE_OBJ);
|
L4_FP_ALL_SPACES | L4_FP_DELETE_OBJ);
|
||||||
|
@ -17,23 +17,34 @@
|
|||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/rpc_server.h>
|
#include <base/rpc_server.h>
|
||||||
#include <base/allocator.h>
|
#include <base/allocator.h>
|
||||||
|
#include <base/object_pool.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Cap_session_component : public Rpc_object<Cap_session>
|
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:
|
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) { }
|
void upgrade_ram_quota(size_t ram_quota) { }
|
||||||
|
|
||||||
Native_capability alloc(Native_capability ep);
|
Native_capability alloc(Native_capability ep);
|
||||||
|
|
||||||
void free(Native_capability cap);
|
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))
|
if (l4_msgtag_has_error(tag))
|
||||||
PERR("cannot create more thread kernel-objects!");
|
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 */
|
/* 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()
|
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
|
* We inform our protection domain about thread destruction, which will end up in
|
||||||
|
Loading…
Reference in New Issue
Block a user