]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOUserClient.cpp
xnu-4903.231.4.tar.gz
[apple/xnu.git] / iokit / Kernel / IOUserClient.cpp
index 985e3b201286c38571cd1d2fdd55c97da161fa5d..b99f027ddd6fa28a952469428e29dd759f473360 100644 (file)
@@ -40,6 +40,7 @@
 #include <IOKit/IOBSD.h>
 #include <IOKit/IOStatisticsPrivate.h>
 #include <IOKit/IOTimeStamp.h>
+#include <IOKit/IODeviceTreeSupport.h>
 #include <IOKit/system.h>
 #include <libkern/OSDebug.h>
 #include <sys/proc.h>
@@ -124,45 +125,13 @@ do { \
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-// definitions we should get from osfmk
-
-//typedef struct ipc_port * ipc_port_t;
-typedef natural_t ipc_kobject_type_t;
-
-#define IKOT_IOKIT_SPARE       27
-#define IKOT_IOKIT_CONNECT     29
-#define IKOT_IOKIT_OBJECT      30
-
 extern "C" {
 
-extern ipc_port_t iokit_alloc_object_port( io_object_t obj,
-                       ipc_kobject_type_t type );
-
-extern kern_return_t iokit_destroy_object_port( ipc_port_t port );
-
-extern mach_port_name_t iokit_make_send_right( task_t task,
-                               io_object_t obj, ipc_kobject_type_t type );
-
-extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta );
-
-extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task);
-
-extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef);
-
-extern ipc_port_t master_device_port;
-
-extern void iokit_retain_port( ipc_port_t port );
-extern void iokit_release_port( ipc_port_t port );
-extern void iokit_release_port_send( ipc_port_t port );
-
-extern kern_return_t iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type );
-
 #include <mach/mach_traps.h>
 #include <vm/vm_map.h>
 
 } /* extern "C" */
 
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
@@ -202,17 +171,28 @@ static IOLock *           gIOObjectPortLock;
 // not in dictForType() for debugging ease
 static OSDictionary *  gIOObjectPorts;
 static OSDictionary *  gIOConnectPorts;
