X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/316670eb35587141e969394ae8537d66b9211e80..fe8ab488e9161c46dd9885d58fc52996dc0249ff:/osfmk/ipc/mach_msg.c diff --git a/osfmk/ipc/mach_msg.c b/osfmk/ipc/mach_msg.c index 2b4c67eb2..a12c70919 100644 --- a/osfmk/ipc/mach_msg.c +++ b/osfmk/ipc/mach_msg.c @@ -85,7 +85,6 @@ #include #include #include -#include #include #include #include @@ -104,13 +103,13 @@ #include #include #include +#include #include #include #include - #ifndef offsetof #define offsetof(type, member) ((size_t)(&((type *)0)->member)) #endif /* offsetof */ @@ -154,9 +153,14 @@ mach_msg_format_0_trailer_t trailer_template = { }; /* - * Routine: mach_msg_send + * Routine: mach_msg_send [Kernel Internal] * Purpose: - * Send a message. + * Routine for kernel-task threads to send a message. + * + * Unlike mach_msg_send_from_kernel(), this routine + * looks port names up in the kernel's port namespace + * and copies in the kernel virtual memory (instead + * of taking a vm_map_copy_t pointer for OOL descriptors). * Conditions: * Nothing locked. * Returns: @@ -217,14 +221,16 @@ mach_msg_send( trailer->msgh_audit = current_thread()->task->audit_token; trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0; trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE; - - mr = ipc_kmsg_copyin(kmsg, space, map, option & MACH_SEND_NOTIFY); + + mr = ipc_kmsg_copyin(kmsg, space, map, &option); + if (mr != MACH_MSG_SUCCESS) { ipc_kmsg_free(kmsg); return mr; } - mr = ipc_kmsg_send(kmsg, option & MACH_SEND_TIMEOUT, send_timeout); + mr = ipc_kmsg_send(kmsg, option, send_timeout); + if (mr != MACH_MSG_SUCCESS) { mr |= ipc_kmsg_copyout_pseudo(kmsg, space, map, MACH_MSG_BODY_NULL); (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, @@ -235,6 +241,20 @@ mach_msg_send( return mr; } +/* + * message header as seen at user-space + * (for MACH_RCV_LARGE/IDENTITY updating) + */ +typedef struct +{ + mach_msg_bits_t msgh_bits; + mach_msg_size_t msgh_size; + mach_port_name_t msgh_remote_port; + mach_port_name_t msgh_local_port; + mach_msg_size_t msgh_reserved; + mach_msg_id_t msgh_id; +} mach_msg_user_header_t; + /* * Routine: mach_msg_receive_results * Purpose: @@ -283,20 +303,36 @@ mach_msg_receive_results(void) * msize save area instead of the message (which was left on * the queue). */ + if (option & MACH_RCV_LARGE_IDENTITY) { + if (copyout((char *) &self->ith_receiver_name, + msg_addr + offsetof(mach_msg_user_header_t, msgh_local_port), + sizeof(mach_port_name_t))) + mr = MACH_RCV_INVALID_DATA; + } if (copyout((char *) &self->ith_msize, - msg_addr + offsetof(mach_msg_header_t, msgh_size), + msg_addr + offsetof(mach_msg_user_header_t, msgh_size), sizeof(mach_msg_size_t))) - mr = MACH_RCV_INVALID_DATA; - goto out; + mr = MACH_RCV_INVALID_DATA; + } else { + + /* discard importance in message */ + ipc_importance_clean(kmsg); + + if (msg_receive_error(kmsg, msg_addr, option, seqno, space) + == MACH_RCV_INVALID_DATA) + mr = MACH_RCV_INVALID_DATA; } - - if (msg_receive_error(kmsg, msg_addr, option, seqno, space) - == MACH_RCV_INVALID_DATA) - mr = MACH_RCV_INVALID_DATA; } - goto out; + return mr; } +#if IMPORTANCE_INHERITANCE + + /* adopt/transform any importance attributes carried in the message */ + ipc_importance_receive(kmsg, option); + +#endif /* IMPORTANCE_INHERITANCE */ + trailer_size = ipc_kmsg_add_trailer(kmsg, space, option, self, seqno, FALSE, kmsg->ikm_header->msgh_remote_port->ip_context); /* @@ -310,13 +346,16 @@ mach_msg_receive_results(void) mach_msg_body_t *slist; slist = ipc_kmsg_get_scatter(msg_addr, slist_size, kmsg); - mr = ipc_kmsg_copyout(kmsg, space, map, slist); + mr = ipc_kmsg_copyout(kmsg, space, map, slist, option); ipc_kmsg_free_scatter(slist, slist_size); } else { - mr = ipc_kmsg_copyout(kmsg, space, map, MACH_MSG_BODY_NULL); + mr = ipc_kmsg_copyout(kmsg, space, map, MACH_MSG_BODY_NULL, option); } if (mr != MACH_MSG_SUCCESS) { + /* already received importance, so have to undo that here */ + ipc_importance_unreceive(kmsg, option); + if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) { if (ipc_kmsg_put(msg_addr, kmsg, kmsg->ikm_header->msgh_size + trailer_size) == MACH_RCV_INVALID_DATA) @@ -327,16 +366,33 @@ mach_msg_receive_results(void) == MACH_RCV_INVALID_DATA) mr = MACH_RCV_INVALID_DATA; } - goto out; + } else { + mr = ipc_kmsg_put(msg_addr, + kmsg, + kmsg->ikm_header->msgh_size + + trailer_size); } - mr = ipc_kmsg_put(msg_addr, - kmsg, - kmsg->ikm_header->msgh_size + - trailer_size); - out: + return mr; } +/* + * Routine: mach_msg_receive [Kernel Internal] + * Purpose: + * Routine for kernel-task threads to actively receive a message. + * + * Unlike being dispatched to by ipc_kobject_server() or the + * reply part of mach_msg_rpc_from_kernel(), this routine + * looks up the receive port name in the kernel's port + * namespace and copies out received port rights to that namespace + * as well. Out-of-line memory is copied out the kernel's + * address space (rather than just providing the vm_map_copy_t). + * Conditions: + * Nothing locked. + * Returns: + * MACH_MSG_SUCCESS Received a message. + * See for list of MACH_RCV_XXX errors. + */ mach_msg_return_t mach_msg_receive( mach_msg_header_t *msg, @@ -408,7 +464,10 @@ mach_msg_overwrite_trap( mach_msg_return_t mr = MACH_MSG_SUCCESS; vm_map_t map = current_map(); - + + /* Only accept options allowed by the user */ + option &= MACH_MSG_OPTION_USER; + if (option & MACH_SEND_MSG) { ipc_space_t space = current_space(); ipc_kmsg_t kmsg; @@ -418,13 +477,14 @@ mach_msg_overwrite_trap( if (mr != MACH_MSG_SUCCESS) return mr; - mr = ipc_kmsg_copyin(kmsg, space, map, option & MACH_SEND_NOTIFY); + mr = ipc_kmsg_copyin(kmsg, space, map, &option); + if (mr != MACH_MSG_SUCCESS) { ipc_kmsg_free(kmsg); return mr; } - mr = ipc_kmsg_send(kmsg, option & MACH_SEND_TIMEOUT, msg_timeout); + mr = ipc_kmsg_send(kmsg, option, msg_timeout); if (mr != MACH_MSG_SUCCESS) { mr |= ipc_kmsg_copyout_pseudo(kmsg, space, map, MACH_MSG_BODY_NULL);