]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOUserClient.cpp
xnu-4570.31.3.tar.gz
[apple/xnu.git] / iokit / Kernel / IOUserClient.cpp
index 5cfa033774d2b0a1d01b1cb51bca21148da429b9..6a3fc814b113beef0832682348598ed16ae60df8 100644 (file)
@@ -37,6 +37,7 @@
 #include <IOKit/IOMemoryDescriptor.h>
 #include <IOKit/IOBufferMemoryDescriptor.h>
 #include <IOKit/IOLib.h>
 #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>
 #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 <sys/kauth.h>
 #include <sys/codesign.h>
 
+#include <mach/sdt.h>
+
 #if CONFIG_MACF
 
 extern "C" {
 #if CONFIG_MACF
 
 extern "C" {
@@ -69,8 +72,9 @@ extern "C" {
 
 enum
 {
 
 enum
 {
-    kIOUCAsync0Flags = 3ULL,
-    kIOUCAsync64Flag = 1ULL
+    kIOUCAsync0Flags          = 3ULL,
+    kIOUCAsync64Flag          = 1ULL,
+    kIOUCAsyncErrorLoggedFlag = 2ULL
 };
 
 #if IOKITSTATS
 };
 
 #if IOKITSTATS
@@ -99,6 +103,25 @@ do { \
 
 #endif /* IOKITSTATS */
 
 
 #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 */
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 // definitions we should get from osfmk
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 // definitions we should get from osfmk
@@ -616,6 +639,7 @@ class IOServiceUserNotification : public IOUserNotification
     OSArray    *       newSet;
     OSObject   *       lastEntry;
     bool               armed;
     OSArray    *       newSet;
     OSObject   *       lastEntry;
     bool               armed;
+    bool                ipcLogged;
 
 public:
 
 
 public:
 
@@ -623,6 +647,7 @@ public:
                        void * reference, vm_size_t referenceSize,
                       bool clientIs64 );
     virtual void free() APPLE_KEXT_OVERRIDE;
                        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 );
 
     static bool _handler( void * target,
                           void * ref, IOService * newService, IONotifier * notifier );
@@ -646,6 +671,7 @@ class IOServiceMessageUserNotification : public IOUserNotification
     vm_size_t          msgSize;
     uint8_t            clientIs64;
     int                        owningPID;
     vm_size_t          msgSize;
     uint8_t            clientIs64;
     int                        owningPID;
+    bool                ipcLogged;
 
 public:
 
 
 public:
 
@@ -655,6 +681,7 @@ public:
                       bool clientIs64 );
 
     virtual void free() APPLE_KEXT_OVERRIDE;
                       bool clientIs64 );
 
     virtual void free() APPLE_KEXT_OVERRIDE;
