Loading...
iokit/Kernel/IOUserClient.cpp xnu-3248.50.21 xnu-4570.41.2
--- xnu/xnu-3248.50.21/iokit/Kernel/IOUserClient.cpp
+++ xnu/xnu-4570.41.2/iokit/Kernel/IOUserClient.cpp
@@ -37,6 +37,7 @@
 #include <IOKit/IOMemoryDescriptor.h>
 #include <IOKit/IOBufferMemoryDescriptor.h>
 #include <IOKit/IOLib.h>
+#include <IOKit/IOBSD.h>
 #include <IOKit/IOStatisticsPrivate.h>
 #include <IOKit/IOTimeStamp.h>
 #include <IOKit/system.h>
@@ -45,6 +46,8 @@
 #include <sys/kauth.h>
 #include <sys/codesign.h>
 
+#include <mach/sdt.h>
+
 #if CONFIG_MACF
 
 extern "C" {
@@ -69,8 +72,9 @@
 
 enum
 {
-    kIOUCAsync0Flags = 3ULL,
-    kIOUCAsync64Flag = 1ULL
+    kIOUCAsync0Flags          = 3ULL,
+    kIOUCAsync64Flag          = 1ULL,
+    kIOUCAsyncErrorLoggedFlag = 2ULL
 };
 
 #if IOKITSTATS
@@ -98,6 +102,25 @@
 #define IOStatisticsClientCall()
 
 #endif /* IOKITSTATS */
+
+#if DEVELOPMENT || DEBUG
+
+#define FAKE_STACK_FRAME(a)                                             \
+        const void ** __frameptr;                                       \
+        const void  * __retaddr;                                        \
+        __frameptr = (typeof(__frameptr)) __builtin_frame_address(0);   \
+        __retaddr = __frameptr[1];                                      \
+        __frameptr[1] = (a);
+
+#define FAKE_STACK_FRAME_END()                                          \
+        __frameptr[1] = __retaddr;
+
+#else /* DEVELOPMENT || DEBUG */
+
+#define FAKE_STACK_FRAME(a)
+#define FAKE_STACK_FRAME_END()
+
+#endif /* DEVELOPMENT || DEBUG */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -247,6 +270,7 @@
 {
     OSDictionary *	dict;
     IOMachPort *	machPort;
+    IOUserClient *      uc;
     bool		destroyed = true;
 
     IOTakeLock( gIOObjectPortLock);
@@ -257,10 +281,15 @@
 	machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
 	if( machPort) {
 	    destroyed = (machPort->mscount <= *mscount);
-	    if( destroyed)
+	    if (!destroyed) *mscount = machPort->mscount;
+            else
+            {
+		if ((IKOT_IOKIT_CONNECT == type) && (uc = OSDynamicCast(IOUserClient, obj)))
+		{
+		    uc->noMoreSenders();
+		}
 		dict->removeObject( (const OSSymbol *) obj );
-	    else
-		*mscount = machPort->mscount;
+	    }
 	} 
 	obj->release();
     }
@@ -275,6 +304,8 @@
 {
     OSDictionary *	dict;
     IOMachPort *	machPort;
+
+    assert(IKOT_IOKIT_CONNECT != type);
 
     IOTakeLock( gIOObjectPortLock);
 
@@ -324,14 +355,18 @@
 	if (port)
 	{
 	    IOUserClient * uc;
-	    if ((uc = OSDynamicCast(IOUserClient, obj)) && uc->mappings)
+	    if ((uc = OSDynamicCast(IOUserClient, obj)))
 	    {
-		dict->setObject((const OSSymbol *) uc->mappings, port);
-		iokit_switch_object_port(port->port, uc->mappings, IKOT_IOKIT_CONNECT);
-
-		uc->mappings->release();
-		uc->mappings = 0;
-	    }
+                uc->noMoreSenders();
+                if (uc->mappings)
+                {
+                    dict->setObject((const OSSymbol *) uc->mappings, port);
+                    iokit_switch_object_port(port->port, uc->mappings, IKOT_IOKIT_CONNECT);
+
+                    uc->mappings->release();
+                    uc->mappings = 0;
+                }
+            }
 	    dict->removeObject( (const OSSymbol *) obj );
 	}
     }
@@ -567,10 +602,13 @@
 
     if( IKOT_IOKIT_CONNECT == type)
     {
-	if( (client = OSDynamicCast( IOUserClient, obj ))) {
-		IOStatisticsClientCall();
+	if( (client = OSDynamicCast( IOUserClient, obj )))
+	{
+	    IOStatisticsClientCall();
+	    IOLockLock(client->lock);
 	    client->clientDied();
-    }
+	    IOLockUnlock(client->lock);
+        }
     }
     else if( IKOT_IOKIT_OBJECT == type)
     {
@@ -603,6 +641,7 @@
     OSArray 	*	newSet;
     OSObject	*	lastEntry;
     bool		armed;
+    bool                ipcLogged;
 
 public:
 
@@ -610,6 +649,7 @@
                        void * reference, vm_size_t referenceSize,
 		       bool clientIs64 );
     virtual void free() APPLE_KEXT_OVERRIDE;
+    void invalidatePort(void);
 
     static bool _handler( void * target,
                           void * ref, IOService * newService, IONotifier * notifier );
@@ -633,6 +673,7 @@
     vm_size_t		msgSize;
     uint8_t		clientIs64;
     int			owningPID;
+    bool                ipcLogged;
 
 public:
 
@@ -642,6 +683,7 @@
 		       bool clientIs64 );
 
     virtual void free() APPLE_KEXT_OVERRIDE;
+    void invalidatePort(void);
     
     static IOReturn _handler( void * target, void * ref,
                               UInt32 messageType, IOService * provider,
@@ -747,6 +789,11 @@
     return( true );
 }
 
+void IOServiceUserNotification::invalidatePort(void)
+{
+    if (pingMsg) pingMsg->msgHdr.msgh_remote_port = MACH_PORT_NULL;
+}
+
 void IOServiceUserNotification::free( void )
 {
     PingMsg   *	_pingMsg;
@@ -817,8 +864,11 @@
 	if( port)
 	    iokit_release_port( port );
 
-        if( KERN_SUCCESS != kr)
-            IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr );
+        if( (KERN_SUCCESS != kr) && !ipcLogged)
+        {
+            ipcLogged = true;
+            IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__, kr );
+        }
     }
 
     return( true );
