X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..db6096698656d32db7df630594bd9617ee54f828:/osfmk/kern/ipc_kobject.c diff --git a/osfmk/kern/ipc_kobject.c b/osfmk/kern/ipc_kobject.c index 06898cc5f..89b8f9e68 100644 --- a/osfmk/kern/ipc_kobject.c +++ b/osfmk/kern/ipc_kobject.c @@ -1,16 +1,19 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER @@ -20,7 +23,7 @@ * Please see the License for the specific language governing rights and * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ @@ -50,6 +53,13 @@ * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ +/* + * NOTICE: This file was modified by McAfee Research in 2004 to introduce + * support for mandatory and extensible security protections. This notice + * is included in support of clause 2.2 (b) of the Apple Public License, + * Version 2.0. + * Copyright (c) 2005 SPARTA, Inc. + */ /* */ /* @@ -73,16 +83,61 @@ #include #include #include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if VM32_SUPPORT +#include +#endif +#include + +#include +#include + +#include + +#if CONFIG_AUDIT +#include +#endif + +#if MACH_MACHINE_ROUTINES +#include +#endif /* MACH_MACHINE_ROUTINES */ +#if XK_PROXY +#include +#endif /* XK_PROXY */ -#include +#include #include +#include #include -#include +#include #include +#include #include #include +#include #include +#include + +#include /* * Routine: ipc_kobject_notify @@ -94,8 +149,6 @@ ipc_kobject_notify( mach_msg_header_t *request_header, mach_msg_header_t *reply_header); -#include - typedef struct { mach_msg_id_t num; mig_routine_t routine; @@ -116,73 +169,54 @@ mig_hash_t mig_buckets[MAX_MIG_ENTRIES]; int mig_table_max_displ; mach_msg_size_t mig_reply_size; +#if CONFIG_MACF +#include +#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if MACH_MACHINE_ROUTINES -#include -#endif /* MACH_MACHINE_ROUTINES */ -#if XK_PROXY -#include -#endif /* XK_PROXY */ -mig_subsystem_t mig_e[] = { - (mig_subsystem_t)&mach_port_subsystem, - (mig_subsystem_t)&mach_host_subsystem, - (mig_subsystem_t)&host_priv_subsystem, - (mig_subsystem_t)&host_security_subsystem, - (mig_subsystem_t)&clock_subsystem, - (mig_subsystem_t)&clock_priv_subsystem, - (mig_subsystem_t)&processor_subsystem, - (mig_subsystem_t)&processor_set_subsystem, - (mig_subsystem_t)&is_iokit_subsystem, - (mig_subsystem_t)&memory_object_name_subsystem, - (mig_subsystem_t)&lock_set_subsystem, - (mig_subsystem_t)&ledger_subsystem, - (mig_subsystem_t)&semaphore_subsystem, - (mig_subsystem_t)&task_subsystem, - (mig_subsystem_t)&thread_act_subsystem, - (mig_subsystem_t)&vm_map_subsystem, - (mig_subsystem_t)&UNDReply_subsystem, +const struct mig_subsystem *mig_e[] = { + (const struct mig_subsystem *)&mach_vm_subsystem, + (const struct mig_subsystem *)&mach_port_subsystem, + (const struct mig_subsystem *)&mach_host_subsystem, + (const struct mig_subsystem *)&host_priv_subsystem, + (const struct mig_subsystem *)&host_security_subsystem, + (const struct mig_subsystem *)&clock_subsystem, + (const struct mig_subsystem *)&clock_priv_subsystem, + (const struct mig_subsystem *)&processor_subsystem, + (const struct mig_subsystem *)&processor_set_subsystem, + (const struct mig_subsystem *)&is_iokit_subsystem, + (const struct mig_subsystem *)&memory_object_name_subsystem, + (const struct mig_subsystem *)&lock_set_subsystem, + (const struct mig_subsystem *)&task_subsystem, + (const struct mig_subsystem *)&thread_act_subsystem, +#if VM32_SUPPORT + (const struct mig_subsystem *)&vm32_map_subsystem, +#endif + (const struct mig_subsystem *)&UNDReply_subsystem, + (const struct mig_subsystem *)&default_pager_object_subsystem, #if XK_PROXY - (mig_subsystem_t)&do_uproxy_xk_uproxy_subsystem, + (const struct mig_subsystem *)&do_uproxy_xk_uproxy_subsystem, #endif /* XK_PROXY */ #if MACH_MACHINE_ROUTINES - (mig_subsystem_t)&MACHINE_SUBSYSTEM, + (const struct mig_subsystem *)&MACHINE_SUBSYSTEM, #endif /* MACH_MACHINE_ROUTINES */ #if MCMSG && iPSC860 - (mig_subsystem_t)&mcmsg_info_subsystem, + (const struct mig_subsystem *)&mcmsg_info_subsystem, #endif /* MCMSG && iPSC860 */ + +#if CONFIG_MACF + (const struct mig_subsystem *)&security_subsystem, +#endif }; void mig_init(void) { - register unsigned int i, n = sizeof(mig_e)/sizeof(mig_subsystem_t); - register unsigned int howmany; - register mach_msg_id_t j, pos, nentry, range; + unsigned int i, n = sizeof(mig_e)/sizeof(const struct mig_subsystem *); + int howmany; + mach_msg_id_t j, pos, nentry, range; for (i = 0; i < n; i++) { range = mig_e[i]->end - mig_e[i]->start; @@ -196,7 +230,7 @@ mig_init(void) nentry = j + mig_e[i]->start; for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1; mig_buckets[pos].num; - pos = ++pos % MAX_MIG_ENTRIES, howmany++) { + pos++, pos = pos % MAX_MIG_ENTRIES, howmany++) { if (mig_buckets[pos].num == nentry) { printf("message id = %d\n", nentry); panic("multiple entries with the same msgh_id"); @@ -237,24 +271,15 @@ ipc_kobject_server( mach_msg_size_t reply_size; ipc_kmsg_t reply; kern_return_t kr; - mig_routine_t routine; ipc_port_t *destp; mach_msg_format_0_trailer_t *trailer; register mig_hash_t *ptr; - unsigned int th; - - /* Only fetch current thread if ETAP is configured */ - ETAP_DATA_LOAD(th, current_thread()); - ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH, - EVENT_BEGIN, - ((thread_t) th), - &request->ikm_header.msgh_id, - sizeof(int)); + /* - * Find out corresponding mig_hash entry if any - */ + * Find out corresponding mig_hash entry if any + */ { - register int key = request->ikm_header.msgh_id; + register int key = request->ikm_header->msgh_id; register int i = MIG_HASH(key); register int max_iter = mig_table_max_displ; @@ -287,8 +312,15 @@ ipc_kobject_server( * Initialize reply message. */ { -#define InP ((mach_msg_header_t *) &request->ikm_header) -#define OutP ((mig_reply_error_t *) &reply->ikm_header) +#define InP ((mach_msg_header_t *) request->ikm_header) +#define OutP ((mig_reply_error_t *) reply->ikm_header) + + /* + * MIG should really assure no data leakage - + * but until it does, pessimistically zero the + * whole reply buffer. + */ + bzero((void *)OutP, reply_size); OutP->NDR = NDR_record; OutP->Head.msgh_size = sizeof(mig_reply_error_t); @@ -297,6 +329,7 @@ ipc_kobject_server( MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0); OutP->Head.msgh_remote_port = InP->msgh_local_port; OutP->Head.msgh_local_port = MACH_PORT_NULL; + OutP->Head.msgh_reserved = (mach_msg_size_t)InP->msgh_id; /* useful for debug */ OutP->Head.msgh_id = InP->msgh_id + 100; #undef InP @@ -309,18 +342,18 @@ ipc_kobject_server( */ { if (ptr) { - (*ptr->routine)(&request->ikm_header, &reply->ikm_header); + (*ptr->routine)(request->ikm_header, reply->ikm_header); kernel_task->messages_received++; } else { - if (!ipc_kobject_notify(&request->ikm_header, &reply->ikm_header)){ + if (!ipc_kobject_notify(request->ikm_header, reply->ikm_header)){ #if MACH_IPC_TEST printf("ipc_kobject_server: bogus kernel message, id=%d\n", - request->ikm_header.msgh_id); + request->ikm_header->msgh_id); #endif /* MACH_IPC_TEST */ - _MIG_MSGID_INVALID(request->ikm_header.msgh_id); + _MIG_MSGID_INVALID(request->ikm_header->msgh_id); - ((mig_reply_error_t *) &reply->ikm_header)->RetCode + ((mig_reply_error_t *) reply->ikm_header)->RetCode = MIG_BAD_ID; } else @@ -340,8 +373,8 @@ ipc_kobject_server( * We set msgh_remote_port to IP_NULL so that the kmsg * destroy routines don't try to destroy the port twice. */ - destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port; - switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) { + destp = (ipc_port_t *) &request->ikm_header->msgh_remote_port; + switch (MACH_MSGH_BITS_REMOTE(request->ikm_header->msgh_bits)) { case MACH_MSG_TYPE_PORT_SEND: ipc_port_release_send(*destp); break; @@ -355,9 +388,9 @@ ipc_kobject_server( } *destp = IP_NULL; - if (!(reply->ikm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) && - ((mig_reply_error_t *) &reply->ikm_header)->RetCode != KERN_SUCCESS) - kr = ((mig_reply_error_t *) &reply->ikm_header)->RetCode; + if (!(reply->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) && + ((mig_reply_error_t *) reply->ikm_header)->RetCode != KERN_SUCCESS) + kr = ((mig_reply_error_t *) reply->ikm_header)->RetCode; else kr = KERN_SUCCESS; @@ -377,7 +410,7 @@ ipc_kobject_server( * Destroy everthing except the reply port right, * which is needed in the reply message. */ - request->ikm_header.msgh_local_port = MACH_PORT_NULL; + request->ikm_header->msgh_local_port = MACH_PORT_NULL; ipc_kmsg_destroy(request); } @@ -389,14 +422,8 @@ ipc_kobject_server( ipc_kmsg_free(reply); - ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH, - EVENT_END, - ((thread_t) th), - &request->ikm_header.msgh_id, - sizeof(int)); - return IKM_NULL; - } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) { + } else if (!IP_VALID((ipc_port_t)reply->ikm_header->msgh_remote_port)) { /* * Can't queue the reply message if the destination * (the reply port) isn't valid. @@ -404,27 +431,16 @@ ipc_kobject_server( ipc_kmsg_destroy(reply); - ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH, - EVENT_END, - ((thread_t) th), - &request->ikm_header.msgh_id, - sizeof(int)); - return IKM_NULL; } trailer = (mach_msg_format_0_trailer_t *) - ((vm_offset_t)&reply->ikm_header + (int)reply->ikm_header.msgh_size); + ((vm_offset_t)reply->ikm_header + (int)reply->ikm_header->msgh_size); + trailer->msgh_sender = KERNEL_SECURITY_TOKEN; trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0; trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE; - ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH, - EVENT_END, - ((thread_t) th), - &request->ikm_header.msgh_id, - sizeof(int)); - return reply; } @@ -447,6 +463,11 @@ ipc_kobject_set( { ip_lock(port); ipc_kobject_set_atomically(port, kobject, type); + +#if CONFIG_MACF_MACH + mac_port_label_update_kobject (&port->ip_label, type); +#endif + ip_unlock(port); } @@ -492,22 +513,28 @@ ipc_kobject_destroy( mach_destroy_memory_entry(port); break; - default: /* XXX (bogon) */ + case IKOT_HOST_NOTIFY: + host_notify_port_destroy(port); + break; + +#if CONFIG_MACF_MACH + case IKOT_LABELH: + labelh_destroy(port); + break; +#endif + + default: break; } } -extern int vnode_pager_workaround; - boolean_t ipc_kobject_notify( mach_msg_header_t *request_header, mach_msg_header_t *reply_header) { ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port; - mig_subsystem_t paging_subsystem_object; - mach_port_seqno_t seqno; ((mig_reply_error_t *) reply_header)->RetCode = MIG_NO_REPLY; switch (request_header->msgh_id) { @@ -526,15 +553,24 @@ ipc_kobject_notify( } if (ip_kotype(port) == IKOT_UPL) { upl_no_senders( - (ipc_port_t)request_header->msgh_remote_port, + request_header->msgh_remote_port, (mach_port_mscount_t) ((mach_no_senders_notification_t *) request_header)->not_count); - (ipc_port_t)reply_header->msgh_remote_port - = MACH_PORT_NULL; + reply_header->msgh_remote_port = MACH_PORT_NULL; + return TRUE; + } +#if CONFIG_AUDIT + if (ip_kotype(port) == IKOT_AU_SESSIONPORT) { + audit_session_nosenders(request_header); return TRUE; } - +#endif + if (ip_kotype(port) == IKOT_FILEPORT) { + fileport_notify(request_header); + return TRUE; + } + break; case MACH_NOTIFY_PORT_DELETED: @@ -553,8 +589,6 @@ ipc_kobject_notify( case IKOT_IOKIT_CONNECT: case IKOT_IOKIT_SPARE: { - extern boolean_t iokit_notify( mach_msg_header_t *msg); - return iokit_notify(request_header); } #endif @@ -562,68 +596,3 @@ ipc_kobject_notify( return FALSE; } } - - - -#include -#if MACH_COUNTERS && MACH_KDB - -#include -#include - -#define printf kdbprintf - -extern void kobjserver_stats(void); -extern void bucket_stats_print(mig_hash_t *bucket); - -extern void kobjserver_stats_clear(void); - - -void -kobjserver_stats_clear(void) -{ - int i; - for (i = 0; i < MAX_MIG_ENTRIES; i++) { - mig_buckets[i].callcount = 0; - } -} - -void -kobjserver_stats(void) -{ - register unsigned int i, n = sizeof(mig_e)/sizeof(mig_subsystem_t); - register unsigned int howmany; - register mach_msg_id_t j, pos, nentry, range; - - db_printf("Kobject server call counts:\n"); - for (i = 0; i < n; i++) { - db_printf(" "); - db_printsym((vm_offset_t)mig_e[i], DB_STGY_ANY); - db_printf(":\n"); - range = mig_e[i]->end - mig_e[i]->start; - if (!mig_e[i]->start || range < 0) continue; - - for (j = 0; j < range; j++) { - nentry = j + mig_e[i]->start; - for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1; - mig_buckets[pos].num; - pos = ++pos % MAX_MIG_ENTRIES, howmany++) { - if (mig_buckets[pos].num == nentry) - bucket_stats_print(&mig_buckets[pos]); - } - } - } -} - -void -bucket_stats_print(mig_hash_t *bucket) -{ - if (bucket->callcount) { - db_printf(" "); - db_printsym((vm_offset_t)bucket->routine, DB_STGY_ANY); - db_printf(" (%d):\t%d\n", bucket->num, bucket->callcount); - } -} - - -#endif /* MACH_COUNTERS && MACH_KDB */