+    void invalidatePort(void);
     
     static IOReturn _handler( void * target, void * ref,
                               UInt32 messageType, IOService * provider,
     
     static IOReturn _handler( void * target, void * ref,
                               UInt32 messageType, IOService * provider,
@@ -760,6 +787,11 @@ bool IOServiceUserNotification::init( mach_port_t port, natural_t type,
     return( true );
 }
 
     return( true );
 }
 
+void IOServiceUserNotification::invalidatePort(void)
+{
+    if (pingMsg) pingMsg->msgHdr.msgh_remote_port = MACH_PORT_NULL;
+}
+
 void IOServiceUserNotification::free( void )
 {
     PingMsg   *        _pingMsg;
 void IOServiceUserNotification::free( void )
 {
     PingMsg   *        _pingMsg;
@@ -830,8 +862,11 @@ bool IOServiceUserNotification::handler( void * ref,
        if( port)
            iokit_release_port( port );
 
        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 );
     }
 
     return( true );
@@ -841,12 +876,11 @@ OSObject * IOServiceUserNotification::getNextObject()
 {
     unsigned int       count;
     OSObject *         result;
 {
     unsigned int       count;
     OSObject *         result;
+    OSObject *         releaseEntry;
 
 
-    IOTakeLock( lock );
-
-    if( lastEntry)
-        lastEntry->release();
+    IOLockLock(lock);
 
 
+    releaseEntry = lastEntry;
     count = newSet->getCount();
     if( count ) {
         result = newSet->getObject( count - 1 );
     count = newSet->getCount();
     if( count ) {
         result = newSet->getObject( count - 1 );
@@ -858,7 +892,9 @@ OSObject * IOServiceUserNotification::getNextObject()
     }
     lastEntry = result;
 
     }
     lastEntry = result;
 
-    IOUnlock( lock );
+    IOLockUnlock(lock);
+
+    if (releaseEntry) releaseEntry->release();
 
     return( result );
 }
 
     return( result );
 }
@@ -884,7 +920,7 @@ bool IOServiceMessageUserNotification::init( mach_port_t port, natural_t type,
     owningPID = proc_selfpid();
 
     extraSize += sizeof(IOServiceInterestContent64);
     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 );
     pingMsg = (PingMsg *) IOMalloc( msgSize);
     if( !pingMsg)
         return( false );
@@ -912,6 +948,11 @@ bool IOServiceMessageUserNotification::init( mach_port_t port, natural_t type,
     return( true );
 }
 
     return( true );
 }
 
+void IOServiceMessageUserNotification::invalidatePort(void)
+{
+    if (pingMsg) pingMsg->msgHdr.msgh_remote_port = MACH_PORT_NULL;
+}
+
 void IOServiceMessageUserNotification::free( void )
 {
     PingMsg *  _pingMsg;
 void IOServiceMessageUserNotification::free( void )
 {
     PingMsg *  _pingMsg;
@@ -940,13 +981,17 @@ IOReturn IOServiceMessageUserNotification::_handler( void * target, void * ref,
 
 IOReturn IOServiceMessageUserNotification::handler( void * ref,
                                     UInt32 messageType, IOService * provider,
 
 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;
     kern_return_t               kr;
+    vm_size_t                           argSize;
+    vm_size_t                           thisMsgSize;
     ipc_port_t                          thisPort, providerPort;
     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)
     {
 
     if (kIOMessageCopyClientID == messageType)
     {
@@ -954,24 +999,16 @@ IOReturn IOServiceMessageUserNotification::handler( void * ref,
         return (kIOReturnSuccess);
     }
 
         return (kIOReturnSuccess);
     }
 
-    data->messageType = messageType;
-
-    if( argSize == 0)
+    if (callerArgSize == 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 (clientIs64) argSize = sizeof(data->messageArgument[0]);
+       else            argSize = sizeof(uint32_t);
     }
     else
     {
     }
     else
     {
-        if( argSize > kIOUserNotifyMaxMessageSize)
-            argSize = kIOUserNotifyMaxMessageSize;
-        bcopy( messageArgument, data->messageArgument, argSize );
+        if( callerArgSize > kIOUserNotifyMaxMessageSize)
+            callerArgSize = kIOUserNotifyMaxMessageSize;
+        argSize = callerArgSize;
     }
 
     // adjust message size for ipc restrictions
     }
 
     // adjust message size for ipc restrictions
@@ -979,20 +1016,55 @@ IOReturn IOServiceMessageUserNotification::handler( void * ref,
     type = pingMsg->notifyHeader.type;
     type &= ~(kIOKitNoticationMsgSizeMask << kIOKitNoticationTypeSizeAdjShift);
     type |= ((argSize & kIOKitNoticationMsgSizeMask) << kIOKitNoticationTypeSizeAdjShift);
     type = pingMsg->notifyHeader.type;
     type &= ~(kIOKitNoticationMsgSizeMask << kIOKitNoticationTypeSizeAdjShift);
     type |= ((argSize & kIOKitNoticationMsgSizeMask) << kIOKitNoticationTypeSizeAdjShift);
-    pingMsg->notifyHeader.type = type;
     argSize = (argSize + kIOKitNoticationMsgSizeMask) & ~kIOKitNoticationMsgSizeMask;
 
     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 );
 
     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 );
     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)
                                                 (MACH_SEND_MSG | MACH_SEND_ALWAYS | MACH_SEND_IMPORTANCE),
                                                 0);
     if( thisPort)
@@ -1000,8 +1072,14 @@ IOReturn IOServiceMessageUserNotification::handler( void * ref,
     if( providerPort)
        iokit_release_port( providerPort );
 
     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 );
 }
 
     return( kIOReturnSuccess );
 }
