name = "VIRTUAL";
break;
case MACH_MSG_OVERWRITE:
- name = "OVERWRITE";
+ name = "OVERWRITE(DEPRECATED)";
break;
case MACH_MSG_ALLOCATE:
name = "ALLOCATE";
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
assert(IP_VALID(port));
ip_lock(port);
/* fall thru with reply - same options */
+ kernel_reply = TRUE;
}
#if IMPORTANCE_INHERITANCE
}
#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 */
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;
}
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) ?
* 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);
}
/*
* 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;
}
* 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 */
* 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));
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);
}
}
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);
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);
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);
*/
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;
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;
/*
* 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,
}
}
-/*
- * 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: