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


Reply via email to