X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/55e303ae13a4cf49d70f2294092726f2fffb9ef2..593a1d5fd87cdf5b46dd5fcb84467b432cea0f91:/iokit/Kernel/IOCatalogue.cpp diff --git a/iokit/Kernel/IOCatalogue.cpp b/iokit/Kernel/IOCatalogue.cpp index 6e9f45c52..0b5f54a25 100644 --- a/iokit/Kernel/IOCatalogue.cpp +++ b/iokit/Kernel/IOCatalogue.cpp @@ -1,16 +1,19 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, 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. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * 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 @@ -20,7 +23,7 @@ * Please see the License for the specific language governing rights and * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. @@ -28,6 +31,12 @@ * HISTORY * */ +/* + * 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 #include @@ -39,6 +48,7 @@ extern "C" { #include #include #include +#include }; #include @@ -49,8 +59,8 @@ extern "C" { extern "C" { int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize ); extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize ); -extern void OSRuntimeUnloadCPPForSegment( - struct segment_command * segment); +/* operates on 32 bit segments */ +extern void OSRuntimeUnloadCPPForSegment(struct segment_command * segment); }; @@ -118,6 +128,410 @@ kmod_start_or_stop( extern "C" kern_return_t kmod_retain(kmod_t id); extern "C" kern_return_t kmod_release(kmod_t id); +#if CONFIG_MACF_KEXT +/* MAC Framework support */ + +/* + * define IOC_DEBUG to display run-time debugging information + * #define IOC_DEBUG 1 + */ + +#ifdef IOC_DEBUG +#define DPRINTF(x) printf x +#else +#define IOC_DEBUG +#define DPRINTF(x) +#endif + +static bool +primitive_type(OSObject *obj) +{ + const OSMetaClass *typeID; + + typeID = OSTypeIDInst(obj); + if (typeID == OSTypeID(OSString) || typeID == OSTypeID(OSNumber) || + typeID == OSTypeID(OSBoolean) || typeID == OSTypeID(OSData)) + return(true); + else + return(false); +} + +static int +primitive_type_length(OSObject *obj) +{ + const OSMetaClass *typeID; + int len; + + typeID = OSTypeIDInst(obj); + if (typeID == OSTypeID(OSString)) { + OSString * stringObj = OSDynamicCast(OSString, obj); + len = stringObj->getLength() + 1; + } + else if (typeID == OSTypeID(OSNumber)) { + len = sizeof("4294967295"); /* UINT32_MAX */ + } + else if (typeID == OSTypeID(OSBoolean)) { + OSBoolean * boolObj = OSDynamicCast(OSBoolean, obj); + len = boolObj->isTrue() ? sizeof("true") : sizeof("false"); + } + else if (typeID == OSTypeID(OSData)) { + OSData * dataObj = OSDynamicCast(OSData, obj); + len = dataObj->getLength(); + } + else { + len = 0; + } + return(len); +} + +static void +primitive_type_collect(struct mac_module_data_element *element, OSObject *value) +{ + const OSMetaClass *typeID; + + typeID = OSTypeIDInst(value); + if (typeID == OSTypeID(OSString)) { + OSString *stringObj = OSDynamicCast(OSString, value); + element->value_type = MAC_DATA_TYPE_PRIMITIVE; + element->value_size = stringObj->getLength() + 1; + DPRINTF(("osdict: string %s size %d\n", + stringObj->getCStringNoCopy(), element->value_size)); + memcpy(element->value, stringObj->getCStringNoCopy(), + element->value_size); + } else if (typeID == OSTypeID(OSNumber)) { + OSNumber *numberObj = OSDynamicCast(OSNumber, value); + element->value_type = MAC_DATA_TYPE_PRIMITIVE; + element->value_size = sprintf(element->value, "%u", + numberObj->unsigned32BitValue()) + 1; + } else if (typeID == OSTypeID(OSBoolean)) { + OSBoolean *boolObj = OSDynamicCast(OSBoolean, value); + element->value_type = MAC_DATA_TYPE_PRIMITIVE; + if (boolObj->isTrue()) { + strcpy(element->value, "true"); + element->value_size = 5; + } else { + strcpy(element->value, "false"); + element->value_size = 6; + } + } else if (typeID == OSTypeID(OSData)) { + OSData *dataObj = OSDynamicCast(OSData, value); + element->value_type = MAC_DATA_TYPE_PRIMITIVE; + element->value_size = dataObj->getLength(); + DPRINTF(("osdict: data size %d\n", dataObj->getLength())); + memcpy(element->value, dataObj->getBytesNoCopy(), + element->value_size); + } +} + +/********************************************************************* +* This function takes an OSDictionary and returns a struct mac_module_data +* list. +*********************************************************************/ +struct mac_module_data * +osdict_encode(OSDictionary *dict) +{ + const OSMetaClass * typeID; // don't release + OSString * key = NULL; // don't release + OSCollectionIterator * keyIterator = 0; // must release + struct mac_module_data * module_data = 0; + struct mac_module_data_element * element; + unsigned int strtabsize = 0; + unsigned int listtabsize = 0; + unsigned int dicttabsize = 0; + unsigned int nkeys = 0; + unsigned int datalen; + char *strtab = NULL; + char *listtab = NULL; + char *dicttab = NULL; + vm_offset_t data_addr; + + keyIterator = OSCollectionIterator::withCollection(dict); + if (!keyIterator) + goto finish; + + /* Iterate over OSModuleData to figure out total size */ + while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) { + + // Get the key's value and determine its type + OSObject * value = dict->getObject(key); + if (!value) + continue; + + typeID = OSTypeIDInst(value); + if (primitive_type(value)) { + strtabsize += primitive_type_length(value); + } + else if (typeID == OSTypeID(OSArray)) { + unsigned int k, cnt, nents; + OSArray *arrayObj = OSDynamicCast(OSArray, value); + + nents = 0; + cnt = arrayObj->getCount(); + for (k = 0; k < cnt; k++) { + value = arrayObj->getObject(k); + typeID = OSTypeIDInst(value); + if (primitive_type(value)) { + listtabsize += primitive_type_length(value); + nents++; + } + else if (typeID == OSTypeID(OSDictionary)) { + unsigned int dents; + OSDictionary *dictObj; + OSString *dictkey; + OSCollectionIterator *dictIterator; + + dents = 0; + dictObj = OSDynamicCast(OSDictionary, value); + dictIterator = OSCollectionIterator::withCollection(dictObj); + if (!dictIterator) + goto finish; + while ((dictkey = OSDynamicCast(OSString, + dictIterator->getNextObject()))) { + OSObject *dictvalue; + + dictvalue = dictObj->getObject(dictkey); + if (!dictvalue) + continue; + if (primitive_type(dictvalue)) { + strtabsize += primitive_type_length(dictvalue); + } + else { + continue; /* Only handle primitive types here. */ + } + /* + * Allow for the "arraynnn/" prefix in the key length. + */ + strtabsize += dictkey->getLength() + 1; + dents++; + } + dictIterator->release(); + if (dents-- > 0) { + dicttabsize += sizeof(struct mac_module_data_list) + + dents * sizeof(struct mac_module_data_element); + nents++; + } + } + else { + continue; /* Skip everything else. */ + } + } + if (nents == 0) + continue; + listtabsize += sizeof(struct mac_module_data_list) + + (nents - 1) * sizeof(struct mac_module_data_element); + } + else { + continue; /* skip anything else */ + } + strtabsize += key->getLength() + 1; + nkeys++; + } + if (nkeys == 0) + goto finish; + + /* + * Allocate and fill in the module data structures. + */ + datalen = sizeof(struct mac_module_data) + + sizeof(mac_module_data_element) * (nkeys - 1) + + strtabsize + listtabsize + dicttabsize; + DPRINTF(("osdict: datalen %d strtabsize %d listtabsize %d dicttabsize %d\n", + datalen, strtabsize, listtabsize, dicttabsize)); + if (kmem_alloc(kernel_map, &data_addr, datalen) != KERN_SUCCESS) + goto finish; + module_data = (mac_module_data *)data_addr; + module_data->base_addr = data_addr; + module_data->size = datalen; + module_data->count = nkeys; + strtab = (char *)&module_data->data[nkeys]; + listtab = strtab + strtabsize; + dicttab = listtab + listtabsize; + DPRINTF(("osdict: data_addr %p strtab %p listtab %p dicttab %p end %p\n", + data_addr, strtab, listtab, dicttab, data_addr + datalen)); + + keyIterator->reset(); + nkeys = 0; + element = &module_data->data[0]; + DPRINTF(("osdict: element %p\n", element)); + while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) { + + // Get the key's value and determine its type + OSObject * value = dict->getObject(key); + if (!value) + continue; + + /* Store key */ + DPRINTF(("osdict: element @%p\n", element)); + element->key = strtab; + element->key_size = key->getLength() + 1; + DPRINTF(("osdict: key %s size %d @%p\n", key->getCStringNoCopy(), element->key_size, strtab)); + memcpy(element->key, key->getCStringNoCopy(), element->key_size); + + typeID = OSTypeIDInst(value); + if (primitive_type(value)) { + /* Store value */ + element->value = element->key + element->key_size; + DPRINTF(("osdict: primitive element value %p\n", element->value)); + primitive_type_collect(element, value); + strtab += element->key_size + element->value_size; + DPRINTF(("osdict: new strtab %p\n", strtab)); + } + else if (typeID == OSTypeID(OSArray)) { + unsigned int k, cnt, nents; + char *astrtab; + struct mac_module_data_list *arrayhd; + struct mac_module_data_element *ele; + OSArray *arrayObj = OSDynamicCast(OSArray, value); + + element->value = listtab; + DPRINTF(("osdict: array element value %p\n", element->value)); + element->value_type = MAC_DATA_TYPE_ARRAY; + arrayhd = (struct mac_module_data_list *)element->value; + arrayhd->type = 0; + DPRINTF(("osdict: arrayhd %p\n", arrayhd)); + nents = 0; + astrtab = strtab + element->key_size; + ele = &(arrayhd->list[0]); + cnt = arrayObj->getCount(); + for (k = 0; k < cnt; k++) { + value = arrayObj->getObject(k); + DPRINTF(("osdict: array ele %d @%p\n", nents, ele)); + ele->key = NULL; + ele->key_size = 0; + typeID = OSTypeIDInst(value); + if (primitive_type(value)) { + if (arrayhd->type != 0 && + arrayhd->type != MAC_DATA_TYPE_PRIMITIVE) + continue; + arrayhd->type = MAC_DATA_TYPE_PRIMITIVE; + ele->value = astrtab; + primitive_type_collect(ele, value); + astrtab += ele->value_size; + DPRINTF(("osdict: array new astrtab %p\n", astrtab)); + } + else if (typeID == OSTypeID(OSDictionary)) { + unsigned int dents; + char *dstrtab; + OSDictionary *dictObj; + OSString *dictkey; + OSCollectionIterator *dictIterator; + struct mac_module_data_list *dicthd; + struct mac_module_data_element *dele; + + if (arrayhd->type != 0 && + arrayhd->type != MAC_DATA_TYPE_DICT) + continue; + dictObj = OSDynamicCast(OSDictionary, value); + dictIterator = OSCollectionIterator::withCollection(dictObj); + if (!dictIterator) + goto finish; + DPRINTF(("osdict: dict\n")); + ele->value = dicttab; + ele->value_type = MAC_DATA_TYPE_DICT; + dicthd = (struct mac_module_data_list *)ele->value; + DPRINTF(("osdict: dicthd %p\n", dicthd)); + dstrtab = astrtab; + dents = 0; + while ((dictkey = OSDynamicCast(OSString, + dictIterator->getNextObject()))) { + OSObject *dictvalue; + + dictvalue = dictObj->getObject(dictkey); + if (!dictvalue) + continue; + dele = &(dicthd->list[dents]); + DPRINTF(("osdict: dict ele %d @%p\n", dents, dele)); + if (primitive_type(dictvalue)) { + dele->key = dstrtab; + dele->key_size = dictkey->getLength() + 1; + DPRINTF(("osdict: dictkey %s size %d @%p\n", + dictkey->getCStringNoCopy(), dictkey->getLength(), dstrtab)); + memcpy(dele->key, dictkey->getCStringNoCopy(), + dele->key_size); + dele->value = dele->key + dele->key_size; + primitive_type_collect(dele, dictvalue); + dstrtab += dele->key_size + dele->value_size; + DPRINTF(("osdict: dict new dstrtab %p\n", dstrtab)); + } + else { + continue; /* Only handle primitive types here. */ + } + dents++; + } + dictIterator->release(); + if (dents == 0) + continue; + arrayhd->type = MAC_DATA_TYPE_DICT; + ele->value_size = sizeof(struct mac_module_data_list) + + (dents - 1) * sizeof(struct mac_module_data_element); + DPRINTF(("osdict: dict ele size %d ents %d\n", ele->value_size, dents)); + dicttab += ele->value_size; + DPRINTF(("osdict: new dicttab %p\n", dicttab)); + dicthd->count = dents; + astrtab = dstrtab; + } + else { + continue; /* Skip everything else. */ + } + nents++; + ele++; + } + if (nents == 0) + continue; + element->value_size = sizeof(struct mac_module_data_list) + + (nents - 1) * sizeof(struct mac_module_data_element); + listtab += element->value_size; + DPRINTF(("osdict: new listtab %p\n", listtab)); + arrayhd->count = nents; + strtab = astrtab; + DPRINTF(("osdict: new strtab %p\n", strtab)); + } + else { + continue; /* skip anything else */ + } + element++; + } + DPRINTF(("module_data list @%p, key %p value %p\n", + module_data, module_data->data[0].key, module_data->data[0].value)); +finish: + if (keyIterator) + keyIterator->release(); + return(module_data); +} + +/********************************************************************* +* This function takes a plist and looks for an OSModuleData dictionary. +* If it is found, an encoded copy is returned. +*********************************************************************/ +kmod_args_t +get_module_data(OSDictionary * kextPlist, mach_msg_type_number_t * datalen) +{ + + OSDictionary * kextModuleData = 0; // don't release + struct mac_module_data * module_data = 0; + vm_map_copy_t copy = 0; + + kextModuleData = OSDynamicCast(OSDictionary, + kextPlist->getObject("OSModuleData")); + if (!kextModuleData) + goto finish; + + module_data = osdict_encode(kextModuleData); + if (!module_data) + goto finish; + *datalen = module_data->size; + /* + * Make a CoW copy of data and free the original. The copy is + * consumed by a call to vm_map_copyout() in kmod_start_or_stop(). + */ + vm_map_copyin(kernel_map, (vm_offset_t)module_data, *datalen, FALSE, ©); + kmem_free(kernel_map, (vm_offset_t)module_data, *datalen); + DPRINTF(("get_module_data: copy @ %p\n", copy)); +finish: + return (kmod_args_t)copy; +} +#endif /* MAC */ + static kern_return_t start_prelink_module(UInt32 moduleIndex) { @@ -205,7 +619,7 @@ kern_return_t start_prelink_module(UInt32 moduleIndex) if (depInfo) { kr = kmod_retain(KMOD_PACK_IDS(id, depInfo->id)); - kfree((vm_offset_t) depInfo, sizeof(kmod_info_t)); + kfree(depInfo, sizeof(kmod_info_t)); } else IOLog("%s: NO DEP %s\n", kmod_info->name, str->getCStringNoCopy()); } @@ -278,7 +692,7 @@ extern "C" Boolean kmod_load_request(const char * moduleName, Boolean make_reque // Is the module already loaded? ret = (0 != (kmod_info = kmod_lookupbyname_locked((char *)moduleName))); if (ret) { - kfree((vm_offset_t) kmod_info, sizeof(kmod_info_t)); + kfree(kmod_info, sizeof(kmod_info_t)); break; } sym = OSSymbol::withCString(moduleName); @@ -298,6 +712,7 @@ extern "C" Boolean kmod_load_request(const char * moduleName, Boolean make_reque IOLog("IOCatalogue: %s cannot be loaded " "(kmod load function not set).\n", moduleName); + ret = true; break; } @@ -456,7 +871,6 @@ void IOCatalogue::initialize( void ) // Initialize the IOCatalog object. bool IOCatalogue::init(OSArray * initArray) { - IORegistryEntry * entry; OSDictionary * dict; if ( !super::init() ) @@ -488,10 +902,6 @@ bool IOCatalogue::init(OSArray * initArray) thread_call_func_delayed( ping, this, deadline ); #endif - entry = IORegistryEntry::getRegistryRoot(); - if ( entry ) - entry->setProperty(kIOCatalogueKey, this); - return true; } @@ -844,7 +1254,7 @@ IOReturn IOCatalogue::unloadModule( OSString * moduleName ) const if ( k_info->stop && !((ret = k_info->stop(k_info, 0)) == kIOReturnSuccess) ) { - kfree((vm_offset_t) k_info, sizeof(kmod_info_t)); + kfree(k_info, sizeof(kmod_info_t)); return ret; } @@ -853,18 +1263,16 @@ IOReturn IOCatalogue::unloadModule( OSString * moduleName ) const } if (k_info) { - kfree((vm_offset_t) k_info, sizeof(kmod_info_t)); + kfree(k_info, sizeof(kmod_info_t)); } return ret; } -static IOReturn _terminateDrivers( OSArray * array, OSDictionary * matching ) +static IOReturn _terminateDrivers( OSDictionary * matching ) { - OSCollectionIterator * tables; OSDictionary * dict; OSIterator * iter; - OSArray * arrayCopy; IOService * service; IOReturn ret; @@ -903,9 +1311,17 @@ static IOReturn _terminateDrivers( OSArray * array, OSDictionary * matching ) } while( !service && !iter->isValid()); iter->release(); + return ret; +} + +static IOReturn _removeDrivers( OSArray * array, OSDictionary * matching ) +{ + OSCollectionIterator * tables; + OSDictionary * dict; + OSArray * arrayCopy; + IOReturn ret = kIOReturnSuccess; + // remove configs from catalog. - if ( ret != kIOReturnSuccess ) - return ret; arrayCopy = OSArray::withCapacity(100); if ( !arrayCopy ) @@ -941,9 +1357,10 @@ IOReturn IOCatalogue::terminateDrivers( OSDictionary * matching ) { IOReturn ret; - ret = kIOReturnSuccess; + ret = _terminateDrivers(matching); IOLockLock( lock ); - ret = _terminateDrivers(array, matching); + if (kIOReturnSuccess == ret) + ret = _removeDrivers(array, matching); kernelTables->reset(); IOLockUnlock( lock ); @@ -963,9 +1380,10 @@ IOReturn IOCatalogue::terminateDriversForModule( dict->setObject(gIOModuleIdentifierKey, moduleName); + ret = _terminateDrivers(dict); IOLockLock( lock ); - - ret = _terminateDrivers(array, dict); + if (kIOReturnSuccess == ret) + ret = _removeDrivers(array, dict); kernelTables->reset(); // Unload the module itself. @@ -1042,18 +1460,10 @@ void IOCatalogue::reset(void) bool IOCatalogue::serialize(OSSerialize * s) const { - bool ret; - if ( !s ) return false; - IOLockLock( lock ); - - ret = array->serialize(s); - - IOLockUnlock( lock ); - - return ret; + return super::serialize(s); } bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const @@ -1063,7 +1473,7 @@ bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const switch ( kind ) { case kIOCatalogGetContents: - if (!serialize(s)) + if (!array->serialize(s)) kr = kIOReturnNoMemory; break; @@ -1125,6 +1535,8 @@ bool IOCatalogue::recordStartupExtensions(void) { /********************************************************************* +* This function operates on sections retrieved from the currently running +* 32 bit mach kernel. *********************************************************************/ bool IOCatalogue::addExtensionsFromArchive(OSData * mkext) { @@ -1167,18 +1579,22 @@ bool IOCatalogue::addExtensionsFromArchive(OSData * mkext) return result; } - /********************************************************************* * This function clears out all references to the in-kernel linker, * frees the list of startup extensions in extensionDict, and * deallocates the kernel's __KLD segment to reclaim that memory. +* +* The segments it operates on are strictly 32 bit segments. *********************************************************************/ kern_return_t IOCatalogue::removeKernelLinker(void) { kern_return_t result = KERN_SUCCESS; - struct segment_command * segment; + struct segment_command * segmentLE, *segmentKLD; + boolean_t keepsyms = FALSE; +#if __ppc__ || __arm__ char * dt_segment_name; void * segment_paddress; int segment_size; +#endif /* This must be the very first thing done by this function. */ @@ -1193,6 +1609,8 @@ kern_return_t IOCatalogue::removeKernelLinker(void) { goto finish; } + PE_parse_boot_argn("keepsyms", &keepsyms, sizeof (keepsyms)); + IOLog("Jettisoning kernel linker.\n"); kernelLinkerPresent = 0; @@ -1212,25 +1630,15 @@ kern_return_t IOCatalogue::removeKernelLinker(void) { * memory so that any cross-dependencies (not that there * should be any) are handled. */ - segment = getsegbyname("__KLD"); - if (!segment) { - IOLog("error removing kernel linker: can't find %s segment\n", - "__KLD"); + segmentKLD = getsegbyname("__KLD"); + if (!segmentKLD) { + IOLog("error removing kernel linker: can't find __KLD segment\n"); result = KERN_FAILURE; goto finish; } - OSRuntimeUnloadCPPForSegment(segment); - - segment = getsegbyname("__LINKEDIT"); - if (!segment) { - IOLog("error removing kernel linker: can't find %s segment\n", - "__LINKEDIT"); - result = KERN_FAILURE; - goto finish; - } - OSRuntimeUnloadCPPForSegment(segment); - + OSRuntimeUnloadCPPForSegment(segmentKLD); +#if __ppc__ || __arm__ /* Free the memory that was set up by bootx. */ dt_segment_name = "Kernel-__KLD"; @@ -1238,22 +1646,22 @@ kern_return_t IOCatalogue::removeKernelLinker(void) { IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, (int)segment_size); } - - dt_segment_name = "Kernel-__LINKEDIT"; - if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) { - IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, - (int)segment_size); - } +#elif __i386__ + /* On x86, use the mapping data from the segment load command to + * unload KLD directly, unless the keepsyms boot-arg was enabled. + * This may invalidate any assumptions about "avail_start" + * defining the lower bound for valid physical addresses. + */ + if (!keepsyms && segmentKLD->vmaddr && segmentKLD->vmsize) + ml_static_mfree(segmentKLD->vmaddr, segmentKLD->vmsize); +#else +#error arch +#endif struct section * sect; sect = getsectbyname("__PRELINK", "__symtab"); - if (sect && sect->addr) - { - vm_offset_t - virt = ml_static_ptovirt(sect->addr); - if( virt) { - ml_static_mfree(virt, sect->size); - } + if (sect && sect->addr) { + ml_static_mfree(sect->addr, sect->size); } finish: @@ -1264,3 +1672,26 @@ finish: return result; } + +/********************************************************************* +* This function stops the catalogue from making kextd requests during +* shutdown. +*********************************************************************/ +void IOCatalogue::disableExternalLinker(void) { + IOLockLock(gIOKLDLock); + /* If kmod_load_extension (the kextd requester function) is in use, + * disable new module requests. + */ + if (kmod_load_function == &kmod_load_extension) { + kmod_load_function = NULL; + } + + IOLockUnlock(gIOKLDLock); +} + +extern "C" +void jettison_kernel_linker(void) +{ + if (gIOCatalogue != NULL) + gIOCatalogue->removeKernelLinker(); +}