Loading...
libsa/kmod.cpp xnu-344.21.73 xnu-792
--- xnu/xnu-344.21.73/libsa/kmod.cpp
+++ xnu/xnu-792/libsa/kmod.cpp
@@ -3,22 +3,19 @@
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
  * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
@@ -171,6 +168,72 @@
 }
 
 /*********************************************************************
+*********************************************************************/
+static
+Boolean kextIsADependency(OSString * name) {
+    Boolean result = true;
+    OSDictionary * extensionsDict = 0;    // don't release
+    OSDictionary * extDict = 0;           // don't release
+    OSDictionary * extPlist = 0;          // don't release
+    OSBoolean * isKernelResourceObj = 0;  // don't release
+    OSData * driverCode = 0;              // don't release
+    OSData * compressedCode = 0;          // don't release
+
+    extensionsDict = getStartupExtensions();
+    if (!extensionsDict) {
+        IOLog("kextIsADependency(): No extensions dictionary.\n");
+        LOG_DELAY();
+        result = false;
+        goto finish;
+    }
+    
+
+    extDict = OSDynamicCast(OSDictionary,
+        extensionsDict->getObject(name));
+    if (!extDict) {
+        IOLog("kextIsADependency(): "
+           "Extension \"%s\" cannot be found.\n",
+           name->getCStringNoCopy());
+        LOG_DELAY();
+        result = false;
+        goto finish;
+    }
+
+    extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
+    if (!extPlist) {
+        IOLog("getDependencyListForKmod(): "
+            "Extension \"%s\" has no property list.\n",
+            name->getCStringNoCopy());
+        LOG_DELAY();
+        result = false;
+        goto finish;
+    }
+
+   /* A kext that is a kernel component is still a dependency, as there
+    * are fake kmod entries for them.
+    */
+    isKernelResourceObj = OSDynamicCast(OSBoolean,
+        extPlist->getObject("OSKernelResource"));
+    if (isKernelResourceObj && isKernelResourceObj->isTrue()) {
+        result = true;
+        goto finish;
+    }
+
+    driverCode = OSDynamicCast(OSData, extDict->getObject("code"));
+    compressedCode = OSDynamicCast(OSData,
+        extDict->getObject("compressedCode"));
+
+    if (!driverCode && !compressedCode) {
+        result = false;
+        goto finish;
+    }
+
+finish:
+
+    return result;
+}
+
+/*********************************************************************
 * This function builds a uniqued, in-order list of modules that need
 * to be loaded in order for kmod_name to be successfully loaded. This
 * list ends with kmod_name itself.
@@ -185,9 +248,6 @@
     OSDictionary * extPlist;       // don't release
     OSString     * extName;        // don't release
     OSArray      * dependencyList = NULL; // return value, caller releases
-    OSBoolean * isKernelResourceObj = 0; // don't release
-    bool isKernelResource = false;
-    bool declaresExecutable = false;
     unsigned int   i;
 
    /* These are used to remove duplicates from the dependency list.
@@ -258,27 +318,6 @@
         goto finish;
     }
 
-   /* A kext that's not a kernel extension and declares no executable has nothing
-    * to load, so just return an empty array.
-    */
-    isKernelResourceObj = OSDynamicCast(OSBoolean,
-        extPlist->getObject("OSKernelResource"));
-    if (isKernelResourceObj && isKernelResourceObj->isTrue()) {
-        isKernelResource = true;
-    } else {
-        isKernelResource = false;
-    }
-
-    if (extPlist->getObject("CFBundleExecutable")) {
-        declaresExecutable = true;
-    } else {
-        declaresExecutable = false;
-    }
-
-    if (!isKernelResource && !declaresExecutable) {
-        error = 0;
-        goto finish;
-    }
 
    /* Okay, let's get started.
     */
@@ -371,28 +410,6 @@
                     goto finish;
                 }
 
-               /* Don't add any entries that are not kernel resources and that declare no
-                * executable. Such kexts have nothing to load and so don't belong in the
-                * dependency list. Entries that are kernel resource *do* get added,
-                * however, because such kexts get fake kmod entries for reference counting.
-                */
-                isKernelResourceObj = OSDynamicCast(OSBoolean,
-                    curExtPlist->getObject("OSKernelResource"));
-                if (isKernelResourceObj && isKernelResourceObj->isTrue()) {
-                    isKernelResource = true;
-                } else {
-                    isKernelResource = false;
-                }
-                if (curExtPlist->getObject("CFBundleExecutable")) {
-                    declaresExecutable = true;
-                } else {
-                    declaresExecutable = false;
-                }
-
-                if (!isKernelResource && !declaresExecutable) {
-                    continue;
-                }
-
                 dependencyList->setObject(curDepName);
             }
 
@@ -429,7 +446,9 @@
 
    /* Go backward through the original list, using the encounteredNames
     * dictionary to check for duplicates. We put originalList in as the
-    * value because we need some non-NULL value.
+    * value because we need some non-NULL value. Here we also drop any
+    * extensions that aren't proper dependencies (that is, any that are
+    * nonkernel kexts without code).
     */
     i = originalList->getCount();
 
@@ -440,7 +459,9 @@
             OSString * item = OSDynamicCast(OSString,
                 originalList->getObject(i));
 
-            if ( ! encounteredNames->getObject(item) ) {
+            if ( (!encounteredNames->getObject(item)) &&
+                 kextIsADependency(item)) {
+
                 encounteredNames->setObject(item, originalList);
                 dependencyList->setObject(item);
             }
@@ -567,7 +588,7 @@
     headers_pad = round_headers_size - headers_size;
 
     k_result = vm_allocate(kernel_map, (vm_offset_t *)&buffer,
-        round_size, TRUE);
+        round_size, VM_FLAGS_ANYWHERE);
     if (k_result != KERN_SUCCESS) {
         IOLog("alloc_for_kmod(): Can't allocate memory.\n");
         LOG_DELAY();
@@ -1047,7 +1068,7 @@
     IOLog("kmod id %d successfully created at 0x%lx, size %ld.\n",
         (unsigned int)kmod_id, link_buffer_address, link_buffer_size);
     LOG_DELAY();
-#endif DEBUG
+#endif /* DEBUG */
 
    /* Record dependencies for the newly-loaded kmod.
     */
@@ -1082,7 +1103,7 @@
 finish:
 
     if (kmod_info_freeme) {
-        kfree(kmod_info_freeme, sizeof(kmod_info_t));
+        kfree((unsigned int)kmod_info_freeme, sizeof(kmod_info_t));
     }
 
    /* Only do a kld_unload_all() if at least one load happened.
@@ -1100,7 +1121,7 @@
     if (kmod_dependencies) {
         for (i = 0; i < num_dependencies; i++) {
             if (kmod_dependencies[i]) {
-                kfree(kmod_dependencies[i], sizeof(kmod_info_t));
+                kfree((unsigned int)kmod_dependencies[i], sizeof(kmod_info_t));
             }
         }
         kfree((unsigned int)kmod_dependencies,
@@ -1194,7 +1215,7 @@
 finish:
 
     if (kmod_info) {
-        kfree(kmod_info, sizeof(kmod_info_t));
+        kfree((unsigned int)kmod_info, sizeof(kmod_info_t));
     }
 
     if (dependencyList) {