]> 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 d568aaca2f2d269359effde1f8e42f09c69ad082..6a3fc814b113beef0832682348598ed16ae60df8 100644 (file)
@@ -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>
@@ -646,6 +647,7 @@ 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 );
@@ -679,6 +681,7 @@ public:
                       bool clientIs64 );
 
     virtual void free() APPLE_KEXT_OVERRIDE;
+    void invalidatePort(void);
     
     static IOReturn _handler( void * target, void * ref,
                               UInt32 messageType, IOService * provider,
@@ -784,6 +787,11 @@ 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;
@@ -940,6 +948,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;
@@ -993,9 +1006,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
@@ -1617,7 +1630,7 @@ IOMemoryMap * IOUserClient::mapClientMemory64(
 {
     IOReturn           err;
     IOOptionBits       options = 0;
-    IOMemoryDescriptor * memory;
+    IOMemoryDescriptor * memory = 0;
     IOMemoryMap *      map = 0;
 
     err = clientMemoryForType( (UInt32) type, &options, &memory );
@@ -1921,38 +1934,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 */
@@ -1961,38 +1972,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 */
@@ -2311,6 +2320,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;
 
@@ -2327,7 +2338,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;
@@ -2336,7 +2348,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;
         }
@@ -2354,6 +2365,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)
@@ -2529,7 +2547,6 @@ static kern_return_t internal_io_service_add_interest_notification(
                                              reference, referenceSize,
                                             kIOUserNotifyMaxMessageSize,
                                             client64 )) {
-                       iokit_release_port_send(port);
             userNotify->release();
             userNotify = 0;
         }
@@ -2549,6 +2566,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 );
 }
 
@@ -3666,7 +3690,7 @@ kern_return_t is_io_connect_unmap_memory_from_task
 {
     IOReturn           err;
     IOOptionBits       options = 0;
-    IOMemoryDescriptor * memory;
+    IOMemoryDescriptor * memory = 0;
     IOMemoryMap *      map;
 
     CHECK( IOUserClient, connection, client );
@@ -3793,6 +3817,8 @@ kern_return_t is_io_connect_method_var_output
     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 | kIOMemoryMapCopyOnWrite,
@@ -3888,6 +3914,9 @@ kern_return_t is_io_connect_method
     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 | kIOMemoryMapCopyOnWrite,
@@ -3968,11 +3997,16 @@ 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;
     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 | kIOMemoryMapCopyOnWrite,
@@ -4862,6 +4896,9 @@ kern_return_t is_io_catalog_send_data(
         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;
@@ -4879,6 +4916,16 @@ kern_return_t is_io_catalog_send_data(
         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;
 
@@ -5008,9 +5055,10 @@ kern_return_t is_io_catalog_send_data(
     }
 
     if (obj) obj->release();
-    
+
     *result = kr;
     return( KERN_SUCCESS);
+#endif /* NO_KEXTD */
 }
 
 /* Routine io_catalog_terminate */
@@ -5097,7 +5145,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,