@@ -828,12 +878,11 @@
 {
     unsigned int	count;
     OSObject *		result;
-
-    IOTakeLock( lock );
-
-    if( lastEntry)
-        lastEntry->release();
-
+    OSObject *		releaseEntry;
+
+    IOLockLock(lock);
+
+    releaseEntry = lastEntry;
     count = newSet->getCount();
     if( count ) {
         result = newSet->getObject( count - 1 );
@@ -845,7 +894,9 @@
     }
     lastEntry = result;
 
-    IOUnlock( lock );
+    IOLockUnlock(lock);
+
+    if (releaseEntry) releaseEntry->release();
 
     return( result );
 }
@@ -871,7 +922,7 @@
     owningPID = proc_selfpid();
 
     extraSize += sizeof(IOServiceInterestContent64);
-    msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize + extraSize;
+    msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize;
     pingMsg = (PingMsg *) IOMalloc( msgSize);
     if( !pingMsg)
         return( false );
@@ -899,6 +950,11 @@
     return( true );
 }
 
+void IOServiceMessageUserNotification::invalidatePort(void)
+{
+    if (pingMsg) pingMsg->msgHdr.msgh_remote_port = MACH_PORT_NULL;
+}
+
 void IOServiceMessageUserNotification::free( void )
 {
     PingMsg *	_pingMsg;
@@ -927,13 +983,17 @@
 
 IOReturn IOServiceMessageUserNotification::handler( void * ref,
                                     UInt32 messageType, IOService * provider,
-                                    void * messageArgument, vm_size_t argSize )
-{
+                                    void * messageArgument, vm_size_t callerArgSize )
+{
+    enum 			 { kLocalMsgSize = 0x100 };
+    uint64_t                     stackMsg[kLocalMsgSize / sizeof(uint64_t)];
+    void *                       allocMsg;
     kern_return_t		 kr;
+    vm_size_t  			 argSize;
+    vm_size_t  			 thisMsgSize;
     ipc_port_t 			 thisPort, providerPort;
-    IOServiceInterestContent64 * data = (IOServiceInterestContent64 *)
-					((((uint8_t *) pingMsg) + msgSize) - pingMsg->notifyHeader.size);
-                                        // == pingMsg->notifyHeader.content;
+    struct PingMsg *             thisMsg;
+    IOServiceInterestContent64 * data;
 
     if (kIOMessageCopyClientID == messageType)
     {
@@ -941,24 +1001,16 @@
         return (kIOReturnSuccess);
     }
 
-    data->messageType = messageType;
-
-    if( argSize == 0)
-    {
-	data->messageArgument[0] = (io_user_reference_t) messageArgument;
-	if (clientIs64)
-	    argSize = sizeof(data->messageArgument[0]);
-	else
-	{
-	    data->messageArgument[0] |= (data->messageArgument[0] << 32);
-	    argSize = sizeof(uint32_t);
-	}
+    if (callerArgSize == 0)
+    {
+	if (clientIs64) argSize = sizeof(data->messageArgument[0]);
+	else            argSize = sizeof(uint32_t);
     }
     else
     {
-        if( argSize > kIOUserNotifyMaxMessageSize)
-            argSize = kIOUserNotifyMaxMessageSize;
-        bcopy( messageArgument, data->messageArgument, argSize );
+        if( callerArgSize > kIOUserNotifyMaxMessageSize)
+            callerArgSize = kIOUserNotifyMaxMessageSize;
+        argSize = callerArgSize;
     }
 
     // adjust message size for ipc restrictions
@@ -966,20 +1018,55 @@
     type = pingMsg->notifyHeader.type;
     type &= ~(kIOKitNoticationMsgSizeMask << kIOKitNoticationTypeSizeAdjShift);
     type |= ((argSize & kIOKitNoticationMsgSizeMask) << kIOKitNoticationTypeSizeAdjShift);
-    pingMsg->notifyHeader.type = type;
     argSize = (argSize + kIOKitNoticationMsgSizeMask) & ~kIOKitNoticationMsgSizeMask;
 
-    pingMsg->msgHdr.msgh_size = msgSize - pingMsg->notifyHeader.size
-        + sizeof( IOServiceInterestContent64 )
-        - sizeof( data->messageArgument)
-        + argSize;
+    thisMsgSize = msgSize
+		+ sizeof( IOServiceInterestContent64 )
+		- sizeof( data->messageArgument)
+		+ argSize;
+
+    if (thisMsgSize > sizeof(stackMsg))
+    {
+	allocMsg = IOMalloc(thisMsgSize);
+	if (!allocMsg) return (kIOReturnNoMemory);
+	thisMsg = (typeof(thisMsg)) allocMsg;
+    }
+    else
+    {
+	allocMsg = 0;
+	thisMsg  = (typeof(thisMsg)) stackMsg;
+    }
+
+    bcopy(pingMsg, thisMsg, msgSize);
+    thisMsg->notifyHeader.type = type;
+    data = (IOServiceInterestContent64 *) (((uint8_t *) thisMsg) + msgSize);
+	// == pingMsg->notifyHeader.content;
+    data->messageType = messageType;
+
+    if (callerArgSize == 0)
+    {
+	data->messageArgument[0] = (io_user_reference_t) messageArgument;
+	if (!clientIs64)
+	{
+	    data->messageArgument[0] |= (data->messageArgument[0] << 32);
+	}
+    }
+    else
+    {
+        bcopy( messageArgument, data->messageArgument, callerArgSize );
+        bzero((void *)(((uintptr_t) &data->messageArgument[0]) + callerArgSize), argSize - callerArgSize);
+    }
+
+    thisMsg->notifyHeader.type = type;
+    thisMsg->msgHdr.msgh_size  = thisMsgSize;
 
     providerPort = iokit_port_for_object( provider, IKOT_IOKIT_OBJECT );
-    pingMsg->ports[0].name = providerPort;
+    thisMsg->ports[0].name = providerPort;
     thisPort = iokit_port_for_object( this, IKOT_IOKIT_OBJECT );
-    pingMsg->msgHdr.msgh_local_port = thisPort;
-    kr = mach_msg_send_from_kernel_with_options( &pingMsg->msgHdr,
-						 pingMsg->msgHdr.msgh_size,
+    thisMsg->msgHdr.msgh_local_port = thisPort;
+
+    kr = mach_msg_send_from_kernel_with_options( &thisMsg->msgHdr,
+						 thisMsg->msgHdr.msgh_size,
 						 (MACH_SEND_MSG | MACH_SEND_ALWAYS | MACH_SEND_IMPORTANCE),
 						 0);
     if( thisPort)
@@ -987,8 +1074,14 @@
     if( providerPort)
 	iokit_release_port( providerPort );
 
-    if( KERN_SUCCESS != kr)
-        IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr );
+    if (allocMsg)
+        IOFree(allocMsg, thisMsgSize);
+
+    if((KERN_SUCCESS != kr) && !ipcLogged)
+    {
+        ipcLogged = true;
+        IOLog("%s: mach_msg_send_from_kernel_proper (0x%x)\n", __PRETTY_FUNCTION__, kr );
+    }
 
     return( kIOReturnSuccess );
 }
@@ -1004,11 +1097,13 @@
 #define super IOService
 OSDefineMetaClassAndAbstractStructors( IOUserClient, IOService )
 
+IOLock       * gIOUserClientOwnersLock;
+
 void IOUserClient::initialize( void )
 {
-    gIOObjectPortLock = IOLockAlloc();
-
-    assert( gIOObjectPortLock );
+    gIOObjectPortLock       = IOLockAlloc();
+    gIOUserClientOwnersLock = IOLockAlloc();
+    assert(gIOObjectPortLock && gIOUserClientOwnersLock);
 }
 
 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef,
@@ -1333,15 +1428,132 @@
     return true;
 }
 
+struct IOUserClientOwner
+{
+    task_t         task;
+    queue_chain_t  taskLink;
+    IOUserClient * uc;
+    queue_chain_t  ucLink;
+};
+
+IOReturn
+IOUserClient::registerOwner(task_t task)
+{
+    IOUserClientOwner * owner;
+    IOReturn            ret;
+    bool                newOwner;
+
+    IOLockLock(gIOUserClientOwnersLock);
+
+    newOwner = true;
+    ret = kIOReturnSuccess;
+
+    if (!owners.next) queue_init(&owners);
+    else
+    {
+        queue_iterate(&owners, owner, IOUserClientOwner *, ucLink)
+        {
+            if (task != owner->task) continue;
+            newOwner = false;
+            break;
+        }
+    }
+    if (newOwner)
+    {
+        owner = IONew(IOUserClientOwner, 1);
+        if (!newOwner) ret = kIOReturnNoMemory;
+        else
+        {
+            owner->task = task;
+            owner->uc   = this;
+            queue_enter_first(&owners, owner, IOUserClientOwner *, ucLink);
+            queue_enter_first(task_io_user_clients(task), owner, IOUserClientOwner *, taskLink);
+        }
+    }
+
+    IOLockUnlock(gIOUserClientOwnersLock);
+
+    return (ret);
+}
+
+void
+IOUserClient::noMoreSenders(void)
+{
+    IOUserClientOwner * owner;
+
+    IOLockLock(gIOUserClientOwnersLock);
+
+    if (owners.next)
+    {
+        while (!queue_empty(&owners))
+        {
+            owner = (IOUserClientOwner *)(void *) queue_first(&owners);
+            queue_remove(task_io_user_clients(owner->task), owner, IOUserClientOwner *, taskLink);
+            queue_remove(&owners, owner, IOUserClientOwner *, ucLink);
+            IODelete(owner, IOUserClientOwner, 1);
+        }
+        owners.next = owners.prev = NULL;
+    }
+
+    IOLockUnlock(gIOUserClientOwnersLock);
+}
+
+extern "C" kern_return_t
+iokit_task_terminate(task_t task)
+{
+    IOUserClientOwner * owner;
+    IOUserClient      * dead;
+    IOUserClient      * uc;
+    queue_head_t      * taskque;
+
+    IOLockLock(gIOUserClientOwnersLock);
+
+    taskque = task_io_user_clients(task);
+    dead = NULL;
+    while (!queue_empty(taskque))
+    {
+        owner = (IOUserClientOwner *)(void *) queue_first(taskque);
+        uc = owner->uc;
+        queue_remove(taskque, owner, IOUserClientOwner *, taskLink);
+        queue_remove(&uc->owners, owner, IOUserClientOwner *, ucLink);
+        if (queue_empty(&uc->owners))
+        {
+            uc->retain();
+            IOLog("destroying out of band connect for %s\n", uc->getName());
+            // now using the uc queue head as a singly linked queue,
+            // leaving .next as NULL to mark it empty
+            uc->owners.next = NULL;
+            uc->owners.prev = (queue_entry_t) dead;
+            dead = uc;
+        }
+        IODelete(owner, IOUserClientOwner, 1);
+    }
+
+    IOLockUnlock(gIOUserClientOwnersLock);
+
+    while (dead)
+    {
+        uc = dead;
+        dead = (IOUserClient *)(void *) dead->owners.prev;
+        uc->owners.prev = NULL;
+        if (uc->sharedInstance || !uc->closed) uc->clientDied();
+        uc->release();
+    }
+
+    return (KERN_SUCCESS);
+}
+
 void IOUserClient::free()
 {
-    if( mappings)
-        mappings->release();
+    if( mappings) mappings->release();
+    if (lock) IOLockFree(lock);
 		
     IOStatisticsUnregisterCounter();
 
-    if (reserved)
-        IODelete(reserved, ExpansionData, 1);
+    assert(!owners.next);
+    assert(!owners.prev);
+
+    if (reserved) IODelete(reserved, ExpansionData, 1);
 		
     super::free();
 }
@@ -1421,17 +1633,21 @@
 {
     IOReturn		err;
     IOOptionBits	options = 0;
-    IOMemoryDescriptor * memory;
+    IOMemoryDescriptor * memory = 0;
     IOMemoryMap *	map = 0;
 
     err = clientMemoryForType( (UInt32) type, &options, &memory );
 
     if( memory && (kIOReturnSuccess == err)) {
+
+        FAKE_STACK_FRAME(getMetaClass());
 
         options = (options & ~kIOMapUserOptionsMask)
 		| (mapFlags & kIOMapUserOptionsMask);
 	map = memory->createMappingInTask( task, atAddress, options );
 	memory->release();
+
+        FAKE_STACK_FRAME_END();
     }
 
     return( map );
@@ -1458,6 +1674,17 @@
     return( 0 );
 }
 
+IOExternalTrap * IOUserClient::
+getExternalTrapForIndex(UInt32 index)
+{
+	return NULL;
+}
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+// Suppressing the deprecated-declarations warning. Avoiding the use of deprecated
+// functions can break clients of kexts implementing getExternalMethodForIndex()
 IOExternalMethod * IOUserClient::
 getTargetAndMethodForIndex(IOService **targetP, UInt32 index)
 {
@@ -1478,12 +1705,6 @@
         *targetP = (IOService *) method->object;
 
     return method;
-}
-
-IOExternalTrap * IOUserClient::
-getExternalTrapForIndex(UInt32 index)
-{
-	return NULL;
 }
 
 IOExternalTrap * IOUserClient::
@@ -1497,6 +1718,7 @@
 
       return trap;
 }
