X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d7e50217d7adf6e52786a38bcaa4cd698cb9a79e..21362eb3e66fd2c787aee132bce100a44d71a99c:/osfmk/kern/ipc_mig.c diff --git a/osfmk/kern/ipc_mig.c b/osfmk/kern/ipc_mig.c index a880cdea1..e68fa9f06 100644 --- a/osfmk/kern/ipc_mig.c +++ b/osfmk/kern/ipc_mig.c @@ -1,16 +1,19 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, 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@ @@ -60,13 +63,14 @@ #include #include -#include #include #include +#include #include #include #include #include + #include #include #include @@ -158,8 +162,8 @@ mach_msg_rpc_from_kernel( } /* insert send-once right for the reply port */ - kmsg->ikm_header.msgh_local_port = reply; - kmsg->ikm_header.msgh_bits |= + kmsg->ikm_header->msgh_local_port = reply; + kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS(0, MACH_MSG_TYPE_MAKE_SEND_ONCE); ipc_port_reference(reply); @@ -177,7 +181,7 @@ mach_msg_rpc_from_kernel( ipc_port_release(reply); return MACH_RCV_PORT_DIED; } - if (!self->top_act || !self->top_act->active) { + if (!self->active) { ip_unlock(reply); ipc_port_release(reply); return MACH_RCV_INTERRUPTED; @@ -206,7 +210,7 @@ mach_msg_rpc_from_kernel( assert(mr == MACH_RCV_INTERRUPTED); - if (self->top_act && self->top_act->handlers) { + if (self->handlers) { ipc_port_release(reply); return(mr); } @@ -224,9 +228,9 @@ mach_msg_rpc_from_kernel( } *****/ - if (rcv_size < kmsg->ikm_header.msgh_size) { + if (rcv_size < kmsg->ikm_header->msgh_size) { ipc_kmsg_copyout_dest(kmsg, ipc_space_reply); - ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size); + ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header->msgh_size); return MACH_RCV_TOO_LARGE; } @@ -237,20 +241,15 @@ mach_msg_rpc_from_kernel( */ ipc_kmsg_copyout_to_kernel(kmsg, ipc_space_reply); - ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size); + ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header->msgh_size); return MACH_MSG_SUCCESS; } -/************** These Calls are set up for kernel-loaded tasks **************/ -/************** Apple does not plan on supporting that. These **************/ -/************** need to be reworked to deal with the kernel **************/ -/************** proper to eliminate the kernel specific code MIG **************/ -/************** must generate. **************/ - +/************** These Calls are set up for kernel-loaded tasks/threads **************/ /* - * Routine: mach_msg + * Routine: mach_msg_overwrite * Purpose: * Like mach_msg_overwrite_trap except that message buffers * live in kernel space. Doesn't handle any options. @@ -265,15 +264,15 @@ mach_msg_rpc_from_kernel( mach_msg_return_t mach_msg_overwrite( - mach_msg_header_t *msg, - mach_msg_option_t option, + mach_msg_header_t *msg, + mach_msg_option_t option, mach_msg_size_t send_size, mach_msg_size_t rcv_size, - mach_port_name_t rcv_name, - mach_msg_timeout_t timeout, - mach_port_name_t notify, - mach_msg_header_t *rcv_msg, - mach_msg_size_t rcv_msg_size) + mach_port_name_t rcv_name, + __unused mach_msg_timeout_t msg_timeout, + __unused mach_port_name_t notify, + __unused mach_msg_header_t *rcv_msg, + __unused mach_msg_size_t rcv_msg_size) { ipc_space_t space = current_space(); vm_map_t map = current_map(); @@ -283,10 +282,37 @@ mach_msg_overwrite( mach_msg_format_0_trailer_t *trailer; if (option & MACH_SEND_MSG) { - mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg); - if (mr != MACH_MSG_SUCCESS) - panic("mach_msg"); + mach_msg_size_t msg_and_trailer_size; + mach_msg_max_trailer_t *max_trailer; + + if ((send_size < sizeof(mach_msg_header_t)) || (send_size & 3)) + return MACH_SEND_MSG_TOO_SMALL; + + if (send_size > MACH_MSG_SIZE_MAX - MAX_TRAILER_SIZE) + return MACH_SEND_TOO_LARGE; + + msg_and_trailer_size = send_size + MAX_TRAILER_SIZE; + kmsg = ipc_kmsg_alloc(msg_and_trailer_size); + + if (kmsg == IKM_NULL) + return MACH_SEND_NO_BUFFER; + + (void) memcpy((void *) kmsg->ikm_header, (const void *) msg, send_size); + + kmsg->ikm_header->msgh_size = send_size; + /* + * Reserve for the trailer the largest space (MAX_TRAILER_SIZE) + * However, the internal size field of the trailer (msgh_trailer_size) + * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to optimize + * the cases where no implicit data is requested. + */ + max_trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + send_size); + max_trailer->msgh_sender = current_thread()->task->sec_token; + max_trailer->msgh_audit = current_thread()->task->audit_token; + max_trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0; + max_trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE; + mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL); if (mr != MACH_MSG_SUCCESS) { ipc_kmsg_free(kmsg); @@ -330,15 +356,16 @@ mach_msg_overwrite( return mr; trailer = (mach_msg_format_0_trailer_t *) - ((vm_offset_t)&kmsg->ikm_header + kmsg->ikm_header.msgh_size); + ((vm_offset_t)kmsg->ikm_header + kmsg->ikm_header->msgh_size); if (option & MACH_RCV_TRAILER_MASK) { trailer->msgh_seqno = seqno; trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(option); } - if (rcv_size < (kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size)) { + if (rcv_size < (kmsg->ikm_header->msgh_size + trailer->msgh_trailer_size)) { ipc_kmsg_copyout_dest(kmsg, space); - ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg); + (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, sizeof *msg); + ipc_kmsg_free(kmsg); return MACH_RCV_TOO_LARGE; } @@ -347,17 +374,19 @@ mach_msg_overwrite( if (mr != MACH_MSG_SUCCESS) { if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) { ipc_kmsg_put_to_kernel(msg, kmsg, - kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size); + kmsg->ikm_header->msgh_size + trailer->msgh_trailer_size); } else { ipc_kmsg_copyout_dest(kmsg, space); - ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg); + (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, sizeof *msg); + ipc_kmsg_free(kmsg); } return mr; } - ipc_kmsg_put_to_kernel(msg, kmsg, - kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size); + (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, + kmsg->ikm_header->msgh_size + trailer->msgh_trailer_size); + ipc_kmsg_free(kmsg); } return MACH_MSG_SUCCESS; @@ -367,39 +396,23 @@ mach_msg_overwrite( * Routine: mig_get_reply_port * Purpose: * Called by client side interfaces living in the kernel - * to get a reply port. This port is used for - * mach_msg() calls which are kernel calls. + * to get a reply port. */ mach_port_t mig_get_reply_port(void) { - thread_t self = current_thread(); - - assert(self->ith_mig_reply == (mach_port_t)0); - - /* - * JMM - for now we have no real clients of this under the kernel - * loaded server model because we only have one of those. In order - * to avoid MIG changes, we just return null here - and return] - * references to ipc_port_t's instead of names. - * - * if (self->ith_mig_reply == MACH_PORT_NULL) - * self->ith_mig_reply = mach_reply_port(); - */ - return self->ith_mig_reply; + return (MACH_PORT_NULL); } /* * Routine: mig_dealloc_reply_port * Purpose: * Called by client side interfaces to get rid of a reply port. - * Shouldn't ever be called inside the kernel, because - * kernel calls shouldn't prompt Mig to call it. */ void mig_dealloc_reply_port( - mach_port_t reply_port) + __unused mach_port_t reply_port) { panic("mig_dealloc_reply_port"); } @@ -412,7 +425,7 @@ mig_dealloc_reply_port( */ void mig_put_reply_port( - mach_port_t reply_port) + __unused mach_port_t reply_port) { } @@ -463,7 +476,7 @@ mig_user_deallocate( char *data, vm_size_t size) { - kfree((vm_offset_t)data, size); + kfree(data, size); } /* @@ -477,9 +490,11 @@ mig_object_init( mig_object_t mig_object, const IMIGObject *interface) { - assert(mig_object != MIG_OBJECT_NULL); - mig_object->pVtbl = (IMIGObjectVtbl *)interface; + if (mig_object == MIG_OBJECT_NULL) + return KERN_INVALID_ARGUMENT; + mig_object->pVtbl = (const IMIGObjectVtbl *)interface; mig_object->port = MACH_PORT_NULL; + return KERN_SUCCESS; } /* @@ -495,7 +510,7 @@ mig_object_init( */ void mig_object_destroy( - mig_object_t mig_object) + __assert_only mig_object_t mig_object) { assert(mig_object->port == MACH_PORT_NULL); return;