2  * Copyright (c) 2008-2009 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  30 #include <kern/clock.h> 
  31 #include <kern/host.h> 
  32 #include <kern/kext_alloc.h> 
  33 #include <kextd/kextd_mach.h> 
  34 #include <libkern/kernel_mach_header.h> 
  35 #include <libkern/kext_panic_report.h> 
  36 #include <libkern/kext_request_keys.h> 
  37 #include <libkern/mkext.h> 
  38 #include <libkern/prelink.h> 
  39 #include <libkern/version.h> 
  40 #include <libkern/zlib.h> 
  41 #include <mach/mach_vm.h> 
  42 #include <sys/sysctl.h> 
  45 #include <libkern/OSKextLibPrivate.h> 
  46 #include <libkern/c++/OSKext.h> 
  47 #include <libkern/c++/OSLib.h> 
  49 #include <IOKit/IOLib.h> 
  50 #include <IOKit/IOCatalogue.h> 
  51 #include <IOKit/IORegistryEntry.h> 
  52 #include <IOKit/IOService.h> 
  55 #pragma mark External & Internal Function Protos 
  57 /********************************************************************* 
  58 *********************************************************************/ 
  60 // in libkern/OSKextLib.cpp, not in header for a reason. 
  61 extern kern_return_t 
OSKextPingKextd(void); 
  63 extern int  IODTGetLoaderInfo(const char * key
, void ** infoAddr
, int * infoSize
); 
  64 extern void IODTFreeLoaderInfo(const char * key
, void * infoAddr
, int infoSize
); 
  65 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t 
* segment
); 
  66 extern void OSRuntimeUnloadCPP(kmod_info_t 
* ki
, void * data
); 
  68 extern ppnum_t 
pmap_find_phys(pmap_t pmap
, addr64_t va
); /* osfmk/machine/pmap.h */ 
  71 static OSReturn 
_OSKextCreateRequest( 
  72     const char    * predicate
, 
  73     OSDictionary 
** requestP
); 
  74 static OSString 
* _OSKextGetRequestPredicate(OSDictionary 
* requestDict
); 
  75 static OSObject 
* _OSKextGetRequestArgument( 
  76     OSDictionary 
* requestDict
, 
  77     const char   * argName
); 
  78 static bool _OSKextSetRequestArgument( 
  79     OSDictionary 
* requestDict
, 
  82 static void * _OSKextExtractPointer(OSData 
* wrapper
); 
  83 static OSReturn 
_OSDictionarySetCStringValue( 
  88 static void * MACFCopyModuleDataForKext( 
  90     mach_msg_type_number_t 
* datalen
); 
  91 #endif /* CONFIG_MACF_KEXT */ 
  94 #pragma mark Constants & Macros 
  96 /********************************************************************* 
  98 *********************************************************************/ 
 100 /* A typical Snow Leopard system has a bit under 120 kexts loaded. 
 101  * Use this number to create containers. 
 103 #define kOSKextTypicalLoadCount      (120) 
 105 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict. 
 106  * A loaded kext will no dependents or external retains will have 2 retains. 
 108 #define kOSKextMinRetainCount        (1) 
 109 #define kOSKextMinLoadedRetainCount  (2) 
 112  * Strings and substrings used in dependency resolution. 
 114 #define APPLE_KEXT_PREFIX            "com.apple." 
 115 #define KERNEL_LIB                   "com.apple.kernel" 
 117 #define PRIVATE_KPI                  "com.apple.kpi.private" 
 119 /* Version for compatbility pseudokexts (com.apple.kernel.*), 
 120  * compatible back to v6.0. 
 122 #define KERNEL6_LIB                  "com.apple.kernel.6.0" 
 123 #define KERNEL6_VERSION              "7.9.9" 
 125 #define KERNEL_LIB_PREFIX            "com.apple.kernel." 
 126 #define KPI_LIB_PREFIX               "com.apple.kpi." 
 128 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0) 
 130 /********************************************************************* 
 131 * infoDict keys for internally-stored data. Saves on ivar slots for 
 132 * objects we don't keep around past boot time or during active load. 
 133 *********************************************************************/ 
 135 /* A usable, uncompressed file is stored under this key. 
 137 #define _kOSKextExecutableKey                "_OSKextExecutable" 
 139 /* An indirect reference to the executable file from an mkext 
 140  * is stored under this key. 
 142 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference" 
 144 /* If the file is contained in a larger buffer laid down by the booter or 
 145  * sent from user space, the OSKext stores that OSData under this key so that 
 146  * references are properly tracked. This is always an mkext, right now. 
 148 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData" 
 151 #pragma mark Typedefs 
 153 /********************************************************************* 
 155 *********************************************************************/ 
 157 /********************************************************************* 
 158 * MkextEntryRef describes the contents of an OSData object 
 159 * referencing a file entry from an mkext so that we can uncompress 
 160 * (if necessary) and extract it on demand. 
 162 * It contains the mkextVersion in case we ever wind up supporting 
 163 * multiple mkext formats. Mkext format 1 is officially retired as of 
 165 *********************************************************************/ 
 166 typedef struct MkextEntryRef 
{ 
 167     mkext_basic_header 
* mkext
;     // beginning of whole mkext file 
 168     void               * fileinfo
;  // mkext2_file_entry or equiv; see mkext.h 
 172 #pragma mark Global and static Module Variables 
 174 /********************************************************************* 
 175 * Global & static variables, used to keep track of kexts. 
 176 *********************************************************************/ 
 178 static  bool                sPrelinkBoot               
= false; 
 179 static  bool                sSafeBoot                  
= false; 
 182 * sKextLock is the principal lock for OSKext. Below, there is also an 
 183 * sKextInnerLock used to guard access to data accessed on in-calls from 
 184 * IOService. This 2nd lock is required to prevent a deadlock 
 185 * with IOService calling back into OSKext::considerUnloads() 
 186 * on a separate thread during a kext load operation. 
 188 static IORecursiveLock    
* sKextLock                  
= NULL
; 
 190 static OSDictionary       
* sKextsByID                 
= NULL
; 
 191 static OSArray            
* sLoadedKexts               
= NULL
; 
 193 // Requests to kextd waiting to be picked up. 
 194 static OSArray            
* sKernelRequests            
= NULL
; 
 195 // Identifier of kext load requests in sKernelRequests 
 196 static OSSet              
* sPostedKextLoadIdentifiers 
= NULL
; 
 197 static OSArray            
* sRequestCallbackRecords    
= NULL
; 
 199 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel 
 200 static OSSet              
* sAllKextLoadIdentifiers    
= NULL
; 
 201 static KXLDContext        
* sKxldContext               
= NULL
; 
 202 static uint32_t             sNextLoadTag               
= 0; 
 203 static uint32_t             sNextRequestTag            
= 0; 
 205 static bool                 sUserLoadsActive           
= false; 
 206 static bool                 sKextdActive               
= false; 
 207 static bool                 sDeferredLoadSucceeded     
= false; 
 208 static bool                 sConsiderUnloadsExecuted   
= false; 
 210 static bool                 sKernelRequestsEnabled     
= true; 
 211 static bool                 sLoadEnabled               
= true; 
 212 static bool                 sUnloadEnabled             
= true; 
 214 /********************************************************************* 
 215 * Stuff for the OSKext representing the kernel itself. 
 217 static OSKext          
* sKernelKext             
= NULL
; 
 219 /* Set up a fake kmod_info struct for the kernel. 
 220  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP() 
 221  * before OSKext is initialized; that call only needs the name 
 222  * and address to be set correctly. 
 224  * We don't do much else with the kerne's kmod_info; we never 
 225  * put it into the kmod list, never adjust the reference count, 
 226  * and never have kernel components reference it. 
 227  * For that matter, we don't do much with kmod_info structs 
 228  * at all anymore! We just keep them filled in for gdb and 
 229  * binary compability. 
 231 kmod_info_t g_kernel_kmod_info 
= { 
 233     /* info_version    */ KMOD_INFO_VERSION
, 
 234     /* id              */ 0,                 // loadTag: kernel is always 0 
 235     /* name            */ kOSKextKernelIdentifier
,    // bundle identifier 
 236     /* version         */ "0",               // filled in in OSKext::initialize() 
 237     /* reference_count */ -1,                // never adjusted; kernel never unloads 
 238     /* reference_list  */ NULL
, 
 239     /* address         */ (vm_address_t
)&_mh_execute_header
, 
 240     /* size            */ 0,                 // filled in in OSKext::initialize() 
 247 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c, 
 248 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s, 
 249 // misc_protos.h, db_low_trace.c, kgmacros 
 250 // 'kmod' is a holdover from the old kmod system, we can't rename it. 
 251 kmod_info_t 
* kmod 
= NULL
; 
 253 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE) 
 255 static char     * unloaded_kext_paniclist        
= NULL
; 
 256 static uint32_t   unloaded_kext_paniclist_size   
= 0; 
 257 static uint32_t   unloaded_kext_paniclist_length 
= 0; 
 258 AbsoluteTime      last_loaded_timestamp
; 
 260 static char     * loaded_kext_paniclist          
= NULL
; 
 261 static uint32_t   loaded_kext_paniclist_size     
= 0; 
 262 static uint32_t   loaded_kext_paniclist_length   
= 0; 
 263 AbsoluteTime      last_unloaded_timestamp
; 
 264 static void     * last_unloaded_address          
= NULL
; 
 266 static uint64_t   last_unloaded_size             
= 0; 
 268 static uint32_t   last_unloaded_size             
= 0; 
 269 #endif /* __LP64__ */ 
 273 /********************************************************************* 
 274 * Because we can start IOService matching from OSKext (via IOCatalogue) 
 275 * and IOService can call into OSKext, there is potential for cross-lock 
 276 * contention, so OSKext needs two locks. The regular sKextLock above 
 277 * guards most OSKext class/static variables, and sKextInnerLock guards 
 278 * variables that can be accessed on in-calls from IOService, currently: 
 280 *   * OSKext::considerUnloads() 
 282 * Note that sConsiderUnloadsExecuted above belongs to sKextLock! 
 284 * When both sKextLock and sKextInnerLock need to be taken, 
 285 * always lock sKextLock first and unlock it second. Never take both 
 286 * locks in an entry point to OSKext; if you need to do so, you must 
 287 * spawn an independent thread to avoid potential deadlocks for threads 
 288 * calling into OSKext. 
 290 * All static variables from here to the closing comment block fall 
 291 * under sKextInnerLock. 
 293 static IORecursiveLock 
*    sKextInnerLock             
= NULL
; 
 295 static bool                 sAutounloadEnabled         
= true; 
 296 static bool                 sConsiderUnloadsCalled     
= false; 
 297 static bool                 sConsiderUnloadsPending    
= false; 
 299 static unsigned int         sConsiderUnloadDelay       
= 60;     // seconds 
 300 static thread_call_t        sUnloadCallout             
= 0; 
 301 static thread_call_t        sDestroyLinkContextThread  
= 0;      // one-shot, one-at-a-time thread 
 302 static bool                 sSystemSleep               
= false;  // true when system going to sleep 
 304 static  const OSKextLogSpec kDefaultKernelLogFilter    
= kOSKextLogBasicLevel 
| 
 305                                                          kOSKextLogVerboseFlagsMask
; 
 306 static  OSKextLogSpec       sKernelLogFilter           
= kDefaultKernelLogFilter
; 
 307 static  bool                sBootArgLogFilterFound     
= false; 
 308 SYSCTL_INT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW
, &sKernelLogFilter
, 
 309     sKernelLogFilter
, "kernel kext logging"); 
 311 static  OSKextLogSpec       sUserSpaceKextLogFilter    
= kOSKextLogSilentFilter
; 
 312 static  OSArray           
* sUserSpaceLogSpecArray     
= NULL
; 
 313 static  OSArray           
* sUserSpaceLogMessageArray  
= NULL
; 
 316 * End scope for sKextInnerLock-protected variables. 
 317 *********************************************************************/ 
 320 #pragma mark OSData callbacks (need to move to OSData) 
 322 /********************************************************************* 
 323 * C functions used for callbacks. 
 324 *********************************************************************/ 
 326 void osdata_kmem_free(void * ptr
, unsigned int length
) { 
 327     kmem_free(kernel_map
, (vm_address_t
)ptr
, length
); 
 331 void osdata_phys_free(void * ptr
, unsigned int length
) { 
 332     ml_static_mfree((vm_offset_t
)ptr
, length
); 
 336 void osdata_vm_deallocate(void * ptr
, unsigned int length
) 
 338     (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
); 
 344 #pragma mark KXLD Allocation Callback 
 346 /********************************************************************* 
 347 * KXLD Allocation Callback 
 348 *********************************************************************/ 
 352     KXLDAllocateFlags 
* flags
, 
 355     vm_address_t  result       
= 0;     // returned 
 356     kern_return_t mach_result  
= KERN_FAILURE
; 
 357     bool          success      
= false; 
 358     OSKext      
* theKext      
= (OSKext 
*)user_data
; 
 359     u_long        roundSize    
= round_page(size
); 
 360     OSData      
* linkBuffer   
= NULL
;  // must release 
 362     mach_result 
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
); 
 363     if (mach_result 
!= KERN_SUCCESS
) { 
 365             kOSKextLogErrorLevel 
| 
 366             kOSKextLogGeneralFlag
, 
 367             "Can't allocate kernel memory to link %s.", 
 368             theKext
->getIdentifierCString()); 
 372    /* Create an OSData wrapper for the allocated buffer. 
 373     * Note that we do not set a dealloc function on it here. 
 374     * We have to call vm_map_unwire() on it in OSKext::unload() 
 375     * and an OSData dealloc function can't take all those parameters. 
 377     linkBuffer 
= OSData::withBytesNoCopy((void *)result
, roundSize
); 
 380             kOSKextLogErrorLevel 
| 
 381             kOSKextLogGeneralFlag
, 
 382             "Can't allocate linked executable wrapper for %s.", 
 383             theKext
->getIdentifierCString()); 
 388         kOSKextLogProgressLevel 
| 
 389         kOSKextLogLoadFlag 
| kOSKextLogLinkFlag
, 
 390         "Allocated link buffer for kext %s at %p (%lu bytes).", 
 391         theKext
->getIdentifierCString(), 
 392         (void *)result
, (unsigned long)roundSize
); 
 394     theKext
->setLinkedExecutable(linkBuffer
); 
 396     *flags 
= kKxldAllocateWritable
; 
 400     if (!success 
&& result
) { 
 401         kext_free(result
, roundSize
); 
 405     OSSafeRelease(linkBuffer
); 
 407     return (kxld_addr_t
)result
; 
 410 /********************************************************************* 
 411 *********************************************************************/ 
 414     KXLDLogSubsystem    subsystem
, 
 420     OSKext 
*theKext 
= (OSKext 
*) user_data
; 
 421     OSKextLogSpec logSpec 
= 0; 
 424     case kKxldLogLinking
: 
 425         logSpec 
|= kOSKextLogLinkFlag
; 
 427     case kKxldLogPatching
: 
 428         logSpec 
|= kOSKextLogPatchFlag
; 
 433     case kKxldLogExplicit
: 
 434         logSpec 
|= kOSKextLogExplicitLevel
; 
 437         logSpec 
|= kOSKextLogErrorLevel
; 
 440         logSpec 
|= kOSKextLogWarningLevel
; 
 443         logSpec 
|= kOSKextLogProgressLevel
; 
 446         logSpec 
|= kOSKextLogDetailLevel
; 
 449         logSpec 
|= kOSKextLogDebugLevel
; 
 453     OSKextVLog(theKext
, logSpec
, format
, argList
); 
 457 #pragma mark Module Config (Startup & Shutdown) 
 459 /********************************************************************* 
 460 * Module Config (Class Definition & Class Methods) 
 461 *********************************************************************/ 
 462 #define super OSObject 
 463 OSDefineMetaClassAndStructors(OSKext
, OSObject
) 
 465 /********************************************************************* 
 466 *********************************************************************/ 
 469 OSKext::initialize(void) 
 471     OSData          
* kernelExecutable   
= NULL
;  // do not release 
 472     u_char          
* kernelStart        
= NULL
;  // do not free 
 473     size_t            kernelLength       
= 0; 
 474     OSString        
* scratchString      
= NULL
;  // must release 
 475     IORegistryEntry 
* registryRoot       
= NULL
;  // do not release 
 476     OSNumber        
* kernelCPUType      
= NULL
;  // must release 
 477     OSNumber        
* kernelCPUSubtype   
= NULL
;  // must release 
 478     OSKextLogSpec     bootLogFilter      
= kOSKextLogSilentFilter
; 
 479     bool              setResult          
= false; 
 480     uint64_t        * timestamp          
= 0; 
 481     char              bootArgBuffer
[16];  // for PE_parse_boot_argn w/strings 
 483    /* This must be the first thing allocated. Everything else grabs this lock. 
 485     sKextLock 
= IORecursiveLockAlloc(); 
 486     sKextInnerLock 
= IORecursiveLockAlloc(); 
 488     assert(sKextInnerLock
); 
 490     sKextsByID 
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
); 
 491     sLoadedKexts 
= OSArray::withCapacity(kOSKextTypicalLoadCount
); 
 492     sKernelRequests 
= OSArray::withCapacity(0); 
 493     sPostedKextLoadIdentifiers 
= OSSet::withCapacity(0); 
 494     sAllKextLoadIdentifiers 
= OSSet::withCapacity(kOSKextTypicalLoadCount
); 
 495     sRequestCallbackRecords 
= OSArray::withCapacity(0); 
 496     assert(sKextsByID 
&& sLoadedKexts 
&& sKernelRequests 
&& 
 497         sPostedKextLoadIdentifiers 
&& sAllKextLoadIdentifiers 
&& 
 498         sRequestCallbackRecords
); 
 500    /* Read the log flag boot-args and set the log flags. 
 502     if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof("kextlog=0x00000000 "))) { 
 503         sBootArgLogFilterFound 
= true; 
 504         sKernelLogFilter 
= bootLogFilter
; 
 505         // log this if any flags are set 
 506         OSKextLog(/* kext */ NULL
, 
 507             kOSKextLogBasicLevel 
| 
 509             "Kernel kext log filter 0x%x per kextlog boot arg.", 
 510             (unsigned)sKernelLogFilter
); 
 513     sSafeBoot 
= PE_parse_boot_argn("-x", bootArgBuffer
, 
 514         sizeof(bootArgBuffer
)) ? true : false; 
 517         OSKextLog(/* kext */ NULL
, 
 518             kOSKextLogWarningLevel 
| 
 519             kOSKextLogGeneralFlag
, 
 520             "SAFE BOOT DETECTED - " 
 521             "only valid OSBundleRequired kexts will be loaded."); 
 524    /* Set up an OSKext instance to represent the kernel itself. 
 526     sKernelKext 
= new OSKext
; 
 529     kernelStart 
= (u_char 
*)&_mh_execute_header
; 
 530     kernelLength 
= getlastaddr() - (vm_offset_t
)kernelStart
; 
 531     kernelExecutable 
= OSData::withBytesNoCopy( 
 532         kernelStart
, kernelLength
); 
 533     assert(kernelExecutable
); 
 535     sKernelKext
->loadTag 
= sNextLoadTag
++;  // the kernel is load tag 0 
 536     sKernelKext
->bundleID 
= OSSymbol::withCString(kOSKextKernelIdentifier
); 
 538     sKernelKext
->version 
= OSKextParseVersionString(osrelease
); 
 539     sKernelKext
->compatibleVersion 
= sKernelKext
->version
; 
 540     sKernelKext
->linkedExecutable 
= kernelExecutable
; 
 541     // linkState will be set first time we do a link 
 543     sKernelKext
->flags
.hasAllDependencies 
= 1; 
 544     sKernelKext
->flags
.kernelComponent 
= 1; 
 545     sKernelKext
->flags
.prelinked 
= 0; 
 546     sKernelKext
->flags
.loaded 
= 1; 
 547     sKernelKext
->flags
.started 
= 1; 
 548     sKernelKext
->flags
.CPPInitialized 
= 0; 
 550     sKernelKext
->kmod_info 
= &g_kernel_kmod_info
; 
 551     strlcpy(g_kernel_kmod_info
.version
, osrelease
, 
 552         sizeof(g_kernel_kmod_info
.version
)); 
 553     g_kernel_kmod_info
.size 
= kernelLength
; 
 554     g_kernel_kmod_info
.id 
= sKernelKext
->loadTag
; 
 556    /* Cons up an info dict, so we don't have to have special-case 
 559     sKernelKext
->infoDict 
= OSDictionary::withCapacity(5); 
 560     assert(sKernelKext
->infoDict
); 
 561     setResult 
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
, 
 562         sKernelKext
->bundleID
); 
 564     setResult 
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
, 
 568     scratchString 
= OSString::withCStringNoCopy(osrelease
); 
 569     assert(scratchString
); 
 570     setResult 
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
, 
 573     OSSafeReleaseNULL(scratchString
); 
 575     scratchString 
= OSString::withCStringNoCopy("mach_kernel"); 
 576     assert(scratchString
); 
 577     setResult 
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
, 
 580     OSSafeReleaseNULL(scratchString
); 
 582    /* Add the kernel kext to the bookkeeping dictionaries. Note that 
 583     * the kernel kext doesn't have a kmod_info struct. copyInfo() 
 584     * gathers info from other places anyhow. 
 586     setResult 
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
); 
 588     setResult 
= sLoadedKexts
->setObject(sKernelKext
); 
 590     sKernelKext
->release(); 
 592     registryRoot 
= IORegistryEntry::getRegistryRoot(); 
 593     kernelCPUType 
= OSNumber::withNumber( 
 594         (long long unsigned int)_mh_execute_header
.cputype
, 
 595         8 * sizeof(_mh_execute_header
.cputype
)); 
 596     kernelCPUSubtype 
= OSNumber::withNumber( 
 597         (long long unsigned int)_mh_execute_header
.cpusubtype
, 
 598         8 * sizeof(_mh_execute_header
.cpusubtype
)); 
 599     assert(registryRoot 
&& kernelCPUSubtype 
&& kernelCPUType
); 
 601     registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
); 
 602     registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
); 
 604     OSSafeRelease(kernelCPUType
); 
 605     OSSafeRelease(kernelCPUSubtype
); 
 607     timestamp 
= __OSAbsoluteTimePtr(&last_loaded_timestamp
); 
 609     timestamp 
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
); 
 612     OSKextLog(/* kext */ NULL
, 
 613         kOSKextLogProgressLevel 
| 
 614         kOSKextLogGeneralFlag
, 
 615         "Kext system initialized."); 
 620 /********************************************************************* 
 621 * This could be in OSKextLib.cpp but we need to hold a lock 
 622 * while removing all the segments and sKextLock will do. 
 623 *********************************************************************/ 
 626 OSKext::removeKextBootstrap(void) 
 628     OSReturn                   result                
= kOSReturnError
; 
 630     static bool                alreadyDone           
= false; 
 631     boolean_t                  keepsyms              
= FALSE
; 
 633     const char               * dt_kernel_header_name 
= "Kernel-__HEADER"; 
 634     const char               * dt_kernel_symtab_name 
= "Kernel-__SYMTAB"; 
 635     kernel_mach_header_t     
* dt_mach_header        
= NULL
; 
 636     int                        dt_mach_header_size   
= 0; 
 637     struct symtab_command    
* dt_symtab             
= NULL
; 
 638     int                        dt_symtab_size        
= 0; 
 641     kernel_segment_command_t 
* seg_to_remove         
= NULL
; 
 642 #if __ppc__ || __arm__ 
 643     const char               * dt_segment_name       
= NULL
; 
 644     void                     * segment_paddress      
= NULL
; 
 645     int                        segment_size          
= 0; 
 648    /* This must be the very first thing done by this function. 
 650     IORecursiveLockLock(sKextLock
); 
 652    /* If we already did this, it's a success. 
 655         result 
= kOSReturnSuccess
; 
 659     OSKextLog(/* kext */ NULL
, 
 660         kOSKextLogProgressLevel 
| 
 661         kOSKextLogGeneralFlag
, 
 662         "Jettisoning kext bootstrap segments."); 
 664     PE_parse_boot_argn("keepsyms", &keepsyms
, sizeof(keepsyms
)); 
 667     * Dispose of unnecessary stuff that the booter didn't need to load. 
 669     dt_result 
= IODTGetLoaderInfo(dt_kernel_header_name
, 
 670         (void **)&dt_mach_header
, &dt_mach_header_size
); 
 671     if (dt_result 
== 0 && dt_mach_header
) { 
 672         IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
, 
 673             round_page_32(dt_mach_header_size
)); 
 675     dt_result 
= IODTGetLoaderInfo(dt_kernel_symtab_name
, 
 676         (void **)&dt_symtab
, &dt_symtab_size
); 
 677     if (dt_result 
== 0 && dt_symtab
) { 
 678         IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
, 
 679             round_page_32(dt_symtab_size
)); 
 683     * KLD bootstrap segment. 
 685     // xxx - should rename KLD segment 
 686     seg_to_remove 
= getsegbyname("__KLD"); 
 688         OSRuntimeUnloadCPPForSegment(seg_to_remove
); 
 691 #if __ppc__ || __arm__ 
 692    /* Free the memory that was set up by bootx. 
 694     dt_segment_name 
= "Kernel-__KLD"; 
 695     if (0 == IODTGetLoaderInfo(dt_segment_name
, &segment_paddress
, &segment_size
)) { 
 696         IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
, 
 699 #elif __i386__ || __x86_64__ 
 700    /* On x86, use the mapping data from the segment load command to 
 701     * unload KLD directly. 
 702     * This may invalidate any assumptions about  "avail_start" 
 703     * defining the lower bound for valid physical addresses. 
 705     if (seg_to_remove 
&& seg_to_remove
->vmaddr 
&& seg_to_remove
->vmsize
) { 
 706         ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
); 
 712     seg_to_remove 
= NULL
; 
 715     * Prelinked kernel's symtab (if there is one). 
 717     kernel_section_t 
* sect
; 
 718     sect 
= getsectbyname("__PRELINK", "__symtab"); 
 719     if (sect 
&& sect
->addr 
&& sect
->size
) { 
 720         ml_static_mfree(sect
->addr
, sect
->size
); 
 724     * Dump the LINKEDIT segment, unless keepsyms is set. 
 727         seg_to_remove 
= (kernel_segment_command_t 
*)getsegbyname("__LINKEDIT"); 
 729             OSRuntimeUnloadCPPForSegment(seg_to_remove
); 
 732 #if __ppc__ || __arm__ 
 733         dt_segment_name 
= "Kernel-__LINKEDIT"; 
 734         if (0 == IODTGetLoaderInfo(dt_segment_name
, 
 735             &segment_paddress
, &segment_size
)) { 
 737             IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
, 
 740 #elif __i386__ || __x86_64__ 
 741         if (seg_to_remove 
&& seg_to_remove
->vmaddr 
&& seg_to_remove
->vmsize
) { 
 742             ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
); 
 748         OSKextLog(/* kext */ NULL
, 
 749             kOSKextLogBasicLevel 
| 
 750             kOSKextLogGeneralFlag
, 
 751             "keepsyms boot arg specified; keeping linkedit segment for symbols."); 
 754     seg_to_remove 
= NULL
; 
 757     result 
= kOSReturnSuccess
; 
 761    /* This must be the very last thing done before returning. 
 763     IORecursiveLockUnlock(sKextLock
); 
 768 /********************************************************************* 
 769 *********************************************************************/ 
 771 OSKext::flushNonloadedKexts( 
 772     Boolean flushPrelinkedKexts
) 
 774     OSSet                
* prelinkedKexts  
= NULL
;  // must release 
 775     OSCollectionIterator 
* kextIterator    
= NULL
;  // must release 
 776     OSCollectionIterator 
* prelinkIterator 
= NULL
;  // must release 
 777     const OSSymbol       
* thisID          
= NULL
;  // do not release 
 778     OSKext               
* thisKext        
= NULL
;  // do not release 
 781     IORecursiveLockLock(sKextLock
); 
 783     OSKextLog(/* kext */ NULL
, 
 784         kOSKextLogProgressLevel 
| 
 785         kOSKextLogKextBookkeepingFlag
, 
 786         "Flushing nonloaded kexts and other unused data."); 
 788     OSKext::considerDestroyingLinkContext(); 
 790    /* If we aren't flushing unused prelinked kexts, we have to put them 
 791     * aside while we flush everything else so make a container for them. 
 793     if (!flushPrelinkedKexts
) { 
 794         prelinkedKexts 
= OSSet::withCapacity(0); 
 795         if (!prelinkedKexts
) { 
 800    /* Set aside prelinked kexts (in-use or not) and break 
 801     * any lingering inter-kext references for nonloaded kexts 
 802     * so they have min. retain counts. 
 804     kextIterator 
= OSCollectionIterator::withCollection(sKextsByID
); 
 809     while ((thisID 
= OSDynamicCast(OSSymbol
,  
 810             kextIterator
->getNextObject()))) { 
 812         thisKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
)); 
 815             if (prelinkedKexts 
&& thisKext
->isPrelinked()) { 
 816                 prelinkedKexts
->setObject(thisKext
); 
 818             thisKext
->flushDependencies(/* forceIfLoaded */ false); 
 822    /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly. 
 824     sKextsByID
->flushCollection(); 
 826    /* Now put the loaded kexts back into the ID dictionary. 
 828     count 
= sLoadedKexts
->getCount(); 
 829     for (i 
= 0; i 
< count
; i
++) { 
 830         thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
 831         sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
); 
 834    /* Finally, put back the prelinked kexts if we saved any. 
 836     if (prelinkedKexts
) { 
 837         prelinkIterator 
= OSCollectionIterator::withCollection(prelinkedKexts
); 
 838         if (!prelinkIterator
) { 
 842         while ((thisKext 
= OSDynamicCast(OSKext
, 
 843             prelinkIterator
->getNextObject()))) { 
 845             sKextsByID
->setObject(thisKext
->getIdentifierCString(), 
 851     IORecursiveLockUnlock(sKextLock
); 
 853     OSSafeRelease(prelinkedKexts
); 
 854     OSSafeRelease(kextIterator
); 
 855     OSSafeRelease(prelinkIterator
); 
 860 /********************************************************************* 
 861 *********************************************************************/ 
 864 OSKext::setKextdActive(Boolean active
) 
 866     IORecursiveLockLock(sKextLock
); 
 867     sKextdActive 
