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 Rm_session::Local_addr
Core_rm_session::attach(Dataspace_capability ds_cap, size_t size, Core_rm_session::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr, off_t offset, bool use_local_addr,
Rm_session::Local_addr local_addr) Rm_session::Local_addr local_addr,
bool executable)
{ {
using namespace Codezero; using namespace Codezero;

View File

@ -34,7 +34,8 @@ namespace Genode {
Local_addr attach(Dataspace_capability ds_cap, size_t size = 0, Local_addr attach(Dataspace_capability ds_cap, size_t size = 0,
off_t offset = 0, bool use_local_addr = false, 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) { } void detach(Local_addr) { }

View File

@ -206,7 +206,8 @@ namespace Genode {
**************************************/ **************************************/
Local_addr attach(Dataspace_capability ds, size_t size, 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); void detach(Local_addr local_addr);

View File

@ -34,9 +34,11 @@ namespace Genode {
: _cap(session) { } : _cap(session) { }
Local_addr attach(Dataspace_capability ds, size_t size, off_t offset, 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) { 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, 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(); Linux_dataspace::Filename fname = Linux_dataspace_client(ds).fname();
fname.buf[sizeof(fname.buf) - 1] = 0; 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 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, void *addr = lx_mmap(use_local_addr ? (void*)local_addr : 0, size,
prot, flags, fd, offset); prot, flags, fd, offset);
@ -84,7 +85,8 @@ Rm_session::Local_addr
Platform_env::Rm_session_mmap::attach(Dataspace_capability ds, Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
size_t size, off_t offset, size_t size, off_t offset,
bool use_local_addr, bool use_local_addr,
Rm_session::Local_addr local_addr) Rm_session::Local_addr local_addr,
bool executable)
{ {
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
@ -150,7 +152,7 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
* and map it. * and map it.
*/ */
if (_is_attached()) 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; return (void *)local_addr;
@ -197,7 +199,8 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
continue; continue;
map_local(region.dataspace(), region.size(), region.offset(), 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; 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. * 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)); _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, Local_addr attach(Genode::Dataspace_capability ds_cap,
Genode::size_t size, Genode::off_t offset, 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; using namespace Genode;

View File

@ -40,7 +40,7 @@ namespace Genode {
void upgrade_ram_quota(size_t ram_quota) { } 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; } return (addr_t)0; }
void detach(Local_addr) { } void detach(Local_addr) { }

View File

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

View File

@ -34,7 +34,8 @@ namespace Genode {
Local_addr attach(Dataspace_capability ds_cap, size_t size=0, Local_addr attach(Dataspace_capability ds_cap, size_t size=0,
off_t offset=0, bool use_local_addr = false, 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) { } void detach(Local_addr) { }

View File

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

View File

@ -34,7 +34,8 @@ namespace Genode {
Local_addr attach(Dataspace_capability ds_cap, size_t size=0, Local_addr attach(Dataspace_capability ds_cap, size_t size=0,
off_t offset=0, bool use_local_addr = false, 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) { } void detach(Local_addr) { }

View File

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

View File

@ -39,7 +39,8 @@ namespace Genode {
Local_addr attach(Dataspace_capability ds_cap, size_t size=0, Local_addr attach(Dataspace_capability ds_cap, size_t size=0,
off_t offset=0, bool use_local_addr = false, 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) { } void detach(Local_addr) { }

View File

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

View File

@ -25,10 +25,12 @@ namespace Genode {
: Rpc_client<Rm_session>(session) { } : Rpc_client<Rm_session>(session) { }
Local_addr attach(Dataspace_capability ds, size_t size, off_t offset, 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, return call<Rpc_attach>(ds, size, offset,
use_local_addr, local_addr); use_local_addr, local_addr,
executable);
} }
void detach(Local_addr local_addr) { 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 * \param use_local_addr if set to true, attach the dataspace at
* the specified 'local_addr' * the specified 'local_addr'
* \param local_addr local destination address * \param local_addr local destination address
* \param executable if the mapping should be executable
* *
* \throw Attach_failed if dataspace or offset is invalid, * \throw Attach_failed if dataspace or offset is invalid,
* or on region conflict * or on region conflict
@ -128,7 +129,8 @@ namespace Genode {
virtual Local_addr attach(Dataspace_capability ds, virtual Local_addr attach(Dataspace_capability ds,
size_t size = 0, off_t offset = 0, size_t size = 0, off_t offset = 0,
bool use_local_addr = false, 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 * Shortcut for attaching a dataspace at a predefined local address
@ -137,6 +139,13 @@ namespace Genode {
size_t size = 0, off_t offset = 0) { size_t size = 0, off_t offset = 0) {
return attach(ds, size, offset, true, local_addr); } 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 * Remove region from local address space
*/ */
@ -179,7 +188,7 @@ namespace Genode {
GENODE_RPC_THROW(Rpc_attach, Local_addr, attach, GENODE_RPC_THROW(Rpc_attach, Local_addr, attach,
GENODE_TYPE_LIST(Invalid_dataspace, Region_conflict, GENODE_TYPE_LIST(Invalid_dataspace, Region_conflict,
Out_of_metadata, Invalid_args), 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(Rpc_detach, void, detach, Local_addr);
GENODE_RPC_THROW(Rpc_add_client, Pager_capability, add_client, GENODE_RPC_THROW(Rpc_add_client, Pager_capability, add_client,
GENODE_TYPE_LIST(Invalid_thread, Out_of_memory), 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" puts "Error: detaching from sub RM session failed"
exit -1 exit -1
} }
if {![regexp {60040000-60044000 rwxs} $maps]} { if {![regexp {60040000-60044000 rw.s} $maps]} {
puts "Error: populating already attached sub RM session failed" puts "Error: populating already attached sub RM session failed"
exit -1 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" puts "Error: using offset parameter to sub RM attach did not work"
exit -1 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" puts "Error: using offset and size parameters to sub RM attach did not work"
exit -1 exit -1
} }

View File

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

View File

@ -342,7 +342,7 @@ namespace Genode {
** Region manager session interface ** ** 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); void detach (Local_addr);
Pager_capability add_client (Thread_capability); Pager_capability add_client (Thread_capability);
void fault_handler (Signal_context_capability handler); 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::Local_addr
Rm_session_component::attach(Dataspace_capability ds_cap, size_t size, Rm_session_component::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr, off_t offset, bool use_local_addr,
Rm_session::Local_addr local_addr) Rm_session::Local_addr local_addr,
bool executable)
{ {
/* serialize access */ /* serialize access */
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);

View File

@ -78,6 +78,13 @@ namespace Genode {
size_t size = 0, off_t offset = 0) { size_t size = 0, off_t offset = 0) {
return Rm_connection::attach_at(ds, local_addr - _base, size, offset); } 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) { void detach(Local_addr local_addr) {
Rm_connection::detach((addr_t)local_addr - _base); } 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) void setup_text(addr_t vaddr, size_t size, off_t offset)
{ {
_vaddr = vaddr; _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) 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::Local_addr
Rm_session_component::attach(Dataspace_capability ds_cap, size_t size, Rm_session_component::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr, off_t offset, bool use_local_addr,
Rm_session::Local_addr local_addr) Rm_session::Local_addr local_addr,
bool executable)
{ {
if (verbose) if (verbose)
PDBG("size = %zd, offset = %x", size, (unsigned int)offset); 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(); 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); Lock::Guard lock_guard(_region_map_lock);
_region_map.insert(new (env()->heap()) Region(addr, (void*)((addr_t)addr + size - 1), ds_cap, offset)); _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, 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); void detach (Local_addr);
Pager_capability add_client (Thread_capability); Pager_capability add_client (Thread_capability);
void fault_handler (Signal_context_capability handler); void fault_handler (Signal_context_capability handler);

View File

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