+#pragma clang diagnostic pop
 
 IOReturn IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference)
 {
@@ -1582,6 +1804,7 @@
     if (numArgs > kMaxAsyncArgs)
         return kIOReturnMessageTooLarge;
 
+    bzero(&replyMsg, sizeof(replyMsg));
     replyMsg.msgHdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND /*remote*/,
 						0 /*local*/);
     replyMsg.msgHdr.msgh_remote_port = replyPort;
@@ -1630,8 +1853,11 @@
 		kr = mach_msg_send_from_kernel_proper( &replyMsg.msgHdr,
 										 replyMsg.msgHdr.msgh_size);
 	}
-    if ((KERN_SUCCESS != kr) && (MACH_SEND_TIMED_OUT != kr))
-        IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr );
+    if ((KERN_SUCCESS != kr) && (MACH_SEND_TIMED_OUT != kr) && !(kIOUCAsyncErrorLoggedFlag & reference[0]))
+    {
+        reference[0] |= kIOUCAsyncErrorLoggedFlag;
+        IOLog("%s: mach_msg_send_from_kernel_proper(0x%x)\n", __PRETTY_FUNCTION__, kr );
+    }
     return kr;
 }
 
@@ -1711,38 +1937,36 @@
 	io_name_t obj_name, 
 	io_name_t class_name)
 {
-	const OSMetaClass* my_obj = NULL;
-	const OSMetaClass* superclass = NULL;
-	const OSSymbol *my_name = NULL;
-	const char *my_cstr = NULL;
-
-	if (!obj_name || !class_name) 
-		return (kIOReturnBadArgument);
-
-    if( master_port != master_device_port)
-        return( kIOReturnNotPrivileged);
-
-	my_name = OSSymbol::withCString(obj_name);
-	
-	if (my_name) {
-		my_obj = OSMetaClass::getMetaClassWithName(my_name);
-		my_name->release();
-	}
-	if (my_obj) {
-		superclass = my_obj->getSuperClass();
-	}
-	
-	if (!superclass)  {
-		return( kIOReturnNotFound );
-	}
-
-	my_cstr = superclass->getClassName();
-		
-	if (my_cstr) {
-		strlcpy(class_name, my_cstr, sizeof(io_name_t));
-		return( kIOReturnSuccess );
-	}
-	return (kIOReturnNotFound);
+    IOReturn            ret;
+    const OSMetaClass * meta;
+    const OSMetaClass * super;
+    const OSSymbol    * name;
+    const char        * cstr;
+
+    if (!obj_name || !class_name)          return (kIOReturnBadArgument);
+    if (master_port != master_device_port) return( kIOReturnNotPrivileged);
+
+    ret = kIOReturnNotFound;
+    meta = 0;
+    do
+    {
+        name = OSSymbol::withCString(obj_name);
+        if (!name) break;
+        meta = OSMetaClass::copyMetaClassWithName(name);
+        if (!meta) break;
+        super = meta->getSuperClass();
+        if (!super) break;
+        cstr = super->getClassName();
+        if (!cstr) break;
+        strlcpy(class_name, cstr, sizeof(io_name_t));
+        ret = kIOReturnSuccess;
+    }
+    while (false);
+
+    OSSafeReleaseNULL(name);
+    if (meta) meta->releaseMetaClass();
+
+    return (ret);
 }
 
 /* Routine io_object_get_bundle_identifier */
