summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoan Lledó <jlledom@member.fsf.org>2021-11-06 09:13:32 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2021-11-07 17:55:13 +0100
commit44ca02a46b6fa0a8f1181fdc08efa779c3bdce80 (patch)
tree140b4a8af5706b6e204bf398baa117a4f62ff615
parenta0473675b98f51c48ea92c357793c2dbed0d1d85 (diff)
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>
-rw-r--r--include/mach/mach4.defs10
-rw-r--r--vm/memory_object_proxy.h8
-rw-r--r--vm/vm_map.c56
3 files changed, 74 insertions, 0 deletions
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 <kern/list.h>
#include <kern/rbtree.h>
#include <kern/slab.h>
+#include <kern/mach4.server.h>
#include <vm/pmap.h>
#include <vm/vm_fault.h>
#include <vm/vm_map.h>
@@ -53,6 +54,7 @@
#include <vm/vm_page.h>
#include <vm/vm_resident.h>
#include <vm/vm_kern.h>
+#include <vm/memory_object_proxy.h>
#include <ipc/ipc_port.h>
#include <string.h>
@@ -4807,6 +4809,60 @@ kern_return_t vm_region(
}
/*
+ * 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
*
* Description: