|
|
1.1 ! root 1: /* memory_object_proxy.c - Proxy memory objects for Mach. ! 2: Copyright (C) 2005 Free Software Foundation, Inc. ! 3: Written by Marcus Brinkmann. ! 4: ! 5: This file is part of GNU Mach. ! 6: ! 7: GNU Mach is free software; you can redistribute it and/or modify it ! 8: under the terms of the GNU General Public License as published by ! 9: the Free Software Foundation; either version 2, or (at your option) ! 10: any later version. ! 11: ! 12: GNU Mach is distributed in the hope that it will be useful, but ! 13: WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 15: General Public License for more details. ! 16: ! 17: You should have received a copy of the GNU General Public License ! 18: along with this program; if not, write to the Free Software ! 19: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ ! 20: ! 21: /* A proxy memory object is a kernel port that can be used like a real ! 22: memory object in a vm_map call, except that the current and maximum ! 23: protection are restricted to the proxy object's maximum protection ! 24: at the time the mapping is established. The kernel port will hold ! 25: a reference to the real memory object for the life time of the ! 26: proxy object. ! 27: ! 28: Note that we don't need to do any reference counting on the proxy ! 29: object. Our caller will hold a reference to the proxy object when ! 30: looking it up, and is expected to acquire its own reference to the ! 31: real memory object if needed before releasing the reference to the ! 32: proxy object. ! 33: ! 34: The user provided real memory object and the maximum protection are ! 35: not checked for validity. The maximum protection is only used as a ! 36: mask, and the memory object is validated at the time the mapping is ! 37: established. */ ! 38: ! 39: #include <mach/port.h> ! 40: #include <mach/kern_return.h> ! 41: #include <mach/notify.h> ! 42: #include <mach/vm_prot.h> ! 43: #include <kern/printf.h> ! 44: #include <kern/slab.h> ! 45: #include <ipc/ipc_port.h> ! 46: #include <ipc/ipc_space.h> ! 47: ! 48: #include <vm/memory_object_proxy.h> ! 49: ! 50: /* The cache which holds our proxy memory objects. */ ! 51: static struct kmem_cache memory_object_proxy_cache; ! 52: ! 53: struct memory_object_proxy ! 54: { ! 55: struct ipc_port *port; ! 56: ! 57: ipc_port_t object; ! 58: vm_prot_t max_protection; ! 59: }; ! 60: typedef struct memory_object_proxy *memory_object_proxy_t; ! 61: ! 62: ! 63: void ! 64: memory_object_proxy_init (void) ! 65: { ! 66: kmem_cache_init (&memory_object_proxy_cache, "memory_object_proxy", ! 67: sizeof (struct memory_object_proxy), 0, NULL, NULL, NULL, 0); ! 68: } ! 69: ! 70: /* Lookup a proxy memory object by its port. */ ! 71: static memory_object_proxy_t ! 72: memory_object_proxy_port_lookup (ipc_port_t port) ! 73: { ! 74: memory_object_proxy_t proxy; ! 75: ! 76: if (!IP_VALID(port)) ! 77: return 0; ! 78: ! 79: ip_lock (port); ! 80: if (ip_active (port) && (ip_kotype (port) == IKOT_PAGER_PROXY)) ! 81: proxy = (memory_object_proxy_t) port->ip_kobject; ! 82: else ! 83: proxy = 0; ! 84: ip_unlock (port); ! 85: return proxy; ! 86: } ! 87: ! 88: ! 89: /* Process a no-sender notification for the proxy memory object ! 90: port. */ ! 91: boolean_t ! 92: memory_object_proxy_notify (mach_msg_header_t *msg) ! 93: { ! 94: if (msg->msgh_id == MACH_NOTIFY_NO_SENDERS) ! 95: { ! 96: memory_object_proxy_t proxy; ! 97: mach_no_senders_notification_t *ns; ! 98: ! 99: ns = (mach_no_senders_notification_t *) msg; ! 100: proxy = memory_object_proxy_port_lookup ! 101: ((ipc_port_t) ns->not_header.msgh_remote_port); ! 102: assert (proxy); ! 103: ! 104: ipc_port_release_send (proxy->object); ! 105: return TRUE; ! 106: } ! 107: ! 108: printf ("memory_object_proxy_notify: strange notification %d\n", ! 109: msg->msgh_id); ! 110: return FALSE; ! 111: } ! 112: ! 113: ! 114: /* Create a new proxy memory object from [START;START+LEN) in the ! 115: given OBJECT at OFFSET in the new object with the maximum ! 116: protection MAX_PROTECTION and return it in *PORT. */ ! 117: kern_return_t ! 118: memory_object_create_proxy (ipc_space_t space, vm_prot_t max_protection, ! 119: ipc_port_t *object, natural_t object_count, ! 120: vm_offset_t *offset, natural_t offset_count, ! 121: vm_offset_t *start, natural_t start_count, ! 122: vm_offset_t *len, natural_t len_count, ! 123: ipc_port_t *port) ! 124: { ! 125: memory_object_proxy_t proxy; ! 126: ipc_port_t notify; ! 127: ! 128: if (space == IS_NULL) ! 129: return KERN_INVALID_TASK; ! 130: ! 131: if (offset_count != object_count || start_count != object_count ! 132: || len_count != object_count) ! 133: return KERN_INVALID_ARGUMENT; ! 134: ! 135: /* FIXME: Support more than one memory object. */ ! 136: if (object_count != 1) ! 137: return KERN_INVALID_ARGUMENT; ! 138: ! 139: if (!IP_VALID(object[0])) ! 140: return KERN_INVALID_NAME; ! 141: ! 142: /* FIXME: Support a different offset from 0. */ ! 143: if (offset[0] != 0) ! 144: return KERN_INVALID_ARGUMENT; ! 145: ! 146: /* FIXME: Support a different range from total. */ ! 147: if (start[0] != 0 || len[0] != (vm_offset_t) ~0) ! 148: return KERN_INVALID_ARGUMENT; ! 149: ! 150: proxy = (memory_object_proxy_t) kmem_cache_alloc (&memory_object_proxy_cache); ! 151: ! 152: /* Allocate port, keeping a reference for it. */ ! 153: proxy->port = ipc_port_alloc_kernel (); ! 154: if (proxy->port == IP_NULL) ! 155: { ! 156: kmem_cache_free (&memory_object_proxy_cache, (vm_offset_t) proxy); ! 157: return KERN_RESOURCE_SHORTAGE; ! 158: } ! 159: /* Associate the port with the proxy memory object. */ ! 160: ipc_kobject_set (proxy->port, (ipc_kobject_t) proxy, IKOT_PAGER_PROXY); ! 161: ! 162: /* Request no-senders notifications on the port. */ ! 163: notify = ipc_port_make_sonce (proxy->port); ! 164: ip_lock (proxy->port); ! 165: ipc_port_nsrequest (proxy->port, 1, notify, ¬ify); ! 166: assert (notify == IP_NULL); ! 167: ! 168: proxy->object = ipc_port_copy_send (object[0]); ! 169: proxy->max_protection = max_protection; ! 170: ! 171: *port = ipc_port_make_send (proxy->port); ! 172: return KERN_SUCCESS; ! 173: } ! 174: ! 175: ! 176: /* Lookup the real memory object and maximum protection for the proxy ! 177: memory object port PORT, for which the caller holds a reference. ! 178: *OBJECT is only guaranteed to be valid as long as the caller holds ! 179: the reference to PORT (unless the caller acquires its own reference ! 180: to it). If PORT is not a proxy memory object, return ! 181: KERN_INVALID_ARGUMENT. */ ! 182: kern_return_t ! 183: memory_object_proxy_lookup (ipc_port_t port, ipc_port_t *object, ! 184: vm_prot_t *max_protection) ! 185: { ! 186: memory_object_proxy_t proxy; ! 187: ! 188: proxy = memory_object_proxy_port_lookup (port); ! 189: if (!proxy) ! 190: return KERN_INVALID_ARGUMENT; ! 191: ! 192: *object = proxy->object; ! 193: *max_protection = proxy->max_protection; ! 194: ! 195: return KERN_SUCCESS; ! 196: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.