@@ -1751,38 +1975,36 @@
 	io_name_t obj_name, 
 	io_name_t bundle_name)
 {
-	const OSMetaClass* my_obj = NULL;
-	const OSSymbol *my_name = NULL;
-	const OSSymbol *identifier = NULL;
-	const char *my_cstr = NULL;
-
-	if (!obj_name || !bundle_name) 
-		return (kIOReturnBadArgument);
-
-    if( master_port != master_device_port)
-        return( kIOReturnNotPrivileged);
-	
-	my_name = OSSymbol::withCString(obj_name);	
-	
-	if (my_name) {
-		my_obj = OSMetaClass::getMetaClassWithName(my_name);
-		my_name->release();
-	}
-
-	if (my_obj) {
-		identifier = my_obj->getKmodName();
-	}
-	if (!identifier) {
-		return( kIOReturnNotFound );
-	}
-	
-	my_cstr = identifier->getCStringNoCopy();
-	if (my_cstr) {
-		strlcpy(bundle_name, identifier->getCStringNoCopy(), sizeof(io_name_t));
-		return( kIOReturnSuccess );
-	}
-
-	return (kIOReturnBadArgument);
+    IOReturn            ret;
+    const OSMetaClass * meta;
+    const OSSymbol    * name;
+    const OSSymbol    * identifier;
+    const char        * cstr;
+
+    if (!obj_name || !bundle_name)         return (kIOReturnBadArgument);
+    if (master_port != master_device_port) return( kIOReturnNotPrivileged);
+
+    ret = kIOReturnNotFound;
+    meta = 0;
+    do
+    {
+        name = OSSymbol::withCString(obj_name);
+        if (!name) break;
+        meta = OSMetaClass::copyMetaClassWithName(name);
+        if (!meta) break;
+        identifier = meta->getKmodName();
+        if (!identifier) break;
+        cstr = identifier->getCStringNoCopy();
+        if (!cstr) break;
+        strlcpy(bundle_name, identifier->getCStringNoCopy(), sizeof(io_name_t));
+        ret = kIOReturnSuccess;
+    }
+    while (false);
+
+    OSSafeReleaseNULL(name);
+    if (meta) meta->releaseMetaClass();
+
+    return (ret);
 }
 
 /* Routine io_object_conforms_to */
