|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: * File: kern/ipc_kobject.c ! 52: * Author: Rich Draves ! 53: * Date: 1989 ! 54: * ! 55: * Functions for letting a port represent a kernel object. ! 56: */ ! 57: ! 58: #import <mach/features.h> ! 59: ! 60: #include <mach/port.h> ! 61: #include <mach/kern_return.h> ! 62: #include <mach/message.h> ! 63: #include <mach/mig_errors.h> ! 64: #include <mach/notify.h> ! 65: #include <kern/ipc_kobject.h> ! 66: #include <ipc/ipc_object.h> ! 67: #include <ipc/ipc_kmsg.h> ! 68: #include <ipc/ipc_port.h> ! 69: #include <ipc/ipc_thread.h> ! 70: ! 71: #if MACH_MACHINE_ROUTINES ! 72: #include <machine/machine_routines.h> ! 73: #endif ! 74: ! 75: /* Forward Declarations */ ! 76: ! 77: boolean_t ! 78: ipc_kobject_notify( ! 79: mach_msg_header_t *request_header, ! 80: mach_msg_header_t *reply_header); ! 81: ! 82: #include <mach/ndr.h> ! 83: ! 84: /* ! 85: * Routine: ipc_kobject_server ! 86: * Purpose: ! 87: * Handle a message sent to the kernel. ! 88: * Generates a reply message. ! 89: * Conditions: ! 90: * Nothing locked. ! 91: */ ! 92: ! 93: ipc_kmsg_t ! 94: ipc_kobject_server( ! 95: ipc_kmsg_t request) ! 96: { ! 97: mach_msg_size_t reply_size; ! 98: ipc_kmsg_t reply; ! 99: kern_return_t kr; ! 100: mig_routine_t routine; ! 101: ipc_port_t *destp; ! 102: ! 103: if (request->ikm_header.msgh_bits & MACH_MSGH_BITS_OLD_FORMAT) { ! 104: reply_size = ikm_less_overhead(2048); ! 105: reply = ikm_alloc(reply_size); ! 106: if (reply == IKM_NULL) { ! 107: printf("ipc_kobject_server: dropping request\n"); ! 108: ipc_kmsg_destroy(request); ! 109: return IKM_NULL; ! 110: } ! 111: ikm_init(reply, reply_size); ! 112: ! 113: reply->ikm_sender = KERNEL_SECURITY_ID_VALUE; ! 114: ! 115: /* ! 116: * Initialize reply message. ! 117: */ ! 118: { ! 119: #define InP ((mach_msg_header_t *) &request->ikm_header) ! 120: #define OutP ((mig_reply_header_t *) &reply->ikm_header) ! 121: ! 122: static mach_msg_type_t RetCodeType = { ! 123: /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32, ! 124: /* msgt_size = */ 32, ! 125: /* msgt_number = */ 1, ! 126: /* msgt_inline = */ TRUE, ! 127: /* msgt_longform = */ FALSE, ! 128: /* msgt_unused = */ 0 ! 129: }; ! 130: OutP->Head.msgh_bits = ! 131: MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0) | ! 132: MACH_MSGH_BITS_OLD_FORMAT; ! 133: OutP->Head.msgh_size = sizeof(mig_reply_header_t); ! 134: OutP->Head.msgh_remote_port = InP->msgh_local_port; ! 135: OutP->Head.msgh_local_port = MACH_PORT_NULL; ! 136: OutP->Head.msgh_reserved = 0; ! 137: OutP->Head.msgh_id = InP->msgh_id + 100; ! 138: ! 139: OutP->RetCodeType = RetCodeType; ! 140: ! 141: #undef InP ! 142: #undef OutP ! 143: } ! 144: ! 145: /* ! 146: * Find the server routine to call, and call it ! 147: * to perform the kernel function ! 148: */ ! 149: #if MACH_NET ! 150: if (netipc_msg_send(request)) ! 151: ((mig_reply_header_t *) ! 152: &reply->ikm_header)->RetCode = MIG_NO_REPLY; ! 153: else ! 154: #endif ! 155: { ! 156: extern mig_routine_t mach_server_routine(), ! 157: mach_port_server_routine(), ! 158: mach_host_server_routine(); ! 159: #if DRIVERKIT ! 160: extern mig_routine_t driverServer_server_routine(); ! 161: #endif ! 162: ! 163: #if MACH_MACHINE_ROUTINES ! 164: extern mig_routine_t MACHINE_SERVER_ROUTINE(); ! 165: #endif ! 166: ! 167: if ((routine = ! 168: mach_server_routine(&request->ikm_header)) != 0 ! 169: || (routine = ! 170: mach_host_server_routine(&request->ikm_header)) != 0 ! 171: #if DRIVERKIT ! 172: || (routine = ! 173: driverServer_server_routine(&request->ikm_header)) != 0 ! 174: #endif DRIVERKIT ! 175: #if MACH_MACHINE_ROUTINES ! 176: || (routine = ! 177: MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0 ! 178: #endif MACH_MACHINE_ROUTINES ! 179: ) { ! 180: (*routine)(&request->ikm_header, &reply->ikm_header); ! 181: } ! 182: else ! 183: if (!ipc_kobject_notify( ! 184: &request->ikm_header,&reply->ikm_header)) { ! 185: ((mig_reply_header_t *) ! 186: &reply->ikm_header)->RetCode = MIG_BAD_ID; ! 187: #if MACH_IPC_TEST ! 188: printf("ipc_kobject_server: bogus kernel message, id=%d\n", ! 189: request->ikm_header.msgh_id); ! 190: #endif MACH_IPC_TEST ! 191: } ! 192: } ! 193: ! 194: kr = ((mig_reply_header_t *) &reply->ikm_header)->RetCode; ! 195: } ! 196: else { ! 197: reply_size = ikm_less_overhead(2048); ! 198: reply = ikm_alloc(reply_size); ! 199: if (reply == IKM_NULL) { ! 200: printf("ipc_kobject_server: dropping request\n"); ! 201: ipc_kmsg_destroy(request); ! 202: return IKM_NULL; ! 203: } ! 204: ikm_init(reply, reply_size); ! 205: ! 206: reply->ikm_sender = KERNEL_SECURITY_ID_VALUE; ! 207: ! 208: /* ! 209: * Initialize reply message. ! 210: */ ! 211: { ! 212: #define InP ((mach_msg_header_t *) &request->ikm_header) ! 213: #define OutP ((mig_reply_error_t *) &reply->ikm_header) ! 214: ! 215: OutP->NDR = NDR_record; ! 216: OutP->Head.msgh_size = sizeof(mig_reply_error_t); ! 217: ! 218: OutP->Head.msgh_bits = ! 219: MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0); ! 220: OutP->Head.msgh_remote_port = InP->msgh_local_port; ! 221: OutP->Head.msgh_local_port = MACH_PORT_NULL; ! 222: OutP->Head.msgh_reserved = 0; ! 223: OutP->Head.msgh_id = InP->msgh_id + 100; ! 224: ! 225: #undef InP ! 226: #undef OutP ! 227: } ! 228: ! 229: /* ! 230: * Find the server routine to call, and call it ! 231: * to perform the kernel function ! 232: */ ! 233: { ! 234: extern mig_routine_t mach_port_server_routine(); ! 235: #if MACH_DEBUG ! 236: extern mig_routine_t mach_debug_server_routine(); ! 237: #endif ! 238: ! 239: if ((routine = ! 240: mach_port_server_routine(&request->ikm_header)) != 0 ! 241: #if MACH_DEBUG ! 242: || (routine = ! 243: mach_debug_server_routine(&request->ikm_header)) != 0 ! 244: #endif MACH_DEBUG ! 245: ) { ! 246: (*routine)(&request->ikm_header, &reply->ikm_header); ! 247: } ! 248: else ! 249: if (!ipc_kobject_notify( ! 250: &request->ikm_header,&reply->ikm_header)) { ! 251: ((mig_reply_error_t *) ! 252: &reply->ikm_header)->RetCode = MIG_BAD_ID; ! 253: #if MACH_IPC_TEST ! 254: printf("ipc_kobject_server: bogus kernel message, id=%d\n", ! 255: request->ikm_header.msgh_id); ! 256: #endif MACH_IPC_TEST ! 257: } ! 258: } ! 259: ! 260: if (!(reply->ikm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX)) ! 261: kr = ((mig_reply_error_t *) &reply->ikm_header)->RetCode; ! 262: else ! 263: kr = KERN_SUCCESS; ! 264: } ! 265: ! 266: /* ! 267: * Destroy destination. The following code differs from ! 268: * ipc_object_destroy in that we release the send-once ! 269: * right instead of generating a send-once notification ! 270: * (which would bring us here again, creating a loop). ! 271: * It also differs in that we only expect send or ! 272: * send-once rights, never receive rights. ! 273: * ! 274: * We set msgh_remote_port to IP_NULL so that the kmsg ! 275: * destroy routines don't try to destroy the port twice. ! 276: */ ! 277: destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port; ! 278: switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) { ! 279: case MACH_MSG_TYPE_PORT_SEND: ! 280: ipc_port_release_send(*destp); ! 281: break; ! 282: ! 283: case MACH_MSG_TYPE_PORT_SEND_ONCE: ! 284: ipc_port_release_sonce(*destp); ! 285: break; ! 286: ! 287: default: ! 288: panic("ipc_object_destroy: strange destination rights"); ! 289: } ! 290: *destp = IP_NULL; ! 291: ! 292: if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) { ! 293: /* ! 294: * The server function is responsible for the contents ! 295: * of the message. The reply port right is moved ! 296: * to the reply message, and we have deallocated ! 297: * the destination port right, so we just need ! 298: * to free the kmsg. ! 299: */ ! 300: ! 301: /* like ipc_kmsg_put, but without the copyout */ ! 302: ! 303: ikm_check_initialized(request, request->ikm_size); ! 304: if ((request->ikm_size == IKM_SAVED_KMSG_SIZE) && ! 305: (ikm_cache() == IKM_NULL)) ! 306: ikm_cache() = request; ! 307: else ! 308: ikm_free(request); ! 309: } else { ! 310: /* ! 311: * The message contents of the request are intact. ! 312: * Destroy everthing except the reply port right, ! 313: * which is needed in the reply message. ! 314: */ ! 315: ! 316: request->ikm_header.msgh_local_port = MACH_PORT_NULL; ! 317: ipc_kmsg_destroy(request); ! 318: } ! 319: ! 320: if (kr == MIG_NO_REPLY) { ! 321: /* ! 322: * The server function will send a reply message ! 323: * using the reply port right, which it has saved. ! 324: */ ! 325: ! 326: ikm_free(reply); ! 327: return IKM_NULL; ! 328: } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) { ! 329: /* ! 330: * Can't queue the reply message if the destination ! 331: * (the reply port) isn't valid. ! 332: */ ! 333: ! 334: ipc_kmsg_destroy(reply); ! 335: return IKM_NULL; ! 336: } ! 337: ! 338: return reply; ! 339: } ! 340: ! 341: /* ! 342: * Routine: ipc_kobject_set ! 343: * Purpose: ! 344: * Make a port represent a kernel object of the given type. ! 345: * The caller is responsible for handling refs for the ! 346: * kernel object, if necessary. ! 347: * Conditions: ! 348: * Nothing locked. The port must be active. ! 349: */ ! 350: ! 351: void ! 352: ipc_kobject_set( ! 353: ipc_port_t port, ! 354: ipc_kobject_t kobject, ! 355: ipc_kobject_type_t type) ! 356: { ! 357: ip_lock(port); ! 358: assert(ip_active(port)); ! 359: port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type; ! 360: port->ip_kobject = kobject; ! 361: ip_unlock(port); ! 362: } ! 363: ! 364: /* ! 365: * Routine: ipc_kobject_destroy ! 366: * Purpose: ! 367: * Release any kernel object resources associated ! 368: * with the port, which is being destroyed. ! 369: * ! 370: * This should only be needed when resources are ! 371: * associated with a user's port. In the normal case, ! 372: * when the kernel is the receiver, the code calling ! 373: * ipc_port_dealloc_kernel should clean up the resources. ! 374: * Conditions: ! 375: * The port is not locked, but it is dead. ! 376: */ ! 377: ! 378: void ! 379: ipc_kobject_destroy(port) ! 380: ipc_port_t port; ! 381: { ! 382: switch (ip_kotype(port)) { ! 383: #if MACH_NET ! 384: case IKOT_NETIPC: ! 385: netipc_ignore(IP_NULL, port); ! 386: break; ! 387: #endif ! 388: ! 389: default: ! 390: #if MACH_ASSERT ! 391: printf("ipc_kobject_destroy: port 0x%x, kobj 0x%x, type %d\n", ! 392: port, port->ip_kobject, ip_kotype(port)); ! 393: #endif MACH_ASSERT ! 394: break; ! 395: } ! 396: } ! 397: ! 398: /* ! 399: * Routine: ipc_kobject_notify ! 400: * Purpose: ! 401: * Deliver notifications to kobjects that care about them. ! 402: */ ! 403: ! 404: boolean_t ! 405: ipc_kobject_notify(request_header, reply_header) ! 406: mach_msg_header_t *request_header; ! 407: mach_msg_header_t *reply_header; ! 408: { ! 409: ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port; ! 410: ! 411: ((mig_reply_header_t *) reply_header)->RetCode = MIG_NO_REPLY; ! 412: switch (request_header->msgh_id) { ! 413: case MACH_NOTIFY_PORT_DELETED: ! 414: case MACH_NOTIFY_MSG_ACCEPTED: ! 415: case MACH_NOTIFY_PORT_DESTROYED: ! 416: case MACH_NOTIFY_NO_SENDERS: ! 417: case MACH_NOTIFY_SEND_ONCE: ! 418: case MACH_NOTIFY_DEAD_NAME: ! 419: break; ! 420: ! 421: default: ! 422: return FALSE; ! 423: } ! 424: switch (ip_kotype(port)) { ! 425: default: ! 426: return FALSE; ! 427: } ! 428: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.