X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/c910b4d9d2451126ae3917b931cd4390c11e1d52..440d4c6cfad24426bfddca7518f16c17f4e443f7:/osfmk/kern/ipc_mig.c diff --git a/osfmk/kern/ipc_mig.c b/osfmk/kern/ipc_mig.c index 0dbe02f08..512073675 100644 --- a/osfmk/kern/ipc_mig.c +++ b/osfmk/kern/ipc_mig.c @@ -79,8 +79,11 @@ #include #include #include +#include #include +#include + /* * Routine: mach_msg_send_from_kernel * Purpose: @@ -98,6 +101,13 @@ * or destination is above kernel limit */ +#if IKM_SUPPORT_LEGACY + +#undef mach_msg_send_from_kernel +mach_msg_return_t mach_msg_send_from_kernel( + mach_msg_header_t *msg, + mach_msg_size_t send_size); + mach_msg_return_t mach_msg_send_from_kernel( mach_msg_header_t *msg, @@ -106,14 +116,43 @@ mach_msg_send_from_kernel( ipc_kmsg_t kmsg; mach_msg_return_t mr; - if (!MACH_PORT_VALID((mach_port_name_t)msg->msgh_remote_port)) - return MACH_SEND_INVALID_DEST; + mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg); + if (mr != MACH_MSG_SUCCESS) + return mr; + + mr = ipc_kmsg_copyin_from_kernel_legacy(kmsg); + if (mr != MACH_MSG_SUCCESS) { + ipc_kmsg_free(kmsg); + return mr; + } + + mr = ipc_kmsg_send_always(kmsg); + if (mr != MACH_MSG_SUCCESS) { + ipc_kmsg_destroy(kmsg); + } + + return mr; +} + +#endif /* IKM_SUPPORT_LEGACY */ + +mach_msg_return_t +mach_msg_send_from_kernel_proper( + mach_msg_header_t *msg, + mach_msg_size_t send_size) +{ + ipc_kmsg_t kmsg; + mach_msg_return_t mr; mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg); if (mr != MACH_MSG_SUCCESS) return mr; - ipc_kmsg_copyin_from_kernel(kmsg); + mr = ipc_kmsg_copyin_from_kernel(kmsg); + if (mr != MACH_MSG_SUCCESS) { + ipc_kmsg_free(kmsg); + return mr; + } mr = ipc_kmsg_send_always(kmsg); if (mr != MACH_MSG_SUCCESS) { @@ -123,6 +162,8 @@ mach_msg_send_from_kernel( return mr; } +#if IKM_SUPPORT_LEGACY + mach_msg_return_t mach_msg_send_from_kernel_with_options( mach_msg_header_t *msg, @@ -133,14 +174,16 @@ mach_msg_send_from_kernel_with_options( ipc_kmsg_t kmsg; mach_msg_return_t mr; - if (!MACH_PORT_VALID((mach_port_name_t)msg->msgh_remote_port)) - return MACH_SEND_INVALID_DEST; - mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg); if (mr != MACH_MSG_SUCCESS) return mr; - ipc_kmsg_copyin_from_kernel(kmsg); + mr = ipc_kmsg_copyin_from_kernel_legacy(kmsg); + if (mr != MACH_MSG_SUCCESS) { + ipc_kmsg_free(kmsg); + return mr; + } + mr = ipc_kmsg_send(kmsg, option, timeout_val); if (mr != MACH_MSG_SUCCESS) { ipc_kmsg_destroy(kmsg); @@ -149,6 +192,8 @@ mach_msg_send_from_kernel_with_options( return mr; } +#endif /* IKM_SUPPORT_LEGACY */ + /* * Routine: mach_msg_rpc_from_kernel * Purpose: @@ -164,11 +209,47 @@ mach_msg_send_from_kernel_with_options( * MACH_RCV_PORT_DIED The reply port was deallocated. */ +mach_msg_return_t mach_msg_rpc_from_kernel_body(mach_msg_header_t *msg, + mach_msg_size_t send_size, mach_msg_size_t rcv_size, boolean_t legacy); + +#if IKM_SUPPORT_LEGACY + +#undef mach_msg_rpc_from_kernel mach_msg_return_t mach_msg_rpc_from_kernel( + mach_msg_header_t *msg, + mach_msg_size_t send_size, + mach_msg_size_t rcv_size); + +mach_msg_return_t +mach_msg_rpc_from_kernel( + mach_msg_header_t *msg, + mach_msg_size_t send_size, + mach_msg_size_t rcv_size) +{ + return mach_msg_rpc_from_kernel_body(msg, send_size, rcv_size, TRUE); +} + +#endif /* IKM_SUPPORT_LEGACY */ + +mach_msg_return_t +mach_msg_rpc_from_kernel_proper( mach_msg_header_t *msg, mach_msg_size_t send_size, mach_msg_size_t rcv_size) +{ + return mach_msg_rpc_from_kernel_body(msg, send_size, rcv_size, FALSE); +} + +mach_msg_return_t +mach_msg_rpc_from_kernel_body( + mach_msg_header_t *msg, + mach_msg_size_t send_size, + mach_msg_size_t rcv_size, +#if !IKM_SUPPORT_LEGACY + __unused +#endif + boolean_t legacy) { thread_t self = current_thread(); ipc_port_t reply; @@ -176,7 +257,6 @@ mach_msg_rpc_from_kernel( mach_port_seqno_t seqno; mach_msg_return_t mr; - assert(MACH_PORT_VALID((mach_port_name_t)msg->msgh_remote_port)); assert(msg->msgh_local_port == MACH_PORT_NULL); mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg); @@ -197,10 +277,20 @@ mach_msg_rpc_from_kernel( kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS(0, MACH_MSG_TYPE_MAKE_SEND_ONCE); - ipc_port_reference(reply); - - ipc_kmsg_copyin_from_kernel(kmsg); - + ip_reference(reply); + +#if IKM_SUPPORT_LEGACY + if(legacy) + mr = ipc_kmsg_copyin_from_kernel_legacy(kmsg); + else + mr = ipc_kmsg_copyin_from_kernel(kmsg); +#else + mr = ipc_kmsg_copyin_from_kernel(kmsg); +#endif + if (mr != MACH_MSG_SUCCESS) { + ipc_kmsg_free(kmsg); + return mr; + } mr = ipc_kmsg_send_always(kmsg); if (mr != MACH_MSG_SUCCESS) { ipc_kmsg_destroy(kmsg); @@ -213,12 +303,12 @@ mach_msg_rpc_from_kernel( ip_lock(reply); if ( !ip_active(reply)) { ip_unlock(reply); - ipc_port_release(reply); + ip_release(reply); return MACH_RCV_PORT_DIED; } if (!self->active) { ip_unlock(reply); - ipc_port_release(reply); + ip_release(reply); return MACH_RCV_INTERRUPTED; } @@ -246,11 +336,11 @@ mach_msg_rpc_from_kernel( assert(mr == MACH_RCV_INTERRUPTED); if (self->handlers) { - ipc_port_release(reply); + ip_release(reply); return(mr); } } - ipc_port_release(reply); + ip_release(reply); /* * Check to see how much of the message/trailer can be received. @@ -283,7 +373,14 @@ mach_msg_rpc_from_kernel( * We don't have to put them anywhere; just leave them * as they are. */ - ipc_kmsg_copyout_to_kernel(kmsg, ipc_space_reply); +#if IKM_SUPPORT_LEGACY + if(legacy) + ipc_kmsg_copyout_to_kernel_legacy(kmsg, ipc_space_reply); + else + ipc_kmsg_copyout_to_kernel(kmsg, ipc_space_reply); +#else + ipc_kmsg_copyout_to_kernel(kmsg, ipc_space_reply); +#endif ipc_kmsg_put_to_kernel(msg, kmsg, rcv_size); return mr; } @@ -322,7 +419,7 @@ mach_msg_overwrite( ipc_kmsg_t kmsg; mach_port_seqno_t seqno; mach_msg_return_t mr; - mach_msg_format_0_trailer_t *trailer; + mach_msg_trailer_size_t trailer_size; if (option & MACH_SEND_MSG) { mach_msg_size_t msg_and_trailer_size; @@ -356,7 +453,7 @@ mach_msg_overwrite( 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); + mr = ipc_kmsg_copyin(kmsg, space, map, FALSE); if (mr != MACH_MSG_SUCCESS) { ipc_kmsg_free(kmsg); return mr; @@ -392,32 +489,28 @@ mach_msg_overwrite( kmsg = self->ith_kmsg; seqno = self->ith_seqno; - ipc_object_release(object); + io_release(object); } while (mr == MACH_RCV_INTERRUPTED); if (mr != MACH_MSG_SUCCESS) return mr; - trailer = (mach_msg_format_0_trailer_t *) - ((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)) { + trailer_size = ipc_kmsg_add_trailer(kmsg, space, option, current_thread(), seqno, TRUE, + kmsg->ikm_header->msgh_remote_port->ip_context); + + if (rcv_size < (kmsg->ikm_header->msgh_size + trailer_size)) { ipc_kmsg_copyout_dest(kmsg, space); (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, sizeof *msg); ipc_kmsg_free(kmsg); return MACH_RCV_TOO_LARGE; } - mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL, - MACH_MSG_BODY_NULL); + mr = ipc_kmsg_copyout(kmsg, space, map, MACH_MSG_BODY_NULL); 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_size); } else { ipc_kmsg_copyout_dest(kmsg, space); (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, sizeof *msg); @@ -428,7 +521,7 @@ mach_msg_overwrite( } (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, - kmsg->ikm_header->msgh_size + trailer->msgh_trailer_size); + kmsg->ikm_header->msgh_size + trailer_size); ipc_kmsg_free(kmsg); } @@ -457,7 +550,6 @@ void mig_dealloc_reply_port( __unused mach_port_t reply_port) { - panic("mig_dealloc_reply_port"); } /* @@ -642,8 +734,8 @@ convert_mig_object_to_port( assert(previous == IP_NULL); - if (hw_compare_and_store((uint32_t)IP_NULL, (uint32_t)port, - (uint32_t *)&mig_object->port)) { + if (OSCompareAndSwapPtr((void *)IP_NULL, (void *)port, + (void * volatile *)&mig_object->port)) { deallocate = FALSE; } else { ipc_port_dealloc_kernel(port);