summaryrefslogtreecommitdiff
path: root/vm/vm_user.c
diff options
context:
space:
mode:
authorDiego Nieto Cid <dnietoc@gmail.com>2025-09-21 21:23:42 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2025-09-22 00:51:29 +0200
commit9ae4d99c1d1e7c9c0977cebb4df9b86fa92cca94 (patch)
tree62e1baaaefde974b943755eb8771ad0a2ca182f4 /vm/vm_user.c
parent1269629d90b28a23ef9742645cfaf657ea3165bb (diff)
Implement per-task virtual memory limitHEADmaster
* doc/mach.texi: add a "Memory Limitations" section to document the new interfaces. * include/mach/gnumach.defs: (vm_set_size_limit) new routine (vm_get_size_limit) likewise * kern/task.c: (task_create_kernel) if parent_task is not null copy virtual memory limit * tests/test-vm.c: (test_vm_limit) add test for the new routines * vm/vm_map.h: (struct vm_map) new fields size_none, size_cur_limit and size_max_limit (vm_map_find_entry) add new parameters cur_protection and max_protection * vm/vm_map.c: (vm_map_setup) initialize new fields (vm_map_enforce_limit) new function (vm_map_copy_limits) new function (vm_map_find_entry) add protection and max_protection parameters. call limit enforcer function (vm_map_enter) likewise (vm_map_copyout) likewise (vm_map_copyout_page_list) likewise (vm_map_fork) copy parent limit to the new map and compute and set size_none of the new map * vm/vm_user.c: (vm_set_size_limit) new function (vm_get_size_limit) likewise * xen/grant.c: update call to vm_map_find_entry to pass protection parameters Message-ID: <0b71f4f89b7cc2b159893a805480d7493d522d60.1758485757.git.dnietoc@gmail.com>
Diffstat (limited to 'vm/vm_user.c')
-rw-r--r--vm/vm_user.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/vm/vm_user.c b/vm/vm_user.c
index c6dbda68..ef2c39d7 100644
--- a/vm/vm_user.c
+++ b/vm/vm_user.c
@@ -813,3 +813,72 @@ kern_return_t vm_pages_phys(
return KERN_SUCCESS;
}
+
+/*
+ * vm_set_size_limit
+ *
+ * Sets the current/maximum virtual adress space limits
+ * of the `target_task`.
+ *
+ * The host privileged port must be provided to increase
+ * the max limit.
+ */
+kern_return_t
+vm_set_size_limit(
+ const ipc_port_t host_port,
+ vm_map_t map,
+ vm_size_t current_limit,
+ vm_size_t max_limit)
+{
+ ipc_kobject_type_t ikot_host = IKOT_NONE;
+
+ if (current_limit > max_limit)
+ return KERN_INVALID_ARGUMENT;
+ if (map == VM_MAP_NULL)
+ return KERN_INVALID_TASK;
+
+ if (!IP_VALID(host_port))
+ return KERN_INVALID_HOST;
+ ip_lock(host_port);
+ if (ip_active(host_port))
+ ikot_host = ip_kotype(host_port);
+ ip_unlock(host_port);
+
+ if (ikot_host != IKOT_HOST && ikot_host != IKOT_HOST_PRIV)
+ return KERN_INVALID_HOST;
+
+ vm_map_lock(map);
+ if (max_limit > map->size_max_limit && ikot_host != IKOT_HOST_PRIV) {
+ vm_map_unlock(map);
+ return KERN_NO_ACCESS;
+ }
+
+ map->size_cur_limit = current_limit;
+ map->size_max_limit = max_limit;
+ vm_map_unlock(map);
+
+ return KERN_SUCCESS;
+}
+
+/*
+ * vm_get_size_limit
+ *
+ * Gets the current/maximum virtual adress space limits
+ * of the provided `map`.
+ */
+kern_return_t
+vm_get_size_limit(
+ vm_map_t map,
+ vm_size_t *current_limit,
+ vm_size_t *max_limit)
+{
+ if (map == VM_MAP_NULL)
+ return KERN_INVALID_TASK;
+
+ vm_map_lock_read(map);
+ *current_limit = map->size_cur_limit;
+ *max_limit = map->size_max_limit;
+ vm_map_unlock_read(map);
+
+ return KERN_SUCCESS;
+}