Add an 'executable' flag to 'Rm_session::attach()'

With this patch clients of the RM service can state if they want a mapping
to be executable or not. This allows dataspaces to be mapped as
non-executable on Linux by default and as executable only if needed.

Partially fixes #176.
This commit is contained in:
Christian Prochaska 2012-04-16 18:55:18 +02:00 committed by Norman Feske
parent de92956220
commit 7a369bc74d
26 changed files with 94 additions and 42 deletions

View File

@ -25,7 +25,8 @@ using namespace Genode;
Rm_session::Local_addr
Core_rm_session::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr,
Rm_session::Local_addr local_addr)
Rm_session::Local_addr local_addr,
bool executable)
{
using namespace Codezero;

View File

@ -34,7 +34,8 @@ namespace Genode {
Local_addr attach(Dataspace_capability ds_cap, size_t size = 0,
off_t offset = 0, bool use_local_addr = false,
Local_addr local_addr = 0);
Local_addr local_addr = 0,
bool executable = false);
void detach(Local_addr) { }

View File

@ -206,7 +206,8 @@ namespace Genode {
**************************************/
Local_addr attach(Dataspace_capability ds, size_t size,
off_t, bool, Local_addr);
off_t, bool, Local_addr,
bool executable);
void detach(Local_addr local_addr);

View File

@ -34,9 +34,11 @@ namespace Genode {
: _cap(session) { }
Local_addr attach(Dataspace_capability ds, size_t size, off_t offset,
bool use_local_addr, Local_addr local_addr)
bool use_local_addr, Local_addr local_addr,
bool executable = false)
{
return _local()->attach(ds, size, offset, use_local_addr, local_addr);
return _local()->attach(ds, size, offset, use_local_addr,
local_addr, executable);
}
void detach(Local_addr local_addr) {

View File

@ -43,7 +43,8 @@ static bool is_sub_rm_session(Dataspace_capability ds)
static void *map_local(Dataspace_capability ds, Genode::size_t size,
addr_t offset, bool use_local_addr, addr_t local_addr)
addr_t offset, bool use_local_addr, addr_t local_addr,
bool executable)
{
Linux_dataspace::Filename fname = Linux_dataspace_client(ds).fname();
fname.buf[sizeof(fname.buf) - 1] = 0;
@ -56,7 +57,7 @@ static void *map_local(Dataspace_capability ds, Genode::size_t size,
}
int flags = MAP_SHARED | (use_local_addr ? MAP_FIXED : 0);
int prot = PROT_READ | PROT_EXEC | (writable ? PROT_WRITE : 0);
int prot = PROT_READ | (writable ? PROT_WRITE : 0) | (executable ? PROT_EXEC : 0);
void *addr = lx_mmap(use_local_addr ? (void*)local_addr : 0, size,
prot, flags, fd, offset);
@ -84,7 +85,8 @@ Rm_session::Local_addr
Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
size_t size, off_t offset,
bool use_local_addr,
Rm_session::Local_addr local_addr)
Rm_session::Local_addr local_addr,
bool executable)
{
Lock::Guard lock_guard(_lock);
@ -150,7 +152,7 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
* and map it.
*/
if (_is_attached())
map_local(ds, region_size, offset, true, _base + (addr_t)local_addr);
map_local(ds, region_size, offset, true, _base + (addr_t)local_addr, executable);
return (void *)local_addr;
@ -197,7 +199,8 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
continue;
map_local(region.dataspace(), region.size(), region.offset(),
true, rm->_base + region.start() + region.offset());
true, rm->_base + region.start() + region.offset(),
executable);
}
return rm->_base;
@ -209,7 +212,8 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
*
* Boring, a plain dataspace is attached to a root RM session.
*/
void *addr = map_local(ds, region_size, offset, use_local_addr, local_addr);
void *addr = map_local(ds, region_size, offset, use_local_addr,
local_addr, executable);
_add_to_rmap(Region((addr_t)addr, offset, ds, region_size));

View File

