]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ipc/mach_msg.c
xnu-2782.1.97.tar.gz
[apple/xnu.git] / osfmk / ipc / mach_msg.c
index 2b4c67eb224daff2c1246557924726805dc98b71..a12c7091944902f024593a116e3c1c52c926c650 100644 (file)
@@ -85,7 +85,6 @@
 #include <kern/ipc_mig.h>
 #include <kern/task.h>
 #include <kern/thread.h>
 #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 <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_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>
 
 
 #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 */
 #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:
  *     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:
  *     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;
        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;
        }
 
        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, 
        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;
 }
 
        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:
 /*
  *     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).
               */
               * 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,
              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)))
                          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);
        /*
        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);
                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 {
                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) {
        }
 
        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)
                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;
                }
                                                == 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;
 }
 
        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
 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();
 
        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 (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;
 
                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;
                }
 
                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);
 
                if (mr != MACH_MSG_SUCCESS) {
                        mr |= ipc_kmsg_copyout_pseudo(kmsg, space, map, MACH_MSG_BODY_NULL);