* Functions to manipulate IPC objects.
*/
-#include <mach_rt.h>
-
#include <mach/mach_types.h>
#include <mach/boolean.h>
#include <mach/kern_return.h>
#include <kern/ipc_kobject.h>
#include <ipc/ipc_types.h>
+#include <ipc/ipc_importance.h>
#include <ipc/port.h>
#include <ipc/ipc_space.h>
#include <ipc/ipc_entry.h>
#include <ipc/ipc_notify.h>
#include <ipc/ipc_port.h>
#include <ipc/ipc_pset.h>
-#include <ipc/ipc_labelh.h>
#include <security/mac_mach_internal.h>
* Returns:
* KERN_SUCCESS Object returned locked.
* KERN_INVALID_TASK The space is dead.
- * KERN_INVALID_NAME The name doesn't denote a right.
- * KERN_INVALID_RIGHT Name doesn't denote the correct right.
+ * KERN_INVALID_NAME The name doesn't denote a right
+ * KERN_INVALID_RIGHT Name doesn't denote the correct right
*/
-
kern_return_t
ipc_object_translate(
ipc_space_t space,
if ((entry1->ie_bits & MACH_PORT_TYPE(right1)) == MACH_PORT_TYPE_NONE) {
is_read_unlock(space);
+ mach_port_guard_exception(name1, 0, 0, kGUARD_EXC_INVALID_RIGHT);
return KERN_INVALID_RIGHT;
}
if ((entry2->ie_bits & MACH_PORT_TYPE(right2)) == MACH_PORT_TYPE_NONE) {
is_read_unlock(space);
+ mach_port_guard_exception(name2, 0, 0, kGUARD_EXC_INVALID_RIGHT);
return KERN_INVALID_RIGHT;
}
* Allocate an object.
* Conditions:
* Nothing locked. If successful, the object is returned locked.
+ * The space is write locked on successful return.
* The caller doesn't get a reference for the object.
* Returns:
* KERN_SUCCESS The object is allocated.
ipc_port_t port = (ipc_port_t)object;
bzero((char *)port, sizeof(*port));
-#if CONFIG_MACF_MACH
- mac_port_label_init(&port->ip_label);
-#endif
} else if (otype == IOT_PORT_SET) {
ipc_pset_t pset = (ipc_pset_t)object;
ipc_entry_modified(space, *namep, entry);
io_lock(object);
- is_write_unlock(space);
object->io_references = 1; /* for entry, not caller */
object->io_bits = io_makebits(TRUE, otype, 0);
ipc_port_t port = (ipc_port_t)object;
bzero((char *)port, sizeof(*port));
-#if CONFIG_MACF_MACH
- mac_port_label_init(&port->ip_label);
-#endif
} else if (otype == IOT_PORT_SET) {
ipc_pset_t pset = (ipc_pset_t)object;
switch (msgt_name) {
case MACH_MSG_TYPE_MOVE_RECEIVE:
- case MACH_MSG_TYPE_COPY_RECEIVE:
return MACH_MSG_TYPE_PORT_RECEIVE;
case MACH_MSG_TYPE_MOVE_SEND_ONCE:
case MACH_MSG_TYPE_COPY_SEND:
return MACH_MSG_TYPE_PORT_SEND;
+ case MACH_MSG_TYPE_DISPOSE_RECEIVE:
+ case MACH_MSG_TYPE_DISPOSE_SEND:
+ case MACH_MSG_TYPE_DISPOSE_SEND_ONCE:
+ /* fall thru */
default:
return MACH_MSG_TYPE_PORT_NONE;
}
ipc_port_t soright;
ipc_port_t release_port;
kern_return_t kr;
- queue_head_t links_data;
- queue_t links = &links_data;
- wait_queue_link_t wql;
-
- queue_init(links);
+ int assertcnt = 0;
/*
* Could first try a read lock when doing
msgt_name, TRUE,
objectp, &soright,
&release_port,
- links);
+ &assertcnt);
if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
ipc_entry_dealloc(space, name, entry);
is_write_unlock(space);
- while(!queue_empty(links)) {
- wql = (wait_queue_link_t) dequeue(links);
- wait_queue_link_free(wql);
+#if IMPORTANCE_INHERITANCE
+ if (0 < assertcnt && ipc_importance_task_is_any_receiver_type(current_task()->task_imp_base)) {
+ ipc_importance_task_drop_internal_assertion(current_task()->task_imp_base, assertcnt);
}
+#endif /* IMPORTANCE_INHERITANCE */
if (release_port != IP_NULL)
ip_release(release_port);
ipc_port_t port = (ipc_port_t) object;
ip_lock(port);
+ imq_lock(&port->ip_messages);
assert(ip_active(port));
if (port->ip_destination != IP_NULL) {
assert(port->ip_receiver == ipc_space_kernel);
port->ip_receiver_name = MACH_PORT_NULL;
port->ip_destination = IP_NULL;
}
+ imq_unlock(&port->ip_messages);
ip_unlock(port);
break;
}
ipc_port_t port = (ipc_port_t) object;
ip_lock(port);
- assert(ip_active(port));
- assert(port->ip_receiver_name != MACH_PORT_NULL);
- assert(port->ip_receiver == ipc_space_kernel);
+ if (ip_active(port)) {
+ assert(port->ip_receiver_name != MACH_PORT_NULL);
+ assert((port->ip_receiver == ipc_space_kernel) ||
+ (port->ip_receiver->is_node_id != HOST_LOCAL_NODE));
+ port->ip_mscount++;
+ }
- ip_reference(port);
- port->ip_mscount++;
port->ip_srights++;
+ ip_reference(port);
ip_unlock(port);
break;
}
ipc_port_t port = (ipc_port_t) object;
ip_lock(port);
- assert(ip_active(port));
- assert(port->ip_receiver_name != MACH_PORT_NULL);
-
- ip_reference(port);
+ if (ip_active(port)) {
+ assert(port->ip_receiver_name != MACH_PORT_NULL);
+ }
port->ip_sorights++;
+ ip_reference(port);
ip_unlock(port);
break;
}
boolean_t overflow,
mach_port_name_t *namep)
{
+ struct knote *kn = current_thread()->ith_knote;
mach_port_name_t name;
ipc_entry_t entry;
kern_return_t kr;
assert(IO_VALID(object));
assert(io_otype(object) == IOT_PORT);
+ if (ITH_KNOTE_VALID(kn, msgt_name)) {
+ filt_machport_turnstile_prepare_lazily(kn,
+ msgt_name, (ipc_port_t)object);
+ }
+
is_write_lock(space);
for (;;) {
kr = ipc_right_copyout(space, name, entry,
msgt_name, overflow, object);
+
/* object is unlocked */
is_write_unlock(space);
ipc_entry_t oentry;
ipc_entry_t entry;
kern_return_t kr;
+ struct knote *kn = current_thread()->ith_knote;
+
+#if IMPORTANCE_INHERITANCE
+ int assertcnt = 0;
+ ipc_importance_task_t task_imp = IIT_NULL;
+#endif /* IMPORTANCE_INHERITANCE */
assert(IO_VALID(object));
assert(io_otype(object) == IOT_PORT);
+ if (ITH_KNOTE_VALID(kn, msgt_name)) {
+ filt_machport_turnstile_prepare_lazily(kn,
+ msgt_name, (ipc_port_t)object);
+ }
+
kr = ipc_entry_alloc_name(space, name, &entry);
if (kr != KERN_SUCCESS)
return kr;
/* space is write-locked and active, object is locked and active */
+#if IMPORTANCE_INHERITANCE
+ /*
+ * We are slamming a receive right into the space, without
+ * first having been enqueued on a port destined there. So,
+ * we have to arrange to boost the task appropriately if this
+ * port has assertions (and the task wants them).
+ */
+ if (msgt_name == MACH_MSG_TYPE_PORT_RECEIVE) {
+ ipc_port_t port = (ipc_port_t)object;
+
+ if (space->is_task != TASK_NULL) {
+ task_imp = space->is_task->task_imp_base;
+ if (ipc_importance_task_is_any_receiver_type(task_imp)) {
+ assertcnt = port->ip_impcount;
+ ipc_importance_task_reference(task_imp);
+ } else {
+ task_imp = IIT_NULL;
+ }
+ }
+
+ /* take port out of limbo */
+ assert(port->ip_tempowner != 0);
+ port->ip_tempowner = 0;
+ }
+
+#endif /* IMPORTANCE_INHERITANCE */
+
kr = ipc_right_copyout(space, name, entry,
msgt_name, overflow, object);
+
/* object is unlocked */
is_write_unlock(space);
+
+#if IMPORTANCE_INHERITANCE
+ /*
+ * Add the assertions to the task that we captured before
+ */
+ if (task_imp != IIT_NULL) {
+ ipc_importance_task_hold_internal_assertion(task_imp, assertcnt);
+ ipc_importance_task_release(task_imp);
+ }
+#endif /* IMPORTANCE_INHERITANCE */
+
return kr;
}
return kr;
}
-/*
- * Get a label out of a port, to be used by a kernel call
- * that takes a security label as a parameter. In this case, we want
- * to use the label stored in the label handle and not the label on its
- * port.
- *
- * The port should be locked for this call. The lock protecting
- * label handle contents should not be necessary, as they can only
- * be modified when a label handle with one reference is a task label.
- * User allocated label handles can never be modified.
- */
-#if CONFIG_MACF_MACH
-struct label *io_getlabel (ipc_object_t objp)
-{
- ipc_port_t port = (ipc_port_t)objp;
-
- assert(io_otype(objp) == IOT_PORT);
-
- if (ip_kotype(port) == IKOT_LABELH)
- return &((ipc_labelh_t) port->ip_kobject)->lh_label;
- else
- return &port->ip_label;
-}
-#endif
-
/*
* Check whether the object is a port if so, free it. But
* keep track of that fact.