]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ipc/ipc_right.c
xnu-3789.70.16.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_right.c
index c5f5cec0cdcef58745c03031938e6b93aecfe65b..7a937f5bef66d0d1666847f89703dfe977b89aa5 100644 (file)
@@ -75,6 +75,7 @@
 #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>
@@ -1310,6 +1311,7 @@ ipc_right_delta(
                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)
@@ -1384,7 +1386,7 @@ ipc_right_delta(
                                                name, entry);
 
                                ip_unlock(port);
-                               ip_release(port);
+                               port_to_release = port;
 
                                entry->ie_object = IO_NULL;
                                ipc_entry_dealloc(space, name, entry);
@@ -1399,6 +1401,9 @@ ipc_right_delta(
 
                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);
 
@@ -1714,6 +1719,8 @@ ipc_right_copyin_check(
            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:
@@ -1853,6 +1860,23 @@ ipc_right_copyin(
                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);