]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ipc/ipc_kmsg.c
xnu-3248.20.55.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_kmsg.c
index 1005a37d9b5512500596eb1520641eeb83c2838c..f5737416afa4c434aa8ea783fdbfff673de47e7f 100644 (file)
@@ -397,7 +397,7 @@ mm_copy_options_string64(
                name = "VIRTUAL";
                break;
            case MACH_MSG_OVERWRITE:
-               name = "OVERWRITE";
+               name = "OVERWRITE(DEPRECATED)";
                break;
            case MACH_MSG_ALLOCATE:
                name = "ALLOCATE";
@@ -1373,9 +1373,20 @@ ipc_kmsg_send(
        mach_msg_timeout_t      send_timeout)
 {
        ipc_port_t port;
+       thread_t th = current_thread();
        mach_msg_return_t error = MACH_MSG_SUCCESS;
+       boolean_t kernel_reply = FALSE;
        spl_t s;
 
+       /* Check if honor qlimit flag is set on thread. */
+       if ((th->options & TH_OPT_HONOR_QLIMIT) == TH_OPT_HONOR_QLIMIT) {
+               /* Remove the MACH_SEND_ALWAYS flag to honor queue limit. */
+               option &= (~MACH_SEND_ALWAYS);
+               /* Add the timeout flag since the message queue might be full. */
+               option |= MACH_SEND_TIMEOUT;
+               th->options &= (~TH_OPT_HONOR_QLIMIT);
+       }
+
 #if IMPORTANCE_INHERITANCE
        boolean_t did_importance = FALSE;
 #if IMPORTANCE_DEBUG
@@ -1435,6 +1446,7 @@ retry:
                assert(IP_VALID(port));
                ip_lock(port);
                /* fall thru with reply - same options */
+               kernel_reply = TRUE;
        }
 
 #if IMPORTANCE_INHERITANCE
@@ -1495,7 +1507,7 @@ retry:
                }
 #if IMPORTANCE_DEBUG
                KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (IMPORTANCE_CODE(IMP_MSG, IMP_MSG_SEND)) | DBG_FUNC_END,
-                                         audit_token_pid_from_task(current_task()), sender_pid, imp_msgh_id, importance_cleared, 0);
+                                         task_pid(current_task()), sender_pid, imp_msgh_id, importance_cleared, 0);
 #endif /* IMPORTANCE_DEBUG */
        }
 #endif /* IMPORTANCE_INHERITANCE */
@@ -1510,6 +1522,18 @@ retry:
                ipc_kmsg_destroy(kmsg);
                return MACH_MSG_SUCCESS;
        }
+
+       if (error != MACH_MSG_SUCCESS && kernel_reply) {
+               /*
+                * Kernel reply messages that fail can't be allowed to
+                * pseudo-receive on error conditions. We need to just treat
+                * the message as a successful delivery.
+                */
+               ip_release(port); /* JMM - Future: release right, not just ref */
+               kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
+               ipc_kmsg_destroy(kmsg);
+               return MACH_MSG_SUCCESS;
+       }
        return error;
 }
 
