From 44ca02a46b6fa0a8f1181fdc08efa779c3bdce80 Mon Sep 17 00:00:00 2001 From: Joan Lledó Date: Sat, 6 Nov 2021 09:13:32 +0100 Subject: vm: vm_region_get_proxy 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: vm_region_get_proxy RPC declaration * vm/vm_map.c: vm_region_get_proxy implementation Message-Id: <20211106081333.10366-2-jlledom@mailfence.com> --- include/mach/mach4.defs | 10 +++++++++ vm/memory_object_proxy.h | 8 +++++++ vm/vm_map.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/include/mach/mach4.defs b/include/mach/mach4.defs index 22bbbaec..2820bd73 100644 --- a/include/mach/mach4.defs +++ b/include/mach/mach4.defs @@ -111,3 +111,13 @@ routine memory_object_create_proxy( start : vm_offset_array_t; len : vm_size_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 vm_region_get_proxy( + task : task_t; + address : vm_address_t; + max_protection : vm_prot_t; + len : vm_size_t; + out proxy : mach_port_t); diff --git a/vm/memory_object_proxy.h b/vm/memory_object_proxy.h index 8b3f2025..97f20b36 100644 --- a/vm/memory_object_proxy.h +++ b/vm/memory_object_proxy.h @@ -36,4 +36,12 @@ extern kern_return_t memory_object_proxy_lookup (ipc_port_t port, vm_offset_t *start, vm_offset_t *len); +extern kern_return_t +memory_object_create_proxy (ipc_space_t space, vm_prot_t max_protection, + ipc_port_t *object, natural_t object_count, + vm_offset_t *offset, natural_t offset_count, + vm_offset_t *start, natural_t start_count, + vm_size_t *len, natural_t len_count, + ipc_port_t *port); + #endif /* _VM_MEMORY_OBJECT_PROXY_H_ */ diff --git a/vm/vm_map.c b/vm/vm_map.c index a687d365..900862d9 100644 --- a/vm/vm_map.c +++ b/vm/vm_map.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,7 @@ #include #include #include +#include #include #include @@ -4806,6 +4808,60 @@ kern_return_t vm_region( return(KERN_SUCCESS); } +/* + * vm_region_get_proxy: + * + * 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 +vm_region_get_proxy (task_t task, vm_address_t address, + vm_prot_t max_protection, vm_size_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; +} + /* * Routine: vm_map_simplify * -- cgit v1.2.3