+static OSDictionary *  gIOIdentifierPorts;
 
 OSDictionary * IOMachPort::dictForType( ipc_kobject_type_t type )
 {
     OSDictionary **            dict;
 
-    if( IKOT_IOKIT_OBJECT == type )
-       dict = &gIOObjectPorts;
-    else if( IKOT_IOKIT_CONNECT == type )
-       dict = &gIOConnectPorts;
-    else
-       return( 0 );
+    switch (type)
+    {
+       case IKOT_IOKIT_OBJECT:
+           dict = &gIOObjectPorts;
+           break;
+       case IKOT_IOKIT_CONNECT:
+           dict = &gIOConnectPorts;
+           break;
+       case IKOT_IOKIT_IDENT:
+           dict = &gIOIdentifierPorts;
+           break;
+       default:
+           panic("dictForType %d", type);
+           dict = NULL;
+           break;
+    }
 
     if( 0 == *dict)
         *dict = OSDictionary::withCapacity( 1 );
@@ -403,6 +383,7 @@ public:
     virtual void reset() APPLE_KEXT_OVERRIDE;
     virtual bool isValid() APPLE_KEXT_OVERRIDE;
     virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
+    virtual OSObject * copyNextObject();
 };
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -491,11 +472,20 @@ IOUserIterator::isValid()
 OSObject *
 IOUserIterator::getNextObject()
 {
-    OSObject * ret;
+    assert(false);
+    return (NULL);
+}
+
+OSObject *
+IOUserIterator::copyNextObject()
+{
+    OSObject * ret = NULL;
 
     IOLockLock(lock);
-    assert(OSDynamicCast(OSIterator, userIteratorObject));
-    ret = ((OSIterator *)userIteratorObject)->getNextObject();
+    if (userIteratorObject) {
+        ret = ((OSIterator *)userIteratorObject)->getNextObject();
+        if (ret) ret->retain();
+    }
     IOLockUnlock(lock);
 
     return (ret);
@@ -507,10 +497,19 @@ extern "C" {
 // functions called from osfmk/device/iokit_rpc.c
 
 void
-iokit_add_reference( io_object_t obj )
+iokit_add_reference( io_object_t obj, ipc_kobject_type_t type )
 {
-    if( obj)
-       obj->retain();
+    IOUserClient * uc;
+
+    if (!obj) return;
+
+    if ((IKOT_IOKIT_CONNECT == type)
+       && (uc = OSDynamicCast(IOUserClient, obj)))
+    {
+       OSIncrementAtomic(&uc->__ipc);
+    }
+
+    obj->retain();
 }
 
 void
@@ -520,18 +519,6 @@ iokit_remove_reference( io_object_t obj )
        obj->release();
 }
 
-void
-iokit_add_connect_reference( io_object_t obj )
-{
-    IOUserClient * uc;
-
-    if (!obj) return;
-
-    if ((uc = OSDynamicCast(IOUserClient, obj))) OSIncrementAtomic(&uc->__ipc);
-
-    obj->retain();
-}
-
 void
 iokit_remove_connect_reference( io_object_t obj )
 {
@@ -605,7 +592,9 @@ iokit_client_died( io_object_t obj, ipc_port_t /* port */,
        if( (client = OSDynamicCast( IOUserClient, obj )))
        {
            IOStatisticsClientCall();
+           IOLockLock(client->lock);
            client->clientDied();
+           IOLockUnlock(client->lock);
         }
     }
     else if( IKOT_IOKIT_OBJECT == type)
@@ -637,7 +626,6 @@ class IOServiceUserNotification : public IOUserNotification
     PingMsg    *       pingMsg;
     vm_size_t          msgSize;
     OSArray    *       newSet;
-    OSObject   *       lastEntry;
     bool               armed;
     bool                ipcLogged;
 
@@ -647,12 +635,14 @@ public:
                        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 );
     virtual bool handler( void * ref, IOService * newService );
 
     virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
+    virtual OSObject * copyNextObject() APPLE_KEXT_OVERRIDE;
 };
 
 class IOServiceMessageUserNotification : public IOUserNotification
@@ -680,6 +670,7 @@ public:
                       bool clientIs64 );
 
     virtual void free() APPLE_KEXT_OVERRIDE;
+    void invalidatePort(void);
     
     static IOReturn _handler( void * target, void * ref,
                               UInt32 messageType, IOService * provider,
@@ -689,6 +680,7 @@ public:
                               void * messageArgument, vm_size_t argSize );
 
     virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
+    virtual OSObject * copyNextObject() APPLE_KEXT_OVERRIDE;
 };
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -785,16 +777,19 @@ bool IOServiceUserNotification::init( mach_port_t port, natural_t type,
     return( true );
 }
 
+void IOServiceUserNotification::invalidatePort(void)
+{
+    if (pingMsg) pingMsg->msgHdr.msgh_remote_port = MACH_PORT_NULL;
+}
+
 void IOServiceUserNotification::free( void )
 {
     PingMsg   *        _pingMsg;
     vm_size_t  _msgSize;
     OSArray   *        _newSet;
-    OSObject  *        _lastEntry;
 
     _pingMsg   = pingMsg;
     _msgSize   = msgSize;
-    _lastEntry = lastEntry;
     _newSet    = newSet;
 
     super::free();
@@ -806,9 +801,6 @@ void IOServiceUserNotification::free( void )
         IOFree(_pingMsg, _msgSize);
        }
 
-    if( _lastEntry)
-        _lastEntry->release();
-
     if( _newSet)
         _newSet->release();
 }
@@ -864,16 +856,19 @@ bool IOServiceUserNotification::handler( void * ref,
 
     return( true );
 }
-
 OSObject * IOServiceUserNotification::getNextObject()