@@ -1670,17 +1694,11 @@ ipc_kmsg_copyin_header(
        ipc_entry_t reply_entry = IE_NULL;
        ipc_entry_t voucher_entry = IE_NULL;
 
-#if IMPORTANCE_INHERITANCE
        int assertcnt = 0;
+#if IMPORTANCE_INHERITANCE
        boolean_t needboost = FALSE;
 #endif /* IMPORTANCE_INHERITANCE */
 
-       queue_head_t links_data;
-       queue_t links = &links_data;
-       wait_queue_link_t wql;
-
-       queue_init(links);
-
        if ((mbits != msg->msgh_bits) ||
            (!MACH_MSG_TYPE_PORT_ANY_SEND(dest_type)) ||
            ((reply_type == 0) ?
@@ -1796,21 +1814,11 @@ ipc_kmsg_copyin_header(
                 *      Perform the delayed reply right copyin (guaranteed success).
                 */
                if (reply_entry != IE_NULL) {
-#if IMPORTANCE_INHERITANCE
                        kr = ipc_right_copyin(space, reply_name, reply_entry,
                                              reply_type, TRUE,
                                              &reply_port, &reply_soright,
-                                             &release_port,
-                                             &assertcnt,
-                                             links);
+                                             &release_port, &assertcnt);
                        assert(assertcnt == 0);
-#else
-                       kr = ipc_right_copyin(space, reply_name, reply_entry,
-                                             reply_type, TRUE,
-                                             &reply_port, &reply_soright,
-                                             &release_port,
-                                             links);
-#endif /* IMPORTANCE_INHERITANCE */
                        assert(kr == KERN_SUCCESS);
                }
 
@@ -1901,21 +1909,11 @@ ipc_kmsg_copyin_header(
                        /*
                         *      copyin the destination.
                         */
-#if IMPORTANCE_INHERITANCE
                        kr = ipc_right_copyin(space, dest_name, dest_entry,
                                              dest_type, FALSE,
                                              &dest_port, &dest_soright,
-                                             &release_port,
-                                             &assertcnt,
-                                             links);
+                                             &release_port, &assertcnt);
                        assert(assertcnt == 0);
-#else
-                       kr = ipc_right_copyin(space, dest_name, dest_entry,
-                                             dest_type, FALSE,
-                                             &dest_port, &dest_soright,
-                                             &release_port,
-                                             links);
-#endif /* IMPORTANCE_INHERITANCE */
                        if (kr != KERN_SUCCESS) {
                                goto invalid_dest;
                        }
@@ -1927,21 +1925,11 @@ ipc_kmsg_copyin_header(
                         *      It's OK if the reply right has gone dead in the meantime.
                         */
                        if (MACH_PORT_VALID(reply_name)) {
-#if IMPORTANCE_INHERITANCE
                                kr = ipc_right_copyin(space, reply_name, reply_entry,
                                                      reply_type, TRUE,
                                                      &reply_port, &reply_soright,
-                                                     &release_port,
-                                                     &assertcnt,
-                                                     links);
+                                                     &release_port, &assertcnt);
                                assert(assertcnt == 0);
-#else
-                               kr = ipc_right_copyin(space, reply_name, reply_entry,
-                                                     reply_type, TRUE,
-                                                     &reply_port, &reply_soright,
-                                                     &release_port,
-                                                     links);
-#endif /* IMPORTANCE_INHERITANCE */
                                assert(kr == KERN_SUCCESS);
                        } else {
                                /* convert invalid name to equivalent ipc_object type */
@@ -1954,23 +1942,13 @@ ipc_kmsg_copyin_header(
                 * are fully copied in (guaranteed success).
                 */
                if (IE_NULL != voucher_entry) {
-#if IMPORTANCE_INHERITANCE
                        kr = ipc_right_copyin(space, voucher_name, voucher_entry,
                                              voucher_type, FALSE,
                                              (ipc_object_t *)&voucher_port,
                                              &voucher_soright,
                                              &voucher_release_port,
-                                             &assertcnt,
-                                             links);
+                                             &assertcnt);
                        assert(assertcnt == 0);
-#else
-                       kr = ipc_right_copyin(space, voucher_name, voucher_entry,
-                                             voucher_type, FALSE,
-                                             (ipc_object_t *)&voucher_port,
-                                             &voucher_soright,
-                                             &voucher_release_port,
-                                             links);
-#endif /* IMPORTANCE_INHERITANCE */
                        assert(KERN_SUCCESS == kr);
                        assert(IP_VALID(voucher_port));
                        assert(ip_active(voucher_port));
@@ -2053,7 +2031,7 @@ ipc_kmsg_copyin_header(
                ipc_port_t dport = (ipc_port_t)dest_port;
 
                /* dport still locked from above */
-               if (ipc_port_importance_delta(dport, 1) == FALSE) {
+               if (ipc_port_importance_delta(dport, IPID_OPTION_SENDPOSSIBLE, 1) == FALSE) {
                        ip_unlock(dport);
                }
        }
@@ -2072,11 +2050,6 @@ ipc_kmsg_copyin_header(
        msg->msgh_remote_port = (ipc_port_t)dest_port;
        msg->msgh_local_port = (ipc_port_t)reply_port;
 
-       while(!queue_empty(links)) {
-               wql = (wait_queue_link_t) dequeue(links);
-               wait_queue_link_free(wql);
-       }
-
        if (release_port != IP_NULL)
                ip_release(release_port);
 
@@ -2088,11 +2061,6 @@ ipc_kmsg_copyin_header(
 invalid_reply:
        is_write_unlock(space);
 
-       while(!queue_empty(links)) {
-               wql = (wait_queue_link_t) dequeue(links);
-               wait_queue_link_free(wql);
-       }
-
        if (release_port != IP_NULL)
                ip_release(release_port);
 
@@ -2104,11 +2072,6 @@ invalid_reply:
 invalid_dest:
        is_write_unlock(space);
 
-       while(!queue_empty(links)) {
-               wql = (wait_queue_link_t) dequeue(links);
-               wait_queue_link_free(wql);
-       }
-
        if (release_port != IP_NULL)
                ip_release(release_port);
 
@@ -2573,7 +2536,7 @@ ipc_kmsg_copyin_body(
      */
     if (space_needed) {
         if (vm_allocate(ipc_kernel_copy_map, &paddr, space_needed, 
-                    VM_FLAGS_ANYWHERE) != KERN_SUCCESS) {
+                    VM_FLAGS_ANYWHERE | VM_MAKE_TAG(VM_KERN_MEMORY_IPC)) != KERN_SUCCESS) {
             ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
             mr = MACH_MSG_VM_KERNEL;
             goto out;
@@ -3485,55 +3448,15 @@ ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t *dsc, mach_msg_descrip
     copy_options = dsc->copy;
     assert(copy_options != MACH_MSG_KALLOC_COPY_T);
     dsc_type = dsc->type;
-    rcv_addr = 0;
 
     if (copy != VM_MAP_COPY_NULL) {
-        /*
-         * Check to see if there is an overwrite descriptor
-         * specified in the scatter list for this ool data.
-         * The descriptor has already been verified.
-         */
-#if 0
-        if (saddr != MACH_MSG_DESCRIPTOR_NULL) {
-            if (differs) {
-                OTHER_OOL_DESCRIPTOR *scatter_dsc;
-
-                scatter_dsc = (OTHER_OOL_DESCRIPTOR *)saddr;
-                if (scatter_dsc->copy == MACH_MSG_OVERWRITE) {
-                    rcv_addr = (mach_vm_offset_t) scatter_dsc->address;
-                    copy_options = MACH_MSG_OVERWRITE;
-                } else {
-                    copy_options = MACH_MSG_VIRTUAL_COPY;
-                }
-            } else {
-                mach_msg_ool_descriptor_t *scatter_dsc;
-
-                scatter_dsc = &saddr->out_of_line;
-                if (scatter_dsc->copy == MACH_MSG_OVERWRITE) {
-                    rcv_addr = CAST_USER_ADDR_T(scatter_dsc->address);
-                    copy_options = MACH_MSG_OVERWRITE;
-                } else {
-                    copy_options = MACH_MSG_VIRTUAL_COPY;
-                }
-            }
-            INCREMENT_SCATTER(saddr, sdsc_count, differs);
-        }
-#endif
-
+       kern_return_t kr;
 
-        /*
-         * Whether the data was virtually or physically
-         * copied we have a vm_map_copy_t for it.
-         * If there's an overwrite region specified
-         * overwrite it, otherwise do a virtual copy out.
-         */
-        kern_return_t kr;
-        if (copy_options == MACH_MSG_OVERWRITE && rcv_addr != 0) {
-            kr = vm_map_copy_overwrite(map, rcv_addr,
-                    copy, TRUE);
-        } else {
-            kr = vm_map_copyout(map, &rcv_addr, copy);
-        }      
+        rcv_addr = 0;
+       if (vm_map_copy_validate_size(map, copy, (vm_map_size_t)size) == FALSE)
+               panic("Inconsistent OOL/copyout size on %p: expected %d, got %lld @%p",
+                     dsc, size, (unsigned long long)copy->size, copy);
+        kr = vm_map_copyout(map, &rcv_addr, copy);
         if (kr != KERN_SUCCESS) {
             if (kr == KERN_RESOURCE_SHORTAGE)
                 *mr |= MACH_MSG_VM_KERNEL;
@@ -3656,8 +3579,9 @@ ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t *dsc,
             /*
              * Dynamically allocate the region
              */
-            int anywhere = VM_MAKE_TAG(VM_MEMORY_MACH_MSG)|
-                VM_FLAGS_ANYWHERE;
+            int anywhere = VM_FLAGS_ANYWHERE;
+           if (vm_kernel_map_is_kernel(map)) anywhere |= VM_MAKE_TAG(VM_KERN_MEMORY_IPC);
+           else                              anywhere |= VM_MAKE_TAG(VM_MEMORY_MACH_MSG);
 
             kern_return_t kr;
             if ((kr = mach_vm_allocate(map, &rcv_addr, 
@@ -4078,163 +4002,6 @@ ipc_kmsg_copyout_dest(
        }
 }
 
-/*
- *      Routine:        ipc_kmsg_copyin_scatter
- *      Purpose:
- *              allocate and copyin a scatter list
- *      Algorithm:
- *              The gather (kmsg) is valid since it has been copied in.
- *              Gather list descriptors are sequentially paired with scatter
- *              list descriptors, with port descriptors in either list ignored.
- *              Descriptors are consistent if the type fileds match and size
- *              of the scatter descriptor is less than or equal to the
- *              size of the gather descriptor.  A MACH_MSG_ALLOCATE copy
- *              strategy in a scatter descriptor matches any size in the
- *              corresponding gather descriptor assuming they are the same type.
- *              Either list may be larger than the other.  During the
- *              subsequent copy out, excess scatter descriptors are ignored
- *              and excess gather descriptors default to dynamic allocation.
- *
- *              In the case of a size error, the scatter list is released.
- *      Conditions:
- *              Nothing locked.
- *      Returns:
- *              the allocated message body containing the scatter list.
- */
-
-mach_msg_body_t *
-ipc_kmsg_get_scatter(
-       mach_vm_address_t       msg_addr,
-       mach_msg_size_t         slist_size,
-       ipc_kmsg_t              kmsg)
-{
-        mach_msg_body_t         *slist;
-        mach_msg_body_t         *body;
-        mach_msg_descriptor_t   *gstart, *gend;
-        mach_msg_descriptor_t   *sstart, *send;
-
-#if defined(__LP64__)
-        panic("ipc_kmsg_get_scatter called!");
-#endif
-
-        if (slist_size < sizeof(mach_msg_base_t))
-                return MACH_MSG_BODY_NULL;
-
-        slist_size -= (mach_msg_size_t)sizeof(mach_msg_header_t);
-        slist = (mach_msg_body_t *)kalloc(slist_size);
-        if (slist == MACH_MSG_BODY_NULL)
-                return slist;
-
-        if (copyin(msg_addr + sizeof(mach_msg_header_t), (char *)slist, slist_size)) {
-                kfree(slist, slist_size);
-                return MACH_MSG_BODY_NULL;
-        }
-
-        if ((slist->msgh_descriptor_count* sizeof(mach_msg_descriptor_t)
-             + sizeof(mach_msg_size_t)) > slist_size) {
-                kfree(slist, slist_size);
-                return MACH_MSG_BODY_NULL;
-        }
-
-        body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
-        gstart = (mach_msg_descriptor_t *) (body + 1);
-        gend = gstart + body->msgh_descriptor_count;
-
-        sstart = (mach_msg_descriptor_t *) (slist + 1);
-        send = sstart + slist->msgh_descriptor_count;
-
-        while (gstart < gend) {
-            mach_msg_descriptor_type_t  g_type;
-
-            /*
-             * Skip port descriptors in gather list.
-             */
-            g_type = gstart->type.type;
-
-            if (g_type != MACH_MSG_PORT_DESCRIPTOR) {
-
-             /*
-              * A scatter list with a 0 descriptor count is treated as an
-              * automatic size mismatch.
-              */
-             if (slist->msgh_descriptor_count == 0) {
-                        kfree(slist, slist_size);
-                        return MACH_MSG_BODY_NULL;
-             }
-
-             /*
-              * Skip port descriptors in  scatter list.
-              */
-             while (sstart < send) {
-                    if (sstart->type.type != MACH_MSG_PORT_DESCRIPTOR)
-                        break;
-                    sstart++;
-             }
-
-             /*
-              * No more scatter descriptors, we're done
-              */
-             if (sstart >= send) {
-                    break;
-             }
-
-             /*
-              * Check type, copy and size fields
-              */
-                if (g_type == MACH_MSG_OOL_DESCRIPTOR ||
-                    g_type == MACH_MSG_OOL_VOLATILE_DESCRIPTOR) {
-                    if (sstart->type.type != MACH_MSG_OOL_DESCRIPTOR &&
-                        sstart->type.type != MACH_MSG_OOL_VOLATILE_DESCRIPTOR) {
-                        kfree(slist, slist_size);
-                        return MACH_MSG_BODY_NULL;
-                    }
-                    if (sstart->out_of_line.copy == MACH_MSG_OVERWRITE &&
-                        gstart->out_of_line.size > sstart->out_of_line.size) {
-                        kfree(slist, slist_size);
-                        return MACH_MSG_BODY_NULL;
-                    }
-                }
-                else {
-                 if (sstart->type.type != MACH_MSG_OOL_PORTS_DESCRIPTOR) {
-                        kfree(slist, slist_size);
-                        return MACH_MSG_BODY_NULL;
-                 }
-                    if (sstart->ool_ports.copy == MACH_MSG_OVERWRITE &&
-                        gstart->ool_ports.count > sstart->ool_ports.count) {
-                        kfree(slist, slist_size);
-                        return MACH_MSG_BODY_NULL;
-                    }
-                }
-                sstart++;
-            }
-            gstart++;
-        }
-        return slist;
-}
-
-
-/*
- *      Routine:        ipc_kmsg_free_scatter
- *      Purpose:
- *              Deallocate a scatter list.  Since we actually allocated
- *              a body without a header, and since the header was originally
- *              accounted for in slist_size, we have to ajust it down
- *              before freeing the scatter list.
- */
-void
-ipc_kmsg_free_scatter(
-        mach_msg_body_t *slist,
-        mach_msg_size_t slist_size)
-{
-#if defined(__LP64__)
-        panic("%s called; halting!", __func__);
-#endif
-
-        slist_size -= (mach_msg_size_t)sizeof(mach_msg_header_t);
-        kfree(slist, slist_size);
-}
-
-
 /*
  *     Routine:        ipc_kmsg_copyout_to_kernel
  *     Purpose: