diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2015-07-09 14:13:25 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2015-07-09 14:13:25 +0200 |
commit | eaee9424a120c289abc3eeeff331cb0d45efe971 (patch) | |
tree | e0bb7aec9484943d15277c67292d5036a9702569 /vm/vm_user.c | |
parent | 1e0429e5f39ec219cbef3af2752528b8a29bc1be (diff) | |
download | gnumach-eaee9424a120c289abc3eeeff331cb0d45efe971.tar.gz gnumach-eaee9424a120c289abc3eeeff331cb0d45efe971.tar.bz2 gnumach-eaee9424a120c289abc3eeeff331cb0d45efe971.zip |
Allow non-privileged tasks to wire 64KiB task memory
* doc/mach.texi (vm_wire): Document that the host port does not have to be
privileged.
* include/mach/mach_hosts.defs (vm_wire): Use mach_port_t instead of
host_priv_t.
* vm/vm_map.h (vm_map): Add user_wired field.
* vm/vm_map.c (vm_map_setup): Initialize user_wired field to 0.
(vm_map_pageable_common, vm_map_entry_delete, vm_map_copy_overwrite,
vm_map_copyout_page_list, vm_map_copyin_page_list): When switching
user_wired_count field of entry between 0 and non-0, accumulate the
corresponding size into the user_wired field of map.
* vm/vm_user.c (vm_wire): Turn host parameter into port parameter, and
inline a version of convert_port_to_host_priv which records whether the host
port is privileged or not. When it is not privileged, check whether
the additional amount to user_wired will overcome 64KiB.
Diffstat (limited to 'vm/vm_user.c')
-rw-r--r-- | vm/vm_user.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/vm/vm_user.c b/vm/vm_user.c index f7c87cc0..8c7a5d8f 100644 --- a/vm/vm_user.c +++ b/vm/vm_user.c @@ -405,15 +405,32 @@ kern_return_t vm_map( * * [ To unwire the pages, specify VM_PROT_NONE. ] */ -kern_return_t vm_wire(host, map, start, size, access) - const host_t host; +kern_return_t vm_wire(port, map, start, size, access) + const ipc_port_t port; vm_map_t map; vm_offset_t start; vm_size_t size; vm_prot_t access; { - if (host == HOST_NULL) + host_t host; + boolean_t priv; + + if (!IP_VALID(port)) + return KERN_INVALID_HOST; + + ip_lock(port); + if (!ip_active(port) || + (ip_kotype(port) != IKOT_HOST_PRIV + && ip_kotype(port) != IKOT_HOST)) + { + ip_unlock(port); return KERN_INVALID_HOST; + } + + priv = ip_kotype(port) == IKOT_HOST_PRIV; + ip_unlock(port); + + host = (host_t) port->ip_kobject; if (map == VM_MAP_NULL) return KERN_INVALID_TASK; @@ -426,6 +443,10 @@ kern_return_t vm_wire(host, map, start, size, access) if (projected_buffer_in_range(map, start, start+size)) return(KERN_INVALID_ARGUMENT); + /* TODO: make it tunable */ + if (!priv && access != VM_PROT_NONE && map->user_wired + size > 65536) + return KERN_NO_ACCESS; + return vm_map_pageable_user(map, trunc_page(start), round_page(start+size), |