|
|
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.