@@ -1552,17 +1630,21 @@ IOMemoryMap * IOUserClient::mapClientMemory64(
 {
     IOReturn           err;
     IOOptionBits       options = 0;
 {
     IOReturn           err;
     IOOptionBits       options = 0;
-    IOMemoryDescriptor * memory;
+    IOMemoryDescriptor * memory = 0;
     IOMemoryMap *      map = 0;
 
     err = clientMemoryForType( (UInt32) type, &options, &memory );
 
     if( memory && (kIOReturnSuccess == err)) {
 
     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();
         options = (options & ~kIOMapUserOptionsMask)
                | (mapFlags & kIOMapUserOptionsMask);
        map = memory->createMappingInTask( task, atAddress, options );
        memory->release();
+
+        FAKE_STACK_FRAME_END();
     }
 
     return( map );
     }
 
     return( map );
@@ -1589,6 +1671,17 @@ IOExternalAsyncMethod * IOUserClient::getExternalAsyncMethodForIndex( UInt32 /*
     return( 0 );
 }
 
     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)
 {
 IOExternalMethod * IOUserClient::
 getTargetAndMethodForIndex(IOService **targetP, UInt32 index)
 {
@@ -1611,12 +1704,6 @@ getAsyncTargetAndMethodForIndex(IOService ** targetP, UInt32 index)
     return method;
 }
 
     return method;
 }
 
-IOExternalTrap * IOUserClient::
-getExternalTrapForIndex(UInt32 index)
-{
-       return NULL;
-}
-
 IOExternalTrap * IOUserClient::
 getTargetAndTrapForIndex(IOService ** targetP, UInt32 index)
 {
 IOExternalTrap * IOUserClient::
 getTargetAndTrapForIndex(IOService ** targetP, UInt32 index)
 {
@@ -1628,6 +1715,7 @@ getTargetAndTrapForIndex(IOService ** targetP, UInt32 index)
 
       return trap;
 }
 
       return trap;
 }
+#pragma clang diagnostic pop
 
 IOReturn IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference)
 {
 
 IOReturn IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference)
 {
@@ -1713,6 +1801,7 @@ IOReturn IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference,
     if (numArgs > kMaxAsyncArgs)
         return kIOReturnMessageTooLarge;
 
     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;
     replyMsg.msgHdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND /*remote*/,
                                                0 /*local*/);
     replyMsg.msgHdr.msgh_remote_port = replyPort;
@@ -1761,8 +1850,11 @@ IOReturn IOUserClient::_sendAsyncResult64(OSAsyncReference64 reference,
                kr = mach_msg_send_from_kernel_proper( &replyMsg.msgHdr,
                                                                                 replyMsg.msgHdr.msgh_size);
        }
                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;
 }
 
     return kr;
 }
 
@@ -1842,38 +1934,36 @@ kern_return_t is_io_object_get_superclass(
        io_name_t obj_name, 
        io_name_t class_name)
 {
        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;
+    IOReturn            ret;
+    const OSMetaClass * meta;
+    const OSMetaClass * super;
+    const OSSymbol    * name;
+    const char        * cstr;
 
 
-       if (!obj_name || !class_name) 
-               return (kIOReturnBadArgument);
+    if (!obj_name || !class_name)          return (kIOReturnBadArgument);
+    if (master_port != master_device_port) return( kIOReturnNotPrivileged);
 
 
-    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);
 
 
-       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 );
-       }
+    OSSafeReleaseNULL(name);
+    if (meta) meta->releaseMetaClass();
 
 
-       my_cstr = superclass->getClassName();
-               
-       if (my_cstr) {
-               strlcpy(class_name, my_cstr, sizeof(io_name_t));
-               return( kIOReturnSuccess );
-       }
-       return (kIOReturnNotFound);
+    return (ret);
 }
 
 /* Routine io_object_get_bundle_identifier */
 }
 
 /* Routine io_object_get_bundle_identifier */
