#include <kern/ipc_mig.h>
#include <kern/task.h>
#include <kern/thread.h>
-#include <kern/lock.h>
#include <kern/sched_prim.h>
#include <kern/exception.h>
#include <kern/misc_protos.h>
#include <ipc/ipc_pset.h>
#include <ipc/ipc_space.h>
#include <ipc/ipc_entry.h>
+#include <ipc/ipc_importance.h>
#include <machine/machine_routines.h>
#include <security/mac_mach_internal.h>
#include <sys/kdebug.h>
-
#ifndef offsetof
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
#endif /* offsetof */
};
/*
- * 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:
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,
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:
* 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);
/*
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)
== 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 <mach/message.h> for list of MACH_RCV_XXX errors.
+ */
mach_msg_return_t
mach_msg_receive(
mach_msg_header_t *msg,
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;
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);