@ -39,7 +39,8 @@ class Context_area_rm_session : public Genode::Rm_session
*/
Local_addr attach(Genode::Dataspace_capability ds_cap,
Genode::size_t size, Genode::off_t offset,
bool use_local_addr, Local_addr local_addr)
bool use_local_addr, Local_addr local_addr,
bool executable)
{
using namespace Genode;

View File

@ -40,7 +40,7 @@ namespace Genode {
void upgrade_ram_quota(size_t ram_quota) { }
Local_addr attach(Dataspace_capability, size_t, off_t, bool, Local_addr) {
Local_addr attach(Dataspace_capability, size_t, off_t, bool, Local_addr, bool) {
return (addr_t)0; }
void detach(Local_addr) { }

View File

@ -25,7 +25,8 @@ using namespace Genode;
Rm_session::Local_addr
Core_rm_session::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr,
Rm_session::Local_addr local_addr)
Rm_session::Local_addr local_addr,
bool executable)
{
Dataspace_component *ds = static_cast<Dataspace_component *>(_ds_ep->obj_by_cap(ds_cap));
if (!ds)

View File

@ -34,7 +34,8 @@ namespace Genode {
Local_addr attach(Dataspace_capability ds_cap, size_t size=0,
off_t offset=0, bool use_local_addr = false,
Local_addr local_addr = 0);
Local_addr local_addr = 0,
bool executable = false);
void detach(Local_addr) { }

View File

@ -29,7 +29,8 @@ using namespace Genode;
Rm_session::Local_addr
Core_rm_session::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr,
Rm_session::Local_addr local_addr)
Rm_session::Local_addr local_addr,
bool executable)
{
Dataspace_component *ds = static_cast<Dataspace_component *>(_ds_ep->obj_by_cap(ds_cap));
if (!ds)

View File

@ -34,7 +34,8 @@ namespace Genode {
Local_addr attach(Dataspace_capability ds_cap, size_t size=0,
off_t offset=0, bool use_local_addr = false,
Local_addr local_addr = 0);
Local_addr local_addr = 0,
bool executable = false);
void detach(Local_addr) { }

View File

@ -22,7 +22,7 @@ using namespace Genode;
Rm_session::Local_addr
Core_rm_session::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr,
Rm_session::Local_addr)
Rm_session::Local_addr, bool executable)
{
using namespace Okl4;

View File

@ -39,7 +39,8 @@ namespace Genode {
Local_addr attach(Dataspace_capability ds_cap, size_t size=0,
off_t offset=0, bool use_local_addr = false,
Local_addr local_addr = 0);
Local_addr local_addr = 0,
bool executable = false);
void detach(Local_addr) { }

View File

@ -46,7 +46,8 @@ namespace Genode {
Local_addr attach(Dataspace_capability ds,
size_t size = 0, off_t offset = 0,
bool use_local_addr = false,
Local_addr local_addr = (addr_t)0) {
Local_addr local_addr = (addr_t)0,
bool executable = false) {
bool try_again;
do {
@ -54,7 +55,8 @@ namespace Genode {
try {
return Rm_session_client::attach(ds, size, offset,
use_local_addr,
local_addr);
local_addr,
executable);
} catch (Rm_session::Out_of_metadata) {

View File

@ -25,10 +25,12 @@ namespace Genode {
: Rpc_client<Rm_session>(session) { }
Local_addr attach(Dataspace_capability ds, size_t size, off_t offset,
bool use_local_addr, Local_addr local_addr)
bool use_local_addr, Local_addr local_addr,
bool executable = false)
{
return call<Rpc_attach>(ds, size, offset,
use_local_addr, local_addr);
use_local_addr, local_addr,
executable);
}
void detach(Local_addr local_addr) {

View File

@ -117,6 +117,7 @@ namespace Genode {
* \param use_local_addr if set to true, attach the dataspace at
* the specified 'local_addr'
* \param local_addr local destination address
* \param executable if the mapping should be executable
*
* \throw Attach_failed if dataspace or offset is invalid,
* or on region conflict
@ -128,7 +129,8 @@ namespace Genode {
virtual Local_addr attach(Dataspace_capability ds,
size_t size = 0, off_t offset = 0,
bool use_local_addr = false,
Local_addr local_addr = (addr_t)0) = 0;
Local_addr local_addr = (addr_t)0,
bool executable = false) = 0;
/**
* Shortcut for attaching a dataspace at a predefined local address
@ -137,6 +139,13 @@ namespace Genode {
size_t size = 0, off_t offset = 0) {
return attach(ds, size, offset, true, local_addr); }
/**
* Shortcut for attaching a dataspace executable at a predefined local address
*/
Local_addr attach_executable(Dataspace_capability ds, addr_t local_addr,
size_t size = 0, off_t offset = 0) {
return attach(ds, size, offset, true, local_addr, true); }
/**
* Remove region from local address space
*/
@ -179,7 +188,7 @@ namespace Genode {
GENODE_RPC_THROW(Rpc_attach, Local_addr, attach,
GENODE_TYPE_LIST(Invalid_dataspace, Region_conflict,
Out_of_metadata, Invalid_args),
Dataspace_capability, size_t, off_t, bool, Local_addr);
Dataspace_capability, size_t, off_t, bool, Local_addr, bool);
GENODE_RPC(Rpc_detach, void, detach, Local_addr);
GENODE_RPC_THROW(Rpc_add_client, Pager_capability, add_client,
GENODE_TYPE_LIST(Invalid_thread, Out_of_memory),

View File

@ -42,15 +42,15 @@ if [have_spec linux_x86_32] {
puts "Error: detaching from sub RM session failed"
exit -1
}
if {![regexp {60040000-60044000 rwxs} $maps]} {
if {![regexp {60040000-60044000 rw.s} $maps]} {
puts "Error: populating already attached sub RM session failed"
exit -1
}
if {![regexp {60080000-60083000 rwxs 00001000} $maps]} {
if {![regexp {60080000-60083000 rw.s 00001000} $maps]} {
puts "Error: using offset parameter to sub RM attach did not work"
exit -1
}
if {![regexp {600c0000-600c2000 rwxs 00001000} $maps]} {
if {![regexp {600c0000-600c2000 rw.s 00001000} $maps]} {
puts "Error: using offset and size parameters to sub RM attach did not work"
exit -1
}

View File

@ -84,8 +84,11 @@ static addr_t _setup_elf(Parent_capability parent_cap,
bool parent_info = false;
off_t offset;
Dataspace_capability ds_cap;
void *out_ptr = 0;
bool write = seg.flags().w;
bool exec = seg.flags().x;
if (write) {
/* read-write segment */
@ -133,6 +136,9 @@ static addr_t _setup_elf(Parent_capability parent_cap,
/* detach dataspace */
env()->rm_session()->detach(base);
try { out_ptr = rm.attach_at(ds_cap, addr, size, offset); }
catch (Rm_session::Attach_failed) { }
} else {
/* read-only segment */
@ -142,11 +148,14 @@ static addr_t _setup_elf(Parent_capability parent_cap,
/* XXX currently we assume r/o segment sizes never differ */
if (seg.file_size() != seg.mem_size())
PWRN("filesz and memsz for read-only segment differ");
}
void *out_ptr = 0;
try { out_ptr = rm.attach(ds_cap, size, offset, true, addr); }
if (exec)
try { out_ptr = rm.attach_executable(ds_cap, addr, size, offset); }
catch (Rm_session::Attach_failed) { }
else
try { out_ptr = rm.attach_at(ds_cap, addr, size, offset); }
catch (Rm_session::Attach_failed) { }
}
if ((addr_t)out_ptr != addr)
PWRN("addresses differ after attach (addr=%p out_ptr=%p)",

View File

@ -49,7 +49,8 @@ class Context_area_rm_session : public Rm_session
*/
Local_addr attach(Dataspace_capability ds_cap,
size_t size, off_t offset,
bool use_local_addr, Local_addr local_addr)
bool use_local_addr, Local_addr local_addr,
bool executable)
{
Dataspace_component *ds =
dynamic_cast<Dataspace_component*>(Dataspace_capability::deref(ds_cap));

View File

@ -38,7 +38,8 @@ namespace Genode {
Local_addr attach(Dataspace_capability ds_cap, size_t size=0,
off_t offset=0, bool use_local_addr = false,
Local_addr local_addr = 0)
Local_addr local_addr = 0,
bool executable = false)
{
Dataspace_component *ds = static_cast<Dataspace_component *>(_ds_ep->obj_by_cap(ds_cap));
if (!ds)

View File

@ -342,7 +342,7 @@ namespace Genode {
** Region manager session interface **
**************************************/
Local_addr attach (Dataspace_capability, size_t, off_t, bool, Local_addr);
Local_addr attach (Dataspace_capability, size_t, off_t, bool, Local_addr, bool);
void detach (Local_addr);
Pager_capability add_client (Thread_capability);
void fault_handler (Signal_context_capability handler);

View File

@ -318,7 +318,8 @@ void Rm_faulter::continue_after_resolved_fault()
Rm_session::Local_addr
Rm_session_component::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr,
Rm_session::Local_addr local_addr)
Rm_session::Local_addr local_addr,
bool executable)
{
/* serialize access */
Lock::Guard lock_guard(_lock);

View File

@ -78,6 +78,13 @@ namespace Genode {
size_t size = 0, off_t offset = 0) {
return Rm_connection::attach_at(ds, local_addr - _base, size, offset); }
/**
* Overwritten from 'Rm_connection'
*/
Local_addr attach_executable(Dataspace_capability ds, addr_t local_addr,
size_t size = 0, off_t offset = 0) {
return Rm_connection::attach_executable(ds, local_addr - _base, size, offset); }
void detach(Local_addr local_addr) {
Rm_connection::detach((addr_t)local_addr - _base); }
};
@ -128,7 +135,7 @@ namespace Genode {
void setup_text(addr_t vaddr, size_t size, off_t offset)
{
_vaddr = vaddr;
Rm_area::r()->attach_at(_ds_rom, vaddr, size, offset);
Rm_area::r()->attach_executable(_ds_rom, vaddr, size, offset);
}
addr_t alloc_region(addr_t vaddr, addr_t vlimit)

View File

@ -57,7 +57,8 @@ Rm_session_component::Region *Rm_session_component::find_region(void *local_addr
Rm_session::Local_addr
Rm_session_component::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr,
Rm_session::Local_addr local_addr)
Rm_session::Local_addr local_addr,
bool executable)
{
if (verbose)
PDBG("size = %zd, offset = %x", size, (unsigned int)offset);
@ -76,7 +77,9 @@ Rm_session_component::attach(Dataspace_capability ds_cap, size_t size,
throw Invalid_args();
}
void *addr = _parent_rm_session.attach(ds_cap, size, offset, use_local_addr, local_addr);
void *addr = _parent_rm_session.attach(ds_cap, size, offset,
use_local_addr, local_addr,
executable);
Lock::Guard lock_guard(_region_map_lock);
_region_map.insert(new (env()->heap()) Region(addr, (void*)((addr_t)addr + size - 1), ds_cap, offset));

View File

@ -93,7 +93,7 @@ namespace Gdb_monitor {
**************************************/
Local_addr attach (Dataspace_capability, Genode::size_t,
Genode::off_t, bool, Local_addr);
Genode::off_t, bool, Local_addr, bool);
void detach (Local_addr);
Pager_capability add_client (Thread_capability);
void fault_handler (Signal_context_capability handler);

View File

@ -188,7 +188,8 @@ namespace Noux {
Local_addr attach(Dataspace_capability ds,
size_t size = 0, off_t offset = 0,
bool use_local_addr = false,
Local_addr local_addr = (addr_t)0)
Local_addr local_addr = (addr_t)0,
bool executable = false)
{
if (size == 0)
size = Dataspace_client(ds).size();
@ -199,7 +200,8 @@ namespace Noux {
*/
local_addr = _rm.attach(ds, size, offset,
use_local_addr, local_addr);
use_local_addr, local_addr,
executable);
/*
* Record attachement for later replay (needed during