+{
+    assert(false);
+    return (NULL);
+}
+
+OSObject * IOServiceUserNotification::copyNextObject()
 {
     unsigned int       count;
     OSObject *         result;
-    OSObject *         releaseEntry;
 
     IOLockLock(lock);
 
-    releaseEntry = lastEntry;
     count = newSet->getCount();
     if( count ) {
         result = newSet->getObject( count - 1 );
@@ -883,12 +878,9 @@ OSObject * IOServiceUserNotification::getNextObject()
         result = 0;
         armed = true;
     }
-    lastEntry = result;
 
     IOLockUnlock(lock);
 
-    if (releaseEntry) releaseEntry->release();
-
     return( result );
 }
 
@@ -941,6 +933,11 @@ bool IOServiceMessageUserNotification::init( mach_port_t port, natural_t type,
     return( true );
 }
 
+void IOServiceMessageUserNotification::invalidatePort(void)
+{
+    if (pingMsg) pingMsg->msgHdr.msgh_remote_port = MACH_PORT_NULL;
+}
+
 void IOServiceMessageUserNotification::free( void )
 {
     PingMsg *  _pingMsg;
@@ -994,9 +991,9 @@ IOReturn IOServiceMessageUserNotification::handler( void * ref,
     }
     else
     {
+        if( callerArgSize > kIOUserNotifyMaxMessageSize)
+            callerArgSize = kIOUserNotifyMaxMessageSize;
         argSize = callerArgSize;
-        if( argSize > kIOUserNotifyMaxMessageSize)
-            argSize = kIOUserNotifyMaxMessageSize;
     }
 
     // adjust message size for ipc restrictions
@@ -1077,6 +1074,11 @@ OSObject * IOServiceMessageUserNotification::getNextObject()
     return( 0 );
 }
 
+OSObject * IOServiceMessageUserNotification::copyNextObject()
+{
+    return( NULL );
+}
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 #undef super
@@ -1447,7 +1449,7 @@ IOUserClient::registerOwner(task_t task)
     if (newOwner)
     {
         owner = IONew(IOUserClientOwner, 1);
-        if (!newOwner) ret = kIOReturnNoMemory;
+        if (!owner) ret = kIOReturnNoMemory;
         else
         {
             owner->task = task;
@@ -1532,6 +1534,7 @@ iokit_task_terminate(task_t task)
 void IOUserClient::free()
 {
     if( mappings) mappings->release();
+    if (lock) IOLockFree(lock);
                
     IOStatisticsUnregisterCounter();
 
@@ -1646,9 +1649,41 @@ IOReturn IOUserClient::exportObjectToClient(task_t task,
     name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT );
 
     *(mach_port_name_t *)clientObj = name;
+
+    if (obj) obj->release();
+
     return kIOReturnSuccess;
 }
 
+IOReturn IOUserClient::copyPortNameForObjectInTask(task_t task,
+                       OSObject *obj, mach_port_name_t * port_name)
+{
+    mach_port_name_t   name;
+
+    name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_IDENT );
+
+    *(mach_port_name_t *) port_name = name;
+
+    return kIOReturnSuccess;
+}
+
+IOReturn IOUserClient::copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name,
+                       OSObject **obj)
+{
+    OSObject * object;
+
+    object = iokit_lookup_object_with_port_name(port_name, IKOT_IOKIT_IDENT, task);
+
+    *obj = object;
+
+    return (object ? kIOReturnSuccess : kIOReturnIPCError);
+}
+
+IOReturn IOUserClient::adjustPortNameReferencesInTask(task_t task, mach_port_name_t port_name, mach_port_delta_t delta)
+{
+    return (iokit_mod_send_right(task, port_name, delta));
+}
+
 IOExternalMethod * IOUserClient::getExternalMethodForIndex( UInt32 /* index */)
 {
     return( 0 );
@@ -1922,38 +1957,36 @@ kern_return_t is_io_object_get_superclass(
        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 */
@@ -1962,38 +1995,36 @@ kern_return_t is_io_object_get_bundle_identifier(
        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 */
@@ -2029,12 +2060,24 @@ kern_return_t is_io_iterator_next(
 {
     IOReturn    ret;
     OSObject * obj;
+    OSIterator * iter;
+    IOUserIterator * uiter;
 
-    CHECK( OSIterator, iterator, iter );
+       if ((uiter = OSDynamicCast(IOUserIterator, iterator)))
+       {
+               obj = uiter->copyNextObject();
+       }
+       else if ((iter = OSDynamicCast(OSIterator, iterator)))
+       {
+               obj = iter->getNextObject();
+               if (obj) obj->retain();
+       }
+       else
+       {
+           return( kIOReturnBadArgument );
+       }
 
-    obj = iter->getNextObject();
     if( obj) {
-       obj->retain();
        *object = obj;
         ret = kIOReturnSuccess;
     } else
@@ -2312,6 +2355,8 @@ static kern_return_t internal_io_service_add_notification(
     do {
         err = kIOReturnNoResources;
 
+        if (matching_size > (sizeof(io_struct_inband_t) * 1024)) return(kIOReturnMessageTooLarge);
+
         if( !(sym = OSSymbol::withCString( notification_type )))
            err = kIOReturnNoResources;
 
@@ -2328,7 +2373,8 @@ static kern_return_t internal_io_service_add_notification(
        else if( (sym == gIOMatchedNotification)
              || (sym == gIOFirstMatchNotification))
            userMsgType = kIOServiceMatchedNotificationType;
-       else if( sym == gIOTerminatedNotification)
+       else if ((sym == gIOTerminatedNotification)
+             || (sym == gIOWillTerminateNotification))
            userMsgType = kIOServiceTerminatedNotificationType;
        else
            userMsgType = kLastIOKitNotificationType;
@@ -2337,7 +2383,6 @@ static kern_return_t internal_io_service_add_notification(
 
         if( userNotify && !userNotify->init( port, userMsgType,
                                              reference, referenceSize, client64)) {
-                       iokit_release_port_send(port);
             userNotify->release();
             userNotify = 0;
         }
@@ -2355,6 +2400,13 @@ static kern_return_t internal_io_service_add_notification(
 
     } while( false );
 
+    if ((kIOReturnSuccess != err) && userNotify)
+    {
+       userNotify->invalidatePort();
+       userNotify->release();
+       userNotify = 0;
+    }
+
     if( sym)
        sym->release();
     if( dict)
@@ -2530,7 +2582,6 @@ static kern_return_t internal_io_service_add_interest_notification(
                                              reference, referenceSize,
                                             kIOUserNotifyMaxMessageSize,
                                             client64 )) {
-                       iokit_release_port_send(port);
             userNotify->release();
             userNotify = 0;
         }
@@ -2550,6 +2601,13 @@ static kern_return_t internal_io_service_add_interest_notification(
 
     } while( false );
 
+    if ((kIOReturnSuccess != err) && userNotify)
+    {
+       userNotify->invalidatePort();
+       userNotify->release();
+       userNotify = 0;
+    }
+
     return( err );
 }
 
@@ -3257,8 +3315,8 @@ kern_return_t is_io_registry_entry_get_child_iterator(
 {
     CHECK( IORegistryEntry, registry_entry, entry );
 
-    *iterator = entry->getChildIterator(
-    IORegistryEntry::getPlane( plane ));
+    *iterator = IOUserIterator::withIterator(entry->getChildIterator(
+    IORegistryEntry::getPlane( plane )));
 
     return( kIOReturnSuccess );
 }
@@ -3271,8 +3329,8 @@ kern_return_t is_io_registry_entry_get_parent_iterator(
 {
     CHECK( IORegistryEntry, registry_entry, entry );
 
-    *iterator = entry->getParentIterator(
-       IORegistryEntry::getPlane( plane ));
+    *iterator = IOUserIterator::withIterator(entry->getParentIterator(
+       IORegistryEntry::getPlane( plane )));
 
     return( kIOReturnSuccess );
 }
@@ -3442,6 +3500,7 @@ kern_return_t is_io_service_open_extended(
 
            client->sharedInstance = (0 != client->getProperty(kIOUserClientSharedInstanceKey));
            client->closed = false;
+           client->lock = IOLockAlloc();
 
            disallowAccess = (crossEndian
                && (kOSBooleanTrue != service->getProperty(kIOUserClientCrossEndianCompatibleKey))
@@ -3493,7 +3552,9 @@ kern_return_t is_io_service_close(
 
     if (client->sharedInstance || OSCompareAndSwap8(0, 1, &client->closed)) 
     {
+       IOLockLock(client->lock);
        client->clientClose();
+       IOLockUnlock(client->lock);
     }
     else
     {
@@ -3529,11 +3590,15 @@ kern_return_t is_io_connect_set_notification_port(
        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 */
@@ -3543,11 +3608,15 @@ kern_return_t is_io_connect_set_notification_port_64(
        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 */
@@ -3583,6 +3652,7 @@ kern_return_t is_io_connect_map_memory_into_task
            mach_port_name_t name __unused =
                IOMachPort::makeSendRightForTask(
                                     into_task, map, IKOT_IOKIT_OBJECT );
+           map->release();
 
         } else {
             // keep it with the user client
@@ -3693,7 +3763,11 @@ kern_return_t is_io_connect_unmap_memory_from_task
 
            mach_port_name_t name = 0;
            if (from_task != current_task())
+           {
                name = IOMachPort::makeSendRightForTask( from_task, map, IKOT_IOKIT_OBJECT );
+               map->release();
+           }
+
            if (name)
            {
                map->userClientUnmap();
@@ -3974,6 +4048,8 @@ kern_return_t is_io_connect_async_method
     args.asyncReference      = reference;
     args.asyncReferenceCount = referenceCnt;
 
+    args.structureVariableOutputData = 0;
+
     args.scalarInput = scalar_input;
     args.scalarInputCount = scalar_inputCnt;
     args.structureInput = inband_input;
@@ -4891,7 +4967,7 @@ kern_return_t is_io_catalog_send_data(
         return kIOReturnBadArgument;
     }
 
-    if (!IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management"))
+    if (!IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-secure-management"))
     {
         OSString * taskName = IOCopyLogNameForPID(proc_selfpid());
         IOLog("IOCatalogueSendData(%s): Not entitled\n", taskName ? taskName->getCStringNoCopy() : "");
@@ -5120,7 +5196,7 @@ kern_return_t is_io_catalog_get_data(
         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,
@@ -5198,7 +5274,7 @@ kern_return_t iokit_user_client_trap(struct iokit_user_client_trap_args *args)
     IOUserClient *userClient;
 
     if ((userClient = OSDynamicCast(IOUserClient,
-            iokit_lookup_connect_ref_current_task((OSObject *)(args->userClientRef))))) {
+            iokit_lookup_connect_ref_current_task((mach_port_name_t)(uintptr_t)args->userClientRef)))) {
         IOExternalTrap *trap;
         IOService *target = NULL;
 
@@ -5220,6 +5296,24 @@ kern_return_t iokit_user_client_trap(struct iokit_user_client_trap_args *args)
     return result;
 }
 
+/* Routine io_device_tree_entry_exists_with_name */
+kern_return_t is_io_device_tree_entry_exists_with_name(
+       mach_port_t master_port,
+       io_name_t name,
+       boolean_t *exists )
+{
+       OSCollectionIterator *iter;
+
+       if (master_port != master_device_port)
+               return (kIOReturnNotPrivileged);
+
+       iter = IODTFindMatchingEntries(IORegistryEntry::getRegistryRoot(), kIODTRecursive, name);
+       *exists = iter && iter->getNextObject();
+       OSSafeReleaseNULL(iter);
+
+       return kIOReturnSuccess;
+}
+
 } /* extern "C" */
 
 IOReturn IOUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args,