+++ /dev/null
-/*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * 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. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * 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
- * 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.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-/*
- * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
- * support for mandatory and extensible security protections. This notice
- * is included in support of clause 2.2 (b) of the Apple Public License,
- * Version 2.0.
- */
-
-#include <libkern/c++/OSContainers.h>
-#include <IOKit/IOCatalogue.h>
-#include <IOKit/IOLib.h>
-#include <libsa/kext.h>
-#include <libsa/catalogue.h>
-
-extern "C" {
-#include <mach-o/kld.h>
-#include <libsa/vers_rsrc.h>
-#include <libsa/stdlib.h>
-#include <mach/kmod.h>
-#include <vm/vm_kern.h>
-#include <mach/kern_return.h>
-#include <mach-o/fat.h>
-#include <mach_loader.h>
-
-#include "kld_patch.h"
-#include "dgraph.h"
-#include "load.h"
-};
-
-
-extern "C" {
-extern kern_return_t
-kmod_create_internal(
- kmod_info_t *info,
- kmod_t *id);
-
-extern kern_return_t
-kmod_destroy_internal(kmod_t id);
-
-extern kern_return_t
-kmod_start_or_stop(
- kmod_t id,
- int start,
- kmod_args_t *data,
- mach_msg_type_number_t *dataCount);
-
-extern kern_return_t kmod_retain(kmod_t id);
-extern kern_return_t kmod_release(kmod_t id);
-
-extern Boolean kmod_load_request(const char * moduleName, Boolean make_request);
-};
-
-extern kmod_args_t
-get_module_data(OSDictionary * kextPlist, mach_msg_type_number_t * datalen);
-
-extern struct mac_module_data *osdict_encode(OSDictionary *dict);
-
-#define DEBUG
-#ifdef DEBUG
-#define LOG_DELAY(x) IODelay((x) * 1000000)
-#define VTYELLOW "\033[33m"
-#define VTRESET "\033[0m"
-#else
-#define LOG_DELAY(x)
-#define VTYELLOW
-#define VTRESET
-#endif /* DEBUG */
-
-
-#define KERNEL_PREFIX "com.apple.kernel"
-#define KPI_PREFIX "com.apple.kpi"
-
-
-/*********************************************************************
-*
-*********************************************************************/
-static
-bool getKext(
- const char * bundleid,
- OSDictionary ** plist,
- unsigned char ** code,
- unsigned long * code_size,
- bool * caller_owns_code)
-{
- bool result = true;
- OSDictionary * extensionsDict; // don't release
- OSDictionary * extDict; // don't release
- OSDictionary * extPlist; // don't release
- unsigned long code_size_local;
-
- /* Get the dictionary of startup extensions.
- * This is keyed by module name.
- */
- extensionsDict = getStartupExtensions();
- if (!extensionsDict) {
- IOLog("startup extensions dictionary is missing\n");
- result = false;
- goto finish;
- }
-
- /* Get the requested extension's dictionary entry and its property
- * list, containing module dependencies.
- */
- extDict = OSDynamicCast(OSDictionary,
- extensionsDict->getObject(bundleid));
-
- if (!extDict) {
- IOLog("extension \"%s\" cannot be found\n",
- bundleid);
- result = false;
- goto finish;
- }
-
- if (plist) {
- extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
- if (!extPlist) {
- IOLog("extension \"%s\" has no info dictionary\n",
- bundleid);
- result = false;
- goto finish;
- }
- *plist = extPlist;
- }
-
- if (code) {
-
- /* If asking for code, the caller must provide a return buffer
- * for ownership!
- */
- if (!caller_owns_code) {
- IOLog("getKext(): invalid usage (caller_owns_code not provided)\n");
- result = false;
- goto finish;
- }
-
- *code = 0;
- if (code_size) {
- *code_size = 0;
- }
- *caller_owns_code = false;
-
- *code = (unsigned char *)kld_file_getaddr(bundleid,
- (unsigned long *)&code_size_local);
- if (*code) {
- if (code_size) {
- *code_size = code_size_local;
- }
- } else {
- OSData * driverCode = 0; // release only if uncompressing!
-
- driverCode = OSDynamicCast(OSData, extDict->getObject("code"));
- if (driverCode) {
- *code = (unsigned char *)driverCode->getBytesNoCopy();
- if (code_size) {
- *code_size = driverCode->getLength();
- }
- } else { // Look for compressed code and uncompress it
- OSData * compressedCode = 0;
- compressedCode = OSDynamicCast(OSData,
- extDict->getObject("compressedCode"));
- if (compressedCode) {
- if (!uncompressModule(compressedCode, &driverCode)) {
- IOLog("extension \"%s\": couldn't uncompress code\n",
- bundleid);
- result = false;
- goto finish;
- }
- *caller_owns_code = true;
- *code = (unsigned char *)driverCode->getBytesNoCopy();
- if (code_size) {
- *code_size = driverCode->getLength();
- }
- driverCode->release();
- }
- }
- }
- }
-
-finish:
-
- return result;
-}
-
-
-/*********************************************************************
-*
-*********************************************************************/
-static
-bool verifyCompatibility(OSString * extName, OSString * requiredVersion)
-{
- OSDictionary * extPlist; // don't release
- OSString * extVersion; // don't release
- OSString * extCompatVersion; // don't release
- VERS_version ext_version;
- VERS_version ext_compat_version;
- VERS_version required_version;
-
- if (!getKext(extName->getCStringNoCopy(), &extPlist, NULL, NULL, NULL)) {
- return false;
- }
-
- extVersion = OSDynamicCast(OSString,
- extPlist->getObject("CFBundleVersion"));
- if (!extVersion) {
- IOLog("verifyCompatibility(): "
- "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
- extName->getCStringNoCopy());
- return false;
- }
-
- extCompatVersion = OSDynamicCast(OSString,
- extPlist->getObject("OSBundleCompatibleVersion"));
- if (!extCompatVersion) {
- IOLog("verifyCompatibility(): "
- "Extension \"%s\" has no \"OSBundleCompatibleVersion\" property.\n",
- extName->getCStringNoCopy());
- return false;
- }
-
- required_version = VERS_parse_string(requiredVersion->getCStringNoCopy());
- if (required_version < 0) {
- IOLog("verifyCompatibility(): "
- "Can't parse required version \"%s\" of dependency %s.\n",
- requiredVersion->getCStringNoCopy(),
- extName->getCStringNoCopy());
- return false;
- }
- ext_version = VERS_parse_string(extVersion->getCStringNoCopy());
- if (ext_version < 0) {
- IOLog("verifyCompatibility(): "
- "Can't parse version \"%s\" of dependency %s.\n",
- extVersion->getCStringNoCopy(),
- extName->getCStringNoCopy());
- return false;
- }
- ext_compat_version = VERS_parse_string(extCompatVersion->getCStringNoCopy());
- if (ext_compat_version < 0) {
- IOLog("verifyCompatibility(): "
- "Can't parse compatible version \"%s\" of dependency %s.\n",
- extCompatVersion->getCStringNoCopy(),
- extName->getCStringNoCopy());
- return false;
- }
-
- if (required_version > ext_version || required_version < ext_compat_version) {
- return false;
- }
-
- return true;
-}
-
-/*********************************************************************
-*********************************************************************/
-static
-bool kextIsDependency(const char * kext_name, char * is_kernel) {
- bool 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
-
- if (is_kernel) {
- *is_kernel = 0;
- }
-
- /* Get the dictionary of startup extensions.
- * This is keyed by module name.
- */
- extensionsDict = getStartupExtensions();
- if (!extensionsDict) {
- IOLog("startup extensions dictionary is missing\n");
- result = false;
- goto finish;
- }
-
- /* Get the requested extension's dictionary entry and its property
- * list, containing module dependencies.
- */
- extDict = OSDynamicCast(OSDictionary,
- extensionsDict->getObject(kext_name));
-
- if (!extDict) {
- IOLog("extension \"%s\" cannot be found\n",
- kext_name);
- result = false;
- goto finish;
- }
-
- extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
- if (!extPlist) {
- IOLog("extension \"%s\" has no info dictionary\n",
- kext_name);
- 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()) {
- if (is_kernel) {
- *is_kernel = 1;
- }
- }
-
- driverCode = OSDynamicCast(OSData, extDict->getObject("code"));
- compressedCode = OSDynamicCast(OSData,
- extDict->getObject("compressedCode"));
-
- /* A kernel component that has code represents a KPI.
- */
- if ((driverCode || compressedCode) && is_kernel && *is_kernel) {
- *is_kernel = 2;
- }
-
- if (!driverCode && !compressedCode && !isKernelResourceObj) {
- result = false;
- goto finish;
- }
-
-finish:
-
- return result;
-}
-
-/*********************************************************************
-*********************************************************************/
-static bool
-addDependenciesForKext(OSDictionary * kextPlist,
- OSArray * dependencyList,
- OSString * trueParent,
- Boolean skipKernelDependencies)
-{
- bool result = true;
- bool hasDirectKernelDependency = false;
- bool hasKernelStyleDependency = false;
- bool hasKPIStyleDependency = false;
- OSString * kextName = 0; // don't release
- OSDictionary * libraries = 0; // don't release
- OSCollectionIterator * keyIterator = 0; // must release
- OSString * libraryName = 0; // don't release
- OSString * dependentName = 0; // don't release
-
- kextName = OSDynamicCast(OSString,
- kextPlist->getObject("CFBundleIdentifier"));
- if (!kextName) {
- // XXX: Add log message
- result = false;
- goto finish;
- }
-
- libraries = OSDynamicCast(OSDictionary,
- kextPlist->getObject("OSBundleLibraries"));
- if (!libraries) {
- result = true;
- goto finish;
- }
-
- keyIterator = OSCollectionIterator::withCollection(libraries);
- if (!keyIterator) {
- // XXX: Add log message
- result = false;
- goto finish;
- }
-
- dependentName = trueParent ? trueParent : kextName;
-
- while ( (libraryName = OSDynamicCast(OSString,
- keyIterator->getNextObject())) ) {
-
- OSString * libraryVersion = OSDynamicCast(OSString,
- libraries->getObject(libraryName));
- if (!libraryVersion) {
- // XXX: Add log message
- result = false;
- goto finish;
- }
- if (!verifyCompatibility(libraryName, libraryVersion)) {
- result = false;
- goto finish;
- } else {
- char is_kernel_component;
-
- if (!kextIsDependency(libraryName->getCStringNoCopy(),
- &is_kernel_component)) {
-
- is_kernel_component = 0;
- }
-
- if (!skipKernelDependencies || !is_kernel_component) {
- dependencyList->setObject(dependentName);
- dependencyList->setObject(libraryName);
- }
- if (!hasDirectKernelDependency && is_kernel_component) {
- hasDirectKernelDependency = true;
- }
-
- /* We already know from the kextIsDependency() call whether
- * the dependency *itself* is kernel- or KPI-style, but since
- * the declaration semantic is by bundle ID, we check that here
- * instead.
- */
- if (strncmp(libraryName->getCStringNoCopy(),
- KERNEL_PREFIX, strlen(KERNEL_PREFIX)) == 0) {
-
- hasKernelStyleDependency = true;
-
- } else if (strncmp(libraryName->getCStringNoCopy(),
- KPI_PREFIX, strlen(KPI_PREFIX)) == 0) {
-
- hasKPIStyleDependency = true;
- }
- }
- }
-
- if (!hasDirectKernelDependency) {
- const OSSymbol * kernelName = 0;
-
- /* a kext without any kernel dependency is assumed dependent on 6.0 */
- dependencyList->setObject(dependentName);
-
- kernelName = OSSymbol::withCString("com.apple.kernel.libkern");
- if (!kernelName) {
- // XXX: Add log message
- result = false;
- goto finish;
- }
- dependencyList->setObject(kernelName);
- kernelName->release();
-
- IOLog("Extension \"%s\" has no explicit kernel dependency; using version 6.0.\n",
- kextName->getCStringNoCopy());
-
- } else if (hasKernelStyleDependency && hasKPIStyleDependency) {
- IOLog("Extension \"%s\" has immediate dependencies "
- "on both com.apple.kernel and com.apple.kpi components; use only one style.\n",
- kextName->getCStringNoCopy());
- }
-
-finish:
- if (keyIterator) keyIterator->release();
- return result;
-}
-
-/*********************************************************************
-*********************************************************************/
-static
-bool getVersionForKext(OSDictionary * kextPlist, char ** version)
-{
- OSString * kextName = 0; // don't release
- OSString * kextVersion; // don't release
-
- kextName = OSDynamicCast(OSString,
- kextPlist->getObject("CFBundleIdentifier"));
- if (!kextName) {
- // XXX: Add log message
- return false;
- }
-
- kextVersion = OSDynamicCast(OSString,
- kextPlist->getObject("CFBundleVersion"));
- if (!kextVersion) {
- IOLog("getVersionForKext(): "
- "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
- kextName->getCStringNoCopy());
- return false;
- }
-
- if (version) {
- *version = (char *)kextVersion->getCStringNoCopy();
- }
-
- return true;
-}
-
-/*********************************************************************
-*********************************************************************/
-static
-bool add_dependencies_for_kmod(const char * kmod_name, dgraph_t * dgraph)
-{
- bool result = true;
- OSDictionary * kextPlist = 0; // don't release
- unsigned int index = 0;
- OSArray * dependencyList = 0; // must release
- unsigned char * code = 0;
- unsigned long code_length = 0;
- bool code_is_kmem = false;
- char * kmod_vers = 0; // from plist, don't free
- char is_kernel_component = 0;
- dgraph_entry_t * dgraph_entry = 0; // don't free
- dgraph_entry_t * dgraph_dependency = 0; // don't free
- bool kext_is_dependency = true;
-
-#if CONFIG_MACF_KEXT
- kmod_args_t user_data = 0;
- mach_msg_type_number_t user_data_length;
-#endif
-
- /*****
- * Set up the root kmod.
- */
- if (!getKext(kmod_name, &kextPlist, &code, &code_length,
- &code_is_kmem)) {
- IOLog("can't find extension %s\n", kmod_name);
- result = false;
- goto finish;
- }
-
- if (!kextIsDependency(kmod_name, &is_kernel_component)) {
- IOLog("extension %s is not loadable\n", kmod_name);
- result = false;
- goto finish;
- }
-
- if (!getVersionForKext(kextPlist, &kmod_vers)) {
- IOLog("can't get version for extension %s\n", kmod_name);
- result = false;
- goto finish;
- }
-
-#if CONFIG_MACF_KEXT
- // check kext for module data in the plist
- user_data = get_module_data(kextPlist, &user_data_length);
-#endif
-
- dgraph_entry = dgraph_add_dependent(dgraph, kmod_name,
- code, code_length, code_is_kmem,
-#if CONFIG_MACF_KEXT
- user_data, user_data_length,
-#endif
- kmod_name, kmod_vers,
- 0 /* load_address not yet known */, is_kernel_component);
- if (!dgraph_entry) {
- IOLog("can't record %s in dependency graph\n", kmod_name);
- result = false;
- // kmem_alloc()ed code is freed in finish: block.
- goto finish;
- }
-
- // pass ownership of code to kld patcher
- if (code) {
- if (kload_map_entry(dgraph_entry) != kload_error_none) {
- IOLog("can't map %s in preparation for loading\n", kmod_name);
- result = false;
- // kmem_alloc()ed code is freed in finish: block.
- goto finish;
- }
- }
- // clear local record of code
- code = 0;
- code_length = 0;
- code_is_kmem = false;
-
- /*****
- * Now handle all the dependencies.
- */
- dependencyList = OSArray::withCapacity(5);
- if (!dependencyList) {
- IOLog("memory allocation failure\n");
- result = false;
- goto finish;
- }
-
- index = 0;
- if (!addDependenciesForKext(kextPlist, dependencyList, NULL, false)) {
- IOLog("can't determine immediate dependencies for extension %s\n",
- kmod_name);
- result = false;
- goto finish;
- }
-
- /* IMPORTANT: loop condition gets list count every time through, as the
- * array CAN change each iteration.
- */
- for (index = 0; index < dependencyList->getCount(); index += 2) {
- OSString * dependentName = 0;
- OSString * libraryName = 0;
- const char * dependent_name = 0;
- const char * library_name = 0;
-
- /* 255 is an arbitrary limit. Multiplied by 2 because the dependency
- * list is stocked with pairs (dependent -> dependency).
- */
- if (index > (2 * 255)) {
- IOLog("extension dependency graph ridiculously long, indicating a loop\n");
- result = false;
- goto finish;
- }
-
- dependentName = OSDynamicCast(OSString,
- dependencyList->getObject(index));
- libraryName = OSDynamicCast(OSString,
- dependencyList->getObject(index + 1));
-
- if (!dependentName || !libraryName) {
- IOLog("malformed dependency list\n");
- result = false;
- goto finish;
- }
-
- dependent_name = dependentName->getCStringNoCopy();
- library_name = libraryName->getCStringNoCopy();
-
- if (!getKext(library_name, &kextPlist, NULL, NULL, NULL)) {
-
- IOLog("can't find extension %s\n", library_name);
- result = false;
- goto finish;
- }
-
- OSString * string = OSDynamicCast(OSString,
- kextPlist->getObject("OSBundleSharedExecutableIdentifier"));
- if (string) {
- library_name = string->getCStringNoCopy();
- if (!getKext(library_name, &kextPlist, NULL, NULL, NULL)) {
- IOLog("can't find extension %s\n", library_name);
- result = false;
- goto finish;
- }
- }
-
- kext_is_dependency = kextIsDependency(library_name,
- &is_kernel_component);
-
- if (kext_is_dependency) {
- dgraph_entry = dgraph_find_dependent(dgraph, dependent_name);
- if (!dgraph_entry) {
- IOLog("internal error with dependency graph\n");
- LOG_DELAY(1);
- result = false;
- goto finish;
- }
-
- if (!getVersionForKext(kextPlist, &kmod_vers)) {
- IOLog("can't get version for extension %s\n", library_name);
- result = false;
- goto finish;
- }
-
- /* It's okay for code to be zero, as for a pseudokext
- * representing a kernel component.
- */
- if (!getKext(library_name, NULL /* already got it */,
- &code, &code_length, &code_is_kmem)) {
- IOLog("can't find extension %s\n", library_name);
- result = false;
- goto finish;
- }
-
-#if CONFIG_MACF_KEXT
- // check kext for module data in the plist
- // XXX - is this really needed?
- user_data = get_module_data(kextPlist, &user_data_length);
-#endif
- dgraph_dependency = dgraph_add_dependency(dgraph, dgraph_entry,
- library_name, code, code_length, code_is_kmem,
-#if CONFIG_MACF_KEXT
- user_data, user_data_length,
-#endif
- library_name, kmod_vers,
- 0 /* load_address not yet known */, is_kernel_component);
-
- if (!dgraph_dependency) {
- IOLog("can't record dependency %s -> %s\n", dependent_name,
- library_name);
- result = false;
- // kmem_alloc()ed code is freed in finish: block.
- goto finish;
- }
-
- // pass ownership of code to kld patcher
- if (code) {
- if (kload_map_entry(dgraph_dependency) != kload_error_none) {
- IOLog("can't map %s in preparation for loading\n", library_name);
- result = false;
- // kmem_alloc()ed code is freed in finish: block.
- goto finish;
- }
- }
- // clear local record of code
- code = 0;
- code_length = 0;
- code_is_kmem = false;
- }
-
- /* Now put the library's dependencies onto the pending set.
- */
- if (!addDependenciesForKext(kextPlist, dependencyList,
- kext_is_dependency ? NULL : dependentName, !kext_is_dependency)) {
-
- IOLog("can't determine immediate dependencies for extension %s\n",
- library_name);
- result = false;
- goto finish;
- }
- }
-
-finish:
- if (code && code_is_kmem) {
- kmem_free(kernel_map, (unsigned int)code, code_length);
- }
- if (dependencyList) dependencyList->release();
-
-#if CONFIG_MACF_KEXT
- if (user_data && !result) {
- vm_map_copy_discard((vm_map_copy_t)user_data);
- }
-#endif
-
- return result;
-}
-
-/*********************************************************************
-* This is the function that IOCatalogue calls in order to load a kmod.
-* It first checks whether the kmod is already loaded. If the kmod
-* isn't loaded, this function builds a dependency list and calls
-* load_kmod() repeatedly to guarantee that each dependency is in fact
-* loaded.
-*********************************************************************/
-__private_extern__
-kern_return_t load_kernel_extension(char * kmod_name)
-{
- kern_return_t result = KERN_SUCCESS;
- kload_error load_result = kload_error_none;
- dgraph_t dgraph;
- bool free_dgraph = false;
- kmod_info_t * kmod_info;
-
-// Put this in for lots of messages about kext loading.
-#if 0
- kload_set_log_level(kload_log_level_load_details);
-#endif
-
- /* See if the kmod is already loaded.
- */
- if ((kmod_info = kmod_lookupbyname_locked(kmod_name))) {
- kfree(kmod_info, sizeof(kmod_info_t));
- return KERN_SUCCESS;
- }
-
- if (dgraph_init(&dgraph) != dgraph_valid) {
- IOLog("Can't initialize dependency graph to load %s.\n",
- kmod_name);
- result = KERN_FAILURE;
- goto finish;
- }
-
- free_dgraph = true;
- if (!add_dependencies_for_kmod(kmod_name, &dgraph)) {
- IOLog("Can't determine dependencies for %s.\n",
- kmod_name);
- result = KERN_FAILURE;
- goto finish;
- }
-
- dgraph.root = dgraph_find_root(&dgraph);
-
- if (!dgraph.root) {
- IOLog("Dependency graph to load %s has no root.\n",
- kmod_name);
- result = KERN_FAILURE;
- goto finish;
- }
-
- /* A kernel component is built in and need not be loaded.
- */
- if (dgraph.root->is_kernel_component) {
- result = KERN_SUCCESS;
- goto finish;
- }
-
- dgraph_establish_load_order(&dgraph);
-
- load_result = kload_load_dgraph(&dgraph);
- if (load_result != kload_error_none &&
- load_result != kload_error_already_loaded) {
-
- IOLog(VTYELLOW "Failed to load extension %s.\n" VTRESET, kmod_name);
-
- result = KERN_FAILURE;
- goto finish;
- }
-
-finish:
-
- if (free_dgraph) {
- dgraph_free(&dgraph, 0 /* don't free dgraph itself */);
- }
- return result;
-}
-
-#define COM_APPLE "com.apple."
-
-__private_extern__ void
-load_security_extensions (void)
-{
- OSDictionary * extensionsDict = NULL; // don't release
- OSCollectionIterator* keyIterator = NULL; // must release
- OSString * key = NULL; // don't release
- OSDictionary * extDict; // don't release
- OSDictionary * extPlist; // don't release
- OSBoolean * isSec = 0; // don't release
- Boolean ret;
-
- extensionsDict = getStartupExtensions();
- if (!extensionsDict) {
- IOLog("startup extensions dictionary is missing\n");
- LOG_DELAY(1);
- return;
- }
-
- keyIterator = OSCollectionIterator::withCollection(extensionsDict);
- if (!keyIterator) {
- IOLog("Error: Failed to allocate iterator for extensions.\n");
- LOG_DELAY(1);
- return;
- }
-
- while ((key = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
-
- const char * bundle_id = key->getCStringNoCopy();
-
- /* Skip extensions whose bundle IDs don't start with "com.apple.".
- */
- if (!bundle_id || (strncmp(bundle_id, COM_APPLE, strlen(COM_APPLE)) != 0)) {
- continue;
- }
-
- extDict = OSDynamicCast(OSDictionary, extensionsDict->getObject(key));
- if (!extDict) {
- IOLog("extension \"%s\" cannot be found\n",
- key->getCStringNoCopy());
- continue;
- }
-
- extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
- if (!extPlist) {
- IOLog("extension \"%s\" has no info dictionary\n",
- key->getCStringNoCopy());
- continue;
- }
-
- isSec = OSDynamicCast(OSBoolean,
- extPlist->getObject("AppleSecurityExtension"));
- if (isSec && isSec->isTrue()) {
- printf("Loading security extension %s\n", key->getCStringNoCopy());
- ret = kmod_load_request(key->getCStringNoCopy(), false);
- if (!ret) {
- load_kernel_extension((char *)key->getCStringNoCopy());
- }
- }
- }
-
- if (keyIterator)
- keyIterator->release();
-
- return;
-}