Fix: don't deference stale pager pointer in core

Reset pager pointer in platform_thread if pager object is removed.

Fixes #532
This commit is contained in:
Alexander Boettcher 2012-11-29 13:37:30 +01:00 committed by Norman Feske
parent 1720e04fdc
commit fa2cbdc7cb
7 changed files with 51 additions and 3 deletions

View File

@ -157,7 +157,10 @@ void Platform_thread::unbind()
void Platform_thread::pager(Pager_object *pager_obj)
{
_pager_obj = pager_obj;
_pager.local = pager_obj->cap();
if (_pager_obj)
_pager.local = pager_obj->cap();
else
_pager.local = Native_capability();
}

View File

@ -20,14 +20,26 @@
#include <base/signal.h>
#include <pager/capability.h>
#include <cap_session/cap_session.h>
#include <thread/capability.h>
namespace Genode {
struct Pager_object
{
Thread_capability _thread_cap;
virtual ~Pager_object() { }
void exception_handler(Signal_context_capability) { }
public:
/**
* Remember thread cap so that rm_session can tell thread that
* rm_client is gone.
*/
Thread_capability thread_cap() { return _thread_cap; } const
void thread_cap(Thread_capability cap) { _thread_cap = cap; }
};
class Pager_activation_base { };

View File

@ -65,6 +65,8 @@ namespace Genode {
bool singlestep;
} _state;
Thread_capability _thread_cap;
void _copy_state(Nova::Utcb * utcb);
static void _page_fault_handler();
@ -176,6 +178,13 @@ namespace Genode {
void client_set_ec(addr_t ec) { _state.sel_client_ec = ec; }
void single_step(bool on) { _state.singlestep = on; }
/**
* Remember thread cap so that rm_session can tell thread that
* rm_client is gone.
*/
Thread_capability thread_cap() { return _thread_cap; } const
void thread_cap(Thread_capability cap) { _thread_cap = cap; }
};

View File

@ -34,6 +34,10 @@ void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds)
{
size_t page_rounded_size = (ds->size() + get_page_size() - 1) & get_page_mask();
if (verbose_ram_ds)
printf("-- revoke - ram ds size=0x%8zx phys 0x%8lx has core-local addr 0x%8lx - thread 0x%8p\n",
page_rounded_size, ds->phys_addr(), ds->core_local_addr(), Thread_base::myself()->utcb());
unmap_local((Nova::Utcb *)Thread_base::myself()->utcb(),
ds->core_local_addr(),
page_rounded_size >> get_page_size_log2());
@ -76,8 +80,8 @@ void Ram_session_component::_clear_ds(Dataspace_component *ds)
}
if (verbose_ram_ds)
printf("-- ram ds size=%zx phys %lx has core-local addr %p\n",
page_rounded_size, ds->phys_addr(), virt_addr);
printf("-- map - ram ds size=0x%8zx phys 0x%8lx has core-local addr 0x%8p - thread 0x%8p\n",
page_rounded_size, ds->phys_addr(), virt_addr, Thread_base::myself()->utcb());
/* map the dataspace's physical pages to local addresses */
const Nova::Rights rights(true, true, true);

View File

@ -43,6 +43,8 @@ namespace Genode {
*/
unsigned long _badge;
Thread_capability _thread_cap;
/**
* User-level signal handler registered for this pager object via
* 'Cpu_session::exception_handler()'.
@ -97,6 +99,13 @@ namespace Genode {
Signal_transmitter transmitter(_exception_sigh);
transmitter.submit();
}
/**
* Remember thread cap so that rm_session can tell thread that
* rm_client is gone.
*/
Thread_capability thread_cap() { return _thread_cap; } const
void thread_cap(Thread_capability cap) { _thread_cap = cap; }
};
/**

View File

@ -81,6 +81,8 @@ int Cpu_session_component::set_pager(Thread_capability thread_cap,
if (!p) return -2;
thread->platform_thread()->pager(p);
p->thread_cap(thread->cap());
return 0;
}

View File

@ -756,6 +756,15 @@ Rm_session_component::~Rm_session_component()
/* remove all clients */
while (Rm_client *cl = _client_slab.raw()->first_object()) {
Thread_capability thread_cap = cl->thread_cap();
if (thread_cap.valid()) {
/* lookup thread and reset pager pointer */
Cpu_thread_component *cpu_thread = dynamic_cast<Cpu_thread_component *>
(_thread_ep->obj_by_cap(thread_cap));
if (cpu_thread)
cpu_thread->platform_thread()->pager(0);
}
_lock.unlock();
cl->dissolve_from_faulting_rm_session();
this->dissolve(cl);