mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-29 15:44:02 +00:00
core: restrict mapping size recursively on regions
This commit is contained in:
parent
5b8a2af979
commit
30c69e73b3
@ -41,8 +41,9 @@ void Pd_session_component::map(addr_t virt, addr_t size)
|
||||
|
||||
auto lambda = [&] (Region_map_component *region_map,
|
||||
Rm_region *region,
|
||||
addr_t ds_offset,
|
||||
addr_t region_offset) -> addr_t
|
||||
addr_t const ds_offset,
|
||||
addr_t const region_offset,
|
||||
addr_t const dst_region_size) -> addr_t
|
||||
{
|
||||
Dataspace_component * dsc = region ? region->dataspace() : nullptr;
|
||||
if (!dsc) {
|
||||
@ -54,7 +55,8 @@ void Pd_session_component::map(addr_t virt, addr_t size)
|
||||
region,
|
||||
ds_offset,
|
||||
region_offset,
|
||||
dsc, virt);
|
||||
dsc, virt,
|
||||
dst_region_size);
|
||||
|
||||
/* asynchronously map memory */
|
||||
uint8_t err = Nova::NOVA_PD_OOM;
|
||||
|
@ -318,7 +318,8 @@ class Genode::Region_map_component : private Weak_object<Region_map_component>,
|
||||
Dataspace_capability _ds_cap;
|
||||
|
||||
template <typename F>
|
||||
auto _apply_to_dataspace(addr_t addr, F f, addr_t offset, unsigned level)
|
||||
auto _apply_to_dataspace(addr_t addr, F f, addr_t offset,
|
||||
unsigned level, addr_t dst_region_size)
|
||||
-> typename Trait::Functor<decltype(&F::operator())>::Return_type
|
||||
{
|
||||
using Functor = Trait::Functor<decltype(&F::operator())>;
|
||||
@ -327,13 +328,17 @@ class Genode::Region_map_component : private Weak_object<Region_map_component>,
|
||||
Lock::Guard lock_guard(_lock);
|
||||
|
||||
/* skip further lookup when reaching the recursion limit */
|
||||
if (!level) return f(this, nullptr, 0, 0);
|
||||
if (!level) return f(this, nullptr, 0, 0, dst_region_size);
|
||||
|
||||
/* lookup region and dataspace */
|
||||
Rm_region *region = _map.metadata((void*)addr);
|
||||
Dataspace_component *dsc = region ? region->dataspace()
|
||||
: nullptr;
|
||||
|
||||
if (region && dst_region_size > region->size())
|
||||
dst_region_size = region->size();
|
||||
|
||||
|
||||
/* calculate offset in dataspace */
|
||||
addr_t ds_offset = region ? (addr - region->base()
|
||||
+ region->offset()) : 0;
|
||||
@ -342,15 +347,16 @@ class Genode::Region_map_component : private Weak_object<Region_map_component>,
|
||||
Native_capability cap = dsc ? dsc->sub_rm()
|
||||
: Native_capability();
|
||||
|
||||
if (!cap.valid()) return f(this, region, ds_offset, offset);
|
||||
if (!cap.valid()) return f(this, region, ds_offset, offset, dst_region_size);
|
||||
|
||||
/* in case of a nested dataspace perform a recursive lookup */
|
||||
auto lambda = [&] (Region_map_component *rmc) -> Return_type
|
||||
{
|
||||
return (!rmc) ? f(nullptr, nullptr, ds_offset, offset)
|
||||
return (!rmc) ? f(nullptr, nullptr, ds_offset, offset, dst_region_size)
|
||||
: rmc->_apply_to_dataspace(ds_offset, f,
|
||||
offset+region->base(),
|
||||
--level);
|
||||
--level,
|
||||
dst_region_size);
|
||||
};
|
||||
return _session_ep->apply(cap, lambda);
|
||||
}
|
||||
@ -419,7 +425,7 @@ class Genode::Region_map_component : private Weak_object<Region_map_component>,
|
||||
{
|
||||
enum { RECURSION_LIMIT = 5 };
|
||||
|
||||
return _apply_to_dataspace(addr, f, 0, RECURSION_LIMIT);
|
||||
return _apply_to_dataspace(addr, f, 0, RECURSION_LIMIT, ~0UL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -438,7 +444,7 @@ class Genode::Region_map_component : private Weak_object<Region_map_component>,
|
||||
addr_t ds_offset,
|
||||
addr_t region_offset,
|
||||
Dataspace_component *dsc,
|
||||
addr_t);
|
||||
addr_t, addr_t);
|
||||
|
||||
/**************************
|
||||
** Region map interface **
|
||||
|
@ -185,8 +185,9 @@ int Rm_client::pager(Ipc_pager &pager)
|
||||
|
||||
auto lambda = [&] (Region_map_component *region_map,
|
||||
Rm_region *region,
|
||||
addr_t ds_offset,
|
||||
addr_t region_offset) -> int
|
||||
addr_t const ds_offset,
|
||||
addr_t const region_offset,
|
||||
addr_t const dst_region_size) -> int
|
||||
{
|
||||
Dataspace_component * dsc = region ? region->dataspace() : nullptr;
|
||||
if (!dsc) {
|
||||
@ -240,7 +241,8 @@ int Rm_client::pager(Ipc_pager &pager)
|
||||
region,
|
||||
ds_offset,
|
||||
region_offset,
|
||||
dsc, pf_addr);
|
||||
dsc, pf_addr,
|
||||
dst_region_size);
|
||||
|
||||
/*
|
||||
* On kernels with a mapping database, the 'dsc' dataspace is a leaf
|
||||
@ -312,16 +314,17 @@ void Rm_faulter::continue_after_resolved_fault()
|
||||
|
||||
Mapping Region_map_component::create_map_item(Region_map_component *,
|
||||
Rm_region *region,
|
||||
addr_t ds_offset,
|
||||
addr_t region_offset,
|
||||
addr_t const ds_offset,
|
||||
addr_t const region_offset,
|
||||
Dataspace_component *dsc,
|
||||
addr_t page_addr)
|
||||
addr_t const page_addr,
|
||||
addr_t const dst_region_size)
|
||||
{
|
||||
addr_t ds_base = dsc->map_src_addr();
|
||||
Fault_area src_fault_area(ds_base + ds_offset);
|
||||
Fault_area dst_fault_area(page_addr);
|
||||
src_fault_area.constrain(ds_base, dsc->size());
|
||||
dst_fault_area.constrain(region_offset + region->base(), region->size());
|
||||
dst_fault_area.constrain(region_offset + region->base(), dst_region_size);
|
||||
|
||||
/*
|
||||
* Determine mapping size compatible with source and destination,
|
||||
@ -360,6 +363,10 @@ Region_map_component::attach(Dataspace_capability ds_cap, size_t size,
|
||||
/* check dataspace validity */
|
||||
if (!dsc) throw Invalid_dataspace();
|
||||
|
||||
size_t const off = offset;
|
||||
if (off >= dsc->size())
|
||||
throw Region_conflict();
|
||||
|
||||
if (!size)
|
||||
size = dsc->size() - offset;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user