= active
; 
 868     if (sKernelRequests
->getCount()) { 
 871     IORecursiveLockUnlock(sKextLock
); 
 876 /********************************************************************* 
 877 *********************************************************************/ 
 880 OSKext::setDeferredLoadSucceeded(Boolean succeeded
) 
 882     IORecursiveLockLock(sKextLock
); 
 883     sDeferredLoadSucceeded 
= succeeded
; 
 884     IORecursiveLockUnlock(sKextLock
); 
 889 /********************************************************************* 
 890 * Called from IOSystemShutdownNotification. 
 891 *********************************************************************/ 
 894 OSKext::willShutdown(void) 
 896     OSReturn       checkResult 
= kOSReturnError
; 
 897     OSDictionary 
* exitRequest 
= NULL
;  // must release 
 899     IORecursiveLockLock(sKextLock
); 
 901     OSKext::setLoadEnabled(false); 
 902     OSKext::setUnloadEnabled(false); 
 903     OSKext::setAutounloadsEnabled(false); 
 904     OSKext::setKernelRequestsEnabled(false); 
 906     OSKextLog(/* kext */ NULL
, 
 907         kOSKextLogProgressLevel 
| 
 908         kOSKextLogGeneralFlag
, 
 909         "System shutdown; requesting immediate kextd exit."); 
 911     checkResult 
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
, 
 913     if (checkResult 
!= kOSReturnSuccess
) { 
 916     if (!sKernelRequests
->setObject(exitRequest
)) { 
 923     IORecursiveLockUnlock(sKextLock
); 
 925     OSSafeRelease(exitRequest
); 
 929 /********************************************************************* 
 930 *********************************************************************/ 
 933 OSKext::getLoadEnabled(void) 
 937     IORecursiveLockLock(sKextLock
); 
 938     result 
= sLoadEnabled
; 
 939     IORecursiveLockUnlock(sKextLock
); 
 943 /********************************************************************* 
 944 *********************************************************************/ 
 947 OSKext::setLoadEnabled(bool flag
) 
 951     IORecursiveLockLock(sKextLock
); 
 952     result 
= sLoadEnabled
; 
 953     sLoadEnabled 
= (flag 
? true : false); 
 955     if (sLoadEnabled 
!= result
) { 
 956         OSKextLog(/* kext */ NULL
, 
 957             kOSKextLogBasicLevel 
| 
 959             "Kext loading now %sabled.", sLoadEnabled 
? "en" : "dis"); 
 962     IORecursiveLockUnlock(sKextLock
); 
 967 /********************************************************************* 
 968 *********************************************************************/ 
 971 OSKext::getUnloadEnabled(void) 
 975     IORecursiveLockLock(sKextLock
); 
 976     result 
= sUnloadEnabled
; 
 977     IORecursiveLockUnlock(sKextLock
); 
 981 /********************************************************************* 
 982 *********************************************************************/ 
 985 OSKext::setUnloadEnabled(bool flag
) 
 989     IORecursiveLockLock(sKextLock
); 
 990     result 
= sUnloadEnabled
; 
 991     sUnloadEnabled 
= (flag 
? true : false); 
 992     IORecursiveLockUnlock(sKextLock
); 
 994     if (sUnloadEnabled 
!= result
) { 
 995         OSKextLog(/* kext */ NULL
, 
 996             kOSKextLogBasicLevel 
| 
 997             kOSKextLogGeneralFlag 
| kOSKextLogLoadFlag
, 
 998             "Kext unloading now %sabled.", sUnloadEnabled 
? "en" : "dis"); 
1004 /********************************************************************* 
1005 * Do not call any function that takes sKextLock here! 
1006 *********************************************************************/ 
1009 OSKext::getAutounloadEnabled(void) 
1013     IORecursiveLockLock(sKextInnerLock
); 
1014     result 
= sAutounloadEnabled 
? true : false; 
1015     IORecursiveLockUnlock(sKextInnerLock
); 
1019 /********************************************************************* 
1020 * Do not call any function that takes sKextLock here! 
1021 *********************************************************************/ 
1024 OSKext::setAutounloadsEnabled(bool flag
) 
1028     IORecursiveLockLock(sKextInnerLock
); 
1030     result 
= sAutounloadEnabled
; 
1031     sAutounloadEnabled 
= (flag 
? true : false); 
1032     if (!sAutounloadEnabled 
&& sUnloadCallout
) { 
1033         thread_call_cancel(sUnloadCallout
); 
1036     if (sAutounloadEnabled 
!= result
) { 
1037         OSKextLog(/* kext */ NULL
, 
1038             kOSKextLogBasicLevel 
| 
1039             kOSKextLogGeneralFlag 
| kOSKextLogLoadFlag
, 
1040             "Kext autounloading now %sabled.", 
1041             sAutounloadEnabled 
? "en" : "dis"); 
1044     IORecursiveLockUnlock(sKextInnerLock
); 
1049 /********************************************************************* 
1050 *********************************************************************/ 
1051 /* instance method operating on OSKext field */ 
1053 OSKext::setAutounloadEnabled(bool flag
) 
1055     bool result 
= flags
.autounloadEnabled 
? true : false; 
1056     flags
.autounloadEnabled 
= flag 
? 1 : 0; 
1058     if (result 
!= (flag 
? true : false)) { 
1060             kOSKextLogProgressLevel 
| 
1061             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
1062             "Autounloading for kext %s now %sabled.", 
1063             getIdentifierCString(), 
1064             flags
.autounloadEnabled 
? "en" : "dis"); 
1069 /********************************************************************* 
1070 *********************************************************************/ 
1073 OSKext::setKernelRequestsEnabled(bool flag
) 
1077     IORecursiveLockLock(sKextLock
); 
1078     result 
= sKernelRequestsEnabled
; 
1079     sKernelRequestsEnabled 
= flag 
? true : false; 
1081     if (sKernelRequestsEnabled 
!= result
) { 
1082         OSKextLog(/* kext */ NULL
, 
1083             kOSKextLogBasicLevel 
| 
1084             kOSKextLogGeneralFlag
, 
1085             "Kernel requests now %sabled.", 
1086             sKernelRequestsEnabled 
? "en" : "dis"); 
1088     IORecursiveLockUnlock(sKextLock
); 
1092 /********************************************************************* 
1093 *********************************************************************/ 
1096 OSKext::getKernelRequestsEnabled(void) 
1100     IORecursiveLockLock(sKextLock
); 
1101     result 
= sKernelRequestsEnabled
; 
1102     IORecursiveLockUnlock(sKextLock
); 
1107 #pragma mark Kext Life Cycle 
1109 /********************************************************************* 
1110 *********************************************************************/ 
1112 OSKext::withPrelinkedInfoDict( 
1113     OSDictionary 
* anInfoDict
) 
1115     OSKext 
* newKext 
= new OSKext
; 
1117     if (newKext 
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
)) { 
1125 /********************************************************************* 
1126 *********************************************************************/ 
1128 OSKext::initWithPrelinkedInfoDict( 
1129     OSDictionary 
* anInfoDict
) 
1131     bool            result              
= false; 
1132     kern_return_t   alloc_result        
= KERN_SUCCESS
; 
1133     OSString      
* kextPath            
= NULL
;  // do not release 
1134     OSNumber      
* addressNum          
= NULL
;  // reused; do not release 
1135     OSNumber      
* lengthNum           
= NULL
;  // reused; do not release 
1136     void          * data                
= NULL
;  // do not free 
1137     void          * srcData             
= NULL
;  // do not free 
1138     OSData        
* prelinkedExecutable 
= NULL
;  // must release 
1139     void          * linkStateCopy       
= NULL
;  // kmem_free on error 
1140     uint32_t        linkStateLength     
= 0; 
1141     uint32_t        length              
= 0;     // reused 
1143     if (!super::init()) { 
1147    /* Get the path. Don't look for an arch-specific path property. 
1149     kextPath 
= OSDynamicCast(OSString
, 
1150         anInfoDict
->getObject(kPrelinkBundlePathKey
)); 
1152     if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) { 
1156    /* Don't need the path to be in the info dictionary any more. 
1158     anInfoDict
->removeObject(kPrelinkBundlePathKey
); 
1160    /* If we have a link state, create an OSData wrapper for it. 
1162     addressNum 
= OSDynamicCast(OSNumber
, 
1163         anInfoDict
->getObject(kPrelinkLinkStateKey
)); 
1165         lengthNum 
= OSDynamicCast(OSNumber
,  
1166             anInfoDict
->getObject(kPrelinkLinkStateSizeKey
)); 
1169                 kOSKextLogErrorLevel 
| 
1170                 kOSKextLogArchiveFlag
, 
1171                 "Kext %s can't find prelinked kext link state size.", 
1172                 getIdentifierCString()); 
1176         data 
= (void *) (intptr_t) (addressNum
->unsigned64BitValue()); 
1177         linkStateLength 
= (uint32_t) (lengthNum
->unsigned32BitValue()); 
1179         anInfoDict
->removeObject(kPrelinkLinkStateKey
); 
1180         anInfoDict
->removeObject(kPrelinkLinkStateSizeKey
); 
1182        /* Copy the link state out of the booter-provided memory so it is in 
1183         * the VM system and we can page it out. 
1185         alloc_result 
= kmem_alloc_pageable(kernel_map
, 
1186             (vm_offset_t 
*)&linkStateCopy
, linkStateLength
); 
1187         if (alloc_result 
!= KERN_SUCCESS
) { 
1189                 kOSKextLogErrorLevel 
| 
1190                 kOSKextLogArchiveFlag
, 
1191                 "Kext %s failed to copy prelinked link state.", 
1192                 getIdentifierCString()); 
1195         memcpy(linkStateCopy
, data
, linkStateLength
); 
1197         linkState 
= OSData::withBytesNoCopy(linkStateCopy
, linkStateLength
); 
1200                 kOSKextLogErrorLevel 
| 
1201                 kOSKextLogArchiveFlag
, 
1202                 "Kext %s failed to create link state wrapper.", 
1203                 getIdentifierCString()); 
1206         linkState
->setDeallocFunction(osdata_kmem_free
); 
1208        /* Clear linkStateCopy; the OSData owns it now so we mustn't free it. 
1210         linkStateCopy 
= NULL
; 
1213    /* Create an OSData wrapper around the linked executable. 
1215     addressNum 
= OSDynamicCast(OSNumber
, 
1216         anInfoDict
->getObject(kPrelinkExecutableLoadKey
)); 
1218         lengthNum 
= OSDynamicCast(OSNumber
, 
1219             anInfoDict
->getObject(kPrelinkExecutableSizeKey
)); 
1222                 kOSKextLogErrorLevel 
| 
1223                 kOSKextLogArchiveFlag
, 
1224                 "Kext %s can't find prelinked kext executable size.", 
1225                 getIdentifierCString()); 
1229         data 
= (void *) (intptr_t) (addressNum
->unsigned64BitValue()); 
1230         length 
= (uint32_t) (lengthNum
->unsigned32BitValue()); 
1232         anInfoDict
->removeObject(kPrelinkExecutableLoadKey
); 
1233         anInfoDict
->removeObject(kPrelinkExecutableSizeKey
); 
1235        /* If the kext's load address differs from its source address, allocate 
1236         * space in the kext map at the load address and copy the kext over. 
1238         addressNum 
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
)); 
1240             srcData 
= (void *) (intptr_t) (addressNum
->unsigned64BitValue()); 
1242             if (data 
!= srcData
) { 
1244                 alloc_result 
= kext_alloc((vm_offset_t 
*)&data
, length
, /* fixed */ TRUE
); 
1245                 if (alloc_result 
!= KERN_SUCCESS
) { 
1247                         kOSKextLogErrorLevel 
| kOSKextLogGeneralFlag
, 
1248                         "Failed to allocate space for prelinked kext %s.", 
1249                         getIdentifierCString()); 
1252                 memcpy(data
, srcData
, length
); 
1255                     kOSKextLogErrorLevel 
| kOSKextLogGeneralFlag
, 
1256                     "Error: prelinked kext %s - source and load addresses " 
1257                     "differ on ILP32 architecture.", 
1258                     getIdentifierCString()); 
1260 #endif /* __LP64__ */ 
1263             anInfoDict
->removeObject(kPrelinkExecutableSourceKey
); 
1266        /* We don't need to set a dealloc function for the linked executable 
1267         * because it is freed separately in OSKext::unload(), which must unwire 
1268         * part of the memory. 
1269         * xxx - do we *have* to do it that way? 
1271         prelinkedExecutable 
= OSData::withBytesNoCopy(data
, length
); 
1272         if (!prelinkedExecutable
) { 
1274                 kOSKextLogErrorLevel 
| 
1275                 kOSKextLogGeneralFlag 
| kOSKextLogArchiveFlag
, 
1276                 "Kext %s failed to create executable wrapper.", 
1277                 getIdentifierCString()); 
1280         setLinkedExecutable(prelinkedExecutable
); 
1282         addressNum 
= OSDynamicCast(OSNumber
, 
1283             anInfoDict
->getObject(kPrelinkKmodInfoKey
)); 
1286                 kOSKextLogErrorLevel 
| 
1287                 kOSKextLogArchiveFlag
,  
1288                 "Kext %s can't find prelinked kext kmod_info address.", 
1289                 getIdentifierCString()); 
1293         kmod_info 
= (kmod_info_t 
*) (intptr_t) (addressNum
->unsigned64BitValue()); 
1295         anInfoDict
->removeObject(kPrelinkKmodInfoKey
); 
1298    /* If the plist has a UUID for an interface, save that off. 
1300     if (isInterface()) { 
1301         interfaceUUID 
= OSDynamicCast(OSData
, 
1302             anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
)); 
1303         if (interfaceUUID
) { 
1304             interfaceUUID
->retain(); 
1305             anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
); 
1309     flags
.prelinked 
= true; 
1311    /* If we created a kext from prelink info, 
1312     * we must be booting from a prelinked kernel. 
1314     sPrelinkBoot 
= true; 
1316     result 
= registerIdentifier(); 
1320    /* If we didn't hand linkStateCopy off to an OSData, free it. 
1322     if (linkStateCopy
) { 
1323         kmem_free(kernel_map
, (vm_offset_t
)linkStateCopy
, linkStateLength
); 
1326     OSSafeRelease(prelinkedExecutable
); 
1331 /********************************************************************* 
1332 *********************************************************************/ 
1334 OSKext::withBooterData( 
1335     OSString 
* deviceTreeName
, 
1336     OSData   
* booterData
) 
1338     OSKext 
* newKext 
= new OSKext
; 
1340     if (newKext 
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) { 
1348 /********************************************************************* 
1349 *********************************************************************/ 
1350 typedef struct _BooterKextFileInfo 
{ 
1351     uint32_t  infoDictPhysAddr
; 
1352     uint32_t  infoDictLength
; 
1353     uint32_t  executablePhysAddr
; 
1354     uint32_t  executableLength
; 
1355     uint32_t  bundlePathPhysAddr
; 
1356     uint32_t  bundlePathLength
; 
1357 } _BooterKextFileInfo
; 
1360 OSKext::initWithBooterData( 
1361     OSString 
* deviceTreeName
, 
1362     OSData   
* booterData
) 
1364     bool                  result         
= false; 
1365     _BooterKextFileInfo 
* kextFileInfo   
= NULL
;  // do not free 
1366     char                * infoDictAddr   
= NULL
;  // do not free 
1367     void                * executableAddr 
= NULL
;  // do not free 
1368     char                * bundlePathAddr 
= NULL
;  // do not free 
1370     OSObject            
* parsedXML 
= NULL
;  // must release 
1371     OSDictionary        
* theInfoDict    
= NULL
;  // do not release 
1372     OSString            
* kextPath       
= NULL
;  // must release 
1373     OSString            
* errorString    
= NULL
;  // must release 
1374     OSData              
* executable     
= NULL
;  // must release 
1376     if (!super::init()) { 
1380     kextFileInfo 
= (_BooterKextFileInfo 
*)booterData
->getBytesNoCopy(); 
1381     if (!kextFileInfo
) { 
1383             kOSKextLogErrorLevel 
| 
1384             kOSKextLogGeneralFlag
,  
1385             "No booter-provided data for kext device tree entry %s.", 
1386             deviceTreeName
->getCStringNoCopy()); 
1390    /* The info plist must exist or we can't read the kext. 
1392     if (!kextFileInfo
->infoDictPhysAddr 
|| !kextFileInfo
->infoDictLength
) { 
1394             kOSKextLogErrorLevel 
| 
1395             kOSKextLogGeneralFlag
,  
1396             "No kext info dictionary for booter device tree entry %s.", 
1397             deviceTreeName
->getCStringNoCopy()); 
1401     infoDictAddr 
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
); 
1402     if (!infoDictAddr
) { 
1404             kOSKextLogErrorLevel 
| 
1405             kOSKextLogGeneralFlag
,  
1406             "Can't translate physical address 0x%x of kext info dictionary " 
1407             "for device tree entry %s.", 
1408             (int)kextFileInfo
->infoDictPhysAddr
, 
1409             deviceTreeName
->getCStringNoCopy()); 
1413     parsedXML 
= OSUnserializeXML(infoDictAddr
, &errorString
); 
1415         theInfoDict 
= OSDynamicCast(OSDictionary
, parsedXML
); 
1418         const char * errorCString 
= "(unknown error)"; 
1420         if (errorString 
&& errorString
->getCStringNoCopy()) { 
1421             errorCString 
= errorString
->getCStringNoCopy(); 
1422         } else if (parsedXML
) { 
1423             errorCString 
= "not a dictionary"; 
1426             kOSKextLogErrorLevel 
| 
1427             kOSKextLogGeneralFlag
,  
1428             "Error unserializing info dictionary for device tree entry %s: %s.", 
1429             deviceTreeName
->getCStringNoCopy(), errorCString
); 
1433    /* A bundle path is not mandatory. 
1435     if (kextFileInfo
->bundlePathPhysAddr 
&& kextFileInfo
->bundlePathLength
) { 
1436         bundlePathAddr 
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
); 
1437         if (!bundlePathAddr
) { 
1439                 kOSKextLogErrorLevel 
| 
1440                 kOSKextLogGeneralFlag
,  
1441                 "Can't translate physical address 0x%x of kext bundle path " 
1442                 "for device tree entry %s.", 
1443                 (int)kextFileInfo
->bundlePathPhysAddr
, 
1444                 deviceTreeName
->getCStringNoCopy()); 
1447         bundlePathAddr
[kextFileInfo
->bundlePathLength
-1] = '\0'; // just in case! 
1449         kextPath 
= OSString::withCString(bundlePathAddr
); 
1452                 kOSKextLogErrorLevel 
| 
1453                 kOSKextLogGeneralFlag
,  
1454                 "Failed to create wrapper for device tree entry %s kext path %s.", 
1455                 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
); 
1460     if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) { 
1464    /* An executable is not mandatory. 
1466     if (kextFileInfo
->executablePhysAddr 
&& kextFileInfo
->executableLength
) { 
1467         executableAddr 
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
); 
1468         if (!executableAddr
) { 
1470                 kOSKextLogErrorLevel 
| 
1471                 kOSKextLogGeneralFlag
,  
1472                 "Can't translate physical address 0x%x of kext executable " 
1473                 "for device tree entry %s.", 
1474                 (int)kextFileInfo
->executablePhysAddr
, 
1475                 deviceTreeName
->getCStringNoCopy()); 
1479         executable 
= OSData::withBytesNoCopy(executableAddr
, 
1480             kextFileInfo
->executableLength
); 
1483                 kOSKextLogErrorLevel 
| 
1484                 kOSKextLogGeneralFlag
,  
1485                 "Failed to create executable wrapper for device tree entry %s.", 
1486                 deviceTreeName
->getCStringNoCopy()); 
1490        /* A kext with an executable needs to retain the whole booterData 
1491         * object to keep the executable in memory. 
1493         if (!setExecutable(executable
, booterData
)) { 
1495                 kOSKextLogErrorLevel 
| 
1496                 kOSKextLogGeneralFlag
,  
1497                 "Failed to set kext executable for device tree entry %s.", 
1498                 deviceTreeName
->getCStringNoCopy()); 
1503     result 
= registerIdentifier(); 
1506     OSSafeRelease(parsedXML
); 
1507     OSSafeRelease(kextPath
); 
1508     OSSafeRelease(errorString
); 
1509     OSSafeRelease(executable
); 
1514 /********************************************************************* 
1515 *********************************************************************/ 
1517 OSKext::registerIdentifier(void) 
1519     bool            result              
= false; 
1520     OSKext        
* existingKext        
= NULL
;  // do not release 
1521     bool            existingIsLoaded    
= false; 
1522     bool            existingIsPrelinked 
= false; 
1523     OSKextVersion   newVersion          
= -1; 
1524     OSKextVersion   existingVersion     
= -1; 
1525     char            newVersionCString
[kOSKextVersionMaxLength
]; 
1526     char            existingVersionCString
[kOSKextVersionMaxLength
]; 
1527     OSData        
* newUUID             
= NULL
;  // must release 
1528     OSData        
* existingUUID        
= NULL
;  // must release 
1530    /* Get the new kext's version for checks & log messages. 
1532     newVersion 
= getVersion(); 
1533     OSKextVersionGetString(newVersion
, newVersionCString
, 
1534         kOSKextVersionMaxLength
); 
1536    /* If we don't have an existing kext with this identifier, 
1537     * just record the new kext and we're done! 
1539     existingKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
)); 
1540     if (!existingKext
) { 
1541         sKextsByID
->setObject(bundleID
, this); 
1546    /* Get the existing kext's version for checks & log messages. 
1548     existingVersion 
= existingKext
->getVersion(); 
1549     OSKextVersionGetString(existingVersion
, 
1550         existingVersionCString
, kOSKextVersionMaxLength
); 
1552     existingIsLoaded 
= existingKext
->isLoaded(); 
1553     existingIsPrelinked 
= existingKext
->isPrelinked(); 
1555    /* If we have a kext with this identifier that's already loaded/prelinked, 
1556     * we can't use the new one, but let's be really thorough and check how 
1557     * the two are related for a precise diagnostic log message. 
1559     * Note that user space can't find out about nonloaded prelinked kexts, 
1560     * so in this case we log a message when new & existing are equivalent 
1561     * at the step rather than warning level, because we are always going 
1562     * be getting a copy of the kext in the user load request mkext. 
1564     if (existingIsLoaded 
|| existingIsPrelinked
) { 
1565         bool sameVersion 
= (newVersion 
== existingVersion
); 
1566         bool sameExecutable 
= true;  // assume true unless we have UUIDs 
1568        /* Only get the UUID if the existing kext is loaded. Doing so 
1569         * might have to uncompress an mkext executable and we shouldn't 
1570         * take that hit when neither kext is loaded. 
1572         newUUID 
= copyUUID(); 
1573         existingUUID 
= existingKext
->copyUUID(); 
1575        /* I'm entirely too paranoid about checking equivalence of executables, 
1576         * but I remember nasty problems with it in the past. 
1578         * - If we have UUIDs for both kexts, compare them. 
1579         * - If only one kext has a UUID, they're definitely different. 
1581         if (newUUID 
&& existingUUID
) { 
1582             sameExecutable 
= newUUID
->isEqualTo(existingUUID
); 
1583         } else if (newUUID 
|| existingUUID
) { 
1584             sameExecutable 
= false; 
1587         if (!newUUID 
&& !existingUUID
) { 
1589            /* If there are no UUIDs, we can't really tell that the executables 
1590             * are *different* without a lot of work; the loaded kext's 
1591             * unrelocated executable is no longer around (and we never had it 
1592             * in-kernel for a prelinked kext). We certainly don't want to do 
1593             * a whole fake link for the new kext just to compare, either. 
1596             OSKextVersionGetString(version
, newVersionCString
, 
1597                 sizeof(newVersionCString
)); 
1599                 kOSKextLogWarningLevel 
| 
1600                 kOSKextLogKextBookkeepingFlag
, 
1601                 "Notice - new kext %s, v%s matches %s kext " 
1602                 "but can't determine if executables are the same (no UUIDs).", 
1603                 getIdentifierCString(), 
1605                 (existingIsLoaded 
? "loaded" : "prelinked")); 
1608         if (sameVersion 
&& sameExecutable
) { 
1610                 (existingIsLoaded 
? kOSKextLogWarningLevel 
: kOSKextLogStepLevel
) | 
1611                 kOSKextLogKextBookkeepingFlag
, 
1612                 "Refusing new kext %s, v%s: a %s copy is already present " 
1613                 "(same version and executable).", 
1614                 getIdentifierCString(), newVersionCString
, 
1615                 (existingIsLoaded 
? "loaded" : "prelinked")); 
1618                /* This condition is significant so log it under warnings. 
1621                     kOSKextLogWarningLevel 
| 
1622                     kOSKextLogKextBookkeepingFlag
, 
1623                     "Refusing new kext %s, v%s: already have %s v%s.", 
1624                     getIdentifierCString(), 
1626                     (existingIsLoaded 
? "loaded" : "prelinked"), 
1627                     existingVersionCString
); 
1629                /* This condition is significant so log it under warnings. 
1632                     kOSKextLogWarningLevel 
| kOSKextLogKextBookkeepingFlag
, 
1633                     "Refusing new kext %s, v%s: a %s copy with a different " 
1634                     "executable UUID is already present.", 
1635                     getIdentifierCString(), newVersionCString
, 
1636                     (existingIsLoaded 
? "loaded" : "prelinked")); 
1640     } /* if (existingIsLoaded || existingIsPrelinked) */ 
1642    /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether 
1643     * user loads are happening or if we're still in early boot. User agents are 
1644     * supposed to resolve dependencies topside and include only the exact 
1645     * kexts needed; so we always accept the new kext (in fact we should never 
1646     * see an older unloaded copy hanging around). 
1648     if (sUserLoadsActive
) { 
1649         sKextsByID
->setObject(bundleID
, this); 
1653             kOSKextLogStepLevel 
| 
1654             kOSKextLogKextBookkeepingFlag
, 
1655             "Dropping old copy of kext %s (v%s) for newly-added (v%s).", 
1656             getIdentifierCString(), 
1657             existingVersionCString
, 
1663    /* During early boot, the kext with the highest version always wins out. 
1664     * Prelinked kernels will never hit this, but mkexts and booter-read 
1665     * kexts might have duplicates. 
1667     if (newVersion 
> existingVersion
) { 
1668         sKextsByID
->setObject(bundleID
, this); 
1672             kOSKextLogStepLevel 
| 
1673             kOSKextLogKextBookkeepingFlag
, 
1674             "Dropping lower version (v%s) of registered kext %s for higher (v%s).", 
1675             existingVersionCString
, 
1676             getIdentifierCString(), 
1681             kOSKextLogStepLevel 
| 
1682             kOSKextLogKextBookkeepingFlag
, 
1683             "Kext %s is already registered with a higher/same version (v%s); " 
1684             "dropping newly-added (v%s).", 
1685             getIdentifierCString(), 
1686             existingVersionCString
, 
1690    /* result has been set appropriately by now. */ 
1696             kOSKextLogStepLevel 
| 
1697             kOSKextLogKextBookkeepingFlag
, 
1698             "Kext %s, v%s registered and available for loading.", 
1699             getIdentifierCString(), newVersionCString
); 
1702     OSSafeRelease(newUUID
); 
1703     OSSafeRelease(existingUUID
); 
1708 /********************************************************************* 
1709 * Does the bare minimum validation to look up a kext. 
1710 * All other validation is done on the spot as needed. 
1712 * No need for lock, only called from init 
1713 **********************************************************************/ 
1715 OSKext::setInfoDictionaryAndPath( 
1716     OSDictionary 
* aDictionary
, 
1719     bool          result                   
= false; 
1720     OSString    
* bundleIDString           
= NULL
;  // do not release 
1721     OSString    
* versionString            
= NULL
;  // do not release 
1722     OSString    
* compatibleVersionString  
= NULL
;  // do not release 
1723     const char  * versionCString           
= NULL
;  // do not free 
1724     const char  * compatibleVersionCString 
= NULL
;  // do not free 
1725     OSBoolean   
* scratchBool              
= NULL
;  // do not release 
1728         panic("Attempt to set info dictionary on a kext " 
1729             "that already has one (%s).", 
1730             getIdentifierCString()); 
1733     if (!aDictionary 
|| !OSDynamicCast(OSDictionary
, aDictionary
)) { 
1737     infoDict 
= aDictionary
; 
1740    /* Check right away if the info dictionary has any log flags. 
1742     scratchBool 
= OSDynamicCast(OSBoolean
, 
1743         getPropertyForHostArch(kOSBundleEnableKextLoggingKey
)); 
1744     if (scratchBool 
== kOSBooleanTrue
) { 
1745         flags
.loggingEnabled 
= 1; 
1748    /* The very next thing to get is the bundle identifier. Unlike 
1749     * in user space, a kext with no bundle identifier gets axed 
1752     bundleIDString 
= OSDynamicCast(OSString
, 
1753         getPropertyForHostArch(kCFBundleIdentifierKey
)); 
1754     if (!bundleIDString
) { 
1756             kOSKextLogErrorLevel 
| 
1757             kOSKextLogValidationFlag
, 
1758             "CFBundleIdentifier missing/invalid type in kext %s.", 
1759             aPath 
? aPath
->getCStringNoCopy() : "(unknown)"); 
1762     bundleID 
= OSSymbol::withString(bundleIDString
); 
1765             kOSKextLogErrorLevel 
| 
1766             kOSKextLogValidationFlag
, 
1767             "Can't copy bundle identifier as symbol for kext %s.", 
1768             bundleIDString
->getCStringNoCopy()); 
1772    /* Save the path if we got one (it should always be available but it's 
1773     * just something nice to have for bookkeeping). 
1781     * Minimal validation to initialize. We'll do other validation on the spot. 
1783     if (bundleID
->getLength() >= KMOD_MAX_NAME
) { 
1785             kOSKextLogErrorLevel 
| 
1786             kOSKextLogValidationFlag
, 
1787             "Kext %s error - CFBundleIdentifier over max length %d.", 
1788             getIdentifierCString(), KMOD_MAX_NAME 
- 1); 
1792     version 
= compatibleVersion 
= -1; 
1794     versionString 
= OSDynamicCast(OSString
, 
1795         getPropertyForHostArch(kCFBundleVersionKey
)); 
1796     if (!versionString
) { 
1798             kOSKextLogErrorLevel 
| 
1799             kOSKextLogValidationFlag
, 
1800             "Kext %s error - CFBundleVersion missing/invalid type.", 
1801             getIdentifierCString()); 
1804     versionCString 
= versionString
->getCStringNoCopy(); 
1805     version 
= OSKextParseVersionString(versionCString
); 
1808             kOSKextLogErrorLevel 
| 
1809             kOSKextLogValidationFlag
, 
1810             "Kext %s error - CFBundleVersion bad value '%s'.", 
1811             getIdentifierCString(), versionCString
); 
1815     compatibleVersion 
= -1;  // set to illegal value for kexts that don't have 
1817     compatibleVersionString 
= OSDynamicCast(OSString
, 
1818         getPropertyForHostArch(kOSBundleCompatibleVersionKey
)); 
1819     if (compatibleVersionString
) { 
1820         compatibleVersionCString 
= compatibleVersionString
->getCStringNoCopy(); 
1821         compatibleVersion 
= OSKextParseVersionString(compatibleVersionCString
); 
1822         if (compatibleVersion 
< 0) { 
1824                 kOSKextLogErrorLevel 
| 
1825                 kOSKextLogValidationFlag
, 
1826                 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.", 
1827                 getIdentifierCString(), compatibleVersionCString
); 
1831         if (compatibleVersion 
> version
) { 
1833                 kOSKextLogErrorLevel 
| 
1834                 kOSKextLogValidationFlag
, 
1835                 "Kext %s error - %s %s > %s %s (must be <=).", 
1836                 getIdentifierCString(), 
1837                 kOSBundleCompatibleVersionKey
, compatibleVersionCString
, 
1838                 kCFBundleVersionKey
,  versionCString
); 
1843    /* Set flags for later use if the infoDict gets flushed. We only 
1844     * check for true values, not false ones(!) 
1846     scratchBool 
= OSDynamicCast(OSBoolean
, 
1847         getPropertyForHostArch(kOSBundleIsInterfaceKey
)); 
1848     if (scratchBool 
&& scratchBool
->isTrue()) { 
1849         flags
.interface 
= 1; 
1852     scratchBool 
= OSDynamicCast(OSBoolean
, 
1853         getPropertyForHostArch(kOSKernelResourceKey
)); 
1854     if (scratchBool 
&& scratchBool
->isTrue()) { 
1855         flags
.kernelComponent 
= 1; 
1856         flags
.interface 
= 1;  // xxx - hm. the kernel itself isn't an interface... 
1859        /* A kernel component has one implicit dependency on the kernel. 
1861         flags
.hasAllDependencies 
= 1; 
1871 /********************************************************************* 
1872 * Not used for prelinked kernel boot as there is no unrelocated 
1874 *********************************************************************/ 
1876 OSKext::setExecutable( 
1877     OSData 
* anExecutable
, 
1878     OSData 
* externalData
, 
1879     bool     externalDataIsMkext
) 
1881     bool         result        
= false; 
1882     const char * executableKey 
= NULL
;  // do not free 
1884     if (!anExecutable
) { 
1885         infoDict
->removeObject(_kOSKextExecutableKey
); 
1886         infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
); 
1887         infoDict
->removeObject(_kOSKextExecutableExternalDataKey
); 
1892     if (infoDict
->getObject(_kOSKextExecutableKey
) || 
1893         infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) { 
1895         panic("Attempt to set an executable on a kext " 
1896             "that already has one (%s).", 
1897             getIdentifierCString()); 
1901     if (externalDataIsMkext
) { 
1902         executableKey 
= _kOSKextMkextExecutableReferenceKey
; 
1904         executableKey 
= _kOSKextExecutableKey
; 
1908         infoDict
->setObject(executableKey
, anExecutable
); 
1910             infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
); 
1920 /********************************************************************* 
1921 *********************************************************************/ 
1926         panic("Attempt to free loaded kext %s.", getIdentifierCString()); 
1929     OSSafeRelease(infoDict
); 
1930     OSSafeRelease(bundleID
); 
1931     OSSafeRelease(path
); 
1932     OSSafeRelease(dependencies
); 
1933     OSSafeRelease(linkState
); 
1934     OSSafeRelease(linkedExecutable
); 
1935     OSSafeRelease(metaClasses
); 
1936     OSSafeRelease(interfaceUUID
); 
1938     if (isInterface() && kmod_info
) { 
1939         kfree(kmod_info
, sizeof(kmod_info_t
)); 
1947 #pragma mark Mkext files 
1949 /********************************************************************* 
1950 *********************************************************************/ 
1952 OSKext::readMkextArchive(OSData 
* mkextData
, 
1953     uint32_t * checksumPtr
) 
1955     OSReturn       result       
= kOSKextReturnBadData
; 
1956     uint32_t       mkextLength  
= 0; 
1957     mkext_header 
* mkextHeader  
= 0;   // do not free 
1958     uint32_t       mkextVersion 
= 0; 
1960    /* Note default return of kOSKextReturnBadData above. 
1962     mkextLength 
= mkextData
->getLength(); 
1963     if (mkextLength 
< sizeof(mkext_basic_header
)) { 
1964         OSKextLog(/* kext */ NULL
, 
1965             kOSKextLogErrorLevel 
| 
1966             kOSKextLogArchiveFlag
, 
1967             "Mkext archive too small to be valid."); 
1971     mkextHeader 
= (mkext_header 
*)mkextData
->getBytesNoCopy(); 
1973     if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC 
|| 
1974         MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) { 
1975         OSKextLog(/* kext */ NULL
, 
1976             kOSKextLogErrorLevel 
| 
1977             kOSKextLogArchiveFlag
, 
1978             "Mkext archive has invalid magic or signature."); 
1982     if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) { 
1983         OSKextLog(/* kext */ NULL
, 
1984             kOSKextLogErrorLevel 
| 
1985             kOSKextLogArchiveFlag
, 
1986             "Mkext archive recorded length doesn't match actual file length."); 
1990     mkextVersion 
= MKEXT_GET_VERSION(mkextHeader
); 
1992     if (mkextVersion 
== MKEXT_VERS_2
) { 
1993         result 
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
); 
1994     } else if (mkextVersion 
== MKEXT_VERS_1
) { 
1995         result 
= OSKext::readMkext1Archive(mkextData
, checksumPtr
); 
1997         OSKextLog(/* kext */ NULL
, 
1998             kOSKextLogErrorLevel 
| 
1999             kOSKextLogArchiveFlag
, 
2000             "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
); 
2001         result 
= kOSKextReturnUnsupported
; 
2008 /********************************************************************* 
2009 * Assumes magic, signature, version, length have been checked. 
2011 * Doesn't do as much bounds-checking as it should, but we're dropping 
2012 * mkext1 support from the kernel for SnowLeopard soon. 
2014 * Should keep track of all kexts created so far, and if we hit a 
2015 * fatal error halfway through, remove those kexts. If we've dropped 
2016 * an older version that had already been read, whoops! Might want to 
2017 * add a level of buffering? 
2018 *********************************************************************/ 
2021 OSKext::readMkext1Archive( 
2023     uint32_t * checksumPtr
) 
2025     OSReturn        result              
= kOSReturnError
; 
2026     uint32_t        mkextLength
; 
2027     mkext1_header 
* mkextHeader         
= 0;  // do not free 
2028     void          * mkextEnd            
= 0;  // do not free 
2029     uint32_t        mkextVersion
; 
2030     uint8_t       * crc_address         
= 0; 
2032     uint32_t        numKexts            
= 0; 
2034     OSData        
* infoDictDataObject  
= NULL
;  // must release 
2035     OSObject      
* parsedXML      
= NULL
;  // must release 
2036     OSDictionary  
* infoDict            
= NULL
;  // do not release 
2037     OSString      
* errorString         
= NULL
;  // must release 
2038     OSData        
* mkextExecutableInfo 
= NULL
;  // must release 
2039     OSKext        
* theKext             
= NULL
;  // must release 
2041     mkextLength 
= mkextData
->getLength(); 
2042     mkextHeader 
= (mkext1_header 
*)mkextData
->getBytesNoCopy(); 
2043     mkextEnd 
= (char *)mkextHeader 
+ mkextLength
; 
2044     mkextVersion 
= OSSwapBigToHostInt32(mkextHeader
->version
); 
2046     crc_address 
= (u_int8_t 
*)&mkextHeader
->version
; 
2047     checksum 
= mkext_adler32(crc_address
, 
2048         (uintptr_t)mkextHeader 
+ 
2049         OSSwapBigToHostInt32(mkextHeader
->length
) - (uintptr_t)crc_address
); 
2051     if (OSSwapBigToHostInt32(mkextHeader
->adler32
) != checksum
) { 
2052         OSKextLog(/* kext */ NULL
, 
2053             kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2054             "Kext archive has a bad checksum."); 
2055         result 
= kOSKextReturnBadData
; 
2060         *checksumPtr 
= checksum
; 
2063    /* Check that the CPU type & subtype match that of the running kernel. */ 
2064     if (OSSwapBigToHostInt32(mkextHeader
->cputype
) != (UInt32
)CPU_TYPE_ANY
) { 
2065         if ((UInt32
)_mh_execute_header
.cputype 
!= 
2066             OSSwapBigToHostInt32(mkextHeader
->cputype
)) { 
2068             OSKextLog(/* kext */ NULL
, 
2069                 kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2070                 "Kext archive doesn't contain software " 
2071                 "for this computer's CPU type."); 
2072             result 
= kOSKextReturnArchNotFound
; 
2077     numKexts 
= OSSwapBigToHostInt32(mkextHeader
->numkexts
); 
2079     for (uint32_t i 
= 0; i 
< numKexts
; i
++) { 
2081         OSSafeReleaseNULL(infoDictDataObject
); 
2082         OSSafeReleaseNULL(infoDict
); 
2083         OSSafeReleaseNULL(mkextExecutableInfo
); 
2084         OSSafeReleaseNULL(errorString
); 
2085         OSSafeReleaseNULL(theKext
); 
2087         mkext_kext 
* kextEntry 
= &mkextHeader
->kext
[i
]; 
2088         mkext_file 
* infoDictPtr 
= &kextEntry
->plist
; 
2089         mkext_file 
* executablePtr 
= &kextEntry
->module; 
2090         if (kextEntry 
>= mkextEnd
) { 
2091             OSKextLog(/* kext */ NULL
, 
2092                 kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2093                 "Mkext file overrun."); 
2094             result 
= kOSKextReturnBadData
; 
2098        /* Note that we're pretty tolerant of errors in individual entries. 
2099         * As long as we can keep processing, we do. 
2101         infoDictDataObject 
= OSKext::extractMkext1Entry( 
2102             mkextHeader
, infoDictPtr
); 
2103         if (!infoDictDataObject
) { 
2104             OSKextLog(/* kext */ NULL
, 
2105                 kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2106                 "Can't uncompress info dictionary " 
2107                 "from mkext archive entry %d.", i
); 
2111         parsedXML 
= OSUnserializeXML( 
2112                 (const char *)infoDictDataObject
->getBytesNoCopy(), 
2115             infoDict 
= OSDynamicCast(OSDictionary
, parsedXML
); 
2118             const char * errorCString 
= "(unknown error)"; 
2120             if (errorString 
&& errorString
->getCStringNoCopy()) { 
2121                 errorCString 
= errorString
->getCStringNoCopy(); 
2122             } else if (parsedXML
) { 
2123                 errorCString 
= "not a dictionary"; 
2125             OSKextLog(/* kext */ NULL
, 
2126                 kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2127                 "Error: Can't read XML property list " 
2128                   "for mkext archive entry %d: %s.", i
, errorCString
); 
2132         theKext 
= new OSKext
; 
2134             OSKextLog(/* kext */ NULL
, 
2135                 kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2136                 "Kext allocation failure."); 
2141         * Prepare an entry to hold the mkext entry info for the 
2142         * compressed binary module, if there is one. If all four fields 
2143         * of the module entry are zero, there isn't one. 
2145         if ((OSSwapBigToHostInt32(executablePtr
->offset
) || 
2146             OSSwapBigToHostInt32(executablePtr
->compsize
) || 
2147             OSSwapBigToHostInt32(executablePtr
->realsize
) || 
2148             OSSwapBigToHostInt32(executablePtr
->modifiedsecs
))) { 
2150             MkextEntryRef entryRef
; 
2152             mkextExecutableInfo 
= OSData::withCapacity(sizeof(entryRef
)); 
2153             if (!mkextExecutableInfo
) { 
2154                 panic("Error: Couldn't allocate data object " 
2155                       "for mkext archive entry %d.\n", i
); 
2158             entryRef
.mkext 
= (mkext_basic_header 
*)mkextHeader
; 
2159             entryRef
.fileinfo 
= (uint8_t *)executablePtr
; 
2160             if (!mkextExecutableInfo
->appendBytes(&entryRef
, 
2161                 sizeof(entryRef
))) { 
2163                 OSKextLog(/* kext */ NULL
, 
2164                     kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2165                     "Couldn't record executable info " 
2166                     "for mkext archive entry %d.", i
); 
2167                 // we might hit a load error later but oh well 
2168                 // xxx - should probably remove theKext 
2174        /* Init can fail because of a data/runtime error, or because the 
2175         * kext is a dup. Either way, we don't care here. 
2177         if (!theKext
->initWithMkext1Info(infoDict
, mkextExecutableInfo
, 
2180             // theKext is released at the top of the loop or in the finish block 
2184        /* If we got even one kext out of the mkext archive, 
2185         * we have successfully read the archive, in that we 
2186         * have data references into its mapped memory. 
2188         result 
= kOSReturnSuccess
; 
2193     OSSafeRelease(infoDictDataObject
); 
2194     OSSafeRelease(parsedXML
); 
2195     OSSafeRelease(errorString
); 
2196     OSSafeRelease(mkextExecutableInfo
); 
2197     OSSafeRelease(theKext
); 
2202 /********************************************************************* 
2203 *********************************************************************/ 
2205 OSKext::initWithMkext1Info( 
2206     OSDictionary 
* anInfoDict
, 
2207     OSData       
* executableWrapper
, 
2210     bool result 
= false; 
2212     // mkext1 doesn't allow for path (might stuff in info dict) 
2213     if (!setInfoDictionaryAndPath(anInfoDict
, /* path */ NULL
)) { 
2217     if (!registerIdentifier()) { 
2221     if (!setExecutable(executableWrapper
, mkextData
, true)) { 
2229    /* If we can't init, remove the kext from the lookup dictionary. 
2230     * This is safe to call in init because there's an implicit retain. 
2233         OSKext::removeKext(this, /* removePersonalities? */ false); 
2239 /********************************************************************* 
2240 * xxx - this should take the input data length 
2241 *********************************************************************/ 
2244 OSKext::extractMkext1Entry( 
2245     const void  * mkextFileBase
, 
2248     OSData      
* result                 
= NULL
; 
2249     OSData      
* uncompressedData       
= NULL
;  // release on error 
2250     const char  * errmsg                 
= NULL
; 
2252     mkext_file  
* fileinfo
; 
2253     uint8_t     * uncompressedDataBuffer 
= 0; // do not free (panic on alloc. fail) 
2254     size_t        uncompressed_size      
= 0; 
2255     kern_return_t kern_result
; 
2257     fileinfo 
= (mkext_file 
*)entry
; 
2259     size_t offset 
= OSSwapBigToHostInt32(fileinfo
->offset
); 
2260     size_t compressed_size 
= OSSwapBigToHostInt32(fileinfo
->compsize
); 
2261     size_t expected_size 
= OSSwapBigToHostInt32(fileinfo
->realsize
); 
2263     // Add 1 for '\0' to terminate XML string (for plists) 
2264     // (we really should have the archive format include that). 
2265     size_t alloc_size 
= expected_size 
+ 1; 
2266     time_t modifiedsecs 
= OSSwapBigToHostInt32(fileinfo
->modifiedsecs
); 
2268    /* If these four fields are zero there's no file, but it's up to 
2269     * the calling context to decide if that's an error. 
2271     if (offset 
== 0 && compressed_size 
== 0 && 
2272         expected_size 
== 0 && modifiedsecs 
== 0) { 
2276     kern_result 
= kmem_alloc(kernel_map
, 
2277         (vm_offset_t 
*)&uncompressedDataBuffer
, 
2279     if (kern_result 
!= KERN_SUCCESS
) { 
2284     uncompressedData 
= OSData::withBytesNoCopy(uncompressedDataBuffer
, 
2286     if (uncompressedData 
== NULL
) { 
2287        /* No need to free uncompressedDataBuffer here, either. */ 
2291     uncompressedData
->setDeallocFunction(&osdata_kmem_free
); 
2293    /* Do the decompression if necessary. Note that even if the file isn't 
2294     * compressed, we want to make a copy so that we don't have the tie to 
2295     * the larger mkext file buffer any more. 
2296     * xxx - need to detect decompression overflow too 
2298     if (compressed_size 
!= 0) { 
2299         errmsg 
= "OSKext::uncompressMkext - " 
2300             "uncompressed file shorter than expected"; 
2301         uncompressed_size 
= decompress_lzss(uncompressedDataBuffer
, 
2303             ((uint8_t *)mkextFileBase
) + offset
, 
2305         if (uncompressed_size 
!= expected_size
) { 
2309         memcpy(uncompressedDataBuffer
, 
2310             ((uint8_t *)mkextFileBase
) + offset
, 
2314     // Add a terminating nul character in case the data is XML. 
2315     // (we really should have the archive format include that). 
2316     uncompressedDataBuffer
[expected_size
] = '\0'; 
2318     result 
= uncompressedData
; 
2323         OSKextLog(/* kext */ NULL
, 
2324             kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2327         if (uncompressedData
) { 
2328             uncompressedData
->release(); 
2334 /********************************************************************* 
2335 * Assumes magic, signature, version, length have been checked. 
2336 * xxx - need to add further bounds checking for each file entry 
2338 * Should keep track of all kexts created so far, and if we hit a 
2339 * fatal error halfway through, remove those kexts. If we've dropped 
2340 * an older version that had already been read, whoops! Might want to 
2341 * add a level of buffering? 
2342 *********************************************************************/ 
2345 OSKext::readMkext2Archive( 
2347     OSDictionary 
** mkextPlistOut
, 
2348     uint32_t      * checksumPtr
) 
2350     OSReturn        result                     
= kOSReturnError
; 
2351     uint32_t        mkextLength
; 
2352     mkext2_header 
* mkextHeader                
= NULL
;  // do not free 
2353     void          * mkextEnd                   
= NULL
;  // do not free 
2354     uint32_t        mkextVersion
; 
2355     uint8_t       * crc_address                
= NULL
; 
2357     uint32_t        mkextPlistOffset
; 
2358     uint32_t        mkextPlistCompressedSize
; 
2359     char          * mkextPlistEnd              
= NULL
;  // do not free 
2360     uint32_t        mkextPlistFullSize
; 
2361     OSString      
* errorString                
= NULL
;  // must release 
2362     OSData        
* mkextPlistUncompressedData 
= NULL
;  // must release 
2363     const char    * mkextPlistDataBuffer       
= NULL
;  // do not free 
2364     OSObject      
* parsedXML           
= NULL
;  // must release 
2365     OSDictionary  
* mkextPlist                 
= NULL
;  // do not release 
2366     OSArray       
* mkextInfoDictArray         
= NULL
;  // do not release 
2369     mkextLength 
= mkextData
->getLength(); 
2370     mkextHeader 
= (mkext2_header 
*)mkextData
->getBytesNoCopy(); 
2371     mkextEnd 
= (char *)mkextHeader 
+ mkextLength
; 
2372     mkextVersion 
= MKEXT_GET_VERSION(mkextHeader
); 
2374     crc_address 
= (u_int8_t 
*)&mkextHeader
->version
; 
2375     checksum 
= mkext_adler32(crc_address
, 
2376         (uintptr_t)mkextHeader 
+ 
2377         MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
); 
2379     if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) { 
2380         OSKextLog(/* kext */ NULL
, 
2381             kOSKextLogErrorLevel 
| 
2382             kOSKextLogArchiveFlag
, 
2383             "Mkext archive has bad checksum."); 
2384         result 
= kOSKextReturnBadData
; 
2389         *checksumPtr 
= checksum
; 
2392    /* Check that the CPU type & subtype match that of the running kernel. */ 
2393     if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) { 
2394         OSKextLog(/* kext */ NULL
, 
2395             kOSKextLogErrorLevel 
| 
2396             kOSKextLogArchiveFlag
, 
2397             "Mkext archive must have a specific CPU type."); 
2398         result 
= kOSKextReturnBadData
; 
2401         if ((UInt32
)_mh_execute_header
.cputype 
!= 
2402             MKEXT_GET_CPUTYPE(mkextHeader
)) { 
2404             OSKextLog(/* kext */ NULL
, 
2405                 kOSKextLogErrorLevel 
| 
2406                 kOSKextLogArchiveFlag
, 
2407                 "Mkext archive does not match the running kernel's CPU type."); 
2408             result 
= kOSKextReturnArchNotFound
; 
2413     mkextPlistOffset 
= MKEXT2_GET_PLIST(mkextHeader
); 
2414     mkextPlistCompressedSize 
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
); 
2415     mkextPlistEnd 
= (char *)mkextHeader 
+ mkextPlistOffset 
+ 
2416         mkextPlistCompressedSize
; 
2417     if (mkextPlistEnd 
> mkextEnd
) { 
2418         OSKextLog(/* kext */ NULL
, 
2419             kOSKextLogErrorLevel 
| 
2420             kOSKextLogArchiveFlag
, 
2421             "Mkext archive file overrun."); 
2422         result 
= kOSKextReturnBadData
; 
2425     mkextPlistFullSize 
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
); 
2426     if (mkextPlistCompressedSize
) { 
2427         mkextPlistUncompressedData 
= sKernelKext
->extractMkext2FileData( 
2428             (UInt8 
*)mkextHeader 
+ mkextPlistOffset
, 
2430             mkextPlistCompressedSize
, mkextPlistFullSize
); 
2431         if (!mkextPlistUncompressedData
) { 
2434         mkextPlistDataBuffer 
= (const char *) 
2435             mkextPlistUncompressedData
->getBytesNoCopy(); 
2437         mkextPlistDataBuffer 
= (const char *)mkextHeader 
+ mkextPlistOffset
; 
2440    /* IOCFSerialize added a nul byte to the end of the string. Very nice of it. 
2442     parsedXML 
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
); 
2444         mkextPlist 
= OSDynamicCast(OSDictionary
, parsedXML
); 
2447         const char * errorCString 
= "(unknown error)"; 
2449         if (errorString 
&& errorString
->getCStringNoCopy()) { 
2450             errorCString 
= errorString
->getCStringNoCopy(); 
2451         } else if (parsedXML
) { 
2452             errorCString 
= "not a dictionary"; 
2454         OSKextLog(/* kext */ NULL
, 
2455             kOSKextLogErrorLevel 
| 
2456             kOSKextLogArchiveFlag
, 
2457             "Error unserializing mkext plist: %s.", errorCString
); 
2461    /* If the caller needs the plist, hand it back and retain it. 
2462     * (This function releases it at the end.) 
2464     if (mkextPlistOut
) { 
2465         *mkextPlistOut 
= mkextPlist
; 
2466         (*mkextPlistOut
)->retain(); 
2469     mkextInfoDictArray 
= OSDynamicCast(OSArray
, 
2470         mkextPlist
->getObject(kMKEXTInfoDictionariesKey
)); 
2471     if (!mkextInfoDictArray
) { 
2472         OSKextLog(/* kext */ NULL
, 
2473             kOSKextLogErrorLevel 
| 
2474             kOSKextLogArchiveFlag
, 
2475             "Mkext archive contains no kext info dictionaries."); 
2479     count 
= mkextInfoDictArray
->getCount(); 
2480     for (i 
= 0; i 
< count
; i
++) { 
2481         OSDictionary 
* infoDict
; 
2484         infoDict 
= OSDynamicCast(OSDictionary
, 
2485             mkextInfoDictArray
->getObject(i
)); 
2487        /* Create the kext for the entry, then release it, because the 
2488         * kext system keeps them around until explicitly removed. 
2489         * Any creation/registration failures are already logged for us. 
2491         OSKext 
* newKext 
= OSKext::withMkext2Info(infoDict
, mkextData
); 
2492         OSSafeRelease(newKext
); 
2495    /* Even if we didn't keep any kexts from the mkext, we may have a load 
2496     * request to process, so we are successful (no errors occurred). 
2498     result 
= kOSReturnSuccess
; 
2502     OSSafeRelease(parsedXML
); 
2503     OSSafeRelease(mkextPlistUncompressedData
); 
2504     OSSafeRelease(errorString
); 
2509 /********************************************************************* 
2510 *********************************************************************/ 
2513 OSKext::withMkext2Info( 
2514     OSDictionary 
* anInfoDict
, 
2517     OSKext 
* newKext 
= new OSKext
; 
2519     if (newKext 
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) { 
2527 /********************************************************************* 
2528 *********************************************************************/ 
2530 OSKext::initWithMkext2Info( 
2531     OSDictionary 
* anInfoDict
, 
2534     bool                   result              
= false; 
2535     OSString             
* kextPath            
= NULL
;  // do not release 
2536     OSNumber             
* executableOffsetNum 
= NULL
;  // do not release 
2537     OSCollectionIterator 
* iterator            
= NULL
;  // must release 
2538     OSData               
* executable          
= NULL
;  // must release 
2540     if (!super::init()) { 
2544    /* Get the path. Don't look for an arch-specific path property. 
2546     kextPath 
= OSDynamicCast(OSString
, 
2547         anInfoDict
->getObject(kMKEXTBundlePathKey
)); 
2549     if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) { 
2553    /* Don't need the path to be in the info dictionary any more. 
2555     anInfoDict
->removeObject(kMKEXTBundlePathKey
); 
2557     executableOffsetNum 
= OSDynamicCast(OSNumber
, 
2558         infoDict
->getObject(kMKEXTExecutableKey
)); 
2559     if (executableOffsetNum
) { 
2560         executable 
= createMkext2FileEntry(mkextData
, 
2561             executableOffsetNum
, "executable"); 
2562         infoDict
->removeObject(kMKEXTExecutableKey
); 
2566         if (!setExecutable(executable
, mkextData
, true)) { 
2571     result 
= registerIdentifier(); 
2575     OSSafeRelease(executable
); 
2576     OSSafeRelease(iterator
); 
2580 /********************************************************************* 
2581 *********************************************************************/ 
2583 OSKext::createMkext2FileEntry( 
2585     OSNumber   
* offsetNum
, 
2588     OSData        
* result      
= NULL
; 
2589     MkextEntryRef   entryRef
; 
2590     uint8_t       * mkextBuffer 
= (uint8_t *)mkextData
->getBytesNoCopy(); 
2591     uint32_t        entryOffset 
= offsetNum
->unsigned32BitValue(); 
2593     result 
= OSData::withCapacity(sizeof(entryRef
)); 
2598     entryRef
.mkext 
= (mkext_basic_header 
*)mkextBuffer
; 
2599     entryRef
.fileinfo 
= mkextBuffer 
+ entryOffset
; 
2600     if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) { 
2601         OSSafeReleaseNULL(result
); 
2608             kOSKextLogErrorLevel 
| 
2609             kOSKextLogArchiveFlag
, 
2610             "Can't create wrapper for mkext file entry '%s' of kext %s.", 
2611             name
, getIdentifierCString()); 
2616 /********************************************************************* 
2617 *********************************************************************/ 
2619 static void * z_alloc(void *, u_int items
, u_int size
); 
2620 static void   z_free(void *, void *ptr
); 
2622 typedef struct z_mem 
{ 
2623     uint32_t alloc_size
; 
2628  * Space allocation and freeing routines for use by zlib routines. 
2631 z_alloc(void * notused __unused
, u_int num_items
, u_int size
) 
2633     void     * result 
= NULL
; 
2634     z_mem    
* zmem 
= NULL
; 
2635     uint32_t   total 
= num_items 
* size
; 
2636     uint32_t   allocSize 
=  total 
+ sizeof(zmem
); 
2638     zmem 
= (z_mem 
*)kalloc(allocSize
); 
2642     zmem
->alloc_size 
= allocSize
; 
2643     result 
= (void *)&(zmem
->data
); 
2649 z_free(void * notused __unused
, void * ptr
) 
2651     uint32_t * skipper 
= (uint32_t *)ptr 
- 1; 
2652     z_mem    
* zmem 
= (z_mem 
*)skipper
; 
2653     kfree((void *)zmem
, zmem
->alloc_size
); 
2659 OSKext::extractMkext2FileData( 
2662     uint32_t     compressedSize
, 
2665     OSData      
* result 
= NULL
; 
2667     OSData      
* uncompressedData 
= NULL
;   // release on error 
2669     uint8_t     * uncompressedDataBuffer 
= 0;    // do not free 
2670     unsigned long uncompressedSize
; 
2672     bool          zstream_inited 
= false; 
2675    /* If the file isn't compressed, we want to make a copy 
2676     * so that we don't have the tie to the larger mkext file buffer any more. 
2678     if (!compressedSize
) { 
2679         uncompressedData 
= OSData::withBytes(data
, fullSize
); 
2680         // xxx - no check for failure? 
2681         result 
= uncompressedData
; 
2685     if (KERN_SUCCESS 
!= kmem_alloc(kernel_map
, 
2686         (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
)) { 
2688        /* How's this for cheesy? The kernel is only asked to extract 
2689         * kext plists so we tailor the log messages. 
2691         if (this == sKernelKext
) { 
2693                 kOSKextLogErrorLevel 
| 
2694                 kOSKextLogArchiveFlag
, 
2695                 "Allocation failure extracting %s from mkext.", name
); 
2698                 kOSKextLogErrorLevel 
| 
2699                 kOSKextLogArchiveFlag
, 
2700                 "Allocation failure extracting %s from mkext for kext %s.", 
2701                 name
, getIdentifierCString()); 
2706     uncompressedData 
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
); 
2707     if (!uncompressedData
) { 
2708         if (this == sKernelKext
) { 
2710                 kOSKextLogErrorLevel 
| 
2711                 kOSKextLogArchiveFlag
, 
2712                 "Allocation failure extracting %s from mkext.", name
); 
2715                 kOSKextLogErrorLevel 
| 
2716                 kOSKextLogArchiveFlag
, 
2717                 "Allocation failure extracting %s from mkext for kext %s.", 
2718                 name
, getIdentifierCString()); 
2722     uncompressedData
->setDeallocFunction(&osdata_kmem_free
); 
2724     if (this == sKernelKext
) { 
2726             kOSKextLogDetailLevel 
| 
2727             kOSKextLogArchiveFlag
, 
2728             "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.", 
2729             name
, compressedSize
, fullSize
); 
2732             kOSKextLogDetailLevel 
| 
2733             kOSKextLogArchiveFlag
, 
2734             "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.", 
2735             getIdentifierCString(), name
, compressedSize
, fullSize
); 
2738     bzero(&zstream
, sizeof(zstream
)); 
2739     zstream
.next_in   
= (UInt8 
*)data
; 
2740     zstream
.avail_in  
= compressedSize
; 
2742     zstream
.next_out  
= uncompressedDataBuffer
; 
2743     zstream
.avail_out 
= fullSize
; 
2745     zstream
.zalloc    
= z_alloc
; 
2746     zstream
.zfree     
= z_free
; 
2748     zlib_result 
= inflateInit(&zstream
); 
2749     if (Z_OK 
!= zlib_result
) { 
2750         if (this == sKernelKext
) { 
2752                 kOSKextLogErrorLevel 
| 
2753                 kOSKextLogArchiveFlag
, 
2754                 "Mkext error; zlib inflateInit failed (%d) for %s.", 
2758                 kOSKextLogErrorLevel 
| 
2759                 kOSKextLogArchiveFlag
, 
2760                 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .", 
2761                 getIdentifierCString(), zlib_result
, name
); 
2765         zstream_inited 
= true; 
2768     zlib_result 
= inflate(&zstream
, Z_FINISH
); 
2770     if (zlib_result 
== Z_STREAM_END 
|| zlib_result 
== Z_OK
) { 
2771         uncompressedSize 
= zstream
.total_out
; 
2773         if (this == sKernelKext
) { 
2775                 kOSKextLogErrorLevel 
| 
2776                 kOSKextLogArchiveFlag
, 
2777                 "Mkext error; zlib inflate failed (%d) for %s.", 
2781                 kOSKextLogErrorLevel 
| 
2782                 kOSKextLogArchiveFlag
, 
2783                 "Kext %s - mkext error; zlib inflate failed (%d) for %s .", 
2784                 getIdentifierCString(), zlib_result
, name
); 
2788                 kOSKextLogErrorLevel 
| 
2789                 kOSKextLogArchiveFlag
, 
2790                 "zlib error: %s.", zstream
.msg
); 
2795     if (uncompressedSize 
!= fullSize
) { 
2796         if (this == sKernelKext
) { 
2798                 kOSKextLogErrorLevel 
| 
2799                 kOSKextLogArchiveFlag
, 
2800                 "Mkext error; zlib inflate discrepancy for %s, " 
2801                 "uncompressed size != original size.", name
); 
2804                 kOSKextLogErrorLevel 
| 
2805                 kOSKextLogArchiveFlag
, 
2806                 "Kext %s - mkext error; zlib inflate discrepancy for %s, " 
2807                 "uncompressed size != original size.", 
2808                 getIdentifierCString(), name
); 
2813     result 
= uncompressedData
; 
2816    /* Don't bother checking return, nothing we can do on fail. 
2818     if (zstream_inited
) inflateEnd(&zstream
); 
2821         OSSafeRelease(uncompressedData
); 
2827 /********************************************************************* 
2828 *********************************************************************/ 
2831 OSKext::loadFromMkext( 
2832     OSKextLogSpec   clientLogFilter
, 
2834     uint32_t        mkextBufferLength
, 
2836     uint32_t      * logInfoLengthOut
) 
2838     OSReturn         result                      
= kOSReturnError
; 
2839     OSReturn         tempResult                  
= kOSReturnError
; 
2841     OSData         
* mkextData                   
= NULL
;  // must release 
2842     OSDictionary   
* mkextPlist                  
= NULL
;  // must release 
2844     OSArray        
* logInfoArray                
= NULL
;  // must release 
2845     OSSerialize    
* serializer                  
= NULL
;  // must release 
2847     OSString       
* predicate                   
= NULL
;  // do not release 
2848     OSDictionary   
* requestArgs                 
= NULL
;  // do not release 
2850     OSString       
* kextIdentifier              
= NULL
;  // do not release 
2851     OSNumber       
* startKextExcludeNum         
= NULL
;  // do not release 
2852     OSNumber       
* startMatchingExcludeNum     
= NULL
;  // do not release 
2853     OSBoolean      
* delayAutounloadBool         
= NULL
;  // do not release 
2854     OSArray        
* personalityNames            
= NULL
;  // do not release 
2856    /* Default values for these two options: regular autounload behavior, 
2857     * load all kexts, send no personalities. 
2859     Boolean            delayAutounload           
= false; 
2860     OSKextExcludeLevel startKextExcludeLevel     
= kOSKextExcludeNone
; 
2861     OSKextExcludeLevel startMatchingExcludeLevel 
= kOSKextExcludeAll
; 
2863     IORecursiveLockLock(sKextLock
); 
2867         *logInfoLengthOut 
= 0; 
2870     OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut 
? true : false); 
2872     OSKextLog(/* kext */ NULL
, 
2873         kOSKextLogDebugLevel 
| 
2875         "Received kext load request from user space."); 
2877    /* Regardless of processing, the fact that we have gotten here means some 
2878     * user-space program is up and talking to us, so we'll switch our kext 
2879     * registration to reflect that. 
2881     if (!sUserLoadsActive
) { 
2882         OSKextLog(/* kext */ NULL
, 
2883             kOSKextLogProgressLevel 
| 
2884             kOSKextLogGeneralFlag 
| kOSKextLogLoadFlag
, 
2885             "Switching to late startup (user-space) kext loading policy."); 
2887         sUserLoadsActive 
= true; 
2890     if (!sLoadEnabled
) { 
2891         OSKextLog(/* kext */ NULL
, 
2892             kOSKextLogErrorLevel 
| 
2894             "Kext loading is disabled."); 
2895         result 
= kOSKextReturnDisabled
; 
2899    /* Note that we do not set a dealloc function on this OSData 
2900     * object! No references to it can remain after the loadFromMkext() 
2901     * call since we are in a MIG function, and will vm_deallocate() 
2904     mkextData 
= OSData::withBytesNoCopy(mkextBuffer
, 
2907         OSKextLog(/* kext */ NULL
, 
2908             kOSKextLogErrorLevel 
| 
2909             kOSKextLogLoadFlag 
| kOSKextLogIPCFlag
, 
2910             "Failed to create wrapper for kext load request."); 
2911         result 
= kOSKextReturnNoMemory
; 
2915     result 
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
); 
2916     if (result 
!= kOSReturnSuccess
) { 
2917         OSKextLog(/* kext */ NULL
, 
2918             kOSKextLogErrorLevel 
| 
2920             "Failed to read kext load request."); 
2924     predicate 
= _OSKextGetRequestPredicate(mkextPlist
); 
2925     if (!predicate 
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) { 
2926         OSKextLog(/* kext */ NULL
, 
2927             kOSKextLogErrorLevel 
| 
2929             "Received kext load request with no predicate; skipping."); 
2930         result 
= kOSKextReturnInvalidArgument
; 
2934     requestArgs 
= OSDynamicCast(OSDictionary
, 
2935         mkextPlist
->getObject(kKextRequestArgumentsKey
)); 
2936     if (!requestArgs 
|| !requestArgs
->getCount()) { 
2937         OSKextLog(/* kext */ NULL
, 
2938             kOSKextLogErrorLevel 
| 
2940             "Received kext load request with no arguments."); 
2941         result 
= kOSKextReturnInvalidArgument
; 
2945     kextIdentifier 
= OSDynamicCast(OSString
, 
2946         requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
)); 
2947     if (!kextIdentifier
) { 
2948         OSKextLog(/* kext */ NULL
, 
2949             kOSKextLogErrorLevel 
| 
2951             "Received kext load request with no kext identifier."); 
2952         result 
= kOSKextReturnInvalidArgument
; 
2956     startKextExcludeNum 
= OSDynamicCast(OSNumber
, 
2957         requestArgs
->getObject(kKextKextRequestArgumentStartExcludeKey
)); 
2958     startMatchingExcludeNum 
= OSDynamicCast(OSNumber
, 
2959         requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
)); 
2960     delayAutounloadBool 
= OSDynamicCast(OSBoolean
, 
2961         requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
)); 
2962     personalityNames 
= OSDynamicCast(OSArray
, 
2963         requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
)); 
2965     if (delayAutounloadBool
) { 
2966         delayAutounload 
= delayAutounloadBool
->getValue(); 
2968     if (startKextExcludeNum
) { 
2969         startKextExcludeLevel 
= startKextExcludeNum
->unsigned8BitValue(); 
2971     if (startMatchingExcludeNum
) { 
2972         startMatchingExcludeLevel 
= startMatchingExcludeNum
->unsigned8BitValue(); 
2975     OSKextLog(/* kext */ NULL
, 
2976         kOSKextLogProgressLevel 
| 
2978         "Received request from user space to load kext %s.", 
2979         kextIdentifier
->getCStringNoCopy()); 
2981    /* Load the kext, with no deferral, since this is a load from outside 
2983     * xxx - Would like a better way to handle the default values for the 
2984     * xxx - start/match opt args. 
2986     result 
= OSKext::loadKextWithIdentifier( 
2988         /* allowDefer */ false, 
2990         startKextExcludeLevel
, 
2991         startMatchingExcludeLevel
, 
2993     if (result 
!= kOSReturnSuccess
) { 
2996    /* If the load came down from kextd, it will shortly inform IOCatalogue 
2997     * for matching via a separate IOKit calldown. 
3002    /* Gather up the collected log messages for user space. Any 
3003     * error messages past this call will not make it up as log messages 
3004     * but will be in the system log. 
3006     logInfoArray 
= OSKext::clearUserSpaceLogFilter(); 
3008     if (logInfoArray 
&& logInfoOut 
&& logInfoLengthOut
) { 
3009         tempResult 
= OSKext::serializeLogInfo(logInfoArray
, 
3010             logInfoOut
, logInfoLengthOut
); 
3011         if (tempResult 
!= kOSReturnSuccess
) { 
3012             result 
= tempResult
; 
3016     OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false); 
3018    /* Note: mkextDataObject will have been retained by every kext w/an 
3019     * executable in it. That should all have been flushed out at the 
3020     * and of the load operation, but you never know.... 
3022     if (mkextData 
&& mkextData
->getRetainCount() > 1) { 
3023         OSKextLog(/* kext */ NULL
, 
3024             kOSKextLogErrorLevel 
| 
3025             kOSKextLogLoadFlag 
| kOSKextLogIPCFlag
, 
3026             "Kext load request buffer from user space still retained by a kext; " 
3027             "probable memory leak."); 
3030     IORecursiveLockUnlock(sKextLock
); 
3032     OSSafeRelease(mkextData
); 
3033     OSSafeRelease(mkextPlist
); 
3034     OSSafeRelease(serializer
); 
3035     OSSafeRelease(logInfoArray
); 
3040 /********************************************************************* 
3041 *********************************************************************/ 
3044 OSKext::serializeLogInfo( 
3045     OSArray   
* logInfoArray
, 
3047     uint32_t  * logInfoLengthOut
) 
3049     OSReturn        result      
= kOSReturnError
; 
3050     char          * buffer      
= NULL
; 
3051     kern_return_t   kmem_result 
= KERN_FAILURE
; 
3052     OSSerialize  
* serializer   
= NULL
;  // must release; reused 
3053     char         * logInfo            
= NULL
;  // returned by reference 
3054     uint32_t       logInfoLength      
= 0; 
3056     if (!logInfoArray 
|| !logInfoOut 
|| !logInfoLengthOut
) { 
3057         OSKextLog(/* kext */ NULL
, 
3058             kOSKextLogErrorLevel 
| 
3060             "Internal error; invalid arguments to OSKext::serializeLogInfo()."); 
3061        /* Bad programmer. */ 
3062         result 
= kOSKextReturnInvalidArgument
; 
3066     serializer 
= OSSerialize::withCapacity(0); 
3068         OSKextLog(/* kext */ NULL
, 
3069             kOSKextLogErrorLevel 
| 
3071             "Failed to create serializer on log info for request from user space."); 
3072        /* Incidental error; we're going to (try to) allow the request 
3073         * itself to succeed. */ 
3076     if (!logInfoArray
->serialize(serializer
)) { 
3077         OSKextLog(/* kext */ NULL
, 
3078             kOSKextLogErrorLevel 
| 
3080             "Failed to serialize log info for request from user space."); 
3081        /* Incidental error; we're going to (try to) allow the request 
3082         * itself to succeed. */ 
3084         logInfo 
= serializer
->text(); 
3085         logInfoLength 
= serializer
->getLength(); 
3087         kmem_result 
= kmem_alloc(kernel_map
, (vm_offset_t 
*)&buffer
, logInfoLength
); 
3088         if (kmem_result 
!= KERN_SUCCESS
) { 
3089             OSKextLog(/* kext */ NULL
, 
3090                 kOSKextLogErrorLevel 
| 
3092                 "Failed to copy log info for request from user space."); 
3093            /* Incidental error; we're going to (try to) allow the request 
3096             memcpy(buffer
, logInfo
, logInfoLength
); 
3097             *logInfoOut 
= buffer
; 
3098             *logInfoLengthOut 
= logInfoLength
; 
3102     result 
= kOSReturnSuccess
; 
3104     OSSafeRelease(serializer
); 
3109 #pragma mark Instance Management Methods 
3111 /********************************************************************* 
3112 *********************************************************************/ 
3114 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
) 
3116     OSKext 
* foundKext 
= NULL
; 
3118     IORecursiveLockLock(sKextLock
); 
3119     foundKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
)); 
3121         foundKext
->retain(); 
3123     IORecursiveLockUnlock(sKextLock
); 
3128 /********************************************************************* 
3129 *********************************************************************/ 
3131 OSKext::lookupKextWithIdentifier(OSString 
* kextIdentifier
) 
3133     return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy()); 
3136 /********************************************************************* 
3137 *********************************************************************/ 
3139 OSKext::lookupKextWithLoadTag(uint32_t aTag
) 
3141     OSKext 
* foundKext 
= NULL
;                 // returned 
3144     IORecursiveLockLock(sKextLock
); 
3146     count 
= sLoadedKexts
->getCount(); 
3147     for (i 
= 0; i 
< count
; i
++) { 
3148         OSKext 
* thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
3149         if (thisKext
->getLoadTag() == aTag
) { 
3150             foundKext 
= thisKext
; 
3151             foundKext
->retain(); 
3157     IORecursiveLockUnlock(sKextLock
); 
3162 /********************************************************************* 
3163 *********************************************************************/ 
3165 OSKext::lookupKextWithAddress(vm_address_t address
) 
3167     OSKext 
* foundKext 
= NULL
;                 // returned 
3170     IORecursiveLockLock(sKextLock
); 
3172     count 
= sLoadedKexts
->getCount(); 
3173     for (i 
= 0; i 
< count
; i
++) { 
3174         OSKext 
* thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
3175         if (thisKext
->linkedExecutable
) { 
3176             vm_address_t kext_start 
= 
3177                 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy(); 
3178             vm_address_t kext_end 
= kext_start 
+ 
3179                 thisKext
->linkedExecutable
->getLength(); 
3181             if ((kext_start 
<= address
) && (address 
< kext_end
)) { 
3182                 foundKext 
= thisKext
; 
3183                 foundKext
->retain(); 
3190     IORecursiveLockUnlock(sKextLock
); 
3195 /********************************************************************* 
3196 *********************************************************************/ 
3198 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
) 
3200     bool result 
= false; 
3201     OSKext 
* foundKext 
= NULL
;                 // returned 
3203     IORecursiveLockLock(sKextLock
); 
3205     foundKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
)); 
3206     if (foundKext 
&& foundKext
->isLoaded()) { 
3210     IORecursiveLockUnlock(sKextLock
); 
3215 /********************************************************************* 
3216 * xxx - should spawn a separate thread so a kext can safely have 
3217 * xxx - itself unloaded. 
3218 *********************************************************************/ 
3223     bool     terminateServicesAndRemovePersonalitiesFlag
) 
3225     OSReturn result    
= kOSKextReturnInUse
; 
3226     OSKext 
* checkKext 
= NULL
;   // do not release 
3228     IORecursiveLockLock(sKextLock
); 
3230    /* If the kext has no identifier, it failed to init 
3231     * so isn't in sKextsByID and it isn't loaded. 
3233     if (!aKext
->getIdentifier()) { 
3234         result 
= kOSReturnSuccess
; 
3238     checkKext 
= OSDynamicCast(OSKext
, 
3239         sKextsByID
->getObject(aKext
->getIdentifier())); 
3240     if (checkKext 
!= aKext
) { 
3241         result 
= kOSKextReturnNotFound
; 
3245     if (aKext
->isLoaded()) { 
3246        /* If we are terminating, send the request to the IOCatalogue 
3247         * (which will actually call us right back but that's ok we have 
3248         * a recursive lock don't you know) but do not ask the IOCatalogue 
3249         * to call back with an unload, we'll do that right here. 
3251         if (terminateServicesAndRemovePersonalitiesFlag
) { 
3252             result 
= gIOCatalogue
->terminateDriversForModule( 
3253                 aKext
->getIdentifierCString(), /* unload */ false); 
3254             if (result 
!= kOSReturnSuccess
) { 
3256                     kOSKextLogProgressLevel 
| 
3257                     kOSKextLogKextBookkeepingFlag
, 
3258                     "Can't remove kext %s; services failed to terminate - 0x%x.", 
3259                     aKext
->getIdentifierCString(), result
); 
3264         result 
= aKext
->unload(); 
3265         if (result 
!= kOSReturnSuccess
) { 
3270    /* Remove personalities as requested. This is a bit redundant for a loaded 
3271     * kext as IOCatalogue::terminateDriversForModule() removes driver 
3272     * personalities, but it doesn't restart matching, which we always want 
3273     * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures 
3276     if (terminateServicesAndRemovePersonalitiesFlag
) { 
3277         aKext
->removePersonalitiesFromCatalog(); 
3281         kOSKextLogProgressLevel 
| 
3282         kOSKextLogKextBookkeepingFlag
, 
3283         "Removing kext %s.", 
3284         aKext
->getIdentifierCString()); 
3286     sKextsByID
->removeObject(aKext
->getIdentifier()); 
3287     result 
= kOSReturnSuccess
; 
3290     IORecursiveLockUnlock(sKextLock
); 
3294 /********************************************************************* 
3295 *********************************************************************/ 
3298 OSKext::removeKextWithIdentifier( 
3299     const char * kextIdentifier
, 
3300     bool         terminateServicesAndRemovePersonalitiesFlag
) 
3302     OSReturn result 
= kOSReturnError
; 
3304     IORecursiveLockLock(sKextLock
); 
3306     OSKext 
* aKext 
= OSDynamicCast(OSKext
, 
3307         sKextsByID
->getObject(kextIdentifier
)); 
3309         result 
= kOSKextReturnNotFound
; 
3310         OSKextLog(/* kext */ NULL
, 
3311             kOSKextLogErrorLevel 
| 
3312             kOSKextLogKextBookkeepingFlag
, 
3313             "Can't remove kext %s - not found.", 
3318     result 
= OSKext::removeKext(aKext
, 
3319         terminateServicesAndRemovePersonalitiesFlag
); 
3322     IORecursiveLockUnlock(sKextLock
); 
3327 /********************************************************************* 
3328 *********************************************************************/ 
3331 OSKext::removeKextWithLoadTag( 
3332     OSKextLoadTag loadTag
, 
3333     bool          terminateServicesAndRemovePersonalitiesFlag
) 
3335     OSReturn result    
= kOSReturnError
; 
3336     OSKext 
* foundKext 
= NULL
; 
3339     IORecursiveLockLock(sKextLock
); 
3341     count 
= sLoadedKexts
->getCount(); 
3342     for (i 
= 0; i 
< count
; i
++) { 
3343         OSKext 
* thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
3344         if (thisKext
->loadTag 
== loadTag
) { 
3345             foundKext 
= thisKext
; 
3351         result 
= kOSKextReturnNotFound
; 
3352         OSKextLog(/* kext */ NULL
, 
3353             kOSKextLogErrorLevel 
| 
3354             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
3355             "Can't remove kext with load tag %d - not found.", 
3360     result 
= OSKext::removeKext(foundKext
, 
3361         terminateServicesAndRemovePersonalitiesFlag
); 
3364     IORecursiveLockUnlock(sKextLock
); 
3369 /********************************************************************* 
3370 *********************************************************************/ 
3372 OSKext::copyKexts(void) 
3374     OSDictionary 
* result
; 
3376     IORecursiveLockLock(sKextLock
); 
3377     result 
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection()); 
3378     IORecursiveLockUnlock(sKextLock
); 
3384 #pragma mark Accessors 
3386 /********************************************************************* 
3387 *********************************************************************/ 
3389 OSKext::getIdentifier(void) 
3394 /********************************************************************* 
3395 * A kext must have a bundle identifier to even survive initialization; 
3396 * this is guaranteed to exist past then. 
3397 *********************************************************************/ 
3399 OSKext::getIdentifierCString(void) 
3401     return bundleID
->getCStringNoCopy(); 
3404 /********************************************************************* 
3405 *********************************************************************/ 
3407 OSKext::getVersion(void) 
3412 /********************************************************************* 
3413 *********************************************************************/ 
3415 OSKext::getCompatibleVersion(void) 
3417     return compatibleVersion
; 
3420 /********************************************************************* 
3421 *********************************************************************/ 
3423 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
) 
3425     if ((compatibleVersion 
> -1 && version 
> -1) && 
3426         (compatibleVersion 
<= version 
&& aVersion 
<= version
)) { 
3432 /********************************************************************* 
3433 *********************************************************************/ 
3435 OSKext::declaresExecutable(void) 
3437     if (getPropertyForHostArch(kCFBundleExecutableKey
)) { 
3443 /********************************************************************* 
3444 *********************************************************************/ 
3446 OSKext::getExecutable(void) 
3448     OSData 
* result              
= NULL
; 
3449     OSData 
* extractedExecutable 
= NULL
;  // must release 
3450     OSData 
* mkextExecutableRef  
= NULL
;  // do not release 
3452     result 
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
)); 
3457     mkextExecutableRef 
= OSDynamicCast(OSData
, 
3458         getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
)); 
3460     if (mkextExecutableRef
) { 
3462         MkextEntryRef 
* mkextEntryRef 
= (MkextEntryRef 
*) 
3463             mkextExecutableRef
->getBytesNoCopy(); 
3464         uint32_t mkextVersion 
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
); 
3465         if (mkextVersion 
== MKEXT_VERS_2
) { 
3466             mkext2_file_entry 
* fileinfo 
= 
3467                 (mkext2_file_entry 
*)mkextEntryRef
->fileinfo
; 
3468             uint32_t compressedSize 
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
); 
3469             uint32_t fullSize 
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
); 
3470             extractedExecutable 
= extractMkext2FileData( 
3471                 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable", 
3472                 compressedSize
, fullSize
); 
3473         } else if (mkextVersion 
== MKEXT_VERS_1
) { 
3474             extractedExecutable 
= extractMkext1Entry( 
3475                 mkextEntryRef
->mkext
, mkextEntryRef
->fileinfo
); 
3477             OSKextLog(this, kOSKextLogErrorLevel 
| 
3478             kOSKextLogArchiveFlag
, 
3479                 "Kext %s - unknown mkext version 0x%x for executable.", 
3480                 getIdentifierCString(), mkextVersion
); 
3483        /* Regardless of success, remove the mkext executable, 
3484         * and drop one reference on the mkext.  (setExecutable() does not 
3485         * replace, it removes, or panics if asked to replace.) 
3487         infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
); 
3488         infoDict
->removeObject(_kOSKextExecutableExternalDataKey
); 
3490         if (extractedExecutable 
&& extractedExecutable
->getLength()) { 
3491             if (!setExecutable(extractedExecutable
)) { 
3494             result 
= extractedExecutable
; 
3502     OSSafeRelease(extractedExecutable
); 
3507 /********************************************************************* 
3508 *********************************************************************/ 
3510 OSKext::isInterface(void) 
3512     return flags
.interface
; 
3515 /********************************************************************* 
3516 *********************************************************************/ 
3518 OSKext::isKernelComponent(void) 
3520     return flags
.kernelComponent 
? true : false; 
3523 /********************************************************************* 
3524 * We might want to check this recursively for all dependencies, 
3525 * since a subtree of dependencies could get loaded before we hit 
3526 * a dependency that isn't safe-boot-loadable. 
3528 * xxx - Might want to return false if OSBundleEnableKextLogging or 
3529 * OSBundleDebugLevel 
3530 * or IOKitDebug is nonzero too (we used to do that, but I don't see 
3531 * the point except it's usually development drivers, which might 
3532 * cause panics on startup, that have those properties). Heh; could 
3533 * use a "kx" boot-arg! 
3534 *********************************************************************/ 
3536 OSKext::isLoadableInSafeBoot(void) 
3538     bool       result   
= false; 
3539     OSString 
* required 
= NULL
;  // do not release 
3542     required 
= OSDynamicCast(OSString
, 
3543         getPropertyForHostArch(kOSBundleRequiredKey
)); 
3547     if (required
->isEqualTo(kOSBundleRequiredRoot
)        || 
3548         required
->isEqualTo(kOSBundleRequiredLocalRoot
)   || 
3549         required
->isEqualTo(kOSBundleRequiredNetworkRoot
) || 
3550         required
->isEqualTo(kOSBundleRequiredSafeBoot
)    || 
3551         required
->isEqualTo(kOSBundleRequiredConsole
)) { 
3560 /********************************************************************* 
3561 *********************************************************************/ 
3563 OSKext::isPrelinked(void) 
3565     return flags
.prelinked 
? true : false; 
3568 /********************************************************************* 
3569 *********************************************************************/ 
3570 bool OSKext::isLoaded(void) 
3572     return flags
.loaded 
? true : false; 
3575 /********************************************************************* 
3576 *********************************************************************/ 
3578 OSKext::isStarted(void) 
3580     return flags
.started 
? true : false; 
3583 /********************************************************************* 
3584 *********************************************************************/ 
3586 OSKext::isCPPInitialized(void) 
3588     return flags
.CPPInitialized
; 
3591 /********************************************************************* 
3592 *********************************************************************/ 
3594 OSKext::setCPPInitialized(bool initialized
) 
3596     flags
.CPPInitialized 
= initialized
; 
3599 /********************************************************************* 
3600 *********************************************************************/ 
3602 OSKext::getLoadTag(void) 
3607 /********************************************************************* 
3608 *********************************************************************/ 
3610 OSKext::copyUUID(void) 
3612     OSData                     
* result        
= NULL
; 
3613     OSData                     
* theExecutable 
= NULL
;  // do not release 
3614     const kernel_mach_header_t 
* header        
= NULL
; 
3615     const struct load_command  
* load_cmd      
= NULL
; 
3616     const struct uuid_command  
* uuid_cmd      
= NULL
; 
3619    /* An interface kext doesn't have a linked executable with an LC_UUID, 
3620     * we create one when it's linked. 
3622     if (interfaceUUID
) { 
3623         result 
= interfaceUUID
; 
3628    /* For real kexts, try to get the UUID from the linked executable, 
3629     * or if is hasn't been linked yet, the unrelocated executable. 
3631     theExecutable 
= linkedExecutable
; 
3632     if (!theExecutable
) { 
3633         theExecutable 
= getExecutable(); 
3635     if (!theExecutable
) { 
3639     header 
= (const kernel_mach_header_t 
*)theExecutable
->getBytesNoCopy(); 
3640     load_cmd 
= (const struct load_command 
*)&header
[1]; 
3642     for (i 
= 0; i 
< header
->ncmds
; i
++) { 
3643         if (load_cmd
->cmd 
== LC_UUID
) { 
3644             uuid_cmd 
= (struct uuid_command 
*)load_cmd
; 
3645             result 
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
)); 
3648         load_cmd 
= (struct load_command 
*)((caddr_t
)load_cmd 
+ load_cmd
->cmdsize
); 
3655 /********************************************************************* 
3656 *********************************************************************/ 
3657 #if defined (__ppc__) 
3658 #define ARCHNAME "ppc" 
3659 #elif defined (__i386__) 
3660 #define ARCHNAME "i386" 
3661 #elif defined (__x86_64__) 
3662 #define ARCHNAME "x86_64" 
3664 #error architecture not supported 
3667 #define ARCH_SEPARATOR_CHAR  '_' 
3669 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
) 
3671     char     * result 
= NULL
; 
3672     uint32_t   keyLength 
= strlen(key
); 
3675    /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'. 
3677     keySize 
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
); 
3678     result 
= (char *)kalloc(keySize
); 
3682     strlcpy(result
, key
, keySize
); 
3683     result
[keyLength
++] = ARCH_SEPARATOR_CHAR
; 
3684     result
[keyLength
] = '\0'; 
3685     strlcat(result
, ARCHNAME
, keySize
); 
3686     *keySizeOut 
= keySize
; 
3692 /********************************************************************* 
3693 *********************************************************************/ 
3695 OSKext::getPropertyForHostArch(const char * key
) 
3697     OSObject 
* result           
= NULL
;  // do not release 
3698     uint32_t   hostArchKeySize  
= 0; 
3699     char     * hostArchKey      
= NULL
;  // must kfree 
3701     if (!key 
|| !infoDict
) { 
3705    /* Some properties are not allowed to be arch-variant: 
3706     * - Any CFBundle... property. 
3707     * - OSBundleIsInterface. 
3708     * - OSKernelResource. 
3710     if (STRING_HAS_PREFIX(key
, "OS") || 
3711         STRING_HAS_PREFIX(key
, "IO")) { 
3713         hostArchKey 
= makeHostArchKey(key
, &hostArchKeySize
); 
3715             OSKextLog(/* kext (this isn't about a kext) */ NULL
, 
3716                 kOSKextLogErrorLevel 
| kOSKextLogGeneralFlag
, 
3717                 "Allocation failure."); 
3720         result 
= infoDict
->getObject(hostArchKey
); 
3724         result 
= infoDict
->getObject(key
); 
3728     if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
); 
3733 #pragma mark Load/Start/Stop/Unload 
3735 /********************************************************************* 
3736 *********************************************************************/ 
3738 OSKext::loadKextWithIdentifier( 
3739     const char       * kextIdentifierCString
, 
3740     Boolean            allowDeferFlag
, 
3741     Boolean            delayAutounloadFlag
, 
3742     OSKextExcludeLevel startOpt
, 
3743     OSKextExcludeLevel startMatchingOpt
, 
3744     OSArray          
* personalityNames
) 
3746     OSReturn   result         
= kOSReturnError
; 
3747     OSString 
* kextIdentifier 
= NULL
;  // must release 
3749     kextIdentifier 
= OSString::withCString(kextIdentifierCString
); 
3750     if (!kextIdentifier
) { 
3751         result 
= kOSKextReturnNoMemory
; 
3754     result 
= OSKext::loadKextWithIdentifier(kextIdentifier
, 
3755         allowDeferFlag
, delayAutounloadFlag
, 
3756         startOpt
, startMatchingOpt
, personalityNames
); 
3759     OSSafeRelease(kextIdentifier
); 
3764 /********************************************************************* 
3765 *********************************************************************/ 
3767 OSKext::loadKextWithIdentifier( 
3768     OSString          
* kextIdentifier
, 
3769     Boolean             allowDeferFlag
, 
3770     Boolean             delayAutounloadFlag
, 
3771     OSKextExcludeLevel  startOpt
, 
3772     OSKextExcludeLevel  startMatchingOpt
, 
3773     OSArray           
* personalityNames
) 
3775     OSReturn          result               
= kOSReturnError
; 
3776     OSKext          
* theKext              
= NULL
;  // do not release 
3777     OSDictionary    
* loadRequest          
= NULL
;  // must release 
3778     const OSSymbol  
* kextIdentifierSymbol 
= NULL
;  // must release 
3780     IORecursiveLockLock(sKextLock
); 
3782     if (!kextIdentifier
) { 
3783         result 
= kOSKextReturnInvalidArgument
; 
3787     OSKext::recordIdentifierRequest(kextIdentifier
); 
3789     theKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
)); 
3791         if (!allowDeferFlag
) { 
3792             OSKextLog(/* kext */ NULL
, 
3793                 kOSKextLogErrorLevel 
| 
3795                 "Can't load kext %s - not found.", 
3796                 kextIdentifier
->getCStringNoCopy()); 
3800         if (!sKernelRequestsEnabled
) { 
3802                 kOSKextLogErrorLevel 
| 
3804                 "Can't load kext %s - requests to user space are disabled.", 
3805                 kextIdentifier
->getCStringNoCopy()); 
3806             result 
= kOSKextReturnDisabled
; 
3810        /* Create a new request unless one is already sitting 
3811         * in sKernelRequests for this bundle identifier 
3813         kextIdentifierSymbol 
= OSSymbol::withString(kextIdentifier
); 
3814         if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) { 
3815             result 
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
, 
3817             if (result 
!= kOSReturnSuccess
) { 
3820             if (!_OSKextSetRequestArgument(loadRequest
, 
3821                 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) { 
3823                 result 
= kOSKextReturnNoMemory
; 
3826             if (!sKernelRequests
->setObject(loadRequest
)) { 
3827                 result 
= kOSKextReturnNoMemory
; 
3831             if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) { 
3832                 result 
= kOSKextReturnNoMemory
; 
3837                 kOSKextLogDebugLevel 
| 
3839                 "Kext %s not found; queued load request to user space.", 
3840                 kextIdentifier
->getCStringNoCopy()); 
3846             OSKextLog(/* kext */ NULL
, 
3847                 ((sPrelinkBoot
) ? kOSKextLogDebugLevel 
: kOSKextLogErrorLevel
) | 
3849                 "Not loading kext %s - not found and kextd not available in early boot.", 
3850                 kextIdentifier
->getCStringNoCopy()); 
3853         result 
= kOSKextReturnDeferred
; 
3857     result 
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
); 
3859     if (result 
!= kOSReturnSuccess
) { 
3861             kOSKextLogErrorLevel 
| 
3863             "Failed to load kext %s (error 0x%x).", 
3864             kextIdentifier
->getCStringNoCopy(), (int)result
); 
3866         OSKext::removeKext(theKext
, 
3867             /* terminateService/removePersonalities */ true); 
3871     if (delayAutounloadFlag
) { 
3873             kOSKextLogProgressLevel 
| 
3874             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
3875             "Setting delayed autounload for %s.", 
3876             kextIdentifier
->getCStringNoCopy()); 
3877         theKext
->flags
.delayAutounload 
= 1; 
3881     OSSafeRelease(loadRequest
); 
3882     OSSafeRelease(kextIdentifierSymbol
); 
3884     IORecursiveLockUnlock(sKextLock
); 
3889 /********************************************************************* 
3890 *********************************************************************/ 
3893 OSKext::recordIdentifierRequest( 
3894     OSString 
* kextIdentifier
) 
3896     const OSSymbol 
* kextIdentifierSymbol 
= NULL
;  // must release 
3899     if (!sAllKextLoadIdentifiers 
|| !kextIdentifier
) { 
3903     kextIdentifierSymbol 
= OSSymbol::withString(kextIdentifier
); 
3904     if (!kextIdentifierSymbol
) { 
3905         // xxx - this is really a basic alloc failure 
3910     if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) { 
3911         if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) { 
3914             // xxx - need to find a way to associate this whole func w/the kext 
3915             OSKextLog(/* kext */ NULL
, 
3916                 // xxx - check level 
3917                 kOSKextLogStepLevel 
| 
3918                 kOSKextLogArchiveFlag
, 
3919                 "Recorded kext %s as a candidate for inclusion in prelinked kernel.", 
3920                 kextIdentifier
->getCStringNoCopy()); 
3926         OSKextLog(/* kext */ NULL
, 
3927             kOSKextLogErrorLevel 
| 
3928             kOSKextLogArchiveFlag
, 
3929             "Failed to record kext %s as a candidate for inclusion in prelinked kernel.", 
3930             kextIdentifier
->getCStringNoCopy()); 
3932     OSSafeRelease(kextIdentifierSymbol
); 
3936 /********************************************************************* 
3937 *********************************************************************/ 
3940     OSKextExcludeLevel   startOpt
, 
3941     OSKextExcludeLevel   startMatchingOpt
, 
3942     OSArray            
* personalityNames
) 
3944     OSReturn             result                       
= kOSReturnError
; 
3945     kern_return_t        kxldResult
; 
3946     OSKextExcludeLevel   dependenciesStartOpt         
= startOpt
; 
3947     OSKextExcludeLevel   dependenciesStartMatchingOpt 
= startMatchingOpt
; 
3948     unsigned int         i
, count
; 
3949     Boolean              alreadyLoaded                
= false; 
3950     OSKext             
* lastLoadedKext               
= NULL
; 
3952     if (!sLoadEnabled
) { 
3953         if (!isLoaded() || (!isStarted() && startOpt 
!= kOSKextExcludeNone
) || 
3954             (startMatchingOpt 
!= kOSKextExcludeNone
)) { 
3957                 kOSKextLogErrorLevel 
| 
3959                 "Kext loading is disabled " 
3960                 "(attempt to load/start/start matching for kext %s).", 
3961                 getIdentifierCString()); 
3963         result 
= kOSKextReturnDisabled
; 
3968         alreadyLoaded 
= true; 
3969         result 
= kOSReturnSuccess
; 
3972             kOSKextLogDebugLevel 
| 
3973             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
3974             "Kext %s is already loaded.", 
3975             getIdentifierCString()); 
3979    /* If we've pushed the next available load tag to the invalid value, 
3980     * we can't load any more kexts. 
3982     if (sNextLoadTag 
== kOSKextInvalidLoadTag
) { 
3984             kOSKextLogErrorLevel 
| 
3986             "Can't load kext %s - no more load tags to assign.", 
3987             getIdentifierCString()); 
3988         result 
= kOSKextReturnNoResources
; 
3992    /* This is a bit of a hack, because we shouldn't be handling  
3993     * personalities within the load function. 
3995     if (!declaresExecutable()) { 
3996         result 
= kOSReturnSuccess
; 
4000    /* Are we in safe boot? 
4002     if (sSafeBoot 
&& !isLoadableInSafeBoot()) { 
4004             kOSKextLogErrorLevel 
| 
4006             "Can't load kext %s - not loadable during safe boot.", 
4007             getIdentifierCString()); 
4008         result 
= kOSKextReturnBootLevel
; 
4013         kOSKextLogProgressLevel 
| kOSKextLogLoadFlag
, 
4015         getIdentifierCString()); 
4018     if (!sKxldContext
) { 
4019         kxldResult 
= kxld_create_context(&sKxldContext
, &kern_allocate
,  
4020             &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,  
4021             /* cputype */ 0, /* cpusubtype */ 0); 
4024                 kOSKextLogErrorLevel 
| 
4025                 kOSKextLogLoadFlag 
| kOSKextLogLinkFlag
, 
4026                 "Can't load kext %s - failed to create link context.", 
4027                 getIdentifierCString()); 
4028             result 
= kOSKextReturnNoMemory
; 
4033     /* We only need to resolve dependencies once for the whole graph, but 
4034      * resolveDependencies will just return if there's no work to do, so it's 
4035      * safe to call it more than once. 
4037     if (!resolveDependencies()) { 
4038         // xxx - check resolveDependencies() for log msg 
4040             kOSKextLogErrorLevel 
| 
4041             kOSKextLogLoadFlag 
| kOSKextLogDependenciesFlag
, 
4042             "Can't load kext %s - failed to resolve library dependencies.", 
4043             getIdentifierCString()); 
4044         result 
= kOSKextReturnDependencies
; 
4048    /* If we are excluding just the kext being loaded now (and not its 
4049     * dependencies), drop the exclusion level to none so dependencies 
4050     * start and/or add their personalities. 
4052     if (dependenciesStartOpt 
== kOSKextExcludeKext
) { 
4053         dependenciesStartOpt 
= kOSKextExcludeNone
; 
4056     if (dependenciesStartMatchingOpt 
== kOSKextExcludeKext
) { 
4057         dependenciesStartMatchingOpt 
= kOSKextExcludeNone
; 
4060    /* Load the dependencies, recursively. 
4062     count 
= getNumDependencies(); 
4063     for (i 
= 0; i 
< count
; i
++) { 
4064         OSKext 
* dependency 
= OSDynamicCast(OSKext
, 
4065             dependencies
->getObject(i
)); 
4066         if (dependency 
== NULL
) { 
4068                 kOSKextLogErrorLevel 
| 
4069                 kOSKextLogLoadFlag 
| kOSKextLogDependenciesFlag
, 
4070                 "Internal error loading kext %s; dependency disappeared.", 
4071                 getIdentifierCString()); 
4072             result 
= kOSKextReturnInternalError
; 
4076        /* Dependencies must be started accorting to the opt, 
4077         * but not given the personality names of the main kext. 
4079         result 
= dependency
->load(dependenciesStartOpt
, 
4080             dependenciesStartMatchingOpt
, 
4081             /* personalityNames */ NULL
); 
4082         if (result 
!= KERN_SUCCESS
) { 
4084                 kOSKextLogErrorLevel 
| 
4085                 kOSKextLogLoadFlag 
| kOSKextLogDependenciesFlag
, 
4086                 "Dependency %s of kext %s failed to load.", 
4087                 dependency
->getIdentifierCString(), 
4088                 getIdentifierCString()); 
4090             OSKext::removeKext(dependency
, 
4091                 /* terminateService/removePersonalities */ true); 
4092             result 
= kOSKextReturnDependencyLoadError
; 
4098     result 
= loadExecutable(); 
4099     if (result 
!= KERN_SUCCESS
) { 
4103     flags
.loaded 
= true; 
4105    /* Add the kext to the list of loaded kexts and update the kmod_info 
4106     * struct to point to that of the last loaded kext (which is the way 
4107     * it's always been done, though I'd rather do them in order now). 
4109     lastLoadedKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject()); 
4110     sLoadedKexts
->setObject(this); 
4112    /* Keep the kernel itself out of the kmod list. 
4114     if (lastLoadedKext 
== sKernelKext
) { 
4115         lastLoadedKext 
= NULL
; 
4118     if (lastLoadedKext
) { 
4119         kmod_info
->next 
= lastLoadedKext
->kmod_info
; 
4122    /* Make the global kmod list point at the just-loaded kext. Note that the 
4123     * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard, 
4124     * although we do report it in kextstat these days by using the newer 
4125     * OSArray of loaded kexts, which does contain it. 
4127     * (The OSKext object representing the kernel doesn't even have a kmod_info 
4128     * struct, though I suppose we could stick a pointer to it from the 
4129     * static struct in OSRuntime.cpp.) 
4133    /* Save the list of loaded kexts in case we panic. 
4135     clock_get_uptime(&last_loaded_timestamp
); 
4136     OSKext::saveLoadedKextPanicList(); 
4139    /* This is a bit of a hack, because we shouldn't be handling  
4140     * personalities within the load function. 
4142     if (declaresExecutable() && (startOpt 
== kOSKextExcludeNone
)) { 
4144         if (result 
!= kOSReturnSuccess
) { 
4146                 kOSKextLogErrorLevel 
| kOSKextLogLoadFlag
, 
4147                 "Kext %s start failed (result 0x%x).", 
4148                 getIdentifierCString(), result
); 
4149             result 
= kOSKextReturnStartStopError
; 
4153    /* If not excluding matching, send the personalities to the kernel. 
4154     * This never affects the result of the load operation. 
4156     if (result 
== kOSReturnSuccess 
&& startMatchingOpt 
== kOSKextExcludeNone
) { 
4157         sendPersonalitiesToCatalog(true, personalityNames
); 
4161     if (result 
!= kOSReturnSuccess
) { 
4163             kOSKextLogErrorLevel 
| 
4165             "Kext %s failed to load (0x%x).", 
4166             getIdentifierCString(), (int)result
); 
4167     } else if (!alreadyLoaded
) { 
4169             kOSKextLogProgressLevel 
| 
4172             getIdentifierCString()); 
4177 /********************************************************************* 
4178 * called only by load() 
4179 *********************************************************************/ 
4181 OSKext::loadExecutable() 
4183     OSReturn              result             
= kOSReturnError
; 
4184     kern_return_t         kxldResult
; 
4185     u_char            
**  kxlddeps           
= NULL
;  // must kfree 
4186     uint32_t              num_kxlddeps       
= 0; 
4187     uint32_t              num_kmod_refs      
= 0; 
4188     u_char              
* linkStateBytes     
= NULL
;  // do not free 
4189     u_long                linkStateLength    
= 0; 
4190     u_char             
** linkStateBytesPtr  
= NULL
;  // do not free 
4191     u_long              
* linkStateLengthPtr 
= NULL
;  // do not free 
4192     struct mach_header 
** kxldHeaderPtr      
= NULL
;  // do not free 
4193     struct mach_header  
* kxld_header        
= NULL
;  // xxx - need to free here? 
4194     OSData              
* theExecutable      
= NULL
;  // do not release 
4195     OSString            
* versString         
= NULL
;  // do not release 
4196     const char          * versCString        
= NULL
;  // do not free 
4197     const char          * string             
= NULL
;  // do not free 
4200    /* We need the version string for a variety of bits below. 
4202     versString 
= OSDynamicCast(OSString
, 
4203         getPropertyForHostArch(kCFBundleVersionKey
)); 
4207     versCString 
= versString
->getCStringNoCopy(); 
4209     if (isKernelComponent()) { 
4210        if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) { 
4211            if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) { 
4213                     kOSKextLogErrorLevel 
| 
4215                     "Kernel component %s has incorrect version %s; " 
4217                     getIdentifierCString(), 
4218                     versCString
, KERNEL6_VERSION
); 
4219                result 
= kOSKextReturnInternalError
; 
4221            } else if (strcmp(versCString
, osrelease
)) { 
4223                     kOSKextLogErrorLevel 
| 
4225                     "Kernel component %s has incorrect version %s; " 
4227                     getIdentifierCString(), 
4228                     versCString
, osrelease
); 
4229                result 
= kOSKextReturnInternalError
; 
4235     if (isPrelinked()) { 
4239     theExecutable 
= getExecutable(); 
4240     if (!theExecutable
) { 
4241         if (declaresExecutable()) { 
4243                 kOSKextLogErrorLevel 
| 
4245                 "Can't load kext %s - executable is missing.", 
4246                 getIdentifierCString()); 
4247             result 
= kOSKextReturnValidation
; 
4253     if (isKernelComponent()) { 
4254         num_kxlddeps 
= 1; // the kernel itself 
4256         num_kxlddeps 
= getNumDependencies(); 
4258     if (!num_kxlddeps
) { 
4260             kOSKextLogErrorLevel 
| 
4261             kOSKextLogLoadFlag 
| kOSKextLogDependenciesFlag
, 
4262             "Can't load kext %s - it has no library dependencies.", 
4263             getIdentifierCString()); 
4266     kxlddeps 
= (u_char 
**)kalloc(num_kxlddeps 
* sizeof(*kxlddeps
)); 
4269             kOSKextLogErrorLevel 
| 
4270             kOSKextLogLoadFlag 
| kOSKextLogLinkFlag
, 
4271             "Can't allocate link context to load kext %s.", 
4272             getIdentifierCString()); 
4276     if (isKernelComponent()) { 
4277         OSData 
* kernelLinkState 
= OSKext::getKernelLinkState(); 
4278         kxlddeps
[0] = (u_char 
*)kernelLinkState
->getBytesNoCopy(); 
4279     } else for (i 
= 0; i 
< num_kxlddeps
; i
++) { 
4280         OSKext 
* dependency 
= OSDynamicCast(OSKext
, dependencies
->getObject(i
)); 
4281         if (!dependency
->linkState
) { 
4282             // xxx - maybe we should panic here 
4284                 kOSKextLogErrorLevel 
| 
4285                 kOSKextLogLoadFlag 
| kOSKextLogLinkFlag
, 
4286                 "Can't load kext %s - link state missing.", 
4287                 getIdentifierCString()); 
4290         kxlddeps
[i
] = (u_char 
*)dependency
->linkState
->getBytesNoCopy(); 
4291         assert(kxlddeps
[i
]); 
4294    /* We only need link state for a library kext. 
4296     if (compatibleVersion 
> -1 && (declaresExecutable() || isKernelComponent())) { 
4297         linkStateBytesPtr 
= &linkStateBytes
; 
4298         linkStateLengthPtr 
= &linkStateLength
; 
4301    /* We only need the linked executable for a real kext. 
4303     if (!isInterface()) { 
4304         kxldHeaderPtr 
= &kxld_header
; 
4309         kOSKextLogExplicitLevel 
| 
4310         kOSKextLogLoadFlag 
| kOSKextLogLinkFlag
, 
4311         "Kext %s - calling kxld_link_file:\n" 
4312         "    kxld_context: %p\n" 
4313         "    executable: %p    executable_length: %d\n" 
4315         "    kxld_dependencies: %p    num_dependencies: %d\n" 
4316         "    kxld_header_ptr: %p    kmod_info_ptr: %p\n" 
4317         "    link_state_ptr: %p    link_state_length_ptr: %p", 
4318         getIdentifierCString(), kxldContext
, 
4319         theExecutable
->getBytesNoCopy(), theExecutable
->getLength(), 
4320         this, kxlddeps
, num_kxlddeps
, 
4321         kxldHeaderPtr
, kernelKmodInfoPtr
, 
4322         linkStateBytesPtr
, linkStateLengthPtr
); 
4325    /* After this call, the linkedExecutable instance variable 
4328     kxldResult 
= kxld_link_file(sKxldContext
, 
4329         (u_char 
*)theExecutable
->getBytesNoCopy(), 
4330         theExecutable
->getLength(), 
4331         getIdentifierCString(), this, kxlddeps
, num_kxlddeps
, 
4332         (u_char 
**)kxldHeaderPtr
, (kxld_addr_t 
*)&kmod_info
, 
4333         linkStateBytesPtr
, linkStateLengthPtr
, 
4334         /* symbolFile */ NULL
, /* symbolFileSize */ NULL
); 
4336     if (kxldResult 
!= KERN_SUCCESS
) { 
4337         // xxx - add kxldResult here? 
4339             kOSKextLogErrorLevel 
| 
4341             "Can't load kext %s - link failed.", 
4342             getIdentifierCString()); 
4343         result 
= kOSKextReturnLinkError
; 
4347    /* If we got a link state, wrap it in an OSData and keep it 
4348     * around for later use linking other kexts that depend on this kext. 
4350     if (linkStateBytes 
&& linkStateLength 
> 0) { 
4351         linkState 
= OSData::withBytesNoCopy(linkStateBytes
, linkStateLength
); 
4353         linkState
->setDeallocFunction(&osdata_kmem_free
); 
4356    /* If this isn't an interface, We've written data & instructions into kernel  
4357     * memory, so flush the data cache and invalidate the instruction cache. 
4359     if (!isInterface()) { 
4360         flush_dcache(kmod_info
->address
, kmod_info
->size
, false); 
4361         invalidate_icache(kmod_info
->address
, kmod_info
->size
, false); 
4366     if (isInterface()) { 
4368        /* Whip up a fake kmod_info entry for the interface kext. 
4370         kmod_info 
= (kmod_info_t 
*)kalloc(sizeof(kmod_info_t
)); 
4372             result 
= KERN_MEMORY_ERROR
; 
4376        /* A pseudokext has almost nothing in its kmod_info struct. 
4378         bzero(kmod_info
, sizeof(kmod_info_t
)); 
4380         kmod_info
->info_version 
= KMOD_INFO_VERSION
; 
4382        /* An interface kext doesn't have a linkedExecutable, so save a 
4383         * copy of the UUID out of the original executable via copyUUID() 
4384         * while we still have the original executable. 
4386         interfaceUUID 
= copyUUID(); 
4389     kmod_info
->id 
= loadTag 
= sNextLoadTag
++; 
4390     kmod_info
->reference_count 
= 0;  // KMOD_DECL... sets it to -1 (invalid). 
4392    /* Stamp the bundle ID and version from the OSKext over anything 
4393     * resident inside the kmod_info. 
4395     string 
= getIdentifierCString(); 
4396     strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
)); 
4398     string 
= versCString
; 
4399     strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
)); 
4401    /* Add the dependencies' kmod_info structs as kmod_references. 
4403     num_kmod_refs 
= getNumDependencies(); 
4404     if (num_kmod_refs
) { 
4405         kmod_info
->reference_list 
= (kmod_reference_t 
*)kalloc( 
4406             num_kmod_refs 
* sizeof(kmod_reference_t
)); 
4407         if (!kmod_info
->reference_list
) { 
4408             result 
= KERN_MEMORY_ERROR
; 
4411         bzero(kmod_info
->reference_list
, 
4412             num_kmod_refs 
* sizeof(kmod_reference_t
)); 
4413         for (uint32_t refIndex 
= 0; refIndex 
< num_kmod_refs
; refIndex
++) { 
4414             kmod_reference_t 
* ref 
= &(kmod_info
->reference_list
[refIndex
]); 
4415             OSKext 
* refKext 
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
)); 
4416             ref
->info 
= refKext
->kmod_info
; 
4417             ref
->info
->reference_count
++; 
4419             if (refIndex 
+ 1 < num_kmod_refs
) { 
4420                 ref
->next 
= kmod_info
->reference_list 
+ refIndex 
+ 1; 
4425     if (!isInterface() && linkedExecutable
) { 
4427             kOSKextLogProgressLevel 
| 
4429             "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",  
4431             (unsigned)kmod_info
->size 
/ PAGE_SIZE
, 
4432             (unsigned long)kmod_info
->address
, 
4433             (unsigned)kmod_info
->id
); 
4436     result 
= setVMProtections(); 
4437     if (result 
!= KERN_SUCCESS
) { 
4441     result 
= kOSReturnSuccess
; 
4444     if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps 
* sizeof(void *))); 
4446    /* We no longer need the unrelocated executable (which the linker 
4447     * has altered anyhow). 
4449     setExecutable(NULL
); 
4451     if (result 
!= kOSReturnSuccess
) { 
4453             kOSKextLogErrorLevel 
| 
4455             "Failed to load executable for kext %s.", 
4456             getIdentifierCString()); 
4458         if (kmod_info 
&& kmod_info
->reference_list
) { 
4459             kfree(kmod_info
->reference_list
, 
4460                 num_kmod_refs 
* sizeof(kmod_reference_t
)); 
4462         if (isInterface()) { 
4463             kfree(kmod_info
, sizeof(kmod_info_t
)); 
4466         if (linkedExecutable
) { 
4467             linkedExecutable
->release(); 
4468             linkedExecutable 
= NULL
; 
4475 /********************************************************************* 
4476 * xxx - initWithPrelinkedInfoDict doesn't use this 
4477 *********************************************************************/ 
4479 OSKext::setLinkedExecutable(OSData 
* anExecutable
) 
4481     if (linkedExecutable
) { 
4482         panic("Attempt to set linked executable on kext " 
4483             "that already has one (%s).\n", 
4484             getIdentifierCString()); 
4486     linkedExecutable 
= anExecutable
; 
4487     linkedExecutable
->retain(); 
4491 /********************************************************************* 
4492 * called only by loadExecutable() 
4493 *********************************************************************/ 
4495 OSKext::setVMProtections(void) 
4497     vm_map_t                    kext_map        
= NULL
; 
4498     kernel_segment_command_t  
* seg             
= NULL
; 
4499     vm_map_offset_t             start           
= 0; 
4500     vm_map_offset_t             end             
= 0; 
4501     OSReturn                    result          
= kOSReturnError
; 
4503     if (!kmod_info
->address 
&& !kmod_info
->size
) { 
4504         result 
= kOSReturnSuccess
; 
4508     /* Get the kext's vm map */ 
4509     kext_map 
= kext_get_vm_map(kmod_info
); 
4511         result 
= KERN_MEMORY_ERROR
; 
4515     /* XXX: On arm, the vme covering the prelinked kernel (really, the whole 
4516      * range from 0xc0000000 to a little over 0xe0000000) has maxprot set to 0 
4517      * so the vm_map_protect calls below fail 
4518      * I believe this happens in the call to vm_map_enter in kmem_init but I  
4521     /* Protect the headers as read-only; they do not need to be wired */ 
4522     result 
= vm_map_protect(kext_map
, kmod_info
->address
,  
4523         kmod_info
->address 
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
); 
4524     if (result 
!= KERN_SUCCESS
) { 
4528     /* Set the VM protections and wire down each of the segments */ 
4529     seg 
= firstsegfromheader((kernel_mach_header_t 
*)kmod_info
->address
); 
4531         start 
= round_page(seg
->vmaddr
); 
4532         end 
= trunc_page(seg
->vmaddr 
+ seg
->vmsize
); 
4534         result 
= vm_map_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
); 
4535         if (result 
!= KERN_SUCCESS
) { 
4537                 kOSKextLogErrorLevel 
| 
4539                 "Kext %s failed to set maximum VM protections " 
4540                 "for segment %s - 0x%x.",  
4541                 getIdentifierCString(), seg
->segname
, (int)result
); 
4545         result 
= vm_map_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
); 
4546         if (result 
!= KERN_SUCCESS
) { 
4548                 kOSKextLogErrorLevel 
| 
4550                 "Kext %s failed to set initial VM protections " 
4551                 "for segment %s - 0x%x.",  
4552                 getIdentifierCString(), seg
->segname
, (int)result
); 
4556         result 
= vm_map_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
); 
4557         if (result 
!= KERN_SUCCESS
) { 
4561         seg 
= nextsegfromheader((kernel_mach_header_t 
*) kmod_info
->address
, seg
); 
4568 /********************************************************************* 
4569 *********************************************************************/ 
4571 OSKext::validateKextMapping(bool startFlag
) 
4573     OSReturn                              result      
= kOSReturnError
; 
4574     const char                          * whichOp 
= startFlag 
? "start" : "stop"; 
4575     kern_return_t                         kern_result 
= 0; 
4576     vm_map_t                              kext_map    
= NULL
; 
4577     mach_vm_address_t                     address     
= 0; 
4578     mach_vm_size_t                        size        
= 0; 
4580     mach_msg_type_number_t                count
; 
4581     vm_region_submap_short_info_data_64_t info
; 
4583     count 
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
; 
4584     bzero(&info
, sizeof(info
)); 
4586    // xxx - do we need a distinct OSReturn value for these or is "bad data" 
4587    // xxx - sufficient? 
4589    /* Verify that the kmod_info and start/stop pointers are non-NULL. 
4593             kOSKextLogErrorLevel 
| 
4595             "Kext %s - NULL kmod_info pointer.", 
4596             getIdentifierCString()); 
4597         result 
= kOSKextReturnBadData
; 
4602         address 
= (mach_vm_address_t
)kmod_info
->start
; 
4604         address 
= (mach_vm_address_t
)kmod_info
->stop
; 
4609             kOSKextLogErrorLevel 
| 
4611             "Kext %s - NULL module %s pointer.", 
4612             getIdentifierCString(), whichOp
); 
4613         result 
= kOSKextReturnBadData
; 
4617     kext_map 
= kext_get_vm_map(kmod_info
); 
4618     depth 
= (kernel_map 
== kext_map
) ? 1 : 2; 
4620    /* Verify that the start/stop function lies within the kext's address range. 
4622     if (address 
< kmod_info
->address 
+ kmod_info
->hdr_size 
|| 
4623         kmod_info
->address 
+ kmod_info
->size 
<= address
) 
4626             kOSKextLogErrorLevel 
| 
4628             "Kext %s module %s pointer is outside of kext range " 
4629             "(%s %p - kext at %p-%p)..", 
4630             getIdentifierCString(), 
4634             (void *)kmod_info
->address
, 
4635             (void *)(kmod_info
->address 
+ kmod_info
->size
)); 
4636         result 
= kOSKextReturnBadData
; 
4640    /* Only do these checks before calling the start function; 
4641     * If anything goes wrong with the mapping while the kext is running, 
4642     * we'll likely have panicked well before any attempt to stop the kext. 
4646        /* Verify that the start/stop function is executable. 
4648         kern_result 
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
, 
4649             (vm_region_recurse_info_t
)&info
, &count
); 
4650         if (kern_result 
!= KERN_SUCCESS
) { 
4652                 kOSKextLogErrorLevel 
| 
4654                 "Kext %s - bad %s pointer %p.", 
4655                 getIdentifierCString(), 
4656                 whichOp
, (void *)address
); 
4657             result 
= kOSKextReturnBadData
; 
4661         if (!(info
.protection 
& VM_PROT_EXECUTE
)) { 
4663                 kOSKextLogErrorLevel 
| 
4665                 "Kext %s - memory region containing module %s function " 
4666                 "is not executable.", 
4667                 getIdentifierCString(), whichOp
); 
4668             result 
= kOSKextReturnBadData
; 
4672        /* Verify that the kext is backed by physical memory. 
4674         for (address 
= kmod_info
->address
; 
4675              address 
< round_page(kmod_info
->address 
+ kmod_info
->size
); 
4676              address 
+= PAGE_SIZE
) 
4678             if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) { 
4680                     kOSKextLogErrorLevel 
| 
4682                     "Kext %s - page %p is not backed by physical memory.", 
4683                     getIdentifierCString(),  
4685                 result 
= kOSKextReturnBadData
; 
4691     result 
= kOSReturnSuccess
; 
4696 /********************************************************************* 
4697 *********************************************************************/ 
4699 OSKext::start(bool startDependenciesFlag
) 
4701     OSReturn                            result 
= kOSReturnError
; 
4702     kern_return_t                       (* startfunc
)(kmod_info_t 
*, void *); 
4703     unsigned int                        i
, count
; 
4704     void                              * kmodStartData      
= NULL
;  // special handling needed 
4705 #if CONFIG_MACF_KEXT 
4706     mach_msg_type_number_t              kmodStartDataCount 
= 0; 
4707 #endif /* CONFIG_MACF_KEXT */ 
4709     if (isStarted() || isInterface() || isKernelComponent()) { 
4710         result 
= kOSReturnSuccess
; 
4716             kOSKextLogErrorLevel 
| 
4718             "Attempt to start nonloaded kext %s.", 
4719             getIdentifierCString());  
4720         result 
= kOSKextReturnInvalidArgument
; 
4724     result 
= validateKextMapping(/* start? */ true); 
4725     if (result 
!= kOSReturnSuccess
) { 
4729     startfunc 
= kmod_info
->start
; 
4731     count 
= getNumDependencies(); 
4732     for (i 
= 0; i 
< count
; i
++) { 
4733         OSKext 
* dependency 
= OSDynamicCast(OSKext
, dependencies
->getObject(i
)); 
4734         if (dependency 
== NULL
) { 
4736                 kOSKextLogErrorLevel 
| 
4738                 "Kext %s start - internal error, dependency disappeared.", 
4739                 getIdentifierCString()); 
4742         if (!dependency
->isStarted()) { 
4743             if (startDependenciesFlag
) { 
4744                 OSReturn dependencyResult 
= 
4745                     dependency
->start(startDependenciesFlag
); 
4746                 if (dependencyResult 
!= KERN_SUCCESS
) { 
4748                         kOSKextLogErrorLevel 
| 
4750                         "Kext %s start - dependency %s failed to start (error 0x%x).", 
4751                         getIdentifierCString(), 
4752                         dependency
->getIdentifierCString(), 
4758                     kOSKextLogErrorLevel 
| 
4760                     "Not starting %s - dependency %s not started yet.", 
4761                     getIdentifierCString(), 
4762                     dependency
->getIdentifierCString()); 
4763                 result 
= kOSKextReturnStartStopError
;  // xxx - make new return? 
4769 #if CONFIG_MACF_KEXT 
4770    /* See if the kext has any MAC framework module data in its plist. 
4771     * This is passed in as arg #2 of the kext's start routine, 
4772     * which is otherwise reserved for any other kext. 
4774     kmodStartData 
= MACFCopyModuleDataForKext(this, &kmodStartDataCount
); 
4775 #endif /* CONFIG_MACF_KEXT */ 
4778         kOSKextLogDetailLevel 
| 
4780         "Kext %s calling module start function.", 
4781         getIdentifierCString());  
4785 #if !__i386__ && !__ppc__ 
4786     result 
= OSRuntimeInitializeCPP(kmod_info
, NULL
); 
4787     if (result 
== KERN_SUCCESS
) { 
4790         result 
= startfunc(kmod_info
, kmodStartData
); 
4792 #if !__i386__ && !__ppc__ 
4793         if (result 
!= KERN_SUCCESS
) { 
4794             (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
); 
4801    /* On success overlap the setting of started/starting. On failure just 
4804     if (result 
== KERN_SUCCESS
) { 
4807         // xxx - log start error from kernel? 
4809             kOSKextLogProgressLevel 
| 
4811             "Kext %s is now started.", 
4812             getIdentifierCString());  
4814         invokeOrCancelRequestCallbacks( 
4815             /* result not actually used */ kOSKextReturnStartStopError
, 
4816             /* invokeFlag */ false); 
4818             kOSKextLogProgressLevel 
| 
4820             "Kext %s did not start (return code 0x%x).", 
4821             getIdentifierCString(), result
);  
4825 #if CONFIG_MACF_KEXT 
4826    /* Free the module data for a MAC framework kext. When we start using 
4827     * param #2 we'll have to distinguish and free/release appropriately. 
4829     * xxx - I'm pretty sure the old codepath freed the data and that it's 
4830     * xxx - up to the kext to copy it. 
4832     if (kmodStartData
) { 
4833         kmem_free(kernel_map
, (vm_offset_t
)kmodStartData
, kmodStartDataCount
); 
4835 #endif /* CONFIG_MACF_KEXT */ 
4840 /********************************************************************* 
4841 *********************************************************************/ 
4843 bool OSKext::canUnloadKextWithIdentifier( 
4844     OSString 
* kextIdentifier
, 
4845     bool       checkClassesFlag
) 
4847     bool     result 
= false; 
4848     OSKext 
* aKext  
= NULL
;  // do not release 
4850     IORecursiveLockLock(sKextLock
); 
4852     aKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
)); 
4855         goto finish
;  // can't unload what's not loaded 
4858     if (aKext
->isLoaded()) { 
4859         if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) { 
4862         if (checkClassesFlag 
&& aKext
->hasOSMetaClassInstances()) { 
4870     IORecursiveLockUnlock(sKextLock
); 
4874 /********************************************************************* 
4875 *********************************************************************/ 
4879     OSReturn result 
= kOSReturnError
; 
4880     kern_return_t (*stopfunc
)(kmod_info_t 
*, void *); 
4882     if (!isStarted() || isInterface()) { 
4883         result 
= kOSReturnSuccess
; 
4889             kOSKextLogErrorLevel 
| 
4891             "Attempt to stop nonloaded kext %s.", 
4892             getIdentifierCString()); 
4893         result 
= kOSKextReturnInvalidArgument
; 
4897    /* Refuse to stop if we have clients or instances. It is up to 
4898     * the caller to make sure those aren't true. 
4900     if (getRetainCount() > kOSKextMinLoadedRetainCount
) { 
4902             kOSKextLogErrorLevel 
| 
4904             "Kext %s - C++ instances; can't stop.", 
4905             getIdentifierCString()); 
4906         result 
= kOSKextReturnInUse
; 
4910     if (getRetainCount() > kOSKextMinLoadedRetainCount
) { 
4913             kOSKextLogErrorLevel 
| 
4915             "Kext %s - has references (linkage or tracking object); " 
4917             getIdentifierCString()); 
4918         result 
= kOSKextReturnInUse
; 
4922    /* Note: If validateKextMapping fails on the stop & unload path, 
4923     * we are in serious trouble and a kernel panic is likely whether 
4924     * we stop & unload the kext or not. 
4926     result 
= validateKextMapping(/* start? */ false); 
4927     if (result 
!= kOSReturnSuccess
) { 
4931    /* Save the list of loaded kexts in case we panic. 
4933     OSKext::saveUnloadedKextPanicList(this); 
4935     stopfunc 
= kmod_info
->stop
; 
4938             kOSKextLogDetailLevel 
| 
4940             "Kext %s calling module stop function.", 
4941             getIdentifierCString());  
4945         result 
= stopfunc(kmod_info
, /* userData */ NULL
); 
4946 #if !__i386__ && !__ppc__ 
4947         if (result 
== KERN_SUCCESS
) { 
4948             result 
= OSRuntimeFinalizeCPP(kmod_info
, NULL
); 
4954         if (result 
== KERN_SUCCESS
) { 
4958                 kOSKextLogDetailLevel 
| 
4960                 "Kext %s is now stopped and ready to unload.", 
4961                 getIdentifierCString());  
4964                 kOSKextLogErrorLevel 
| 
4966                 "Kext %s did not stop (return code 0x%x).", 
4967                 getIdentifierCString(), result
);  
4968             result 
= kOSKextReturnStartStopError
; 
4976 /********************************************************************* 
4977 *********************************************************************/ 
4979 OSKext::unload(void) 
4981     OSReturn     result 
= kOSReturnError
; 
4983     uint32_t     num_kmod_refs 
= 0; 
4985     if (!sUnloadEnabled
) { 
4987             kOSKextLogErrorLevel 
| 
4989             "Kext unloading is disabled (%s).", 
4990             this->getIdentifierCString()); 
4992         result 
= kOSKextReturnDisabled
; 
4996    /* Refuse to unload if we have clients or instances. It is up to 
4997     * the caller to make sure those aren't true. 
4999     if (getRetainCount() > kOSKextMinLoadedRetainCount
) { 
5000         // xxx - Don't log under errors? this is more of an info thing 
5002             kOSKextLogErrorLevel 
| 
5003             kOSKextLogKextBookkeepingFlag
, 
5004             "Can't unload kext %s; outstanding references (linkage or tracking object).", 
5005             getIdentifierCString()); 
5006         result 
= kOSKextReturnInUse
; 
5011     if (hasOSMetaClassInstances()) { 
5013             kOSKextLogErrorLevel 
| 
5014             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
5015             "Can't unload kext %s; classes have instances:", 
5016             getIdentifierCString()); 
5017         reportOSMetaClassInstances(kOSKextLogErrorLevel 
| 
5018             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
); 
5019         result 
= kOSKextReturnInUse
; 
5024         result 
= kOSReturnSuccess
; 
5028     if (isKernelComponent()) { 
5029         result 
= kOSKextReturnInvalidArgument
; 
5033    /* Note that the kext is unloading before running any code that 
5034     * might be in the kext (request callbacks, module stop function). 
5035     * We will deny certain requests made against a kext in the process 
5038     flags
.unloading 
= 1; 
5042         if (result 
!= KERN_SUCCESS
) { 
5044                 kOSKextLogErrorLevel 
| 
5046                 "Kext %s can't unload - module stop returned 0x%x.", 
5047                 getIdentifierCString(), (unsigned)result
); 
5048             result 
= kOSKextReturnStartStopError
; 
5054         kOSKextLogProgressLevel 
| 
5056         "Kext %s unloading.", 
5057         getIdentifierCString()); 
5059    /* Even if we don't call the stop function, we want to be sure we 
5060     * have no OSMetaClass references before unloading the kext executable 
5061     * from memory. OSMetaClasses may have pointers into the kext executable 
5062     * and that would cause a panic on OSKext::free() when metaClasses is freed. 
5065         metaClasses
->flushCollection(); 
5068    /* Remove the kext from the list of loaded kexts, patch the gap 
5069     * in the kmod_info_t linked list, and reset "kmod" to point to the 
5070     * last loaded kext that isn't the fake kernel kext (sKernelKext). 
5072     index 
= sLoadedKexts
->getNextIndexOfObject(this, 0); 
5073     if (index 
!= (unsigned int)-1) { 
5075         sLoadedKexts
->removeObject(index
); 
5077         OSKext 
* nextKext 
= OSDynamicCast(OSKext
, 
5078             sLoadedKexts
->getObject(index
)); 
5082                 OSKext 
* gapKext 
= OSDynamicCast(OSKext
, 
5083                     sLoadedKexts
->getObject(index 
- 1)); 
5085                 nextKext
->kmod_info
->next 
= gapKext
->kmod_info
; 
5087             } else /* index == 0 */ { 
5088                 nextKext
->kmod_info
->next 
= NULL
; 
5092         OSKext 
* lastKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject()); 
5093         if (lastKext 
&& lastKext 
!= sKernelKext
) { 
5094             kmod 
= lastKext
->kmod_info
; 
5096             kmod 
= NULL
;  // clear the global kmod variable 
5100    /* Clear out the kmod references that we're keeping for compatibility 
5101     * with current panic backtrace code & kgmacros. 
5102     * xxx - will want to update those bits sometime and remove this. 
5104     num_kmod_refs 
= getNumDependencies(); 
5105     if (num_kmod_refs 
&& kmod_info 
&& kmod_info
->reference_list
) { 
5106         for (uint32_t refIndex 
= 0; refIndex 
< num_kmod_refs
; refIndex
++) { 
5107             kmod_reference_t 
* ref 
= &(kmod_info
->reference_list
[refIndex
]); 
5108             ref
->info
->reference_count
--; 
5110         kfree(kmod_info
->reference_list
, 
5111             num_kmod_refs 
* sizeof(kmod_reference_t
)); 
5114    /* If we have a linked executable, release & clear it, and then 
5115     * unwire & deallocate the buffer the OSData wrapped. 
5117     if (linkedExecutable
) { 
5120        /* linkedExecutable is just a wrapper for the executable and doesn't 
5123         linkedExecutable
->release(); 
5124         linkedExecutable 
= NULL
; 
5127             kOSKextLogProgressLevel 
| 
5129             "Kext %s unwiring and unmapping linked executable.", 
5130             getIdentifierCString()); 
5132         kext_map 
= kext_get_vm_map(kmod_info
); 
5134             // xxx - do we have to do this before freeing? Why can't we just free it? 
5135             // xxx - we should be able to set a dealloc func on the linkedExecutable 
5136             result 
= vm_map_unwire(kext_map
, 
5137                 kmod_info
->address 
+ kmod_info
->hdr_size
,  
5138                 kmod_info
->address 
+ kmod_info
->size
, FALSE
); 
5139             if (result 
== KERN_SUCCESS
) { 
5140                 kext_free(kmod_info
->address
, kmod_info
->size
); 
5145    /* An interface kext has a fake kmod_info that was allocated, 
5146     * so we have to free it. 
5148     if (isInterface()) { 
5149         kfree(kmod_info
, sizeof(kmod_info_t
)); 
5154     flags
.loaded 
= false; 
5155     flushDependencies(); 
5158         kOSKextLogProgressLevel 
| kOSKextLogLoadFlag
, 
5159         "Kext %s unloaded.", getIdentifierCString()); 
5162     OSKext::saveLoadedKextPanicList(); 
5164     flags
.unloading 
= 0; 
5168 /********************************************************************* 
5169 *********************************************************************/ 
5171 _OSKextConsiderDestroyingLinkContext( 
5172     __unused thread_call_param_t p0
, 
5173     __unused thread_call_param_t p1
) 
5175    /* Once both recursive locks are taken in correct order, we shouldn't 
5176     * have to worry about further recursive lock takes. 
5178     IORecursiveLockLock(sKextLock
); 
5179     IORecursiveLockLock(sKextInnerLock
); 
5181    /* The first time we destroy the kxldContext is in the first  
5182     * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled 
5183     * before calling this function. Thereafter any call to this function 
5184     * will actually destroy the context. 
5186     if (sConsiderUnloadsCalled 
&& sKxldContext
) { 
5187         kxld_destroy_context(sKxldContext
); 
5188         sKxldContext 
= NULL
; 
5191    /* Free the thread_call that was allocated to execute this function. 
5193     if (sDestroyLinkContextThread
) { 
5194         if (!thread_call_free(sDestroyLinkContextThread
)) { 
5195             OSKextLog(/* kext */ NULL
, 
5196                 kOSKextLogErrorLevel 
| 
5197                 kOSKextLogGeneralFlag
, 
5198                 "thread_call_free() failed for kext link context."); 
5200         sDestroyLinkContextThread 
= 0; 
5203     IORecursiveLockUnlock(sKextInnerLock
); 
5204     IORecursiveLockUnlock(sKextLock
); 
5209 /********************************************************************* 
5210 * Destroying the kxldContext requires checking variables under both 
5211 * sKextInnerLock and sKextLock, so we do it on a separate thread 
5212 * to avoid deadlocks with IOService, with which OSKext has a reciprocal 
5213 * call relationship. 
5215 * Do not call any function that takes sKextLock here! This function 
5216 * can be invoked with sKextInnerLock, and the two must always 
5217 * be taken in the order: sKextLock -> sKextInnerLock. 
5218 *********************************************************************/ 
5221 OSKext::considerDestroyingLinkContext(void) 
5223     IORecursiveLockLock(sKextInnerLock
); 
5225    /* If we have already queued a thread to destroy the link context, 
5226     * don't bother resetting; that thread will take care of it. 
5228     if (sDestroyLinkContextThread
) { 
5232    /* The function to be invoked in the thread will deallocate 
5233     * this thread_call, so don't share it around. 
5235     sDestroyLinkContextThread 
= thread_call_allocate( 
5236         &_OSKextConsiderDestroyingLinkContext
, 0); 
5237     if (!sDestroyLinkContextThread
) { 
5238         OSKextLog(/* kext */ NULL
, 
5239             kOSKextLogErrorLevel 
| kOSKextLogGeneralFlag 
| kOSKextLogLinkFlag
, 
5240             "Can't create thread to destroy kext link context."); 
5244     thread_call_enter(sDestroyLinkContextThread
); 
5247     IORecursiveLockUnlock(sKextInnerLock
); 
5251 /********************************************************************* 
5252 *********************************************************************/ 
5254 OSKext::getKernelLinkState() 
5256     kern_return_t   kxldResult
; 
5257     u_char        
* kernel          
= NULL
; 
5258     size_t          kernelLength
; 
5259     u_char        
* linkStateBytes  
= NULL
; 
5260     u_long          linkStateLength
; 
5261     OSData        
* linkState       
= NULL
; 
5263     if (sKernelKext 
&& sKernelKext
->linkState
) { 
5267     kernel 
= (u_char 
*)&_mh_execute_header
; 
5268     kernelLength 
= getlastaddr() - (vm_offset_t
)kernel
; 
5270     kxldResult 
= kxld_link_file(sKxldContext
, 
5273         kOSKextKernelIdentifier
, 
5274         /* callbackData */ NULL
, 
5275         /* dependencies */ NULL
, 
5276         /* numDependencies */ 0, 
5277         /* linkedObjectOut */ NULL
, 
5278         /* kmod_info_kern out */ NULL
, 
5281         /* symbolFile */ NULL
, 
5282         /* symbolFileSize */ NULL
); 
5284         panic("Can't generate kernel link state; no kexts can be loaded."); 
5288     linkState 
= OSData::withBytesNoCopy(linkStateBytes
, linkStateLength
); 
5289     linkState
->setDeallocFunction(&osdata_kmem_free
); 
5290     sKernelKext
->linkState 
= linkState
; 
5293     return sKernelKext
->linkState
; 
5297 #pragma mark Autounload 
5299 /********************************************************************* 
5300 * This is a static method because the kext will be deallocated if it 
5302 *********************************************************************/ 
5304 OSKext::autounloadKext(OSKext 
* aKext
) 
5306     OSReturn result 
= kOSKextReturnInUse
; 
5308    /* Check for external references to this kext (usu. dependents), 
5309     * instances of defined classes (or classes derived from them), 
5310     * outstanding requests. 
5312     if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) || 
5313         !aKext
->flags
.autounloadEnabled 
|| 
5314         aKext
->isKernelComponent()) { 
5319    /* Skip a delay-autounload kext, once. 
5321     if (aKext
->flags
.delayAutounload
) { 
5323             kOSKextLogProgressLevel 
| 
5324             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
5325             "Kext %s has delayed autounload set; skipping and clearing flag.", 
5326             aKext
->getIdentifierCString()); 
5327         aKext
->flags
.delayAutounload 
= 0; 
5331     if (aKext
->hasOSMetaClassInstances() || 
5332         aKext
->countRequestCallbacks()) { 
5336     result 
= OSKext::removeKext(aKext
); 
5343 /********************************************************************* 
5344 *********************************************************************/ 
5346 _OSKextConsiderUnloads( 
5347     __unused thread_call_param_t p0
, 
5348     __unused thread_call_param_t p1
) 
5350     bool         didUnload 
= false; 
5351     unsigned int count
, i
; 
5353    /* Once both recursive locks are taken in correct order, we shouldn't 
5354     * have to worry about further recursive lock takes. 
5356     IORecursiveLockLock(sKextLock
); 
5357     IORecursiveLockLock(sKextInnerLock
); 
5359     OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true); 
5361    /* If the system is powering down, don't try to unload anything. 
5367     OSKextLog(/* kext */ NULL
, 
5368         kOSKextLogProgressLevel 
| 
5370         "Checking for unused kexts to autounload."); 
5373     * Remove any request callbacks marked as stale, 
5374     * and mark as stale any currently in flight. 
5376     count 
= sRequestCallbackRecords
->getCount(); 
5380             OSDictionary 
* callbackRecord 
= OSDynamicCast(OSDictionary
, 
5381                 sRequestCallbackRecords
->getObject(i
)); 
5382             OSBoolean 
* stale 
= OSDynamicCast(OSBoolean
, 
5383                 callbackRecord
->getObject(kKextRequestStaleKey
)); 
5385             if (stale 
&& stale
->isTrue()) { 
5386                 OSKext::invokeRequestCallback(callbackRecord
, 
5387                     kOSKextReturnTimeout
); 
5389                 callbackRecord
->setObject(kKextRequestStaleKey
, 
5396     * Make multiple passes through the array of loaded kexts until 
5397     * we don't unload any. This handles unwinding of dependency 
5398     * chains. We have to go *backwards* through the array because 
5399     * kexts are removed from it when unloaded, and we cannot make 
5400     * a copy or we'll mess up the retain counts we rely on to 
5401     * check whether a kext will unload. If only we could have 
5402     * nonretaining collections like CF has.... 
5407         count 
= sLoadedKexts
->getCount(); 
5411                 OSKext 
* thisKext 
= OSDynamicCast(OSKext
, 
5412                     sLoadedKexts
->getObject(i
)); 
5413                 didUnload 
= (kOSReturnSuccess 
== OSKext::autounloadKext(thisKext
)); 
5416     } while (didUnload
); 
5419     sConsiderUnloadsPending 
= false; 
5420     sConsiderUnloadsExecuted 
= true; 
5422     (void) OSKext::considerRebuildOfPrelinkedKernel(); 
5424     IORecursiveLockUnlock(sKextInnerLock
); 
5425     IORecursiveLockUnlock(sKextLock
); 
5430 /********************************************************************* 
5431 * Do not call any function that takes sKextLock here! 
5432 *********************************************************************/ 
5433 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
) 
5437     IORecursiveLockLock(sKextInnerLock
); 
5439     if (!sUnloadCallout
) { 
5440         sUnloadCallout 
= thread_call_allocate(&_OSKextConsiderUnloads
, 0); 
5443     if (rescheduleOnlyFlag 
&& !sConsiderUnloadsPending
) { 
5447     thread_call_cancel(sUnloadCallout
); 
5448     if (OSKext::getAutounloadEnabled() && !sSystemSleep
) { 
5449         clock_interval_to_deadline(sConsiderUnloadDelay
, 
5450             1000 * 1000 * 1000, &when
); 
5452         OSKextLog(/* kext */ NULL
, 
5453             kOSKextLogProgressLevel 
| 
5455             "%scheduling %sscan for unused kexts in %lu seconds.", 
5456             sConsiderUnloadsPending 
? "Res" : "S", 
5457             sConsiderUnloadsCalled 
? "" : "initial ", 
5458             (unsigned long)sConsiderUnloadDelay
); 
5460         sConsiderUnloadsPending 
= true; 
5461         thread_call_enter_delayed(sUnloadCallout
, when
); 
5465    /* The kxld context should be reused throughout boot.  We mark the end of 
5466     * period as the first time considerUnloads() is called, and we destroy 
5467     * the first kxld context in that function.  Afterwards, it will be 
5468     * destroyed in flushNonloadedKexts. 
5470     if (!sConsiderUnloadsCalled
) { 
5471         sConsiderUnloadsCalled 
= true; 
5472         OSKext::considerDestroyingLinkContext(); 
5475     IORecursiveLockUnlock(sKextInnerLock
); 
5479 /********************************************************************* 
5480 * Do not call any function that takes sKextLock here! 
5481 *********************************************************************/ 
5484 IOReturn 
OSKextSystemSleepOrWake(UInt32 messageType
) 
5486     IORecursiveLockLock(sKextInnerLock
); 
5488    /* If the system is going to sleep, cancel the reaper thread timer, 
5489     * and note that we're in a sleep state in case it just fired but hasn't 
5490     * taken the lock yet. If we are coming back from sleep, just 
5491     * clear the sleep flag; IOService's normal operation will cause 
5492     * unloads to be considered soon enough. 
5494     if (messageType 
== kIOMessageSystemWillSleep
) { 
5495         if (sUnloadCallout
) { 
5496             thread_call_cancel(sUnloadCallout
); 
5498         sSystemSleep 
= true; 
5499     } else if (messageType 
== kIOMessageSystemHasPoweredOn
) { 
5500         sSystemSleep 
= false; 
5502     IORecursiveLockUnlock(sKextInnerLock
); 
5504     return kIOReturnSuccess
; 
5511 #pragma mark Prelinked Kernel 
5513 /********************************************************************* 
5514 * Do not access sConsiderUnloads... variables other than 
5515 * sConsiderUnloadsExecuted in this function. They are guarded by a 
5517 *********************************************************************/ 
5520 OSKext::considerRebuildOfPrelinkedKernel(void) 
5522     OSReturn       checkResult      
= kOSReturnError
; 
5523     static bool    requestedPrelink 
= false; 
5524     OSDictionary 
* prelinkRequest   
= NULL
;  // must release 
5526     IORecursiveLockLock(sKextLock
); 
5528     if (!sDeferredLoadSucceeded 
|| !sConsiderUnloadsExecuted 
||  
5529         sSafeBoot 
|| requestedPrelink
)  
5534     OSKextLog(/* kext */ NULL
, 
5535         kOSKextLogProgressLevel 
| 
5536         kOSKextLogArchiveFlag
, 
5537         "Requesting build of prelinked kernel."); 
5539     checkResult 
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
, 
5541     if (checkResult 
!= kOSReturnSuccess
) { 
5545     if (!sKernelRequests
->setObject(prelinkRequest
)) { 
5550     requestedPrelink 
= true; 
5553     IORecursiveLockUnlock(sKextLock
); 
5554     OSSafeRelease(prelinkRequest
); 
5559 #pragma mark Dependencies 
5561 /********************************************************************* 
5562 *********************************************************************/ 
5564 OSKext::resolveDependencies( 
5565     OSArray 
* loopStack
) 
5567     bool                   result                   
= false; 
5568     OSArray              
* localLoopStack           
= NULL
;   // must release 
5569     bool                   addedToLoopStack         
= false; 
5570     OSDictionary         
* libraries                
= NULL
;   // do not release 
5571     OSCollectionIterator 
* libraryIterator          
= NULL
;   // must release 
5572     OSString             
* libraryID                
= NULL
;   // do not release 
5573     OSString             
* infoString               
= NULL
;   // do not release 
5574     OSString             
* readableString           
= NULL
;   // do not release 
5575     OSKext               
* libraryKext              
= NULL
;   // do not release 
5576     bool                   hasRawKernelDependency   
= false; 
5577     bool                   hasKernelDependency      
= false; 
5578     bool                   hasKPIDependency         
= false; 
5579     bool                   hasPrivateKPIDependency  
= false; 
5582    /* A kernel component will automatically have this flag set, 
5583     * and a loaded kext should also have it set (as should all its 
5584     * loaded dependencies). 
5586     if (flags
.hasAllDependencies
) { 
5591    /* Check for loops in the dependency graph. 
5594         if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) { 
5596                 kOSKextLogErrorLevel 
| 
5597                 kOSKextLogDependenciesFlag
, 
5598                 "Kext %s has a dependency loop; can't resolve dependencies.", 
5599                 getIdentifierCString()); 
5604             kOSKextLogStepLevel 
| 
5605             kOSKextLogDependenciesFlag
, 
5606             "Kext %s resolving dependencies.", 
5607             getIdentifierCString()); 
5609         loopStack 
= OSArray::withCapacity(6);  // any small capacity will do 
5612                 kOSKextLogErrorLevel 
| 
5613                 kOSKextLogDependenciesFlag
, 
5614                 "Kext %s can't create bookkeeping stack to resolve dependencies.", 
5615                 getIdentifierCString()); 
5618         localLoopStack 
= loopStack
; 
5620     if (!loopStack
->setObject(this)) { 
5622             kOSKextLogErrorLevel 
| 
5623             kOSKextLogDependenciesFlag
, 
5624             "Kext %s - internal error resolving dependencies.", 
5625             getIdentifierCString()); 
5628     addedToLoopStack 
= true; 
5630    /* Purge any existing kexts in the dependency list and start over. 
5632     flushDependencies(); 
5635             kOSKextLogErrorLevel 
| 
5636             kOSKextLogDependenciesFlag
, 
5637             "Kext %s - internal error resolving dependencies.", 
5638             getIdentifierCString()); 
5641     libraries 
= OSDynamicCast(OSDictionary
, 
5642         getPropertyForHostArch(kOSBundleLibrariesKey
)); 
5643     if (libraries 
== NULL 
|| libraries
->getCount() == 0) { 
5645             kOSKextLogErrorLevel 
| 
5646             kOSKextLogValidationFlag 
| kOSKextLogDependenciesFlag
, 
5647             "Kext %s - can't resolve dependencies; %s missing/invalid type.", 
5648             getIdentifierCString(), kOSBundleLibrariesKey
); 
5652    /* Make a new array to hold the dependencies (flush freed the old one). 
5654     dependencies 
= OSArray::withCapacity(libraries
->getCount()); 
5655     if (!dependencies
) { 
5657             kOSKextLogErrorLevel 
| 
5658             kOSKextLogDependenciesFlag
, 
5659             "Kext %s - can't allocate dependencies array.", 
5660             getIdentifierCString()); 
5664     // xxx - compat: We used to add an implicit dependency on kernel 6.0 
5665     // xxx - compat: if none were declared. 
5667     libraryIterator 
= OSCollectionIterator::withCollection(libraries
); 
5668     if (!libraryIterator
) { 
5670             kOSKextLogErrorLevel 
| 
5671             kOSKextLogDependenciesFlag
, 
5672             "Kext %s - can't allocate dependencies iterator.", 
5673             getIdentifierCString()); 
5677     while ((libraryID 
= OSDynamicCast(OSString
, 
5678            libraryIterator
->getNextObject()))) { 
5680        const char * library_id 
= libraryID
->getCStringNoCopy(); 
5682         OSString 
* libraryVersion 
= OSDynamicCast(OSString
, 
5683             libraries
->getObject(libraryID
)); 
5684         if (libraryVersion 
== NULL
) { 
5686                 kOSKextLogErrorLevel 
| 
5687                 kOSKextLogValidationFlag 
| kOSKextLogDependenciesFlag
, 
5688                 "Kext %s - illegal type in OSBundleLibraries.", 
5689                 getIdentifierCString()); 
5693         OSKextVersion libraryVers 
= 
5694             OSKextParseVersionString(libraryVersion
->getCStringNoCopy()); 
5695         if (libraryVers 
== -1) { 
5697                 kOSKextLogErrorLevel 
| 
5698                 kOSKextLogValidationFlag 
| kOSKextLogDependenciesFlag
, 
5699                 "Kext %s - invalid library version %s.", 
5700                 getIdentifierCString(), 
5701                 libraryVersion
->getCStringNoCopy()); 
5705         libraryKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
)); 
5706         if (libraryKext 
== NULL
) { 
5708                 kOSKextLogErrorLevel 
| 
5709                 kOSKextLogDependenciesFlag
, 
5710                 "Kext %s - library kext %s not found.", 
5711                 getIdentifierCString(), library_id
); 
5715         if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) { 
5717                 kOSKextLogErrorLevel 
| 
5718                 kOSKextLogDependenciesFlag
, 
5719                 "Kext %s - library kext %s not compatible " 
5720                 "with requested version %s.", 
5721                 getIdentifierCString(), library_id
, 
5722                 libraryVersion
->getCStringNoCopy()); 
5726         if (!libraryKext
->resolveDependencies(loopStack
)) { 
5730        /* Add the library directly only if it has an executable to link. 
5731         * Otherwise it's just used to collect other dependencies, so put 
5732         * *its* dependencies on the list for this kext. 
5734         // xxx - We are losing info here; would like to make fake entries or 
5735         // xxx - keep these in the dependency graph for loaded kexts. 
5736         // xxx - I really want to make kernel components not a special case! 
5737         if (libraryKext
->declaresExecutable() || 
5738             libraryKext
->isInterface()) { 
5740             if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) { 
5741                 dependencies
->setObject(libraryKext
); 
5744                     kOSKextLogDetailLevel 
| 
5745                     kOSKextLogDependenciesFlag
, 
5746                     "Kext %s added dependency %s.", 
5747                     getIdentifierCString(), 
5748                     libraryKext
->getIdentifierCString()); 
5751             int       numLibDependencies  
= libraryKext
->getNumDependencies(); 
5752             OSArray 
* libraryDependencies 
= libraryKext
->getDependencies(); 
5755             if (numLibDependencies
) { 
5756                 // xxx - this msg level should be 1 lower than the per-kext one 
5758                     kOSKextLogDetailLevel 
| 
5759                     kOSKextLogDependenciesFlag
, 
5760                     "Kext %s pulling %d dependencies from codeless library %s.", 
5761                     getIdentifierCString(), 
5763                     libraryKext
->getIdentifierCString()); 
5765             for (index 
= 0; index 
< numLibDependencies
; index
++) { 
5766                 OSKext 
* thisLibDependency 
= OSDynamicCast(OSKext
, 
5767                     libraryDependencies
->getObject(index
)); 
5768                 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) { 
5769                     dependencies
->setObject(thisLibDependency
); 
5771                         kOSKextLogDetailLevel 
| 
5772                         kOSKextLogDependenciesFlag
, 
5773                         "Kext %s added dependency %s from codeless library %s.", 
5774                         getIdentifierCString(), 
5775                         thisLibDependency
->getIdentifierCString(), 
5776                         libraryKext
->getIdentifierCString()); 
5781         if ((strlen(library_id
) == strlen(KERNEL_LIB
)) && 
5782             0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) { 
5784             hasRawKernelDependency 
= true; 
5785         } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) { 
5786             hasKernelDependency 
= true; 
5787         } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) { 
5788             hasKPIDependency 
= true; 
5789             if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) { 
5790                 hasPrivateKPIDependency 
= true; 
5796     if (hasRawKernelDependency 
|| hasKernelDependency
) { 
5798             kOSKextLogErrorLevel 
| 
5799             kOSKextLogValidationFlag 
| kOSKextLogDependenciesFlag
, 
5800             "Error - kext %s declares %s dependencies. " 
5801             "Only %s* dependencies are supported for 64-bit kexts.", 
5802             getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
); 
5805     if (!hasKPIDependency
) { 
5807             kOSKextLogWarningLevel 
| 
5808             kOSKextLogDependenciesFlag
, 
5809             "Warning - kext %s declares no %s* dependencies. " 
5810             "If it uses any KPIs, the link may fail with undefined symbols.", 
5811             getIdentifierCString(), KPI_LIB_PREFIX
); 
5813 #else /* __LP64__ */ 
5814     // xxx - will change to flatly disallow "kernel" dependencies at some point 
5815     // xxx - is it invalid to do both "com.apple.kernel" and any 
5816     // xxx - "com.apple.kernel.*"? 
5818     if (hasRawKernelDependency 
&& hasKernelDependency
) { 
5820             kOSKextLogErrorLevel 
| 
5821             kOSKextLogValidationFlag 
| kOSKextLogDependenciesFlag
, 
5822             "Error - kext %s declares dependencies on both " 
5824             getIdentifierCString(), KERNEL_LIB
, KERNEL6_LIB
); 
5828     if ((hasRawKernelDependency 
|| hasKernelDependency
) && hasKPIDependency
) { 
5830             kOSKextLogWarningLevel 
| 
5831             kOSKextLogDependenciesFlag
, 
5832             "Warning - kext %s has immediate dependencies on both " 
5833             "%s* and %s* components; use only one style.", 
5834             getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
); 
5837     if (!hasRawKernelDependency 
&& !hasKernelDependency 
&& !hasKPIDependency
) { 
5838         // xxx - do we want to use validation flag for these too? 
5840             kOSKextLogWarningLevel 
| 
5841             kOSKextLogDependenciesFlag
, 
5842             "Warning - %s declares no kernel dependencies; using %s.", 
5843             getIdentifierCString(), KERNEL6_LIB
); 
5844         OSKext 
* kernelKext 
= OSDynamicCast(OSKext
, 
5845             sKextsByID
->getObject(KERNEL6_LIB
)); 
5847             dependencies
->setObject(kernelKext
); 
5850                 kOSKextLogErrorLevel 
| 
5851                 kOSKextLogDependenciesFlag
, 
5852                 "Error - Library %s not found for %s.", 
5853                 KERNEL6_LIB
, getIdentifierCString()); 
5857    /* If the kext doesn't have a raw kernel or KPI dependency, then add all of 
5858     * its indirect dependencies to simulate old-style linking.  XXX - Should 
5859     * check for duplicates. 
5861     if (!hasRawKernelDependency 
&& !hasKPIDependency
) { 
5864         count 
= getNumDependencies(); 
5866        /* We add to the dependencies array in this loop, but do not iterate 
5867         * past its original count. 
5869         for (i 
= 0; i 
< count
; i
++) { 
5870             OSKext 
* dependencyKext 
= OSDynamicCast(OSKext
, 
5871                 dependencies
->getObject(i
)); 
5872             dependencyKext
->addBleedthroughDependencies(dependencies
); 
5875 #endif /* __LP64__ */ 
5877     if (hasPrivateKPIDependency
) { 
5878         bool hasApplePrefix 
= false; 
5879         bool infoCopyrightIsValid 
= false; 
5880         bool readableCopyrightIsValid 
= false; 
5882         hasApplePrefix 
= STRING_HAS_PREFIX(getIdentifierCString(),  
5885         infoString 
= OSDynamicCast(OSString
,   
5886             getPropertyForHostArch("CFBundleGetInfoString")); 
5888             infoCopyrightIsValid 
=  
5889                 kxld_validate_copyright_string(infoString
->getCStringNoCopy()); 
5892         readableString 
= OSDynamicCast(OSString
, 
5893             getPropertyForHostArch("NSHumanReadableCopyright")); 
5894         if (readableString
) { 
5895             readableCopyrightIsValid 
=  
5896                 kxld_validate_copyright_string(readableString
->getCStringNoCopy()); 
5899         if (!hasApplePrefix 
|| (!infoCopyrightIsValid 
&& !readableCopyrightIsValid
)) { 
5901                 kOSKextLogErrorLevel 
| 
5902                 kOSKextLogDependenciesFlag
, 
5903                 "Error - kext %s declares a dependency on %s. " 
5904                   "Only Apple kexts may declare a dependency on %s.", 
5905                   getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
); 
5911     flags
.hasAllDependencies 
= 1; 
5915     if (addedToLoopStack
) { 
5916         count 
= loopStack
->getCount(); 
5917         if (count 
> 0 && (this == loopStack
->getObject(count 
- 1))) { 
5918             loopStack
->removeObject(count 
- 1);             
5921                 kOSKextLogErrorLevel 
| 
5922                 kOSKextLogDependenciesFlag
, 
5923                 "Kext %s - internal error resolving dependencies.", 
5924                 getIdentifierCString()); 
5928     if (result 
&& localLoopStack
) { 
5930             kOSKextLogStepLevel 
| 
5931             kOSKextLogDependenciesFlag
, 
5932             "Kext %s successfully resolved dependencies.", 
5933             getIdentifierCString()); 
5936     OSSafeRelease(localLoopStack
); 
5937     OSSafeRelease(libraryIterator
); 
5942 /********************************************************************* 
5943 *********************************************************************/ 
5945 OSKext::addBleedthroughDependencies(OSArray 
* anArray
) 
5947     bool result 
= false; 
5948     unsigned int dependencyIndex
, dependencyCount
; 
5950     dependencyCount 
= getNumDependencies(); 
5952     for (dependencyIndex 
= 0; 
5953          dependencyIndex 
< dependencyCount
; 
5954          dependencyIndex
++) { 
5956         OSKext 
* dependency 
= OSDynamicCast(OSKext
, 
5957             dependencies
->getObject(dependencyIndex
)); 
5960                 kOSKextLogErrorLevel 
| 
5961                 kOSKextLogDependenciesFlag
, 
5962                 "Kext %s - internal error propagating compatibility dependencies.", 
5963                 getIdentifierCString()); 
5966         if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) { 
5967             anArray
->setObject(dependency
); 
5969         dependency
->addBleedthroughDependencies(anArray
); 
5978 /********************************************************************* 
5979 *********************************************************************/ 
5981 OSKext::flushDependencies(bool forceFlag
) 
5983     bool result 
= false; 
5985    /* Only clear the dependencies if the kext isn't loaded; 
5986     * we need the info for loaded kexts to track references. 
5988     if (!isLoaded() || forceFlag
) { 
5990             // xxx - check level 
5992                 kOSKextLogProgressLevel 
| 
5993                 kOSKextLogDependenciesFlag
, 
5994                 "Kext %s flushing dependencies.", 
5995                 getIdentifierCString()); 
5996             OSSafeReleaseNULL(dependencies
); 
5999         if (!isKernelComponent()) { 
6000             flags
.hasAllDependencies 
= 0; 
6008 /********************************************************************* 
6009 *********************************************************************/ 
6011 OSKext::getNumDependencies(void) 
6013     if (!dependencies
) { 
6016     return dependencies
->getCount(); 
6019 /********************************************************************* 
6020 *********************************************************************/ 
6022 OSKext::getDependencies(void) 
6024     return dependencies
; 
6028 #pragma mark OSMetaClass Support 
6030 /********************************************************************* 
6031 *********************************************************************/ 
6034     OSMetaClass 
* aClass
, 
6035     uint32_t      numClasses
) 
6037     OSReturn result 
= kOSMetaClassNoInsKModSet
; 
6040         metaClasses 
= OSSet::withCapacity(numClasses
); 
6046     if (metaClasses
->containsObject(aClass
)) { 
6048             kOSKextLogWarningLevel 
| 
6050             "Notice - kext %s has already registered class %s.", 
6051             getIdentifierCString(), 
6052             aClass
->getClassName()); 
6053         result 
= kOSReturnSuccess
; 
6057     if (!metaClasses
->setObject(aClass
)) { 
6061             kOSKextLogDetailLevel 
| 
6063             "Kext %s registered class %s.", 
6064             getIdentifierCString(), 
6065             aClass
->getClassName()); 
6068     if (!flags
.autounloadEnabled
) { 
6069         const OSMetaClass 
* metaScan  
= NULL
;  // do not release 
6071         for (metaScan 
= aClass
; metaScan
; metaScan 
= metaScan
->getSuperClass()) { 
6072             if (metaScan 
== OSTypeID(IOService
)) { 
6075                     kOSKextLogProgressLevel 
| 
6077                     "Kext %s has IOService subclass %s; enabling autounload.", 
6078                     getIdentifierCString(), 
6079                     aClass
->getClassName()); 
6081                 flags
.autounloadEnabled 
= 1; 
6087     result 
= kOSReturnSuccess
; 
6090     if (result 
!= kOSReturnSuccess
) { 
6092             kOSKextLogErrorLevel 
| 
6094             "Kext %s failed to register class %s.", 
6095             getIdentifierCString(), 
6096             aClass
->getClassName()); 
6102 /********************************************************************* 
6103 *********************************************************************/ 
6105 OSKext::removeClass( 
6106     OSMetaClass 
* aClass
) 
6108     OSReturn result 
= kOSMetaClassNoKModSet
; 
6114     if (!metaClasses
->containsObject(aClass
)) { 
6116             kOSKextLogWarningLevel 
| 
6118             "Notice - kext %s asked to unregister unknown class %s.", 
6119             getIdentifierCString(), 
6120             aClass
->getClassName()); 
6121         result 
= kOSReturnSuccess
; 
6126         kOSKextLogDetailLevel 
| 
6128         "Kext %s unregistering class %s.", 
6129         getIdentifierCString(), 
6130         aClass
->getClassName()); 
6132     metaClasses
->removeObject(aClass
); 
6134     result 
= kOSReturnSuccess
; 
6137     if (result 
!= kOSReturnSuccess
) { 
6139             kOSKextLogErrorLevel 
| 
6141             "Failed to unregister kext %s class %s.", 
6142             getIdentifierCString(), 
6143             aClass
->getClassName()); 
6148 /********************************************************************* 
6149 *********************************************************************/ 
6151 OSKext::getMetaClasses(void) 
6156 /********************************************************************* 
6157 *********************************************************************/ 
6159 OSKext::hasOSMetaClassInstances(void) 
6161     bool                   result        
= false; 
6162     OSCollectionIterator 
* classIterator 
= NULL
;  // must release 
6163     OSMetaClass          
* checkClass    
= NULL
;  // do not release 
6169     classIterator 
= OSCollectionIterator::withCollection(metaClasses
); 
6170     if (!classIterator
) { 
6171         // xxx - log alloc failure? 
6174     while ((checkClass 
= (OSMetaClass 
*)classIterator
->getNextObject())) { 
6175         if (checkClass
->getInstanceCount()) { 
6183     OSSafeRelease(classIterator
); 
6187 /********************************************************************* 
6188 *********************************************************************/ 
6191 OSKext::reportOSMetaClassInstances( 
6192     const char     * kextIdentifier
, 
6193     OSKextLogSpec    msgLogSpec
) 
6195     OSKext 
* theKext 
= NULL
; // must release 
6197     theKext 
= OSKext::lookupKextWithIdentifier(kextIdentifier
); 
6202     theKext
->reportOSMetaClassInstances(msgLogSpec
); 
6204     OSSafeRelease(theKext
); 
6208 /********************************************************************* 
6209 *********************************************************************/ 
6211 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
) 
6213     OSCollectionIterator 
* classIterator 
= NULL
;  // must release 
6214     OSMetaClass          
* checkClass    
= NULL
;  // do not release 
6220     classIterator 
= OSCollectionIterator::withCollection(metaClasses
); 
6221     if (!classIterator
) { 
6224     while ((checkClass 
= (OSMetaClass 
*)classIterator
->getNextObject())) { 
6225         if (checkClass
->getInstanceCount()) { 
6228                 "    Kext %s class %s has %d instance%s.", 
6229                 getIdentifierCString(), 
6230                 checkClass
->getClassName(), 
6231                 checkClass
->getInstanceCount(), 
6232                 checkClass
->getInstanceCount() == 1 ? "" : "s"); 
6237     OSSafeRelease(classIterator
); 
6242 #pragma mark User-Space Requests 
6244 /********************************************************************* 
6245 * XXX - this function is a big ugly mess 
6246 *********************************************************************/ 
6249 OSKext::handleRequest( 
6250     host_priv_t     hostPriv
, 
6251     OSKextLogSpec   clientLogFilter
, 
6252     char          * requestBuffer
, 
6253     uint32_t        requestLength
, 
6254     char         ** responseOut
, 
6255     uint32_t      * responseLengthOut
, 
6257     uint32_t      * logInfoLengthOut
) 
6259     OSReturn       result             
= kOSReturnError
; 
6260     kern_return_t  kmem_result        
= KERN_FAILURE
; 
6262     char         * response           
= NULL
;  // returned by reference 
6263     uint32_t       responseLength     
= 0; 
6265     OSObject     
* parsedXML      
= NULL
;  // must release 
6266     OSDictionary 
* requestDict        
= NULL
;  // do not release 
6267     OSString     
* errorString        
= NULL
;  // must release 
6269     OSData       
* responseData       
= NULL
;  // must release 
6270     OSObject     
* responseObject 
= NULL
;  // must release 
6272     OSSerialize  
* serializer         
= NULL
;  // must release 
6274     OSArray      
* logInfoArray       
= NULL
;  // must release 
6276     OSString     
* predicate          
= NULL
;  // do not release 
6277     OSString     
* kextIdentifier     
= NULL
;  // do not release 
6278     OSArray      
* kextIdentifiers    
= NULL
;  // do not release 
6279     OSKext       
* theKext            
= NULL
;  // do not release 
6280     OSBoolean    
* boolArg            
= NULL
;  // do not release 
6282     IORecursiveLockLock(sKextLock
); 
6285         *responseOut 
= NULL
; 
6286         *responseLengthOut 
= 0; 
6290         *logInfoLengthOut 
= 0; 
6293     OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut 
? true : false); 
6295    /* XML must be nul-terminated. 
6297     if (requestBuffer
[requestLength 
- 1] != '\0') { 
6298         OSKextLog(/* kext */ NULL
, 
6299             kOSKextLogErrorLevel 
| 
6301             "Invalid request from user space (not nul-terminated)."); 
6302         result 
= kOSKextReturnBadData
; 
6305     parsedXML 
= OSUnserializeXML((const char *)requestBuffer
, &errorString
); 
6307         requestDict 
= OSDynamicCast(OSDictionary
, parsedXML
); 
6310         const char * errorCString 
= "(unknown error)"; 
6312         if (errorString 
&& errorString
->getCStringNoCopy()) { 
6313             errorCString 
= errorString
->getCStringNoCopy(); 
6314         } else if (parsedXML
) { 
6315             errorCString 
= "not a dictionary"; 
6317         OSKextLog(/* kext */ NULL
, 
6318             kOSKextLogErrorLevel 
| 
6320             "Error unserializing request from user space: %s.", 
6322         result 
= kOSKextReturnSerialization
; 
6326     predicate 
= _OSKextGetRequestPredicate(requestDict
); 
6328         OSKextLog(/* kext */ NULL
, 
6329             kOSKextLogErrorLevel 
| 
6331             "Recieved kext request from user space with no predicate."); 
6332         result 
= kOSKextReturnInvalidArgument
; 
6336     OSKextLog(/* kext */ NULL
, 
6337         kOSKextLogDebugLevel 
| 
6339         "Received '%s' request from user space.", 
6340         predicate
->getCStringNoCopy()); 
6342     result 
= kOSKextReturnNotPrivileged
; 
6343     if (hostPriv 
== HOST_PRIV_NULL
) { 
6344         if (!predicate
->isEqualTo(kKextRequestPredicateGetLoaded
) && 
6345             !predicate
->isEqualTo(kKextRequestPredicateGetKernelLinkState
) && 
6346             !predicate
->isEqualTo(kKextRequestPredicateGetKernelLoadAddress
)) { 
6352    /* Get common args in anticipation of use. 
6354     kextIdentifier 
= OSDynamicCast(OSString
, _OSKextGetRequestArgument( 
6355         requestDict
, kKextRequestArgumentBundleIdentifierKey
)); 
6356     kextIdentifiers 
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument( 
6357         requestDict
, kKextRequestArgumentBundleIdentifierKey
)); 
6358     if (kextIdentifier
) { 
6359         theKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
)); 
6361     boolArg 
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument( 
6362         requestDict
, kKextRequestArgumentValueKey
)); 
6364     result 
= kOSKextReturnInvalidArgument
; 
6366     if (predicate
->isEqualTo(kKextRequestPredicateStart
)) { 
6367         if (!kextIdentifier
) { 
6368             OSKextLog(/* kext */ NULL
, 
6369                 kOSKextLogErrorLevel 
| 
6371                 "Invalid arguments to kext start request."); 
6372         } else if (!theKext
) { 
6373             OSKextLog(/* kext */ NULL
, 
6374                 kOSKextLogErrorLevel 
| 
6376                 "Kext %s not found for start request.", 
6377                 kextIdentifier
->getCStringNoCopy()); 
6378             result 
= kOSKextReturnNotFound
; 
6380             result 
= theKext
->start(); 
6383     } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) { 
6384         if (!kextIdentifier
) { 
6385             OSKextLog(/* kext */ NULL
, 
6386                 kOSKextLogErrorLevel 
| 
6388                 "Invalid arguments to kext stop request."); 
6389         } else if (!theKext
) { 
6390             OSKextLog(/* kext */ NULL
, 
6391                 kOSKextLogErrorLevel 
| 
6393                 "Kext %s not found for stop request.", 
6394                 kextIdentifier
->getCStringNoCopy()); 
6395             result 
= kOSKextReturnNotFound
; 
6397             result 
= theKext
->stop(); 
6400     } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) { 
6401         if (!kextIdentifier
) { 
6402             OSKextLog(/* kext */ NULL
, 
6403                 kOSKextLogErrorLevel 
| 
6405                 "Invalid arguments to kext unload request."); 
6406         } else if (!theKext
) { 
6407             OSKextLog(/* kext */ NULL
, 
6408                 kOSKextLogErrorLevel 
| 
6410                 "Kext %s not found for unload request.", 
6411                 kextIdentifier
->getCStringNoCopy()); 
6412             result 
= kOSKextReturnNotFound
; 
6414             OSBoolean 
* terminateFlag 
= OSDynamicCast(OSBoolean
, 
6415                 _OSKextGetRequestArgument(requestDict
, 
6416                     kKextRequestArgumentTerminateIOServicesKey
)); 
6417             result 
= OSKext::removeKext(theKext
, terminateFlag 
== kOSBooleanTrue
); 
6420     } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) { 
6421         result 
= OSKext::dispatchResource(requestDict
); 
6423     } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) { 
6424         OSBoolean 
* delayAutounloadBool 
= NULL
; 
6426         delayAutounloadBool 
= OSDynamicCast(OSBoolean
, 
6427             _OSKextGetRequestArgument(requestDict
, 
6428                 kKextRequestArgumentDelayAutounloadKey
)); 
6430        /* If asked to delay autounload, reset the timer if it's currently set. 
6431         * (That is, don't schedule an unload if one isn't already pending. 
6433         if (delayAutounloadBool 
== kOSBooleanTrue
) { 
6434             OSKext::considerUnloads(/* rescheduleOnly? */ true); 
6437         responseObject 
= OSDynamicCast(OSObject
, 
6438             OSKext::copyLoadedKextInfo(kextIdentifiers
)); 
6439         if (!responseObject
) { 
6440             result 
= kOSKextReturnInternalError
; 
6442             OSKextLog(/* kext */ NULL
, 
6443                 kOSKextLogDebugLevel 
| 
6445                 "Returning loaded kext info."); 
6446             result 
= kOSReturnSuccess
; 
6449     } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelLoadAddress
)) { 
6450         OSNumber 
* addressNum 
= NULL
;  // released as responseObject 
6451         kernel_segment_command_t 
* textseg 
= getsegbyname("__TEXT"); 
6454             OSKextLog(/* kext */ NULL
, 
6455                 kOSKextLogErrorLevel 
| 
6456                 kOSKextLogGeneralFlag 
| kOSKextLogIPCFlag
, 
6457                 "Can't find text segment for kernel load address."); 
6458             result 
= kOSReturnError
; 
6462         OSKextLog(/* kext */ NULL
, 
6463             kOSKextLogDebugLevel 
| 
6465             "Returning kernel load address 0x%llx.", 
6466             (unsigned long long)textseg
->vmaddr
); 
6467         addressNum 
= OSNumber::withNumber((long long unsigned int)textseg
->vmaddr
, 
6468             8 * sizeof(long long unsigned int)); 
6469         responseObject 
= OSDynamicCast(OSObject
, addressNum
); 
6470         result 
= kOSReturnSuccess
; 
6472     } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelLinkState
)) { 
6473         OSKextLog(/* kext */ NULL
, 
6474             kOSKextLogDebugLevel 
| 
6476             "Returning kernel link state."); 
6477         responseData 
= sKernelKext
->linkState
; 
6478         responseData
->retain(); 
6479         result 
= kOSReturnSuccess
; 
6481     } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) { 
6483        /* Hand the current sKernelRequests array to the caller 
6484         * (who must release it), and make a new one. 
6486         responseObject 
= OSDynamicCast(OSObject
, sKernelRequests
); 
6487         sKernelRequests 
= OSArray::withCapacity(0); 
6488         sPostedKextLoadIdentifiers
->flushCollection(); 
6489         OSKextLog(/* kext */ NULL
, 
6490             kOSKextLogDebugLevel 
| 
6492             "Returning kernel requests."); 
6493         result 
= kOSReturnSuccess
; 
6495     } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) { 
6497         /* Return the set of all requested bundle identifiers */ 
6498         responseObject 
= OSDynamicCast(OSObject
, sAllKextLoadIdentifiers
); 
6499         responseObject
->retain(); 
6500         OSKextLog(/* kext */ NULL
, 
6501             kOSKextLogDebugLevel 
| 
6503             "Returning load requests."); 
6504         result 
= kOSReturnSuccess
; 
6508     * Now we have handle the request, or not. Gather up the response & logging 
6509     * info to ship to user space. 
6512    /* Note: Nothing in OSKext is supposed to retain requestDict, 
6513     * but you never know.... 
6515     if (requestDict
->getRetainCount() > 1) { 
6516         OSKextLog(/* kext */ NULL
, 
6517             kOSKextLogWarningLevel 
| 
6519             "Request from user space still retained by a kext; " 
6520             "probable memory leak."); 
6523     if (responseData 
&& responseObject
) { 
6524         OSKextLog(/* kext */ NULL
, 
6525             kOSKextLogErrorLevel 
| 
6527             "Mistakenly generated both data & plist responses to user request " 
6528             "(returning only data)."); 
6531     if (responseData 
&& responseData
->getLength() && responseOut
) { 
6533         response 
= (char *)responseData
->getBytesNoCopy(); 
6534         responseLength 
= responseData
->getLength(); 
6535     } else if (responseOut 
&& responseObject
) { 
6536         serializer 
= OSSerialize::withCapacity(0); 
6538             result 
= kOSKextReturnNoMemory
; 
6542         if (!responseObject
->serialize(serializer
)) { 
6543             OSKextLog(/* kext */ NULL
, 
6544                 kOSKextLogErrorLevel 
| 
6546                 "Failed to serialize response to request from user space."); 
6547             result 
= kOSKextReturnSerialization
; 
6551         response 
= (char *)serializer
->text(); 
6552         responseLength 
= serializer
->getLength(); 
6555     if (responseOut 
&& response
) { 
6558        /* This kmem_alloc sets the return value of the function. 
6560         kmem_result 
= kmem_alloc(kernel_map
, (vm_offset_t 
*)&buffer
, 
6562         if (kmem_result 
!= KERN_SUCCESS
) { 
6563             OSKextLog(/* kext */ NULL
, 
6564                 kOSKextLogErrorLevel 
| 
6566                 "Failed to copy response to request from user space."); 
6567             result 
= kmem_result
; 
6570             memcpy(buffer
, response
, responseLength
); 
6571             *responseOut 
= buffer
; 
6572             *responseLengthOut 
= responseLength
; 
6578    /* Gather up the collected log messages for user space. Any messages 
6579     * messages past this call will not make it up as log messages but 
6580     * will be in the system log. Note that we ignore the return of the 
6581     * serialize; it has no bearing on the operation at hand even if we 
6582     * fail to get the log messages. 
6584     logInfoArray 
= OSKext::clearUserSpaceLogFilter(); 
6586     if (logInfoArray 
&& logInfoOut 
&& logInfoLengthOut
) { 
6587         (void)OSKext::serializeLogInfo(logInfoArray
, 
6588             logInfoOut
, logInfoLengthOut
); 
6591     IORecursiveLockUnlock(sKextLock
); 
6593     OSSafeRelease(requestDict
); 
6594     OSSafeRelease(errorString
); 
6595     OSSafeRelease(responseData
); 
6596     OSSafeRelease(responseObject
); 
6597     OSSafeRelease(serializer
); 
6598     OSSafeRelease(logInfoArray
); 
6603 /********************************************************************* 
6604 *********************************************************************/ 
6607 OSKext::copyLoadedKextInfo(OSArray 
* kextIdentifiers
) 
6609     OSArray      
* result 
= NULL
; 
6610     OSDictionary 
* kextInfo 
= NULL
;  // must release 
6612     uint32_t       idCount 
= 0; 
6613     uint32_t       idIndex 
= 0; 
6615     IORecursiveLockLock(sKextLock
); 
6617    /* Empty list of bundle ids is equivalent to no list (get all). 
6619     if (kextIdentifiers 
&& !kextIdentifiers
->getCount()) { 
6620         kextIdentifiers 
= NULL
; 
6621     } else if (kextIdentifiers
) { 
6622         idCount 
= kextIdentifiers
->getCount(); 
6625     count 
= sLoadedKexts
->getCount(); 
6626     result 
= OSArray::withCapacity(count
); 
6630     for (i 
= 0; i 
< count
; i
++) { 
6631         OSKext   
* thisKext     
= NULL
;  // do not release 
6632         Boolean    includeThis  
= true; 
6635             kextInfo
->release(); 
6638         thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
6643        /* Skip current kext if we have a list of bundle IDs and 
6644         * it isn't in the list. 
6646         if (kextIdentifiers
) { 
6647             const OSString 
* thisKextID 
= thisKext
->getIdentifier(); 
6649             includeThis 
= false; 
6651             for (idIndex 
= 0; idIndex 
< idCount
; idIndex
++) { 
6652                 const OSString 
* thisRequestID 
= OSDynamicCast(OSString
, 
6653                     kextIdentifiers
->getObject(idIndex
)); 
6654                 if (thisKextID
->isEqualTo(thisRequestID
)) { 
6665         kextInfo 
= thisKext
->copyInfo(); 
6666         result
->setObject(kextInfo
); 
6670     IORecursiveLockUnlock(sKextLock
); 
6672     if (kextInfo
) kextInfo
->release(); 
6677 /********************************************************************* 
6686 Dependency Load Tags 
6687 # Dependent References 
6690 *********************************************************************/ 
6691 #define _OSKextLoadInfoDictCapacity   (12) 
6694 OSKext::copyInfo(void) 
6696     OSDictionary         
* result             
= NULL
; 
6697     bool                   success            
= false; 
6698     OSNumber             
* cpuTypeNumber      
= NULL
;  // must release 
6699     OSNumber             
* cpuSubtypeNumber   
= NULL
;  // must release 
6700     OSString             
* versionString      
= NULL
;  // do not release 
6701     OSData               
* uuid               
= NULL
;  // must release 
6702     OSNumber             
* scratchNumber      
= NULL
;  // must release 
6703     OSArray              
* dependencyLoadTags 
= NULL
;  // must release 
6704     OSCollectionIterator 
* metaClassIterator  
= NULL
;  // must release 
6705     OSArray              
* metaClassInfo      
= NULL
;  // must release 
6706     OSDictionary         
* metaClassDict      
= NULL
;  // must release 
6707     OSMetaClass          
* thisMetaClass      
= NULL
;  // do not release 
6708     OSString             
* metaClassName      
= NULL
;  // must release 
6709     OSString             
* superclassName     
= NULL
;  // must release 
6712     result 
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
); 
6717    /* CPU Type & Subtype. 
6718     * Use the CPU type of the kernel for all (loaded) kexts. 
6719     * xxx - should we not include this for the kernel components, 
6720     * xxx - or for any interface? they have mach-o files, they're just weird. 
6722     if (linkedExecutable 
|| (this == sKernelKext
)) { 
6724         cpuTypeNumber 
= OSNumber::withNumber( 
6725             (long long unsigned int)_mh_execute_header
.cputype
, 
6726             8 * sizeof(_mh_execute_header
.cputype
)); 
6727         if (cpuTypeNumber
) { 
6728             result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
); 
6732     // I don't want to rely on a mach header for nonkernel kexts, yet 
6733     if (this == sKernelKext
) { 
6734         cpuSubtypeNumber 
= OSNumber::withNumber( 
6735             (long long unsigned int)_mh_execute_header
.cputype
, 
6736             8 * sizeof(_mh_execute_header
.cputype
)); 
6737         if (cpuSubtypeNumber
) { 
6738             result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
); 
6742    /* CFBundleIdentifier. 
6744     result
->setObject(kCFBundleIdentifierKey
, bundleID
); 
6748     versionString 
= OSDynamicCast(OSString
, 
6749         getPropertyForHostArch(kCFBundleVersionKey
)); 
6750     if (versionString
) { 
6751         result
->setObject(kCFBundleVersionKey
, versionString
); 
6754    /* OSBundleCompatibleVersion. 
6756     versionString 
= OSDynamicCast(OSString
, 
6757         getPropertyForHostArch(kOSBundleCompatibleVersionKey
)); 
6758     if (versionString
) { 
6759         result
->setObject(kOSBundleCompatibleVersionKey
, versionString
); 
6765         result
->setObject(kOSBundlePathKey
, path
); 
6772         result
->setObject(kOSBundleUUIDKey
, uuid
); 
6776     * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted. 
6778     result
->setObject(kOSKernelResourceKey
, 
6779         isKernelComponent() ? kOSBooleanTrue 
: kOSBooleanFalse
); 
6781     result
->setObject(kOSBundleIsInterfaceKey
, 
6782         isInterface() ? kOSBooleanTrue 
: kOSBooleanFalse
); 
6784     result
->setObject(kOSBundlePrelinkedKey
, 
6785         isPrelinked() ? kOSBooleanTrue 
: kOSBooleanFalse
); 
6787     result
->setObject(kOSBundleStartedKey
, 
6788         isStarted() ? kOSBooleanTrue 
: kOSBooleanFalse
); 
6792     scratchNumber 
= OSNumber::withNumber((unsigned long long)loadTag
, 
6793         /* numBits */ 8 * sizeof(loadTag
)); 
6794     if (scratchNumber
) { 
6795         result
->setObject(kOSBundleLoadTagKey
, scratchNumber
); 
6796         OSSafeReleaseNULL(scratchNumber
); 
6799    /* LoadAddress, LoadSize. 
6801     if (isInterface() || linkedExecutable
) { 
6802        /* These go to userspace via serialization, so we don't want any doubts 
6805         uint64_t    loadAddress 
= 0; 
6806         uint32_t    loadSize    
= 0; 
6807         uint32_t    wiredSize   
= 0; 
6809        /* Interfaces always report 0 load address & size. 
6810         * Just the way they roll. 
6812         * xxx - leaving in # when we have a linkedExecutable...a kernelcomp 
6813         * xxx - shouldn't have one! 
6815         if (linkedExecutable 
/* && !isInterface() */) { 
6816             loadAddress 
= (uint64_t)linkedExecutable
->getBytesNoCopy(); 
6817             loadSize 
= linkedExecutable
->getLength(); 
6819            /* If we have a kmod_info struct, calculated the wired size 
6820             * from that. Otherwise it's the full load size. 
6823                 wiredSize 
= loadSize 
- kmod_info
->hdr_size
; 
6825                 wiredSize 
= loadSize
; 
6829         scratchNumber 
= OSNumber::withNumber( 
6830             (unsigned long long)(loadAddress
), 
6831             /* numBits */ 8 * sizeof(loadAddress
)); 
6832         if (scratchNumber
) { 
6833             result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
); 
6834             OSSafeReleaseNULL(scratchNumber
); 
6836         scratchNumber 
= OSNumber::withNumber( 
6837             (unsigned long long)(loadSize
), 
6838             /* numBits */ 8 * sizeof(loadSize
)); 
6839         if (scratchNumber
) { 
6840             result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
); 
6841             OSSafeReleaseNULL(scratchNumber
); 
6843         scratchNumber 
= OSNumber::withNumber( 
6844             (unsigned long long)(wiredSize
), 
6845             /* numBits */ 8 * sizeof(wiredSize
)); 
6846         if (scratchNumber
) { 
6847             result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
); 
6848             OSSafeReleaseNULL(scratchNumber
); 
6852    /* OSBundleDependencies. In descending order for 
6853     * easy compatibility with kextstat(8). 
6855     if ((count 
= getNumDependencies())) { 
6856         dependencyLoadTags 
= OSArray::withCapacity(count
); 
6857         result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
); 
6861             OSKext 
* dependency 
= OSDynamicCast(OSKext
, 
6862                 dependencies
->getObject(i
)); 
6864             OSSafeReleaseNULL(scratchNumber
); 
6869             scratchNumber 
= OSNumber::withNumber( 
6870                 (unsigned long long)dependency
->getLoadTag(), 
6871                 /* numBits*/ 8 * sizeof(loadTag
)); 
6872             if (scratchNumber
) { 
6873                 dependencyLoadTags
->setObject(scratchNumber
); 
6878     OSSafeReleaseNULL(scratchNumber
); 
6880    /* OSBundleMetaClasses. 
6882     if (metaClasses 
&& metaClasses
->getCount()) { 
6883         metaClassIterator 
= OSCollectionIterator::withCollection(metaClasses
); 
6884         metaClassInfo 
= OSArray::withCapacity(metaClasses
->getCount()); 
6885         if (!metaClassIterator 
|| !metaClassInfo
) { 
6888         result
->setObject(kOSBundleClassesKey
, metaClassInfo
); 
6890         while ( (thisMetaClass 
= OSDynamicCast(OSMetaClass
, 
6891             metaClassIterator
->getNextObject())) ) { 
6893             OSSafeReleaseNULL(metaClassDict
); 
6894             OSSafeReleaseNULL(metaClassName
); 
6895             OSSafeReleaseNULL(superclassName
); 
6896             OSSafeReleaseNULL(scratchNumber
); 
6898             metaClassDict 
= OSDictionary::withCapacity(3); 
6899             if (!metaClassDict
) { 
6903             metaClassName 
= OSString::withCString(thisMetaClass
->getClassName()); 
6904             if (thisMetaClass
->getSuperClass()) { 
6905                 superclassName 
= OSString::withCString( 
6906                     thisMetaClass
->getSuperClass()->getClassName()); 
6908             scratchNumber 
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(), 
6909                 8 * sizeof(unsigned int)); 
6910             if (!metaClassDict 
|| !metaClassName 
|| !superclassName 
|| 
6916             metaClassInfo
->setObject(metaClassDict
); 
6917             metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
); 
6918             metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
); 
6919             metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
); 
6923    /* OSBundleRetainCount. 
6925     OSSafeReleaseNULL(scratchNumber
); 
6927         int extRetainCount 
= getRetainCount() - 1; 
6931         scratchNumber 
= OSNumber::withNumber( 
6932             (int)extRetainCount
, 
6933             /* numBits*/ 8 * sizeof(int)); 
6934         if (scratchNumber
) { 
6935             result
->setObject(kOSBundleRetainCountKey
, scratchNumber
); 
6941     OSSafeRelease(cpuTypeNumber
); 
6942     OSSafeRelease(cpuSubtypeNumber
); 
6943     OSSafeRelease(uuid
); 
6944     OSSafeRelease(scratchNumber
); 
6945     OSSafeRelease(dependencyLoadTags
); 
6946     OSSafeRelease(metaClassIterator
); 
6947     OSSafeRelease(metaClassInfo
); 
6948     OSSafeRelease(metaClassDict
); 
6949     OSSafeRelease(metaClassName
); 
6950     OSSafeRelease(superclassName
); 
6952         OSSafeReleaseNULL(result
); 
6957 /********************************************************************* 
6958 *********************************************************************/ 
6961 OSKext::requestResource( 
6962     const char                    * kextIdentifierCString
, 
6963     const char                    * resourceNameCString
, 
6964     OSKextRequestResourceCallback   callback
, 
6966     OSKextRequestTag              
* requestTagOut
) 
6968     OSReturn           result          
= kOSReturnError
; 
6969     OSKext           
* callbackKext    
= NULL
;  // must release (looked up) 
6971     OSKextRequestTag   requestTag      
= -1; 
6972     OSNumber         
* requestTagNum   
= NULL
;  // must release 
6974     OSDictionary     
* requestDict     
= NULL
;  // must release 
6975     OSString         
* kextIdentifier  
= NULL
;  // must release 
6976     OSString         
* resourceName    
= NULL
;  // must release 
6978     OSDictionary     
* callbackRecord  
= NULL
;  // must release 
6979     OSData           
* callbackWrapper 
= NULL
;  // must release 
6981     OSData           
* contextWrapper  
= NULL
;  // must release 
6983     IORecursiveLockLock(sKextLock
); 
6985     if (requestTagOut
) { 
6986         *requestTagOut 
= kOSKextRequestTagInvalid
; 
6989     if (!kextIdentifierCString 
|| !resourceNameCString 
|| !callback
) { 
6990         result 
= kOSKextReturnInvalidArgument
; 
6994     callbackKext 
= OSKext::lookupKextWithAddress((vm_address_t
)callback
); 
6995     if (!callbackKext
) { 
6996         OSKextLog(/* kext */ NULL
, 
6997             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
6998             "Resource request has bad callback address."); 
6999         result 
= kOSKextReturnInvalidArgument
; 
7002     if (!callbackKext
->flags
.starting 
&& !callbackKext
->flags
.started
) { 
7003         OSKextLog(/* kext */ NULL
, 
7004             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
7005             "Resource request callback is in a kext that is not started."); 
7006         result 
= kOSKextReturnInvalidArgument
; 
7010    /* Do not allow any new requests to be made on a kext that is unloading. 
7012     if (callbackKext
->flags
.stopping
) { 
7013         result 
= kOSKextReturnStopping
; 
7017    /* If we're wrapped the next available request tag around to the negative 
7018     * numbers, we can't service any more requests. 
7020     if (sNextRequestTag 
== kOSKextRequestTagInvalid
) { 
7021         OSKextLog(/* kext */ NULL
, 
7022             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
7023             "No more request tags available; restart required."); 
7024         result 
= kOSKextReturnNoResources
; 
7027     requestTag 
= sNextRequestTag
++; 
7029     result 
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
, 
7031     if (result 
!= kOSReturnSuccess
) { 
7035     kextIdentifier 
= OSString::withCString(kextIdentifierCString
); 
7036     resourceName   
= OSString::withCString(resourceNameCString
); 
7037     requestTagNum  
= OSNumber::withNumber((long long unsigned int)requestTag
, 
7038         8 * sizeof(requestTag
)); 
7039     if (!kextIdentifier 
|| 
7042         !_OSKextSetRequestArgument(requestDict
, 
7043             kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) || 
7044         !_OSKextSetRequestArgument(requestDict
, 
7045             kKextRequestArgumentNameKey
, resourceName
) || 
7046         !_OSKextSetRequestArgument(requestDict
, 
7047             kKextRequestArgumentRequestTagKey
, requestTagNum
)) { 
7049         result 
= kOSKextReturnNoMemory
; 
7053     callbackRecord 
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection()); 
7054     if (!callbackRecord
) { 
7055         result 
= kOSKextReturnNoMemory
; 
7058     // we validate callback address at call time 
7059     callbackWrapper 
= OSData::withBytes((void *)&callback
, sizeof(void *)); 
7061         contextWrapper 
= OSData::withBytes((void *)&context
, sizeof(void *)); 
7063     if (!callbackWrapper 
|| !_OSKextSetRequestArgument(callbackRecord
, 
7064             kKextRequestArgumentCallbackKey
, callbackWrapper
)) { 
7066         result 
= kOSKextReturnNoMemory
; 
7071         if (!contextWrapper 
|| !_OSKextSetRequestArgument(callbackRecord
, 
7072             kKextRequestArgumentContextKey
, contextWrapper
)) { 
7074             result 
= kOSKextReturnNoMemory
; 
7079    /* Only post the requests after all the other potential failure points 
7082     if (!sKernelRequests
->setObject(requestDict
) || 
7083         !sRequestCallbackRecords
->setObject(callbackRecord
)) { 
7085         result 
= kOSKextReturnNoMemory
; 
7091     result 
= kOSReturnSuccess
; 
7092     if (requestTagOut
) { 
7093         *requestTagOut 
= requestTag
; 
7098    /* If we didn't succeed, yank the request & callback 
7099     * from their holding arrays. 
7101     if (result 
!= kOSReturnSuccess
) { 
7104         index 
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0); 
7105         if (index 
!= (unsigned int)-1) { 
7106             sKernelRequests
->removeObject(index
); 
7108         index 
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0); 
7109         if (index 
!= (unsigned int)-1) { 
7110             sRequestCallbackRecords
->removeObject(index
); 
7114     OSKext::considerUnloads(/* rescheduleOnly? */ true); 
7116     IORecursiveLockUnlock(sKextLock
); 
7118     if (callbackKext
)    callbackKext
->release(); 
7119     if (requestTagNum
)   requestTagNum
->release(); 
7121     if (requestDict
)     requestDict
->release(); 
7122     if (kextIdentifier
)  kextIdentifier
->release(); 
7123     if (resourceName
)    resourceName
->release(); 
7125     if (callbackRecord
)  callbackRecord
->release(); 
7126     if (callbackWrapper
) callbackWrapper
->release(); 
7127     if (contextWrapper
)  contextWrapper
->release(); 
7132 /********************************************************************* 
7133 *********************************************************************/ 
7136 OSKext::dequeueCallbackForRequestTag( 
7137     OSKextRequestTag    requestTag
, 
7138     OSDictionary     
** callbackRecordOut
) 
7140     OSReturn   result 
= kOSReturnError
; 
7141     OSNumber 
* requestTagNum  
= NULL
;  // must release 
7143     requestTagNum  
= OSNumber::withNumber((long long unsigned int)requestTag
, 
7144         8 * sizeof(requestTag
)); 
7145     if (!requestTagNum
) { 
7149     result 
= OSKext::dequeueCallbackForRequestTag(requestTagNum
, 
7153     OSSafeRelease(requestTagNum
); 
7158 /********************************************************************* 
7159 *********************************************************************/ 
7162 OSKext::dequeueCallbackForRequestTag( 
7163     OSNumber     
*    requestTagNum
, 
7164     OSDictionary 
** callbackRecordOut
) 
7166     OSReturn        result          
= kOSKextReturnInvalidArgument
; 
7167     OSDictionary  
* callbackRecord  
= NULL
;  // retain if matched! 
7168     OSNumber      
* callbackTagNum  
= NULL
;  // do not release 
7169     unsigned int    count
, i
; 
7171     IORecursiveLockLock(sKextLock
); 
7173     result 
= kOSReturnError
; 
7174     count 
= sRequestCallbackRecords
->getCount(); 
7175     for (i 
= 0; i 
< count
; i
++) { 
7176         callbackRecord 
= OSDynamicCast(OSDictionary
, 
7177             sRequestCallbackRecords
->getObject(i
)); 
7178         if (!callbackRecord
) { 
7182        /* If we don't find a tag, we basically have a leak here. Maybe 
7183         * we should just remove it. 
7185         callbackTagNum 
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument( 
7186             callbackRecord
, kKextRequestArgumentRequestTagKey
)); 
7187         if (!callbackTagNum
) { 
7191        /* We could be even more paranoid and check that all the incoming 
7192         * args match what's in the callback record. 
7194         if (callbackTagNum
->isEqualTo(requestTagNum
)) { 
7195             if (callbackRecordOut
) { 
7196                 *callbackRecordOut 
= callbackRecord
; 
7197                 callbackRecord
->retain(); 
7199             sRequestCallbackRecords
->removeObject(i
); 
7200             result 
= kOSReturnSuccess
; 
7204     result 
= kOSKextReturnNotFound
; 
7207     IORecursiveLockUnlock(sKextLock
); 
7211 /********************************************************************* 
7212 *********************************************************************/ 
7215 OSKext::dispatchResource(OSDictionary 
* requestDict
) 
7217     OSReturn                        result          
= kOSReturnError
; 
7218     OSDictionary                  
* callbackRecord  
= NULL
;  // must release 
7219     OSNumber                      
* requestTag      
= NULL
;  // do not release 
7220     OSNumber                      
* requestResult   
= NULL
;  // do not release 
7221     OSData                        
* dataObj         
= NULL
;  // do not release 
7222     uint32_t                        dataLength      
= 0; 
7223     const void                    * dataPtr         
= NULL
;  // do not free 
7224     OSData                        
* callbackWrapper 
= NULL
;  // do not release 
7225     OSKextRequestResourceCallback   callback        
= NULL
; 
7226     OSData                        
* contextWrapper  
= NULL
;  // do not release 
7227     void                          * context         
= NULL
;  // do not free 
7228     OSKext                        
* callbackKext    
= NULL
;  // must release (looked up) 
7230     IORecursiveLockLock(sKextLock
); 
7232    /* Get the args from the request. Right now we need the tag 
7233     * to look up the callback record, and the result for invoking the callback. 
7235     requestTag 
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
, 
7236         kKextRequestArgumentRequestTagKey
)); 
7237     requestResult 
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
, 
7238         kKextRequestArgumentResultKey
)); 
7239     if (!requestTag 
|| !requestResult
) { 
7240         result 
= kOSKextReturnInvalidArgument
; 
7244    /* Look for a callback record matching this request's tag. 
7246     result 
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
); 
7247     if (result 
!= kOSReturnSuccess
) { 
7252     * Get the context pointer of the callback record (if there is one). 
7254     contextWrapper 
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
, 
7255         kKextRequestArgumentContextKey
)); 
7256     context 
= _OSKextExtractPointer(contextWrapper
); 
7257     if (contextWrapper 
&& !context
) { 
7261     callbackWrapper 
= OSDynamicCast(OSData
, 
7262         _OSKextGetRequestArgument(callbackRecord
, 
7263             kKextRequestArgumentCallbackKey
)); 
7264     callback 
= (OSKextRequestResourceCallback
) 
7265         _OSKextExtractPointer(callbackWrapper
); 
7270    /* Check for a data obj. We might not have one and that's ok, that means 
7271     * we didn't find the requested resource, and we still have to tell the 
7272     * caller that via the callback. 
7274     dataObj 
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
, 
7275         kKextRequestArgumentValueKey
)); 
7277         dataPtr 
= dataObj
->getBytesNoCopy(); 
7278         dataLength 
= dataObj
->getLength(); 
7281     callbackKext 
= OSKext::lookupKextWithAddress((vm_address_t
)callback
); 
7282     if (!callbackKext
) { 
7283         OSKextLog(/* kext */ NULL
, 
7284             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
7285             "Can't invoke callback for resource request; " 
7286             "no kext loaded at callback address %p.", 
7290     if (!callbackKext
->flags
.starting 
&& !callbackKext
->flags
.started
) { 
7291         OSKextLog(/* kext */ NULL
, 
7292             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
7293             "Can't invoke kext resource callback; " 
7294             "kext at callback address %p is not running.", 
7299     (void)callback(requestTag
->unsigned32BitValue(), 
7300         (OSReturn
)requestResult
->unsigned32BitValue(), 
7301         dataPtr
, dataLength
, context
); 
7303     result 
= kOSReturnSuccess
; 
7306     if (callbackKext
)   callbackKext
->release(); 
7307     if (callbackRecord
) callbackRecord
->release(); 
7309     IORecursiveLockUnlock(sKextLock
); 
7313 /********************************************************************* 
7314 *********************************************************************/ 
7317 OSKext::invokeRequestCallback( 
7318     OSDictionary 
* callbackRecord
, 
7319     OSReturn       callbackResult
) 
7321     OSString 
* predicate  
= _OSKextGetRequestPredicate(callbackRecord
); 
7322     OSNumber 
* resultNum  
= NULL
;  // must release 
7328     resultNum  
= OSNumber::withNumber((long long unsigned int)callbackResult
, 
7329         8 * sizeof(callbackResult
)); 
7334    /* Insert the result into the callback record and dispatch it as if it 
7335     * were the reply coming down from user space. 
7337     _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
, 
7340     if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) { 
7341        /* This removes the pending callback record. 
7343         OSKext::dispatchResource(callbackRecord
); 
7347     if (resultNum
) resultNum
->release(); 
7351 /********************************************************************* 
7352 *********************************************************************/ 
7355 OSKext::cancelRequest( 
7356     OSKextRequestTag    requestTag
, 
7359     OSReturn       result         
= kOSKextReturnNoMemory
; 
7360     OSDictionary 
* callbackRecord 
= NULL
;  // must release 
7361     OSData       
* contextWrapper 
= NULL
;  // do not release 
7363     result 
= OSKext::dequeueCallbackForRequestTag(requestTag
, 
7366     if (result 
== kOSReturnSuccess 
&& contextOut
) { 
7367         contextWrapper 
= OSDynamicCast(OSData
, 
7368             _OSKextGetRequestArgument(callbackRecord
, 
7369                 kKextRequestArgumentContextKey
)); 
7370         *contextOut 
= _OSKextExtractPointer(contextWrapper
); 
7373     if (callbackRecord
) callbackRecord
->release(); 
7378 /********************************************************************* 
7379 *********************************************************************/ 
7381 OSKext::invokeOrCancelRequestCallbacks( 
7382     OSReturn callbackResult
, 
7385     unsigned int count
, i
; 
7387     IORecursiveLockLock(sKextLock
); 
7389     count 
= sRequestCallbackRecords
->getCount(); 
7396         OSDictionary 
* request 
= OSDynamicCast(OSDictionary
, 
7397             sRequestCallbackRecords
->getObject(i
)); 
7402         OSData 
* callbackWrapper 
= OSDynamicCast(OSData
, 
7403             _OSKextGetRequestArgument(request
, 
7404                 kKextRequestArgumentCallbackKey
)); 
7406         if (!callbackWrapper
) { 
7407             sRequestCallbackRecords
->removeObject(i
); 
7411         vm_address_t callbackAddress 
= (vm_address_t
) 
7412             _OSKextExtractPointer(callbackWrapper
); 
7414         if ((kmod_info
->address 
<= callbackAddress
) && 
7415             (callbackAddress 
< (kmod_info
->address 
+ kmod_info
->size
))) { 
7418                /* This removes the callback record. 
7420                 invokeRequestCallback(request
, callbackResult
); 
7422                 sRequestCallbackRecords
->removeObject(i
); 
7428     IORecursiveLockUnlock(sKextLock
); 
7432 /********************************************************************* 
7433 *********************************************************************/ 
7435 OSKext::countRequestCallbacks(void) 
7437     uint32_t     result 
= 0; 
7438     unsigned int count
, i
; 
7440     IORecursiveLockLock(sKextLock
); 
7442     count 
= sRequestCallbackRecords
->getCount(); 
7449         OSDictionary 
* request 
= OSDynamicCast(OSDictionary
, 
7450             sRequestCallbackRecords
->getObject(i
)); 
7455         OSData 
* callbackWrapper 
= OSDynamicCast(OSData
, 
7456             _OSKextGetRequestArgument(request
, 
7457                 kKextRequestArgumentCallbackKey
)); 
7459         if (!callbackWrapper
) { 
7463         vm_address_t callbackAddress 
= (vm_address_t
) 
7464             _OSKextExtractPointer(callbackWrapper
); 
7466         if ((kmod_info
->address 
<= callbackAddress
) && 
7467             (callbackAddress 
< (kmod_info
->address 
+ kmod_info
->size
))) { 
7474     IORecursiveLockUnlock(sKextLock
); 
7478 /********************************************************************* 
7479 *********************************************************************/ 
7480 static OSReturn 
_OSKextCreateRequest( 
7481     const char    * predicate
, 
7482     OSDictionary 
** requestP
) 
7484     OSReturn result 
= kOSKextReturnNoMemory
; 
7485     OSDictionary 
* request 
= NULL
;  // must release on error 
7486     OSDictionary 
* args 
= NULL
;     // must release 
7488     request 
= OSDictionary::withCapacity(2); 
7492     result 
= _OSDictionarySetCStringValue(request
, 
7493         kKextRequestPredicateKey
, predicate
); 
7494     if (result 
!= kOSReturnSuccess
) { 
7497     result 
= kOSReturnSuccess
; 
7500     if (result 
!= kOSReturnSuccess
) { 
7501         if (request
) request
->release(); 
7503         *requestP 
= request
; 
7505     if (args
) args
->release(); 
7510 /********************************************************************* 
7511 *********************************************************************/ 
7512 static OSString 
* _OSKextGetRequestPredicate(OSDictionary 
* requestDict
) 
7514     return OSDynamicCast(OSString
, 
7515         requestDict
->getObject(kKextRequestPredicateKey
)); 
7518 /********************************************************************* 
7519 *********************************************************************/ 
7520 static OSObject 
* _OSKextGetRequestArgument( 
7521     OSDictionary 
* requestDict
, 
7522     const char   * argName
) 
7524     OSDictionary 
* args 
= OSDynamicCast(OSDictionary
, 
7525         requestDict
->getObject(kKextRequestArgumentsKey
)); 
7527         return args
->getObject(argName
); 
7532 /********************************************************************* 
7533 *********************************************************************/ 
7534 static bool _OSKextSetRequestArgument( 
7535     OSDictionary 
* requestDict
, 
7536     const char   * argName
, 
7539     OSDictionary 
* args 
= OSDynamicCast(OSDictionary
, 
7540         requestDict
->getObject(kKextRequestArgumentsKey
)); 
7542         args 
= OSDictionary::withCapacity(2); 
7546         requestDict
->setObject(kKextRequestArgumentsKey
, args
); 
7550         return args
->setObject(argName
, value
); 
7556 /********************************************************************* 
7557 *********************************************************************/ 
7558 static void * _OSKextExtractPointer(OSData 
* wrapper
) 
7560     void       * result 
= NULL
; 
7561     const void * resultPtr 
= NULL
; 
7566     resultPtr 
= wrapper
->getBytesNoCopy(); 
7567     result 
= *(void **)resultPtr
; 
7572 /********************************************************************* 
7573 *********************************************************************/ 
7574 static OSReturn 
_OSDictionarySetCStringValue( 
7575     OSDictionary 
* dict
, 
7577     const char   * cValue
) 
7579     OSReturn result 
= kOSKextReturnNoMemory
; 
7580     const OSSymbol 
* key 
= NULL
;  // must release 
7581     OSString 
* value 
= NULL
;  // must release 
7583     key 
= OSSymbol::withCString(cKey
); 
7584     value 
= OSString::withCString(cValue
); 
7585     if (!key 
|| !value
) { 
7588     if (dict
->setObject(key
, value
)) { 
7589         result 
= kOSReturnSuccess
; 
7593     if (key
)   key
->release(); 
7594     if (value
) value
->release(); 
7600 #pragma mark Personalities (IOKit Drivers) 
7602 /********************************************************************* 
7603 *********************************************************************/ 
7606 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
) 
7608     OSArray              
* result                
= NULL
;  // returned 
7609     OSCollectionIterator 
* kextIterator          
= NULL
;  // must release 
7610     OSArray              
* personalities         
= NULL
;  // must release 
7611     OSCollectionIterator 
* personalitiesIterator 
= NULL
;  // must release 
7613     OSString             
* kextID                
= NULL
;  // do not release 
7614     OSKext               
* theKext               
= NULL
;  // do not release 
7616     IORecursiveLockLock(sKextLock
); 
7618    /* Let's conservatively guess that any given kext has around 3 
7619     * personalities for now. 
7621     result 
= OSArray::withCapacity(sKextsByID
->getCount() * 3); 
7626     kextIterator 
= OSCollectionIterator::withCollection(sKextsByID
); 
7627     if (!kextIterator
) { 
7631     while ((kextID 
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) { 
7632         if (personalitiesIterator
) { 
7633             personalitiesIterator
->release(); 
7634             personalitiesIterator 
= NULL
; 
7636         if (personalities
) { 
7637             personalities
->release(); 
7638             personalities 
= NULL
; 
7641         theKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
)); 
7642         if (!sSafeBoot 
|| !filterSafeBootFlag 
|| theKext
->isLoadableInSafeBoot()) { 
7643             personalities 
= theKext
->copyPersonalitiesArray(); 
7644             if (!personalities
) { 
7647             result
->merge(personalities
); 
7649             // xxx - check for better place to put this log msg 
7651                 kOSKextLogWarningLevel 
| 
7653                 "Kext %s is not loadable during safe boot; " 
7654                 "omitting its personalities.", 
7655                 theKext
->getIdentifierCString()); 
7661     IORecursiveLockUnlock(sKextLock
); 
7663     if (kextIterator
)          kextIterator
->release(); 
7664     if (personalitiesIterator
) personalitiesIterator
->release(); 
7665     if (personalities
)         personalities
->release(); 
7670 /********************************************************************* 
7671 *********************************************************************/ 
7674 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
) 
7676     int numPersonalities 
= 0; 
7678     OSKextLog(/* kext */ NULL
, 
7679         kOSKextLogStepLevel 
| 
7681         "Sending all eligible registered kexts' personalities " 
7682         "to the IOCatalogue %s.", 
7683         startMatching 
? "and starting matching" : "but not starting matching"); 
7685     OSArray 
* personalities 
= OSKext::copyAllKextPersonalities( 
7686         /* filterSafeBootFlag */ true); 
7688     if (personalities
) { 
7689         gIOCatalogue
->addDrivers(personalities
, startMatching
); 
7690         numPersonalities 
= personalities
->getCount(); 
7691         personalities
->release(); 
7694     OSKextLog(/* kext */ NULL
, 
7695         kOSKextLogStepLevel 
| 
7697         "%d kext personalit%s sent to the IOCatalogue; %s.", 
7698         numPersonalities
, numPersonalities 
> 0 ? "ies" : "y", 
7699         startMatching 
? "matching started" : "matching not started"); 
7703 /********************************************************************* 
7704 * Do not make a deep copy, just convert the IOKitPersonalities dict 
7705 * to an array for sending to the IOCatalogue. 
7706 *********************************************************************/ 
7708 OSKext::copyPersonalitiesArray(void) 
7710     OSArray              
* result                      
= NULL
; 
7711     OSDictionary         
* personalities               
= NULL
;  // do not release 
7712     OSCollectionIterator 
* personalitiesIterator       
= NULL
;  // must release 
7714     OSString             
* personalityName             
= NULL
;  // do not release     
7715     OSString             
* personalityBundleIdentifier 
= NULL
;  // do not release 
7717     personalities 
= OSDynamicCast(OSDictionary
, 
7718         getPropertyForHostArch(kIOKitPersonalitiesKey
)); 
7719     if (!personalities
) { 
7723     result 
= OSArray::withCapacity(personalities
->getCount()); 
7728     personalitiesIterator 
= 
7729         OSCollectionIterator::withCollection(personalities
); 
7730     if (!personalitiesIterator
) { 
7733     while ((personalityName 
= OSDynamicCast(OSString
, 
7734             personalitiesIterator
->getNextObject()))) { 
7736         OSDictionary 
* personality 
= OSDynamicCast(OSDictionary
, 
7737             personalities
->getObject(personalityName
)); 
7740         * If the personality doesn't have a CFBundleIdentifier, or if it 
7741         * differs from the kext's, insert the kext's ID so we can find it. 
7742         * The publisher ID is used to remove personalities from bundles 
7745         personalityBundleIdentifier 
= OSDynamicCast(OSString
, 
7746             personality
->getObject(kCFBundleIdentifierKey
)); 
7748         if (!personalityBundleIdentifier
) { 
7749             personality
->setObject(kCFBundleIdentifierKey
, bundleID
); 
7750         } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) { 
7751             personality
->setObject(kIOPersonalityPublisherKey
, bundleID
); 
7754         result
->setObject(personality
); 
7758     if (personalitiesIterator
) personalitiesIterator
->release(); 
7763 /********************************************************************* 
7764 Might want to change this to a bool return? 
7765 *********************************************************************/ 
7767 OSKext::sendPersonalitiesToCatalog( 
7769     OSArray 
* personalityNames
) 
7771     OSArray      
* personalitiesToSend     
= NULL
;  // must release 
7772     OSDictionary 
* kextPersonalities 
= NULL
;  // do not release 
7775     if (sSafeBoot 
&& !isLoadableInSafeBoot()) { 
7777             kOSKextLogErrorLevel 
| 
7779             "Kext %s is not loadable during safe boot; " 
7780             "not sending personalities to the IOCatalogue.", 
7781             getIdentifierCString()); 
7785     if (!personalityNames 
|| !personalityNames
->getCount()) { 
7786         personalitiesToSend 
= copyPersonalitiesArray(); 
7788         kextPersonalities 
= OSDynamicCast(OSDictionary
, 
7789             getPropertyForHostArch(kIOKitPersonalitiesKey
)); 
7790         if (!kextPersonalities 
|| !kextPersonalities
->getCount()) { 
7793         personalitiesToSend 
= OSArray::withCapacity(0); 
7794         if (!personalitiesToSend
) { 
7797         count 
= personalityNames
->getCount(); 
7798         for (i 
= 0; i 
< count
; i
++) { 
7799             OSString 
* name 
= OSDynamicCast(OSString
, 
7800                 personalityNames
->getObject(i
)); 
7804             OSDictionary 
* personality 
= OSDynamicCast(OSDictionary
, 
7805                 kextPersonalities
->getObject(name
)); 
7807                 personalitiesToSend
->setObject(personality
); 
7811     if (personalitiesToSend
) { 
7812         unsigned numPersonalities 
= personalitiesToSend
->getCount(); 
7814             kOSKextLogStepLevel 
| 
7816             "Kext %s sending %d personalit%s to the IOCatalogue%s.", 
7817             getIdentifierCString(), 
7819             numPersonalities 
> 1 ? "ies" : "y", 
7820             startMatching 
? " and starting matching" : " but not starting matching"); 
7821         gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
); 
7824     if (personalitiesToSend
) { 
7825         personalitiesToSend
->release(); 
7830 /********************************************************************* 
7831 *********************************************************************/ 
7833 OSKext::removePersonalitiesFromCatalog(void) 
7835     OSDictionary 
* personality 
= NULL
;   // do not release 
7837     personality 
= OSDictionary::withCapacity(1); 
7841     personality
->setObject(kCFBundleIdentifierKey
, getIdentifier()); 
7844         kOSKextLogStepLevel 
| 
7846         "Kext %s removing all personalities naming it from the IOCatalogue.", 
7847         getIdentifierCString()); 
7849    /* Have the IOCatalog remove all personalities matching this kext's 
7850     * bundle ID and trigger matching anew. 
7852     gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true); 
7855     if (personality
) personality
->release(); 
7862 #pragma mark Logging 
7864 /********************************************************************* 
7865 * Do not call any function that takes sKextLock here! 
7866 *********************************************************************/ 
7869 OSKext::setUserSpaceLogFilter( 
7870     OSKextLogSpec   userLogFilter
, 
7873     OSKextLogSpec result
; 
7875     IORecursiveLockLock(sKextInnerLock
); 
7877     result 
= sUserSpaceKextLogFilter
; 
7878     sUserSpaceKextLogFilter 
= userLogFilter
; 
7880    /* If the config flag itself is changing, log the state change 
7881     * going both ways, before setting up the user-space log arrays, 
7882     * so that this is only logged in the kernel. 
7884     if (sUserSpaceKextLogFilter 
!= result
) { 
7885         OSKextLog(/* kext */ NULL
, 
7886             kOSKextLogDebugLevel 
| 
7887             kOSKextLogGeneralFlag
, 
7888             "User-space log flags changed from 0x%x to 0x%x.", 
7889             result
, sUserSpaceKextLogFilter
); 
7892     if (userLogFilter 
&& captureFlag 
&& 
7893         !sUserSpaceLogSpecArray 
&& !sUserSpaceLogMessageArray
) { 
7895         // xxx - do some measurements for a good initial capacity? 
7896         sUserSpaceLogSpecArray 
= OSArray::withCapacity(0); 
7897         sUserSpaceLogMessageArray 
= OSArray::withCapacity(0); 
7899         if (!sUserSpaceLogSpecArray 
|| !sUserSpaceLogMessageArray
) { 
7900             OSKextLog(/* kext */ NULL
, 
7901                 kOSKextLogErrorLevel 
| 
7902                 kOSKextLogGeneralFlag
, 
7903                 "Failed to allocate user-space log message arrays."); 
7904             OSSafeReleaseNULL(sUserSpaceLogSpecArray
); 
7905             OSSafeReleaseNULL(sUserSpaceLogMessageArray
); 
7909     IORecursiveLockUnlock(sKextInnerLock
); 
7914 /********************************************************************* 
7915 * Do not call any function that takes sKextLock here! 
7916 *********************************************************************/ 
7919 OSKext::clearUserSpaceLogFilter(void) 
7921     OSArray        
* result        
= NULL
; 
7922     OSKextLogSpec   oldLogFilter
; 
7924     IORecursiveLockLock(sKextInnerLock
); 
7926     result 
= OSArray::withCapacity(2); 
7928         result
->setObject(sUserSpaceLogSpecArray
); 
7929         result
->setObject(sUserSpaceLogMessageArray
); 
7931     OSSafeReleaseNULL(sUserSpaceLogSpecArray
); 
7932     OSSafeReleaseNULL(sUserSpaceLogMessageArray
); 
7934     oldLogFilter 
= sUserSpaceKextLogFilter
; 
7935     sUserSpaceKextLogFilter 
= kOSKextLogSilentFilter
; 
7937    /* If the config flag itself is changing, log the state change 
7938     * going both ways, after tearing down the user-space log 
7939     * arrays, so this is only logged within the kernel. 
7941     if (oldLogFilter 
!= sUserSpaceKextLogFilter
) { 
7942         OSKextLog(/* kext */ NULL
, 
7943             kOSKextLogDebugLevel 
| 
7944             kOSKextLogGeneralFlag
, 
7945             "User-space log flags changed from 0x%x to 0x%x.", 
7946             oldLogFilter
, sUserSpaceKextLogFilter
); 
7949     IORecursiveLockUnlock(sKextInnerLock
); 
7954 /********************************************************************* 
7955 * Do not call any function that takes sKextLock here! 
7956 *********************************************************************/ 
7959 OSKext::getUserSpaceLogFilter(void) 
7961     OSKextLogSpec result
; 
7963     IORecursiveLockLock(sKextInnerLock
); 
7964     result 
= sUserSpaceKextLogFilter
; 
7965     IORecursiveLockUnlock(sKextInnerLock
); 
7970 /********************************************************************* 
7971 * This function is called by OSMetaClass during kernel C++ setup. 
7972 * Be careful what you access here; assume only OSKext::initialize() 
7975 * Do not call any function that takes sKextLock here! 
7976 *********************************************************************/ 
7977 #define VTRESET   "\033[0m" 
7979 #define VTBOLD    "\033[1m" 
7980 #define VTUNDER   "\033[4m" 
7982 #define VTRED     "\033[31m" 
7983 #define VTGREEN   "\033[32m" 
7984 #define VTYELLOW  "\033[33m" 
7985 #define VTBLUE    "\033[34m" 
7986 #define VTMAGENTA "\033[35m" 
7987 #define VTCYAN    "\033[36m" 
7989 inline const char * colorForFlags(OSKextLogSpec flags
) 
7991     OSKextLogSpec logLevel 
= flags 
& kOSKextLogLevelMask
; 
7994     case kOSKextLogErrorLevel
: 
7995         return VTRED VTBOLD
; 
7997     case kOSKextLogWarningLevel
: 
8000     case kOSKextLogBasicLevel
: 
8001         return VTYELLOW VTUNDER
; 
8003     case kOSKextLogProgressLevel
: 
8006     case kOSKextLogStepLevel
: 
8009     case kOSKextLogDetailLevel
: 
8012     case kOSKextLogDebugLevel
: 
8022 inline bool logSpecMatch( 
8023     OSKextLogSpec msgLogSpec
, 
8024     OSKextLogSpec logFilter
) 
8026     OSKextLogSpec filterKextGlobal  
= logFilter 
& kOSKextLogKextOrGlobalMask
; 
8027     OSKextLogSpec filterLevel       
= logFilter 
& kOSKextLogLevelMask
; 
8028     OSKextLogSpec filterFlags       
= logFilter 
& kOSKextLogFlagsMask
; 
8030     OSKextLogSpec msgKextGlobal    
= msgLogSpec 
& kOSKextLogKextOrGlobalMask
; 
8031     OSKextLogSpec msgLevel         
= msgLogSpec 
& kOSKextLogLevelMask
; 
8032     OSKextLogSpec msgFlags         
= msgLogSpec 
& kOSKextLogFlagsMask
; 
8034    /* Explicit messages always get logged. 
8036     if (msgLevel 
== kOSKextLogExplicitLevel
) { 
8040    /* Warnings and errors are logged regardless of the flags. 
8042     if (msgLevel 
<= kOSKextLogBasicLevel 
&& (msgLevel 
<= filterLevel
)) { 
8046    /* A verbose message that isn't for a logging-enabled kext and isn't global 
8047     * does *not* get logged. 
8049     if (!msgKextGlobal 
&& !filterKextGlobal
) { 
8053    /* Warnings and errors are logged regardless of the flags. 
8054     * All other messages must fit the flags and 
8055     * have a level at or below the filter. 
8058     if ((msgFlags 
& filterFlags
) && (msgLevel 
<= filterLevel
)) { 
8069     OSKextLogSpec    msgLogSpec
, 
8070     const char     * format
, ...) 
8074     va_start(argList
, format
); 
8075     OSKextVLog(aKext
, msgLogSpec
, format
, argList
); 
8082     OSKextLogSpec    msgLogSpec
, 
8083     const char     * format
, 
8086     extern int       disableConsoleOutput
; 
8088     bool             logForKernel       
= false; 
8089     bool             logForUser         
= false; 
8091     char             stackBuffer
[120]; 
8092     uint32_t         length            
= 0; 
8093     char           * allocBuffer       
= NULL
;         // must kfree 
8094     OSNumber       
* logSpecNum        
= NULL
;         // must release 
8095     OSString       
* logString         
= NULL
;         // must release 
8096     char           * buffer            
= stackBuffer
;  // do not free 
8098     IORecursiveLockLock(sKextInnerLock
); 
8100    /* Set the kext/global bit in the message spec if we have no 
8101     * kext or if the kext requests logging. 
8103     if (!aKext 
|| aKext
->flags
.loggingEnabled
) { 
8104         msgLogSpec 
= msgLogSpec 
| kOSKextLogKextOrGlobalMask
; 
8107     logForKernel 
= logSpecMatch(msgLogSpec
, sKernelLogFilter
); 
8108     if (sUserSpaceLogSpecArray 
&& sUserSpaceLogMessageArray
) { 
8109         logForUser 
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
); 
8112     if (! (logForKernel 
|| logForUser
) ) { 
8116    /* No goto from here until past va_end()! 
8118     va_copy(argList
, srcArgList
); 
8119     length 
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
); 
8122     if (length 
+ 1 >= sizeof(stackBuffer
)) { 
8123         allocBuffer 
= (char *)kalloc((length 
+ 1) * sizeof(char)); 
8128        /* No goto from here until past va_end()! 
8130         va_copy(argList
, srcArgList
); 
8131         vsnprintf(allocBuffer
, length 
+ 1, format
, argList
); 
8134         buffer 
= allocBuffer
; 
8137    /* If user space wants the log message, queue it up. 
8139     if (logForUser 
&& sUserSpaceLogSpecArray 
&& sUserSpaceLogMessageArray
) { 
8140         logSpecNum 
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
)); 
8141         logString 
= OSString::withCString(buffer
); 
8142         if (logSpecNum 
&& logString
) { 
8143             sUserSpaceLogSpecArray
->setObject(logSpecNum
); 
8144             sUserSpaceLogMessageArray
->setObject(logString
); 
8148    /* Always log messages from the kernel according to the kernel's 
8153        /* If we are in console mode and have a custom log filter, 
8154         * colorize the log message. 
8156         if (!disableConsoleOutput 
&& sBootArgLogFilterFound
) { 
8157             const char * color 
= "";  // do not free 
8158             color 
= colorForFlags(msgLogSpec
); 
8159             printf("%s%s%s\n", colorForFlags(msgLogSpec
), 
8160                 buffer
, color
[0] ? VTRESET 
: ""); 
8162             printf("%s\n", buffer
); 
8168         kfree(allocBuffer
, (length 
+ 1) * sizeof(char)); 
8170     OSSafeRelease(logString
); 
8171     OSSafeRelease(logSpecNum
); 
8172     IORecursiveLockUnlock(sKextInnerLock
); 
8179 #pragma mark Backtrace Dump & kmod_get_info() support 
8181 /********************************************************************* 
8182 *********************************************************************/ 
8185 OSKext::printKextsInBacktrace( 
8188     int         (* printf_func
)(const char *fmt
, ...), 
8191     vm_offset_t      
* kscan_addr 
= NULL
; 
8192     kmod_info_t      
* k 
= NULL
; 
8193     kmod_reference_t 
* r 
= NULL
; 
8198         IORecursiveLockLock(sKextLock
); 
8201     for (k 
= kmod
; k
; k 
= k
->next
) { 
8202         if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)k
)) == 0) { 
8203             (*printf_func
)("         kmod scan stopped due to missing " 
8204                 "kmod page: %p\n", k
); 
8208             continue; // skip fake entries for built-in kernel components 
8210         for (i 
= 0, kscan_addr 
= addr
; i 
< cnt
; i
++, kscan_addr
++) { 
8211             if ((*kscan_addr 
>= k
->address
) && 
8212                 (*kscan_addr 
< (k
->address 
+ k
->size
))) { 
8215                     (*printf_func
)("      Kernel Extensions in backtrace " 
8216                         "(with dependencies):\n"); 
8219                 (*printf_func
)("         %s(%s)@%p->%p\n", 
8220                     k
->name
, k
->version
, k
->address
, k
->address 
+ k
->size 
- 1); 
8222                 for (r 
= k
->reference_list
; r
; r 
= r
->next
) { 
8223                     kmod_info_t 
* rinfo
; 
8225                     if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)r
)) == 0) { 
8226                         (*printf_func
)("            kmod dependency scan stopped " 
8227                             "due to missing dependency page: %p\n", r
); 
8233                     if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) { 
8234                         (*printf_func
)("            kmod dependency scan stopped " 
8235                             "due to missing kmod page: %p\n", rinfo
); 
8239                     if (!rinfo
->address
) { 
8240                         continue; // skip fake entries for built-ins 
8243                     (*printf_func
)("            dependency: %s(%s)@%p\n", 
8244                         rinfo
->name
, rinfo
->version
, rinfo
->address
); 
8247                 break;  // only report this kmod for one backtrace address 
8253         IORecursiveLockUnlock(sKextLock
); 
8259 /******************************************************************************* 
8260 * substitute() looks at an input string (a pointer within a larger buffer) 
8261 * for a match to a substring, and on match it writes the marker & substitution 
8262 * character to an output string, updating the scan (from) and 
8263 * output (to) indexes as appropriate. 
8264 *******************************************************************************/ 
8265 static int substitute( 
8266     const char * scan_string
, 
8268     uint32_t   * to_index
, 
8269     uint32_t   * from_index
, 
8270     const char * substring
, 
8274 /* string_out must be at least KMOD_MAX_NAME bytes. 
8278     const char * scan_string
, 
8280     uint32_t   * to_index
, 
8281     uint32_t   * from_index
, 
8282     const char * substring
, 
8286     uint32_t substring_length 
= strnlen(substring
, KMOD_MAX_NAME 
- 1); 
8288    /* On a substring match, append the marker (if there is one) and then 
8289     * the substitution character, updating the output (to) index accordingly. 
8290     * Then update the input (from) length by the length of the substring 
8291     * that got replaced. 
8293     if (!strncmp(scan_string
, substring
, substring_length
)) { 
8295             string_out
[(*to_index
)++] = marker
; 
8297         string_out
[(*to_index
)++] = substitution
; 
8298         (*from_index
) += substring_length
; 
8304 /******************************************************************************* 
8305 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least 
8306 * KMOD_MAX_NAME characters and performs various substitutions of common 
8307 * prefixes & substrings as defined by tables in kext_panic_report.h. 
8308 *******************************************************************************/ 
8309 static void compactIdentifier( 
8310     const char * identifier
, 
8311     char       * identifier_out
, 
8312     char      ** identifier_out_end
); 
8316     const char * identifier
, 
8317     char       * identifier_out
, 
8318     char      ** identifier_out_end
) 
8320     uint32_t       from_index
, to_index
; 
8321     uint32_t       scan_from_index 
= 0; 
8322     uint32_t       scan_to_index   
= 0; 
8323     subs_entry_t 
* subs_entry    
= NULL
; 
8326     from_index 
= to_index 
= 0; 
8327     identifier_out
[0] = '\0'; 
8329    /* Replace certain identifier prefixes with shorter @+character sequences. 
8330     * Check the return value of substitute() so we only replace the prefix. 
8332     for (subs_entry 
= &kext_identifier_prefix_subs
[0]; 
8333          subs_entry
->substring 
&& !did_sub
; 
8336         did_sub 
= substitute(identifier
, identifier_out
, 
8337             &scan_to_index
, &scan_from_index
, 
8338             subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
); 
8342    /* Now scan through the identifier looking for the common substrings 
8343     * and replacing them with shorter !+character sequences via substitute(). 
8345     for (/* see above */; 
8346          scan_from_index 
< KMOD_MAX_NAME 
- 1 && identifier
[scan_from_index
]; 
8349         const char   * scan_string 
= &identifier
[scan_from_index
]; 
8353         if (scan_from_index
) { 
8354             for (subs_entry 
= &kext_identifier_substring_subs
[0]; 
8355                  subs_entry
->substring 
&& !did_sub
; 
8358                 did_sub 
= substitute(scan_string
, identifier_out
, 
8359                     &scan_to_index
, &scan_from_index
, 
8360                     subs_entry
->substring
, '!', subs_entry
->substitute
); 
8364        /* If we didn't substitute, copy the input character to the output. 
8367             identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++]; 
8371     identifier_out
[scan_to_index
] = '\0'; 
8372     if (identifier_out_end
) { 
8373         *identifier_out_end 
= &identifier_out
[scan_to_index
]; 
8379 /******************************************************************************* 
8380 * assemble_identifier_and_version() adds to a string buffer a compacted 
8381 * bundle identifier followed by a version string. 
8382 *******************************************************************************/ 
8384 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length. 
8386 static int assemble_identifier_and_version( 
8387     kmod_info_t 
* kmod_info
,  
8388     char        * identPlusVers
); 
8390 assemble_identifier_and_version( 
8391     kmod_info_t 
* kmod_info
,  
8392     char        * identPlusVers
) 
8396     compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
); 
8397     result 
= strnlen(identPlusVers
, KMOD_MAX_NAME 
- 1); 
8398     identPlusVers
[result
++] = '\t';  // increment for real char 
8399     identPlusVers
[result
] = '\0';    // don't increment for nul char 
8400     result 
= strlcat(identPlusVers
, kmod_info
->version
, KMOD_MAX_NAME
); 
8405 /******************************************************************************* 
8406 *******************************************************************************/ 
8407 #define LAST_LOADED " - last loaded " 
8408 #define LAST_LOADED_TS_WIDTH  (16) 
8412 OSKext::saveLoadedKextPanicListTyped( 
8413     const char * prefix
, 
8418     uint32_t   * list_length_ptr
) 
8420     uint32_t      result 
= 0; 
8422     unsigned int  count
, i
; 
8424     count 
= sLoadedKexts
->getCount(); 
8431         OSKext      
* theKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
8432         kmod_info_t 
* kmod_info 
= theKext
->kmod_info
; 
8434         char          identPlusVers
[2*KMOD_MAX_NAME
]; 
8435         uint32_t      identPlusVersLength
; 
8436         char          timestampBuffer
[17]; // enough for a uint64_t 
8438        /* Skip all built-in kexts. 
8440         if (theKext
->isKernelComponent()) { 
8444        /* Filter for kmod name (bundle identifier). 
8446         match 
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
)); 
8447         if ((match 
&& invertFlag
) || (!match 
&& !invertFlag
)) { 
8451        /* Filter for libraries (kexts that have a compatible version). 
8453         if ((libsFlag 
== 0 && theKext
->getCompatibleVersion() > 1) || 
8454             (libsFlag 
== 1 && theKext
->getCompatibleVersion() < 1)) { 
8460             !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) { 
8462             printf("kext scan stopped due to missing kmod_info page: %p\n", 
8468         identPlusVersLength 
= assemble_identifier_and_version(kmod_info
, 
8470         if (!identPlusVersLength
) { 
8471             printf("error saving loaded kext info\n"); 
8475        /* We're going to note the last-loaded kext in the list. 
8477         if (i 
+ 1 == count
) { 
8478             snprintf(timestampBuffer
, sizeof(timestampBuffer
), "%llu", 
8479                 AbsoluteTime_to_scalar(&last_loaded_timestamp
)); 
8480             identPlusVersLength 
+= sizeof(LAST_LOADED
) - 1 + 
8481                 strnlen(timestampBuffer
, sizeof(timestampBuffer
)); 
8484        /* Adding 1 for the newline. 
8486         if (*list_length_ptr 
+ identPlusVersLength 
+ 1 >= list_size
) { 
8490         *list_length_ptr 
= strlcat(paniclist
, identPlusVers
, list_size
); 
8491         if (i 
+ 1 == count
) { 
8492             *list_length_ptr 
= strlcat(paniclist
, LAST_LOADED
, list_size
); 
8493             *list_length_ptr 
= strlcat(paniclist
, timestampBuffer
, list_size
); 
8495         *list_length_ptr 
= strlcat(paniclist
, "\n", list_size
); 
8501         if (*list_length_ptr 
+ 1 <= list_size
) { 
8502             result 
= list_size 
- (*list_length_ptr 
+ 1); 
8509 /********************************************************************* 
8510 *********************************************************************/ 
8513 OSKext::saveLoadedKextPanicList(void) 
8515     char     * newlist        
= NULL
; 
8516     uint32_t   newlist_size   
= 0; 
8517     uint32_t   newlist_length 
= 0; 
8519     IORecursiveLockLock(sKextLock
); 
8522     newlist_size 
= KEXT_PANICLIST_SIZE
; 
8523     newlist 
= (char *)kalloc(newlist_size
); 
8526         OSKextLog(/* kext */ NULL
, 
8527             kOSKextLogErrorLevel 
| kOSKextLogGeneralFlag
, 
8528             "Couldn't allocate kext panic log buffer."); 
8534     // non-"com.apple." kexts 
8535     if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1, 
8536         /* libs? */ -1, newlist
, newlist_size
, &newlist_length
)) { 
8540     // "com.apple." nonlibrary kexts 
8541     if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 
8542         /* libs? */ 0, newlist
, newlist_size
, &newlist_length
)) { 
8546     // "com.apple." library kexts 
8547     if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 
8548         /* libs? */ 1, newlist
, newlist_size
, &newlist_length
)) { 
8553     if (loaded_kext_paniclist
) { 
8554         kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
); 
8556     loaded_kext_paniclist 
= newlist
; 
8557     loaded_kext_paniclist_size 
= newlist_size
; 
8558     loaded_kext_paniclist_length 
= newlist_length
; 
8561     IORecursiveLockUnlock(sKextLock
); 
8565 /********************************************************************* 
8566 *********************************************************************/ 
8569 OSKext::saveUnloadedKextPanicList(OSKext 
* aKext
) 
8571     char     * newlist        
= NULL
; 
8572     uint32_t   newlist_size   
= 0; 
8573     uint32_t   newlist_length 
= 0; 
8574     char       identPlusVers
[2*KMOD_MAX_NAME
]; 
8575     uint32_t   identPlusVersLength
; 
8577     if (!aKext
->kmod_info
) { 
8578         return;  // do not goto finish here b/c of lock 
8581     IORecursiveLockLock(sKextLock
); 
8583     clock_get_uptime(&last_unloaded_timestamp
); 
8584     last_unloaded_address 
= (void *)aKext
->kmod_info
->address
; 
8585     last_unloaded_size 
= aKext
->kmod_info
->size
; 
8588     identPlusVersLength 
= assemble_identifier_and_version(aKext
->kmod_info
, 
8590     if (!identPlusVersLength
) { 
8591         printf("error saving unloaded kext info\n"); 
8595     newlist_length 
= identPlusVersLength
; 
8596     newlist_size 
= newlist_length 
+ 1; 
8597     newlist 
= (char *)kalloc(newlist_size
); 
8600         printf("couldn't allocate kext panic log buffer\n"); 
8606     strlcpy(newlist
, identPlusVers
, newlist_size
); 
8608     if (unloaded_kext_paniclist
) { 
8609         kfree(unloaded_kext_paniclist
, unloaded_kext_paniclist_size
); 
8611     unloaded_kext_paniclist 
= newlist
; 
8612     unloaded_kext_paniclist_size 
= newlist_size
; 
8613     unloaded_kext_paniclist_length 
= newlist_length
; 
8616     IORecursiveLockUnlock(sKextLock
); 
8620 /********************************************************************* 
8621 *********************************************************************/ 
8623 #define __kLoadSizeEscape  "0x%lld" 
8625 #define __kLoadSizeEscape  "0x%ld" 
8626 #endif /* __LP64__ */ 
8630 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...)) 
8632     printf_func("unloaded kexts:\n"); 
8633     if (unloaded_kext_paniclist 
&& 
8634         pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) unloaded_kext_paniclist
) && 
8635         unloaded_kext_paniclist
[0]) { 
8638             "%.*s (addr %p, size " __kLoadSizeEscape 
") - last unloaded %llu\n", 
8639             unloaded_kext_paniclist_length
, unloaded_kext_paniclist
, 
8640             last_unloaded_address
, last_unloaded_size
, 
8641             AbsoluteTime_to_scalar(&last_unloaded_timestamp
)); 
8643         printf_func("(none)\n"); 
8645     printf_func("loaded kexts:\n"); 
8646     if (loaded_kext_paniclist 
&& 
8647         pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) && 
8648         loaded_kext_paniclist
[0]) { 
8650         printf_func("%.*s", loaded_kext_paniclist_length
, loaded_kext_paniclist
); 
8652         printf_func("(none)\n"); 
8657 /********************************************************************* 
8658 *********************************************************************/ 
8659 #if __ppc__ || __i386__ 
8662 OSKext::getKmodInfo( 
8663     kmod_info_array_t      
* kmodList
, 
8664     mach_msg_type_number_t 
* kmodCount
) 
8666     kern_return_t result 
= KERN_FAILURE
; 
8668     kmod_info_t 
* k
, * kmod_info_scan_ptr
; 
8669     kmod_reference_t 
* r
, * ref_scan_ptr
; 
8673     *kmodList 
= (kmod_info_t 
*)0; 
8676     IORecursiveLockLock(sKextLock
); 
8680         size 
+= sizeof(kmod_info_t
); 
8681         r 
= k
->reference_list
; 
8683             size 
+=sizeof(kmod_reference_t
); 
8689         result 
= KERN_SUCCESS
; 
8693     result 
= kmem_alloc(kernel_map
, &data
, size
); 
8694     if (result 
!= KERN_SUCCESS
) { 
8698    /* Copy each kmod_info struct sequentially into the data buffer. 
8699     * Set each struct's nonzero 'next' pointer back to itself as a sentinel; 
8700     * the kernel space address is used to match refs, and a zero 'next' flags 
8701     * the end of kmod_infos in the data buffer and the beginning of references. 
8704     kmod_info_scan_ptr 
= (kmod_info_t 
*)data
; 
8706         *kmod_info_scan_ptr 
= *k
; 
8708             kmod_info_scan_ptr
->next 
= k
; 
8710         kmod_info_scan_ptr
++; 
8714    /* Now add references after the kmod_info structs in the same buffer. 
8715     * Update each kmod_info with the ref_count so we can associate 
8716     * references with kmod_info structs. 
8719     ref_scan_ptr 
= (kmod_reference_t 
*)kmod_info_scan_ptr
; 
8720     kmod_info_scan_ptr 
= (kmod_info_t 
*)data
; 
8722         r 
= k
->reference_list
; 
8725            /* Note the last kmod_info in the data buffer has its next == 0. 
8726             * Since there can only be one like that,  
8727             * this case is handled by the caller. 
8734        /* Stuff the # of refs into the 'reference_list' field of the kmod_info 
8735         * struct for the client to interpret. 
8737         kmod_info_scan_ptr
->reference_list 
= (kmod_reference_t 
*)(long)ref_count
; 
8738         kmod_info_scan_ptr
++; 
8742     result 
= vm_map_copyin(kernel_map
, data
, size
, TRUE
, (vm_map_copy_t 
*)kmodList
); 
8743     if (result 
!= KERN_SUCCESS
) { 
8748     result 
= KERN_SUCCESS
; 
8751     IORecursiveLockUnlock(sKextLock
); 
8753     if (result 
!= KERN_SUCCESS 
&& data
) { 
8754         kmem_free(kernel_map
, data
, size
); 
8755         *kmodList 
= (kmod_info_t 
*)0; 
8760 #endif /* __ppc__ || __i386__ */ 
8762 #pragma mark MAC Framework Support 
8764 /********************************************************************* 
8765 *********************************************************************/ 
8766 #if CONFIG_MACF_KEXT 
8767 /* MAC Framework support */ 
8770  * define IOC_DEBUG to display run-time debugging information 
8771  * #define IOC_DEBUG 1 
8775 #define DPRINTF(x)    printf x 
8781 /********************************************************************* 
8782 *********************************************************************/ 
8784 MACFObjectIsPrimitiveType(OSObject 
* obj
) 
8786     const OSMetaClass 
* typeID 
= NULL
;  // do not release 
8788     typeID 
= OSTypeIDInst(obj
); 
8789     if (typeID 
== OSTypeID(OSString
) || typeID 
== OSTypeID(OSNumber
) || 
8790         typeID 
== OSTypeID(OSBoolean
) || typeID 
== OSTypeID(OSData
)) { 
8797 /********************************************************************* 
8798 *********************************************************************/ 
8800 MACFLengthForObject(OSObject 
* obj
) 
8802     const OSMetaClass 
* typeID 
= NULL
;  // do not release 
8805     typeID 
= OSTypeIDInst(obj
); 
8806     if (typeID 
== OSTypeID(OSString
)) { 
8807         OSString 
* stringObj 
= OSDynamicCast(OSString
, obj
); 
8808         len 
= stringObj
->getLength() + 1; 
8809     } else if (typeID 
== OSTypeID(OSNumber
)) { 
8810         len 
= sizeof("4294967295");    /* UINT32_MAX */ 
8811     } else if (typeID 
== OSTypeID(OSBoolean
)) { 
8812         OSBoolean 
* boolObj 
= OSDynamicCast(OSBoolean
, obj
); 
8813         len 
= boolObj
->isTrue() ? sizeof("true") : sizeof("false"); 
8814     } else if (typeID 
== OSTypeID(OSData
)) { 
8815         OSData 
* dataObj 
= OSDynamicCast(OSData
, obj
); 
8816         len 
= dataObj
->getLength(); 
8823 /********************************************************************* 
8824 *********************************************************************/ 
8826 MACFInitElementFromObject( 
8827     struct mac_module_data_element 
* element
, 
8830     const OSMetaClass 
* typeID 
= NULL
;  // do not release 
8832     typeID 
= OSTypeIDInst(value
); 
8833     if (typeID 
== OSTypeID(OSString
)) { 
8834         OSString 
* stringObj 
= OSDynamicCast(OSString
, value
); 
8835         element
->value_type 
= MAC_DATA_TYPE_PRIMITIVE
; 
8836         element
->value_size 
= stringObj
->getLength() + 1; 
8837         DPRINTF(("osdict: string %s size %d\n",  
8838             stringObj
->getCStringNoCopy(), element
->value_size
)); 
8839         memcpy(element
->value
, stringObj
->getCStringNoCopy(), 
8840             element
->value_size
); 
8841     } else if (typeID 
== OSTypeID(OSNumber
)) { 
8842         OSNumber 
* numberObj 
= OSDynamicCast(OSNumber
, value
); 
8843         element
->value_type 
= MAC_DATA_TYPE_PRIMITIVE
; 
8844         element
->value_size 
= sprintf(element
->value
, "%u", 
8845             numberObj
->unsigned32BitValue()) + 1; 
8846     } else if (typeID 
== OSTypeID(OSBoolean
)) { 
8847         OSBoolean 
* boolObj 
= OSDynamicCast(OSBoolean
, value
); 
8848         element
->value_type 
= MAC_DATA_TYPE_PRIMITIVE
; 
8849         if (boolObj
->isTrue()) { 
8850             strcpy(element
->value
, "true"); 
8851             element
->value_size 
= 5; 
8853             strcpy(element
->value
, "false"); 
8854             element
->value_size 
= 6; 
8856     } else if (typeID 
== OSTypeID(OSData
)) { 
8857         OSData 
* dataObj 
= OSDynamicCast(OSData
, value
); 
8858         element
->value_type 
= MAC_DATA_TYPE_PRIMITIVE
; 
8859         element
->value_size 
= dataObj
->getLength(); 
8860         DPRINTF(("osdict: data size %d\n", dataObj
->getLength())); 
8861         memcpy(element
->value
, dataObj
->getBytesNoCopy(), 
8862             element
->value_size
); 
8867 /********************************************************************* 
8868 * This function takes an OSDictionary and returns a struct mac_module_data 
8870 *********************************************************************/ 
8871 static struct mac_module_data 
* 
8872 MACFEncodeOSDictionary(OSDictionary 
* dict
) 
8874     struct mac_module_data         
* result      
= NULL
;  // do not free 
8875     const OSMetaClass              
* typeID      
= NULL
;  // do not release 
8876     OSString                       
* key         
= NULL
;  // do not release 
8877     OSCollectionIterator           
* keyIterator 
= NULL
;  // must release 
8878     struct mac_module_data_element 
* element     
= NULL
;  // do not free 
8879     unsigned int                     strtabsize  
= 0; 
8880     unsigned int                     listtabsize 
= 0; 
8881     unsigned int                     dicttabsize 
= 0; 
8882     unsigned int                     nkeys       
= 0; 
8883     unsigned int                     datalen     
= 0; 
8884     char                           * strtab      
= NULL
;  // do not free 
8885     char                           * listtab     
= NULL
;  // do not free 
8886     char                           * dicttab     
= NULL
;  // do not free 
8887     vm_offset_t                      data_addr   
= 0; 
8889     keyIterator 
= OSCollectionIterator::withCollection(dict
); 
8894     /* Iterate over OSModuleData to figure out total size */ 
8895     while ( (key 
= OSDynamicCast(OSString
, keyIterator
->getNextObject())) ) { 
8897         // Get the key's value and determine its type 
8898         OSObject 
* value 
= dict
->getObject(key
); 
8903         typeID 
= OSTypeIDInst(value
); 
8904         if (MACFObjectIsPrimitiveType(value
)) { 
8905             strtabsize 
+= MACFLengthForObject(value
); 
8907         else if (typeID 
== OSTypeID(OSArray
)) { 
8908             unsigned int k
, cnt
, nents
; 
8909             OSArray 
* arrayObj 
= OSDynamicCast(OSArray
, value
); 
8912             cnt 
= arrayObj
->getCount(); 
8913             for (k 
= 0; k 
< cnt
; k
++) { 
8914                 value 
= arrayObj
->getObject(k
); 
8915                 typeID 
= OSTypeIDInst(value
); 
8916                 if (MACFObjectIsPrimitiveType(value
)) { 
8917                     listtabsize 
+= MACFLengthForObject(value
); 
8920                 else if (typeID 
== OSTypeID(OSDictionary
)) { 
8921                     unsigned int           dents 
= 0; 
8922                     OSDictionary         
* dictObj      
= NULL
;  // do not release 
8923                     OSString             
* dictkey      
= NULL
;  // do not release 
8924                     OSCollectionIterator 
* dictIterator 
= NULL
;  // must release 
8926                     dictObj 
= OSDynamicCast(OSDictionary
, value
); 
8927                     dictIterator 
= OSCollectionIterator::withCollection(dictObj
); 
8928                     if (!dictIterator
) { 
8931                     while ((dictkey 
= OSDynamicCast(OSString
, 
8932                         dictIterator
->getNextObject()))) { 
8934                         OSObject 
* dictvalue 
= NULL
;  // do not release 
8936                         dictvalue 
= dictObj
->getObject(dictkey
); 
8940                         if (MACFObjectIsPrimitiveType(dictvalue
)) { 
8941                             strtabsize 
+= MACFLengthForObject(dictvalue
); 
8943                             continue; /* Only handle primitive types here. */ 
8946                         * Allow for the "arraynnn/" prefix in the key length. 
8948                         strtabsize 
+= dictkey
->getLength() + 1; 
8951                     dictIterator
->release(); 
8953                         dicttabsize 
+= sizeof(struct mac_module_data_list
) + 
8954                         dents 
* sizeof(struct mac_module_data_element
); 
8959                     continue; /* Skip everything else. */ 
8965             listtabsize 
+= sizeof(struct mac_module_data_list
) + 
8966                 (nents 
- 1) * sizeof(struct mac_module_data_element
); 
8968             continue; /* skip anything else */ 
8970         strtabsize 
+= key
->getLength() + 1; 
8978     * Allocate and fill in the module data structures. 
8980     datalen 
= sizeof(struct mac_module_data
) + 
8981         sizeof(mac_module_data_element
) * (nkeys 
- 1) + 
8982     strtabsize 
+ listtabsize 
+ dicttabsize
; 
8983     DPRINTF(("osdict: datalen %d strtabsize %d listtabsize %d dicttabsize %d\n",  
8984         datalen
, strtabsize
, listtabsize
, dicttabsize
)); 
8985     if (kmem_alloc(kernel_map
, &data_addr
, datalen
) != KERN_SUCCESS
) { 
8988     result 
= (mac_module_data 
*)data_addr
; 
8989     result
->base_addr 
= data_addr
; 
8990     result
->size 
= datalen
; 
8991     result
->count 
= nkeys
; 
8992     strtab 
= (char *)&result
->data
[nkeys
]; 
8993     listtab 
= strtab 
+ strtabsize
; 
8994     dicttab 
= listtab 
+ listtabsize
; 
8995     DPRINTF(("osdict: data_addr %p strtab %p listtab %p dicttab %p end %p\n",  
8996         data_addr
, strtab
, listtab
, dicttab
, data_addr 
+ datalen
)); 
8998     keyIterator
->reset(); 
9000     element 
= &result
->data
[0]; 
9001     DPRINTF(("osdict: element %p\n", element
)); 
9002     while ( (key 
= OSDynamicCast(OSString
, keyIterator
->getNextObject())) ) { 
9004         // Get the key's value and determine its type 
9005         OSObject 
* value 
= dict
->getObject(key
); 
9011         DPRINTF(("osdict: element @%p\n", element
)); 
9012         element
->key 
= strtab
; 
9013         element
->key_size 
= key
->getLength() + 1; 
9014         DPRINTF(("osdict: key %s size %d @%p\n", key
->getCStringNoCopy(), 
9015             element
->key_size
, strtab
)); 
9016         memcpy(element
->key
, key
->getCStringNoCopy(), element
->key_size
); 
9018         typeID 
= OSTypeIDInst(value
); 
9019         if (MACFObjectIsPrimitiveType(value
)) { 
9021             element
->value 
= element
->key 
+ element
->key_size
; 
9022             DPRINTF(("osdict: primitive element value %p\n", element
->value
)); 
9023             MACFInitElementFromObject(element
, value
); 
9024             strtab 
+= element
->key_size 
+ element
->value_size
; 
9025             DPRINTF(("osdict: new strtab %p\n", strtab
)); 
9026         } else if (typeID 
== OSTypeID(OSArray
)) { 
9027             unsigned int k
, cnt
, nents
; 
9029             struct mac_module_data_list 
*arrayhd
; 
9030             struct mac_module_data_element 
*ele
; 
9031             OSArray 
*arrayObj 
= OSDynamicCast(OSArray
, value
); 
9033             element
->value 
= listtab
; 
9034             DPRINTF(("osdict: array element value %p\n", element
->value
)); 
9035             element
->value_type 
= MAC_DATA_TYPE_ARRAY
; 
9036             arrayhd 
= (struct mac_module_data_list 
*)element
->value
; 
9038             DPRINTF(("osdict: arrayhd %p\n", arrayhd
)); 
9040             astrtab 
= strtab 
+ element
->key_size
; 
9041             ele 
= &(arrayhd
->list
[0]); 
9042             cnt 
= arrayObj
->getCount(); 
9043             for (k 
= 0; k 
< cnt
; k
++) { 
9044                 value 
= arrayObj
->getObject(k
); 
9045                 DPRINTF(("osdict: array ele %d @%p\n", nents
, ele
)); 
9048                 typeID 
= OSTypeIDInst(value
); 
9049                 if (MACFObjectIsPrimitiveType(value
)) { 
9050                     if (arrayhd
->type 
!= 0 && 
9051                         arrayhd
->type 
!= MAC_DATA_TYPE_PRIMITIVE
) { 
9055                     arrayhd
->type 
= MAC_DATA_TYPE_PRIMITIVE
; 
9056                     ele
->value 
= astrtab
; 
9057                     MACFInitElementFromObject(ele
, value
); 
9058                     astrtab 
+= ele
->value_size
; 
9059                     DPRINTF(("osdict: array new astrtab %p\n", astrtab
)); 
9060                 } else if (typeID 
== OSTypeID(OSDictionary
)) { 
9062                     char                           * dstrtab      
= NULL
;  // do not free 
9063                     OSDictionary                   
* dictObj      
= NULL
;  // do not release 
9064                     OSString                       
* dictkey      
= NULL
;  // do not release 
9065                     OSCollectionIterator           
* dictIterator 
= NULL
;  // must release 
9066                     struct mac_module_data_list    
* dicthd       
= NULL
;  // do not free 
9067                     struct mac_module_data_element 
* dele         
= NULL
;  // do not free 
9069                     if (arrayhd
->type 
!= 0 && 
9070                         arrayhd
->type 
!= MAC_DATA_TYPE_DICT
) { 
9074                     dictObj 
= OSDynamicCast(OSDictionary
, value
); 
9075                     dictIterator 
= OSCollectionIterator::withCollection(dictObj
); 
9076                     if (!dictIterator
) { 
9079                     DPRINTF(("osdict: dict\n")); 
9080                     ele
->value 
= dicttab
; 
9081                     ele
->value_type 
= MAC_DATA_TYPE_DICT
; 
9082                     dicthd 
= (struct mac_module_data_list 
*)ele
->value
; 
9083                     DPRINTF(("osdict: dicthd %p\n", dicthd
)); 
9086                     while ((dictkey 
= OSDynamicCast(OSString
, 
9087                         dictIterator
->getNextObject()))) { 
9089                         OSObject 
* dictvalue 
= NULL
;  // do not release 
9091                         dictvalue 
= dictObj
->getObject(dictkey
); 
9095                         dele 
= &(dicthd
->list
[dents
]); 
9096                         DPRINTF(("osdict: dict ele %d @%p\n", dents
, dele
)); 
9097                         if (MACFObjectIsPrimitiveType(dictvalue
)) { 
9098                             dele
->key 
= dstrtab
; 
9099                             dele
->key_size 
= dictkey
->getLength() + 1; 
9100                             DPRINTF(("osdict: dictkey %s size %d @%p\n", 
9101                                 dictkey
->getCStringNoCopy(), dictkey
->getLength(), dstrtab
)); 
9102                             memcpy(dele
->key
, dictkey
->getCStringNoCopy(), 
9104                             dele
->value 
= dele
->key 
+ dele
->key_size
; 
9105                             MACFInitElementFromObject(dele
, dictvalue
); 
9106                             dstrtab 
+= dele
->key_size 
+ dele
->value_size
; 
9107                             DPRINTF(("osdict: dict new dstrtab %p\n", dstrtab
)); 
9109                             continue;    /* Only handle primitive types here. */ 
9113                     dictIterator
->release(); 
9117                     arrayhd
->type 
= MAC_DATA_TYPE_DICT
; 
9118                     ele
->value_size 
= sizeof(struct mac_module_data_list
) + 
9119                         (dents 
- 1) * sizeof(struct mac_module_data_element
); 
9120                     DPRINTF(("osdict: dict ele size %d ents %d\n", ele
->value_size
, dents
)); 
9121                     dicttab 
+= ele
->value_size
; 
9122                     DPRINTF(("osdict: new dicttab %p\n", dicttab
)); 
9123                     dicthd
->count 
= dents
; 
9126                     continue;        /* Skip everything else. */ 
9134             element
->value_size 
= sizeof(struct mac_module_data_list
) + 
9135                 (nents 
- 1) * sizeof(struct mac_module_data_element
); 
9136             listtab 
+= element
->value_size
; 
9137             DPRINTF(("osdict: new listtab %p\n", listtab
)); 
9138             arrayhd
->count 
= nents
; 
9140             DPRINTF(("osdict: new strtab %p\n", strtab
)); 
9142             continue;        /* skip anything else */ 
9146     DPRINTF(("result list @%p, key %p value %p\n", 
9147         result
, result
->data
[0].key
, result
->data
[0].value
)); 
9149     if (keyIterator
) keyIterator
->release(); 
9153 /********************************************************************* 
9154 * This function takes a plist and looks for an OSModuleData dictionary. 
9155 * If it is found, an encoded copy is returned. The value must be 
9157 *********************************************************************/ 
9159 MACFCopyModuleDataForKext( 
9161     mach_msg_type_number_t 
* datalen
) 
9164     struct mac_module_data 
* result         
= NULL
; 
9165     OSDictionary           
* kextModuleData 
= NULL
;  // do not release 
9166     vm_map_copy_t            copy           
= 0; 
9168     kextModuleData 
= OSDynamicCast(OSDictionary
, 
9169         theKext
->getPropertyForHostArch("OSModuleData")); 
9170     if (!kextModuleData
) { 
9174     result 
= MACFEncodeOSDictionary(kextModuleData
); 
9178     *datalen 
= module_data
->size
; 
9181     return (void *)result
; 
9183 #endif /* CONFIG_MACF_KEXT */