--- Gnu-Mach/ipc/ipc_kmsg.c 2020/09/02 04:36:56 1.1 +++ Gnu-Mach/ipc/ipc_kmsg.c 2020/09/02 04:47:22 1.1.1.4 @@ -34,22 +34,23 @@ * Operations on kernel messages. */ -#include -#include -#include -#include +#include +#include #include #include #include #include +#include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -61,9 +62,12 @@ #include -extern int copyinmap(); -extern int copyoutmap(); -void ipc_msg_print(); /* forward */ +#include + +#if MACH_KDB +#include +#include +#endif #define is_misaligned(x) ( ((vm_offset_t)(x)) & (sizeof(vm_offset_t)-1) ) #define ptr_align(x) \ @@ -135,9 +139,7 @@ ipc_kmsg_rmqueue( next->ikm_prev = prev; prev->ikm_next = next; } - /* XXX Temporary debug logic */ - kmsg->ikm_next = IKM_BOGUS; - kmsg->ikm_prev = IKM_BOGUS; + ikm_mark_bogus (kmsg); } /* @@ -214,9 +216,9 @@ ipc_kmsg_destroy( */ void -ipc_kmsg_clean_body(saddr, eaddr) - vm_offset_t saddr; - vm_offset_t eaddr; +ipc_kmsg_clean_body( + vm_offset_t saddr, + vm_offset_t eaddr) { while (saddr < eaddr) { mach_msg_type_long_t *type; @@ -313,8 +315,7 @@ ipc_kmsg_clean_body(saddr, eaddr) */ void -ipc_kmsg_clean(kmsg) - ipc_kmsg_t kmsg; +ipc_kmsg_clean(ipc_kmsg_t kmsg) { ipc_marequest_t marequest; ipc_object_t object; @@ -357,11 +358,11 @@ ipc_kmsg_clean(kmsg) */ void -ipc_kmsg_clean_partial(kmsg, eaddr, dolast, number) - ipc_kmsg_t kmsg; - vm_offset_t eaddr; - boolean_t dolast; - mach_msg_type_number_t number; +ipc_kmsg_clean_partial( + ipc_kmsg_t kmsg, + vm_offset_t eaddr, + boolean_t dolast, + mach_msg_type_number_t number) { ipc_object_t object; mach_msg_bits_t mbits = kmsg->ikm_header.msgh_bits; @@ -462,18 +463,11 @@ xxx: type = (mach_msg_type_long_t *) ea */ void -ipc_kmsg_free(kmsg) - ipc_kmsg_t kmsg; +ipc_kmsg_free(ipc_kmsg_t kmsg) { vm_size_t size = kmsg->ikm_size; switch (size) { -#if NORMA_IPC - case IKM_SIZE_NORMA: - /* return it to the norma ipc code */ - norma_kmsg_put(kmsg); - break; -#endif NORMA_IPC case IKM_SIZE_NETWORK: /* return it to the network code */ @@ -502,10 +496,10 @@ ipc_kmsg_free(kmsg) */ mach_msg_return_t -ipc_kmsg_get(msg, size, kmsgp) - mach_msg_header_t *msg; - mach_msg_size_t size; - ipc_kmsg_t *kmsgp; +ipc_kmsg_get( + mach_msg_header_t *msg, + mach_msg_size_t size, + ipc_kmsg_t *kmsgp) { ipc_kmsg_t kmsg; @@ -530,7 +524,7 @@ ipc_kmsg_get(msg, size, kmsgp) ikm_init(kmsg, size); } - if (copyinmsg((char *) msg, (char *) &kmsg->ikm_header, size)) { + if (copyinmsg(msg, &kmsg->ikm_header, size)) { ikm_free(kmsg); return MACH_SEND_INVALID_DATA; } @@ -554,10 +548,10 @@ ipc_kmsg_get(msg, size, kmsgp) */ extern mach_msg_return_t -ipc_kmsg_get_from_kernel(msg, size, kmsgp) - mach_msg_header_t *msg; - mach_msg_size_t size; - ipc_kmsg_t *kmsgp; +ipc_kmsg_get_from_kernel( + mach_msg_header_t *msg, + mach_msg_size_t size, + ipc_kmsg_t *kmsgp) { ipc_kmsg_t kmsg; @@ -569,7 +563,7 @@ ipc_kmsg_get_from_kernel(msg, size, kmsg return MACH_SEND_NO_BUFFER; ikm_init(kmsg, size); - bcopy((char *) msg, (char *) &kmsg->ikm_header, size); + memcpy(&kmsg->ikm_header, msg, size); kmsg->ikm_header.msgh_size = size; *kmsgp = kmsg; @@ -591,16 +585,16 @@ ipc_kmsg_get_from_kernel(msg, size, kmsg */ mach_msg_return_t -ipc_kmsg_put(msg, kmsg, size) - mach_msg_header_t *msg; - ipc_kmsg_t kmsg; - mach_msg_size_t size; +ipc_kmsg_put( + mach_msg_header_t *msg, + ipc_kmsg_t kmsg, + mach_msg_size_t size) { mach_msg_return_t mr; ikm_check_initialized(kmsg, kmsg->ikm_size); - if (copyoutmsg((char *) &kmsg->ikm_header, (char *) msg, size)) + if (copyoutmsg(&kmsg->ikm_header, msg, size)) mr = MACH_RCV_INVALID_DATA; else mr = MACH_MSG_SUCCESS; @@ -634,7 +628,7 @@ ipc_kmsg_put_to_kernel( assert(!KMSG_IN_DIPC(kmsg)); #endif /* DIPC */ - (void) memcpy((void *) msg, (const void *) &kmsg->ikm_header, size); + memcpy(msg, &kmsg->ikm_header, size); ikm_free(kmsg); } @@ -659,13 +653,6 @@ ipc_kmsg_put_to_kernel( * notification would be sent to the named receive right, * then it isn't sent and the send-once right for the notify * port is quietly destroyed. - * - * [MACH_IPC_COMPAT] There is an atomicity problem if the - * reply port is a compat entry and dies at an inopportune - * time. This doesn't have any serious consequences - * (an observant user task might conceivably notice that - * the destination and reply ports were handled inconsistently), - * only happens in compat mode, and is extremely unlikely. * Conditions: * Nothing locked. * Returns: @@ -683,10 +670,10 @@ ipc_kmsg_put_to_kernel( */ mach_msg_return_t -ipc_kmsg_copyin_header(msg, space, notify) - mach_msg_header_t *msg; - ipc_space_t space; - mach_port_t notify; +ipc_kmsg_copyin_header( + mach_msg_header_t *msg, + ipc_space_t space, + mach_port_t notify) { mach_msg_bits_t mbits = msg->msgh_bits &~ MACH_MSGH_BITS_CIRCULAR; mach_port_t dest_name = msg->msgh_remote_port; @@ -1233,27 +1220,7 @@ ipc_kmsg_copyin_header(msg, space, notif kr = ipc_right_copyin(space, reply_name, reply_entry, reply_type, TRUE, &reply_port, &reply_soright); -#if MACH_IPC_COMPAT - if (kr != KERN_SUCCESS) { - assert(kr == KERN_INVALID_NAME); - - /* - * Oops. This must have been a compat entry - * and the port died after the check above. - * We should back out the copyin of dest_port, - * and report MACH_SEND_INVALID_REPLY, but - * if dest_port is alive we can't always do that. - * Punt and pretend we got IO_DEAD, skipping - * further hairy atomicity problems. - */ - - reply_port = IO_DEAD; - reply_soright = IP_NULL; - goto skip_reply_checks; - } -#else MACH_IPC_COMPAT assert(kr == KERN_SUCCESS); -#endif MACH_IPC_COMPAT if ((saved_reply != IP_NULL) && (reply_port == IO_DEAD)) { ipc_port_t dest = (ipc_port_t) dest_port; @@ -1314,15 +1281,6 @@ ipc_kmsg_copyin_header(msg, space, notif if (IE_BITS_TYPE(reply_entry->ie_bits) == MACH_PORT_TYPE_NONE) ipc_entry_dealloc(space, reply_name, reply_entry); -#if MACH_IPC_COMPAT - skip_reply_checks: - /* - * We jump here if the reply entry was a compat entry - * and the port died on us. In this case, the copyin - * code already deallocated reply_entry. - */ -#endif MACH_IPC_COMPAT - if (IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_NONE) ipc_entry_dealloc(space, dest_name, dest_entry); @@ -1377,15 +1335,14 @@ ipc_kmsg_copyin_header(msg, space, notif } mach_msg_return_t -ipc_kmsg_copyin_body(kmsg, space, map) - ipc_kmsg_t kmsg; - ipc_space_t space; - vm_map_t map; +ipc_kmsg_copyin_body( + ipc_kmsg_t kmsg, + ipc_space_t space, + vm_map_t map) { ipc_object_t dest; vm_offset_t saddr, eaddr; boolean_t complex; - mach_msg_return_t mr; boolean_t use_page_lists, steal_pages; dest = (ipc_object_t) kmsg->ikm_header.msgh_remote_port; @@ -1393,13 +1350,6 @@ ipc_kmsg_copyin_body(kmsg, space, map) use_page_lists = ipc_kobject_vm_page_list(ip_kotype((ipc_port_t)dest)); steal_pages = ipc_kobject_vm_page_steal(ip_kotype((ipc_port_t)dest)); -#if NORMA_IPC - if (IP_NORMA_IS_PROXY((ipc_port_t) dest)) { - use_page_lists = TRUE; - steal_pages = TRUE; - } -#endif NORMA_IPC - saddr = (vm_offset_t) (&kmsg->ikm_header + 1); eaddr = (vm_offset_t) &kmsg->ikm_header + kmsg->ikm_header.msgh_size; @@ -1411,7 +1361,7 @@ ipc_kmsg_copyin_body(kmsg, space, map) mach_msg_type_number_t number; boolean_t is_inline, longform, dealloc, is_port; vm_offset_t data; - vm_size_t length; + unsigned64_t length; kern_return_t kr; type = (mach_msg_type_long_t *) saddr; @@ -1462,7 +1412,7 @@ ipc_kmsg_copyin_body(kmsg, space, map) /* calculate length of data in bytes, rounding up */ - length = ((number * size) + 7) >> 3; + length = (((unsigned64_t) number * size) + 7) >> 3; if (is_inline) { vm_size_t amount; @@ -1482,7 +1432,7 @@ ipc_kmsg_copyin_body(kmsg, space, map) if (sizeof(vm_offset_t) > sizeof(mach_msg_type_t)) saddr = ptr_align(saddr); - + if ((eaddr - saddr) < sizeof(vm_offset_t)) { ipc_kmsg_clean_partial(kmsg, taddr, FALSE, 0); return MACH_SEND_MSG_TOO_SMALL; @@ -1605,11 +1555,11 @@ ipc_kmsg_copyin_body(kmsg, space, map) */ mach_msg_return_t -ipc_kmsg_copyin(kmsg, space, map, notify) - ipc_kmsg_t kmsg; - ipc_space_t space; - vm_map_t map; - mach_port_t notify; +ipc_kmsg_copyin( + ipc_kmsg_t kmsg, + ipc_space_t space, + vm_map_t map, + mach_port_t notify) { mach_msg_return_t mr; @@ -1640,8 +1590,7 @@ ipc_kmsg_copyin(kmsg, space, map, notify */ void -ipc_kmsg_copyin_from_kernel( - ipc_kmsg_t kmsg) +ipc_kmsg_copyin_from_kernel(ipc_kmsg_t kmsg) { mach_msg_bits_t bits = kmsg->ikm_header.msgh_bits; mach_msg_type_name_t rname = MACH_MSGH_BITS_REMOTE(bits); @@ -1786,7 +1735,7 @@ ipc_kmsg_copyin_from_kernel( * Nothing locked. * Returns: * MACH_MSG_SUCCESS Copied out port rights. - * MACH_RCV_INVALID_NOTIFY + * MACH_RCV_INVALID_NOTIFY * Notify is non-null and doesn't name a receive right. * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.) * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE @@ -1800,10 +1749,10 @@ ipc_kmsg_copyin_from_kernel( */ mach_msg_return_t -ipc_kmsg_copyout_header(msg, space, notify) - mach_msg_header_t *msg; - ipc_space_t space; - mach_port_t notify; +ipc_kmsg_copyout_header( + mach_msg_header_t *msg, + ipc_space_t space, + mach_port_t notify) { mach_msg_bits_t mbits = msg->msgh_bits; ipc_port_t dest = (ipc_port_t) msg->msgh_remote_port; @@ -1848,9 +1797,17 @@ ipc_kmsg_copyout_header(msg, space, noti } else ip_unlock(dest); - msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | - MACH_MSGH_BITS(0, MACH_MSG_TYPE_PORT_SEND)); - msg->msgh_local_port = dest_name; + if (! ipc_port_flag_protected_payload(dest)) { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(0, MACH_MSG_TYPE_PORT_SEND)); + msg->msgh_local_port = dest_name; + } else { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS( + 0, MACH_MSG_TYPE_PROTECTED_PAYLOAD)); + msg->msgh_protected_payload = + dest->ip_protected_payload; + } msg->msgh_remote_port = MACH_PORT_NULL; return MACH_MSG_SUCCESS; } @@ -1946,10 +1903,18 @@ ipc_kmsg_copyout_header(msg, space, noti } else ip_unlock(dest); - msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | - MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, - MACH_MSG_TYPE_PORT_SEND)); - msg->msgh_local_port = dest_name; + if (! ipc_port_flag_protected_payload(dest)) { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, + MACH_MSG_TYPE_PORT_SEND)); + msg->msgh_local_port = dest_name; + } else { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, + MACH_MSG_TYPE_PROTECTED_PAYLOAD)); + msg->msgh_protected_payload = + dest->ip_protected_payload; + } msg->msgh_remote_port = reply_name; return MACH_MSG_SUCCESS; } @@ -1981,9 +1946,18 @@ ipc_kmsg_copyout_header(msg, space, noti dest_name = MACH_PORT_NULL; } - msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | - MACH_MSGH_BITS(0, MACH_MSG_TYPE_PORT_SEND_ONCE)); - msg->msgh_local_port = dest_name; + if (! ipc_port_flag_protected_payload(dest)) { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(0, + MACH_MSG_TYPE_PORT_SEND_ONCE)); + msg->msgh_local_port = dest_name; + } else { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(0, + MACH_MSG_TYPE_PROTECTED_PAYLOAD)); + msg->msgh_protected_payload = + dest->ip_protected_payload; + } msg->msgh_remote_port = MACH_PORT_NULL; return MACH_MSG_SUCCESS; } @@ -2273,9 +2247,16 @@ ipc_kmsg_copyout_header(msg, space, noti if (IP_VALID(reply)) ipc_port_release(reply); - msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | - MACH_MSGH_BITS(reply_type, dest_type)); - msg->msgh_local_port = dest_name; + if (! ipc_port_flag_protected_payload(dest)) { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(reply_type, dest_type)); + msg->msgh_local_port = dest_name; + } else { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(reply_type, + MACH_MSG_TYPE_PROTECTED_PAYLOAD)); + msg->msgh_protected_payload = dest->ip_protected_payload; + } msg->msgh_remote_port = reply_name; } @@ -2300,11 +2281,11 @@ ipc_kmsg_copyout_header(msg, space, noti */ mach_msg_return_t -ipc_kmsg_copyout_object(space, object, msgt_name, namep) - ipc_space_t space; - ipc_object_t object; - mach_msg_type_name_t msgt_name; - mach_port_t *namep; +ipc_kmsg_copyout_object( + ipc_space_t space, + ipc_object_t object, + mach_msg_type_name_t msgt_name, + mach_port_t *namep) { if (!IO_VALID(object)) { *namep = (mach_port_t) object; @@ -2322,7 +2303,7 @@ ipc_kmsg_copyout_object(space, object, m goto slow_copyout; { - register ipc_port_t port = (ipc_port_t) object; + ipc_port_t port = (ipc_port_t) object; ipc_entry_t entry; is_write_lock(space); @@ -2355,7 +2336,7 @@ ipc_kmsg_copyout_object(space, object, m assert(IE_BITS_UREFS(entry->ie_bits) < MACH_PORT_UREFS_MAX); { - register ipc_entry_bits_t bits = entry->ie_bits + 1; + ipc_entry_bits_t bits = entry->ie_bits + 1; if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) entry->ie_bits = bits; @@ -2410,10 +2391,11 @@ ipc_kmsg_copyout_object(space, object, m */ mach_msg_return_t -ipc_kmsg_copyout_body(saddr, eaddr, space, map) - vm_offset_t saddr, eaddr; - ipc_space_t space; - vm_map_t map; +ipc_kmsg_copyout_body( + vm_offset_t saddr, + vm_offset_t eaddr, + ipc_space_t space, + vm_map_t map) { mach_msg_return_t mr = MACH_MSG_SUCCESS; kern_return_t kr; @@ -2425,7 +2407,7 @@ ipc_kmsg_copyout_body(saddr, eaddr, spac mach_msg_type_size_t size; mach_msg_type_number_t number; boolean_t is_inline, longform, is_port; - vm_size_t length; + unsigned64_t length; vm_offset_t addr; type = (mach_msg_type_long_t *) saddr; @@ -2456,7 +2438,7 @@ ipc_kmsg_copyout_body(saddr, eaddr, spac /* calculate length of data in bytes, rounding up */ - length = ((number * size) + 7) >> 3; + length = (((unsigned64_t) number * size) + 7) >> 3; is_port = MACH_MSG_TYPE_PORT_ANY(name); @@ -2562,11 +2544,11 @@ ipc_kmsg_copyout_body(saddr, eaddr, spac */ mach_msg_return_t -ipc_kmsg_copyout(kmsg, space, map, notify) - ipc_kmsg_t kmsg; - ipc_space_t space; - vm_map_t map; - mach_port_t notify; +ipc_kmsg_copyout( + ipc_kmsg_t kmsg, + ipc_space_t space, + vm_map_t map, + mach_port_t notify) { mach_msg_bits_t mbits = kmsg->ikm_header.msgh_bits; mach_msg_return_t mr; @@ -2656,9 +2638,9 @@ ipc_kmsg_copyout_pseudo( */ void -ipc_kmsg_copyout_dest(kmsg, space) - ipc_kmsg_t kmsg; - ipc_space_t space; +ipc_kmsg_copyout_dest( + ipc_kmsg_t kmsg, + ipc_space_t space) { mach_msg_bits_t mbits = kmsg->ikm_header.msgh_bits; ipc_object_t dest = (ipc_object_t) kmsg->ikm_header.msgh_remote_port; @@ -2701,589 +2683,76 @@ ipc_kmsg_copyout_dest(kmsg, space) } } -#if NORMA_IPC || NORMA_VM -/* - * Routine: ipc_kmsg_copyout_to_kernel - * Purpose: - * Copies out the destination and reply ports in the message. - * Leaves all other rights and memory in the message alone. - * Conditions: - * Nothing locked. - * - * Derived from ipc_kmsg_copyout_dest. - * Use by mach_msg_rpc_from_kernel (which used to use copyout_dest). - * We really do want to save rights and memory. - */ - -void -ipc_kmsg_copyout_to_kernel(kmsg, space) - ipc_kmsg_t kmsg; - ipc_space_t space; -{ - mach_msg_bits_t mbits = kmsg->ikm_header.msgh_bits; - ipc_object_t dest = (ipc_object_t) kmsg->ikm_header.msgh_remote_port; - ipc_object_t reply = (ipc_object_t) kmsg->ikm_header.msgh_local_port; - mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits); - mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits); - mach_port_t dest_name, reply_name; - - assert(IO_VALID(dest)); - - io_lock(dest); - if (io_active(dest)) { - ipc_object_copyout_dest(space, dest, dest_type, &dest_name); - /* dest is unlocked */ - } else { - io_release(dest); - io_check_unlock(dest); - dest_name = MACH_PORT_DEAD; - } - - reply_name = (mach_port_t) reply; - - kmsg->ikm_header.msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | - MACH_MSGH_BITS(reply_type, dest_type)); - kmsg->ikm_header.msgh_local_port = dest_name; - kmsg->ikm_header.msgh_remote_port = reply_name; -} -#endif NORMA_IPC || NORMA_VM - -#if MACH_IPC_COMPAT - -/* - * Routine: ipc_kmsg_copyin_compat - * Purpose: - * "Copy-in" port rights and out-of-line memory - * in the message. - * - * In all failure cases, the message is left holding - * no rights or memory. However, the message buffer - * is not deallocated. If successful, the message - * contains a valid destination port. - * Conditions: - * Nothing locked. - * Returns: - * MACH_MSG_SUCCESS Successful copyin. - * MACH_SEND_INVALID_DEST Can't copyin destination port. - * MACH_SEND_INVALID_REPLY Can't copyin reply port. - * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory. - * MACH_SEND_INVALID_RIGHT Can't copyin port right in body. - * MACH_SEND_INVALID_TYPE Bad type specification. - * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data. - */ - -mach_msg_return_t -ipc_kmsg_copyin_compat(kmsg, space, map) - ipc_kmsg_t kmsg; - ipc_space_t space; - vm_map_t map; -{ - msg_header_t msg; - mach_port_t dest_name; - mach_port_t reply_name; - ipc_object_t dest, reply; - mach_msg_type_name_t dest_type, reply_type; - vm_offset_t saddr, eaddr; - boolean_t complex; - kern_return_t kr; - boolean_t use_page_lists, steal_pages; - - msg = * (msg_header_t *) &kmsg->ikm_header; - dest_name = (mach_port_t) msg.msg_remote_port; - reply_name = (mach_port_t) msg.msg_local_port; - - /* translate the destination and reply ports */ - - kr = ipc_object_copyin_header(space, dest_name, &dest, &dest_type); - if (kr != KERN_SUCCESS) - return MACH_SEND_INVALID_DEST; - - if (reply_name == MACH_PORT_NULL) { - reply = IO_NULL; - reply_type = 0; - } else { - kr = ipc_object_copyin_header(space, reply_name, - &reply, &reply_type); - if (kr != KERN_SUCCESS) { - ipc_object_destroy(dest, dest_type); - return MACH_SEND_INVALID_REPLY; - } - } - - kmsg->ikm_header.msgh_bits = MACH_MSGH_BITS(dest_type, reply_type); - kmsg->ikm_header.msgh_size = (mach_msg_size_t) msg.msg_size; - kmsg->ikm_header.msgh_remote_port = (mach_port_t) dest; - kmsg->ikm_header.msgh_local_port = (mach_port_t) reply; - kmsg->ikm_header.msgh_seqno = (mach_msg_kind_t) msg.msg_type; - kmsg->ikm_header.msgh_id = (mach_msg_id_t) msg.msg_id; - - if (msg.msg_simple) - return MACH_MSG_SUCCESS; - - complex = FALSE; - use_page_lists = ipc_kobject_vm_page_list(ip_kotype((ipc_port_t)dest)); - steal_pages = ipc_kobject_vm_page_steal(ip_kotype((ipc_port_t)dest)); - -#if NORMA_IPC - if (IP_NORMA_IS_PROXY((ipc_port_t) dest)) { - use_page_lists = TRUE; - steal_pages = TRUE; - } -#endif NORMA_IPC - - saddr = (vm_offset_t) (&kmsg->ikm_header + 1); - eaddr = (vm_offset_t) &kmsg->ikm_header + kmsg->ikm_header.msgh_size; - - while (saddr < eaddr) { - vm_offset_t taddr = saddr; - mach_msg_type_long_t *type; - mach_msg_type_name_t name; - mach_msg_type_size_t size; - mach_msg_type_number_t number; - boolean_t is_inline, longform, dealloc, is_port; - vm_offset_t data; - vm_size_t length; - - type = (mach_msg_type_long_t *) saddr; - - if (((eaddr - saddr) < sizeof(mach_msg_type_t)) || - ((longform = ((mach_msg_type_t*)type)->msgt_longform) && - ((eaddr - saddr) < sizeof(mach_msg_type_long_t)))) { - ipc_kmsg_clean_partial(kmsg, taddr, FALSE, 0); - return MACH_SEND_MSG_TOO_SMALL; - } - - is_inline = ((mach_msg_type_t*)type)->msgt_inline; - dealloc = ((mach_msg_type_t*)type)->msgt_deallocate; - if (longform) { - /* This must be aligned */ - if ((sizeof(natural_t) > sizeof(mach_msg_type_t)) && - (is_misaligned(type))) { - saddr = ptr_align(saddr); - continue; - } - name = type->msgtl_name; - size = type->msgtl_size; - number = type->msgtl_number; - saddr += sizeof(mach_msg_type_long_t); - } else { - name = ((mach_msg_type_t*)type)->msgt_name; - size = ((mach_msg_type_t*)type)->msgt_size; - number = ((mach_msg_type_t*)type)->msgt_number; - saddr += sizeof(mach_msg_type_t); - } - - is_port = MSG_TYPE_PORT_ANY(name); - - if (is_port && (size != PORT_T_SIZE_IN_BITS)) { - ipc_kmsg_clean_partial(kmsg, taddr, FALSE, 0); - return MACH_SEND_INVALID_TYPE; - } - - /* - * New IPC says these should be zero, but old IPC - * tasks often leave them with random values. So - * we have to clear them. - */ - - ((mach_msg_type_t*)type)->msgt_unused = 0; - if (longform) { - type->msgtl_header.msgt_name = 0; - type->msgtl_header.msgt_size = 0; - type->msgtl_header.msgt_number = 0; - } - - /* padding (ptrs and ports) ? */ - if ((sizeof(natural_t) > sizeof(mach_msg_type_t)) && - ((size >> 3) == sizeof(natural_t))) - saddr = ptr_align(saddr); - - /* calculate length of data in bytes, rounding up */ - - length = ((number * size) + 7) >> 3; - - if (is_inline) { - vm_size_t amount; - - /* inline data sizes round up to int boundaries */ - - amount = (length + 3) &~ 3; - if ((eaddr - saddr) < amount) { - ipc_kmsg_clean_partial(kmsg, taddr, FALSE, 0); - return MACH_SEND_MSG_TOO_SMALL; - } - - data = saddr; - saddr += amount; - } else { - vm_offset_t addr; - - if ((eaddr - saddr) < sizeof(vm_offset_t)) { - ipc_kmsg_clean_partial(kmsg, taddr, FALSE, 0); - return MACH_SEND_MSG_TOO_SMALL; - } - - /* grab the out-of-line data */ - - addr = * (vm_offset_t *) saddr; - - if (length == 0) - data = 0; - else if (is_port) { - data = kalloc(length); - if (data == 0) - goto invalid_memory; - - if (copyinmap(map, (char *) addr, - (char *) data, length) || - (dealloc && - (vm_deallocate(map, addr, length) != - KERN_SUCCESS))) { - kfree(data, length); - goto invalid_memory; - } - } else { - vm_map_copy_t copy; - - if (use_page_lists) { - kr = vm_map_copyin_page_list(map, - addr, length, dealloc, - steal_pages, ©, FALSE); - } else { - kr = vm_map_copyin(map, addr, length, - dealloc, - ©); - } - if (kr != KERN_SUCCESS) { - invalid_memory: - ipc_kmsg_clean_partial(kmsg, taddr, - FALSE, 0); - return MACH_SEND_INVALID_MEMORY; - } - - data = (vm_offset_t) copy; - } - - * (vm_offset_t *) saddr = data; - saddr += sizeof(vm_offset_t); - complex = TRUE; - } - - if (is_port) { - mach_msg_type_name_t newname = - ipc_object_copyin_type(name); - ipc_object_t *objects = (ipc_object_t *) data; - mach_msg_type_number_t i; - - if (longform) - type->msgtl_name = newname; - else - ((mach_msg_type_t*)type)->msgt_name = newname; - - for (i = 0; i < number; i++) { - mach_port_t port = (mach_port_t) objects[i]; - ipc_object_t object; - - if (!MACH_PORT_VALID(port)) - continue; - - kr = ipc_object_copyin_compat(space, port, - name, dealloc, &object); - if (kr != KERN_SUCCESS) { - ipc_kmsg_clean_partial(kmsg, taddr, - TRUE, i); - return MACH_SEND_INVALID_RIGHT; - } - - if ((newname == MACH_MSG_TYPE_PORT_RECEIVE) && - ipc_port_check_circularity( - (ipc_port_t) object, - (ipc_port_t) dest)) - kmsg->ikm_header.msgh_bits |= - MACH_MSGH_BITS_CIRCULAR; - - objects[i] = object; - } - - complex = TRUE; - } - } - - if (complex) - kmsg->ikm_header.msgh_bits |= MACH_MSGH_BITS_COMPLEX; - - return MACH_MSG_SUCCESS; -} - -/* - * Routine: ipc_kmsg_copyout_compat - * Purpose: - * "Copy-out" port rights and out-of-line memory - * in the message, producing an old IPC message. - * - * Doesn't bother to handle the header atomically. - * Skips over errors. Problem ports produce MACH_PORT_NULL - * (MACH_PORT_DEAD is never produced), and problem memory - * produces a zero address. - * Conditions: - * Nothing locked. - * Returns: - * MACH_MSG_SUCCESS Copied out rights and memory. - */ - -mach_msg_return_t -ipc_kmsg_copyout_compat(kmsg, space, map) - ipc_kmsg_t kmsg; - ipc_space_t space; - vm_map_t map; -{ - msg_header_t msg; - mach_msg_bits_t mbits = kmsg->ikm_header.msgh_bits; - ipc_object_t dest = (ipc_object_t) kmsg->ikm_header.msgh_remote_port; - ipc_object_t reply = (ipc_object_t) kmsg->ikm_header.msgh_local_port; - mach_port_t dest_name, reply_name; - vm_offset_t saddr, eaddr; - kern_return_t kr; - - assert(IO_VALID(dest)); - - io_lock(dest); - if (io_active(dest)) { - mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits); - - ipc_object_copyout_dest(space, dest, dest_type, &dest_name); - /* dest is unlocked */ - } else { - io_release(dest); - io_check_unlock(dest); - dest_name = MACH_PORT_NULL; - } - - if (IO_VALID(reply)) { - mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits); - - kr = ipc_object_copyout_compat(space, reply, reply_type, - &reply_name); - if (kr != KERN_SUCCESS) { - ipc_object_destroy(reply, reply_type); - reply_name = MACH_PORT_NULL; - } - } else - reply_name = MACH_PORT_NULL; - - msg.msg_unused = 0; - msg.msg_simple = (mbits & MACH_MSGH_BITS_COMPLEX) ? FALSE : TRUE; - msg.msg_size = (msg_size_t) kmsg->ikm_header.msgh_size; - msg.msg_type = (integer_t) kmsg->ikm_header.msgh_seqno; - msg.msg_local_port = (port_name_t) dest_name; - msg.msg_remote_port = (port_name_t) reply_name; - msg.msg_id = (integer_t) kmsg->ikm_header.msgh_id; - * (msg_header_t *) &kmsg->ikm_header = msg; - - if (msg.msg_simple) - return MACH_MSG_SUCCESS; - - saddr = (vm_offset_t) (&kmsg->ikm_header + 1); - eaddr = (vm_offset_t) &kmsg->ikm_header + kmsg->ikm_header.msgh_size; - - while (saddr < eaddr) { - vm_offset_t taddr = saddr; - mach_msg_type_long_t *type; - mach_msg_type_name_t name; - mach_msg_type_size_t size; - mach_msg_type_number_t number; - boolean_t is_inline, longform, is_port; - vm_size_t length; - vm_offset_t addr; - - type = (mach_msg_type_long_t *) saddr; - is_inline = ((mach_msg_type_t*)type)->msgt_inline; - longform = ((mach_msg_type_t*)type)->msgt_longform; - if (longform) { - /* This must be aligned */ - if ((sizeof(natural_t) > sizeof(mach_msg_type_t)) && - (is_misaligned(type))) { - saddr = ptr_align(saddr); - continue; - } - name = type->msgtl_name; - size = type->msgtl_size; - number = type->msgtl_number; - saddr += sizeof(mach_msg_type_long_t); - } else { - name = ((mach_msg_type_t*)type)->msgt_name; - size = ((mach_msg_type_t*)type)->msgt_size; - number = ((mach_msg_type_t*)type)->msgt_number; - saddr += sizeof(mach_msg_type_t); - } - - /* padding (ptrs and ports) ? */ - if ((sizeof(natural_t) > sizeof(mach_msg_type_t)) && - ((size >> 3) == sizeof(natural_t))) - saddr = ptr_align(saddr); - - /* calculate length of data in bytes, rounding up */ - - length = ((number * size) + 7) >> 3; - - is_port = MACH_MSG_TYPE_PORT_ANY(name); - - if (is_port) { - mach_port_t *objects; - mach_msg_type_number_t i; - mach_msg_type_name_t newname; - - if (!is_inline && (length != 0)) { - /* first allocate memory in the map */ - - kr = vm_allocate(map, &addr, length, TRUE); - if (kr != KERN_SUCCESS) { - ipc_kmsg_clean_body(taddr, saddr); - goto vm_copyout_failure; - } - } - - newname = ipc_object_copyout_type_compat(name); - if (longform) - type->msgtl_name = newname; - else - ((mach_msg_type_t*)type)->msgt_name = newname; - - objects = (mach_port_t *) - (is_inline ? saddr : * (vm_offset_t *) saddr); - - /* copyout port rights carried in the message */ - - for (i = 0; i < number; i++) { - ipc_object_t object = - (ipc_object_t) objects[i]; - - if (!IO_VALID(object)) { - objects[i] = MACH_PORT_NULL; - continue; - } - - kr = ipc_object_copyout_compat(space, object, - name, &objects[i]); - if (kr != KERN_SUCCESS) { - ipc_object_destroy(object, name); - objects[i] = MACH_PORT_NULL; - } - } - } - - if (is_inline) { - /* inline data sizes round up to int boundaries */ - - saddr += (length + 3) &~ 3; - } else { - vm_offset_t data = * (vm_offset_t *) saddr; - - /* copyout memory carried in the message */ - - if (length == 0) { - assert(data == 0); - addr = 0; - } else if (is_port) { - /* copyout to memory allocated above */ - - (void) copyoutmap(map, (char *) data, - (char *) addr, length); - kfree(data, length); - } else { - vm_map_copy_t copy = (vm_map_copy_t) data; - - kr = vm_map_copyout(map, &addr, copy); - if (kr != KERN_SUCCESS) { - vm_map_copy_discard(copy); - - vm_copyout_failure: - - addr = 0; - } - } - - * (vm_offset_t *) saddr = addr; - saddr += sizeof(vm_offset_t); - } - } - - return MACH_MSG_SUCCESS; -} - -#endif MACH_IPC_COMPAT - -#include #if MACH_KDB char * -ipc_type_name(type_name, received) - int type_name; - boolean_t received; +ipc_type_name( + int type_name, + boolean_t received) { switch (type_name) { case MACH_MSG_TYPE_BOOLEAN: return "boolean"; - + case MACH_MSG_TYPE_INTEGER_16: return "short"; - + case MACH_MSG_TYPE_INTEGER_32: return "int32"; case MACH_MSG_TYPE_INTEGER_64: return "int64"; - + case MACH_MSG_TYPE_CHAR: return "char"; - + case MACH_MSG_TYPE_BYTE: return "byte"; - + case MACH_MSG_TYPE_REAL: return "real"; - + case MACH_MSG_TYPE_STRING: return "string"; - + case MACH_MSG_TYPE_PORT_NAME: return "port_name"; - + case MACH_MSG_TYPE_MOVE_RECEIVE: if (received) { return "port_receive"; } else { return "move_receive"; } - + case MACH_MSG_TYPE_MOVE_SEND: if (received) { return "port_send"; } else { return "move_send"; } - + case MACH_MSG_TYPE_MOVE_SEND_ONCE: if (received) { return "port_send_once"; } else { return "move_send_once"; } - + case MACH_MSG_TYPE_COPY_SEND: return "copy_send"; - + case MACH_MSG_TYPE_MAKE_SEND: return "make_send"; - + case MACH_MSG_TYPE_MAKE_SEND_ONCE: return "make_send_once"; - + default: return (char *) 0; } } - + void ipc_print_type_name( int type_name) @@ -3300,8 +2769,7 @@ ipc_print_type_name( * ipc_kmsg_print [ debug ] */ void -ipc_kmsg_print(kmsg) - ipc_kmsg_t kmsg; +ipc_kmsg_print(ipc_kmsg_t kmsg) { db_printf("kmsg=0x%x\n", kmsg); db_printf("ikm_next=0x%x,prev=0x%x,size=%d,marequest=0x%x", @@ -3309,13 +2777,7 @@ ipc_kmsg_print(kmsg) kmsg->ikm_prev, kmsg->ikm_size, kmsg->ikm_marequest); -#if NORMA_IPC - db_printf(",page=0x%x,copy=0x%x\n", - kmsg->ikm_page, - kmsg->ikm_copy); -#else NORMA_IPC db_printf("\n"); -#endif NORMA_IPC ipc_msg_print(&kmsg->ikm_header); } @@ -3323,8 +2785,7 @@ ipc_kmsg_print(kmsg) * ipc_msg_print [ debug ] */ void -ipc_msg_print(msgh) - mach_msg_header_t *msgh; +ipc_msg_print(mach_msg_header_t *msgh) { vm_offset_t saddr, eaddr; @@ -3481,4 +2942,4 @@ ipc_msg_print(msgh) } } } -#endif MACH_KDB +#endif /* MACH_KDB */