From: Joan Lledó <jlle...@member.fsf.org> To get a proxy to the region a given address belongs to, with protection and range limited to the region ones.
* include/mach/mach4.defs: memory_object_get_proxy RPC declaration * vm/memory_object_proxy.c: memory_object_get_proxy implementation --- include/mach/mach4.defs | 10 ++++++++ vm/memory_object_proxy.c | 50 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/mach/mach4.defs b/include/mach/mach4.defs index 98af5905..e1641146 100644 --- a/include/mach/mach4.defs +++ b/include/mach/mach4.defs @@ -110,3 +110,13 @@ routine memory_object_create_proxy( start : vm_offset_array_t; len : vm_offset_array_t; out proxy : mach_port_t); + +/* Gets a proxy to the region that ADDRESS belongs to, starting at the region + start, with MAX_PROTECTION and LEN limited by the region ones, and returns + it in *PORT. */ +routine memory_object_get_proxy( + task : task_t; + address : vm_address_t; + max_protection : vm_prot_t; + len : vm_offset_t; + out proxy : mach_port_t); diff --git a/vm/memory_object_proxy.c b/vm/memory_object_proxy.c index b55a17f1..b6c73576 100644 --- a/vm/memory_object_proxy.c +++ b/vm/memory_object_proxy.c @@ -191,6 +191,56 @@ memory_object_create_proxy (const ipc_space_t space, vm_prot_t max_protection, return KERN_SUCCESS; } +/* Gets a proxy to the region that ADDRESS belongs to, starting at the region + start, with MAX_PROTECTION and LEN limited by the region ones, and returns + it in *PORT. */ +kern_return_t +memory_object_get_proxy (task_t task, const vm_offset_t address, + vm_prot_t max_protection, vm_offset_t len, + ipc_port_t *port) +{ + kern_return_t ret; + vm_map_entry_t entry, tmp_entry; + vm_offset_t offset, start; + ipc_port_t pager; + + if (task == TASK_NULL) + return(KERN_INVALID_ARGUMENT); + + vm_map_lock_read(task->map); + if (!vm_map_lookup_entry(task->map, address, &tmp_entry)) { + if ((entry = tmp_entry->vme_next) == vm_map_to_entry(task->map)) { + vm_map_unlock_read(task->map); + return(KERN_NO_SPACE); + } + } else { + entry = tmp_entry; + } + + /* Limit the allowed protection and range to the entry ones */ + if (len > entry->vme_end - entry->vme_start) { + vm_map_unlock_read(task->map); + return(KERN_INVALID_ARGUMENT); + } + + max_protection &= entry->max_protection; + pager = ipc_port_copy_send(entry->object.vm_object->pager); + offset = entry->offset; + start = 0; + + vm_map_unlock_read(task->map); + + ret = memory_object_create_proxy(task->itk_space, max_protection, + &pager, 1, + &offset, 1, + &start, 1, + &len, 1, port); + if (ret) + ipc_port_release_send(pager); + + return ret; +} + /* Lookup the real memory object and maximum protection for the proxy memory object port PORT, for which the caller holds a reference. *OBJECT is only guaranteed to be valid as long as the caller holds -- 2.31.1