]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ipc/mach_msg.c
xnu-3247.1.106.tar.gz
[apple/xnu.git] / osfmk / ipc / mach_msg.c
index 2b4c67eb224daff2c1246557924726805dc98b71..98282d7304f4506838bf4c791ccc550f35a26607 100644 (file)
@@ -85,7 +85,6 @@
 #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 */
@@ -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,40 +303,44 @@ 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);
-       /*
-        * If MACH_RCV_OVERWRITE was specified, try to get the scatter
-        * list and verify it against the contents of the message.  If
-        * there is any problem with it, we will continue without it as
-        * normal.
-        */
-       if (option & MACH_RCV_OVERWRITE) {
-               mach_msg_size_t slist_size = self->ith_scatter_list_size;
-               mach_msg_body_t *slist;
-
-               slist = ipc_kmsg_get_scatter(msg_addr, slist_size, kmsg);
-               mr = ipc_kmsg_copyout(kmsg, space, map, slist);
-               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 +351,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 <mach/message.h> for list of MACH_RCV_XXX errors.
+ */
 mach_msg_return_t
 mach_msg_receive(
        mach_msg_header_t       *msg,
@@ -345,7 +386,7 @@ mach_msg_receive(
        mach_port_name_t        rcv_name,
        mach_msg_timeout_t      rcv_timeout,
        void                    (*continuation)(mach_msg_return_t),
-       mach_msg_size_t         slist_size)
+       __unused mach_msg_size_t slist_size)
 {
        thread_t self = current_thread();
        ipc_space_t space = current_space();
@@ -363,7 +404,6 @@ mach_msg_receive(
        self->ith_object = object;
        self->ith_msize = rcv_size;
        self->ith_option = option;
-       self->ith_scatter_list_size = slist_size;
        self->ith_continuation = continuation;
 
        ipc_mqueue_receive(mqueue, option, rcv_size, rcv_timeout, THREAD_ABORTSAFE);
@@ -403,12 +443,14 @@ mach_msg_overwrite_trap(
        mach_msg_timeout_t      msg_timeout = args->timeout;
        __unused mach_port_name_t notify = args->notify;
        mach_vm_address_t       rcv_msg_addr = args->rcv_msg;
-        mach_msg_size_t                scatter_list_size = 0; /* NOT INITIALIZED - but not used in pactice */
        __unused mach_port_seqno_t temp_seqno = 0;
 
        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 +460,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);
@@ -446,22 +489,13 @@ mach_msg_overwrite_trap(
                }
                /* hold ref for object */
 
-               /*
-                * 1. MACH_RCV_OVERWRITE is on, and rcv_msg is our scatter list
-                *    and receive buffer
-                * 2. MACH_RCV_OVERWRITE is off, and rcv_msg might be the
-                *    alternate receive buffer (separate send and receive buffers).
-                */
-               if (option & MACH_RCV_OVERWRITE) 
-                       self->ith_msg_addr = rcv_msg_addr;
-               else if (rcv_msg_addr != (mach_vm_address_t)0)
+               if (rcv_msg_addr != (mach_vm_address_t)0)
                        self->ith_msg_addr = rcv_msg_addr;
                else
                        self->ith_msg_addr = msg_addr;
                self->ith_object = object;
                self->ith_msize = rcv_size;
                self->ith_option = option;
-               self->ith_scatter_list_size = scatter_list_size;
                self->ith_receiver_name = MACH_PORT_NULL;
                self->ith_continuation = thread_syscall_return;