#include <mach/port.h>
#include <mach/message.h>
#include <kern/assert.h>
+#include <kern/ipc_kobject.h>
#include <kern/misc_protos.h>
#include <ipc/port.h>
#include <ipc/ipc_entry.h>
mach_port_urefs_t urefs;
ipc_port_t request = IP_NULL;
ipc_port_t nsrequest = IP_NULL;
+ ipc_port_t port_to_release = IP_NULL;
mach_port_mscount_t mscount = 0;
if ((bits & MACH_PORT_TYPE_SEND) == 0)
name, entry);
ip_unlock(port);
- ip_release(port);
+ port_to_release = port;
entry->ie_object = IO_NULL;
ipc_entry_dealloc(space, name, entry);
is_write_unlock(space);
+ if (port_to_release != IP_NULL)
+ ip_release(port_to_release);
+
if (nsrequest != IP_NULL)
ipc_notify_no_senders(nsrequest, mscount);
case MACH_MSG_TYPE_MOVE_RECEIVE:
if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
return FALSE;
+ if (io_kotype(entry->ie_object) != IKOT_NONE)
+ return FALSE;
break;
case MACH_MSG_TYPE_COPY_SEND:
if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
goto invalid_right;
+ /*
+ * Disallow moving receive-right kobjects, e.g. mk_timer ports
+ * The ipc_port structure uses the kdata union of kobject and
+ * imp_task exclusively. Thus, general use of a kobject port as
+ * a receive right can cause type confusion in the importance
+ * code.
+ */
+ if (io_kotype(entry->ie_object) != IKOT_NONE) {
+ /*
+ * Distinguish an invalid right, e.g., trying to move
+ * a send right as a receive right, from this
+ * situation which is, "This is a valid receive right,
+ * but it's also a kobject and you can't move it."
+ */
+ return KERN_INVALID_CAPABILITY;
+ }
+
port = (ipc_port_t) entry->ie_object;
assert(port != IP_NULL);