@@ -1868,8 +2090,9 @@
     OSObject *		obj;
     OSDictionary *	dict;
 
-    obj = matching_size ? OSUnserializeXML(matching, matching_size)
-			: OSUnserializeXML(matching);
+    assert(matching_size);
+    obj = OSUnserializeXML(matching, matching_size);
+
     if( (dict = OSDynamicCast( OSDictionary, obj))) {
         *matches = service->passiveMatch( dict );
 	kr = kIOReturnSuccess;
@@ -1888,7 +2111,7 @@
 	io_string_t matching,
 	boolean_t *matches )
 {
-    return (internal_io_service_match_property_table(service, matching, 0, matches));
+    return (kIOReturnUnsupported);
 }
 
 
@@ -1940,8 +2163,9 @@
     if( master_port != master_device_port)
         return( kIOReturnNotPrivileged);
 
-    obj = matching_size ? OSUnserializeXML(matching, matching_size)
-			: OSUnserializeXML(matching);
+    assert(matching_size);
+    obj = OSUnserializeXML(matching, matching_size);
+
     if( (dict = OSDynamicCast( OSDictionary, obj))) {
         *existing = IOUserIterator::withIterator(IOService::getMatchingServices( dict ));
 	kr = kIOReturnSuccess;
@@ -1960,7 +2184,7 @@
 	io_string_t matching,
 	io_iterator_t *existing )
 {
-    return (internal_io_service_get_matching_services(master_port, matching, 0, existing));
+    return (kIOReturnUnsupported);
 }
 
 /* Routine io_service_get_matching_services_ool */
@@ -2014,8 +2238,9 @@
     if( master_port != master_device_port)
         return( kIOReturnNotPrivileged);
 
-    obj = matching_size ? OSUnserializeXML(matching, matching_size)
-			: OSUnserializeXML(matching);
+    assert(matching_size);
+    obj = OSUnserializeXML(matching, matching_size);
+
     if( (dict = OSDynamicCast( OSDictionary, obj))) {
         *service = IOService::copyMatchingService( dict );
 	kr = *service ? kIOReturnSuccess : kIOReturnNotFound;
@@ -2034,7 +2259,7 @@
 	io_string_t matching,
 	io_service_t *service )
 {
-    return (internal_io_service_get_matching_service(master_port, matching, 0, service));
+    return (kIOReturnUnsupported);
 }
 
 /* Routine io_service_get_matching_services_ool */
@@ -2098,18 +2323,13 @@
     do {
         err = kIOReturnNoResources;
 
+        if (matching_size > (sizeof(io_struct_inband_t) * 1024)) return(kIOReturnMessageTooLarge);
+
         if( !(sym = OSSymbol::withCString( notification_type )))
 	    err = kIOReturnNoResources;
 
-	if (matching_size)
-	{
-            dict = OSDynamicCast(OSDictionary, OSUnserializeXML(matching, matching_size));
-	}
-	else
-	{
-	    dict = OSDynamicCast(OSDictionary, OSUnserializeXML(matching));
-	}
-
+	assert(matching_size);
+	dict = OSDynamicCast(OSDictionary, OSUnserializeXML(matching, matching_size));
         if (!dict) {
             err = kIOReturnBadArgument;
 	    continue;
@@ -2121,7 +2341,8 @@
 	else if( (sym == gIOMatchedNotification)
 	      || (sym == gIOFirstMatchNotification))
 	    userMsgType = kIOServiceMatchedNotificationType;
-	else if( sym == gIOTerminatedNotification)
+	else if ((sym == gIOTerminatedNotification)
+	      || (sym == gIOWillTerminateNotification))
 	    userMsgType = kIOServiceTerminatedNotificationType;
 	else
 	    userMsgType = kLastIOKitNotificationType;
@@ -2130,7 +2351,6 @@
 
         if( userNotify && !userNotify->init( port, userMsgType,
                                              reference, referenceSize, client64)) {
-			iokit_release_port_send(port);
             userNotify->release();
             userNotify = 0;
         }
@@ -2147,6 +2367,13 @@
 	    err = kIOReturnUnsupported;
 
     } while( false );
+
+    if ((kIOReturnSuccess != err) && userNotify)
+    {
+	userNotify->invalidatePort();
+	userNotify->release();
+	userNotify = 0;
+    }
 
     if( sym)
 	sym->release();
@@ -2167,9 +2394,7 @@
 	mach_msg_type_number_t referenceCnt,
 	io_object_t * notification )
 {
-    return (internal_io_service_add_notification(master_port, notification_type, 
-		matching, 0, port, &reference[0], sizeof(io_async_ref_t),
-		false, notification));
+    return (kIOReturnUnsupported);
 }
 
 /* Routine io_service_add_notification_64 */
@@ -2182,9 +2407,7 @@
 	mach_msg_type_number_t referenceCnt,
 	io_object_t *notification )
 {
-    return (internal_io_service_add_notification(master_port, notification_type, 
-		matching, 0, wake_port, &reference[0], sizeof(io_async_ref64_t),
-		true, notification));
+    return (kIOReturnUnsupported);
 }
 
 /* Routine io_service_add_notification_bin */
@@ -2327,7 +2550,6 @@
                                              reference, referenceSize,
 					     kIOUserNotifyMaxMessageSize,
 					     client64 )) {
-			iokit_release_port_send(port);
             userNotify->release();
             userNotify = 0;
         }
@@ -2346,6 +2568,13 @@
 	sym->release();
 
     } while( false );
+
+    if ((kIOReturnSuccess != err) && userNotify)
+    {
+	userNotify->invalidatePort();
+	userNotify->release();
+	userNotify = 0;
+    }
 
     return( err );
 }
@@ -2718,6 +2947,7 @@
     if( (data = OSDynamicCast( OSData, obj ))) {
 	len = data->getLength();
 	bytes = data->getBytesNoCopy();
+	if (!data->isSerializable()) len = 0;
 
     } else if( (str = OSDynamicCast( OSString, obj ))) {
 	len = str->getLength() + 1;
@@ -2730,6 +2960,7 @@
     } else if( (off = OSDynamicCast( OSNumber, obj ))) {
 	offsetBytes = off->unsigned64BitValue();
 	len = off->numberOfBytes();
+	if (len > sizeof(offsetBytes)) len = sizeof(offsetBytes);
 	bytes = &offsetBytes;
 #ifdef __BIG_ENDIAN__
 	bytes = (const void *)
@@ -2816,7 +3047,7 @@
 #endif
 
     obj = entry->copyProperty( property_name,
-                               IORegistryEntry::getPlane( plane ), options);
+                               IORegistryEntry::getPlane( plane ), options );
     if( !obj)
         return( kIOReturnNotFound );
 
