]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
39037602 | 2 | * Copyright (c) 2000-2016 Apple Inc. All rights reserved. |
1c79356b | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
0a7de745 | 5 | * |
2d21ac55 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
0a7de745 | 14 | * |
2d21ac55 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
0a7de745 | 17 | * |
2d21ac55 A |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
0a7de745 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
27 | */ |
28 | /* | |
29 | * @OSF_COPYRIGHT@ | |
30 | */ | |
0a7de745 | 31 | /* |
1c79356b A |
32 | * Mach Operating System |
33 | * Copyright (c) 1991,1990,1989 Carnegie Mellon University | |
34 | * All Rights Reserved. | |
0a7de745 | 35 | * |
1c79356b A |
36 | * Permission to use, copy, modify and distribute this software and its |
37 | * documentation is hereby granted, provided that both the copyright | |
38 | * notice and this permission notice appear in all copies of the | |
39 | * software, derivative works or modified versions, and any portions | |
40 | * thereof, and that both notices appear in supporting documentation. | |
0a7de745 | 41 | * |
1c79356b A |
42 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" |
43 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
44 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
0a7de745 | 45 | * |
1c79356b | 46 | * Carnegie Mellon requests users of this software to return to |
0a7de745 | 47 | * |
1c79356b A |
48 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
49 | * School of Computer Science | |
50 | * Carnegie Mellon University | |
51 | * Pittsburgh PA 15213-3890 | |
0a7de745 | 52 | * |
1c79356b A |
53 | * any improvements or extensions that they make and grant Carnegie Mellon |
54 | * the rights to redistribute these changes. | |
55 | */ | |
2d21ac55 A |
56 | /* |
57 | * NOTICE: This file was modified by McAfee Research in 2004 to introduce | |
58 | * support for mandatory and extensible security protections. This notice | |
59 | * is included in support of clause 2.2 (b) of the Apple Public License, | |
60 | * Version 2.0. | |
61 | * Copyright (c) 2005 SPARTA, Inc. | |
62 | */ | |
1c79356b A |
63 | /* |
64 | */ | |
65 | /* | |
66 | * File: kern/ipc_kobject.c | |
67 | * Author: Rich Draves | |
68 | * Date: 1989 | |
69 | * | |
70 | * Functions for letting a port represent a kernel object. | |
71 | */ | |
72 | ||
73 | #include <mach_debug.h> | |
74 | #include <mach_ipc_test.h> | |
9bccf70c | 75 | #include <mach/mig.h> |
1c79356b A |
76 | #include <mach/port.h> |
77 | #include <mach/kern_return.h> | |
78 | #include <mach/message.h> | |
79 | #include <mach/mig_errors.h> | |
80 | #include <mach/notify.h> | |
91447636 | 81 | #include <mach/ndr.h> |
b0d623f7 | 82 | #include <mach/vm_param.h> |
91447636 A |
83 | |
84 | #include <mach/mach_vm_server.h> | |
85 | #include <mach/mach_port_server.h> | |
86 | #include <mach/mach_host_server.h> | |
87 | #include <mach/host_priv_server.h> | |
88 | #include <mach/host_security_server.h> | |
89 | #include <mach/clock_server.h> | |
90 | #include <mach/clock_priv_server.h> | |
91447636 | 91 | #include <mach/lock_set_server.h> |
d9a64523 | 92 | #include <mach/memory_entry_server.h> |
91447636 A |
93 | #include <mach/memory_object_control_server.h> |
94 | #include <mach/memory_object_default_server.h> | |
91447636 A |
95 | #include <mach/processor_server.h> |
96 | #include <mach/processor_set_server.h> | |
91447636 | 97 | #include <mach/task_server.h> |
fe8ab488 A |
98 | #include <mach/mach_voucher_server.h> |
99 | #include <mach/mach_voucher_attr_control_server.h> | |
39037602 | 100 | #ifdef VM32_SUPPORT |
b0d623f7 A |
101 | #include <mach/vm32_map_server.h> |
102 | #endif | |
91447636 | 103 | #include <mach/thread_act_server.h> |
cb323159 | 104 | #include <mach/restartable_server.h> |
91447636 | 105 | |
d9a64523 A |
106 | #include <mach/exc_server.h> |
107 | #include <mach/mach_exc_server.h> | |
108 | ||
91447636 A |
109 | #include <device/device_types.h> |
110 | #include <device/device_server.h> | |
111 | ||
112 | #include <UserNotification/UNDReplyServer.h> | |
113 | ||
cb323159 A |
114 | #if CONFIG_ARCADE |
115 | #include <mach/arcade_register_server.h> | |
116 | #endif | |
117 | ||
0a7de745 | 118 | #if CONFIG_AUDIT |
b0d623f7 A |
119 | #include <kern/audit_sessionport.h> |
120 | #endif | |
121 | ||
91447636 A |
122 | #if MACH_MACHINE_ROUTINES |
123 | #include <machine/machine_routines.h> | |
0a7de745 A |
124 | #endif /* MACH_MACHINE_ROUTINES */ |
125 | #if XK_PROXY | |
91447636 | 126 | #include <uk_xkern/xk_uproxy_server.h> |
0a7de745 | 127 | #endif /* XK_PROXY */ |
9bccf70c | 128 | |
91447636 | 129 | #include <kern/ipc_tt.h> |
1c79356b | 130 | #include <kern/ipc_mig.h> |
d1ecb069 | 131 | #include <kern/ipc_misc.h> |
1c79356b | 132 | #include <kern/ipc_kobject.h> |
55e303ae | 133 | #include <kern/host_notify.h> |
1c79356b | 134 | #include <kern/mk_timer.h> |
55e303ae | 135 | #include <kern/misc_protos.h> |
cb323159 A |
136 | |
137 | #if CONFIG_ARCADE | |
138 | #include <kern/arcade.h> | |
139 | #endif /* CONFIG_ARCADE */ | |
140 | ||
1c79356b A |
141 | #include <ipc/ipc_kmsg.h> |
142 | #include <ipc/ipc_port.h> | |
fe8ab488 | 143 | #include <ipc/ipc_voucher.h> |
3e170ce0 | 144 | #include <kern/sync_sema.h> |
1c79356b | 145 | #include <kern/counters.h> |
5ba3f43e | 146 | #include <kern/work_interval.h> |
ea3f0419 | 147 | #include <kern/suid_cred.h> |
1c79356b | 148 | |
91447636 | 149 | #include <vm/vm_protos.h> |
1c79356b | 150 | |
2d21ac55 A |
151 | #include <security/mac_mach_internal.h> |
152 | ||
39236c6e A |
153 | extern char *proc_name_address(void *p); |
154 | extern int proc_pid(void *p); | |
155 | ||
1c79356b A |
156 | /* |
157 | * Routine: ipc_kobject_notify | |
158 | * Purpose: | |
159 | * Deliver notifications to kobjects that care about them. | |
160 | */ | |
161 | boolean_t | |
162 | ipc_kobject_notify( | |
0a7de745 A |
163 | mach_msg_header_t *request_header, |
164 | mach_msg_header_t *reply_header); | |
1c79356b | 165 | |
1c79356b | 166 | typedef struct { |
0a7de745 A |
167 | mach_msg_id_t num; |
168 | mig_routine_t routine; | |
1c79356b | 169 | int size; |
0a7de745 | 170 | #if MACH_COUNTERS |
1c79356b A |
171 | mach_counter_t callcount; |
172 | #endif | |
173 | } mig_hash_t; | |
174 | ||
fe8ab488 | 175 | #define MAX_MIG_ENTRIES 1031 |
1c79356b A |
176 | #define MIG_HASH(x) (x) |
177 | ||
178 | #ifndef max | |
0a7de745 | 179 | #define max(a, b) (((a) > (b)) ? (a) : (b)) |
1c79356b A |
180 | #endif /* max */ |
181 | ||
fe8ab488 A |
182 | static mig_hash_t mig_buckets[MAX_MIG_ENTRIES]; |
183 | static int mig_table_max_displ; | |
184 | static mach_msg_size_t mig_reply_size = sizeof(mig_reply_error_t); | |
1c79356b | 185 | |
ea3f0419 | 186 | static zone_t ipc_kobject_label_zone; |
1c79356b | 187 | |
91447636 | 188 | const struct mig_subsystem *mig_e[] = { |
0a7de745 A |
189 | (const struct mig_subsystem *)&mach_vm_subsystem, |
190 | (const struct mig_subsystem *)&mach_port_subsystem, | |
191 | (const struct mig_subsystem *)&mach_host_subsystem, | |
192 | (const struct mig_subsystem *)&host_priv_subsystem, | |
193 | (const struct mig_subsystem *)&host_security_subsystem, | |
194 | (const struct mig_subsystem *)&clock_subsystem, | |
195 | (const struct mig_subsystem *)&clock_priv_subsystem, | |
196 | (const struct mig_subsystem *)&processor_subsystem, | |
197 | (const struct mig_subsystem *)&processor_set_subsystem, | |
198 | (const struct mig_subsystem *)&is_iokit_subsystem, | |
91447636 | 199 | (const struct mig_subsystem *)&lock_set_subsystem, |
91447636 A |
200 | (const struct mig_subsystem *)&task_subsystem, |
201 | (const struct mig_subsystem *)&thread_act_subsystem, | |
39037602 | 202 | #ifdef VM32_SUPPORT |
b0d623f7 A |
203 | (const struct mig_subsystem *)&vm32_map_subsystem, |
204 | #endif | |
91447636 | 205 | (const struct mig_subsystem *)&UNDReply_subsystem, |
fe8ab488 A |
206 | (const struct mig_subsystem *)&mach_voucher_subsystem, |
207 | (const struct mig_subsystem *)&mach_voucher_attr_control_subsystem, | |
d9a64523 | 208 | (const struct mig_subsystem *)&memory_entry_subsystem, |
cb323159 | 209 | (const struct mig_subsystem *)&task_restartable_subsystem, |
1c79356b A |
210 | |
211 | #if XK_PROXY | |
0a7de745 | 212 | (const struct mig_subsystem *)&do_uproxy_xk_uproxy_subsystem, |
1c79356b A |
213 | #endif /* XK_PROXY */ |
214 | #if MACH_MACHINE_ROUTINES | |
0a7de745 | 215 | (const struct mig_subsystem *)&MACHINE_SUBSYSTEM, |
1c79356b A |
216 | #endif /* MACH_MACHINE_ROUTINES */ |
217 | #if MCMSG && iPSC860 | |
91447636 | 218 | (const struct mig_subsystem *)&mcmsg_info_subsystem, |
1c79356b | 219 | #endif /* MCMSG && iPSC860 */ |
0a7de745 A |
220 | (const struct mig_subsystem *)&catch_exc_subsystem, |
221 | (const struct mig_subsystem *)&catch_mach_exc_subsystem, | |
cb323159 A |
222 | #if CONFIG_ARCADE |
223 | (const struct mig_subsystem *)&arcade_register_subsystem, | |
224 | #endif | |
1c79356b A |
225 | }; |
226 | ||
ea3f0419 | 227 | static void |
1c79356b A |
228 | mig_init(void) |
229 | { | |
0a7de745 A |
230 | unsigned int i, n = sizeof(mig_e) / sizeof(const struct mig_subsystem *); |
231 | int howmany; | |
232 | mach_msg_id_t j, pos, nentry, range; | |
233 | ||
234 | for (i = 0; i < n; i++) { | |
235 | range = mig_e[i]->end - mig_e[i]->start; | |
236 | if (!mig_e[i]->start || range < 0) { | |
237 | panic("the msgh_ids in mig_e[] aren't valid!"); | |
238 | } | |
239 | ||
240 | for (j = 0; j < range; j++) { | |
241 | if (mig_e[i]->routine[j].stub_routine) { | |
242 | /* Only put real entries in the table */ | |
243 | nentry = j + mig_e[i]->start; | |
244 | for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1; | |
245 | mig_buckets[pos].num; | |
246 | pos++, pos = pos % MAX_MIG_ENTRIES, howmany++) { | |
247 | if (mig_buckets[pos].num == nentry) { | |
248 | printf("message id = %d\n", nentry); | |
249 | panic("multiple entries with the same msgh_id"); | |
250 | } | |
251 | if (howmany == MAX_MIG_ENTRIES) { | |
252 | panic("the mig dispatch table is too small"); | |
253 | } | |
254 | } | |
255 | ||
256 | mig_buckets[pos].num = nentry; | |
257 | mig_buckets[pos].routine = mig_e[i]->routine[j].stub_routine; | |
258 | if (mig_e[i]->routine[j].max_reply_msg) { | |
259 | mig_buckets[pos].size = mig_e[i]->routine[j].max_reply_msg; | |
260 | } else { | |
261 | mig_buckets[pos].size = mig_e[i]->maxsize; | |
262 | } | |
263 | ||
264 | mig_table_max_displ = max(howmany, mig_table_max_displ); | |
265 | } | |
266 | } | |
1c79356b | 267 | } |
0a7de745 | 268 | printf("mig_table_max_displ = %d\n", mig_table_max_displ); |
1c79356b A |
269 | } |
270 | ||
ea3f0419 A |
271 | /* |
272 | * Routine: ipc_kobject_init | |
273 | * Purpose: | |
274 | * Deliver notifications to kobjects that care about them. | |
275 | */ | |
276 | void | |
277 | ipc_kobject_init(void) | |
278 | { | |
279 | int label_max = CONFIG_TASK_MAX + CONFIG_THREAD_MAX + 1000 /* UEXT estimate */; | |
280 | ||
281 | mig_init(); | |
282 | ||
283 | ipc_kobject_label_zone = | |
284 | zinit(sizeof(struct ipc_kobject_label), | |
285 | label_max * sizeof(struct ipc_kobject_label), | |
286 | sizeof(struct ipc_kobject_label), | |
287 | "ipc kobject labels"); | |
288 | } | |
1c79356b A |
289 | |
290 | /* | |
291 | * Routine: ipc_kobject_server | |
292 | * Purpose: | |
293 | * Handle a message sent to the kernel. | |
294 | * Generates a reply message. | |
295 | * Version for Untyped IPC. | |
296 | * Conditions: | |
297 | * Nothing locked. | |
298 | */ | |
299 | ||
300 | ipc_kmsg_t | |
301 | ipc_kobject_server( | |
0a7de745 | 302 | ipc_kmsg_t request, |
39037602 | 303 | mach_msg_option_t __unused option) |
1c79356b A |
304 | { |
305 | mach_msg_size_t reply_size; | |
306 | ipc_kmsg_t reply; | |
307 | kern_return_t kr; | |
4bd07ac2 | 308 | ipc_port_t replyp = IPC_PORT_NULL; |
1c79356b | 309 | mach_msg_format_0_trailer_t *trailer; |
39037602 A |
310 | mig_hash_t *ptr; |
311 | task_t task = TASK_NULL; | |
312 | uint32_t exec_token; | |
313 | boolean_t exec_token_changed = FALSE; | |
d9a64523 | 314 | int request_msgh_id = request->ikm_header->msgh_id; |
cb323159 A |
315 | natural_t ikot; |
316 | ipc_port_t port; | |
91447636 | 317 | |
cb323159 A |
318 | reply = NULL; |
319 | port = request->ikm_header->msgh_remote_port; | |
320 | if (IP_VALID(port)) { | |
321 | ikot = ip_kotype(port); | |
322 | } else { | |
323 | ikot = IKOT_UNKNOWN; | |
324 | } | |
325 | if (ikot == IKOT_UEXT_OBJECT) { | |
326 | kr = uext_server(request, &reply); | |
327 | if ((MIG_NO_REPLY == kr) || (KERN_SUCCESS == kr)) { | |
328 | ipc_kmsg_trace_send(request, option); | |
329 | goto msgdone; | |
330 | } | |
331 | } | |
1c79356b | 332 | /* |
cb323159 | 333 | * Find corresponding mig_hash entry if any |
91447636 | 334 | */ |
1c79356b | 335 | { |
0a7de745 A |
336 | unsigned int i = (unsigned int)MIG_HASH(request_msgh_id); |
337 | int max_iter = mig_table_max_displ; | |
338 | ||
339 | do { | |
340 | ptr = &mig_buckets[i++ % MAX_MIG_ENTRIES]; | |
341 | } while (request_msgh_id != ptr->num && ptr->num && --max_iter); | |
342 | ||
343 | if (!ptr->routine || request_msgh_id != ptr->num) { | |
344 | ptr = (mig_hash_t *)0; | |
345 | reply_size = mig_reply_size; | |
346 | } else { | |
347 | reply_size = ptr->size; | |
cb323159 | 348 | #if MACH_COUNTERS |
0a7de745 | 349 | ptr->callcount++; |
1c79356b | 350 | #endif |
0a7de745 | 351 | } |
1c79356b A |
352 | } |
353 | ||
354 | /* round up for trailer size */ | |
0a7de745 | 355 | reply_size += MAX_TRAILER_SIZE; |
1c79356b A |
356 | reply = ipc_kmsg_alloc(reply_size); |
357 | ||
358 | if (reply == IKM_NULL) { | |
359 | printf("ipc_kobject_server: dropping request\n"); | |
39037602 | 360 | ipc_kmsg_trace_send(request, option); |
1c79356b A |
361 | ipc_kmsg_destroy(request); |
362 | return IKM_NULL; | |
363 | } | |
364 | ||
365 | /* | |
366 | * Initialize reply message. | |
367 | */ | |
368 | { | |
0a7de745 A |
369 | #define InP ((mach_msg_header_t *) request->ikm_header) |
370 | #define OutP ((mig_reply_error_t *) reply->ikm_header) | |
371 | ||
372 | /* | |
373 | * MIG should really assure no data leakage - | |
374 | * but until it does, pessimistically zero the | |
375 | * whole reply buffer. | |
376 | */ | |
377 | bzero((void *)OutP, reply_size); | |
378 | ||
379 | OutP->NDR = NDR_record; | |
380 | OutP->Head.msgh_size = sizeof(mig_reply_error_t); | |
381 | ||
382 | OutP->Head.msgh_bits = | |
383 | MACH_MSGH_BITS_SET(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0, 0, 0); | |
384 | OutP->Head.msgh_remote_port = InP->msgh_local_port; | |
385 | OutP->Head.msgh_local_port = MACH_PORT_NULL; | |
386 | OutP->Head.msgh_voucher_port = MACH_PORT_NULL; | |
387 | OutP->Head.msgh_id = InP->msgh_id + 100; | |
388 | ||
389 | #undef InP | |
390 | #undef OutP | |
1c79356b A |
391 | } |
392 | ||
393 | /* | |
394 | * Find the routine to call, and call it | |
395 | * to perform the kernel function | |
396 | */ | |
39037602 | 397 | ipc_kmsg_trace_send(request, option); |
1c79356b | 398 | { |
0a7de745 A |
399 | if (ptr) { |
400 | /* | |
401 | * Check if the port is a task port, if its a task port then | |
402 | * snapshot the task exec token before the mig routine call. | |
403 | */ | |
cb323159 | 404 | if (ikot == IKOT_TASK) { |
0a7de745 A |
405 | task = convert_port_to_task_with_exec_token(port, &exec_token); |
406 | } | |
39037602 | 407 | |
0a7de745 | 408 | (*ptr->routine)(request->ikm_header, reply->ikm_header); |
39037602 | 409 | |
0a7de745 A |
410 | /* Check if the exec token changed during the mig routine */ |
411 | if (task != TASK_NULL) { | |
412 | if (exec_token != task->exec_token) { | |
413 | exec_token_changed = TRUE; | |
414 | } | |
415 | task_deallocate(task); | |
39037602 | 416 | } |
39037602 | 417 | |
0a7de745 A |
418 | kernel_task->messages_received++; |
419 | } else { | |
420 | if (!ipc_kobject_notify(request->ikm_header, reply->ikm_header)) { | |
4bd07ac2 | 421 | #if DEVELOPMENT || DEBUG |
0a7de745 A |
422 | printf("ipc_kobject_server: bogus kernel message, id=%d\n", |
423 | request->ikm_header->msgh_id); | |
424 | #endif /* DEVELOPMENT || DEBUG */ | |
425 | _MIG_MSGID_INVALID(request->ikm_header->msgh_id); | |
426 | ||
427 | ((mig_reply_error_t *) reply->ikm_header)->RetCode | |
428 | = MIG_BAD_ID; | |
429 | } else { | |
430 | kernel_task->messages_received++; | |
431 | } | |
1c79356b | 432 | } |
0a7de745 | 433 | kernel_task->messages_sent++; |
1c79356b A |
434 | } |
435 | ||
cb323159 A |
436 | if (!(reply->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) && |
437 | ((mig_reply_error_t *) reply->ikm_header)->RetCode != KERN_SUCCESS) { | |
438 | kr = ((mig_reply_error_t *) reply->ikm_header)->RetCode; | |
439 | } else { | |
440 | kr = KERN_SUCCESS; | |
441 | } | |
442 | ||
443 | msgdone: | |
1c79356b A |
444 | /* |
445 | * Destroy destination. The following code differs from | |
446 | * ipc_object_destroy in that we release the send-once | |
447 | * right instead of generating a send-once notification | |
cb323159 | 448 | * (which would bring us here again, creating a loop). |
1c79356b A |
449 | * It also differs in that we only expect send or |
450 | * send-once rights, never receive rights. | |
451 | * | |
452 | * We set msgh_remote_port to IP_NULL so that the kmsg | |
453 | * destroy routines don't try to destroy the port twice. | |
454 | */ | |
91447636 | 455 | switch (MACH_MSGH_BITS_REMOTE(request->ikm_header->msgh_bits)) { |
0a7de745 | 456 | case MACH_MSG_TYPE_PORT_SEND: |
cb323159 A |
457 | ipc_port_release_send(request->ikm_header->msgh_remote_port); |
458 | request->ikm_header->msgh_remote_port = IP_NULL; | |
0a7de745 A |
459 | break; |
460 | ||
461 | case MACH_MSG_TYPE_PORT_SEND_ONCE: | |
cb323159 A |
462 | ipc_port_release_sonce(request->ikm_header->msgh_remote_port); |
463 | request->ikm_header->msgh_remote_port = IP_NULL; | |
0a7de745 A |
464 | break; |
465 | ||
466 | default: | |
467 | panic("ipc_kobject_server: strange destination rights"); | |
1c79356b | 468 | } |
1c79356b | 469 | |
fe8ab488 A |
470 | /* |
471 | * Destroy voucher. The kernel MIG servers never take ownership | |
472 | * of vouchers sent in messages. Swallow any such rights here. | |
473 | */ | |
474 | if (IP_VALID(request->ikm_voucher)) { | |
475 | assert(MACH_MSG_TYPE_PORT_SEND == | |
0a7de745 | 476 | MACH_MSGH_BITS_VOUCHER(request->ikm_header->msgh_bits)); |
fe8ab488 A |
477 | ipc_port_release_send(request->ikm_voucher); |
478 | request->ikm_voucher = IP_NULL; | |
479 | } | |
480 | ||
1c79356b A |
481 | if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) { |
482 | /* | |
483 | * The server function is responsible for the contents | |
484 | * of the message. The reply port right is moved | |
485 | * to the reply message, and we have deallocated | |
486 | * the destination port right, so we just need | |
487 | * to free the kmsg. | |
488 | */ | |
489 | ipc_kmsg_free(request); | |
1c79356b A |
490 | } else { |
491 | /* | |
492 | * The message contents of the request are intact. | |
493 | * Destroy everthing except the reply port right, | |
494 | * which is needed in the reply message. | |
495 | */ | |
91447636 | 496 | request->ikm_header->msgh_local_port = MACH_PORT_NULL; |
1c79356b A |
497 | ipc_kmsg_destroy(request); |
498 | } | |
499 | ||
500 | if (kr == MIG_NO_REPLY) { | |
501 | /* | |
502 | * The server function will send a reply message | |
503 | * using the reply port right, which it has saved. | |
504 | */ | |
505 | ||
cb323159 A |
506 | if (reply) { |
507 | ipc_kmsg_free(reply); | |
508 | } | |
1c79356b | 509 | return IKM_NULL; |
cb323159 A |
510 | } |
511 | ||
512 | if (reply) { | |
513 | replyp = reply->ikm_header->msgh_remote_port; | |
514 | } | |
515 | ||
516 | if (!IP_VALID(replyp)) { | |
1c79356b A |
517 | /* |
518 | * Can't queue the reply message if the destination | |
519 | * (the reply port) isn't valid. | |
520 | */ | |
521 | ||
522 | ipc_kmsg_destroy(reply); | |
523 | ||
4bd07ac2 A |
524 | return IKM_NULL; |
525 | } else if (replyp->ip_receiver == ipc_space_kernel) { | |
526 | /* | |
527 | * Don't send replies to kobject kernel ports | |
528 | */ | |
529 | #if DEVELOPMENT || DEBUG | |
530 | printf("%s: refusing to send reply to kobject %d port (id:%d)\n", | |
0a7de745 A |
531 | __func__, ip_kotype(replyp), request_msgh_id); |
532 | #endif /* DEVELOPMENT || DEBUG */ | |
4bd07ac2 | 533 | ipc_kmsg_destroy(reply); |
1c79356b A |
534 | return IKM_NULL; |
535 | } | |
536 | ||
39037602 A |
537 | /* Fail the MIG call if the task exec token changed during the call */ |
538 | if (kr == KERN_SUCCESS && exec_token_changed) { | |
539 | /* | |
540 | * Create a new reply msg with error and destroy the old reply msg. | |
541 | */ | |
542 | ipc_kmsg_t new_reply = ipc_kmsg_alloc(reply_size); | |
543 | ||
544 | if (new_reply == IKM_NULL) { | |
545 | printf("ipc_kobject_server: dropping request\n"); | |
546 | ipc_kmsg_destroy(reply); | |
547 | return IKM_NULL; | |
548 | } | |
549 | /* | |
550 | * Initialize the new reply message. | |
551 | */ | |
552 | { | |
0a7de745 A |
553 | #define OutP_new ((mig_reply_error_t *) new_reply->ikm_header) |
554 | #define OutP_old ((mig_reply_error_t *) reply->ikm_header) | |
39037602 | 555 | |
0a7de745 | 556 | bzero((void *)OutP_new, reply_size); |
39037602 | 557 | |
0a7de745 A |
558 | OutP_new->NDR = OutP_old->NDR; |
559 | OutP_new->Head.msgh_size = sizeof(mig_reply_error_t); | |
560 | OutP_new->Head.msgh_bits = OutP_old->Head.msgh_bits & ~MACH_MSGH_BITS_COMPLEX; | |
561 | OutP_new->Head.msgh_remote_port = OutP_old->Head.msgh_remote_port; | |
562 | OutP_new->Head.msgh_local_port = MACH_PORT_NULL; | |
563 | OutP_new->Head.msgh_voucher_port = MACH_PORT_NULL; | |
564 | OutP_new->Head.msgh_id = OutP_old->Head.msgh_id; | |
39037602 | 565 | |
0a7de745 A |
566 | /* Set the error as KERN_INVALID_TASK */ |
567 | OutP_new->RetCode = KERN_INVALID_TASK; | |
39037602 | 568 | |
0a7de745 | 569 | #undef OutP_new |
39037602 A |
570 | #undef OutP_old |
571 | } | |
572 | ||
573 | /* | |
574 | * Destroy everything in reply except the reply port right, | |
575 | * which is needed in the new reply message. | |
576 | */ | |
577 | reply->ikm_header->msgh_remote_port = MACH_PORT_NULL; | |
578 | ipc_kmsg_destroy(reply); | |
579 | ||
580 | reply = new_reply; | |
581 | } | |
582 | ||
0a7de745 A |
583 | trailer = (mach_msg_format_0_trailer_t *) |
584 | ((vm_offset_t)reply->ikm_header + (int)reply->ikm_header->msgh_size); | |
91447636 | 585 | |
0a7de745 A |
586 | trailer->msgh_sender = KERNEL_SECURITY_TOKEN; |
587 | trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0; | |
588 | trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE; | |
1c79356b | 589 | |
1c79356b A |
590 | return reply; |
591 | } | |
592 | ||
593 | /* | |
594 | * Routine: ipc_kobject_set | |
595 | * Purpose: | |
596 | * Make a port represent a kernel object of the given type. | |
597 | * The caller is responsible for handling refs for the | |
598 | * kernel object, if necessary. | |
599 | * Conditions: | |
600 | * Nothing locked. The port must be active if setting | |
601 | * a kobject linkage. Clearing a linkage is OK on an | |
602 | * inactive port. | |
603 | */ | |
604 | void | |
605 | ipc_kobject_set( | |
0a7de745 A |
606 | ipc_port_t port, |
607 | ipc_kobject_t kobject, | |
608 | ipc_kobject_type_t type) | |
1c79356b A |
609 | { |
610 | ip_lock(port); | |
611 | ipc_kobject_set_atomically(port, kobject, type); | |
612 | ip_unlock(port); | |
613 | } | |
614 | ||
615 | void | |
616 | ipc_kobject_set_atomically( | |
0a7de745 A |
617 | ipc_port_t port, |
618 | ipc_kobject_t kobject, | |
619 | ipc_kobject_type_t type) | |
1c79356b A |
620 | { |
621 | assert(type == IKOT_NONE || ip_active(port)); | |
0a7de745 | 622 | #if MACH_ASSERT |
cb323159 | 623 | port->ip_spares[2] = (port->ip_object.io_bits & IO_BITS_KOTYPE); |
0a7de745 | 624 | #endif /* MACH_ASSERT */ |
cb323159 | 625 | port->ip_object.io_bits = (port->ip_object.io_bits & ~IO_BITS_KOTYPE) | type; |
ea3f0419 A |
626 | if (ip_is_kolabeled(port)) { |
627 | ipc_kobject_label_t labelp = port->ip_kolabel; | |
628 | labelp->ikol_kobject = kobject; | |
629 | } else { | |
630 | port->ip_kobject = kobject; | |
631 | } | |
cb323159 A |
632 | if (type != IKOT_NONE) { |
633 | /* Once set, this bit can never be unset */ | |
634 | port->ip_object.io_bits |= IO_BITS_KOBJECT; | |
635 | } | |
636 | } | |
637 | ||
ea3f0419 A |
638 | /* |
639 | * Routine: ipc_kobject_init_port | |
640 | * Purpose: | |
641 | * Initialize a kobject port with the given types and options. | |
642 | * | |
643 | * This function never fails. | |
644 | */ | |
645 | static inline void | |
646 | ipc_kobject_init_port( | |
647 | ipc_port_t port, | |
648 | ipc_kobject_t kobject, | |
649 | ipc_kobject_type_t type, | |
650 | ipc_kobject_alloc_options_t options) | |
651 | { | |
652 | ipc_kobject_set_atomically(port, kobject, type); | |
653 | ||
654 | if (options & IPC_KOBJECT_ALLOC_MAKE_SEND) { | |
655 | ipc_port_make_send_locked(port); | |
656 | } | |
657 | if (options & IPC_KOBJECT_ALLOC_NSREQUEST) { | |
658 | ipc_port_make_sonce_locked(port); | |
659 | port->ip_nsrequest = port; | |
660 | } | |
661 | if (options & IPC_KOBJECT_ALLOC_NO_GRANT) { | |
662 | port->ip_no_grant = 1; | |
663 | } | |
664 | if (options & IPC_KOBJECT_ALLOC_IMMOVABLE_SEND) { | |
665 | port->ip_immovable_send = 1; | |
666 | } | |
667 | } | |
668 | ||
cb323159 A |
669 | /* |
670 | * Routine: ipc_kobject_alloc_port | |
671 | * Purpose: | |
672 | * Allocate a kobject port in the kernel space of the specified type. | |
673 | * | |
674 | * This function never fails. | |
675 | * | |
676 | * Conditions: | |
677 | * No locks held (memory is allocated) | |
678 | */ | |
679 | ipc_port_t | |
680 | ipc_kobject_alloc_port( | |
681 | ipc_kobject_t kobject, | |
682 | ipc_kobject_type_t type, | |
683 | ipc_kobject_alloc_options_t options) | |
684 | { | |
ea3f0419 | 685 | ipc_port_t port = ipc_port_alloc_kernel(); |
cb323159 A |
686 | |
687 | if (port == IP_NULL) { | |
688 | panic("ipc_kobject_alloc_port(): failed to allocate port"); | |
689 | } | |
690 | ||
ea3f0419 A |
691 | ipc_kobject_init_port(port, kobject, type, options); |
692 | return port; | |
693 | } | |
cb323159 | 694 | |
ea3f0419 A |
695 | /* |
696 | * Routine: ipc_kobject_alloc_labeled_port | |
697 | * Purpose: | |
698 | * Allocate a kobject port and associated mandatory access label | |
699 | * in the kernel space of the specified type. | |
700 | * | |
701 | * This function never fails. | |
702 | * | |
703 | * Conditions: | |
704 | * No locks held (memory is allocated) | |
705 | */ | |
c6bf4f31 | 706 | |
ea3f0419 A |
707 | ipc_port_t |
708 | ipc_kobject_alloc_labeled_port( | |
709 | ipc_kobject_t kobject, | |
710 | ipc_kobject_type_t type, | |
711 | ipc_label_t label, | |
712 | ipc_kobject_alloc_options_t options) | |
713 | { | |
714 | ipc_port_t port; | |
715 | ipc_kobject_label_t labelp; | |
716 | ||
717 | port = ipc_port_alloc_kernel(); | |
718 | if (port == IP_NULL) { | |
719 | panic("ipc_kobject_alloc_port(): failed to allocate port"); | |
cb323159 | 720 | } |
ea3f0419 A |
721 | |
722 | labelp = (ipc_kobject_label_t)zalloc(ipc_kobject_label_zone); | |
723 | if (labelp == NULL) { | |
724 | panic("ipc_kobject_alloc_labeled_port(): failed to allocate label"); | |
c6bf4f31 | 725 | } |
ea3f0419 A |
726 | labelp->ikol_label = label; |
727 | port->ip_kolabel = labelp; | |
728 | port->ip_object.io_bits |= IO_BITS_KOLABEL; | |
cb323159 | 729 | |
ea3f0419 | 730 | ipc_kobject_init_port(port, kobject, type, options); |
cb323159 A |
731 | return port; |
732 | } | |
733 | ||
734 | /* | |
735 | * Routine: ipc_kobject_make_send_lazy_alloc_port | |
736 | * Purpose: | |
737 | * Make a send once for a kobject port. | |
738 | * | |
739 | * A location owning this port is passed in port_store. | |
740 | * If no port exists, a port is made lazily. | |
741 | * | |
742 | * A send right is made for the port, and if this is the first one | |
743 | * (possibly not for the first time), then the no-more-senders | |
744 | * notification is rearmed. | |
745 | * | |
746 | * When a notification is armed, the kobject must donate | |
747 | * one of its references to the port. It is expected | |
748 | * the no-more-senders notification will consume this reference. | |
749 | * | |
750 | * Returns: | |
751 | * TRUE if a notification was armed | |
752 | * FALSE else | |
753 | * | |
754 | * Conditions: | |
755 | * Nothing is locked, memory can be allocated. | |
756 | * The caller must be able to donate a kobject reference to the port. | |
757 | */ | |
758 | boolean_t | |
759 | ipc_kobject_make_send_lazy_alloc_port( | |
760 | ipc_port_t *port_store, | |
761 | ipc_kobject_t kobject, | |
762 | ipc_kobject_type_t type) | |
763 | { | |
764 | ipc_port_t port, previous; | |
765 | boolean_t rc = FALSE; | |
766 | ||
767 | port = os_atomic_load(port_store, dependency); | |
768 | ||
769 | if (!IP_VALID(port)) { | |
770 | port = ipc_kobject_alloc_port(kobject, type, | |
771 | IPC_KOBJECT_ALLOC_MAKE_SEND | IPC_KOBJECT_ALLOC_NSREQUEST); | |
772 | if (os_atomic_cmpxchgv(port_store, IP_NULL, port, &previous, release)) { | |
773 | return TRUE; | |
774 | } | |
775 | ||
776 | // undo what ipc_kobject_alloc_port() did above | |
777 | port->ip_nsrequest = IP_NULL; | |
778 | port->ip_mscount = 0; | |
779 | port->ip_sorights = 0; | |
780 | port->ip_srights = 0; | |
781 | ip_release(port); | |
782 | ip_release(port); | |
783 | ipc_port_dealloc_kernel(port); | |
784 | ||
785 | port = previous; | |
786 | } | |
787 | ||
788 | ip_lock(port); | |
789 | ipc_port_make_send_locked(port); | |
790 | if (port->ip_srights == 1) { | |
791 | ipc_port_make_sonce_locked(port); | |
792 | assert(port->ip_nsrequest == IP_NULL); | |
793 | port->ip_nsrequest = port; | |
794 | rc = TRUE; | |
795 | } | |
796 | ip_unlock(port); | |
797 | ||
798 | return rc; | |
1c79356b A |
799 | } |
800 | ||
ea3f0419 A |
801 | /* |
802 | * Routine: ipc_kobject_make_send_lazy_alloc_labeled_port | |
803 | * Purpose: | |
804 | * Make a send once for a kobject port. | |
805 | * | |
806 | * A location owning this port is passed in port_store. | |
807 | * If no port exists, a port is made lazily. | |
808 | * | |
809 | * A send right is made for the port, and if this is the first one | |
810 | * (possibly not for the first time), then the no-more-senders | |
811 | * notification is rearmed. | |
812 | * | |
813 | * When a notification is armed, the kobject must donate | |
814 | * one of its references to the port. It is expected | |
815 | * the no-more-senders notification will consume this reference. | |
816 | * | |
817 | * Returns: | |
818 | * TRUE if a notification was armed | |
819 | * FALSE else | |
820 | * | |
821 | * Conditions: | |
822 | * Nothing is locked, memory can be allocated. | |
823 | * The caller must be able to donate a kobject reference to the port. | |
824 | */ | |
825 | boolean_t | |
826 | ipc_kobject_make_send_lazy_alloc_labeled_port( | |
827 | ipc_port_t *port_store, | |
828 | ipc_kobject_t kobject, | |
829 | ipc_kobject_type_t type, | |
830 | ipc_label_t label) | |
831 | { | |
832 | ipc_port_t port, previous; | |
833 | boolean_t rc = FALSE; | |
834 | ||
835 | port = os_atomic_load(port_store, dependency); | |
836 | ||
837 | if (!IP_VALID(port)) { | |
838 | port = ipc_kobject_alloc_labeled_port(kobject, type, label, | |
839 | IPC_KOBJECT_ALLOC_MAKE_SEND | IPC_KOBJECT_ALLOC_NSREQUEST); | |
840 | if (os_atomic_cmpxchgv(port_store, IP_NULL, port, &previous, release)) { | |
841 | return TRUE; | |
842 | } | |
843 | ||
844 | // undo what ipc_kobject_alloc_port() did above | |
845 | port->ip_nsrequest = IP_NULL; | |
846 | port->ip_mscount = 0; | |
847 | port->ip_sorights = 0; | |
848 | port->ip_srights = 0; | |
849 | ip_release(port); | |
850 | ip_release(port); | |
851 | zfree(ipc_kobject_label_zone, port->ip_kolabel); | |
852 | port->ip_object.io_bits &= ~IO_BITS_KOLABEL; | |
853 | port->ip_kolabel = NULL; | |
854 | ipc_port_dealloc_kernel(port); | |
855 | ||
856 | port = previous; | |
857 | assert(ip_is_kolabeled(port)); | |
858 | } | |
859 | ||
860 | ip_lock(port); | |
861 | ipc_port_make_send_locked(port); | |
862 | if (port->ip_srights == 1) { | |
863 | ipc_port_make_sonce_locked(port); | |
864 | assert(port->ip_nsrequest == IP_NULL); | |
865 | port->ip_nsrequest = port; | |
866 | rc = TRUE; | |
867 | } | |
868 | ip_unlock(port); | |
869 | ||
870 | return rc; | |
871 | } | |
872 | ||
873 | ||
1c79356b A |
874 | /* |
875 | * Routine: ipc_kobject_destroy | |
876 | * Purpose: | |
877 | * Release any kernel object resources associated | |
878 | * with the port, which is being destroyed. | |
879 | * | |
ea3f0419 A |
880 | * This path to free object resources should only be |
881 | * needed when resources are associated with a user's port. | |
882 | * In the normal case, when the kernel is the receiver, | |
883 | * the code calling ipc_port_dealloc_kernel should clean | |
884 | * up the object resources. | |
885 | * | |
886 | * Cleans up any kobject label that might be present. | |
1c79356b A |
887 | * Conditions: |
888 | * The port is not locked, but it is dead. | |
889 | */ | |
890 | ||
891 | void | |
892 | ipc_kobject_destroy( | |
0a7de745 | 893 | ipc_port_t port) |
1c79356b A |
894 | { |
895 | switch (ip_kotype(port)) { | |
1c79356b A |
896 | case IKOT_TIMER: |
897 | mk_timer_port_destroy(port); | |
898 | break; | |
899 | ||
900 | case IKOT_NAMED_ENTRY: | |
901 | mach_destroy_memory_entry(port); | |
902 | break; | |
903 | ||
55e303ae A |
904 | case IKOT_HOST_NOTIFY: |
905 | host_notify_port_destroy(port); | |
906 | break; | |
907 | ||
ea3f0419 A |
908 | case IKOT_SUID_CRED: |
909 | suid_cred_destroy(port); | |
910 | break; | |
911 | ||
55e303ae | 912 | default: |
1c79356b A |
913 | break; |
914 | } | |
ea3f0419 A |
915 | |
916 | if (ip_is_kolabeled(port)) { | |
917 | ipc_kobject_label_t labelp = port->ip_kolabel; | |
918 | ||
919 | assert(labelp != NULL); | |
920 | assert(ip_is_kobject(port)); | |
921 | port->ip_kolabel = NULL; | |
922 | port->ip_object.io_bits &= ~IO_BITS_KOLABEL; | |
923 | zfree(ipc_kobject_label_zone, labelp); | |
924 | } | |
1c79356b A |
925 | } |
926 | ||
ea3f0419 A |
927 | /* |
928 | * Routine: ipc_kobject_label_check | |
929 | * Purpose: | |
930 | * Check to see if the space is allowed to possess a | |
931 | * right for the given port. In order to qualify, the | |
932 | * space label must contain all the privileges listed | |
933 | * in the port/kobject label. | |
934 | * | |
935 | * Conditions: | |
936 | * Space is write locked and active. | |
937 | * Port is locked and active. | |
938 | */ | |
939 | boolean_t | |
940 | ipc_kobject_label_check( | |
941 | ipc_space_t space, | |
942 | ipc_port_t port, | |
943 | __unused mach_msg_type_name_t msgt_name) | |
944 | { | |
945 | ipc_kobject_label_t labelp; | |
946 | ||
947 | assert(is_active(space)); | |
948 | assert(ip_active(port)); | |
949 | ||
950 | /* Unlabled ports/kobjects are always allowed */ | |
951 | if (!ip_is_kolabeled(port)) { | |
952 | return TRUE; | |
953 | } | |
954 | ||
955 | labelp = port->ip_kolabel; | |
956 | return (labelp->ikol_label & space->is_label) == labelp->ikol_label; | |
957 | } | |
1c79356b | 958 | |
1c79356b A |
959 | boolean_t |
960 | ipc_kobject_notify( | |
961 | mach_msg_header_t *request_header, | |
962 | mach_msg_header_t *reply_header) | |
963 | { | |
4bd07ac2 | 964 | mach_msg_max_trailer_t * trailer; |
cb323159 | 965 | ipc_port_t port = request_header->msgh_remote_port; |
1c79356b A |
966 | |
967 | ((mig_reply_error_t *) reply_header)->RetCode = MIG_NO_REPLY; | |
4bd07ac2 A |
968 | |
969 | trailer = (mach_msg_max_trailer_t *) | |
0a7de745 | 970 | ((vm_offset_t)request_header + request_header->msgh_size); |
5ba3f43e A |
971 | |
972 | /* | |
973 | * The kobject notification is privileged and can change the | |
974 | * refcount on kernel-internal objects - make sure | |
975 | * that the message wasn't faked! | |
976 | */ | |
4bd07ac2 | 977 | if (0 != bcmp(&trailer->msgh_audit, &KERNEL_AUDIT_TOKEN, |
0a7de745 | 978 | sizeof(trailer->msgh_audit))) { |
4bd07ac2 A |
979 | return FALSE; |
980 | } | |
981 | if (0 != bcmp(&trailer->msgh_sender, &KERNEL_SECURITY_TOKEN, | |
0a7de745 | 982 | sizeof(trailer->msgh_sender))) { |
4bd07ac2 A |
983 | return FALSE; |
984 | } | |
985 | ||
1c79356b | 986 | switch (request_header->msgh_id) { |
0a7de745 A |
987 | case MACH_NOTIFY_NO_SENDERS: |
988 | switch (ip_kotype(port)) { | |
989 | case IKOT_VOUCHER: | |
990 | ipc_voucher_notify(request_header); | |
991 | return TRUE; | |
992 | ||
993 | case IKOT_VOUCHER_ATTR_CONTROL: | |
994 | ipc_voucher_attr_control_notify(request_header); | |
995 | return TRUE; | |
996 | ||
997 | case IKOT_SEMAPHORE: | |
998 | semaphore_notify(request_header); | |
999 | return TRUE; | |
1000 | ||
1001 | case IKOT_TASK: | |
1002 | task_port_notify(request_header); | |
1003 | return TRUE; | |
1004 | ||
1005 | case IKOT_NAMED_ENTRY: | |
1006 | ip_lock(port); | |
1007 | ||
1008 | /* | |
1009 | * Bring the sequence number and mscount in | |
1010 | * line with ipc_port_destroy assertion. | |
1011 | */ | |
1012 | port->ip_mscount = 0; | |
1013 | port->ip_messages.imq_seqno = 0; | |
1014 | ipc_port_destroy(port); /* releases lock */ | |
1015 | return TRUE; | |
1016 | ||
1017 | case IKOT_UPL: | |
1018 | upl_no_senders( | |
1019 | request_header->msgh_remote_port, | |
1020 | (mach_port_mscount_t) | |
1021 | ((mach_no_senders_notification_t *) | |
1022 | request_header)->not_count); | |
1023 | reply_header->msgh_remote_port = MACH_PORT_NULL; | |
1024 | return TRUE; | |
1025 | ||
1026 | #if CONFIG_AUDIT | |
1027 | case IKOT_AU_SESSIONPORT: | |
1028 | audit_session_nosenders(request_header); | |
1029 | return TRUE; | |
b0d623f7 | 1030 | #endif |
0a7de745 A |
1031 | case IKOT_FILEPORT: |
1032 | fileport_notify(request_header); | |
1033 | return TRUE; | |
5ba3f43e | 1034 | |
0a7de745 A |
1035 | case IKOT_WORK_INTERVAL: |
1036 | work_interval_port_notify(request_header); | |
1037 | return TRUE; | |
ea3f0419 A |
1038 | |
1039 | case IKOT_SUID_CRED: | |
1040 | suid_cred_notify(request_header); | |
1041 | return TRUE; | |
0a7de745 | 1042 | } |
ea3f0419 | 1043 | |
5ba3f43e | 1044 | break; |
0b4e3aa0 | 1045 | |
0a7de745 A |
1046 | case MACH_NOTIFY_PORT_DELETED: |
1047 | case MACH_NOTIFY_PORT_DESTROYED: | |
1048 | case MACH_NOTIFY_SEND_ONCE: | |
1049 | case MACH_NOTIFY_DEAD_NAME: | |
1c79356b A |
1050 | break; |
1051 | ||
0a7de745 | 1052 | default: |
1c79356b A |
1053 | return FALSE; |
1054 | } | |
1055 | switch (ip_kotype(port)) { | |
1c79356b | 1056 | #ifdef IOKIT |
0a7de745 A |
1057 | case IKOT_IOKIT_OBJECT: |
1058 | case IKOT_IOKIT_CONNECT: | |
1059 | case IKOT_IOKIT_IDENT: | |
cb323159 | 1060 | case IKOT_UEXT_OBJECT: |
0a7de745 A |
1061 | { |
1062 | return iokit_notify(request_header); | |
1063 | } | |
1c79356b | 1064 | #endif |
0a7de745 A |
1065 | case IKOT_TASK_RESUME: |
1066 | { | |
1067 | return task_suspension_notify(request_header); | |
1068 | } | |
39236c6e | 1069 | |
0a7de745 A |
1070 | default: |
1071 | return FALSE; | |
1072 | } | |
1c79356b | 1073 | } |