@@ -1882,38 +1972,36 @@ kern_return_t is_io_object_get_bundle_identifier(
        io_name_t obj_name, 
        io_name_t bundle_name)
 {
        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;
+    IOReturn            ret;
+    const OSMetaClass * meta;
+    const OSSymbol    * name;
+    const OSSymbol    * identifier;
+    const char        * cstr;
 
 
-       if (!obj_name || !bundle_name) 
-               return (kIOReturnBadArgument);
+    if (!obj_name || !bundle_name)         return (kIOReturnBadArgument);
+    if (master_port != master_device_port) return( kIOReturnNotPrivileged);
 
 
-    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();
-       }
+    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);
 
 
-       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 );
-       }
+    OSSafeReleaseNULL(name);
+    if (meta) meta->releaseMetaClass();
 
 
-       return (kIOReturnBadArgument);
+    return (ret);
 }
 
 /* Routine io_object_conforms_to */
 }
 
 /* Routine io_object_conforms_to */
@@ -1999,8 +2087,9 @@ static kern_return_t internal_io_service_match_property_table(
     OSObject *         obj;
     OSDictionary *     dict;
 
     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;
     if( (dict = OSDynamicCast( OSDictionary, obj))) {
         *matches = service->passiveMatch( dict );
        kr = kIOReturnSuccess;
@@ -2019,7 +2108,7 @@ kern_return_t is_io_service_match_property_table(
        io_string_t matching,
        boolean_t *matches )
 {
        io_string_t matching,
        boolean_t *matches )
 {
-    return (internal_io_service_match_property_table(service, matching, 0, matches));
+    return (kIOReturnUnsupported);
 }
 
 
 }
 
 
@@ -2071,8 +2160,9 @@ static kern_return_t internal_io_service_get_matching_services(
     if( master_port != master_device_port)
         return( kIOReturnNotPrivileged);
 
     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;
     if( (dict = OSDynamicCast( OSDictionary, obj))) {
         *existing = IOUserIterator::withIterator(IOService::getMatchingServices( dict ));
        kr = kIOReturnSuccess;
@@ -2091,7 +2181,7 @@ kern_return_t is_io_service_get_matching_services(
        io_string_t matching,
        io_iterator_t *existing )
 {
        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 */
 }
 
 /* Routine io_service_get_matching_services_ool */
@@ -2145,8 +2235,9 @@ static kern_return_t internal_io_service_get_matching_service(
     if( master_port != master_device_port)
         return( kIOReturnNotPrivileged);
 
     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;
     if( (dict = OSDynamicCast( OSDictionary, obj))) {
         *service = IOService::copyMatchingService( dict );
        kr = *service ? kIOReturnSuccess : kIOReturnNotFound;
@@ -2165,7 +2256,7 @@ kern_return_t is_io_service_get_matching_service(
        io_string_t matching,
        io_service_t *service )
 {
        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 */
 }
 
 /* Routine io_service_get_matching_services_ool */
@@ -2229,18 +2320,13 @@ static kern_return_t internal_io_service_add_notification(
     do {
         err = kIOReturnNoResources;
 
     do {
         err = kIOReturnNoResources;
 
+        if (matching_size > (sizeof(io_struct_inband_t) * 1024)) return(kIOReturnMessageTooLarge);
+
         if( !(sym = OSSymbol::withCString( notification_type )))
            err = kIOReturnNoResources;
 
         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;
         if (!dict) {
             err = kIOReturnBadArgument;
            continue;
@@ -2252,7 +2338,8 @@ static kern_return_t internal_io_service_add_notification(
        else if( (sym == gIOMatchedNotification)
              || (sym == gIOFirstMatchNotification))
            userMsgType = kIOServiceMatchedNotificationType;
        else if( (sym == gIOMatchedNotification)
              || (sym == gIOFirstMatchNotification))
            userMsgType = kIOServiceMatchedNotificationType;
-       else if( sym == gIOTerminatedNotification)
+       else if ((sym == gIOTerminatedNotification)
+             || (sym == gIOWillTerminateNotification))
            userMsgType = kIOServiceTerminatedNotificationType;
        else
            userMsgType = kLastIOKitNotificationType;
            userMsgType = kIOServiceTerminatedNotificationType;
        else
            userMsgType = kLastIOKitNotificationType;
@@ -2261,7 +2348,6 @@ static kern_return_t internal_io_service_add_notification(
 
         if( userNotify && !userNotify->init( port, userMsgType,
                                              reference, referenceSize, client64)) {
 
         if( userNotify && !userNotify->init( port, userMsgType,
                                              reference, referenceSize, client64)) {
-                       iokit_release_port_send(port);
             userNotify->release();
             userNotify = 0;
         }
             userNotify->release();
             userNotify = 0;
         }
@@ -2279,6 +2365,13 @@ static kern_return_t internal_io_service_add_notification(
 
     } while( false );
 
 
     } while( false );
 
+    if ((kIOReturnSuccess != err) && userNotify)
+    {
+       userNotify->invalidatePort();
+       userNotify->release();
+       userNotify = 0;
+    }
+
     if( sym)
        sym->release();
     if( dict)
     if( sym)
        sym->release();
     if( dict)
@@ -2298,9 +2391,7 @@ kern_return_t is_io_service_add_notification(
        mach_msg_type_number_t referenceCnt,
        io_object_t * notification )
 {
        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 */
 }
 
 /* Routine io_service_add_notification_64 */
@@ -2313,9 +2404,7 @@ kern_return_t is_io_service_add_notification_64(
        mach_msg_type_number_t referenceCnt,
        io_object_t *notification )
 {
        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 */
 }
 
 /* Routine io_service_add_notification_bin */
@@ -2458,7 +2547,6 @@ static kern_return_t internal_io_service_add_interest_notification(
                                              reference, referenceSize,
                                             kIOUserNotifyMaxMessageSize,
                                             client64 )) {
                                              reference, referenceSize,
                                             kIOUserNotifyMaxMessageSize,
                                             client64 )) {
-                       iokit_release_port_send(port);
             userNotify->release();
             userNotify = 0;
         }
             userNotify->release();
             userNotify = 0;
         }
@@ -2478,6 +2566,13 @@ static kern_return_t internal_io_service_add_interest_notification(
 
     } while( false );
 
 
     } while( false );
 
+    if ((kIOReturnSuccess != err) && userNotify)
+    {
+       userNotify->invalidatePort();
+       userNotify->release();
+       userNotify = 0;
+    }
+
     return( err );
 }
 
     return( err );
 }
 
@@ -2849,6 +2944,7 @@ kern_return_t is_io_registry_entry_get_property_bytes(
     if( (data = OSDynamicCast( OSData, obj ))) {
        len = data->getLength();
        bytes = data->getBytesNoCopy();
     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;
 
     } else if( (str = OSDynamicCast( OSString, obj ))) {
        len = str->getLength() + 1;
@@ -2861,6 +2957,7 @@ kern_return_t is_io_registry_entry_get_property_bytes(
     } else if( (off = OSDynamicCast( OSNumber, obj ))) {
        offsetBytes = off->unsigned64BitValue();
        len = off->numberOfBytes();
     } 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 *)
        bytes = &offsetBytes;
 #ifdef __BIG_ENDIAN__
        bytes = (const void *)
@@ -2947,7 +3044,7 @@ kern_return_t is_io_registry_entry_get_property_recursively(
 #endif
 
     obj = entry->copyProperty( property_name,
 #endif
 
     obj = entry->copyProperty( property_name,
-                               IORegistryEntry::getPlane( plane ), options);
+                               IORegistryEntry::getPlane( plane ), options );
     if( !obj)
         return( kIOReturnNotFound );
 
     if( !obj)
         return( kIOReturnNotFound );
 
@@ -2971,86 +3068,13 @@ kern_return_t is_io_registry_entry_get_property_recursively(
     return( err );
 }
 
     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(
        io_object_t registry_entry,
        io_buf_ptr_t *properties,
        mach_msg_type_number_t *propertiesCnt )
 {
 /* Routine io_registry_entry_get_properties */
 kern_return_t is_io_registry_entry_get_properties(
        io_object_t registry_entry,
        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
 }
 
 #if CONFIG_MACF
@@ -3073,13 +3097,13 @@ GetPropertiesEditor(void                  * reference,
 
     if (!ref->root) ref->root = container;
     if (ref->root == container)
 
     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);
 }
 
     return (value);
 }
 
@@ -3118,9 +3142,9 @@ kern_return_t is_io_registry_entry_get_properties_bin(
 
     if (kIOReturnSuccess == err)
     {
 
     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();
 
     }
     s->release();
 
@@ -3148,25 +3172,29 @@ kern_return_t is_io_registry_entry_get_property_bin(
         return kIOReturnNotPermitted;
 #endif
 
         return kIOReturnNotPermitted;
 #endif
 
-    if ((kIORegistryIterateRecursively & options) && plane[0])
+    sym = OSSymbol::withCString(property_name);
+    if (!sym) return (kIOReturnNoMemory);
+
+    if (gIORegistryEntryPropertyKeysKey == sym)
     {
     {
-       obj = entry->copyProperty(property_name,
-                                 IORegistryEntry::getPlane(plane), options);
+        obj = entry->copyPropertyKeys();
     }
     else
     {
     }
     else
     {
-       obj = entry->copyProperty(property_name);
+        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);
     }
 
     }
 
-    if( !obj)
-        return( kIOReturnNotFound );
-
-    sym = OSSymbol::withCString(property_name);
-    if (sym)
-    {
-        if (gIORemoveOnReadProperties->containsObject(sym)) entry->removeProperty(sym);
-        sym->release();
-    }
+    sym->release();
+    if (!obj) return (kIOReturnNotFound);
 
     OSSerialize * s = OSSerialize::binaryWithCapacity(4096);
     if( !s) {
 
     OSSerialize * s = OSSerialize::binaryWithCapacity(4096);
     if( !s) {
@@ -3212,6 +3240,8 @@ kern_return_t is_io_registry_entry_set_properties
 
     if( KERN_SUCCESS == err) {
 
 
     if( KERN_SUCCESS == err) {
 
+        FAKE_STACK_FRAME(entry->getMetaClass());
+
         // must return success after vm_map_copyout() succeeds
         obj = OSUnserializeXML( (const char *) data, propertiesCnt );
        vm_deallocate( kernel_map, data, propertiesCnt );
         // must return success after vm_map_copyout() succeeds
         obj = OSUnserializeXML( (const char *) data, propertiesCnt );
        vm_deallocate( kernel_map, data, propertiesCnt );
@@ -3232,6 +3262,9 @@ kern_return_t is_io_registry_entry_set_properties
 
        if (obj)
            obj->release();
 
        if (obj)
            obj->release();
+
+        FAKE_STACK_FRAME_END();
+
     } else
         res = err;
 
     } else
         res = err;
 
@@ -3248,7 +3281,7 @@ kern_return_t is_io_registry_entry_get_child_iterator(
     CHECK( IORegistryEntry, registry_entry, entry );
 
     *iterator = entry->getChildIterator(
     CHECK( IORegistryEntry, registry_entry, entry );
 
     *iterator = entry->getChildIterator(
-       IORegistryEntry::getPlane( plane ));
+    IORegistryEntry::getPlane( plane ));
 
     return( kIOReturnSuccess );
 }
 
     return( kIOReturnSuccess );
 }
@@ -3376,7 +3409,8 @@ kern_return_t is_io_service_open_extended(
 
     do
     {
 
     do
     {
-       if (properties)
+       if (properties) return (kIOReturnUnsupported);
+#if 0
        {
            OSObject *      obj;
            vm_offset_t     data;
        {
            OSObject *      obj;
            vm_offset_t     data;
@@ -3404,7 +3438,7 @@ kern_return_t is_io_service_open_extended(
            if (kIOReturnSuccess != res)
                break;
        }
            if (kIOReturnSuccess != res)
                break;
        }
-
+#endif
        crossEndian = (ndr.int_rep != NDR_record.int_rep);
        if (crossEndian)
        {
        crossEndian = (ndr.int_rep != NDR_record.int_rep);
        if (crossEndian)
        {
@@ -3656,7 +3690,7 @@ kern_return_t is_io_connect_unmap_memory_from_task
 {
     IOReturn           err;
     IOOptionBits       options = 0;
 {
     IOReturn           err;
     IOOptionBits       options = 0;
-    IOMemoryDescriptor * memory;
+    IOMemoryDescriptor * memory = 0;
     IOMemoryMap *      map;
 
     CHECK( IOUserClient, connection, client );
     IOMemoryMap *      map;
 
     CHECK( IOUserClient, connection, client );
@@ -3768,6 +3802,7 @@ kern_return_t is_io_connect_method_var_output
     OSObject *           structureVariableOutputData = 0;
 
     bzero(&args.__reserved[0], sizeof(args.__reserved));
     OSObject *           structureVariableOutputData = 0;
 
     bzero(&args.__reserved[0], sizeof(args.__reserved));
+    args.__reservedA = 0;
     args.version = kIOExternalMethodArgumentsCurrentVersion;
 
     args.selector = selector;
     args.version = kIOExternalMethodArgumentsCurrentVersion;
 
     args.selector = selector;
@@ -3782,9 +3817,12 @@ kern_return_t is_io_connect_method_var_output
     args.structureInput = inband_input;
     args.structureInputSize = inband_inputCnt;
 
     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, 
     if (ool_input)
        inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size, 
-                                                   kIODirectionOut, current_task());
+                                                   kIODirectionOut | kIOMemoryMapCopyOnWrite,
+                                                   current_task());
 
     args.structureInputDescriptor = inputMD;
 
 
     args.structureInputDescriptor = inputMD;
 
@@ -3861,6 +3899,7 @@ kern_return_t is_io_connect_method
     IOMemoryDescriptor * outputMD = 0;
 
     bzero(&args.__reserved[0], sizeof(args.__reserved));
     IOMemoryDescriptor * outputMD = 0;
 
     bzero(&args.__reserved[0], sizeof(args.__reserved));
+    args.__reservedA = 0;
     args.version = kIOExternalMethodArgumentsCurrentVersion;
 
     args.selector = selector;
     args.version = kIOExternalMethodArgumentsCurrentVersion;
 
     args.selector = selector;
@@ -3875,9 +3914,13 @@ kern_return_t is_io_connect_method
     args.structureInput = inband_input;
     args.structureInputSize = inband_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, 
     if (ool_input)
        inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size, 
-                                                   kIODirectionOut, current_task());
+                                                   kIODirectionOut | kIOMemoryMapCopyOnWrite,
+                                                   current_task());
 
     args.structureInputDescriptor = inputMD;
 
 
     args.structureInputDescriptor = inputMD;
 
@@ -3941,6 +3984,7 @@ kern_return_t is_io_connect_async_method
     IOMemoryDescriptor * outputMD = 0;
 
     bzero(&args.__reserved[0], sizeof(args.__reserved));
     IOMemoryDescriptor * outputMD = 0;
 
     bzero(&args.__reserved[0], sizeof(args.__reserved));
+    args.__reservedA = 0;
     args.version = kIOExternalMethodArgumentsCurrentVersion;
 
     reference[0]            = (io_user_reference_t) wake_port;
     args.version = kIOExternalMethodArgumentsCurrentVersion;
 
     reference[0]            = (io_user_reference_t) wake_port;
@@ -3953,14 +3997,20 @@ kern_return_t is_io_connect_async_method
     args.asyncReference      = reference;
     args.asyncReferenceCount = referenceCnt;
 
     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;
 
     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,
     if (ool_input)
        inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
-                                                   kIODirectionOut, current_task());
+                                                   kIODirectionOut | kIOMemoryMapCopyOnWrite,
+                                                   current_task());
 
     args.structureInputDescriptor = inputMD;
 
 
     args.structureInputDescriptor = inputMD;
 
@@ -4046,12 +4096,14 @@ kern_return_t shim_io_connect_method_scalarI_scalarO(
 
        if( inputCount != method->count0)
        {
 
        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)
        {
            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;
        }
 
            continue;
        }
 
@@ -4280,12 +4332,14 @@ kern_return_t shim_io_async_method_scalarI_scalarO(
 
        if( inputCount != method->count0)
        {
 
        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)
        {
            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;
        }
 
            continue;
        }
 
@@ -4390,13 +4444,15 @@ kern_return_t shim_io_connect_method_scalarI_structureO(
     do {
        if( inputCount != method->count0)
        {
     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))
        {
            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;
        }
 
            continue;
        }
 
@@ -4463,13 +4519,15 @@ kern_return_t shim_io_async_method_scalarI_structureO(
     do {
        if( inputCount != method->count0)
        {
     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))
        {
            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;
        }
 
            continue;
        }
 
@@ -4561,13 +4619,15 @@ kern_return_t shim_io_connect_method_scalarI_structureI(
     {
        if (inputCount != method->count0)
        {
     {
        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))
        {
            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;
        }
 
            continue;
        }
 
@@ -4637,13 +4697,15 @@ kern_return_t shim_io_async_method_scalarI_structureI(
     {
        if (inputCount != method->count0)
        {
     {
        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))
        {
            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;
        }
 
            continue;
        }
 
@@ -4733,13 +4795,15 @@ kern_return_t shim_io_connect_method_structureI_structureO(
        if( (kIOUCVariableStructureSize != method->count0)
                && (inputCount != method->count0))
        {
        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))
        {
            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;
        }
 
            continue;
        }
 
@@ -4787,13 +4851,15 @@ kern_return_t shim_io_async_method_structureI_structureO(
        if( (kIOUCVariableStructureSize != method->count0)
                && (inputCount != method->count0))
        {
        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))
        {
            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;
        }
 
            continue;
        }
 
@@ -4818,6 +4884,10 @@ kern_return_t shim_io_async_method_structureI_structureO(
     return( err);
 }
 
     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,
 /* Routine io_catalog_send_data */
 kern_return_t is_io_catalog_send_data(
         mach_port_t            master_port,
@@ -4826,6 +4896,9 @@ kern_return_t is_io_catalog_send_data(
         mach_msg_type_number_t         inDataCount,
         kern_return_t *                result)
 {
         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;
     OSObject * obj = 0;
     vm_offset_t data;
     kern_return_t kr = kIOReturnError;
@@ -4843,6 +4916,16 @@ kern_return_t is_io_catalog_send_data(
         return kIOReturnBadArgument;
     }
 
         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) {
         vm_map_offset_t map_data;
 
     if (inData) {
         vm_map_offset_t map_data;
 
@@ -4953,14 +5036,12 @@ kern_return_t is_io_catalog_send_data(
 
         case kIOCatalogKextdFinishedLaunching: {
 #if !NO_KEXTD
 
         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);
                     IOService * serviceRoot = IOService::getServiceRoot();
                     if (serviceRoot) {
                         IOServiceTrace(IOSERVICE_KEXTD_READY, 0, 0, 0, 0);
                         serviceRoot->adjustBusy(-1);
-                        clearedBusy = true;
+                        gIOKextdClearedBusy = true;
                     }
                 }
 #endif
                     }
                 }
 #endif
@@ -4974,9 +5055,10 @@ kern_return_t is_io_catalog_send_data(
     }
 
     if (obj) obj->release();
     }
 
     if (obj) obj->release();
-    
+
     *result = kr;
     return( KERN_SUCCESS);
     *result = kr;
     return( KERN_SUCCESS);
+#endif /* NO_KEXTD */
 }
 
 /* Routine io_catalog_terminate */
 }
 
 /* Routine io_catalog_terminate */
@@ -5063,7 +5145,7 @@ kern_return_t is_io_catalog_get_data(
         vm_size_t size;
 
         size = s->getLength();
         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,
         if ( kr == kIOReturnSuccess ) {
             bcopy(s->text(), (void *)data, size);
             kr = vm_map_copyin(kernel_map, (vm_map_address_t)data,