@@ -2839,43 +3070,6 @@
 
     return( err );
 }
-
-#if CONFIG_MACF
-
-static kern_return_t
-filteredProperties(IORegistryEntry *entry, OSDictionary *properties, OSDictionary **filteredp)
-{
-    kern_return_t	err = 0;
-    OSDictionary	*filtered = NULL;
-    OSCollectionIterator *iter = NULL;
-    OSSymbol		*key;
-    OSObject		*p;
-    kauth_cred_t	cred = kauth_cred_get();
-
-    if (properties == NULL)
-	return kIOReturnUnsupported;
-
-    if ((iter = OSCollectionIterator::withCollection(properties)) == NULL ||
-        (filtered = OSDictionary::withCapacity(properties->getCapacity())) == NULL) {
-	err = kIOReturnNoMemory;
-	goto out;
-    }
-
-    while ((p = iter->getNextObject()) != NULL) {
-	if ((key = OSDynamicCast(OSSymbol, p)) == NULL ||
-	    mac_iokit_check_get_property(cred, entry, key->getCStringNoCopy()) != 0)
-	    continue;
-	filtered->setObject(key, properties->getObject(key));
-    }
-
-out:
-    if (iter != NULL)
-	iter->release();
-    *filteredp = filtered;
-    return err;
-}
-
-#endif
 
 /* Routine io_registry_entry_get_properties */
 kern_return_t is_io_registry_entry_get_properties(
@@ -2883,43 +3077,7 @@
 	io_buf_ptr_t *properties,
 	mach_msg_type_number_t *propertiesCnt )
 {
-    kern_return_t	err = 0;
-    vm_size_t 		len;
-
-    CHECK( IORegistryEntry, registry_entry, entry );
-
-    OSSerialize * s = OSSerialize::withCapacity(4096);
-    if( !s)
-	return( kIOReturnNoMemory );
-
-    if (!entry->serializeProperties(s))
-	err = kIOReturnUnsupported;
-
-#if CONFIG_MACF
-    if (!err && mac_iokit_check_filter_properties(kauth_cred_get(), entry)) {
-	OSObject *propobj = OSUnserializeXML(s->text(), s->getLength());
-	OSDictionary *filteredprops = NULL;
-	err = filteredProperties(entry, OSDynamicCast(OSDictionary, propobj), &filteredprops);
-	if (propobj) propobj->release();
-
-	if (!err) {
-	    s->clearText();
-	    if (!filteredprops->serialize(s))
-		err = kIOReturnUnsupported;
-	}
-	if (filteredprops != NULL)
-	    filteredprops->release();
-    }
-#endif /* CONFIG_MACF */
-
-    if (!err) {
-	len = s->getLength();
-	*propertiesCnt = len;
-	err = copyoutkdata( s->text(), len, properties );
-    }
-
-    s->release();
-    return( err );
+    return (kIOReturnUnsupported);
 }
 
 #if CONFIG_MACF
@@ -2942,13 +3100,13 @@
 
     if (!ref->root) ref->root = container;
     if (ref->root == container)
-	{
-		if (0 != mac_iokit_check_get_property(ref->cred, ref->entry, name->getCStringNoCopy())) 
-		{
-			value = 0;
-		}
-	}
-	if (value) value->retain();
+    {
+        if (0 != mac_iokit_check_get_property(ref->cred, ref->entry, name->getCStringNoCopy()))
+        {
+                value = 0;
+        }
+    }
+    if (value) value->retain();
     return (value);
 }
 
@@ -2987,9 +3145,9 @@
 
     if (kIOReturnSuccess == err)
     {
-		len = s->getLength();
-		*propertiesCnt = len;
-		err = copyoutkdata(s->text(), len, properties);
+        len = s->getLength();
+        *propertiesCnt = len;
+        err = copyoutkdata(s->text(), len, properties);
     }
     s->release();
 
@@ -3017,25 +3175,29 @@
         return kIOReturnNotPermitted;
 #endif
 
-    if ((kIORegistryIterateRecursively & options) && plane[0])
-    {
-	obj = entry->copyProperty(property_name,
-				  IORegistryEntry::getPlane(plane), options);
+    sym = OSSymbol::withCString(property_name);
+    if (!sym) return (kIOReturnNoMemory);
+
+    if (gIORegistryEntryPropertyKeysKey == sym)
+    {
+        obj = entry->copyPropertyKeys();
     }
     else
     {
-	obj = entry->copyProperty(property_name);
-    }
-
-    if( !obj)
-        return( kIOReturnNotFound );
-
-    sym = OSSymbol::withCString(property_name);
-    if (sym)
-    {
-        if (gIORemoveOnReadProperties->containsObject(sym)) entry->removeProperty(sym);
-        sym->release();
-    }
+        if ((kIORegistryIterateRecursively & options) && plane[0])
+        {
+            obj = entry->copyProperty(property_name,
+                                      IORegistryEntry::getPlane(plane), options );
+        }
+        else
+        {
+            obj = entry->copyProperty(property_name);
+        }
+        if (obj && gIORemoveOnReadProperties->containsObject(sym)) entry->removeProperty(sym);
+    }
+
+    sym->release();
+    if (!obj) return (kIOReturnNotFound);
 
     OSSerialize * s = OSSerialize::binaryWithCapacity(4096);
     if( !s) {
@@ -3080,6 +3242,8 @@
     data = CAST_DOWN(vm_offset_t, map_data);
 
     if( KERN_SUCCESS == err) {
+
+        FAKE_STACK_FRAME(entry->getMetaClass());
 
         // must return success after vm_map_copyout() succeeds
         obj = OSUnserializeXML( (const char *) data, propertiesCnt );
@@ -3101,6 +3265,9 @@
 
 	if (obj)
 	    obj->release();
+
+        FAKE_STACK_FRAME_END();
+
     } else
         res = err;
 
@@ -3117,7 +3284,7 @@
     CHECK( IORegistryEntry, registry_entry, entry );
 
     *iterator = entry->getChildIterator(
-	IORegistryEntry::getPlane( plane ));
+    IORegistryEntry::getPlane( plane ));
 
     return( kIOReturnSuccess );
 }
