So I've applied the patch and have tried to actually exercise the new
functionality.

And unfortunately, I'm reminded (by a kernel panic and a corrupted
filesystem) of the two important cases that we have forgot:

* Submaps
* "Anonymous" mappings (created with a null memory object)

Submaps could be doable by recursing down through them — or really, we
can just explicitly not support submaps, they only seem to be relevant
for the kernel's own memory map.

Anonymous mappings are exactly what we're interested in for
realloc/mremap, so it's important that we support them. After reading
up on how memory objects (pagers) and vm_object's and pages and
whatnot work within the kernel, I believe a call to
vm_object_pager_create () should be sufficient to "realize" a
previously-anonymous mapping. I've applied these changes to your
patch:

--- a/vm/memory_object_proxy.c
+++ b/vm/memory_object_proxy.c
@@ -201,6 +201,7 @@ memory_object_get_proxy (task_t task, const
vm_offset_t address,
 {
   kern_return_t ret;
   vm_map_entry_t entry, tmp_entry;
+  vm_object_t object;
   vm_offset_t offset, start;
   ipc_port_t pager;

@@ -217,14 +218,26 @@ memory_object_get_proxy (task_t task, const
vm_offset_t address,
     entry = tmp_entry;
   }

+  if (entry->is_sub_map) {
+    vm_map_unlock_read(task->map);
+    return(KERN_INVALID_ARGUMENT);
+  }
+
   /* 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);
+
+  object = entry->object.vm_object;
+  vm_object_lock(object);
+  /* Create a pager in case this is an internal object that does
+     not yet have one. */
+  vm_object_pager_create(object);
+  pager = ipc_port_copy_send(object->pager);
+  vm_object_unlock(object);
+
   offset = entry->offset;
   start = 0;

And now the kernel at least no longer crashes, even after multiple
iterations of this (good!). I am able to successfully create a proxy
and map it, and it does find the same underlying vm_object_t.
vm_region () also shows the same name and offset between the old and
the new mappings, so all is good in theory.

The only problem is when I try to actually read data from the new
mapping, I get complete garbage :(

Sergey

Reply via email to