base: stricter distinction between rx and rwx

This patch restricts 'Region_map::attach_executable' to create read-only
mappings, while offering the option to map the full rights using a new
'attach_rwx' method.

The 'attach_rwx' method is now used by the dynamic linker to explicitly
attach the linker area with full rwx rights. With the old page-fault
handling code, the execute flag was evaluated only for leaf dataspaces,
not for managed dataspaces while traversing region-map hierarchies.
With the new page-fault handling code, the execute bit is downgraded
to no-execute when passing a managed dataspace that is not attached
as executable.

Issue #4920
This commit is contained in:
Norman Feske 2023-06-10 01:12:30 +02:00
parent a4c59c03e3
commit 3c5d27506f
6 changed files with 16 additions and 11 deletions

View File

@ -127,11 +127,18 @@ struct Genode::Region_map : Interface
return attach(ds, size, offset, true, local_addr); }
/**
* Shortcut for attaching a dataspace executable at a predefined local address
* Shortcut for attaching a dataspace executable at 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); }
return attach(ds, size, offset, true, local_addr, true, false ); }
/**
* Shortcut for attaching a dataspace will full rights at local address
*/
Local_addr attach_rwx(Dataspace_capability ds, addr_t local_addr,
size_t size = 0, off_t offset = 0) {
return attach(ds, size, offset, true, local_addr, true, true ); }
/**
* Remove region from local address space

View File

@ -57,7 +57,7 @@ class Linker::Region_map
Region_map(Env &env, Allocator &md_alloc, addr_t base)
:
_env(env), _range(&md_alloc),
_base((addr_t)_env.rm().attach_at(_rm.dataspace(), base))
_base((addr_t)_env.rm().attach_rwx(_rm.dataspace(), base))
{
_range.add_range(base, Pd_session::LINKER_AREA_SIZE);

View File

@ -135,9 +135,8 @@ static Sub_rm_connection &vm_memory(Genode::uint64_t vm_size = 0)
while (allocated < memory_size) {
Ram_dataspace_capability ds = genode_env().ram().alloc(alloc_size);
addr_t to = vm_memory.attach_executable(ds, memory.addr +
allocated - vmm_local,
alloc_size);
addr_t to = vm_memory.attach_rwx(ds, memory.addr + allocated - vmm_local,
alloc_size);
Assert(to == vm_memory.local_addr(memory.addr + allocated - vmm_local));
allocated += alloc_size;

View File

@ -39,7 +39,7 @@ class Sub_rm_connection : private Genode::Rm_connection,
:
Rm_connection(env),
Genode::Region_map_client(Rm_connection::create(size)),
_offset(env.rm().attach(dataspace())),
_offset(env.rm().attach(dataspace(), 0, 0, false, nullptr, true, true)),
_size(size)
{ }

View File

@ -110,9 +110,8 @@ static Sub_rm_connection &vm_memory(Genode::uint64_t vm_size = 0)
while (allocated < memory_size) {
Ram_dataspace_capability ds = genode_env().ram().alloc(alloc_size);
addr_t to = vm_memory.attach_executable(ds, memory.addr +
allocated - vmm_local,
alloc_size);
addr_t to = vm_memory.attach_rwx(ds, memory.addr + allocated - vmm_local,
alloc_size);
Assert(to == vm_memory.local_addr(memory.addr + allocated - vmm_local));
allocated += alloc_size;

View File

@ -35,7 +35,7 @@ void Sup::Gmm::_add_one_slice()
Ram_dataspace_capability ds = _env.ram().alloc(slice_size);
_map.connection.retry_with_upgrade(Ram_quota{8192}, Cap_quota{2}, [&] () {
_map.rm.attach_executable(ds, attach_base, slice_size); });
_map.rm.attach_rwx(ds, attach_base, slice_size); });
_slices[_slice_index(Offset{attach_base})] = ds;