@@ -3239,11 +3406,14 @@
 
     CHECK( IOService, _service, service );
 
-    if (!owningTask) return (kIOReturnBadArgument);
+    if (!owningTask)                  return (kIOReturnBadArgument);
+    assert(owningTask == current_task());
+    if (owningTask != current_task()) return (kIOReturnBadArgument);
 
     do
     {
-	if (properties)
+	if (properties) return (kIOReturnUnsupported);
+#if 0
 	{
 	    OSObject *	    obj;
 	    vm_offset_t     data;
@@ -3271,7 +3441,7 @@
 	    if (kIOReturnSuccess != res)
 		break;
 	}
-
+#endif
 	crossEndian = (ndr.int_rep != NDR_record.int_rep);
 	if (crossEndian)
 	{
@@ -3296,6 +3466,10 @@
 	{
 	    assert( OSDynamicCast(IOUserClient, client) );
 
+	    client->sharedInstance = (0 != client->getProperty(kIOUserClientSharedInstanceKey));
+	    client->closed = false;
+	    client->lock = IOLockAlloc();
+
 	    disallowAccess = (crossEndian
 		&& (kOSBooleanTrue != service->getProperty(kIOUserClientCrossEndianCompatibleKey))
 		&& (kOSBooleanTrue != client->getProperty(kIOUserClientCrossEndianCompatibleKey)));
@@ -3304,6 +3478,9 @@
 	    else if (0 != mac_iokit_check_open(kauth_cred_get(), client, connect_type))
 		res = kIOReturnNotPermitted;
 #endif
+
+	    if (kIOReturnSuccess == res) res = client->registerOwner(owningTask);
+
 	    if (kIOReturnSuccess != res)
 	    {
 		IOStatisticsClientCall();
@@ -3312,8 +3489,6 @@
 		client = 0;
 		break;
 	    }
-	    client->sharedInstance = (0 != client->getProperty(kIOUserClientSharedInstanceKey));
-	    client->closed = false;
 	    OSString * creatorName = IOCopyLogNameForPID(proc_selfpid());
 	    if (creatorName)
 	    {
@@ -3345,7 +3520,9 @@
 
     if (client->sharedInstance || OSCompareAndSwap8(0, 1, &client->closed)) 
     {
+	IOLockLock(client->lock);
 	client->clientClose();
+	IOLockUnlock(client->lock);
     }
     else
     {
@@ -3381,11 +3558,15 @@
 	mach_port_t port,
 	uint32_t reference)
 {
+    kern_return_t ret;
     CHECK( IOUserClient, connection, client );
 
     IOStatisticsClientCall();
-    return( client->registerNotificationPort( port, notification_type,
-						(io_user_reference_t) reference ));
+    IOLockLock(client->lock);
+    ret = client->registerNotificationPort( port, notification_type,
+						(io_user_reference_t) reference );
+    IOLockUnlock(client->lock);
+    return (ret);
 }
 
 /* Routine io_connect_set_notification_port */
@@ -3395,11 +3576,15 @@
 	mach_port_t port,
 	io_user_reference_t reference)
 {
+    kern_return_t ret;
     CHECK( IOUserClient, connection, client );
 
     IOStatisticsClientCall();
-    return( client->registerNotificationPort( port, notification_type,
-						reference ));
+    IOLockLock(client->lock);
+    ret = client->registerNotificationPort( port, notification_type,
+						reference );
+    IOLockUnlock(client->lock);
+    return (ret);
 }
 
 /* Routine io_connect_map_memory_into_task */
@@ -3519,7 +3704,7 @@
 {
     IOReturn		err;
     IOOptionBits	options = 0;
-    IOMemoryDescriptor * memory;
+    IOMemoryDescriptor * memory = 0;
     IOMemoryMap *	map;
 
     CHECK( IOUserClient, connection, client );
@@ -3631,6 +3816,7 @@
     OSObject *           structureVariableOutputData = 0;
 
     bzero(&args.__reserved[0], sizeof(args.__reserved));
+    args.__reservedA = 0;
     args.version = kIOExternalMethodArgumentsCurrentVersion;
 
     args.selector = selector;
@@ -3645,9 +3831,12 @@
     args.structureInput = inband_input;
     args.structureInputSize = inband_inputCnt;
 
+    if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t)))    return (kIOReturnIPCError);
+
     if (ool_input)
 	inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size, 
-						    kIODirectionOut, current_task());
+						    kIODirectionOut | kIOMemoryMapCopyOnWrite,
+						    current_task());
 
     args.structureInputDescriptor = inputMD;
 
@@ -3724,6 +3913,7 @@
     IOMemoryDescriptor * outputMD = 0;
 
     bzero(&args.__reserved[0], sizeof(args.__reserved));
+    args.__reservedA = 0;
     args.version = kIOExternalMethodArgumentsCurrentVersion;
 
     args.selector = selector;
@@ -3738,9 +3928,13 @@
     args.structureInput = inband_input;
     args.structureInputSize = inband_inputCnt;
 
+    if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t)))    return (kIOReturnIPCError);
+    if (ool_output && (*ool_output_size <= sizeof(io_struct_inband_t))) return (kIOReturnIPCError);
+
     if (ool_input)
 	inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size, 
-						    kIODirectionOut, current_task());
+						    kIODirectionOut | kIOMemoryMapCopyOnWrite,
+						    current_task());
 
     args.structureInputDescriptor = inputMD;
 
@@ -3804,6 +3998,7 @@
     IOMemoryDescriptor * outputMD = 0;
 
     bzero(&args.__reserved[0], sizeof(args.__reserved));
+    args.__reservedA = 0;
     args.version = kIOExternalMethodArgumentsCurrentVersion;
 
     reference[0]	     = (io_user_reference_t) wake_port;
@@ -3815,15 +4010,21 @@
     args.asyncWakePort       = wake_port;
     args.asyncReference      = reference;
     args.asyncReferenceCount = referenceCnt;
+
+    args.structureVariableOutputData = 0;
 
     args.scalarInput = scalar_input;
     args.scalarInputCount = scalar_inputCnt;
     args.structureInput = inband_input;
     args.structureInputSize = inband_inputCnt;
 
+    if (ool_input && (ool_input_size <= sizeof(io_struct_inband_t)))    return (kIOReturnIPCError);
+    if (ool_output && (*ool_output_size <= sizeof(io_struct_inband_t))) return (kIOReturnIPCError);
+
     if (ool_input)
 	inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
-						    kIODirectionOut, current_task());
+						    kIODirectionOut | kIOMemoryMapCopyOnWrite,
+						    current_task());
 
     args.structureInputDescriptor = inputMD;
 
@@ -3909,12 +4110,14 @@
 
 	if( inputCount != method->count0)
 	{
-	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
 	    continue;
 	}
 	if( *outputCount != method->count1)
 	{
-	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
 	    continue;
 	}
 
@@ -4143,12 +4346,14 @@
 
 	if( inputCount != method->count0)
 	{
-	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
 	    continue;
 	}
 	if( *outputCount != method->count1)
 	{
-	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
 	    continue;
 	}
 
@@ -4253,13 +4458,15 @@
     do {
 	if( inputCount != method->count0)
 	{
-	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
 	    continue;
 	}
 	if( (kIOUCVariableStructureSize != method->count1)
 		&& (*outputCount != method->count1))
 	{
-	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
 	    continue;
 	}
 
@@ -4326,13 +4533,15 @@
     do {
 	if( inputCount != method->count0)
 	{
-	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
 	    continue;
 	}
 	if( (kIOUCVariableStructureSize != method->count1)
 		&& (*outputCount != method->count1))
 	{
-	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
 	    continue;
 	}
 
@@ -4424,13 +4633,15 @@
     {
 	if (inputCount != method->count0)
 	{
-	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
 	    continue;
 	}
 	if( (kIOUCVariableStructureSize != method->count1)
 		&& (inputStructCount != method->count1))
 	{
-	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputStructCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputStructCount, uint64_t, (uint64_t)method->count1);
 	    continue;
 	}
 
@@ -4500,13 +4711,15 @@
     {
 	if (inputCount != method->count0)
 	{
-	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
 	    continue;
 	}
 	if( (kIOUCVariableStructureSize != method->count1)
 		&& (inputStructCount != method->count1))
 	{
-	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputStructCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputStructCount, uint64_t, (uint64_t)method->count1);
 	    continue;
 	}
 
@@ -4596,13 +4809,15 @@
 	if( (kIOUCVariableStructureSize != method->count0)
 		&& (inputCount != method->count0))
 	{
-	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0, (uint64_t)kIOUCVariableStructureSize);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
 	    continue;
 	}
 	if( (kIOUCVariableStructureSize != method->count1)
 		&& (*outputCount != method->count1))
 	{
-	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
 	    continue;
 	}
 
@@ -4650,13 +4865,15 @@
 	if( (kIOUCVariableStructureSize != method->count0)
 		&& (inputCount != method->count0))
 	{
-	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient inputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)inputCount, (uint64_t)method->count0, (uint64_t)kIOUCVariableStructureSize);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)inputCount, uint64_t, (uint64_t)method->count0);
 	    continue;
 	}
 	if( (kIOUCVariableStructureSize != method->count1)
 		&& (*outputCount != method->count1))
 	{
-	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
+	    IOLog("%s:%d %s: IOUserClient outputCount count mismatch 0x%llx 0x%llx 0x%llx\n", __FUNCTION__, __LINE__, object->getName(), (uint64_t)*outputCount, (uint64_t)method->count1, (uint64_t)kIOUCVariableStructureSize);
+	    DTRACE_IO2(iokit_count_mismatch, uint64_t, (uint64_t)*outputCount, uint64_t, (uint64_t)method->count1);
 	    continue;
 	}
 
@@ -4681,6 +4898,10 @@
     return( err);
 }
 
+#if !NO_KEXTD
+bool gIOKextdClearedBusy = false;
+#endif
+
 /* Routine io_catalog_send_data */
 kern_return_t is_io_catalog_send_data(
         mach_port_t		master_port,
@@ -4689,6 +4910,9 @@
         mach_msg_type_number_t 	inDataCount,
         kern_return_t *		result)
 {
+#if NO_KEXTD
+    return kIOReturnNotPrivileged;
+#else /* NO_KEXTD */
     OSObject * obj = 0;
     vm_offset_t data;
     kern_return_t kr = kIOReturnError;
@@ -4704,6 +4928,16 @@
         ( !inData || !inDataCount) ) 
     {
         return kIOReturnBadArgument;
+    }
+
+    if (!IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management"))
+    {
+        OSString * taskName = IOCopyLogNameForPID(proc_selfpid());
+        IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName ? taskName->getCStringNoCopy() : "");
+        OSSafeReleaseNULL(taskName);
+        // For now, fake success to not break applications relying on this function succeeding.
+        // See <rdar://problem/32554970> for more details.
+        return kIOReturnSuccess;
     }
 
     if (inData) {
@@ -4816,14 +5050,12 @@
 
         case kIOCatalogKextdFinishedLaunching: {
 #if !NO_KEXTD
-                static bool clearedBusy = false;
-
-                if (!clearedBusy) {
+                if (!gIOKextdClearedBusy) {
                     IOService * serviceRoot = IOService::getServiceRoot();
                     if (serviceRoot) {
                         IOServiceTrace(IOSERVICE_KEXTD_READY, 0, 0, 0, 0);
                         serviceRoot->adjustBusy(-1);
-                        clearedBusy = true;
+                        gIOKextdClearedBusy = true;
                     }
                 }
 #endif
@@ -4837,9 +5069,10 @@
     }
 
     if (obj) obj->release();
-    
+
     *result = kr;
     return( KERN_SUCCESS);
+#endif /* NO_KEXTD */
 }
 
 /* Routine io_catalog_terminate */
@@ -4926,7 +5159,7 @@
         vm_size_t size;
 
         size = s->getLength();
-        kr = vm_allocate(kernel_map, &data, size, VM_FLAGS_ANYWHERE);
+        kr = vm_allocate_kernel(kernel_map, &data, size, VM_FLAGS_ANYWHERE, VM_KERN_MEMORY_IOKIT);
         if ( kr == kIOReturnSuccess ) {
             bcopy(s->text(), (void *)data, size);
             kr = vm_map_copyin(kernel_map, (vm_map_address_t)data,