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/host_special_ports.h> 
  42 #include <mach/mach_vm.h> 
  43 #include <mach/mach_time.h> 
  44 #include <sys/sysctl.h> 
  45 #include <uuid/uuid.h> 
  46 // 04/18/11 - gab: <rdar://problem/9236163> 
  47 #include <sys/random.h> 
  50 #include <libkern/OSKextLibPrivate.h> 
  51 #include <libkern/c++/OSKext.h> 
  52 #include <libkern/c++/OSLib.h> 
  54 #include <IOKit/IOLib.h> 
  55 #include <IOKit/IOCatalogue.h> 
  56 #include <IOKit/IORegistryEntry.h> 
  57 #include <IOKit/IOService.h> 
  59 #include <IOKit/IOStatisticsPrivate.h> 
  62 #pragma mark External & Internal Function Protos 
  64 /********************************************************************* 
  65 *********************************************************************/ 
  67 extern int  IODTGetLoaderInfo(const char * key
, void ** infoAddr
, int * infoSize
); 
  68 extern void IODTFreeLoaderInfo(const char * key
, void * infoAddr
, int infoSize
); 
  69 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t 
* segment
); 
  70 extern void OSRuntimeUnloadCPP(kmod_info_t 
* ki
, void * data
); 
  72 extern ppnum_t 
pmap_find_phys(pmap_t pmap
, addr64_t va
); /* osfmk/machine/pmap.h */ 
  75 static OSReturn 
_OSKextCreateRequest( 
  76     const char    * predicate
, 
  77     OSDictionary 
** requestP
); 
  78 static OSString 
* _OSKextGetRequestPredicate(OSDictionary 
* requestDict
); 
  79 static OSObject 
* _OSKextGetRequestArgument( 
  80     OSDictionary 
* requestDict
, 
  81     const char   * argName
); 
  82 static bool _OSKextSetRequestArgument( 
  83     OSDictionary 
* requestDict
, 
  86 static void * _OSKextExtractPointer(OSData 
* wrapper
); 
  87 static OSReturn 
_OSDictionarySetCStringValue( 
  91 static bool _OSKextInPrelinkRebuildWindow(void); 
  92 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol 
* theBundleID
); 
  94 // We really should add containsObject() & containsCString to OSCollection & subclasses. 
  95 // So few pad slots, though.... 
  96 static bool _OSArrayContainsCString(OSArray 
* array
, const char * cString
); 
  99 static void * GetAppleTEXTHashForKext(OSKext 
* theKext
, OSDictionary 
*theInfoDict
); 
 100 #endif // CONFIG_KEC_FIPS 
 102 /* Prelinked arm kexts do not have VM entries because the method we use to 
 103  * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does 
 104  * not work on ARM.  To get around that, we must free prelinked kext 
 105  * executables with ml_static_mfree() instead of kext_free(). 
 107 #if __i386__ || __x86_64__ 
 108 #define VM_MAPPED_KEXTS 1 
 109 #define KASLR_KEXT_DEBUG 0 
 110 #define KASLR_IOREG_DEBUG 0 
 112 #error Unsupported architecture 
 116 #pragma mark Constants & Macros 
 118 /********************************************************************* 
 120 *********************************************************************/ 
 122 /* A typical Snow Leopard system has a bit under 120 kexts loaded. 
 123  * Use this number to create containers. 
 125 #define kOSKextTypicalLoadCount      (120) 
 127 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict. 
 128  * A loaded kext will no dependents or external retains will have 2 retains. 
 130 #define kOSKextMinRetainCount        (1) 
 131 #define kOSKextMinLoadedRetainCount  (2) 
 134  * Strings and substrings used in dependency resolution. 
 136 #define APPLE_KEXT_PREFIX            "com.apple." 
 137 #define KERNEL_LIB                   "com.apple.kernel" 
 139 #define PRIVATE_KPI                  "com.apple.kpi.private" 
 141 /* Version for compatbility pseudokexts (com.apple.kernel.*), 
 142  * compatible back to v6.0. 
 144 #define KERNEL6_LIB                  "com.apple.kernel.6.0" 
 145 #define KERNEL6_VERSION              "7.9.9" 
 147 #define KERNEL_LIB_PREFIX            "com.apple.kernel." 
 148 #define KPI_LIB_PREFIX               "com.apple.kpi." 
 150 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0) 
 152 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes 
 153 #define MINIMUM_WAKEUP_SECONDS (30) 
 155 /********************************************************************* 
 156 * infoDict keys for internally-stored data. Saves on ivar slots for 
 157 * objects we don't keep around past boot time or during active load. 
 158 *********************************************************************/ 
 160 /* A usable, uncompressed file is stored under this key. 
 162 #define _kOSKextExecutableKey                "_OSKextExecutable" 
 164 /* An indirect reference to the executable file from an mkext 
 165  * is stored under this key. 
 167 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference" 
 169 /* If the file is contained in a larger buffer laid down by the booter or 
 170  * sent from user space, the OSKext stores that OSData under this key so that 
 171  * references are properly tracked. This is always an mkext, right now. 
 173 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData" 
 176 #pragma mark Typedefs 
 178 /********************************************************************* 
 180 *********************************************************************/ 
 182 /********************************************************************* 
 183 * MkextEntryRef describes the contents of an OSData object 
 184 * referencing a file entry from an mkext so that we can uncompress 
 185 * (if necessary) and extract it on demand. 
 187 * It contains the mkextVersion in case we ever wind up supporting 
 188 * multiple mkext formats. Mkext format 1 is officially retired as of 
 190 *********************************************************************/ 
 191 typedef struct MkextEntryRef 
{ 
 192     mkext_basic_header 
* mkext
;     // beginning of whole mkext file 
 193     void               * fileinfo
;  // mkext2_file_entry or equiv; see mkext.h 
 197 #pragma mark Global and static Module Variables 
 199 /********************************************************************* 
 200 * Global & static variables, used to keep track of kexts. 
 201 *********************************************************************/ 
 203 static  bool                sPrelinkBoot               
= false; 
 204 static  bool                sSafeBoot                  
= false; 
 205 static  bool                sKeepSymbols               
= false; 
 207 /********************************************************************* 
 208 * sKextLock is the principal lock for OSKext, and guards all static 
 209 * and global variables not owned by other locks (declared further 
 210 * below). It must be taken by any entry-point method or function, 
 211 * including internal functions called on scheduled threads. 
 213 * sKextLock and sKextInnerLock are recursive due to multiple functions 
 214 * that are called both externally and internally. The other locks are 
 217 * Which locks are taken depends on what they protect, but if more than 
 218 * one must be taken, they must always be locked in this order 
 219 * (and unlocked in reverse order) to prevent deadlocks: 
 223 *    3. sKextSummariesLock 
 224 *    4. sKextLoggingLock 
 226 static IORecursiveLock    
* sKextLock                  
= NULL
; 
 228 static OSDictionary       
* sKextsByID                 
= NULL
; 
 229 static OSArray            
* sLoadedKexts               
= NULL
; 
 230 static OSArray            
* sUnloadedPrelinkedKexts    
= NULL
; 
 232 // Requests to kextd waiting to be picked up. 
 233 static OSArray            
* sKernelRequests            
= NULL
; 
 234 // Identifier of kext load requests in sKernelRequests 
 235 static OSSet              
* sPostedKextLoadIdentifiers 
= NULL
; 
 236 static OSArray            
* sRequestCallbackRecords    
= NULL
; 
 238 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel 
 239 static OSSet              
* sAllKextLoadIdentifiers    
= NULL
; 
 240 static KXLDContext        
* sKxldContext               
= NULL
; 
 241 static uint32_t             sNextLoadTag               
= 0; 
 242 static uint32_t             sNextRequestTag            
= 0; 
 244 static bool                 sUserLoadsActive           
= false; 
 245 static bool                 sKextdActive               
= false; 
 246 static bool                 sDeferredLoadSucceeded     
= false; 
 247 static bool                 sConsiderUnloadsExecuted   
= false; 
 250 static bool                 sKernelRequestsEnabled     
= false; 
 252 static bool                 sKernelRequestsEnabled     
= true; 
 254 static bool                 sLoadEnabled               
= true; 
 255 static bool                 sUnloadEnabled             
= true; 
 257 /********************************************************************* 
 258 * Stuff for the OSKext representing the kernel itself. 
 260 static OSKext          
* sKernelKext             
= NULL
; 
 262 /* Set up a fake kmod_info struct for the kernel. 
 263  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP() 
 264  * before OSKext is initialized; that call only needs the name 
 265  * and address to be set correctly. 
 267  * We don't do much else with the kerne's kmod_info; we never 
 268  * put it into the kmod list, never adjust the reference count, 
 269  * and never have kernel components reference it. 
 270  * For that matter, we don't do much with kmod_info structs 
 271  * at all anymore! We just keep them filled in for gdb and 
 272  * binary compability. 
 274 kmod_info_t g_kernel_kmod_info 
= { 
 276     /* info_version    */ KMOD_INFO_VERSION
, 
 277     /* id              */ 0,                 // loadTag: kernel is always 0 
 278     /* name            */ kOSKextKernelIdentifier
,    // bundle identifier 
 279     /* version         */ "0",               // filled in in OSKext::initialize() 
 280     /* reference_count */ -1,                // never adjusted; kernel never unloads 
 281     /* reference_list  */ NULL
, 
 283     /* size            */ 0,                 // filled in in OSKext::initialize() 
 290 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c, 
 291 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s, 
 292 // misc_protos.h, db_low_trace.c, kgmacros 
 293 // 'kmod' is a holdover from the old kmod system, we can't rename it. 
 294 kmod_info_t 
* kmod 
= NULL
; 
 296 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE) 
 299 static char     * loaded_kext_paniclist         
= NULL
; 
 300 static uint32_t   loaded_kext_paniclist_size    
= 0; 
 301 static uint32_t   loaded_kext_paniclist_length  
= 0; 
 303 AbsoluteTime      last_loaded_timestamp
; 
 304 static char       last_loaded_str
[2*KMOD_MAX_NAME
]; 
 305 static u_long     last_loaded_strlen            
= 0; 
 306 static void     * last_loaded_address           
= NULL
; 
 307 static u_long     last_loaded_size              
= 0; 
 309 AbsoluteTime      last_unloaded_timestamp
; 
 310 static char       last_unloaded_str
[2*KMOD_MAX_NAME
]; 
 311 static u_long     last_unloaded_strlen          
= 0; 
 312 static void     * last_unloaded_address         
= NULL
; 
 313 static u_long     last_unloaded_size            
= 0; 
 315 /********************************************************************* 
 316 * sKextInnerLock protects against cross-calls with IOService and 
 317 * IOCatalogue, and owns the variables declared immediately below. 
 319 * Note that sConsiderUnloadsExecuted above belongs to sKextLock! 
 321 * When both sKextLock and sKextInnerLock need to be taken, 
 322 * always lock sKextLock first and unlock it second. Never take both 
 323 * locks in an entry point to OSKext; if you need to do so, you must 
 324 * spawn an independent thread to avoid potential deadlocks for threads 
 325 * calling into OSKext. 
 327 static IORecursiveLock 
*    sKextInnerLock             
= NULL
; 
 329 static bool                 sAutounloadEnabled         
= true; 
 330 static bool                 sConsiderUnloadsCalled     
= false; 
 331 static bool                 sConsiderUnloadsPending    
= false; 
 333 static unsigned int         sConsiderUnloadDelay       
= 60;     // seconds 
 334 static thread_call_t        sUnloadCallout             
= 0; 
 335 static thread_call_t        sDestroyLinkContextThread  
= 0;      // one-shot, one-at-a-time thread 
 336 static bool                 sSystemSleep               
= false;  // true when system going to sleep 
 337 static AbsoluteTime         sLastWakeTime
;                       // last time we woke up    
 339 /********************************************************************* 
 340 * Backtraces can be printed at various times so we need a tight lock 
 341 * on data used for that. sKextSummariesLock protects the variables 
 342 * declared immediately below. 
 344 * gLoadedKextSummaries is accessed by other modules, but only during 
 345 * a panic so the lock isn't needed then. 
 347 static IOLock                 
* sKextSummariesLock                
= NULL
; 
 349 void (*sLoadedKextSummariesUpdated
)(void) = OSKextLoadedKextSummariesUpdated
; 
 350 OSKextLoadedKextSummaryHeader 
* gLoadedKextSummaries 
= NULL
; 
 351 static size_t sLoadedKextSummariesAllocSize 
= 0; 
 352 OSKextLoadedKextSummaryHeader 
* sPrevLoadedKextSummaries 
= NULL
; 
 353 static size_t sPrevLoadedKextSummariesAllocSize 
= 0; 
 356 /********************************************************************* 
 357 * sKextLoggingLock protects the logging variables declared immediately below. 
 359 static IOLock             
* sKextLoggingLock           
= NULL
; 
 361 static  const OSKextLogSpec kDefaultKernelLogFilter    
= kOSKextLogBasicLevel 
| 
 362                                                          kOSKextLogVerboseFlagsMask
; 
 363 static  OSKextLogSpec       sKernelLogFilter           
= kDefaultKernelLogFilter
; 
 364 static  bool                sBootArgLogFilterFound     
= false; 
 365 SYSCTL_INT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, &sKernelLogFilter
, 
 366     sKernelLogFilter
, "kernel kext logging"); 
 368 static  OSKextLogSpec       sUserSpaceKextLogFilter    
= kOSKextLogSilentFilter
; 
 369 static  OSArray           
* sUserSpaceLogSpecArray     
= NULL
; 
 370 static  OSArray           
* sUserSpaceLogMessageArray  
= NULL
; 
 373 * End scope for sKextInnerLock-protected variables. 
 374 *********************************************************************/ 
 377 #pragma mark OSData callbacks (need to move to OSData) 
 379 /********************************************************************* 
 380 * C functions used for callbacks. 
 381 *********************************************************************/ 
 383 void osdata_kmem_free(void * ptr
, unsigned int length
) { 
 384     kmem_free(kernel_map
, (vm_address_t
)ptr
, length
); 
 388 void osdata_phys_free(void * ptr
, unsigned int length
) { 
 389     ml_static_mfree((vm_offset_t
)ptr
, length
); 
 393 void osdata_vm_deallocate(void * ptr
, unsigned int length
) 
 395     (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
); 
 399 void osdata_kext_free(void * ptr
, unsigned int length
) 
 401     (void)kext_free((vm_offset_t
)ptr
, length
); 
 407 #pragma mark KXLD Allocation Callback 
 409 /********************************************************************* 
 410 * KXLD Allocation Callback 
 411 *********************************************************************/ 
 415     KXLDAllocateFlags 
* flags
, 
 418     vm_address_t  result       
= 0;     // returned 
 419     kern_return_t mach_result  
= KERN_FAILURE
; 
 420     bool          success      
= false; 
 421     OSKext      
* theKext      
= (OSKext 
*)user_data
; 
 422     u_long        roundSize    
= round_page(size
); 
 423     OSData      
* linkBuffer   
= NULL
;  // must release 
 425     mach_result 
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
); 
 426     if (mach_result 
!= KERN_SUCCESS
) { 
 428             kOSKextLogErrorLevel 
| 
 429             kOSKextLogGeneralFlag
, 
 430             "Can't allocate kernel memory to link %s.", 
 431             theKext
->getIdentifierCString()); 
 435    /* Create an OSData wrapper for the allocated buffer. 
 437     linkBuffer 
= OSData::withBytesNoCopy((void *)result
, roundSize
); 
 440             kOSKextLogErrorLevel 
| 
 441             kOSKextLogGeneralFlag
, 
 442             "Can't allocate linked executable wrapper for %s.", 
 443             theKext
->getIdentifierCString()); 
 446     linkBuffer
->setDeallocFunction(osdata_kext_free
); 
 449         kOSKextLogProgressLevel 
| 
 450         kOSKextLogLoadFlag 
| kOSKextLogLinkFlag
, 
 451         "Allocated link buffer for kext %s at %p (%lu bytes).", 
 452         theKext
->getIdentifierCString(), 
 453         (void *)result
, (unsigned long)roundSize
); 
 455     theKext
->setLinkedExecutable(linkBuffer
); 
 457     *flags 
= kKxldAllocateWritable
; 
 461     if (!success 
&& result
) { 
 462         kext_free(result
, roundSize
); 
 466     OSSafeRelease(linkBuffer
); 
 468     return (kxld_addr_t
)result
; 
 471 /********************************************************************* 
 472 *********************************************************************/ 
 475     KXLDLogSubsystem    subsystem
, 
 481     OSKext 
*theKext 
= (OSKext 
*) user_data
; 
 482     OSKextLogSpec logSpec 
= 0; 
 485     case kKxldLogLinking
: 
 486         logSpec 
|= kOSKextLogLinkFlag
; 
 488     case kKxldLogPatching
: 
 489         logSpec 
|= kOSKextLogPatchFlag
; 
 494     case kKxldLogExplicit
: 
 495         logSpec 
|= kOSKextLogExplicitLevel
; 
 498         logSpec 
|= kOSKextLogErrorLevel
; 
 501         logSpec 
|= kOSKextLogWarningLevel
; 
 504         logSpec 
|= kOSKextLogProgressLevel
; 
 507         logSpec 
|= kOSKextLogDetailLevel
; 
 510         logSpec 
|= kOSKextLogDebugLevel
; 
 514     OSKextVLog(theKext
, logSpec
, format
, argList
); 
 518 #pragma mark IOStatistics defines 
 523 #define notifyKextLoadObservers(kext, kmod_info) \ 
 525     IOStatistics::onKextLoad(kext, kmod_info); \ 
 528 #define notifyKextUnloadObservers(kext) \ 
 530     IOStatistics::onKextUnload(kext); \ 
 533 #define notifyAddClassObservers(kext, addedClass, flags) \ 
 535     IOStatistics::onClassAdded(kext, addedClass); \ 
 538 #define notifyRemoveClassObservers(kext, removedClass, flags) \ 
 540     IOStatistics::onClassRemoved(kext, removedClass); \ 
 545 #define notifyKextLoadObservers(kext, kmod_info) 
 546 #define notifyKextUnloadObservers(kext) 
 547 #define notifyAddClassObservers(kext, addedClass, flags) 
 548 #define notifyRemoveClassObservers(kext, removedClass, flags) 
 550 #endif /* IOKITSTATS */ 
 553 #pragma mark Module Config (Startup & Shutdown) 
 555 /********************************************************************* 
 556 * Module Config (Class Definition & Class Methods) 
 557 *********************************************************************/ 
 558 #define super OSObject 
 559 OSDefineMetaClassAndStructors(OSKext
, OSObject
) 
 561 /********************************************************************* 
 562 *********************************************************************/ 
 565 OSKext::initialize(void) 
 567     OSData          
* kernelExecutable   
= NULL
;  // do not release 
 568     u_char          
* kernelStart        
= NULL
;  // do not free 
 569     size_t            kernelLength       
= 0; 
 570     OSString        
* scratchString      
= NULL
;  // must release 
 571     IORegistryEntry 
* registryRoot       
= NULL
;  // do not release 
 572     OSNumber        
* kernelCPUType      
= NULL
;  // must release 
 573     OSNumber        
* kernelCPUSubtype   
= NULL
;  // must release 
 574     OSKextLogSpec     bootLogFilter      
= kOSKextLogSilentFilter
; 
 575     bool              setResult          
= false; 
 576     uint64_t        * timestamp          
= 0; 
 577     char              bootArgBuffer
[16];  // for PE_parse_boot_argn w/strings 
 579    /* This must be the first thing allocated. Everything else grabs this lock. 
 581     sKextLock 
= IORecursiveLockAlloc(); 
 582     sKextInnerLock 
= IORecursiveLockAlloc(); 
 583     sKextSummariesLock 
= IOLockAlloc(); 
 584     sKextLoggingLock 
= IOLockAlloc(); 
 586     assert(sKextInnerLock
); 
 587     assert(sKextSummariesLock
); 
 588     assert(sKextLoggingLock
); 
 590     sKextsByID 
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
); 
 591     sLoadedKexts 
= OSArray::withCapacity(kOSKextTypicalLoadCount
); 
 592     sUnloadedPrelinkedKexts 
= OSArray::withCapacity(kOSKextTypicalLoadCount 
/ 10); 
 593     sKernelRequests 
= OSArray::withCapacity(0); 
 594     sPostedKextLoadIdentifiers 
= OSSet::withCapacity(0); 
 595     sAllKextLoadIdentifiers 
= OSSet::withCapacity(kOSKextTypicalLoadCount
); 
 596     sRequestCallbackRecords 
= OSArray::withCapacity(0); 
 597     assert(sKextsByID 
&& sLoadedKexts 
&& sKernelRequests 
&& 
 598         sPostedKextLoadIdentifiers 
&& sAllKextLoadIdentifiers 
&& 
 599         sRequestCallbackRecords 
&& sUnloadedPrelinkedKexts
); 
 601    /* Read the log flag boot-args and set the log flags. 
 603     if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof(bootLogFilter
))) { 
 604         sBootArgLogFilterFound 
= true; 
 605         sKernelLogFilter 
= bootLogFilter
; 
 606         // log this if any flags are set 
 607         OSKextLog(/* kext */ NULL
, 
 608             kOSKextLogBasicLevel 
| 
 610             "Kernel kext log filter 0x%x per kextlog boot arg.", 
 611             (unsigned)sKernelLogFilter
); 
 614     sSafeBoot 
= PE_parse_boot_argn("-x", bootArgBuffer
, 
 615         sizeof(bootArgBuffer
)) ? true : false; 
 618         OSKextLog(/* kext */ NULL
, 
 619             kOSKextLogWarningLevel 
| 
 620             kOSKextLogGeneralFlag
, 
 621             "SAFE BOOT DETECTED - " 
 622             "only valid OSBundleRequired kexts will be loaded."); 
 625     PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
)); 
 627    /* Set up an OSKext instance to represent the kernel itself. 
 629     sKernelKext 
= new OSKext
; 
 632     kernelStart 
= (u_char 
*)&_mh_execute_header
; 
 633     kernelLength 
= getlastaddr() - (vm_offset_t
)kernelStart
; 
 634     kernelExecutable 
= OSData::withBytesNoCopy( 
 635         kernelStart
, kernelLength
); 
 636     assert(kernelExecutable
); 
 639     IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu \n",  
 640           (unsigned long)kernelStart
,  
 641           (unsigned long)getlastaddr(), 
 645     sKernelKext
->loadTag 
= sNextLoadTag
++;  // the kernel is load tag 0 
 646     sKernelKext
->bundleID 
= OSSymbol::withCString(kOSKextKernelIdentifier
); 
 648     sKernelKext
->version 
= OSKextParseVersionString(osrelease
); 
 649     sKernelKext
->compatibleVersion 
= sKernelKext
->version
; 
 650     sKernelKext
->linkedExecutable 
= kernelExecutable
; 
 652     sKernelKext
->flags
.hasAllDependencies 
= 1; 
 653     sKernelKext
->flags
.kernelComponent 
= 1; 
 654     sKernelKext
->flags
.prelinked 
= 0; 
 655     sKernelKext
->flags
.loaded 
= 1; 
 656     sKernelKext
->flags
.started 
= 1; 
 657     sKernelKext
->flags
.CPPInitialized 
= 0; 
 658     sKernelKext
->flags
.jettisonLinkeditSeg 
= 0; 
 660     sKernelKext
->kmod_info 
= &g_kernel_kmod_info
; 
 661     strlcpy(g_kernel_kmod_info
.version
, osrelease
, 
 662         sizeof(g_kernel_kmod_info
.version
)); 
 663     g_kernel_kmod_info
.size 
= kernelLength
; 
 664     g_kernel_kmod_info
.id 
= sKernelKext
->loadTag
; 
 666    /* Cons up an info dict, so we don't have to have special-case 
 669     sKernelKext
->infoDict 
= OSDictionary::withCapacity(5); 
 670     assert(sKernelKext
->infoDict
); 
 671     setResult 
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
, 
 672         sKernelKext
->bundleID
); 
 674     setResult 
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
, 
 678     scratchString 
= OSString::withCStringNoCopy(osrelease
); 
 679     assert(scratchString
); 
 680     setResult 
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
, 
 683     OSSafeReleaseNULL(scratchString
); 
 685     scratchString 
= OSString::withCStringNoCopy("mach_kernel"); 
 686     assert(scratchString
); 
 687     setResult 
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
, 
 690     OSSafeReleaseNULL(scratchString
); 
 692    /* Add the kernel kext to the bookkeeping dictionaries. Note that 
 693     * the kernel kext doesn't have a kmod_info struct. copyInfo() 
 694     * gathers info from other places anyhow. 
 696     setResult 
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
); 
 698     setResult 
= sLoadedKexts
->setObject(sKernelKext
); 
 700     sKernelKext
->release(); 
 702     registryRoot 
= IORegistryEntry::getRegistryRoot(); 
 703     kernelCPUType 
= OSNumber::withNumber( 
 704         (long long unsigned int)_mh_execute_header
.cputype
, 
 705         8 * sizeof(_mh_execute_header
.cputype
)); 
 706     kernelCPUSubtype 
= OSNumber::withNumber( 
 707         (long long unsigned int)_mh_execute_header
.cpusubtype
, 
 708         8 * sizeof(_mh_execute_header
.cpusubtype
)); 
 709     assert(registryRoot 
&& kernelCPUSubtype 
&& kernelCPUType
); 
 711     registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
); 
 712     registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
); 
 714     OSSafeRelease(kernelCPUType
); 
 715     OSSafeRelease(kernelCPUSubtype
); 
 717     timestamp 
= __OSAbsoluteTimePtr(&last_loaded_timestamp
); 
 719     timestamp 
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
); 
 721     timestamp 
= __OSAbsoluteTimePtr(&sLastWakeTime
); 
 724     OSKextLog(/* kext */ NULL
, 
 725         kOSKextLogProgressLevel 
| 
 726         kOSKextLogGeneralFlag
, 
 727         "Kext system initialized."); 
 729     notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
); 
 734 /********************************************************************* 
 735 * This could be in OSKextLib.cpp but we need to hold a lock 
 736 * while removing all the segments and sKextLock will do. 
 737 *********************************************************************/ 
 740 OSKext::removeKextBootstrap(void) 
 742     OSReturn                   result                
= kOSReturnError
; 
 744     static bool                alreadyDone           
= false; 
 746     const char               * dt_kernel_header_name 
= "Kernel-__HEADER"; 
 747     const char               * dt_kernel_symtab_name 
= "Kernel-__SYMTAB"; 
 748     kernel_mach_header_t     
* dt_mach_header        
= NULL
; 
 749     int                        dt_mach_header_size   
= 0; 
 750     struct symtab_command    
* dt_symtab             
= NULL
; 
 751     int                        dt_symtab_size        
= 0; 
 754     kernel_segment_command_t 
* seg_to_remove         
= NULL
; 
 757    /* This must be the very first thing done by this function. 
 759     IORecursiveLockLock(sKextLock
); 
 761    /* If we already did this, it's a success. 
 764         result 
= kOSReturnSuccess
; 
 768     OSKextLog(/* kext */ NULL
, 
 769         kOSKextLogProgressLevel 
| 
 770         kOSKextLogGeneralFlag
, 
 771         "Jettisoning kext bootstrap segments."); 
 774     * Dispose of unnecessary stuff that the booter didn't need to load. 
 776     dt_result 
= IODTGetLoaderInfo(dt_kernel_header_name
, 
 777         (void **)&dt_mach_header
, &dt_mach_header_size
); 
 778     if (dt_result 
== 0 && dt_mach_header
) { 
 779         IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
, 
 780             round_page_32(dt_mach_header_size
)); 
 782     dt_result 
= IODTGetLoaderInfo(dt_kernel_symtab_name
, 
 783         (void **)&dt_symtab
, &dt_symtab_size
); 
 784     if (dt_result 
== 0 && dt_symtab
) { 
 785         IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
, 
 786             round_page_32(dt_symtab_size
)); 
 790     * KLD bootstrap segment. 
 792     // xxx - should rename KLD segment 
 793     seg_to_remove 
= getsegbyname("__KLD"); 
 795         OSRuntimeUnloadCPPForSegment(seg_to_remove
); 
 798 #if   __i386__ || __x86_64__ 
 799    /* On x86, use the mapping data from the segment load command to 
 800     * unload KLD directly. 
 801     * This may invalidate any assumptions about  "avail_start" 
 802     * defining the lower bound for valid physical addresses. 
 804     if (seg_to_remove 
&& seg_to_remove
->vmaddr 
&& seg_to_remove
->vmsize
) { 
 805         // 04/18/11 - gab: <rdar://problem/9236163> 
 806         // overwrite memory occupied by KLD segment with random data before 
 808         read_random((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
); 
 809         ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
); 
 815     seg_to_remove 
= NULL
; 
 818     * Prelinked kernel's symtab (if there is one). 
 820     kernel_section_t 
* sect
; 
 821     sect 
= getsectbyname("__PRELINK", "__symtab"); 
 822     if (sect 
&& sect
->addr 
&& sect
->size
) { 
 823         ml_static_mfree(sect
->addr
, sect
->size
); 
 826     seg_to_remove 
= (kernel_segment_command_t 
*)getsegbyname("__LINKEDIT"); 
 828     /* kxld always needs the kernel's __LINKEDIT segment, but we can make it 
 829      * pageable, unless keepsyms is set.  To do that, we have to copy it from 
 830      * its booter-allocated memory, free the booter memory, reallocate proper 
 831      * managed memory, then copy the segment back in. 
 835         kern_return_t mem_result
; 
 836         void *seg_copy 
= NULL
; 
 837         void *seg_data 
= NULL
; 
 838         vm_map_offset_t seg_offset 
= 0; 
 839         vm_map_offset_t seg_copy_offset 
= 0; 
 840         vm_map_size_t seg_length 
= 0; 
 842         seg_data 
= (void *) seg_to_remove
->vmaddr
; 
 843         seg_offset 
= (vm_map_offset_t
) seg_to_remove
->vmaddr
; 
 844         seg_length 
= (vm_map_size_t
) seg_to_remove
->vmsize
; 
 846        /* Allocate space for the LINKEDIT copy. 
 848         mem_result 
= kmem_alloc(kernel_map
, (vm_offset_t 
*) &seg_copy
, 
 850         if (mem_result 
!= KERN_SUCCESS
) { 
 851             OSKextLog(/* kext */ NULL
, 
 852                 kOSKextLogErrorLevel 
| 
 853                 kOSKextLogGeneralFlag 
| kOSKextLogArchiveFlag
, 
 854                 "Can't copy __LINKEDIT segment for VM reassign."); 
 857         seg_copy_offset 
= (vm_map_offset_t
) seg_copy
; 
 861         memcpy(seg_copy
, seg_data
, seg_length
); 
 863        /* Dump the booter memory. 
 865         ml_static_mfree(seg_offset
, seg_length
); 
 867        /* Set up the VM region. 
 869         mem_result 
= vm_map_enter_mem_object( 
 872             seg_length
, /* mask */ 0,  
 873             VM_FLAGS_FIXED 
| VM_FLAGS_OVERWRITE
,  
 875             (vm_object_offset_t
) 0, 
 877             /* cur_protection */ VM_PROT_READ 
| VM_PROT_WRITE
, 
 878             /* max_protection */ VM_PROT_ALL
, 
 879             /* inheritance */ VM_INHERIT_DEFAULT
); 
 880         if ((mem_result 
!= KERN_SUCCESS
) ||  
 881             (seg_offset 
!= (vm_map_offset_t
) seg_data
)) 
 883             OSKextLog(/* kext */ NULL
, 
 884                 kOSKextLogErrorLevel 
| 
 885                 kOSKextLogGeneralFlag 
| kOSKextLogArchiveFlag
, 
 886                 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).", 
 887                 seg_data
, seg_length
, mem_result
); 
 893         memcpy(seg_data
, seg_copy
, seg_length
); 
 897         kmem_free(kernel_map
, seg_copy_offset
, seg_length
); 
 899 #else /* we are not CONFIG_KXLD */ 
 900 #error CONFIG_KXLD is expected for this arch 
 903     * Dump the LINKEDIT segment, unless keepsyms is set. 
 906         const char *dt_segment_name 
= "Kernel-__LINKEDIT"; 
 907         if (0 == IODTGetLoaderInfo(dt_segment_name
, 
 908             &segment_paddress
, &segment_size
)) { 
 910             vm_offset_t vmaddr 
= ml_static_ptovirt((vm_offset_t
)segment_paddress
); 
 911             bzero((void*)vmaddr
, segment_size
); 
 913             IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
, 
 917         OSKextLog(/* kext */ NULL
, 
 918            kOSKextLogBasicLevel 
| 
 919            kOSKextLogGeneralFlag
, 
 920            "keepsyms boot arg specified; keeping linkedit segment for symbols."); 
 922 #endif /* CONFIG_KXLD */ 
 924     seg_to_remove 
= NULL
; 
 927     result 
= kOSReturnSuccess
; 
 931    /* This must be the very last thing done before returning. 
 933     IORecursiveLockUnlock(sKextLock
); 
 938 /********************************************************************* 
 939 *********************************************************************/ 
 941 OSKext::flushNonloadedKexts( 
 942     Boolean flushPrelinkedKexts
) 
 944     OSSet                
* prelinkedKexts  
= NULL
;  // must release 
 945     OSCollectionIterator 
* kextIterator    
= NULL
;  // must release 
 946     OSCollectionIterator 
* prelinkIterator 
= NULL
;  // must release 
 947     const OSSymbol       
* thisID          
= NULL
;  // do not release 
 948     OSKext               
* thisKext        
= NULL
;  // do not release 
 951     IORecursiveLockLock(sKextLock
); 
 953     OSKextLog(/* kext */ NULL
, 
 954         kOSKextLogProgressLevel 
| 
 955         kOSKextLogKextBookkeepingFlag
, 
 956         "Flushing nonloaded kexts and other unused data."); 
 958     OSKext::considerDestroyingLinkContext(); 
 960    /* If we aren't flushing unused prelinked kexts, we have to put them 
 961     * aside while we flush everything else so make a container for them. 
 963     if (!flushPrelinkedKexts
) { 
 964         prelinkedKexts 
= OSSet::withCapacity(0); 
 965         if (!prelinkedKexts
) { 
 970    /* Set aside prelinked kexts (in-use or not) and break 
 971     * any lingering inter-kext references for nonloaded kexts 
 972     * so they have min. retain counts. 
 974     kextIterator 
= OSCollectionIterator::withCollection(sKextsByID
); 
 979     while ((thisID 
= OSDynamicCast(OSSymbol
,  
 980             kextIterator
->getNextObject()))) { 
 982         thisKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
)); 
 985             if (prelinkedKexts 
&& thisKext
->isPrelinked()) { 
 986                 prelinkedKexts
->setObject(thisKext
); 
 988             thisKext
->flushDependencies(/* forceIfLoaded */ false); 
 992    /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly. 
 994     sKextsByID
->flushCollection(); 
 996    /* Now put the loaded kexts back into the ID dictionary. 
 998     count 
= sLoadedKexts
->getCount(); 
 999     for (i 
= 0; i 
< count
; i
++) { 
1000         thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
1001         sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
); 
1004    /* Finally, put back the prelinked kexts if we saved any. 
1006     if (prelinkedKexts
) { 
1007         prelinkIterator 
= OSCollectionIterator::withCollection(prelinkedKexts
); 
1008         if (!prelinkIterator
) { 
1012         while ((thisKext 
= OSDynamicCast(OSKext
, 
1013             prelinkIterator
->getNextObject()))) { 
1015             sKextsByID
->setObject(thisKext
->getIdentifierCString(), 
1021     IORecursiveLockUnlock(sKextLock
); 
1023     OSSafeRelease(prelinkedKexts
); 
1024     OSSafeRelease(kextIterator
); 
1025     OSSafeRelease(prelinkIterator
); 
1030 /********************************************************************* 
1031 *********************************************************************/ 
1034 OSKext::setKextdActive(Boolean active
) 
1036     IORecursiveLockLock(sKextLock
); 
1037     sKextdActive 
= active
; 
1038     if (sKernelRequests
->getCount()) { 
1039         OSKext::pingKextd(); 
1041     IORecursiveLockUnlock(sKextLock
); 
1046 /********************************************************************* 
1047 * OSKextLib.cpp might need access to this someday but for now it's 
1049 *********************************************************************/ 
1051 extern void ipc_port_release_send(ipc_port_t
); 
1056 OSKext::pingKextd(void) 
1058     OSReturn    result     
= kOSReturnError
; 
1060     mach_port_t kextd_port 
= IPC_PORT_NULL
; 
1062     if (!sKextdActive
) { 
1063         result 
= kOSKextReturnDisabled
;  // basically unavailable 
1067     result 
= host_get_kextd_port(host_priv_self(), &kextd_port
); 
1068     if (result 
!= KERN_SUCCESS 
|| !IPC_PORT_VALID(kextd_port
)) { 
1069         OSKextLog(/* kext */ NULL
, 
1070             kOSKextLogErrorLevel 
| 
1072             "Can't get kextd port."); 
1076     result 
= kextd_ping(kextd_port
); 
1077     if (result 
!= KERN_SUCCESS
) { 
1078         OSKextLog(/* kext */ NULL
, 
1079             kOSKextLogErrorLevel 
| 
1081             "kextd ping failed (0x%x).", (int)result
); 
1086     if (IPC_PORT_VALID(kextd_port
)) { 
1087         ipc_port_release_send(kextd_port
); 
1094 /********************************************************************* 
1095 *********************************************************************/ 
1098 OSKext::setDeferredLoadSucceeded(Boolean succeeded
) 
1100     IORecursiveLockLock(sKextLock
); 
1101     sDeferredLoadSucceeded 
= succeeded
; 
1102     IORecursiveLockUnlock(sKextLock
); 
1107 /********************************************************************* 
1108 * Called from IOSystemShutdownNotification. 
1109 *********************************************************************/ 
1112 OSKext::willShutdown(void) 
1115     OSReturn       checkResult 
= kOSReturnError
; 
1117     OSDictionary 
* exitRequest 
= NULL
;  // must release 
1119     IORecursiveLockLock(sKextLock
); 
1121     OSKext::setLoadEnabled(false); 
1122     OSKext::setUnloadEnabled(false); 
1123     OSKext::setAutounloadsEnabled(false); 
1124     OSKext::setKernelRequestsEnabled(false); 
1127     OSKextLog(/* kext */ NULL
, 
1128         kOSKextLogProgressLevel 
| 
1129         kOSKextLogGeneralFlag
, 
1130         "System shutdown; requesting immediate kextd exit."); 
1132     checkResult 
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
, 
1134     if (checkResult 
!= kOSReturnSuccess
) { 
1137     if (!sKernelRequests
->setObject(exitRequest
)) { 
1141     OSKext::pingKextd(); 
1146     IORecursiveLockUnlock(sKextLock
); 
1148     OSSafeRelease(exitRequest
); 
1152 /********************************************************************* 
1153 *********************************************************************/ 
1156 OSKext::getLoadEnabled(void) 
1160     IORecursiveLockLock(sKextLock
); 
1161     result 
= sLoadEnabled
; 
1162     IORecursiveLockUnlock(sKextLock
); 
1166 /********************************************************************* 
1167 *********************************************************************/ 
1170 OSKext::setLoadEnabled(bool flag
) 
1174     IORecursiveLockLock(sKextLock
); 
1175     result 
= sLoadEnabled
; 
1176     sLoadEnabled 
= (flag 
? true : false); 
1178     if (sLoadEnabled 
!= result
) { 
1179         OSKextLog(/* kext */ NULL
, 
1180             kOSKextLogBasicLevel 
| 
1182             "Kext loading now %sabled.", sLoadEnabled 
? "en" : "dis"); 
1185     IORecursiveLockUnlock(sKextLock
); 
1190 /********************************************************************* 
1191 *********************************************************************/ 
1194 OSKext::getUnloadEnabled(void) 
1198     IORecursiveLockLock(sKextLock
); 
1199     result 
= sUnloadEnabled
; 
1200     IORecursiveLockUnlock(sKextLock
); 
1204 /********************************************************************* 
1205 *********************************************************************/ 
1208 OSKext::setUnloadEnabled(bool flag
) 
1212     IORecursiveLockLock(sKextLock
); 
1213     result 
= sUnloadEnabled
; 
1214     sUnloadEnabled 
= (flag 
? true : false); 
1215     IORecursiveLockUnlock(sKextLock
); 
1217     if (sUnloadEnabled 
!= result
) { 
1218         OSKextLog(/* kext */ NULL
, 
1219             kOSKextLogBasicLevel 
| 
1220             kOSKextLogGeneralFlag 
| kOSKextLogLoadFlag
, 
1221             "Kext unloading now %sabled.", sUnloadEnabled 
? "en" : "dis"); 
1227 /********************************************************************* 
1228 * Do not call any function that takes sKextLock here! 
1229 *********************************************************************/ 
1232 OSKext::getAutounloadEnabled(void) 
1236     IORecursiveLockLock(sKextInnerLock
); 
1237     result 
= sAutounloadEnabled 
? true : false; 
1238     IORecursiveLockUnlock(sKextInnerLock
); 
1242 /********************************************************************* 
1243 * Do not call any function that takes sKextLock here! 
1244 *********************************************************************/ 
1247 OSKext::setAutounloadsEnabled(bool flag
) 
1251     IORecursiveLockLock(sKextInnerLock
); 
1253     result 
= sAutounloadEnabled
; 
1254     sAutounloadEnabled 
= (flag 
? true : false); 
1255     if (!sAutounloadEnabled 
&& sUnloadCallout
) { 
1256         thread_call_cancel(sUnloadCallout
); 
1259     if (sAutounloadEnabled 
!= result
) { 
1260         OSKextLog(/* kext */ NULL
, 
1261             kOSKextLogBasicLevel 
| 
1262             kOSKextLogGeneralFlag 
| kOSKextLogLoadFlag
, 
1263             "Kext autounloading now %sabled.", 
1264             sAutounloadEnabled 
? "en" : "dis"); 
1267     IORecursiveLockUnlock(sKextInnerLock
); 
1272 /********************************************************************* 
1273 *********************************************************************/ 
1274 /* instance method operating on OSKext field */ 
1276 OSKext::setAutounloadEnabled(bool flag
) 
1278     bool result 
= flags
.autounloadEnabled 
? true : false; 
1279     flags
.autounloadEnabled 
= flag 
? 1 : 0; 
1281     if (result 
!= (flag 
? true : false)) { 
1283             kOSKextLogProgressLevel 
| 
1284             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
1285             "Autounloading for kext %s now %sabled.", 
1286             getIdentifierCString(), 
1287             flags
.autounloadEnabled 
? "en" : "dis"); 
1292 /********************************************************************* 
1293 *********************************************************************/ 
1296 OSKext::setKernelRequestsEnabled(bool flag
) 
1300     IORecursiveLockLock(sKextLock
); 
1301     result 
= sKernelRequestsEnabled
; 
1302     sKernelRequestsEnabled 
= flag 
? true : false; 
1304     if (sKernelRequestsEnabled 
!= result
) { 
1305         OSKextLog(/* kext */ NULL
, 
1306             kOSKextLogBasicLevel 
| 
1307             kOSKextLogGeneralFlag
, 
1308             "Kernel requests now %sabled.", 
1309             sKernelRequestsEnabled 
? "en" : "dis"); 
1311     IORecursiveLockUnlock(sKextLock
); 
1315 /********************************************************************* 
1316 *********************************************************************/ 
1319 OSKext::getKernelRequestsEnabled(void) 
1323     IORecursiveLockLock(sKextLock
); 
1324     result 
= sKernelRequestsEnabled
; 
1325     IORecursiveLockUnlock(sKextLock
); 
1330 #pragma mark Kext Life Cycle 
1332 /********************************************************************* 
1333 *********************************************************************/ 
1335 OSKext::withPrelinkedInfoDict( 
1336     OSDictionary 
* anInfoDict
) 
1338     OSKext 
* newKext 
= new OSKext
; 
1340     if (newKext 
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
)) { 
1348 /********************************************************************* 
1349 *********************************************************************/ 
1351 OSKext::initWithPrelinkedInfoDict( 
1352     OSDictionary 
* anInfoDict
) 
1354     bool            result              
= false; 
1355     OSString      
* kextPath            
= NULL
;  // do not release 
1356     OSNumber      
* addressNum          
= NULL
;  // reused; do not release 
1357     OSNumber      
* lengthNum           
= NULL
;  // reused; do not release 
1358     void          * data                
= NULL
;  // do not free 
1359     void          * srcData             
= NULL
;  // do not free 
1360     OSData        
* prelinkedExecutable 
= NULL
;  // must release 
1361     uint32_t        length              
= 0;     // reused 
1363     if (!super::init()) { 
1367    /* Get the path. Don't look for an arch-specific path property. 
1369     kextPath 
= OSDynamicCast(OSString
, 
1370         anInfoDict
->getObject(kPrelinkBundlePathKey
)); 
1372     if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) { 
1375 #if KASLR_KEXT_DEBUG 
1376     IOLog("kaslr: kext %s \n", getIdentifierCString()); 
1379    /* Also get the executable's bundle-relative path if present. 
1380     * Don't look for an arch-specific path property. 
1382     executableRelPath 
= OSDynamicCast(OSString
, 
1383         anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
)); 
1384     if (executableRelPath
) { 
1385         executableRelPath
->retain(); 
1388    /* Don't need the paths to be in the info dictionary any more. 
1390     anInfoDict
->removeObject(kPrelinkBundlePathKey
); 
1391     anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
); 
1393    /* Create an OSData wrapper around the linked executable. 
1395     addressNum 
= OSDynamicCast(OSNumber
, 
1396         anInfoDict
->getObject(kPrelinkExecutableLoadKey
)); 
1398         lengthNum 
= OSDynamicCast(OSNumber
, 
1399             anInfoDict
->getObject(kPrelinkExecutableSizeKey
)); 
1402                 kOSKextLogErrorLevel 
| 
1403                 kOSKextLogArchiveFlag
, 
1404                 "Kext %s can't find prelinked kext executable size.", 
1405                 getIdentifierCString()); 
1409         data 
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
); 
1410         length 
= (uint32_t) (lengthNum
->unsigned32BitValue()); 
1412 #if KASLR_KEXT_DEBUG 
1413         IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",  
1414               (unsigned long)VM_KERNEL_UNSLIDE(data
),  
1415               (unsigned long)data
, 
1419         anInfoDict
->removeObject(kPrelinkExecutableLoadKey
); 
1420         anInfoDict
->removeObject(kPrelinkExecutableSizeKey
); 
1422        /* If the kext's load address differs from its source address, allocate 
1423         * space in the kext map at the load address and copy the kext over. 
1425         addressNum 
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
)); 
1427             srcData 
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
); 
1429 #if KASLR_KEXT_DEBUG 
1430             IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",  
1431                   (unsigned long)VM_KERNEL_UNSLIDE(srcData
),  
1432                   (unsigned long)srcData
); 
1435             if (data 
!= srcData
) { 
1437                 kern_return_t alloc_result
; 
1439                 alloc_result 
= kext_alloc((vm_offset_t 
*)&data
, length
, /* fixed */ TRUE
); 
1440                 if (alloc_result 
!= KERN_SUCCESS
) { 
1442                         kOSKextLogErrorLevel 
| kOSKextLogGeneralFlag
, 
1443                         "Failed to allocate space for prelinked kext %s.", 
1444                         getIdentifierCString()); 
1447                 memcpy(data
, srcData
, length
); 
1450                     kOSKextLogErrorLevel 
| kOSKextLogGeneralFlag
, 
1451                     "Error: prelinked kext %s - source and load addresses " 
1452                     "differ on ILP32 architecture.", 
1453                     getIdentifierCString()); 
1455 #endif /* __LP64__ */ 
1458             anInfoDict
->removeObject(kPrelinkExecutableSourceKey
); 
1461         prelinkedExecutable 
= OSData::withBytesNoCopy(data
, length
); 
1462         if (!prelinkedExecutable
) { 
1464                 kOSKextLogErrorLevel 
| 
1465                 kOSKextLogGeneralFlag 
| kOSKextLogArchiveFlag
, 
1466                 "Kext %s failed to create executable wrapper.", 
1467                 getIdentifierCString()); 
1472         prelinkedExecutable
->setDeallocFunction(osdata_kext_free
); 
1474         prelinkedExecutable
->setDeallocFunction(osdata_phys_free
); 
1476         setLinkedExecutable(prelinkedExecutable
); 
1478         addressNum 
= OSDynamicCast(OSNumber
, 
1479             anInfoDict
->getObject(kPrelinkKmodInfoKey
)); 
1482                 kOSKextLogErrorLevel 
| 
1483                 kOSKextLogArchiveFlag
,  
1484                 "Kext %s can't find prelinked kext kmod_info address.", 
1485                 getIdentifierCString()); 
1489         if (addressNum
->unsigned64BitValue() != 0) { 
1490             kmod_info 
= (kmod_info_t 
*) (intptr_t) (addressNum
->unsigned64BitValue() + vm_kernel_slide
); 
1491             kmod_info
->address 
+= vm_kernel_slide
; 
1492 #if KASLR_KEXT_DEBUG 
1493             IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",  
1494                   (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
),  
1495                   (unsigned long)kmod_info
); 
1496             IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",  
1497                   (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),  
1498                   (unsigned long)kmod_info
->address
); 
1502         anInfoDict
->removeObject(kPrelinkKmodInfoKey
); 
1505    /* If the plist has a UUID for an interface, save that off. 
1507     if (isInterface()) { 
1508         interfaceUUID 
= OSDynamicCast(OSData
, 
1509             anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
)); 
1510         if (interfaceUUID
) { 
1511             interfaceUUID
->retain(); 
1512             anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
); 
1516     flags
.prelinked 
= true; 
1518    /* If we created a kext from prelink info, 
1519     * we must be booting from a prelinked kernel. 
1521     sPrelinkBoot 
= true; 
1523     result 
= registerIdentifier(); 
1526     OSSafeRelease(prelinkedExecutable
); 
1531 /********************************************************************* 
1532 *********************************************************************/ 
1534 OSKext::withBooterData( 
1535     OSString 
* deviceTreeName
, 
1536     OSData   
* booterData
) 
1538     OSKext 
* newKext 
= new OSKext
; 
1540     if (newKext 
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) { 
1548 /********************************************************************* 
1549 *********************************************************************/ 
1550 typedef struct _BooterKextFileInfo 
{ 
1551     uint32_t  infoDictPhysAddr
; 
1552     uint32_t  infoDictLength
; 
1553     uint32_t  executablePhysAddr
; 
1554     uint32_t  executableLength
; 
1555     uint32_t  bundlePathPhysAddr
; 
1556     uint32_t  bundlePathLength
; 
1557 } _BooterKextFileInfo
; 
1560 OSKext::initWithBooterData( 
1561     OSString 
* deviceTreeName
, 
1562     OSData   
* booterData
) 
1564     bool                  result         
= false; 
1565     _BooterKextFileInfo 
* kextFileInfo   
= NULL
;  // do not free 
1566     char                * infoDictAddr   
= NULL
;  // do not free 
1567     void                * executableAddr 
= NULL
;  // do not free 
1568     char                * bundlePathAddr 
= NULL
;  // do not free 
1570     OSObject            
* parsedXML      
= NULL
;  // must release 
1571     OSDictionary        
* theInfoDict    
= NULL
;  // do not release 
1572     OSString            
* kextPath       
= NULL
;  // must release 
1573     OSString            
* errorString    
= NULL
;  // must release 
1574     OSData              
* executable     
= NULL
;  // must release 
1576     if (!super::init()) { 
1580     kextFileInfo 
= (_BooterKextFileInfo 
*)booterData
->getBytesNoCopy(); 
1581     if (!kextFileInfo
) { 
1583             kOSKextLogErrorLevel 
| 
1584             kOSKextLogGeneralFlag
,  
1585             "No booter-provided data for kext device tree entry %s.", 
1586             deviceTreeName
->getCStringNoCopy()); 
1590    /* The info plist must exist or we can't read the kext. 
1592     if (!kextFileInfo
->infoDictPhysAddr 
|| !kextFileInfo
->infoDictLength
) { 
1594             kOSKextLogErrorLevel 
| 
1595             kOSKextLogGeneralFlag
,  
1596             "No kext info dictionary for booter device tree entry %s.", 
1597             deviceTreeName
->getCStringNoCopy()); 
1601     infoDictAddr 
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
); 
1602     if (!infoDictAddr
) { 
1604             kOSKextLogErrorLevel 
| 
1605             kOSKextLogGeneralFlag
,  
1606             "Can't translate physical address 0x%x of kext info dictionary " 
1607             "for device tree entry %s.", 
1608             (int)kextFileInfo
->infoDictPhysAddr
, 
1609             deviceTreeName
->getCStringNoCopy()); 
1613     parsedXML 
= OSUnserializeXML(infoDictAddr
, &errorString
); 
1615         theInfoDict 
= OSDynamicCast(OSDictionary
, parsedXML
); 
1618         const char * errorCString 
= "(unknown error)"; 
1620         if (errorString 
&& errorString
->getCStringNoCopy()) { 
1621             errorCString 
= errorString
->getCStringNoCopy(); 
1622         } else if (parsedXML
) { 
1623             errorCString 
= "not a dictionary"; 
1626             kOSKextLogErrorLevel 
| 
1627             kOSKextLogGeneralFlag
,  
1628             "Error unserializing info dictionary for device tree entry %s: %s.", 
1629             deviceTreeName
->getCStringNoCopy(), errorCString
); 
1633    /* A bundle path is not mandatory. 
1635     if (kextFileInfo
->bundlePathPhysAddr 
&& kextFileInfo
->bundlePathLength
) { 
1636         bundlePathAddr 
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
); 
1637         if (!bundlePathAddr
) { 
1639                 kOSKextLogErrorLevel 
| 
1640                 kOSKextLogGeneralFlag
,  
1641                 "Can't translate physical address 0x%x of kext bundle path " 
1642                 "for device tree entry %s.", 
1643                 (int)kextFileInfo
->bundlePathPhysAddr
, 
1644                 deviceTreeName
->getCStringNoCopy()); 
1647         bundlePathAddr
[kextFileInfo
->bundlePathLength
-1] = '\0'; // just in case! 
1649         kextPath 
= OSString::withCString(bundlePathAddr
); 
1652                 kOSKextLogErrorLevel 
| 
1653                 kOSKextLogGeneralFlag
,  
1654                 "Failed to create wrapper for device tree entry %s kext path %s.", 
1655                 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
); 
1660     if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) { 
1664    /* An executable is not mandatory. 
1666     if (kextFileInfo
->executablePhysAddr 
&& kextFileInfo
->executableLength
) { 
1667         executableAddr 
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
); 
1668         if (!executableAddr
) { 
1670                 kOSKextLogErrorLevel 
| 
1671                 kOSKextLogGeneralFlag
,  
1672                 "Can't translate physical address 0x%x of kext executable " 
1673                 "for device tree entry %s.", 
1674                 (int)kextFileInfo
->executablePhysAddr
, 
1675                 deviceTreeName
->getCStringNoCopy()); 
1679         executable 
= OSData::withBytesNoCopy(executableAddr
, 
1680             kextFileInfo
->executableLength
); 
1683                 kOSKextLogErrorLevel 
| 
1684                 kOSKextLogGeneralFlag
,  
1685                 "Failed to create executable wrapper for device tree entry %s.", 
1686                 deviceTreeName
->getCStringNoCopy()); 
1690        /* A kext with an executable needs to retain the whole booterData 
1691         * object to keep the executable in memory. 
1693         if (!setExecutable(executable
, booterData
)) { 
1695                 kOSKextLogErrorLevel 
| 
1696                 kOSKextLogGeneralFlag
,  
1697                 "Failed to set kext executable for device tree entry %s.", 
1698                 deviceTreeName
->getCStringNoCopy()); 
1703     result 
= registerIdentifier(); 
1706     OSSafeRelease(parsedXML
); 
1707     OSSafeRelease(kextPath
); 
1708     OSSafeRelease(errorString
); 
1709     OSSafeRelease(executable
); 
1714 /********************************************************************* 
1715 *********************************************************************/ 
1717 OSKext::registerIdentifier(void) 
1719     bool            result              
= false; 
1720     OSKext        
* existingKext        
= NULL
;  // do not release 
1721     bool            existingIsLoaded    
= false; 
1722     bool            existingIsPrelinked 
= false; 
1723     OSKextVersion   newVersion          
= -1; 
1724     OSKextVersion   existingVersion     
= -1; 
1725     char            newVersionCString
[kOSKextVersionMaxLength
]; 
1726     char            existingVersionCString
[kOSKextVersionMaxLength
]; 
1727     OSData        
* newUUID             
= NULL
;  // must release 
1728     OSData        
* existingUUID        
= NULL
;  // must release 
1730     IORecursiveLockLock(sKextLock
); 
1732    /* Get the new kext's version for checks & log messages. 
1734     newVersion 
= getVersion(); 
1735     OSKextVersionGetString(newVersion
, newVersionCString
, 
1736         kOSKextVersionMaxLength
); 
1738    /* If we don't have an existing kext with this identifier, 
1739     * just record the new kext and we're done! 
1741     existingKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
)); 
1742     if (!existingKext
) { 
1743         sKextsByID
->setObject(bundleID
, this); 
1748    /* Get the existing kext's version for checks & log messages. 
1750     existingVersion 
= existingKext
->getVersion(); 
1751     OSKextVersionGetString(existingVersion
, 
1752         existingVersionCString
, kOSKextVersionMaxLength
); 
1754     existingIsLoaded 
= existingKext
->isLoaded(); 
1755     existingIsPrelinked 
= existingKext
->isPrelinked(); 
1757    /* If we have a kext with this identifier that's already loaded/prelinked, 
1758     * we can't use the new one, but let's be really thorough and check how 
1759     * the two are related for a precise diagnostic log message. 
1761     * Note that user space can't find out about nonloaded prelinked kexts, 
1762     * so in this case we log a message when new & existing are equivalent 
1763     * at the step rather than warning level, because we are always going 
1764     * be getting a copy of the kext in the user load request mkext. 
1766     if (existingIsLoaded 
|| existingIsPrelinked
) { 
1767         bool sameVersion 
= (newVersion 
== existingVersion
); 
1768         bool sameExecutable 
= true;  // assume true unless we have UUIDs 
1770        /* Only get the UUID if the existing kext is loaded. Doing so 
1771         * might have to uncompress an mkext executable and we shouldn't 
1772         * take that hit when neither kext is loaded. 
1774         newUUID 
= copyUUID(); 
1775         existingUUID 
= existingKext
->copyUUID(); 
1777        /* I'm entirely too paranoid about checking equivalence of executables, 
1778         * but I remember nasty problems with it in the past. 
1780         * - If we have UUIDs for both kexts, compare them. 
1781         * - If only one kext has a UUID, they're definitely different. 
1783         if (newUUID 
&& existingUUID
) { 
1784             sameExecutable 
= newUUID
->isEqualTo(existingUUID
); 
1785         } else if (newUUID 
|| existingUUID
) { 
1786             sameExecutable 
= false; 
1789         if (!newUUID 
&& !existingUUID
) { 
1791            /* If there are no UUIDs, we can't really tell that the executables 
1792             * are *different* without a lot of work; the loaded kext's 
1793             * unrelocated executable is no longer around (and we never had it 
1794             * in-kernel for a prelinked kext). We certainly don't want to do 
1795             * a whole fake link for the new kext just to compare, either. 
1798             OSKextVersionGetString(version
, newVersionCString
, 
1799                 sizeof(newVersionCString
)); 
1801                 kOSKextLogWarningLevel 
| 
1802                 kOSKextLogKextBookkeepingFlag
, 
1803                 "Notice - new kext %s, v%s matches %s kext " 
1804                 "but can't determine if executables are the same (no UUIDs).", 
1805                 getIdentifierCString(), 
1807                 (existingIsLoaded 
? "loaded" : "prelinked")); 
1810         if (sameVersion 
&& sameExecutable
) { 
1812                 (existingIsLoaded 
? kOSKextLogWarningLevel 
: kOSKextLogStepLevel
) | 
1813                 kOSKextLogKextBookkeepingFlag
, 
1814                 "Refusing new kext %s, v%s: a %s copy is already present " 
1815                 "(same version and executable).", 
1816                 getIdentifierCString(), newVersionCString
, 
1817                 (existingIsLoaded 
? "loaded" : "prelinked")); 
1820                /* This condition is significant so log it under warnings. 
1823                     kOSKextLogWarningLevel 
| 
1824                     kOSKextLogKextBookkeepingFlag
, 
1825                     "Refusing new kext %s, v%s: already have %s v%s.", 
1826                     getIdentifierCString(), 
1828                     (existingIsLoaded 
? "loaded" : "prelinked"), 
1829                     existingVersionCString
); 
1831                /* This condition is significant so log it under warnings. 
1834                     kOSKextLogWarningLevel 
| kOSKextLogKextBookkeepingFlag
, 
1835                     "Refusing new kext %s, v%s: a %s copy with a different " 
1836                     "executable UUID is already present.", 
1837                     getIdentifierCString(), newVersionCString
, 
1838                     (existingIsLoaded 
? "loaded" : "prelinked")); 
1842     } /* if (existingIsLoaded || existingIsPrelinked) */ 
1844    /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether 
1845     * user loads are happening or if we're still in early boot. User agents are 
1846     * supposed to resolve dependencies topside and include only the exact 
1847     * kexts needed; so we always accept the new kext (in fact we should never 
1848     * see an older unloaded copy hanging around). 
1850     if (sUserLoadsActive
) { 
1851         sKextsByID
->setObject(bundleID
, this); 
1855             kOSKextLogStepLevel 
| 
1856             kOSKextLogKextBookkeepingFlag
, 
1857             "Dropping old copy of kext %s (v%s) for newly-added (v%s).", 
1858             getIdentifierCString(), 
1859             existingVersionCString
, 
1865    /* During early boot, the kext with the highest version always wins out. 
1866     * Prelinked kernels will never hit this, but mkexts and booter-read 
1867     * kexts might have duplicates. 
1869     if (newVersion 
> existingVersion
) { 
1870         sKextsByID
->setObject(bundleID
, this); 
1874             kOSKextLogStepLevel 
| 
1875             kOSKextLogKextBookkeepingFlag
, 
1876             "Dropping lower version (v%s) of registered kext %s for higher (v%s).", 
1877             existingVersionCString
, 
1878             getIdentifierCString(), 
1883             kOSKextLogStepLevel 
| 
1884             kOSKextLogKextBookkeepingFlag
, 
1885             "Kext %s is already registered with a higher/same version (v%s); " 
1886             "dropping newly-added (v%s).", 
1887             getIdentifierCString(), 
1888             existingVersionCString
, 
1892    /* result has been set appropriately by now. */ 
1896     IORecursiveLockUnlock(sKextLock
); 
1900             kOSKextLogStepLevel 
| 
1901             kOSKextLogKextBookkeepingFlag
, 
1902             "Kext %s, v%s registered and available for loading.", 
1903             getIdentifierCString(), newVersionCString
); 
1906     OSSafeRelease(newUUID
); 
1907     OSSafeRelease(existingUUID
); 
1912 /********************************************************************* 
1913 * Does the bare minimum validation to look up a kext. 
1914 * All other validation is done on the spot as needed. 
1915 **********************************************************************/ 
1917 OSKext::setInfoDictionaryAndPath( 
1918     OSDictionary 
* aDictionary
, 
1921     bool           result                   
= false; 
1922     OSString     
* bundleIDString           
= NULL
;  // do not release 
1923     OSString     
* versionString            
= NULL
;  // do not release 
1924     OSString     
* compatibleVersionString  
= NULL
;  // do not release 
1925     const char   * versionCString           
= NULL
;  // do not free 
1926     const char   * compatibleVersionCString 
= NULL
;  // do not free 
1927     OSBoolean    
* scratchBool              
= NULL
;  // do not release 
1928     OSDictionary 
* scratchDict              
= NULL
;  // do not release 
1931         panic("Attempt to set info dictionary on a kext " 
1932             "that already has one (%s).", 
1933             getIdentifierCString()); 
1936     if (!aDictionary 
|| !OSDynamicCast(OSDictionary
, aDictionary
)) { 
1940     infoDict 
= aDictionary
; 
1943    /* Check right away if the info dictionary has any log flags. 
1945     scratchBool 
= OSDynamicCast(OSBoolean
, 
1946         getPropertyForHostArch(kOSBundleEnableKextLoggingKey
)); 
1947     if (scratchBool 
== kOSBooleanTrue
) { 
1948         flags
.loggingEnabled 
= 1; 
1951    /* The very next thing to get is the bundle identifier. Unlike 
1952     * in user space, a kext with no bundle identifier gets axed 
1955     bundleIDString 
= OSDynamicCast(OSString
, 
1956         getPropertyForHostArch(kCFBundleIdentifierKey
)); 
1957     if (!bundleIDString
) { 
1959             kOSKextLogErrorLevel 
| 
1960             kOSKextLogValidationFlag
, 
1961             "CFBundleIdentifier missing/invalid type in kext %s.", 
1962             aPath 
? aPath
->getCStringNoCopy() : "(unknown)"); 
1965     bundleID 
= OSSymbol::withString(bundleIDString
); 
1968             kOSKextLogErrorLevel 
| 
1969             kOSKextLogValidationFlag
, 
1970             "Can't copy bundle identifier as symbol for kext %s.", 
1971             bundleIDString
->getCStringNoCopy()); 
1975    /* Save the path if we got one (it should always be available but it's 
1976     * just something nice to have for bookkeeping). 
1984     * Minimal validation to initialize. We'll do other validation on the spot. 
1986     if (bundleID
->getLength() >= KMOD_MAX_NAME
) { 
1988             kOSKextLogErrorLevel 
| 
1989             kOSKextLogValidationFlag
, 
1990             "Kext %s error - CFBundleIdentifier over max length %d.", 
1991             getIdentifierCString(), KMOD_MAX_NAME 
- 1); 
1995     version 
= compatibleVersion 
= -1; 
1997     versionString 
= OSDynamicCast(OSString
, 
1998         getPropertyForHostArch(kCFBundleVersionKey
)); 
1999     if (!versionString
) { 
2001             kOSKextLogErrorLevel 
| 
2002             kOSKextLogValidationFlag
, 
2003             "Kext %s error - CFBundleVersion missing/invalid type.", 
2004             getIdentifierCString()); 
2007     versionCString 
= versionString
->getCStringNoCopy(); 
2008     version 
= OSKextParseVersionString(versionCString
); 
2011             kOSKextLogErrorLevel 
| 
2012             kOSKextLogValidationFlag
, 
2013             "Kext %s error - CFBundleVersion bad value '%s'.", 
2014             getIdentifierCString(), versionCString
); 
2018     compatibleVersion 
= -1;  // set to illegal value for kexts that don't have 
2020     compatibleVersionString 
= OSDynamicCast(OSString
, 
2021         getPropertyForHostArch(kOSBundleCompatibleVersionKey
)); 
2022     if (compatibleVersionString
) { 
2023         compatibleVersionCString 
= compatibleVersionString
->getCStringNoCopy(); 
2024         compatibleVersion 
= OSKextParseVersionString(compatibleVersionCString
); 
2025         if (compatibleVersion 
< 0) { 
2027                 kOSKextLogErrorLevel 
| 
2028                 kOSKextLogValidationFlag
, 
2029                 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.", 
2030                 getIdentifierCString(), compatibleVersionCString
); 
2034         if (compatibleVersion 
> version
) { 
2036                 kOSKextLogErrorLevel 
| 
2037                 kOSKextLogValidationFlag
, 
2038                 "Kext %s error - %s %s > %s %s (must be <=).", 
2039                 getIdentifierCString(), 
2040                 kOSBundleCompatibleVersionKey
, compatibleVersionCString
, 
2041                 kCFBundleVersionKey
,  versionCString
); 
2046    /* Set flags for later use if the infoDict gets flushed. We only 
2047     * check for true values, not false ones(!) 
2049     scratchBool 
= OSDynamicCast(OSBoolean
, 
2050         getPropertyForHostArch(kOSBundleIsInterfaceKey
)); 
2051     if (scratchBool 
== kOSBooleanTrue
) { 
2052         flags
.interface 
= 1; 
2055     scratchBool 
= OSDynamicCast(OSBoolean
, 
2056         getPropertyForHostArch(kOSKernelResourceKey
)); 
2057     if (scratchBool 
== kOSBooleanTrue
) { 
2058         flags
.kernelComponent 
= 1; 
2059         flags
.interface 
= 1;  // xxx - hm. the kernel itself isn't an interface... 
2062        /* A kernel component has one implicit dependency on the kernel. 
2064         flags
.hasAllDependencies 
= 1; 
2067    /* Make sure common string values in personalities are uniqued to OSSymbols. 
2069     scratchDict 
= OSDynamicCast(OSDictionary
,  
2070         getPropertyForHostArch(kIOKitPersonalitiesKey
)); 
2072         uniquePersonalityProperties(scratchDict
); 
2082 /********************************************************************* 
2083 * Not used for prelinked kernel boot as there is no unrelocated 
2085 *********************************************************************/ 
2087 OSKext::setExecutable( 
2088     OSData 
* anExecutable
, 
2089     OSData 
* externalData
, 
2090     bool     externalDataIsMkext
) 
2092     bool         result        
= false; 
2093     const char * executableKey 
= NULL
;  // do not free 
2095     if (!anExecutable
) { 
2096         infoDict
->removeObject(_kOSKextExecutableKey
); 
2097         infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
); 
2098         infoDict
->removeObject(_kOSKextExecutableExternalDataKey
); 
2103     if (infoDict
->getObject(_kOSKextExecutableKey
) || 
2104         infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) { 
2106         panic("Attempt to set an executable on a kext " 
2107             "that already has one (%s).", 
2108             getIdentifierCString()); 
2112     if (externalDataIsMkext
) { 
2113         executableKey 
= _kOSKextMkextExecutableReferenceKey
; 
2115         executableKey 
= _kOSKextExecutableKey
; 
2119         infoDict
->setObject(executableKey
, anExecutable
); 
2121             infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
); 
2131 /********************************************************************* 
2132 *********************************************************************/ 
2134 uniqueStringPlistProperty(OSDictionary 
* dict
, const char * key
) 
2136     OSString       
* stringValue 
= NULL
;  // do not release 
2137     const OSSymbol 
* symbolValue 
= NULL
;  // must release 
2139     stringValue 
= OSDynamicCast(OSString
, dict
->getObject(key
)); 
2144     symbolValue 
= OSSymbol::withString(stringValue
); 
2149     dict
->setObject(key
, symbolValue
); 
2152     if (symbolValue
) symbolValue
->release(); 
2157 /********************************************************************* 
2158 *********************************************************************/ 
2160 uniqueStringPlistProperty(OSDictionary 
* dict
, const OSString 
* key
) 
2162     OSString       
* stringValue 
= NULL
;  // do not release 
2163     const OSSymbol 
* symbolValue 
= NULL
;  // must release 
2165     stringValue 
= OSDynamicCast(OSString
, dict
->getObject(key
)); 
2170     symbolValue 
= OSSymbol::withString(stringValue
); 
2175     dict
->setObject(key
, symbolValue
); 
2178     if (symbolValue
) symbolValue
->release(); 
2183 /********************************************************************* 
2184 * Replace common personality property values with uniqued instances 
2185 * to save on wired memory. 
2186 *********************************************************************/ 
2189 OSKext::uniquePersonalityProperties(OSDictionary 
* personalityDict
) 
2191    /* Properties every personality has. 
2193     uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
); 
2194     uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
); 
2195     uniqueStringPlistProperty(personalityDict
, gIOClassKey
); 
2197    /* Other commonly used properties. 
2199     uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
); 
2200     uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
); 
2201     uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
); 
2203     uniqueStringPlistProperty(personalityDict
, "HIDDefaultBehavior"); 
2204     uniqueStringPlistProperty(personalityDict
, "HIDPointerAccelerationType"); 
2205     uniqueStringPlistProperty(personalityDict
, "HIDRemoteControlType"); 
2206     uniqueStringPlistProperty(personalityDict
, "HIDScrollAccelerationType"); 
2207     uniqueStringPlistProperty(personalityDict
, "IOPersonalityPublisher");  
2208     uniqueStringPlistProperty(personalityDict
, "Physical Interconnect"); 
2209     uniqueStringPlistProperty(personalityDict
, "Physical Interconnect Location"); 
2210     uniqueStringPlistProperty(personalityDict
, "Vendor"); 
2211     uniqueStringPlistProperty(personalityDict
, "Vendor Identification"); 
2212     uniqueStringPlistProperty(personalityDict
, "Vendor Name"); 
2213     uniqueStringPlistProperty(personalityDict
, "bConfigurationValue"); 
2214     uniqueStringPlistProperty(personalityDict
, "bInterfaceNumber"); 
2215     uniqueStringPlistProperty(personalityDict
, "idProduct"); 
2220 /********************************************************************* 
2221 *********************************************************************/ 
2226         panic("Attempt to free loaded kext %s.", getIdentifierCString()); 
2229     OSSafeRelease(infoDict
); 
2230     OSSafeRelease(bundleID
); 
2231     OSSafeRelease(path
); 
2232     OSSafeRelease(executableRelPath
); 
2233     OSSafeRelease(dependencies
); 
2234     OSSafeRelease(linkedExecutable
); 
2235     OSSafeRelease(metaClasses
); 
2236     OSSafeRelease(interfaceUUID
); 
2238     if (isInterface() && kmod_info
) { 
2239         kfree(kmod_info
, sizeof(kmod_info_t
)); 
2247 #pragma mark Mkext files 
2249 /********************************************************************* 
2250 *********************************************************************/ 
2252 OSKext::readMkextArchive(OSData 
* mkextData
, 
2253     uint32_t * checksumPtr
) 
2255     OSReturn       result       
= kOSKextReturnBadData
; 
2256     uint32_t       mkextLength  
= 0; 
2257     mkext_header 
* mkextHeader  
= 0;   // do not free 
2258     uint32_t       mkextVersion 
= 0; 
2260    /* Note default return of kOSKextReturnBadData above. 
2262     mkextLength 
= mkextData
->getLength(); 
2263     if (mkextLength 
< sizeof(mkext_basic_header
)) { 
2264         OSKextLog(/* kext */ NULL
, 
2265             kOSKextLogErrorLevel 
| 
2266             kOSKextLogArchiveFlag
, 
2267             "Mkext archive too small to be valid."); 
2271     mkextHeader 
= (mkext_header 
*)mkextData
->getBytesNoCopy(); 
2273     if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC 
|| 
2274         MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) { 
2275         OSKextLog(/* kext */ NULL
, 
2276             kOSKextLogErrorLevel 
| 
2277             kOSKextLogArchiveFlag
, 
2278             "Mkext archive has invalid magic or signature."); 
2282     if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) { 
2283         OSKextLog(/* kext */ NULL
, 
2284             kOSKextLogErrorLevel 
| 
2285             kOSKextLogArchiveFlag
, 
2286             "Mkext archive recorded length doesn't match actual file length."); 
2290     mkextVersion 
= MKEXT_GET_VERSION(mkextHeader
); 
2292     if (mkextVersion 
== MKEXT_VERS_2
) { 
2293         result 
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
); 
2294     } else if (mkextVersion 
== MKEXT_VERS_1
) { 
2295         result 
= OSKext::readMkext1Archive(mkextData
, checksumPtr
); 
2297         OSKextLog(/* kext */ NULL
, 
2298             kOSKextLogErrorLevel 
| 
2299             kOSKextLogArchiveFlag
, 
2300             "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
); 
2301         result 
= kOSKextReturnUnsupported
; 
2308 /********************************************************************* 
2309 * Assumes magic, signature, version, length have been checked. 
2311 * Doesn't do as much bounds-checking as it should, but we're dropping 
2312 * mkext1 support from the kernel for SnowLeopard soon. 
2314 * Should keep track of all kexts created so far, and if we hit a 
2315 * fatal error halfway through, remove those kexts. If we've dropped 
2316 * an older version that had already been read, whoops! Might want to 
2317 * add a level of buffering? 
2318 *********************************************************************/ 
2321 OSKext::readMkext1Archive( 
2323     uint32_t * checksumPtr
) 
2325     OSReturn        result              
= kOSReturnError
; 
2326     uint32_t        mkextLength
; 
2327     mkext1_header 
* mkextHeader         
= 0;  // do not free 
2328     void          * mkextEnd            
= 0;  // do not free 
2329     uint32_t        mkextVersion
; 
2330     uint8_t       * crc_address         
= 0; 
2332     uint32_t        numKexts            
= 0; 
2334     OSData        
* infoDictDataObject  
= NULL
;  // must release 
2335     OSObject      
* parsedXML           
= NULL
;  // must release 
2336     OSDictionary  
* infoDict            
= NULL
;  // do not release 
2337     OSString      
* errorString         
= NULL
;  // must release 
2338     OSData        
* mkextExecutableInfo 
= NULL
;  // must release 
2339     OSKext        
* theKext             
= NULL
;  // must release 
2341     mkextLength 
= mkextData
->getLength(); 
2342     mkextHeader 
= (mkext1_header 
*)mkextData
->getBytesNoCopy(); 
2343     mkextEnd 
= (char *)mkextHeader 
+ mkextLength
; 
2344     mkextVersion 
= OSSwapBigToHostInt32(mkextHeader
->version
); 
2346     crc_address 
= (u_int8_t 
*)&mkextHeader
->version
; 
2347     checksum 
= mkext_adler32(crc_address
, 
2348         (uintptr_t)mkextHeader 
+ 
2349         OSSwapBigToHostInt32(mkextHeader
->length
) - (uintptr_t)crc_address
); 
2351     if (OSSwapBigToHostInt32(mkextHeader
->adler32
) != checksum
) { 
2352         OSKextLog(/* kext */ NULL
, 
2353             kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2354             "Kext archive has a bad checksum."); 
2355         result 
= kOSKextReturnBadData
; 
2360         *checksumPtr 
= checksum
; 
2363    /* Check that the CPU type & subtype match that of the running kernel. */ 
2364     if (OSSwapBigToHostInt32(mkextHeader
->cputype
) != (UInt32
)CPU_TYPE_ANY
) { 
2365         if ((UInt32
)_mh_execute_header
.cputype 
!= 
2366             OSSwapBigToHostInt32(mkextHeader
->cputype
)) { 
2368             OSKextLog(/* kext */ NULL
, 
2369                 kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2370                 "Kext archive doesn't contain software " 
2371                 "for this computer's CPU type."); 
2372             result 
= kOSKextReturnArchNotFound
; 
2377     numKexts 
= OSSwapBigToHostInt32(mkextHeader
->numkexts
); 
2379     for (uint32_t i 
= 0; i 
< numKexts
; i
++) { 
2381         OSSafeReleaseNULL(infoDictDataObject
); 
2382         OSSafeReleaseNULL(infoDict
); 
2383         OSSafeReleaseNULL(mkextExecutableInfo
); 
2384         OSSafeReleaseNULL(errorString
); 
2385         OSSafeReleaseNULL(theKext
); 
2387         mkext_kext 
* kextEntry 
= &mkextHeader
->kext
[i
]; 
2388         mkext_file 
* infoDictPtr 
= &kextEntry
->plist
; 
2389         mkext_file 
* executablePtr 
= &kextEntry
->module; 
2390         if (kextEntry 
>= mkextEnd
) { 
2391             OSKextLog(/* kext */ NULL
, 
2392                 kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2393                 "Mkext file overrun."); 
2394             result 
= kOSKextReturnBadData
; 
2398        /* Note that we're pretty tolerant of errors in individual entries. 
2399         * As long as we can keep processing, we do. 
2401         infoDictDataObject 
= OSKext::extractMkext1Entry( 
2402             mkextHeader
, infoDictPtr
); 
2403         if (!infoDictDataObject
) { 
2404             OSKextLog(/* kext */ NULL
, 
2405                 kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2406                 "Can't uncompress info dictionary " 
2407                 "from mkext archive entry %d.", i
); 
2411         parsedXML 
= OSUnserializeXML( 
2412                 (const char *)infoDictDataObject
->getBytesNoCopy(), 
2415             infoDict 
= OSDynamicCast(OSDictionary
, parsedXML
); 
2418             const char * errorCString 
= "(unknown error)"; 
2420             if (errorString 
&& errorString
->getCStringNoCopy()) { 
2421                 errorCString 
= errorString
->getCStringNoCopy(); 
2422             } else if (parsedXML
) { 
2423                 errorCString 
= "not a dictionary"; 
2425             OSKextLog(/* kext */ NULL
, 
2426                 kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2427                 "Error: Can't read XML property list " 
2428                   "for mkext archive entry %d: %s.", i
, errorCString
); 
2432         theKext 
= new OSKext
; 
2434             OSKextLog(/* kext */ NULL
, 
2435                 kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2436                 "Kext allocation failure."); 
2441         * Prepare an entry to hold the mkext entry info for the 
2442         * compressed binary module, if there is one. If all four fields 
2443         * of the module entry are zero, there isn't one. 
2445         if ((OSSwapBigToHostInt32(executablePtr
->offset
) || 
2446             OSSwapBigToHostInt32(executablePtr
->compsize
) || 
2447             OSSwapBigToHostInt32(executablePtr
->realsize
) || 
2448             OSSwapBigToHostInt32(executablePtr
->modifiedsecs
))) { 
2450             MkextEntryRef entryRef
; 
2452             mkextExecutableInfo 
= OSData::withCapacity(sizeof(entryRef
)); 
2453             if (!mkextExecutableInfo
) { 
2454                 panic("Error: Couldn't allocate data object " 
2455                       "for mkext archive entry %d.\n", i
); 
2458             entryRef
.mkext 
= (mkext_basic_header 
*)mkextHeader
; 
2459             entryRef
.fileinfo 
= (uint8_t *)executablePtr
; 
2460             if (!mkextExecutableInfo
->appendBytes(&entryRef
, 
2461                 sizeof(entryRef
))) { 
2463                 OSKextLog(/* kext */ NULL
, 
2464                     kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2465                     "Couldn't record executable info " 
2466                     "for mkext archive entry %d.", i
); 
2467                 // we might hit a load error later but oh well 
2468                 // xxx - should probably remove theKext 
2474        /* Init can fail because of a data/runtime error, or because the 
2475         * kext is a dup. Either way, we don't care here. 
2477         if (!theKext
->initWithMkext1Info(infoDict
, mkextExecutableInfo
, 
2480             // theKext is released at the top of the loop or in the finish block 
2484        /* If we got even one kext out of the mkext archive, 
2485         * we have successfully read the archive, in that we 
2486         * have data references into its mapped memory. 
2488         result 
= kOSReturnSuccess
; 
2493     OSSafeRelease(infoDictDataObject
); 
2494     OSSafeRelease(parsedXML
); 
2495     OSSafeRelease(errorString
); 
2496     OSSafeRelease(mkextExecutableInfo
); 
2497     OSSafeRelease(theKext
); 
2502 /********************************************************************* 
2503 *********************************************************************/ 
2505 OSKext::initWithMkext1Info( 
2506     OSDictionary 
* anInfoDict
, 
2507     OSData       
* executableWrapper
, 
2510     bool result 
= false; 
2512     // mkext1 doesn't allow for path (might stuff in info dict) 
2513     if (!setInfoDictionaryAndPath(anInfoDict
, /* path */ NULL
)) { 
2517     if (!registerIdentifier()) { 
2521     if (!setExecutable(executableWrapper
, mkextData
, true)) { 
2529    /* If we can't init, remove the kext from the lookup dictionary. 
2530     * This is safe to call in init because there's an implicit retain. 
2533         OSKext::removeKext(this, /* removePersonalities? */ false); 
2539 /********************************************************************* 
2540 * xxx - this should take the input data length 
2541 *********************************************************************/ 
2544 OSKext::extractMkext1Entry( 
2545     const void  * mkextFileBase
, 
2548     OSData      
* result                 
= NULL
; 
2549     OSData      
* uncompressedData       
= NULL
;  // release on error 
2550     const char  * errmsg                 
= NULL
; 
2552     mkext_file  
* fileinfo
; 
2553     uint8_t     * uncompressedDataBuffer 
= 0; // do not free (panic on alloc. fail) 
2554     size_t        uncompressed_size      
= 0; 
2555     kern_return_t kern_result
; 
2557     fileinfo 
= (mkext_file 
*)entry
; 
2559     size_t offset 
= OSSwapBigToHostInt32(fileinfo
->offset
); 
2560     size_t compressed_size 
= OSSwapBigToHostInt32(fileinfo
->compsize
); 
2561     size_t expected_size 
= OSSwapBigToHostInt32(fileinfo
->realsize
); 
2563     // Add 1 for '\0' to terminate XML string (for plists) 
2564     // (we really should have the archive format include that). 
2565     size_t alloc_size 
= expected_size 
+ 1; 
2566     time_t modifiedsecs 
= OSSwapBigToHostInt32(fileinfo
->modifiedsecs
); 
2568    /* If these four fields are zero there's no file, but it's up to 
2569     * the calling context to decide if that's an error. 
2571     if (offset 
== 0 && compressed_size 
== 0 && 
2572         expected_size 
== 0 && modifiedsecs 
== 0) { 
2576     kern_result 
= kmem_alloc(kernel_map
, 
2577         (vm_offset_t 
*)&uncompressedDataBuffer
, 
2579     if (kern_result 
!= KERN_SUCCESS
) { 
2584     uncompressedData 
= OSData::withBytesNoCopy(uncompressedDataBuffer
, 
2586     if (uncompressedData 
== NULL
) { 
2587        /* No need to free uncompressedDataBuffer here, either. */ 
2591     uncompressedData
->setDeallocFunction(&osdata_kmem_free
); 
2593    /* Do the decompression if necessary. Note that even if the file isn't 
2594     * compressed, we want to make a copy so that we don't have the tie to 
2595     * the larger mkext file buffer any more. 
2596     * xxx - need to detect decompression overflow too 
2598     if (compressed_size 
!= 0) { 
2599         errmsg 
= "OSKext::uncompressMkext - " 
2600             "uncompressed file shorter than expected"; 
2601         uncompressed_size 
= decompress_lzss(uncompressedDataBuffer
, 
2603             ((uint8_t *)mkextFileBase
) + offset
, 
2605         if (uncompressed_size 
!= expected_size
) { 
2609         memcpy(uncompressedDataBuffer
, 
2610             ((uint8_t *)mkextFileBase
) + offset
, 
2614     // Add a terminating nul character in case the data is XML. 
2615     // (we really should have the archive format include that). 
2616     uncompressedDataBuffer
[expected_size
] = '\0'; 
2618     result 
= uncompressedData
; 
2623         OSKextLog(/* kext */ NULL
, 
2624             kOSKextLogErrorLevel 
| kOSKextLogArchiveFlag
, 
2627         if (uncompressedData
) { 
2628             uncompressedData
->release(); 
2634 /********************************************************************* 
2635 * Assumes magic, signature, version, length have been checked. 
2636 * xxx - need to add further bounds checking for each file entry 
2638 * Should keep track of all kexts created so far, and if we hit a 
2639 * fatal error halfway through, remove those kexts. If we've dropped 
2640 * an older version that had already been read, whoops! Might want to 
2641 * add a level of buffering? 
2642 *********************************************************************/ 
2645 OSKext::readMkext2Archive( 
2647     OSDictionary 
** mkextPlistOut
, 
2648     uint32_t      * checksumPtr
) 
2650     OSReturn        result                     
= kOSReturnError
; 
2651     uint32_t        mkextLength
; 
2652     mkext2_header 
* mkextHeader                
= NULL
;  // do not free 
2653     void          * mkextEnd                   
= NULL
;  // do not free 
2654     uint32_t        mkextVersion
; 
2655     uint8_t       * crc_address                
= NULL
; 
2657     uint32_t        mkextPlistOffset
; 
2658     uint32_t        mkextPlistCompressedSize
; 
2659     char          * mkextPlistEnd              
= NULL
;  // do not free 
2660     uint32_t        mkextPlistFullSize
; 
2661     OSString      
* errorString                
= NULL
;  // must release 
2662     OSData        
* mkextPlistUncompressedData 
= NULL
;  // must release 
2663     const char    * mkextPlistDataBuffer       
= NULL
;  // do not free 
2664     OSObject      
* parsedXML                  
= NULL
;  // must release 
2665     OSDictionary  
* mkextPlist                 
= NULL
;  // do not release 
2666     OSArray       
* mkextInfoDictArray         
= NULL
;  // do not release 
2669     mkextLength 
= mkextData
->getLength(); 
2670     mkextHeader 
= (mkext2_header 
*)mkextData
->getBytesNoCopy(); 
2671     mkextEnd 
= (char *)mkextHeader 
+ mkextLength
; 
2672     mkextVersion 
= MKEXT_GET_VERSION(mkextHeader
); 
2674     crc_address 
= (u_int8_t 
*)&mkextHeader
->version
; 
2675     checksum 
= mkext_adler32(crc_address
, 
2676         (uintptr_t)mkextHeader 
+ 
2677         MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
); 
2679     if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) { 
2680         OSKextLog(/* kext */ NULL
, 
2681             kOSKextLogErrorLevel 
| 
2682             kOSKextLogArchiveFlag
, 
2683             "Mkext archive has bad checksum."); 
2684         result 
= kOSKextReturnBadData
; 
2689         *checksumPtr 
= checksum
; 
2692    /* Check that the CPU type & subtype match that of the running kernel. */ 
2693     if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) { 
2694         OSKextLog(/* kext */ NULL
, 
2695             kOSKextLogErrorLevel 
| 
2696             kOSKextLogArchiveFlag
, 
2697             "Mkext archive must have a specific CPU type."); 
2698         result 
= kOSKextReturnBadData
; 
2701         if ((UInt32
)_mh_execute_header
.cputype 
!= 
2702             MKEXT_GET_CPUTYPE(mkextHeader
)) { 
2704             OSKextLog(/* kext */ NULL
, 
2705                 kOSKextLogErrorLevel 
| 
2706                 kOSKextLogArchiveFlag
, 
2707                 "Mkext archive does not match the running kernel's CPU type."); 
2708             result 
= kOSKextReturnArchNotFound
; 
2713     mkextPlistOffset 
= MKEXT2_GET_PLIST(mkextHeader
); 
2714     mkextPlistCompressedSize 
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
); 
2715     mkextPlistEnd 
= (char *)mkextHeader 
+ mkextPlistOffset 
+ 
2716         mkextPlistCompressedSize
; 
2717     if (mkextPlistEnd 
> mkextEnd
) { 
2718         OSKextLog(/* kext */ NULL
, 
2719             kOSKextLogErrorLevel 
| 
2720             kOSKextLogArchiveFlag
, 
2721             "Mkext archive file overrun."); 
2722         result 
= kOSKextReturnBadData
; 
2725     mkextPlistFullSize 
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
); 
2726     if (mkextPlistCompressedSize
) { 
2727         mkextPlistUncompressedData 
= sKernelKext
->extractMkext2FileData( 
2728             (UInt8 
*)mkextHeader 
+ mkextPlistOffset
, 
2730             mkextPlistCompressedSize
, mkextPlistFullSize
); 
2731         if (!mkextPlistUncompressedData
) { 
2734         mkextPlistDataBuffer 
= (const char *) 
2735             mkextPlistUncompressedData
->getBytesNoCopy(); 
2737         mkextPlistDataBuffer 
= (const char *)mkextHeader 
+ mkextPlistOffset
; 
2740    /* IOCFSerialize added a nul byte to the end of the string. Very nice of it. 
2742     parsedXML 
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
); 
2744         mkextPlist 
= OSDynamicCast(OSDictionary
, parsedXML
); 
2747         const char * errorCString 
= "(unknown error)"; 
2749         if (errorString 
&& errorString
->getCStringNoCopy()) { 
2750             errorCString 
= errorString
->getCStringNoCopy(); 
2751         } else if (parsedXML
) { 
2752             errorCString 
= "not a dictionary"; 
2754         OSKextLog(/* kext */ NULL
, 
2755             kOSKextLogErrorLevel 
| 
2756             kOSKextLogArchiveFlag
, 
2757             "Error unserializing mkext plist: %s.", errorCString
); 
2761    /* If the caller needs the plist, hand it back and retain it. 
2762     * (This function releases it at the end.) 
2764     if (mkextPlistOut
) { 
2765         *mkextPlistOut 
= mkextPlist
; 
2766         (*mkextPlistOut
)->retain(); 
2769     mkextInfoDictArray 
= OSDynamicCast(OSArray
, 
2770         mkextPlist
->getObject(kMKEXTInfoDictionariesKey
)); 
2771     if (!mkextInfoDictArray
) { 
2772         OSKextLog(/* kext */ NULL
, 
2773             kOSKextLogErrorLevel 
| 
2774             kOSKextLogArchiveFlag
, 
2775             "Mkext archive contains no kext info dictionaries."); 
2779     count 
= mkextInfoDictArray
->getCount(); 
2780     for (i 
= 0; i 
< count
; i
++) { 
2781         OSDictionary 
* infoDict
; 
2784         infoDict 
= OSDynamicCast(OSDictionary
, 
2785             mkextInfoDictArray
->getObject(i
)); 
2787        /* Create the kext for the entry, then release it, because the 
2788         * kext system keeps them around until explicitly removed. 
2789         * Any creation/registration failures are already logged for us. 
2791         OSKext 
* newKext 
= OSKext::withMkext2Info(infoDict
, mkextData
); 
2792         OSSafeRelease(newKext
); 
2795    /* Even if we didn't keep any kexts from the mkext, we may have a load 
2796     * request to process, so we are successful (no errors occurred). 
2798     result 
= kOSReturnSuccess
; 
2802     OSSafeRelease(parsedXML
); 
2803     OSSafeRelease(mkextPlistUncompressedData
); 
2804     OSSafeRelease(errorString
); 
2809 /********************************************************************* 
2810 *********************************************************************/ 
2813 OSKext::withMkext2Info( 
2814     OSDictionary 
* anInfoDict
, 
2817     OSKext 
* newKext 
= new OSKext
; 
2819     if (newKext 
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) { 
2827 /********************************************************************* 
2828 *********************************************************************/ 
2830 OSKext::initWithMkext2Info( 
2831     OSDictionary 
* anInfoDict
, 
2834     bool                   result              
= false; 
2835     OSString             
* kextPath            
= NULL
;  // do not release 
2836     OSNumber             
* executableOffsetNum 
= NULL
;  // do not release 
2837     OSCollectionIterator 
* iterator            
= NULL
;  // must release 
2838     OSData               
* executable          
= NULL
;  // must release 
2840     if (!super::init()) { 
2844    /* Get the path. Don't look for an arch-specific path property. 
2846     kextPath 
= OSDynamicCast(OSString
, 
2847         anInfoDict
->getObject(kMKEXTBundlePathKey
)); 
2849     if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) { 
2853    /* If we have a path to the executable, save it. 
2855     executableRelPath 
= OSDynamicCast(OSString
, 
2856         anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
)); 
2857     if (executableRelPath
) { 
2858         executableRelPath
->retain(); 
2861    /* Don't need the paths to be in the info dictionary any more. 
2863     anInfoDict
->removeObject(kMKEXTBundlePathKey
); 
2864     anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
); 
2866     executableOffsetNum 
= OSDynamicCast(OSNumber
, 
2867         infoDict
->getObject(kMKEXTExecutableKey
)); 
2868     if (executableOffsetNum
) { 
2869         executable 
= createMkext2FileEntry(mkextData
, 
2870             executableOffsetNum
, "executable"); 
2871         infoDict
->removeObject(kMKEXTExecutableKey
); 
2875         if (!setExecutable(executable
, mkextData
, true)) { 
2880     result 
= registerIdentifier(); 
2884     OSSafeRelease(executable
); 
2885     OSSafeRelease(iterator
); 
2889 /********************************************************************* 
2890 *********************************************************************/ 
2892 OSKext::createMkext2FileEntry( 
2894     OSNumber   
* offsetNum
, 
2897     OSData        
* result      
= NULL
; 
2898     MkextEntryRef   entryRef
; 
2899     uint8_t       * mkextBuffer 
= (uint8_t *)mkextData
->getBytesNoCopy(); 
2900     uint32_t        entryOffset 
= offsetNum
->unsigned32BitValue(); 
2902     result 
= OSData::withCapacity(sizeof(entryRef
)); 
2907     entryRef
.mkext 
= (mkext_basic_header 
*)mkextBuffer
; 
2908     entryRef
.fileinfo 
= mkextBuffer 
+ entryOffset
; 
2909     if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) { 
2910         OSSafeReleaseNULL(result
); 
2917             kOSKextLogErrorLevel 
| 
2918             kOSKextLogArchiveFlag
, 
2919             "Can't create wrapper for mkext file entry '%s' of kext %s.", 
2920             name
, getIdentifierCString()); 
2925 /********************************************************************* 
2926 *********************************************************************/ 
2928 static void * z_alloc(void *, u_int items
, u_int size
); 
2929 static void   z_free(void *, void *ptr
); 
2931 typedef struct z_mem 
{ 
2932     uint32_t alloc_size
; 
2937  * Space allocation and freeing routines for use by zlib routines. 
2940 z_alloc(void * notused __unused
, u_int num_items
, u_int size
) 
2942     void     * result 
= NULL
; 
2943     z_mem    
* zmem 
= NULL
; 
2944     uint32_t   total 
= num_items 
* size
; 
2945     uint32_t   allocSize 
=  total 
+ sizeof(zmem
); 
2947     zmem 
= (z_mem 
*)kalloc(allocSize
); 
2951     zmem
->alloc_size 
= allocSize
; 
2952     result 
= (void *)&(zmem
->data
); 
2958 z_free(void * notused __unused
, void * ptr
) 
2960     uint32_t * skipper 
= (uint32_t *)ptr 
- 1; 
2961     z_mem    
* zmem 
= (z_mem 
*)skipper
; 
2962     kfree((void *)zmem
, zmem
->alloc_size
); 
2968 OSKext::extractMkext2FileData( 
2971     uint32_t     compressedSize
, 
2974     OSData      
* result 
= NULL
; 
2976     OSData      
* uncompressedData 
= NULL
;   // release on error 
2978     uint8_t     * uncompressedDataBuffer 
= 0;    // do not free 
2979     unsigned long uncompressedSize
; 
2981     bool          zstream_inited 
= false; 
2984    /* If the file isn't compressed, we want to make a copy 
2985     * so that we don't have the tie to the larger mkext file buffer any more. 
2987     if (!compressedSize
) { 
2988         uncompressedData 
= OSData::withBytes(data
, fullSize
); 
2989         // xxx - no check for failure? 
2990         result 
= uncompressedData
; 
2994     if (KERN_SUCCESS 
!= kmem_alloc(kernel_map
, 
2995         (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
)) { 
2997        /* How's this for cheesy? The kernel is only asked to extract 
2998         * kext plists so we tailor the log messages. 
3002                 kOSKextLogErrorLevel 
| 
3003                 kOSKextLogArchiveFlag
, 
3004                 "Allocation failure extracting %s from mkext.", name
); 
3007                 kOSKextLogErrorLevel 
| 
3008                 kOSKextLogArchiveFlag
, 
3009                 "Allocation failure extracting %s from mkext for kext %s.", 
3010                 name
, getIdentifierCString()); 
3015     uncompressedData 
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
); 
3016     if (!uncompressedData
) { 
3019                 kOSKextLogErrorLevel 
| 
3020                 kOSKextLogArchiveFlag
, 
3021                 "Allocation failure extracting %s from mkext.", name
); 
3024                 kOSKextLogErrorLevel 
| 
3025                 kOSKextLogArchiveFlag
, 
3026                 "Allocation failure extracting %s from mkext for kext %s.", 
3027                 name
, getIdentifierCString()); 
3031     uncompressedData
->setDeallocFunction(&osdata_kmem_free
); 
3035             kOSKextLogDetailLevel 
| 
3036             kOSKextLogArchiveFlag
, 
3037             "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.", 
3038             name
, compressedSize
, fullSize
); 
3041             kOSKextLogDetailLevel 
| 
3042             kOSKextLogArchiveFlag
, 
3043             "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.", 
3044             getIdentifierCString(), name
, compressedSize
, fullSize
); 
3047     bzero(&zstream
, sizeof(zstream
)); 
3048     zstream
.next_in   
= (UInt8 
*)data
; 
3049     zstream
.avail_in  
= compressedSize
; 
3051     zstream
.next_out  
= uncompressedDataBuffer
; 
3052     zstream
.avail_out 
= fullSize
; 
3054     zstream
.zalloc    
= z_alloc
; 
3055     zstream
.zfree     
= z_free
; 
3057     zlib_result 
= inflateInit(&zstream
); 
3058     if (Z_OK 
!= zlib_result
) { 
3061                 kOSKextLogErrorLevel 
| 
3062                 kOSKextLogArchiveFlag
, 
3063                 "Mkext error; zlib inflateInit failed (%d) for %s.", 
3067                 kOSKextLogErrorLevel 
| 
3068                 kOSKextLogArchiveFlag
, 
3069                 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .", 
3070                 getIdentifierCString(), zlib_result
, name
); 
3074         zstream_inited 
= true; 
3077     zlib_result 
= inflate(&zstream
, Z_FINISH
); 
3079     if (zlib_result 
== Z_STREAM_END 
|| zlib_result 
== Z_OK
) { 
3080         uncompressedSize 
= zstream
.total_out
; 
3084                 kOSKextLogErrorLevel 
| 
3085                 kOSKextLogArchiveFlag
, 
3086                 "Mkext error; zlib inflate failed (%d) for %s.", 
3090                 kOSKextLogErrorLevel 
| 
3091                 kOSKextLogArchiveFlag
, 
3092                 "Kext %s - mkext error; zlib inflate failed (%d) for %s .", 
3093                 getIdentifierCString(), zlib_result
, name
); 
3097                 kOSKextLogErrorLevel 
| 
3098                 kOSKextLogArchiveFlag
, 
3099                 "zlib error: %s.", zstream
.msg
); 
3104     if (uncompressedSize 
!= fullSize
) { 
3107                 kOSKextLogErrorLevel 
| 
3108                 kOSKextLogArchiveFlag
, 
3109                 "Mkext error; zlib inflate discrepancy for %s, " 
3110                 "uncompressed size != original size.", name
); 
3113                 kOSKextLogErrorLevel 
| 
3114                 kOSKextLogArchiveFlag
, 
3115                 "Kext %s - mkext error; zlib inflate discrepancy for %s, " 
3116                 "uncompressed size != original size.", 
3117                 getIdentifierCString(), name
); 
3122     result 
= uncompressedData
; 
3125    /* Don't bother checking return, nothing we can do on fail. 
3127     if (zstream_inited
) inflateEnd(&zstream
); 
3130         OSSafeRelease(uncompressedData
); 
3136 /********************************************************************* 
3137 *********************************************************************/ 
3140 OSKext::loadFromMkext( 
3141     OSKextLogSpec   clientLogFilter
, 
3143     uint32_t        mkextBufferLength
, 
3145     uint32_t      * logInfoLengthOut
) 
3147     OSReturn         result                      
= kOSReturnError
; 
3148     OSReturn         tempResult                  
= kOSReturnError
; 
3150     OSData         
* mkextData                   
= NULL
;  // must release 
3151     OSDictionary   
* mkextPlist                  
= NULL
;  // must release 
3153     OSArray        
* logInfoArray                
= NULL
;  // must release 
3154     OSSerialize    
* serializer                  
= NULL
;  // must release 
3156     OSString       
* predicate                   
= NULL
;  // do not release 
3157     OSDictionary   
* requestArgs                 
= NULL
;  // do not release 
3159     OSString       
* kextIdentifier              
= NULL
;  // do not release 
3160     OSNumber       
* startKextExcludeNum         
= NULL
;  // do not release 
3161     OSNumber       
* startMatchingExcludeNum     
= NULL
;  // do not release 
3162     OSBoolean      
* delayAutounloadBool         
= NULL
;  // do not release 
3163     OSArray        
* personalityNames            
= NULL
;  // do not release 
3165    /* Default values for these two options: regular autounload behavior, 
3166     * load all kexts, send no personalities. 
3168     Boolean            delayAutounload           
= false; 
3169     OSKextExcludeLevel startKextExcludeLevel     
= kOSKextExcludeNone
; 
3170     OSKextExcludeLevel startMatchingExcludeLevel 
= kOSKextExcludeAll
; 
3172     IORecursiveLockLock(sKextLock
); 
3176         *logInfoLengthOut 
= 0; 
3179     OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut 
? true : false); 
3181     OSKextLog(/* kext */ NULL
, 
3182         kOSKextLogDebugLevel 
| 
3184         "Received kext load request from user space."); 
3186    /* Regardless of processing, the fact that we have gotten here means some 
3187     * user-space program is up and talking to us, so we'll switch our kext 
3188     * registration to reflect that. 
3190     if (!sUserLoadsActive
) { 
3191         OSKextLog(/* kext */ NULL
, 
3192             kOSKextLogProgressLevel 
| 
3193             kOSKextLogGeneralFlag 
| kOSKextLogLoadFlag
, 
3194             "Switching to late startup (user-space) kext loading policy."); 
3196         sUserLoadsActive 
= true; 
3199     if (!sLoadEnabled
) { 
3200         OSKextLog(/* kext */ NULL
, 
3201             kOSKextLogErrorLevel 
| 
3203             "Kext loading is disabled."); 
3204         result 
= kOSKextReturnDisabled
; 
3208    /* Note that we do not set a dealloc function on this OSData 
3209     * object! No references to it can remain after the loadFromMkext() 
3210     * call since we are in a MIG function, and will vm_deallocate() 
3213     mkextData 
= OSData::withBytesNoCopy(mkextBuffer
, 
3216         OSKextLog(/* kext */ NULL
, 
3217             kOSKextLogErrorLevel 
| 
3218             kOSKextLogLoadFlag 
| kOSKextLogIPCFlag
, 
3219             "Failed to create wrapper for kext load request."); 
3220         result 
= kOSKextReturnNoMemory
; 
3224     result 
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
); 
3225     if (result 
!= kOSReturnSuccess
) { 
3226         OSKextLog(/* kext */ NULL
, 
3227             kOSKextLogErrorLevel 
| 
3229             "Failed to read kext load request."); 
3233     predicate 
= _OSKextGetRequestPredicate(mkextPlist
); 
3234     if (!predicate 
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) { 
3235         OSKextLog(/* kext */ NULL
, 
3236             kOSKextLogErrorLevel 
| 
3238             "Received kext load request with no predicate; skipping."); 
3239         result 
= kOSKextReturnInvalidArgument
; 
3243     requestArgs 
= OSDynamicCast(OSDictionary
, 
3244         mkextPlist
->getObject(kKextRequestArgumentsKey
)); 
3245     if (!requestArgs 
|| !requestArgs
->getCount()) { 
3246         OSKextLog(/* kext */ NULL
, 
3247             kOSKextLogErrorLevel 
| 
3249             "Received kext load request with no arguments."); 
3250         result 
= kOSKextReturnInvalidArgument
; 
3254     kextIdentifier 
= OSDynamicCast(OSString
, 
3255         requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
)); 
3256     if (!kextIdentifier
) { 
3257         OSKextLog(/* kext */ NULL
, 
3258             kOSKextLogErrorLevel 
| 
3260             "Received kext load request with no kext identifier."); 
3261         result 
= kOSKextReturnInvalidArgument
; 
3265     startKextExcludeNum 
= OSDynamicCast(OSNumber
, 
3266         requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
)); 
3267     startMatchingExcludeNum 
= OSDynamicCast(OSNumber
, 
3268         requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
)); 
3269     delayAutounloadBool 
= OSDynamicCast(OSBoolean
, 
3270         requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
)); 
3271     personalityNames 
= OSDynamicCast(OSArray
, 
3272         requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
)); 
3274     if (delayAutounloadBool
) { 
3275         delayAutounload 
= delayAutounloadBool
->getValue(); 
3277     if (startKextExcludeNum
) { 
3278         startKextExcludeLevel 
= startKextExcludeNum
->unsigned8BitValue(); 
3280     if (startMatchingExcludeNum
) { 
3281         startMatchingExcludeLevel 
= startMatchingExcludeNum
->unsigned8BitValue(); 
3284     OSKextLog(/* kext */ NULL
, 
3285         kOSKextLogProgressLevel 
| 
3287         "Received request from user space to load kext %s.", 
3288         kextIdentifier
->getCStringNoCopy()); 
3290    /* Load the kext, with no deferral, since this is a load from outside 
3292     * xxx - Would like a better way to handle the default values for the 
3293     * xxx - start/match opt args. 
3295     result 
= OSKext::loadKextWithIdentifier( 
3297         /* allowDefer */ false, 
3299         startKextExcludeLevel
, 
3300         startMatchingExcludeLevel
, 
3302     if (result 
!= kOSReturnSuccess
) { 
3305    /* If the load came down from kextd, it will shortly inform IOCatalogue 
3306     * for matching via a separate IOKit calldown. 
3311    /* Gather up the collected log messages for user space. Any 
3312     * error messages past this call will not make it up as log messages 
3313     * but will be in the system log. 
3315     logInfoArray 
= OSKext::clearUserSpaceLogFilter(); 
3317     if (logInfoArray 
&& logInfoOut 
&& logInfoLengthOut
) { 
3318         tempResult 
= OSKext::serializeLogInfo(logInfoArray
, 
3319             logInfoOut
, logInfoLengthOut
); 
3320         if (tempResult 
!= kOSReturnSuccess
) { 
3321             result 
= tempResult
; 
3325     OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false); 
3327    /* Note: mkextDataObject will have been retained by every kext w/an 
3328     * executable in it. That should all have been flushed out at the 
3329     * and of the load operation, but you never know.... 
3331     if (mkextData 
&& mkextData
->getRetainCount() > 1) { 
3332         OSKextLog(/* kext */ NULL
, 
3333             kOSKextLogErrorLevel 
| 
3334             kOSKextLogLoadFlag 
| kOSKextLogIPCFlag
, 
3335             "Kext load request buffer from user space still retained by a kext; " 
3336             "probable memory leak."); 
3339     IORecursiveLockUnlock(sKextLock
); 
3341     OSSafeRelease(mkextData
); 
3342     OSSafeRelease(mkextPlist
); 
3343     OSSafeRelease(serializer
); 
3344     OSSafeRelease(logInfoArray
); 
3349 /********************************************************************* 
3350 *********************************************************************/ 
3353 OSKext::serializeLogInfo( 
3354     OSArray   
* logInfoArray
, 
3356     uint32_t  * logInfoLengthOut
) 
3358     OSReturn        result      
= kOSReturnError
; 
3359     char          * buffer      
= NULL
; 
3360     kern_return_t   kmem_result 
= KERN_FAILURE
; 
3361     OSSerialize  
* serializer   
= NULL
;  // must release; reused 
3362     char         * logInfo            
= NULL
;  // returned by reference 
3363     uint32_t       logInfoLength      
= 0; 
3365     if (!logInfoArray 
|| !logInfoOut 
|| !logInfoLengthOut
) { 
3366         OSKextLog(/* kext */ NULL
, 
3367             kOSKextLogErrorLevel 
| 
3369             "Internal error; invalid arguments to OSKext::serializeLogInfo()."); 
3370        /* Bad programmer. */ 
3371         result 
= kOSKextReturnInvalidArgument
; 
3375     serializer 
= OSSerialize::withCapacity(0); 
3377         OSKextLog(/* kext */ NULL
, 
3378             kOSKextLogErrorLevel 
| 
3380             "Failed to create serializer on log info for request from user space."); 
3381        /* Incidental error; we're going to (try to) allow the request 
3382         * itself to succeed. */ 
3385     if (!logInfoArray
->serialize(serializer
)) { 
3386         OSKextLog(/* kext */ NULL
, 
3387             kOSKextLogErrorLevel 
| 
3389             "Failed to serialize log info for request from user space."); 
3390        /* Incidental error; we're going to (try to) allow the request 
3391         * itself to succeed. */ 
3393         logInfo 
= serializer
->text(); 
3394         logInfoLength 
= serializer
->getLength(); 
3396         kmem_result 
= kmem_alloc(kernel_map
, (vm_offset_t 
*)&buffer
, logInfoLength
); 
3397         if (kmem_result 
!= KERN_SUCCESS
) { 
3398             OSKextLog(/* kext */ NULL
, 
3399                 kOSKextLogErrorLevel 
| 
3401                 "Failed to copy log info for request from user space."); 
3402            /* Incidental error; we're going to (try to) allow the request 
3405             memcpy(buffer
, logInfo
, logInfoLength
); 
3406             *logInfoOut 
= buffer
; 
3407             *logInfoLengthOut 
= logInfoLength
; 
3411     result 
= kOSReturnSuccess
; 
3413     OSSafeRelease(serializer
); 
3418 #pragma mark Instance Management Methods 
3420 /********************************************************************* 
3421 *********************************************************************/ 
3423 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
) 
3425     OSKext 
* foundKext 
= NULL
; 
3427     IORecursiveLockLock(sKextLock
); 
3428     foundKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
)); 
3430         foundKext
->retain(); 
3432     IORecursiveLockUnlock(sKextLock
); 
3437 /********************************************************************* 
3438 *********************************************************************/ 
3440 OSKext::lookupKextWithIdentifier(OSString 
* kextIdentifier
) 
3442     return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy()); 
3445 /********************************************************************* 
3446 *********************************************************************/ 
3448 OSKext::lookupKextWithLoadTag(uint32_t aTag
) 
3450     OSKext 
* foundKext 
= NULL
;                 // returned 
3453     IORecursiveLockLock(sKextLock
); 
3455     count 
= sLoadedKexts
->getCount(); 
3456     for (i 
= 0; i 
< count
; i
++) { 
3457         OSKext 
* thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
3458         if (thisKext
->getLoadTag() == aTag
) { 
3459             foundKext 
= thisKext
; 
3460             foundKext
->retain(); 
3466     IORecursiveLockUnlock(sKextLock
); 
3471 /********************************************************************* 
3472 *********************************************************************/ 
3474 OSKext::lookupKextWithAddress(vm_address_t address
) 
3476     OSKext 
* foundKext 
= NULL
;                 // returned 
3479     IORecursiveLockLock(sKextLock
); 
3481     count 
= sLoadedKexts
->getCount(); 
3482     for (i 
= 0; i 
< count
; i
++) { 
3483         OSKext 
* thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
3484         if (thisKext
->linkedExecutable
) { 
3485             vm_address_t kext_start 
= 
3486                 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy(); 
3487             vm_address_t kext_end 
= kext_start 
+ 
3488                 thisKext
->linkedExecutable
->getLength(); 
3490             if ((kext_start 
<= address
) && (address 
< kext_end
)) { 
3491                 foundKext 
= thisKext
; 
3492                 foundKext
->retain(); 
3499     IORecursiveLockUnlock(sKextLock
); 
3504 /********************************************************************* 
3505 *********************************************************************/ 
3507 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
) 
3509     bool result 
= false; 
3510     OSKext 
* foundKext 
= NULL
;                 // returned 
3512     IORecursiveLockLock(sKextLock
); 
3514     foundKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
)); 
3515     if (foundKext 
&& foundKext
->isLoaded()) { 
3519     IORecursiveLockUnlock(sKextLock
); 
3524 /********************************************************************* 
3525 * xxx - should spawn a separate thread so a kext can safely have 
3526 * xxx - itself unloaded. 
3527 *********************************************************************/ 
3532     bool     terminateServicesAndRemovePersonalitiesFlag
) 
3534     OSReturn result    
= kOSKextReturnInUse
; 
3535     OSKext 
* checkKext 
= NULL
;   // do not release 
3537     IORecursiveLockLock(sKextLock
); 
3539    /* If the kext has no identifier, it failed to init 
3540     * so isn't in sKextsByID and it isn't loaded. 
3542     if (!aKext
->getIdentifier()) { 
3543         result 
= kOSReturnSuccess
; 
3547     checkKext 
= OSDynamicCast(OSKext
, 
3548         sKextsByID
->getObject(aKext
->getIdentifier())); 
3549     if (checkKext 
!= aKext
) { 
3550         result 
= kOSKextReturnNotFound
; 
3554     if (aKext
->isLoaded()) { 
3556        /* If we are terminating, send the request to the IOCatalogue 
3557         * (which will actually call us right back but that's ok we have 
3558         * a recursive lock don't you know) but do not ask the IOCatalogue 
3559         * to call back with an unload, we'll do that right here. 
3561         if (terminateServicesAndRemovePersonalitiesFlag
) { 
3562             result 
= gIOCatalogue
->terminateDriversForModule( 
3563                 aKext
->getIdentifierCString(), /* unload */ false); 
3564             if (result 
!= kOSReturnSuccess
) { 
3566                     kOSKextLogErrorLevel 
| 
3567                     kOSKextLogKextBookkeepingFlag
, 
3568                     "Can't remove kext %s; services failed to terminate - 0x%x.", 
3569                     aKext
->getIdentifierCString(), result
); 
3574         result 
= aKext
->unload(); 
3575         if (result 
!= kOSReturnSuccess
) { 
3580    /* Remove personalities as requested. This is a bit redundant for a loaded 
3581     * kext as IOCatalogue::terminateDriversForModule() removes driver 
3582     * personalities, but it doesn't restart matching, which we always want 
3583     * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures 
3586     if (terminateServicesAndRemovePersonalitiesFlag
) { 
3587         aKext
->removePersonalitiesFromCatalog(); 
3591         kOSKextLogProgressLevel 
| 
3592         kOSKextLogKextBookkeepingFlag
, 
3593         "Removing kext %s.", 
3594         aKext
->getIdentifierCString()); 
3596     sKextsByID
->removeObject(aKext
->getIdentifier()); 
3597     result 
= kOSReturnSuccess
; 
3600     IORecursiveLockUnlock(sKextLock
); 
3604 /********************************************************************* 
3605 *********************************************************************/ 
3608 OSKext::removeKextWithIdentifier( 
3609     const char * kextIdentifier
, 
3610     bool         terminateServicesAndRemovePersonalitiesFlag
) 
3612     OSReturn result 
= kOSReturnError
; 
3614     IORecursiveLockLock(sKextLock
); 
3616     OSKext 
* aKext 
= OSDynamicCast(OSKext
, 
3617         sKextsByID
->getObject(kextIdentifier
)); 
3619         result 
= kOSKextReturnNotFound
; 
3620         OSKextLog(/* kext */ NULL
, 
3621             kOSKextLogErrorLevel 
| 
3622             kOSKextLogKextBookkeepingFlag
, 
3623             "Can't remove kext %s - not found.", 
3628     result 
= OSKext::removeKext(aKext
, 
3629         terminateServicesAndRemovePersonalitiesFlag
); 
3632     IORecursiveLockUnlock(sKextLock
); 
3637 /********************************************************************* 
3638 *********************************************************************/ 
3641 OSKext::removeKextWithLoadTag( 
3642     OSKextLoadTag loadTag
, 
3643     bool          terminateServicesAndRemovePersonalitiesFlag
) 
3645     OSReturn result    
= kOSReturnError
; 
3646     OSKext 
* foundKext 
= NULL
; 
3649     IORecursiveLockLock(sKextLock
); 
3651     count 
= sLoadedKexts
->getCount(); 
3652     for (i 
= 0; i 
< count
; i
++) { 
3653         OSKext 
* thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
3654         if (thisKext
->loadTag 
== loadTag
) { 
3655             foundKext 
= thisKext
; 
3661         result 
= kOSKextReturnNotFound
; 
3662         OSKextLog(/* kext */ NULL
, 
3663             kOSKextLogErrorLevel 
| 
3664             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
3665             "Can't remove kext with load tag %d - not found.", 
3670     result 
= OSKext::removeKext(foundKext
, 
3671         terminateServicesAndRemovePersonalitiesFlag
); 
3674     IORecursiveLockUnlock(sKextLock
); 
3679 /********************************************************************* 
3680 *********************************************************************/ 
3682 OSKext::copyKexts(void) 
3684     OSDictionary 
* result
; 
3686     IORecursiveLockLock(sKextLock
); 
3687     result 
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection()); 
3688     IORecursiveLockUnlock(sKextLock
); 
3694 #pragma mark Accessors 
3696 /********************************************************************* 
3697 *********************************************************************/ 
3699 OSKext::getIdentifier(void) 
3704 /********************************************************************* 
3705 * A kext must have a bundle identifier to even survive initialization; 
3706 * this is guaranteed to exist past then. 
3707 *********************************************************************/ 
3709 OSKext::getIdentifierCString(void) 
3711     return bundleID
->getCStringNoCopy(); 
3714 /********************************************************************* 
3715 *********************************************************************/ 
3717 OSKext::getVersion(void) 
3722 /********************************************************************* 
3723 *********************************************************************/ 
3725 OSKext::getCompatibleVersion(void) 
3727     return compatibleVersion
; 
3730 /********************************************************************* 
3731 *********************************************************************/ 
3733 OSKext::isLibrary(void) 
3735     return (getCompatibleVersion() > 0); 
3738 /********************************************************************* 
3739 *********************************************************************/ 
3741 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
) 
3743     if ((compatibleVersion 
> -1 && version 
> -1) && 
3744         (compatibleVersion 
<= version 
&& aVersion 
<= version
)) { 
3750 /********************************************************************* 
3751 *********************************************************************/ 
3753 OSKext::declaresExecutable(void) 
3755     return (getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
); 
3758 /********************************************************************* 
3759 *********************************************************************/ 
3761 OSKext::getExecutable(void) 
3763     OSData 
* result              
= NULL
; 
3764     OSData 
* extractedExecutable 
= NULL
;  // must release 
3765     OSData 
* mkextExecutableRef  
= NULL
;  // do not release 
3767     result 
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
)); 
3772     mkextExecutableRef 
= OSDynamicCast(OSData
, 
3773         getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
)); 
3775     if (mkextExecutableRef
) { 
3777         MkextEntryRef 
* mkextEntryRef 
= (MkextEntryRef 
*) 
3778             mkextExecutableRef
->getBytesNoCopy(); 
3779         uint32_t mkextVersion 
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
); 
3780         if (mkextVersion 
== MKEXT_VERS_2
) { 
3781             mkext2_file_entry 
* fileinfo 
= 
3782                 (mkext2_file_entry 
*)mkextEntryRef
->fileinfo
; 
3783             uint32_t compressedSize 
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
); 
3784             uint32_t fullSize 
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
); 
3785             extractedExecutable 
= extractMkext2FileData( 
3786                 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable", 
3787                 compressedSize
, fullSize
); 
3788         } else if (mkextVersion 
== MKEXT_VERS_1
) { 
3789             extractedExecutable 
= extractMkext1Entry( 
3790                 mkextEntryRef
->mkext
, mkextEntryRef
->fileinfo
); 
3792             OSKextLog(this, kOSKextLogErrorLevel 
| 
3793             kOSKextLogArchiveFlag
, 
3794                 "Kext %s - unknown mkext version 0x%x for executable.", 
3795                 getIdentifierCString(), mkextVersion
); 
3798        /* Regardless of success, remove the mkext executable, 
3799         * and drop one reference on the mkext.  (setExecutable() does not 
3800         * replace, it removes, or panics if asked to replace.) 
3802         infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
); 
3803         infoDict
->removeObject(_kOSKextExecutableExternalDataKey
); 
3805         if (extractedExecutable 
&& extractedExecutable
->getLength()) { 
3806             if (!setExecutable(extractedExecutable
)) { 
3809             result 
= extractedExecutable
; 
3817     OSSafeRelease(extractedExecutable
); 
3822 /********************************************************************* 
3823 *********************************************************************/ 
3825 OSKext::isInterface(void) 
3827     return flags
.interface
; 
3830 /********************************************************************* 
3831 *********************************************************************/ 
3833 OSKext::isKernel(void) 
3835     return (this == sKernelKext
); 
3838 /********************************************************************* 
3839 *********************************************************************/ 
3841 OSKext::isKernelComponent(void) 
3843     return flags
.kernelComponent 
? true : false; 
3846 /********************************************************************* 
3847 *********************************************************************/ 
3849 OSKext::isExecutable(void) 
3851     return (!isKernel() && !isInterface() && declaresExecutable()); 
3854 /********************************************************************* 
3855 * We might want to check this recursively for all dependencies, 
3856 * since a subtree of dependencies could get loaded before we hit 
3857 * a dependency that isn't safe-boot-loadable. 
3859 * xxx - Might want to return false if OSBundleEnableKextLogging or 
3860 * OSBundleDebugLevel 
3861 * or IOKitDebug is nonzero too (we used to do that, but I don't see 
3862 * the point except it's usually development drivers, which might 
3863 * cause panics on startup, that have those properties). Heh; could 
3864 * use a "kx" boot-arg! 
3865 *********************************************************************/ 
3867 OSKext::isLoadableInSafeBoot(void) 
3869     bool       result   
= false; 
3870     OSString 
* required 
= NULL
;  // do not release 
3877     required 
= OSDynamicCast(OSString
, 
3878         getPropertyForHostArch(kOSBundleRequiredKey
)); 
3882     if (required
->isEqualTo(kOSBundleRequiredRoot
)        || 
3883         required
->isEqualTo(kOSBundleRequiredLocalRoot
)   || 
3884         required
->isEqualTo(kOSBundleRequiredNetworkRoot
) || 
3885         required
->isEqualTo(kOSBundleRequiredSafeBoot
)    || 
3886         required
->isEqualTo(kOSBundleRequiredConsole
)) { 
3895 /********************************************************************* 
3896 *********************************************************************/ 
3898 OSKext::isPrelinked(void) 
3900     return flags
.prelinked 
? true : false; 
3903 /********************************************************************* 
3904 *********************************************************************/ 
3905 bool OSKext::isLoaded(void) 
3907     return flags
.loaded 
? true : false; 
3910 /********************************************************************* 
3911 *********************************************************************/ 
3913 OSKext::isStarted(void) 
3915     return flags
.started 
? true : false; 
3918 /********************************************************************* 
3919 *********************************************************************/ 
3921 OSKext::isCPPInitialized(void) 
3923     return flags
.CPPInitialized
; 
3926 /********************************************************************* 
3927 *********************************************************************/ 
3929 OSKext::setCPPInitialized(bool initialized
) 
3931     flags
.CPPInitialized 
= initialized
; 
3934 /********************************************************************* 
3935 *********************************************************************/ 
3937 OSKext::getLoadTag(void) 
3942 /********************************************************************* 
3943  *********************************************************************/ 
3944 void OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
) 
3946     if (linkedExecutable
) { 
3947         *loadSize 
= linkedExecutable
->getLength(); 
3949         /* If we have a kmod_info struct, calculated the wired size 
3950          * from that. Otherwise it's the full load size. 
3953             *wiredSize 
= *loadSize 
- kmod_info
->hdr_size
; 
3955             *wiredSize 
= *loadSize
; 
3964 /********************************************************************* 
3965 *********************************************************************/ 
3967 OSKext::copyUUID(void) 
3969     OSData                     
* result        
= NULL
; 
3970     OSData                     
* theExecutable 
= NULL
;  // do not release 
3971     const kernel_mach_header_t 
* header        
= NULL
; 
3972     const struct load_command  
* load_cmd      
= NULL
; 
3973     const struct uuid_command  
* uuid_cmd      
= NULL
; 
3976    /* An interface kext doesn't have a linked executable with an LC_UUID, 
3977     * we create one when it's linked. 
3979     if (interfaceUUID
) { 
3980         result 
= interfaceUUID
; 
3985    /* For real kexts, try to get the UUID from the linked executable, 
3986     * or if is hasn't been linked yet, the unrelocated executable. 
3988     theExecutable 
= linkedExecutable
; 
3989     if (!theExecutable
) { 
3990         theExecutable 
= getExecutable(); 
3992     if (!theExecutable
) { 
3996     header 
= (const kernel_mach_header_t 
*)theExecutable
->getBytesNoCopy(); 
3997     load_cmd 
= (const struct load_command 
*)&header
[1]; 
3999     for (i 
= 0; i 
< header
->ncmds
; i
++) { 
4000         if (load_cmd
->cmd 
== LC_UUID
) { 
4001             uuid_cmd 
= (struct uuid_command 
*)load_cmd
; 
4002             result 
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
)); 
4005         load_cmd 
= (struct load_command 
*)((caddr_t
)load_cmd 
+ load_cmd
->cmdsize
); 
4012 /********************************************************************* 
4013 *********************************************************************/ 
4015 #if defined (__i386__) 
4016 #define ARCHNAME "i386" 
4017 #elif defined (__x86_64__) 
4018 #define ARCHNAME "x86_64" 
4020 #error architecture not supported 
4023 #define ARCH_SEPARATOR_CHAR  '_' 
4025 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
) 
4027     char     * result 
= NULL
; 
4028     uint32_t   keyLength 
= strlen(key
); 
4031    /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'. 
4033     keySize 
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
); 
4034     result 
= (char *)kalloc(keySize
); 
4038     strlcpy(result
, key
, keySize
); 
4039     result
[keyLength
++] = ARCH_SEPARATOR_CHAR
; 
4040     result
[keyLength
] = '\0'; 
4041     strlcat(result
, ARCHNAME
, keySize
); 
4042     *keySizeOut 
= keySize
; 
4048 /********************************************************************* 
4049 *********************************************************************/ 
4051 OSKext::getPropertyForHostArch(const char * key
) 
4053     OSObject 
* result           
= NULL
;  // do not release 
4054     uint32_t   hostArchKeySize  
= 0; 
4055     char     * hostArchKey      
= NULL
;  // must kfree 
4057     if (!key 
|| !infoDict
) { 
4061    /* Some properties are not allowed to be arch-variant: 
4062     * - Any CFBundle... property. 
4063     * - OSBundleIsInterface. 
4064     * - OSKernelResource. 
4066     if (STRING_HAS_PREFIX(key
, "OS") || 
4067         STRING_HAS_PREFIX(key
, "IO")) { 
4069         hostArchKey 
= makeHostArchKey(key
, &hostArchKeySize
); 
4071             OSKextLog(/* kext (this isn't about a kext) */ NULL
, 
4072                 kOSKextLogErrorLevel 
| kOSKextLogGeneralFlag
, 
4073                 "Allocation failure."); 
4076         result 
= infoDict
->getObject(hostArchKey
); 
4080         result 
= infoDict
->getObject(key
); 
4084     if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
); 
4089 #pragma mark Load/Start/Stop/Unload 
4091 /********************************************************************* 
4092 *********************************************************************/ 
4095 OSKext::loadKextWithIdentifier( 
4096     const char       * kextIdentifierCString
, 
4097     Boolean            allowDeferFlag
, 
4098     Boolean            delayAutounloadFlag
, 
4099     OSKextExcludeLevel startOpt
, 
4100     OSKextExcludeLevel startMatchingOpt
, 
4101     OSArray          
* personalityNames
) 
4103     OSReturn   result         
= kOSReturnError
; 
4104     OSString 
* kextIdentifier 
= NULL
;  // must release 
4106     kextIdentifier 
= OSString::withCString(kextIdentifierCString
); 
4107     if (!kextIdentifier
) { 
4108         result 
= kOSKextReturnNoMemory
; 
4111     result 
= OSKext::loadKextWithIdentifier(kextIdentifier
, 
4112         allowDeferFlag
, delayAutounloadFlag
, 
4113         startOpt
, startMatchingOpt
, personalityNames
); 
4116     OSSafeRelease(kextIdentifier
); 
4120 /********************************************************************* 
4121 *********************************************************************/ 
4123 OSKext::loadKextWithIdentifier( 
4124     OSString          
* kextIdentifier
, 
4125     Boolean             allowDeferFlag
, 
4126     Boolean             delayAutounloadFlag
, 
4127     OSKextExcludeLevel  startOpt
, 
4128     OSKextExcludeLevel  startMatchingOpt
, 
4129     OSArray           
* personalityNames
) 
4131     OSReturn          result               
= kOSReturnError
; 
4132     OSReturn          pingResult           
= kOSReturnError
; 
4133     OSKext          
* theKext              
= NULL
;  // do not release 
4134     OSDictionary    
* loadRequest          
= NULL
;  // must release 
4135     const OSSymbol  
* kextIdentifierSymbol 
= NULL
;  // must release 
4137     IORecursiveLockLock(sKextLock
); 
4139     if (!kextIdentifier
) { 
4140         result 
= kOSKextReturnInvalidArgument
; 
4144     OSKext::recordIdentifierRequest(kextIdentifier
); 
4146     theKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
)); 
4148         if (!allowDeferFlag
) { 
4149             OSKextLog(/* kext */ NULL
, 
4150                 kOSKextLogErrorLevel 
| 
4152                 "Can't load kext %s - not found.", 
4153                 kextIdentifier
->getCStringNoCopy()); 
4157         if (!sKernelRequestsEnabled
) { 
4159                 kOSKextLogErrorLevel 
| 
4161                 "Can't load kext %s - requests to user space are disabled.", 
4162                 kextIdentifier
->getCStringNoCopy()); 
4163             result 
= kOSKextReturnDisabled
; 
4167        /* Create a new request unless one is already sitting 
4168         * in sKernelRequests for this bundle identifier 
4170         kextIdentifierSymbol 
= OSSymbol::withString(kextIdentifier
); 
4171         if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) { 
4172             result 
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
, 
4174             if (result 
!= kOSReturnSuccess
) { 
4177             if (!_OSKextSetRequestArgument(loadRequest
, 
4178                 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) { 
4180                 result 
= kOSKextReturnNoMemory
; 
4183             if (!sKernelRequests
->setObject(loadRequest
)) { 
4184                 result 
= kOSKextReturnNoMemory
; 
4188             if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) { 
4189                 result 
= kOSKextReturnNoMemory
; 
4194                 kOSKextLogDebugLevel 
| 
4196                 "Kext %s not found; queued load request to user space.", 
4197                 kextIdentifier
->getCStringNoCopy()); 
4200         pingResult 
= OSKext::pingKextd(); 
4201         if (pingResult 
== kOSKextReturnDisabled
) { 
4202             OSKextLog(/* kext */ NULL
, 
4203                 ((sPrelinkBoot
) ? kOSKextLogDebugLevel 
: kOSKextLogErrorLevel
) | 
4205                 "Kext %s might not load - kextd is currently unavailable.", 
4206                 kextIdentifier
->getCStringNoCopy()); 
4209         result 
= kOSKextReturnDeferred
; 
4213     result 
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
); 
4215     if (result 
!= kOSReturnSuccess
) { 
4217             kOSKextLogErrorLevel 
| 
4219             "Failed to load kext %s (error 0x%x).", 
4220             kextIdentifier
->getCStringNoCopy(), (int)result
); 
4222         OSKext::removeKext(theKext
, 
4223             /* terminateService/removePersonalities */ true); 
4227     if (delayAutounloadFlag
) { 
4229             kOSKextLogProgressLevel 
| 
4230             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
4231             "Setting delayed autounload for %s.", 
4232             kextIdentifier
->getCStringNoCopy()); 
4233         theKext
->flags
.delayAutounload 
= 1; 
4237     OSSafeRelease(loadRequest
); 
4238     OSSafeRelease(kextIdentifierSymbol
); 
4240     IORecursiveLockUnlock(sKextLock
); 
4245 /********************************************************************* 
4246 *********************************************************************/ 
4249 OSKext::recordIdentifierRequest( 
4250     OSString 
* kextIdentifier
) 
4252     const OSSymbol 
* kextIdentifierSymbol 
= NULL
;  // must release 
4255     if (!sAllKextLoadIdentifiers 
|| !kextIdentifier
) { 
4259     kextIdentifierSymbol 
= OSSymbol::withString(kextIdentifier
); 
4260     if (!kextIdentifierSymbol
) { 
4261         // xxx - this is really a basic alloc failure 
4266     if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) { 
4267         if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) { 
4270             // xxx - need to find a way to associate this whole func w/the kext 
4271             OSKextLog(/* kext */ NULL
, 
4272                 // xxx - check level 
4273                 kOSKextLogStepLevel 
| 
4274                 kOSKextLogArchiveFlag
, 
4275                 "Recorded kext %s as a candidate for inclusion in prelinked kernel.", 
4276                 kextIdentifier
->getCStringNoCopy()); 
4282         OSKextLog(/* kext */ NULL
, 
4283             kOSKextLogErrorLevel 
| 
4284             kOSKextLogArchiveFlag
, 
4285             "Failed to record kext %s as a candidate for inclusion in prelinked kernel.", 
4286             kextIdentifier
->getCStringNoCopy()); 
4288     OSSafeRelease(kextIdentifierSymbol
); 
4292 /********************************************************************* 
4293 *********************************************************************/ 
4296     OSKextExcludeLevel   startOpt
, 
4297     OSKextExcludeLevel   startMatchingOpt
, 
4298     OSArray            
* personalityNames
) 
4300     OSReturn             result                       
= kOSReturnError
; 
4301     kern_return_t        kxldResult
; 
4302     OSKextExcludeLevel   dependenciesStartOpt         
= startOpt
; 
4303     OSKextExcludeLevel   dependenciesStartMatchingOpt 
= startMatchingOpt
; 
4304     unsigned int         i
, count
; 
4305     Boolean              alreadyLoaded                
= false; 
4306     OSKext             
* lastLoadedKext               
= NULL
; 
4309         alreadyLoaded 
= true; 
4310         result 
= kOSReturnSuccess
; 
4313             kOSKextLogDebugLevel 
| 
4314             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
4315             "Kext %s is already loaded.", 
4316             getIdentifierCString()); 
4320     if (!sLoadEnabled
) { 
4322             kOSKextLogErrorLevel 
| 
4324             "Kext loading is disabled (attempt to load kext %s).", 
4325             getIdentifierCString()); 
4326         result 
= kOSKextReturnDisabled
; 
4330    /* If we've pushed the next available load tag to the invalid value, 
4331     * we can't load any more kexts. 
4333     if (sNextLoadTag 
== kOSKextInvalidLoadTag
) { 
4335             kOSKextLogErrorLevel 
| 
4337             "Can't load kext %s - no more load tags to assign.", 
4338             getIdentifierCString()); 
4339         result 
= kOSKextReturnNoResources
; 
4343    /* This is a bit of a hack, because we shouldn't be handling  
4344     * personalities within the load function. 
4346     if (!declaresExecutable()) { 
4347         result 
= kOSReturnSuccess
; 
4351    /* Are we in safe boot? 
4353     if (sSafeBoot 
&& !isLoadableInSafeBoot()) { 
4355             kOSKextLogErrorLevel 
| 
4357             "Can't load kext %s - not loadable during safe boot.", 
4358             getIdentifierCString()); 
4359         result 
= kOSKextReturnBootLevel
; 
4364         kOSKextLogProgressLevel 
| kOSKextLogLoadFlag
, 
4366         getIdentifierCString()); 
4369     if (!sKxldContext
) { 
4370         kxldResult 
= kxld_create_context(&sKxldContext
, &kern_allocate
,  
4371             &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,  
4372             /* cputype */ 0, /* cpusubtype */ 0); 
4375                 kOSKextLogErrorLevel 
| 
4376                 kOSKextLogLoadFlag 
| kOSKextLogLinkFlag
, 
4377                 "Can't load kext %s - failed to create link context.", 
4378                 getIdentifierCString()); 
4379             result 
= kOSKextReturnNoMemory
; 
4384     /* We only need to resolve dependencies once for the whole graph, but 
4385      * resolveDependencies will just return if there's no work to do, so it's 
4386      * safe to call it more than once. 
4388     if (!resolveDependencies()) { 
4389         // xxx - check resolveDependencies() for log msg 
4391             kOSKextLogErrorLevel 
| 
4392             kOSKextLogLoadFlag 
| kOSKextLogDependenciesFlag
, 
4393             "Can't load kext %s - failed to resolve library dependencies.", 
4394             getIdentifierCString()); 
4395         result 
= kOSKextReturnDependencies
; 
4399    /* If we are excluding just the kext being loaded now (and not its 
4400     * dependencies), drop the exclusion level to none so dependencies 
4401     * start and/or add their personalities. 
4403     if (dependenciesStartOpt 
== kOSKextExcludeKext
) { 
4404         dependenciesStartOpt 
= kOSKextExcludeNone
; 
4407     if (dependenciesStartMatchingOpt 
== kOSKextExcludeKext
) { 
4408         dependenciesStartMatchingOpt 
= kOSKextExcludeNone
; 
4411    /* Load the dependencies, recursively. 
4413     count 
= getNumDependencies(); 
4414     for (i 
= 0; i 
< count
; i
++) { 
4415         OSKext 
* dependency 
= OSDynamicCast(OSKext
, 
4416             dependencies
->getObject(i
)); 
4417         if (dependency 
== NULL
) { 
4419                 kOSKextLogErrorLevel 
| 
4420                 kOSKextLogLoadFlag 
| kOSKextLogDependenciesFlag
, 
4421                 "Internal error loading kext %s; dependency disappeared.", 
4422                 getIdentifierCString()); 
4423             result 
= kOSKextReturnInternalError
; 
4427        /* Dependencies must be started accorting to the opt, 
4428         * but not given the personality names of the main kext. 
4430         result 
= dependency
->load(dependenciesStartOpt
, 
4431             dependenciesStartMatchingOpt
, 
4432             /* personalityNames */ NULL
); 
4433         if (result 
!= KERN_SUCCESS
) { 
4435                 kOSKextLogErrorLevel 
| 
4436                 kOSKextLogLoadFlag 
| kOSKextLogDependenciesFlag
, 
4437                 "Dependency %s of kext %s failed to load.", 
4438                 dependency
->getIdentifierCString(), 
4439                 getIdentifierCString()); 
4441             OSKext::removeKext(dependency
, 
4442                 /* terminateService/removePersonalities */ true); 
4443             result 
= kOSKextReturnDependencyLoadError
; 
4449     result 
= loadExecutable(); 
4450     if (result 
!= KERN_SUCCESS
) { 
4454     flags
.loaded 
= true; 
4456    /* Add the kext to the list of loaded kexts and update the kmod_info 
4457     * struct to point to that of the last loaded kext (which is the way 
4458     * it's always been done, though I'd rather do them in order now). 
4460     lastLoadedKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject()); 
4461     sLoadedKexts
->setObject(this); 
4463    /* Keep the kernel itself out of the kmod list. 
4465     if (lastLoadedKext
->isKernel()) { 
4466         lastLoadedKext 
= NULL
; 
4469     if (lastLoadedKext
) { 
4470         kmod_info
->next 
= lastLoadedKext
->kmod_info
; 
4473     notifyKextLoadObservers(this, kmod_info
); 
4475    /* Make the global kmod list point at the just-loaded kext. Note that the 
4476     * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard, 
4477     * although we do report it in kextstat these days by using the newer 
4478     * OSArray of loaded kexts, which does contain it. 
4480     * (The OSKext object representing the kernel doesn't even have a kmod_info 
4481     * struct, though I suppose we could stick a pointer to it from the 
4482     * static struct in OSRuntime.cpp.) 
4486    /* Save the list of loaded kexts in case we panic. 
4488     OSKext::saveLoadedKextPanicList(); 
4490     if (isExecutable()) { 
4491         OSKext::updateLoadedKextSummaries(); 
4492         savePanicString(/* isLoading */ true); 
4495         registerWithDTrace(); 
4497         jettisonLinkeditSegment(); 
4498 #endif /* CONFIG_DTRACE */ 
4502     if (isExecutable() && !flags
.started
) { 
4503         if (startOpt 
== kOSKextExcludeNone
) { 
4505             if (result 
!= kOSReturnSuccess
) { 
4507                     kOSKextLogErrorLevel 
| kOSKextLogLoadFlag
, 
4508                     "Kext %s start failed (result 0x%x).", 
4509                     getIdentifierCString(), result
); 
4510                 result 
= kOSKextReturnStartStopError
; 
4515    /* If not excluding matching, send the personalities to the kernel. 
4516     * This never affects the result of the load operation. 
4517     * This is a bit of a hack, because we shouldn't be handling  
4518     * personalities within the load function. 
4520     if (result 
== kOSReturnSuccess 
&& startMatchingOpt 
== kOSKextExcludeNone
) { 
4521         result 
= sendPersonalitiesToCatalog(true, personalityNames
); 
4526    /* More hack! If the kext doesn't declare an executable, even if we 
4527     * "loaded" it, we have to remove any personalities naming it, or we'll 
4528     * never see the registry go quiet. Errors here do not count for the 
4529     * load operation itself. 
4531     * Note that in every other regard it's perfectly ok for a kext to 
4532     * not declare an executable and serve only as a package for personalities 
4533     * naming another kext, so we do have to allow such kexts to be "loaded" 
4534     * so that those other personalities get added & matched. 
4536     if (!declaresExecutable()) { 
4538             kOSKextLogStepLevel 
| kOSKextLogLoadFlag
, 
4539             "Kext %s has no executable; removing any personalities naming it.", 
4540             getIdentifierCString()); 
4541         removePersonalitiesFromCatalog(); 
4544     if (result 
!= kOSReturnSuccess
) { 
4546             kOSKextLogErrorLevel 
| 
4548             "Kext %s failed to load (0x%x).", 
4549             getIdentifierCString(), (int)result
); 
4550     } else if (!alreadyLoaded
) { 
4552             kOSKextLogProgressLevel 
| 
4555             getIdentifierCString()); 
4557         queueKextNotification(kKextRequestPredicateLoadNotification
, 
4558             OSDynamicCast(OSString
, bundleID
)); 
4563 /********************************************************************* 
4565 *********************************************************************/ 
4566 static char * strdup(const char * string
) 
4568     char * result 
= NULL
; 
4575     size 
= 1 + strlen(string
); 
4576     result 
= (char *)kalloc(size
); 
4581     memcpy(result
, string
, size
); 
4587 /********************************************************************* 
4589 *********************************************************************/ 
4591 OSKext::slidePrelinkedExecutable() 
4593     OSReturn                   result           
= kOSKextReturnBadData
; 
4594     kernel_mach_header_t     
* mh               
= NULL
; 
4595     kernel_segment_command_t 
* seg              
= NULL
; 
4596     kernel_segment_command_t 
* linkeditSeg      
= NULL
; 
4597     kernel_section_t         
* sec              
= NULL
; 
4598     char                     * linkeditBase     
= NULL
; 
4599     bool                       haveLinkeditBase 
= false; 
4600     char                     * relocBase        
= NULL
; 
4601     bool                       haveRelocBase    
= false; 
4602     struct dysymtab_command  
* dysymtab         
= NULL
; 
4603     struct symtab_command    
* symtab           
= NULL
; 
4604     kernel_nlist_t           
* sym              
= NULL
; 
4605     struct relocation_info   
* reloc            
= NULL
; 
4608     vm_offset_t                new_kextsize
; 
4610     if (linkedExecutable 
== NULL 
|| vm_kernel_slide 
== 0) { 
4611         result 
= kOSReturnSuccess
; 
4615     mh 
= (kernel_mach_header_t 
*)linkedExecutable
->getBytesNoCopy(); 
4617     for (seg 
= firstsegfromheader(mh
); seg 
!= NULL
; seg 
= nextsegfromheader(mh
, seg
)) { 
4618         seg
->vmaddr 
+= vm_kernel_slide
; 
4620 #if KASLR_KEXT_DEBUG 
4621         IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",  
4623               (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),  
4624               (unsigned long)seg
->vmaddr
); 
4627         if (!haveRelocBase
) { 
4628             relocBase 
= (char *) seg
->vmaddr
; 
4629             haveRelocBase 
= true; 
4631         if (!strcmp(seg
->segname
, "__LINKEDIT")) { 
4632             linkeditBase 
= (char *) seg
->vmaddr 
- seg
->fileoff
; 
4633             haveLinkeditBase 
= true; 
4636         for (sec 
= firstsect(seg
); sec 
!= NULL
; sec 
= nextsect(seg
, sec
)) { 
4637             sec
->addr 
+= vm_kernel_slide
; 
4639 #if KASLR_KEXT_DEBUG 
4640             IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",  
4642                   (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),  
4643                   (unsigned long)sec
->addr
); 
4648     dysymtab 
= (struct dysymtab_command 
*) getcommandfromheader(mh
, LC_DYSYMTAB
); 
4650     symtab 
= (struct symtab_command 
*) getcommandfromheader(mh
, LC_SYMTAB
); 
4652     if (symtab 
!= NULL
) { 
4653       /* Some pseudo-kexts have symbol tables without segments. 
4655         if (symtab
->nsyms 
> 0 && haveLinkeditBase
) { 
4656             sym 
= (kernel_nlist_t 
*) (linkeditBase 
+ symtab
->symoff
); 
4657             for (i 
= 0; i 
< symtab
->nsyms
; i
++) { 
4658                 if (sym
[i
].n_type 
& N_STAB
) { 
4661                 sym
[i
].n_value 
+= vm_kernel_slide
; 
4663 #if KASLR_KEXT_DEBUG 
4664 #define MAX_SYMS_TO_LOG 5 
4665                 if ( i 
< MAX_SYMS_TO_LOG 
) { 
4666                     IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",  
4667                           (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),  
4668                           (unsigned long)sym
[i
].n_value
); 
4675     if (dysymtab 
!= NULL
) { 
4676         if (dysymtab
->nextrel 
> 0) { 
4678                 kOSKextLogErrorLevel 
| kOSKextLogLoadFlag 
| 
4680                 "Sliding kext %s: External relocations found.", 
4681                 getIdentifierCString()); 
4685         if (dysymtab
->nlocrel 
> 0) { 
4686             if (!haveLinkeditBase
) { 
4688                     kOSKextLogErrorLevel 
| kOSKextLogLoadFlag 
| 
4690                     "Sliding kext %s: No linkedit segment.", 
4691                     getIdentifierCString()); 
4695             if (!haveRelocBase
) { 
4697                     kOSKextLogErrorLevel 
| kOSKextLogLoadFlag 
| 
4700                     "Sliding kext %s: No writable segments.", 
4702                     "Sliding kext %s: No segments.", 
4704                     getIdentifierCString()); 
4708             reloc 
= (struct relocation_info 
*) (linkeditBase 
+ dysymtab
->locreloff
); 
4709             reloc_size 
= dysymtab
->nlocrel 
* sizeof(struct relocation_info
); 
4711             for (i 
= 0; i 
< dysymtab
->nlocrel
; i
++) { 
4712                 if (   reloc
[i
].r_extern 
!= 0 
4713                     || reloc
[i
].r_type 
!= 0 
4714                     || reloc
[i
].r_length 
!= (sizeof(void *) == 8 ? 3 : 2) 
4716                     || (reloc
[i
].r_address 
& R_SCATTERED
) 
4720                         kOSKextLogErrorLevel 
| kOSKextLogLoadFlag 
| 
4722                         "Sliding kext %s: Unexpected relocation found.", 
4723                         getIdentifierCString()); 
4726                 if (reloc
[i
].r_pcrel 
!= 0) { 
4729                 *((uintptr_t *)(relocBase 
+ reloc
[i
].r_address
)) += vm_kernel_slide
; 
4731 #if KASLR_KEXT_DEBUG 
4732 #define MAX_DYSYMS_TO_LOG 5 
4733                 if ( i 
< MAX_DYSYMS_TO_LOG 
) { 
4734                     IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",  
4735                           (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase 
+ reloc
[i
].r_address
))),  
4736                           (unsigned long)*((uintptr_t *)(relocBase 
+ reloc
[i
].r_address
))); 
4741             /* We should free these relocations, not just delete the reference to them. 
4742              * <rdar://problem/10535549> Free relocations from PIE kexts. 
4744             new_kextsize 
= round_page(kmod_info
->size 
- reloc_size
); 
4746             if ((kmod_info
->size 
- new_kextsize
) > PAGE_SIZE
) { 
4747                 vm_offset_t     endofkext 
= kmod_info
->address 
+ kmod_info
->size
; 
4748                 vm_offset_t     new_endofkext 
= kmod_info
->address 
+ new_kextsize
; 
4749                 vm_offset_t     endofrelocInfo 
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
); 
4750                 int             bytes_remaining 
= endofkext 
- endofrelocInfo
; 
4751                 OSData 
*        new_osdata 
= NULL
; 
4753                 /* fix up symbol offsets if they are after the dsymtab local relocs */ 
4755                     if (dysymtab
->locreloff 
< symtab
->symoff
){ 
4756                         symtab
->symoff 
-= reloc_size
; 
4758                     if (dysymtab
->locreloff 
< symtab
->stroff
) { 
4759                         symtab
->stroff 
-= reloc_size
; 
4762                 if (dysymtab
->locreloff 
< dysymtab
->extreloff
) { 
4763                     dysymtab
->extreloff 
-= reloc_size
; 
4766                 /* move data behind reloc info down to new offset */ 
4767                 if (endofrelocInfo 
< endofkext
) { 
4768                    memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
); 
4771                 /* Create a new OSData for the smaller kext object and reflect  
4772                  * new linkedit segment size. 
4774                 linkeditSeg
->vmsize 
= round_page(linkeditSeg
->vmsize 
- reloc_size
); 
4775                 linkeditSeg
->filesize 
= linkeditSeg
->vmsize
; 
4777                 new_osdata 
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
); 
4779                     /* Fix up kmod info and linkedExecutable. 
4781                     kmod_info
->size 
= new_kextsize
; 
4782                     linkedExecutable
->setDeallocFunction(NULL
); 
4783                     linkedExecutable
->release(); 
4784                     linkedExecutable 
= new_osdata
; 
4787                     kext_free(new_endofkext
, (endofkext 
- new_endofkext
)); 
4789                     ml_static_mfree(new_endofkext
, (endofkext 
- new_endofkext
)); 
4793             dysymtab
->nlocrel 
= 0; 
4794             dysymtab
->locreloff 
= 0; 
4798     result 
= kOSReturnSuccess
; 
4803 /********************************************************************* 
4804 * called only by load() 
4805 *********************************************************************/ 
4807 OSKext::loadExecutable() 
4809     OSReturn              result             
= kOSReturnError
; 
4810     kern_return_t         kxldResult
; 
4811     KXLDDependency     
*  kxlddeps           
= NULL
;  // must kfree 
4812     uint32_t              num_kxlddeps       
= 0; 
4813     OSArray            
*  linkDependencies   
= NULL
;  // must release 
4814     uint32_t              numDirectDependencies   
= 0; 
4815     uint32_t              num_kmod_refs      
= 0; 
4816     struct mach_header 
** kxldHeaderPtr      
= NULL
;  // do not free 
4817     struct mach_header  
* kxld_header        
= NULL
;  // xxx - need to free here? 
4818     OSData              
* theExecutable      
= NULL
;  // do not release 
4819     OSString            
* versString         
= NULL
;  // do not release 
4820     const char          * versCString        
= NULL
;  // do not free 
4821     const char          * string             
= NULL
;  // do not free 
4824    /* We need the version string for a variety of bits below. 
4826     versString 
= OSDynamicCast(OSString
, 
4827         getPropertyForHostArch(kCFBundleVersionKey
)); 
4831     versCString 
= versString
->getCStringNoCopy(); 
4833     if (isKernelComponent()) { 
4834        if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) { 
4836            if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) { 
4838                     kOSKextLogErrorLevel 
| 
4840                     "Kernel component %s has incorrect version %s; " 
4842                     getIdentifierCString(), 
4843                     versCString
, KERNEL6_VERSION
); 
4844                result 
= kOSKextReturnInternalError
; 
4846            } else if (strcmp(versCString
, osrelease
)) { 
4848                     kOSKextLogErrorLevel 
| 
4850                     "Kernel component %s has incorrect version %s; " 
4852                     getIdentifierCString(), 
4853                     versCString
, osrelease
); 
4854                result 
= kOSKextReturnInternalError
; 
4860     if (isPrelinked()) { 
4861         result 
= slidePrelinkedExecutable(); 
4862         if (result 
!= kOSReturnSuccess
) { 
4868     theExecutable 
= getExecutable(); 
4869     if (!theExecutable
) { 
4870         if (declaresExecutable()) { 
4872                 kOSKextLogErrorLevel 
| 
4874                 "Can't load kext %s - executable is missing.", 
4875                 getIdentifierCString()); 
4876             result 
= kOSKextReturnValidation
; 
4882     if (isInterface()) { 
4883         OSData 
*executableCopy 
= OSData::withData(theExecutable
); 
4884         setLinkedExecutable(executableCopy
); 
4885         executableCopy
->release(); 
4889     numDirectDependencies 
= getNumDependencies(); 
4891     if (flags
.hasBleedthrough
) { 
4892         linkDependencies 
= dependencies
; 
4893         linkDependencies
->retain(); 
4895         linkDependencies 
= OSArray::withArray(dependencies
); 
4896         if (!linkDependencies
) { 
4898                 kOSKextLogErrorLevel 
| 
4899                 kOSKextLogLoadFlag 
| kOSKextLogLinkFlag
, 
4900                 "Can't allocate link dependencies to load kext %s.", 
4901                 getIdentifierCString()); 
4905         for (i 
= 0; i 
< numDirectDependencies
; ++i
) { 
4906             OSKext 
* dependencyKext 
= OSDynamicCast(OSKext
, 
4907                 dependencies
->getObject(i
)); 
4908             dependencyKext
->addBleedthroughDependencies(linkDependencies
); 
4912     num_kxlddeps 
= linkDependencies
->getCount(); 
4913     if (!num_kxlddeps
) { 
4915             kOSKextLogErrorLevel 
| 
4916             kOSKextLogLoadFlag 
| kOSKextLogDependenciesFlag
, 
4917             "Can't load kext %s - it has no library dependencies.", 
4918             getIdentifierCString()); 
4922     kxlddeps 
= (KXLDDependency 
*)kalloc(num_kxlddeps 
* sizeof(*kxlddeps
)); 
4925             kOSKextLogErrorLevel 
| 
4926             kOSKextLogLoadFlag 
| kOSKextLogLinkFlag
, 
4927             "Can't allocate link context to load kext %s.", 
4928             getIdentifierCString()); 
4931     bzero(kxlddeps
, num_kxlddeps 
* sizeof(*kxlddeps
)); 
4933     for (i 
= 0; i 
< num_kxlddeps
; ++i 
) { 
4934         OSKext 
* dependency 
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
)); 
4936         if (dependency
->isInterface()) { 
4937             OSKext 
*interfaceTargetKext 
= NULL
; 
4938             OSData 
* interfaceTarget 
= NULL
; 
4940             if (dependency
->isKernelComponent()) { 
4941                 interfaceTargetKext 
= sKernelKext
; 
4942                 interfaceTarget 
= sKernelKext
->linkedExecutable
; 
4944                 interfaceTargetKext 
= OSDynamicCast(OSKext
,  
4945                     dependency
->dependencies
->getObject(0)); 
4947                 interfaceTarget 
= interfaceTargetKext
->linkedExecutable
; 
4950             if (!interfaceTarget
) { 
4955            /* The names set here aren't actually logged yet <rdar://problem/7941514>, 
4956             * it will be useful to have them in the debugger. 
4957             * strdup() failing isn't critical right here so we don't check that. 
4959             kxlddeps
[i
].kext 
= (u_char 
*) interfaceTarget
->getBytesNoCopy(); 
4960             kxlddeps
[i
].kext_size 
= interfaceTarget
->getLength(); 
4961             kxlddeps
[i
].kext_name 
= strdup(interfaceTargetKext
->getIdentifierCString()); 
4963             kxlddeps
[i
].interface 
= (u_char 
*) dependency
->linkedExecutable
->getBytesNoCopy(); 
4964             kxlddeps
[i
].interface_size 
= dependency
->linkedExecutable
->getLength(); 
4965             kxlddeps
[i
].interface_name 
= strdup(dependency
->getIdentifierCString()); 
4967             kxlddeps
[i
].kext 
= (u_char 
*) dependency
->linkedExecutable
->getBytesNoCopy(); 
4968             kxlddeps
[i
].kext_size 
= dependency
->linkedExecutable
->getLength(); 
4969             kxlddeps
[i
].kext_name 
= strdup(dependency
->getIdentifierCString()); 
4972         kxlddeps
[i
].is_direct_dependency 
= (i 
< numDirectDependencies
); 
4975     kxldHeaderPtr 
= &kxld_header
; 
4979         kOSKextLogExplicitLevel 
| 
4980         kOSKextLogLoadFlag 
| kOSKextLogLinkFlag
, 
4981         "Kext %s - calling kxld_link_file:\n" 
4982         "    kxld_context: %p\n" 
4983         "    executable: %p    executable_length: %d\n" 
4985         "    kxld_dependencies: %p    num_dependencies: %d\n" 
4986         "    kxld_header_ptr: %p    kmod_info_ptr: %p\n", 
4987         getIdentifierCString(), sKxldContext
, 
4988         theExecutable
->getBytesNoCopy(), theExecutable
->getLength(), 
4989         this, kxlddeps
, num_kxlddeps
, 
4990         kxldHeaderPtr
, &kmod_info
); 
4993    /* After this call, the linkedExecutable instance variable 
4996     kxldResult 
= kxld_link_file(sKxldContext
, 
4997         (u_char 
*)theExecutable
->getBytesNoCopy(), 
4998         theExecutable
->getLength(), 
4999         getIdentifierCString(), this, kxlddeps
, num_kxlddeps
, 
5000         (u_char 
**)kxldHeaderPtr
, (kxld_addr_t 
*)&kmod_info
); 
5002     if (kxldResult 
!= KERN_SUCCESS
) { 
5003         // xxx - add kxldResult here? 
5005             kOSKextLogErrorLevel 
| 
5007             "Can't load kext %s - link failed.", 
5008             getIdentifierCString()); 
5009         result 
= kOSKextReturnLinkError
; 
5013    /* We've written data & instructions into kernel memory, so flush the data 
5014     * cache and invalidate the instruction cache. 
5015     * I/D caches are coherent on x86 
5017 #if !defined(__i386__) && !defined(__x86_64__) 
5018     flush_dcache(kmod_info
->address
, kmod_info
->size
, false); 
5019     invalidate_icache(kmod_info
->address
, kmod_info
->size
, false); 
5023     if (isInterface()) { 
5025        /* Whip up a fake kmod_info entry for the interface kext. 
5027         kmod_info 
= (kmod_info_t 
*)kalloc(sizeof(kmod_info_t
)); 
5029             result 
= KERN_MEMORY_ERROR
; 
5033        /* A pseudokext has almost nothing in its kmod_info struct. 
5035         bzero(kmod_info
, sizeof(kmod_info_t
)); 
5037         kmod_info
->info_version 
= KMOD_INFO_VERSION
; 
5039        /* An interface kext doesn't have a linkedExecutable, so save a 
5040         * copy of the UUID out of the original executable via copyUUID() 
5041         * while we still have the original executable. 
5043         interfaceUUID 
= copyUUID(); 
5046     kmod_info
->id 
= loadTag 
= sNextLoadTag
++; 
5047     kmod_info
->reference_count 
= 0;  // KMOD_DECL... sets it to -1 (invalid). 
5049    /* Stamp the bundle ID and version from the OSKext over anything 
5050     * resident inside the kmod_info. 
5052     string 
= getIdentifierCString(); 
5053     strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
)); 
5055     string 
= versCString
; 
5056     strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
)); 
5058    /* Add the dependencies' kmod_info structs as kmod_references. 
5060     num_kmod_refs 
= getNumDependencies(); 
5061     if (num_kmod_refs
) { 
5062         kmod_info
->reference_list 
= (kmod_reference_t 
*)kalloc( 
5063             num_kmod_refs 
* sizeof(kmod_reference_t
)); 
5064         if (!kmod_info
->reference_list
) { 
5065             result 
= KERN_MEMORY_ERROR
; 
5068         bzero(kmod_info
->reference_list
, 
5069             num_kmod_refs 
* sizeof(kmod_reference_t
)); 
5070         for (uint32_t refIndex 
= 0; refIndex 
< num_kmod_refs
; refIndex
++) { 
5071             kmod_reference_t 
* ref 
= &(kmod_info
->reference_list
[refIndex
]); 
5072             OSKext 
* refKext 
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
)); 
5073             ref
->info 
= refKext
->kmod_info
; 
5074             ref
->info
->reference_count
++; 
5076             if (refIndex 
+ 1 < num_kmod_refs
) { 
5077                 ref
->next 
= kmod_info
->reference_list 
+ refIndex 
+ 1; 
5082     if (!isInterface() && linkedExecutable
) { 
5084             kOSKextLogProgressLevel 
| 
5086             "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",  
5088             (unsigned)kmod_info
->size 
/ PAGE_SIZE
, 
5089             (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
), 
5090             (unsigned)kmod_info
->id
); 
5093     result 
= setVMProtections(); 
5094     if (result 
!= KERN_SUCCESS
) { 
5098     result 
= kOSReturnSuccess
; 
5101     OSSafeRelease(linkDependencies
); 
5103    /* Clear up locally allocated dependency info. 
5105     for (i 
= 0; i 
< num_kxlddeps
; ++i 
) { 
5108         if (kxlddeps
[i
].kext_name
) { 
5109             size 
= 1 + strlen(kxlddeps
[i
].kext_name
); 
5110             kfree(kxlddeps
[i
].kext_name
, size
); 
5112         if (kxlddeps
[i
].interface_name
) { 
5113             size 
= 1 + strlen(kxlddeps
[i
].interface_name
); 
5114             kfree(kxlddeps
[i
].interface_name
, size
); 
5117     if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps 
* sizeof(*kxlddeps
))); 
5119    /* We no longer need the unrelocated executable (which the linker 
5120     * has altered anyhow). 
5122     setExecutable(NULL
); 
5124     if (result 
!= kOSReturnSuccess
) { 
5126             kOSKextLogErrorLevel 
| 
5128             "Failed to load executable for kext %s.", 
5129             getIdentifierCString()); 
5131         if (kmod_info 
&& kmod_info
->reference_list
) { 
5132             kfree(kmod_info
->reference_list
, 
5133                 num_kmod_refs 
* sizeof(kmod_reference_t
)); 
5135         if (isInterface()) { 
5136             kfree(kmod_info
, sizeof(kmod_info_t
)); 
5139         if (linkedExecutable
) { 
5140             linkedExecutable
->release(); 
5141             linkedExecutable 
= NULL
; 
5148 /********************************************************************* 
5149 * The linkedit segment is used by the kext linker for dependency 
5150 * resolution, and by dtrace for probe initialization. We can free it 
5151 * for non-library kexts, since no kexts depend on non-library kexts 
5152 * by definition, once dtrace has been initialized. 
5153 *********************************************************************/ 
5155 OSKext::jettisonLinkeditSegment(void) 
5157     kernel_mach_header_t     
* machhdr 
= (kernel_mach_header_t 
*)kmod_info
->address
; 
5158     kernel_segment_command_t 
* linkedit 
= NULL
; 
5160     vm_size_t                  linkeditsize
, kextsize
; 
5161     OSData                   
* data 
= NULL
; 
5164         /* We can free symbol tables for all embedded kexts because we don't 
5165          * support runtime kext linking. 
5167     if (sKeepSymbols 
|| !isExecutable() || !linkedExecutable 
|| flags
.jettisonLinkeditSeg
) { 
5169     if (sKeepSymbols 
|| isLibrary() || !isExecutable() || !linkedExecutable 
|| flags
.jettisonLinkeditSeg
) { 
5174    /* Find the linkedit segment.  If it's not the last segment, then freeing 
5175     * it will fragment the kext into multiple VM regions, which OSKext is not 
5176     * designed to handle, so we'll have to skip it. 
5178     linkedit 
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
); 
5183     if (round_page(kmod_info
->address 
+ kmod_info
->size
) != 
5184         round_page(linkedit
->vmaddr 
+ linkedit
->vmsize
)) 
5189    /* Create a new OSData for the smaller kext object. 
5191     linkeditsize 
= round_page(linkedit
->vmsize
); 
5192     kextsize 
= kmod_info
->size 
- linkeditsize
; 
5193     start 
= linkedit
->vmaddr
; 
5195     data 
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
); 
5200    /* Fix the kmod info and linkedExecutable. 
5202     kmod_info
->size 
= kextsize
; 
5203     linkedExecutable
->setDeallocFunction(NULL
); 
5204     linkedExecutable
->release(); 
5205     linkedExecutable 
= data
; 
5206     flags
.jettisonLinkeditSeg 
= 1; 
5208    /* Free the linkedit segment. 
5211     kext_free(start
, linkeditsize
); 
5213     ml_static_mfree(start
, linkeditsize
); 
5220 /********************************************************************* 
5221 *********************************************************************/ 
5223 OSKext::setLinkedExecutable(OSData 
* anExecutable
) 
5225     if (linkedExecutable
) { 
5226         panic("Attempt to set linked executable on kext " 
5227             "that already has one (%s).\n", 
5228             getIdentifierCString()); 
5230     linkedExecutable 
= anExecutable
; 
5231     linkedExecutable
->retain(); 
5236 /********************************************************************* 
5237 * Go through all loaded kexts and tell them to register with dtrace. 
5238 * The instance method only registers if necessary. 
5239 *********************************************************************/ 
5242 OSKext::registerKextsWithDTrace(void) 
5244     uint32_t count 
= sLoadedKexts
->getCount(); 
5247     IORecursiveLockLock(sKextLock
); 
5249     for (i 
= 0; i 
< count
; i
++) { 
5250         OSKext   
* thisKext     
= NULL
;  // do not release 
5252         thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
5253         if (!thisKext 
|| !thisKext
->isExecutable()) { 
5257         thisKext
->registerWithDTrace(); 
5260     IORecursiveLockUnlock(sKextLock
); 
5266     extern int (*dtrace_modload
)(struct kmod_info 
*, uint32_t); 
5267     extern int (*dtrace_modunload
)(struct kmod_info 
*); 
5270 /********************************************************************* 
5271 *********************************************************************/ 
5273 OSKext::registerWithDTrace(void) 
5275    /* Register kext with dtrace. A dtrace_modload failure should not 
5276     * prevent a kext from loading, so we ignore the return code. 
5278     if (!flags
.dtraceInitialized 
&& (dtrace_modload 
!= NULL
)) { 
5279         uint32_t modflag 
= 0; 
5280         OSObject 
* forceInit 
= getPropertyForHostArch("OSBundleForceDTraceInit"); 
5281         if (forceInit 
== kOSBooleanTrue
) { 
5282             modflag 
|= KMOD_DTRACE_FORCE_INIT
; 
5285         (void)(*dtrace_modload
)(kmod_info
, modflag
); 
5286         flags
.dtraceInitialized 
= true; 
5287         jettisonLinkeditSegment(); 
5291 /********************************************************************* 
5292 *********************************************************************/ 
5294 OSKext::unregisterWithDTrace(void) 
5296    /* Unregister kext with dtrace. A dtrace_modunload failure should not 
5297     * prevent a kext from loading, so we ignore the return code. 
5299     if (flags
.dtraceInitialized 
&& (dtrace_modunload 
!= NULL
)) { 
5300         (void)(*dtrace_modunload
)(kmod_info
); 
5301         flags
.dtraceInitialized 
= false; 
5305 #endif /* CONFIG_DTRACE */ 
5308 /********************************************************************* 
5309 * called only by loadExecutable() 
5310 *********************************************************************/ 
5311 #if !VM_MAPPED_KEXTS 
5312 #error Unrecognized architecture  
5314 static inline kern_return_t
 
5317     vm_map_offset_t    start
, 
5318     vm_map_offset_t    end
, 
5322     if (start 
== end
) { // 10538581 
5323         return(KERN_SUCCESS
); 
5325     return vm_map_protect(map
, start
, end
, new_prot
, set_max
); 
5328 static inline kern_return_t
 
5331     vm_map_offset_t    start
, 
5332     vm_map_offset_t    end
, 
5333     vm_prot_t  access_type
, 
5334     boolean_t       user_wire
) 
5336         return vm_map_wire(map
, start
, end
, access_type
, user_wire
); 
5341 OSKext::setVMProtections(void) 
5343     vm_map_t                    kext_map        
= NULL
; 
5344     kernel_segment_command_t  
* seg             
= NULL
; 
5345     vm_map_offset_t             start           
= 0; 
5346     vm_map_offset_t             end             
= 0; 
5347     OSReturn                    result          
= kOSReturnError
; 
5349     if (!kmod_info
->address 
&& !kmod_info
->size
) { 
5350         result 
= kOSReturnSuccess
; 
5354     /* Get the kext's vm map */ 
5355     kext_map 
= kext_get_vm_map(kmod_info
); 
5357         result 
= KERN_MEMORY_ERROR
; 
5361     /* Protect the headers as read-only; they do not need to be wired */ 
5362     result 
= OSKext_protect(kext_map
, kmod_info
->address
,  
5363         kmod_info
->address 
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
); 
5364     if (result 
!= KERN_SUCCESS
) { 
5368     /* Set the VM protections and wire down each of the segments */ 
5369     seg 
= firstsegfromheader((kernel_mach_header_t 
*)kmod_info
->address
); 
5371         start 
= round_page(seg
->vmaddr
); 
5372         end 
= trunc_page(seg
->vmaddr 
+ seg
->vmsize
); 
5374         result 
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
); 
5375         if (result 
!= KERN_SUCCESS
) { 
5377                 kOSKextLogErrorLevel 
| 
5379                 "Kext %s failed to set maximum VM protections " 
5380                 "for segment %s - 0x%x.",  
5381                 getIdentifierCString(), seg
->segname
, (int)result
); 
5385         result 
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
); 
5386         if (result 
!= KERN_SUCCESS
) { 
5388                 kOSKextLogErrorLevel 
| 
5390                 "Kext %s failed to set initial VM protections " 
5391                 "for segment %s - 0x%x.",  
5392                 getIdentifierCString(), seg
->segname
, (int)result
); 
5396         if (segmentShouldBeWired(seg
)) { 
5397             result 
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
); 
5398             if (result 
!= KERN_SUCCESS
) { 
5403         seg 
= nextsegfromheader((kernel_mach_header_t 
*) kmod_info
->address
, seg
); 
5410 /********************************************************************* 
5411 *********************************************************************/ 
5413 OSKext::segmentShouldBeWired(kernel_segment_command_t 
*seg
) 
5415     return (sKeepSymbols 
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
))); 
5418 /********************************************************************* 
5419 *********************************************************************/ 
5421 OSKext::validateKextMapping(bool startFlag
) 
5423     OSReturn                              result      
= kOSReturnError
; 
5424     const char                          * whichOp 
= startFlag 
? "start" : "stop"; 
5425     kern_return_t                         kern_result 
= 0; 
5426     vm_map_t                              kext_map    
= NULL
; 
5427     kernel_segment_command_t            
* seg         
= NULL
; 
5428     mach_vm_address_t                     address     
= 0; 
5429     mach_vm_size_t                        size        
= 0; 
5431     mach_msg_type_number_t                count
; 
5432     vm_region_submap_short_info_data_64_t info
; 
5434     count 
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
; 
5435     bzero(&info
, sizeof(info
)); 
5437    // xxx - do we need a distinct OSReturn value for these or is "bad data" 
5438    // xxx - sufficient? 
5440    /* Verify that the kmod_info and start/stop pointers are non-NULL. 
5444             kOSKextLogErrorLevel 
| 
5446             "Kext %s - NULL kmod_info pointer.", 
5447             getIdentifierCString()); 
5448         result 
= kOSKextReturnBadData
; 
5453         address 
= (mach_vm_address_t
)kmod_info
->start
; 
5455         address 
= (mach_vm_address_t
)kmod_info
->stop
; 
5460             kOSKextLogErrorLevel 
| 
5462             "Kext %s - NULL module %s pointer.", 
5463             getIdentifierCString(), whichOp
); 
5464         result 
= kOSKextReturnBadData
; 
5468     kext_map 
= kext_get_vm_map(kmod_info
); 
5469     depth 
= (kernel_map 
== kext_map
) ? 1 : 2; 
5471    /* Verify that the start/stop function lies within the kext's address range. 
5473     if (address 
< kmod_info
->address 
+ kmod_info
->hdr_size 
|| 
5474         kmod_info
->address 
+ kmod_info
->size 
<= address
) 
5477             kOSKextLogErrorLevel 
| 
5479             "Kext %s module %s pointer is outside of kext range " 
5480             "(%s %p - kext at %p-%p)..", 
5481             getIdentifierCString(), 
5484             (void *)VM_KERNEL_UNSLIDE(address
), 
5485             (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
), 
5486             (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
)); 
5487         result 
= kOSKextReturnBadData
; 
5491    /* Only do these checks before calling the start function; 
5492     * If anything goes wrong with the mapping while the kext is running, 
5493     * we'll likely have panicked well before any attempt to stop the kext. 
5497        /* Verify that the start/stop function is executable. 
5499         kern_result 
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
, 
5500             (vm_region_recurse_info_t
)&info
, &count
); 
5501         if (kern_result 
!= KERN_SUCCESS
) { 
5503                 kOSKextLogErrorLevel 
| 
5505                 "Kext %s - bad %s pointer %p.", 
5506                 getIdentifierCString(), 
5507                 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));  
5508             result 
= kOSKextReturnBadData
; 
5513         if (!(info
.protection 
& VM_PROT_EXECUTE
)) { 
5515                 kOSKextLogErrorLevel 
| 
5517                 "Kext %s - memory region containing module %s function " 
5518                 "is not executable.", 
5519                 getIdentifierCString(), whichOp
); 
5520             result 
= kOSKextReturnBadData
; 
5525        /* Verify that the kext's segments are backed by physical memory. 
5527         seg 
= firstsegfromheader((kernel_mach_header_t 
*)kmod_info
->address
); 
5529             if (!verifySegmentMapping(seg
)) { 
5530                 result 
= kOSKextReturnBadData
; 
5534             seg 
= nextsegfromheader((kernel_mach_header_t 
*) kmod_info
->address
, seg
); 
5539     result 
= kOSReturnSuccess
; 
5544 /********************************************************************* 
5545 *********************************************************************/ 
5547 OSKext::verifySegmentMapping(kernel_segment_command_t 
*seg
) 
5549     mach_vm_address_t address 
= 0; 
5551     if (!segmentShouldBeWired(seg
)) return true; 
5553     for (address 
= seg
->vmaddr
; 
5554          address 
< round_page(seg
->vmaddr 
+ seg
->vmsize
); 
5555          address 
+= PAGE_SIZE
) 
5557         if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) { 
5559                 kOSKextLogErrorLevel 
| 
5561                 "Kext %s - page %p is not backed by physical memory.", 
5562                 getIdentifierCString(),  
5571 /********************************************************************* 
5572 *********************************************************************/ 
5574 OSKext::start(bool startDependenciesFlag
) 
5576     OSReturn                            result 
= kOSReturnError
; 
5577     kern_return_t                       (* startfunc
)(kmod_info_t 
*, void *); 
5578     unsigned int                        i
, count
; 
5579     void                              * kmodStartData 
= NULL
;  
5581     if (isStarted() || isInterface() || isKernelComponent()) { 
5582         result 
= kOSReturnSuccess
; 
5588             kOSKextLogErrorLevel 
| 
5590             "Attempt to start nonloaded kext %s.", 
5591             getIdentifierCString());  
5592         result 
= kOSKextReturnInvalidArgument
; 
5596     if (!sLoadEnabled
) { 
5598             kOSKextLogErrorLevel 
| 
5600             "Kext loading is disabled (attempt to start kext %s).", 
5601             getIdentifierCString()); 
5602         result 
= kOSKextReturnDisabled
; 
5606     result 
= validateKextMapping(/* start? */ true); 
5607     if (result 
!= kOSReturnSuccess
) { 
5611     startfunc 
= kmod_info
->start
; 
5613     count 
= getNumDependencies(); 
5614     for (i 
= 0; i 
< count
; i
++) { 
5615         OSKext 
* dependency 
= OSDynamicCast(OSKext
, dependencies
->getObject(i
)); 
5616         if (dependency 
== NULL
) { 
5618                 kOSKextLogErrorLevel 
| 
5620                 "Kext %s start - internal error, dependency disappeared.", 
5621                 getIdentifierCString()); 
5624         if (!dependency
->isStarted()) { 
5625             if (startDependenciesFlag
) { 
5626                 OSReturn dependencyResult 
= 
5627                     dependency
->start(startDependenciesFlag
); 
5628                 if (dependencyResult 
!= KERN_SUCCESS
) { 
5630                         kOSKextLogErrorLevel 
| 
5632                         "Kext %s start - dependency %s failed to start (error 0x%x).", 
5633                         getIdentifierCString(), 
5634                         dependency
->getIdentifierCString(), 
5640                     kOSKextLogErrorLevel 
| 
5642                     "Not starting %s - dependency %s not started yet.", 
5643                     getIdentifierCString(), 
5644                     dependency
->getIdentifierCString()); 
5645                 result 
= kOSKextReturnStartStopError
;  // xxx - make new return? 
5652         kOSKextLogDetailLevel 
| 
5654         "Kext %s calling module start function.", 
5655         getIdentifierCString());  
5659 #if !CONFIG_STATIC_CPPINIT 
5660     result 
= OSRuntimeInitializeCPP(kmod_info
, NULL
); 
5661     if (result 
== KERN_SUCCESS
) { 
5665         kmodStartData 
= GetAppleTEXTHashForKext(this, this->infoDict
); 
5668         if (kmodStartData
) { 
5670                       kOSKextLogErrorLevel 
| 
5671                       kOSKextLogGeneralFlag
, 
5672                       "Kext %s calling module start function. kmodStartData %p. arch %s", 
5673                       getIdentifierCString(), kmodStartData
, ARCHNAME
);  
5676 #endif // CONFIG_KEC_FIPS  
5678         result 
= startfunc(kmod_info
, kmodStartData
); 
5680 #if !CONFIG_STATIC_CPPINIT 
5681         if (result 
!= KERN_SUCCESS
) { 
5682             (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
); 
5689    /* On success overlap the setting of started/starting. On failure just 
5692     if (result 
== KERN_SUCCESS
) { 
5695         // xxx - log start error from kernel? 
5697             kOSKextLogProgressLevel 
| 
5699             "Kext %s is now started.", 
5700             getIdentifierCString());  
5702         invokeOrCancelRequestCallbacks( 
5703             /* result not actually used */ kOSKextReturnStartStopError
, 
5704             /* invokeFlag */ false); 
5706             kOSKextLogProgressLevel 
| 
5708             "Kext %s did not start (return code 0x%x).", 
5709             getIdentifierCString(), result
);  
5716 /********************************************************************* 
5717 *********************************************************************/ 
5719 bool OSKext::canUnloadKextWithIdentifier( 
5720     OSString 
* kextIdentifier
, 
5721     bool       checkClassesFlag
) 
5723     bool     result 
= false; 
5724     OSKext 
* aKext  
= NULL
;  // do not release 
5726     IORecursiveLockLock(sKextLock
); 
5728     aKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
)); 
5731         goto finish
;  // can't unload what's not loaded 
5734     if (aKext
->isLoaded()) { 
5735         if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) { 
5738         if (checkClassesFlag 
&& aKext
->hasOSMetaClassInstances()) { 
5746     IORecursiveLockUnlock(sKextLock
); 
5750 /********************************************************************* 
5751 *********************************************************************/ 
5755     OSReturn result 
= kOSReturnError
; 
5756     kern_return_t (*stopfunc
)(kmod_info_t 
*, void *); 
5758     if (!isStarted() || isInterface()) { 
5759         result 
= kOSReturnSuccess
; 
5765             kOSKextLogErrorLevel 
| 
5767             "Attempt to stop nonloaded kext %s.", 
5768             getIdentifierCString()); 
5769         result 
= kOSKextReturnInvalidArgument
; 
5773    /* Refuse to stop if we have clients or instances. It is up to 
5774     * the caller to make sure those aren't true. 
5776     if (getRetainCount() > kOSKextMinLoadedRetainCount
) { 
5778             kOSKextLogErrorLevel 
| 
5780             "Kext %s - C++ instances; can't stop.", 
5781             getIdentifierCString()); 
5782         result 
= kOSKextReturnInUse
; 
5786     if (getRetainCount() > kOSKextMinLoadedRetainCount
) { 
5789             kOSKextLogErrorLevel 
| 
5791             "Kext %s - has references (linkage or tracking object); " 
5793             getIdentifierCString()); 
5794         result 
= kOSKextReturnInUse
; 
5798    /* Note: If validateKextMapping fails on the stop & unload path, 
5799     * we are in serious trouble and a kernel panic is likely whether 
5800     * we stop & unload the kext or not. 
5802     result 
= validateKextMapping(/* start? */ false); 
5803     if (result 
!= kOSReturnSuccess
) { 
5807     stopfunc 
= kmod_info
->stop
; 
5810             kOSKextLogDetailLevel 
| 
5812             "Kext %s calling module stop function.", 
5813             getIdentifierCString());  
5817         result 
= stopfunc(kmod_info
, /* userData */ NULL
); 
5818 #if !CONFIG_STATIC_CPPINIT 
5819         if (result 
== KERN_SUCCESS
) { 
5820             result 
= OSRuntimeFinalizeCPP(kmod_info
, NULL
); 
5826         if (result 
== KERN_SUCCESS
) { 
5830                 kOSKextLogDetailLevel 
| 
5832                 "Kext %s is now stopped and ready to unload.", 
5833                 getIdentifierCString());  
5836                 kOSKextLogErrorLevel 
| 
5838                 "Kext %s did not stop (return code 0x%x).", 
5839                 getIdentifierCString(), result
);  
5840             result 
= kOSKextReturnStartStopError
; 
5848 /********************************************************************* 
5849 *********************************************************************/ 
5851 OSKext::unload(void) 
5853     OSReturn     result 
= kOSReturnError
; 
5855     uint32_t     num_kmod_refs 
= 0; 
5857     if (!sUnloadEnabled
) { 
5859             kOSKextLogErrorLevel 
| 
5861             "Kext unloading is disabled (%s).", 
5862             this->getIdentifierCString()); 
5864         result 
= kOSKextReturnDisabled
; 
5868    /* Refuse to unload if we have clients or instances. It is up to 
5869     * the caller to make sure those aren't true. 
5871     if (getRetainCount() > kOSKextMinLoadedRetainCount
) { 
5872         // xxx - Don't log under errors? this is more of an info thing 
5874             kOSKextLogErrorLevel 
| 
5875             kOSKextLogKextBookkeepingFlag
, 
5876             "Can't unload kext %s; outstanding references (linkage or tracking object).", 
5877             getIdentifierCString()); 
5878         result 
= kOSKextReturnInUse
; 
5882     if (hasOSMetaClassInstances()) { 
5884             kOSKextLogErrorLevel 
| 
5885             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
5886             "Can't unload kext %s; classes have instances:", 
5887             getIdentifierCString()); 
5888         reportOSMetaClassInstances(kOSKextLogErrorLevel 
| 
5889             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
); 
5890         result 
= kOSKextReturnInUse
; 
5895         result 
= kOSReturnSuccess
; 
5899     if (isKernelComponent()) { 
5900         result 
= kOSKextReturnInvalidArgument
; 
5904    /* Note that the kext is unloading before running any code that 
5905     * might be in the kext (request callbacks, module stop function). 
5906     * We will deny certain requests made against a kext in the process 
5909     flags
.unloading 
= 1; 
5911    /* Update the string describing the last kext to unload in case we panic. 
5913     savePanicString(/* isLoading */ false); 
5917         if (result 
!= KERN_SUCCESS
) { 
5919                 kOSKextLogErrorLevel 
| 
5921                 "Kext %s can't unload - module stop returned 0x%x.", 
5922                 getIdentifierCString(), (unsigned)result
); 
5923             result 
= kOSKextReturnStartStopError
; 
5929         kOSKextLogProgressLevel 
| 
5931         "Kext %s unloading.", 
5932         getIdentifierCString()); 
5934    /* Even if we don't call the stop function, we want to be sure we 
5935     * have no OSMetaClass references before unloading the kext executable 
5936     * from memory. OSMetaClasses may have pointers into the kext executable 
5937     * and that would cause a panic on OSKext::free() when metaClasses is freed. 
5940         metaClasses
->flushCollection(); 
5943    /* Remove the kext from the list of loaded kexts, patch the gap 
5944     * in the kmod_info_t linked list, and reset "kmod" to point to the 
5945     * last loaded kext that isn't the fake kernel kext (sKernelKext). 
5947     index 
= sLoadedKexts
->getNextIndexOfObject(this, 0); 
5948     if (index 
!= (unsigned int)-1) { 
5950         sLoadedKexts
->removeObject(index
); 
5952         OSKext 
* nextKext 
= OSDynamicCast(OSKext
, 
5953             sLoadedKexts
->getObject(index
)); 
5957                 OSKext 
* gapKext 
= OSDynamicCast(OSKext
, 
5958                     sLoadedKexts
->getObject(index 
- 1)); 
5960                 nextKext
->kmod_info
->next 
= gapKext
->kmod_info
; 
5962             } else /* index == 0 */ { 
5963                 nextKext
->kmod_info
->next 
= NULL
; 
5967         OSKext 
* lastKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject()); 
5968         if (lastKext 
&& !lastKext
->isKernel()) { 
5969             kmod 
= lastKext
->kmod_info
; 
5971             kmod 
= NULL
;  // clear the global kmod variable 
5975    /* Clear out the kmod references that we're keeping for compatibility 
5976     * with current panic backtrace code & kgmacros. 
5977     * xxx - will want to update those bits sometime and remove this. 
5979     num_kmod_refs 
= getNumDependencies(); 
5980     if (num_kmod_refs 
&& kmod_info 
&& kmod_info
->reference_list
) { 
5981         for (uint32_t refIndex 
= 0; refIndex 
< num_kmod_refs
; refIndex
++) { 
5982             kmod_reference_t 
* ref 
= &(kmod_info
->reference_list
[refIndex
]); 
5983             ref
->info
->reference_count
--; 
5985         kfree(kmod_info
->reference_list
, 
5986             num_kmod_refs 
* sizeof(kmod_reference_t
)); 
5990     unregisterWithDTrace(); 
5991 #endif /* CONFIG_DTRACE */ 
5993     notifyKextUnloadObservers(this); 
5995     /* Unwire and free the linked executable. 
5997     if (linkedExecutable
) { 
5999         if (!isInterface()) { 
6000             kernel_segment_command_t 
*seg 
= NULL
; 
6001             vm_map_t kext_map 
= kext_get_vm_map(kmod_info
); 
6005                     kOSKextLogErrorLevel 
| 
6007                     "Failed to free kext %s; couldn't find the kext map.", 
6008                     getIdentifierCString()); 
6009                 result 
= kOSKextReturnInternalError
; 
6014                 kOSKextLogProgressLevel 
| 
6016                 "Kext %s unwiring and unmapping linked executable.", 
6017                 getIdentifierCString()); 
6019             seg 
= firstsegfromheader((kernel_mach_header_t 
*)kmod_info
->address
); 
6021                 if (segmentShouldBeWired(seg
)) { 
6022                     result 
= vm_map_unwire(kext_map
, seg
->vmaddr
,  
6023                         seg
->vmaddr 
+ seg
->vmsize
, FALSE
); 
6024                     if (result 
!= KERN_SUCCESS
) { 
6026                             kOSKextLogErrorLevel 
| 
6028                             "Failed to unwire kext %s.", 
6029                             getIdentifierCString()); 
6030                         result 
= kOSKextReturnInternalError
; 
6035                 seg 
= nextsegfromheader((kernel_mach_header_t 
*) kmod_info
->address
, seg
); 
6039         OSSafeReleaseNULL(linkedExecutable
); 
6042    /* An interface kext has a fake kmod_info that was allocated, 
6043     * so we have to free it. 
6045     if (isInterface()) { 
6046         kfree(kmod_info
, sizeof(kmod_info_t
)); 
6051     flags
.loaded 
= false; 
6052     flushDependencies(); 
6054     /* save a copy of the bundle ID for us to check when deciding to  
6055      * rebuild the kernel cache file.  If a kext was already in the kernel  
6056      * cache and unloaded then later loaded we do not need to rebuild the  
6057      * kernel cache.  9055303 
6059     if (isPrelinked()) { 
6060         if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) { 
6061             IORecursiveLockLock(sKextLock
); 
6062             if (sUnloadedPrelinkedKexts
) { 
6063                 sUnloadedPrelinkedKexts
->setObject(bundleID
); 
6065             IORecursiveLockUnlock(sKextLock
); 
6070         kOSKextLogProgressLevel 
| kOSKextLogLoadFlag
, 
6071         "Kext %s unloaded.", getIdentifierCString()); 
6073     queueKextNotification(kKextRequestPredicateUnloadNotification
, 
6074         OSDynamicCast(OSString
, bundleID
)); 
6077     OSKext::saveLoadedKextPanicList(); 
6078     OSKext::updateLoadedKextSummaries(); 
6080     flags
.unloading 
= 0; 
6084 /********************************************************************* 
6085 * Assumes sKextLock is held. 
6086 *********************************************************************/ 
6089 OSKext::queueKextNotification( 
6090     const char * notificationName
, 
6091     OSString   
* kextIdentifier
) 
6093     OSReturn          result               
= kOSReturnError
; 
6094     OSDictionary    
* loadRequest          
= NULL
;  // must release 
6096     if (!kextIdentifier
) { 
6097         result 
= kOSKextReturnInvalidArgument
; 
6101    /* Create a new request unless one is already sitting 
6102     * in sKernelRequests for this bundle identifier 
6104     result 
= _OSKextCreateRequest(notificationName
, &loadRequest
); 
6105     if (result 
!= kOSReturnSuccess
) { 
6108     if (!_OSKextSetRequestArgument(loadRequest
, 
6109         kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) { 
6111         result 
= kOSKextReturnNoMemory
; 
6114     if (!sKernelRequests
->setObject(loadRequest
)) { 
6115         result 
= kOSKextReturnNoMemory
; 
6119    /* We might want to only queue the notification if kextd is active, 
6120     * but that wouldn't work for embedded. Note that we don't care if 
6121     * the ping immediately succeeds here so don't do anything with the 
6122     * result of this call. 
6124     OSKext::pingKextd(); 
6126     result 
= kOSReturnSuccess
; 
6129     OSSafeRelease(loadRequest
); 
6134 /********************************************************************* 
6135 *********************************************************************/ 
6137 _OSKextConsiderDestroyingLinkContext( 
6138     __unused thread_call_param_t p0
, 
6139     __unused thread_call_param_t p1
) 
6141    /* Take multiple locks in the correct order. 
6143     IORecursiveLockLock(sKextLock
); 
6144     IORecursiveLockLock(sKextInnerLock
); 
6146    /* The first time we destroy the kxldContext is in the first  
6147     * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled 
6148     * before calling this function. Thereafter any call to this function 
6149     * will actually destroy the context. 
6151     if (sConsiderUnloadsCalled 
&& sKxldContext
) { 
6152         kxld_destroy_context(sKxldContext
); 
6153         sKxldContext 
= NULL
; 
6156    /* Free the thread_call that was allocated to execute this function. 
6158     if (sDestroyLinkContextThread
) { 
6159         if (!thread_call_free(sDestroyLinkContextThread
)) { 
6160             OSKextLog(/* kext */ NULL
, 
6161                 kOSKextLogErrorLevel 
| 
6162                 kOSKextLogGeneralFlag
, 
6163                 "thread_call_free() failed for kext link context."); 
6165         sDestroyLinkContextThread 
= 0; 
6168     IORecursiveLockUnlock(sKextInnerLock
); 
6169     IORecursiveLockUnlock(sKextLock
); 
6174 /********************************************************************* 
6175 * Destroying the kxldContext requires checking variables under both 
6176 * sKextInnerLock and sKextLock, so we do it on a separate thread 
6177 * to avoid deadlocks with IOService, with which OSKext has a reciprocal 
6178 * call relationship. 
6180 * This function must be invoked with sKextInnerLock held. 
6181 * Do not call any function that takes sKextLock here! 
6182 *********************************************************************/ 
6185 OSKext::considerDestroyingLinkContext(void) 
6187     IORecursiveLockLock(sKextInnerLock
); 
6189    /* If we have already queued a thread to destroy the link context, 
6190     * don't bother resetting; that thread will take care of it. 
6192     if (sDestroyLinkContextThread
) { 
6196    /* The function to be invoked in the thread will deallocate 
6197     * this thread_call, so don't share it around. 
6199     sDestroyLinkContextThread 
= thread_call_allocate( 
6200         &_OSKextConsiderDestroyingLinkContext
, 0); 
6201     if (!sDestroyLinkContextThread
) { 
6202         OSKextLog(/* kext */ NULL
, 
6203             kOSKextLogErrorLevel 
| kOSKextLogGeneralFlag 
| kOSKextLogLinkFlag
, 
6204             "Can't create thread to destroy kext link context."); 
6208     thread_call_enter(sDestroyLinkContextThread
); 
6211     IORecursiveLockUnlock(sKextInnerLock
); 
6216 #pragma mark Autounload 
6218 /********************************************************************* 
6219 * This is a static method because the kext will be deallocated if it 
6221 *********************************************************************/ 
6224 OSKext::autounloadKext(OSKext 
* aKext
) 
6226     OSReturn result 
= kOSKextReturnInUse
; 
6228    /* Check for external references to this kext (usu. dependents), 
6229     * instances of defined classes (or classes derived from them), 
6230     * outstanding requests. 
6232     if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) || 
6233         !aKext
->flags
.autounloadEnabled 
|| 
6234         aKext
->isKernelComponent()) { 
6239    /* Skip a delay-autounload kext, once. 
6241     if (aKext
->flags
.delayAutounload
) { 
6243             kOSKextLogProgressLevel 
| 
6244             kOSKextLogLoadFlag 
| kOSKextLogKextBookkeepingFlag
, 
6245             "Kext %s has delayed autounload set; skipping and clearing flag.", 
6246             aKext
->getIdentifierCString()); 
6247         aKext
->flags
.delayAutounload 
= 0; 
6251     if (aKext
->hasOSMetaClassInstances() || 
6252         aKext
->countRequestCallbacks()) { 
6256     result 
= OSKext::removeKext(aKext
); 
6263 /********************************************************************* 
6264 *********************************************************************/ 
6266 _OSKextConsiderUnloads( 
6267     __unused thread_call_param_t p0
, 
6268     __unused thread_call_param_t p1
) 
6270     bool         didUnload 
= false; 
6271     unsigned int count
, i
; 
6273    /* Take multiple locks in the correct order 
6274     * (note also sKextSummaries lock further down). 
6276     IORecursiveLockLock(sKextLock
); 
6277     IORecursiveLockLock(sKextInnerLock
); 
6279     OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true); 
6281     IOLockLock(sKextSummariesLock
); 
6283    /* If there is an old kext summary, free that now. 
6285     if (sPrevLoadedKextSummaries
) { 
6286         kmem_free(kernel_map
, (vm_offset_t
)sPrevLoadedKextSummaries
, 
6287             sPrevLoadedKextSummariesAllocSize
); 
6288         sPrevLoadedKextSummaries 
= NULL
; 
6289         sPrevLoadedKextSummariesAllocSize 
= 0; 
6292     IOLockUnlock(sKextSummariesLock
); 
6294    /* If the system is powering down, don't try to unload anything. 
6300     OSKextLog(/* kext */ NULL
, 
6301         kOSKextLogProgressLevel 
| 
6303         "Checking for unused kexts to autounload."); 
6306     * Remove any request callbacks marked as stale, 
6307     * and mark as stale any currently in flight. 
6309     count 
= sRequestCallbackRecords
->getCount(); 
6313             OSDictionary 
* callbackRecord 
= OSDynamicCast(OSDictionary
, 
6314                 sRequestCallbackRecords
->getObject(i
)); 
6315             OSBoolean 
* stale 
= OSDynamicCast(OSBoolean
, 
6316                 callbackRecord
->getObject(kKextRequestStaleKey
)); 
6318             if (stale 
== kOSBooleanTrue
) { 
6319                 OSKext::invokeRequestCallback(callbackRecord
, 
6320                     kOSKextReturnTimeout
); 
6322                 callbackRecord
->setObject(kKextRequestStaleKey
, 
6329     * Make multiple passes through the array of loaded kexts until 
6330     * we don't unload any. This handles unwinding of dependency 
6331     * chains. We have to go *backwards* through the array because 
6332     * kexts are removed from it when unloaded, and we cannot make 
6333     * a copy or we'll mess up the retain counts we rely on to 
6334     * check whether a kext will unload. If only we could have 
6335     * nonretaining collections like CF has.... 
6340         count 
= sLoadedKexts
->getCount(); 
6344                 OSKext 
* thisKext 
= OSDynamicCast(OSKext
, 
6345                     sLoadedKexts
->getObject(i
)); 
6346                 didUnload 
= (kOSReturnSuccess 
== OSKext::autounloadKext(thisKext
)); 
6349     } while (didUnload
); 
6352     sConsiderUnloadsPending 
= false; 
6353     sConsiderUnloadsExecuted 
= true; 
6355     (void) OSKext::considerRebuildOfPrelinkedKernel(); 
6357     IORecursiveLockUnlock(sKextInnerLock
); 
6358     IORecursiveLockUnlock(sKextLock
); 
6363 /********************************************************************* 
6364 * Do not call any function that takes sKextLock here! 
6365 *********************************************************************/ 
6366 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
) 
6370     IORecursiveLockLock(sKextInnerLock
); 
6372     if (!sUnloadCallout
) { 
6373         sUnloadCallout 
= thread_call_allocate(&_OSKextConsiderUnloads
, 0); 
6376     /* we only reset delay value for unloading if we already have something 
6377      * pending.  rescheduleOnlyFlag should not start the count down. 
6379     if (rescheduleOnlyFlag 
&& !sConsiderUnloadsPending
) { 
6383     thread_call_cancel(sUnloadCallout
); 
6384     if (OSKext::getAutounloadEnabled() && !sSystemSleep
) { 
6385         clock_interval_to_deadline(sConsiderUnloadDelay
, 
6386             1000 * 1000 * 1000, &when
); 
6388         OSKextLog(/* kext */ NULL
, 
6389             kOSKextLogProgressLevel 
| 
6391             "%scheduling %sscan for unused kexts in %lu seconds.", 
6392             sConsiderUnloadsPending 
? "Res" : "S", 
6393             sConsiderUnloadsCalled 
? "" : "initial ", 
6394             (unsigned long)sConsiderUnloadDelay
); 
6396         sConsiderUnloadsPending 
= true; 
6397         thread_call_enter_delayed(sUnloadCallout
, when
); 
6401    /* The kxld context should be reused throughout boot.  We mark the end of 
6402     * period as the first time considerUnloads() is called, and we destroy 
6403     * the first kxld context in that function.  Afterwards, it will be 
6404     * destroyed in flushNonloadedKexts. 
6406     if (!sConsiderUnloadsCalled
) { 
6407         sConsiderUnloadsCalled 
= true; 
6408         OSKext::considerDestroyingLinkContext(); 
6411     IORecursiveLockUnlock(sKextInnerLock
); 
6415 /********************************************************************* 
6416 * Do not call any function that takes sKextLock here! 
6417 *********************************************************************/ 
6420 IOReturn 
OSKextSystemSleepOrWake(UInt32 messageType
) 
6422     IORecursiveLockLock(sKextInnerLock
); 
6424    /* If the system is going to sleep, cancel the reaper thread timer, 
6425     * and note that we're in a sleep state in case it just fired but hasn't 
6426     * taken the lock yet. If we are coming back from sleep, just 
6427     * clear the sleep flag; IOService's normal operation will cause 
6428     * unloads to be considered soon enough. 
6430     if (messageType 
== kIOMessageSystemWillSleep
) { 
6431         if (sUnloadCallout
) { 
6432             thread_call_cancel(sUnloadCallout
); 
6434         sSystemSleep 
= true; 
6435         AbsoluteTime_to_scalar(&sLastWakeTime
) = 0; 
6436     } else if (messageType 
== kIOMessageSystemHasPoweredOn
) { 
6437         sSystemSleep 
= false; 
6438         clock_get_uptime(&sLastWakeTime
); 
6440     IORecursiveLockUnlock(sKextInnerLock
); 
6442     return kIOReturnSuccess
; 
6449 #pragma mark Prelinked Kernel 
6451 /********************************************************************* 
6452 * Do not access sConsiderUnloads... variables other than 
6453 * sConsiderUnloadsExecuted in this function. They are guarded by a 
6455 *********************************************************************/ 
6458 OSKext::considerRebuildOfPrelinkedKernel(void) 
6460     static bool     requestedPrelink        
= false; 
6461     OSReturn        checkResult             
= kOSReturnError
; 
6462     OSDictionary 
*  prelinkRequest          
= NULL
;  // must release 
6463     OSCollectionIterator 
* kextIterator     
= NULL
;  // must release 
6464     const OSSymbol 
* thisID                 
= NULL
;  // do not release 
6465     bool            doRebuild               
= false; 
6466     AbsoluteTime    my_abstime
; 
6470     /* Only one auto rebuild per boot and only on boot from prelinked kernel */ 
6471     if (requestedPrelink 
|| !sPrelinkBoot
) { 
6475     /* no direct return from this point */ 
6476     IORecursiveLockLock(sKextLock
); 
6478     /* We need to wait for kextd to get up and running with unloads already done 
6479      * and any new startup kexts loaded.    
6481     if (!sConsiderUnloadsExecuted 
|| 
6482         !sDeferredLoadSucceeded
) { 
6486     /* we really only care about boot / system start up related kexts so bail  
6487      * if we're here after REBUILD_MAX_TIME. 
6489     if (!_OSKextInPrelinkRebuildWindow()) { 
6490         OSKextLog(/* kext */ NULL
, 
6491                   kOSKextLogArchiveFlag
, 
6492                   "%s prebuild rebuild has expired", 
6494         requestedPrelink 
= true; 
6498     /* we do not want to trigger a rebuild if we get here too close to waking 
6499      * up.  (see radar 10233768) 
6501     IORecursiveLockLock(sKextInnerLock
); 
6503     clock_get_uptime(&my_abstime
); 
6504     delta_secs 
= MINIMUM_WAKEUP_SECONDS 
+ 1; 
6505     if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) { 
6506         SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
); 
6507         absolutetime_to_nanoseconds(my_abstime
, &my_ns
); 
6508         delta_secs 
= (SInt32
)(my_ns 
/ NSEC_PER_SEC
); 
6510     IORecursiveLockUnlock(sKextInnerLock
); 
6512     if (delta_secs 
< MINIMUM_WAKEUP_SECONDS
) { 
6513         /* too close to time of last wake from sleep */ 
6516     requestedPrelink 
= true; 
6518     /* Now it's time to see if we have a reason to rebuild.  We may have done  
6519      * some loads and unloads but the kernel cache didn't actually change. 
6520      * We will rebuild if any kext is not marked prelinked AND is not in our 
6521      * list of prelinked kexts that got unloaded.  (see radar 9055303) 
6523     kextIterator 
= OSCollectionIterator::withCollection(sKextsByID
); 
6524     if (!kextIterator
) { 
6528     while ((thisID 
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) { 
6529         OSKext 
*    thisKext
;  // do not release 
6531         thisKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
)); 
6532         if (!thisKext 
|| thisKext
->isPrelinked() || thisKext
->isKernel()) { 
6536         if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) { 
6539         /* kext is loaded and was not in current kernel cache so let's rebuild 
6542         OSKextLog(/* kext */ NULL
, 
6543                   kOSKextLogArchiveFlag
, 
6544                   "considerRebuildOfPrelinkedKernel %s triggered rebuild", 
6545                   thisKext
->bundleID
->getCStringNoCopy()); 
6548     sUnloadedPrelinkedKexts
->flushCollection(); 
6554     checkResult 
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
, 
6556     if (checkResult 
!= kOSReturnSuccess
) { 
6560     if (!sKernelRequests
->setObject(prelinkRequest
)) { 
6564     OSKext::pingKextd(); 
6567     IORecursiveLockUnlock(sKextLock
); 
6568     OSSafeRelease(prelinkRequest
); 
6569     OSSafeRelease(kextIterator
); 
6575 #pragma mark Dependencies 
6577 /********************************************************************* 
6578 *********************************************************************/ 
6580 OSKext::resolveDependencies( 
6581     OSArray 
* loopStack
) 
6583     bool                   result                   
= false; 
6584     OSArray              
* localLoopStack           
= NULL
;   // must release 
6585     bool                   addedToLoopStack         
= false; 
6586     OSDictionary         
* libraries                
= NULL
;   // do not release 
6587     OSCollectionIterator 
* libraryIterator          
= NULL
;   // must release 
6588     OSString             
* libraryID                
= NULL
;   // do not release 
6589     OSString             
* infoString               
= NULL
;   // do not release 
6590     OSString             
* readableString           
= NULL
;   // do not release 
6591     OSKext               
* libraryKext              
= NULL
;   // do not release 
6592     bool                   hasRawKernelDependency   
= false; 
6593     bool                   hasKernelDependency      
= false; 
6594     bool                   hasKPIDependency         
= false; 
6595     bool                   hasPrivateKPIDependency  
= false; 
6598    /* A kernel component will automatically have this flag set, 
6599     * and a loaded kext should also have it set (as should all its 
6600     * loaded dependencies). 
6602     if (flags
.hasAllDependencies
) { 
6607    /* Check for loops in the dependency graph. 
6610         if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) { 
6612                 kOSKextLogErrorLevel 
| 
6613                 kOSKextLogDependenciesFlag
, 
6614                 "Kext %s has a dependency loop; can't resolve dependencies.", 
6615                 getIdentifierCString()); 
6620             kOSKextLogStepLevel 
| 
6621             kOSKextLogDependenciesFlag
, 
6622             "Kext %s resolving dependencies.", 
6623             getIdentifierCString()); 
6625         loopStack 
= OSArray::withCapacity(6);  // any small capacity will do 
6628                 kOSKextLogErrorLevel 
| 
6629                 kOSKextLogDependenciesFlag
, 
6630                 "Kext %s can't create bookkeeping stack to resolve dependencies.", 
6631                 getIdentifierCString()); 
6634         localLoopStack 
= loopStack
; 
6636     if (!loopStack
->setObject(this)) { 
6638             kOSKextLogErrorLevel 
| 
6639             kOSKextLogDependenciesFlag
, 
6640             "Kext %s - internal error resolving dependencies.", 
6641             getIdentifierCString()); 
6644     addedToLoopStack 
= true; 
6646    /* Purge any existing kexts in the dependency list and start over. 
6648     flushDependencies(); 
6651             kOSKextLogErrorLevel 
| 
6652             kOSKextLogDependenciesFlag
, 
6653             "Kext %s - internal error resolving dependencies.", 
6654             getIdentifierCString()); 
6657     libraries 
= OSDynamicCast(OSDictionary
, 
6658         getPropertyForHostArch(kOSBundleLibrariesKey
)); 
6659     if (libraries 
== NULL 
|| libraries
->getCount() == 0) { 
6661             kOSKextLogErrorLevel 
| 
6662             kOSKextLogValidationFlag 
| kOSKextLogDependenciesFlag
, 
6663             "Kext %s - can't resolve dependencies; %s missing/invalid type.", 
6664             getIdentifierCString(), kOSBundleLibrariesKey
); 
6668    /* Make a new array to hold the dependencies (flush freed the old one). 
6670     dependencies 
= OSArray::withCapacity(libraries
->getCount()); 
6671     if (!dependencies
) { 
6673             kOSKextLogErrorLevel 
| 
6674             kOSKextLogDependenciesFlag
, 
6675             "Kext %s - can't allocate dependencies array.", 
6676             getIdentifierCString()); 
6680     // xxx - compat: We used to add an implicit dependency on kernel 6.0 
6681     // xxx - compat: if none were declared. 
6683     libraryIterator 
= OSCollectionIterator::withCollection(libraries
); 
6684     if (!libraryIterator
) { 
6686             kOSKextLogErrorLevel 
| 
6687             kOSKextLogDependenciesFlag
, 
6688             "Kext %s - can't allocate dependencies iterator.", 
6689             getIdentifierCString()); 
6693     while ((libraryID 
= OSDynamicCast(OSString
, 
6694            libraryIterator
->getNextObject()))) { 
6696        const char * library_id 
= libraryID
->getCStringNoCopy(); 
6698         OSString 
* libraryVersion 
= OSDynamicCast(OSString
, 
6699             libraries
->getObject(libraryID
)); 
6700         if (libraryVersion 
== NULL
) { 
6702                 kOSKextLogErrorLevel 
| 
6703                 kOSKextLogValidationFlag 
| kOSKextLogDependenciesFlag
, 
6704                 "Kext %s - illegal type in OSBundleLibraries.", 
6705                 getIdentifierCString()); 
6709         OSKextVersion libraryVers 
= 
6710             OSKextParseVersionString(libraryVersion
->getCStringNoCopy()); 
6711         if (libraryVers 
== -1) { 
6713                 kOSKextLogErrorLevel 
| 
6714                 kOSKextLogValidationFlag 
| kOSKextLogDependenciesFlag
, 
6715                 "Kext %s - invalid library version %s.", 
6716                 getIdentifierCString(), 
6717                 libraryVersion
->getCStringNoCopy()); 
6721         libraryKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
)); 
6722         if (libraryKext 
== NULL
) { 
6724                 kOSKextLogErrorLevel 
| 
6725                 kOSKextLogDependenciesFlag
, 
6726                 "Kext %s - library kext %s not found.", 
6727                 getIdentifierCString(), library_id
); 
6731         if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) { 
6733                 kOSKextLogErrorLevel 
| 
6734                 kOSKextLogDependenciesFlag
, 
6735                 "Kext %s - library kext %s not compatible " 
6736                 "with requested version %s.", 
6737                 getIdentifierCString(), library_id
, 
6738                 libraryVersion
->getCStringNoCopy()); 
6742        /* If a nonprelinked library somehow got into the mix for a 
6743         * prelinked kext, at any point in the chain, we must fail 
6744         * because the prelinked relocs for the library will be all wrong. 
6746         if (this->isPrelinked() && 
6747             libraryKext
->declaresExecutable() && 
6748             !libraryKext
->isPrelinked()) { 
6751                 kOSKextLogErrorLevel 
| 
6752                 kOSKextLogDependenciesFlag
, 
6753                 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.", 
6754                 getIdentifierCString(), library_id
, 
6755                 libraryVersion
->getCStringNoCopy()); 
6759         if (!libraryKext
->resolveDependencies(loopStack
)) { 
6763        /* Add the library directly only if it has an executable to link. 
6764         * Otherwise it's just used to collect other dependencies, so put 
6765         * *its* dependencies on the list for this kext. 
6767         // xxx - We are losing info here; would like to make fake entries or 
6768         // xxx - keep these in the dependency graph for loaded kexts. 
6769         // xxx - I really want to make kernel components not a special case! 
6770         if (libraryKext
->declaresExecutable() || 
6771             libraryKext
->isInterface()) { 
6773             if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) { 
6774                 dependencies
->setObject(libraryKext
); 
6777                     kOSKextLogDetailLevel 
| 
6778                     kOSKextLogDependenciesFlag
, 
6779                     "Kext %s added dependency %s.", 
6780                     getIdentifierCString(), 
6781                     libraryKext
->getIdentifierCString()); 
6784             int       numLibDependencies  
= libraryKext
->getNumDependencies(); 
6785             OSArray 
* libraryDependencies 
= libraryKext
->getDependencies(); 
6788             if (numLibDependencies
) { 
6789                 // xxx - this msg level should be 1 lower than the per-kext one 
6791                     kOSKextLogDetailLevel 
| 
6792                     kOSKextLogDependenciesFlag
, 
6793                     "Kext %s pulling %d dependencies from codeless library %s.", 
6794                     getIdentifierCString(), 
6796                     libraryKext
->getIdentifierCString()); 
6798             for (index 
= 0; index 
< numLibDependencies
; index
++) { 
6799                 OSKext 
* thisLibDependency 
= OSDynamicCast(OSKext
, 
6800                     libraryDependencies
->getObject(index
)); 
6801                 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) { 
6802                     dependencies
->setObject(thisLibDependency
); 
6804                         kOSKextLogDetailLevel 
| 
6805                         kOSKextLogDependenciesFlag
, 
6806                         "Kext %s added dependency %s from codeless library %s.", 
6807                         getIdentifierCString(), 
6808                         thisLibDependency
->getIdentifierCString(), 
6809                         libraryKext
->getIdentifierCString()); 
6814         if ((strlen(library_id
) == strlen(KERNEL_LIB
)) && 
6815             0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) { 
6817             hasRawKernelDependency 
= true; 
6818         } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) { 
6819             hasKernelDependency 
= true; 
6820         } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) { 
6821             hasKPIDependency 
= true; 
6822             if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) { 
6823                 hasPrivateKPIDependency 
= true; 
6828     if (hasRawKernelDependency
) { 
6830             kOSKextLogErrorLevel 
| 
6831             kOSKextLogValidationFlag 
| kOSKextLogDependenciesFlag
, 
6832             "Error - kext %s declares a dependency on %s, which is not permitted.", 
6833             getIdentifierCString(), KERNEL_LIB
); 
6837     if (hasKernelDependency
) { 
6839             kOSKextLogErrorLevel 
| 
6840             kOSKextLogValidationFlag 
| kOSKextLogDependenciesFlag
, 
6841             "Error - kext %s declares %s dependencies. " 
6842             "Only %s* dependencies are supported for 64-bit kexts.", 
6843             getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
); 
6846     if (!hasKPIDependency
) { 
6848             kOSKextLogWarningLevel 
| 
6849             kOSKextLogDependenciesFlag
, 
6850             "Warning - kext %s declares no %s* dependencies. " 
6851             "If it uses any KPIs, the link may fail with undefined symbols.", 
6852             getIdentifierCString(), KPI_LIB_PREFIX
); 
6854 #else /* __LP64__ */ 
6855     // xxx - will change to flatly disallow "kernel" dependencies at some point 
6856     // xxx - is it invalid to do both "com.apple.kernel" and any 
6857     // xxx - "com.apple.kernel.*"? 
6859     if (hasKernelDependency 
&& hasKPIDependency
) { 
6861             kOSKextLogWarningLevel 
| 
6862             kOSKextLogDependenciesFlag
, 
6863             "Warning - kext %s has immediate dependencies on both " 
6864             "%s* and %s* components; use only one style.", 
6865             getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
); 
6868     if (!hasKernelDependency 
&& !hasKPIDependency
) { 
6869         // xxx - do we want to use validation flag for these too? 
6871             kOSKextLogWarningLevel 
| 
6872             kOSKextLogDependenciesFlag
, 
6873             "Warning - %s declares no kernel dependencies; using %s.", 
6874             getIdentifierCString(), KERNEL6_LIB
); 
6875         OSKext 
* kernelKext 
= OSDynamicCast(OSKext
, 
6876             sKextsByID
->getObject(KERNEL6_LIB
)); 
6878             dependencies
->setObject(kernelKext
); 
6881                 kOSKextLogErrorLevel 
| 
6882                 kOSKextLogDependenciesFlag
, 
6883                 "Error - Library %s not found for %s.", 
6884                 KERNEL6_LIB
, getIdentifierCString()); 
6888    /* If the kext doesn't have a raw kernel or KPI dependency, then add all of 
6889     * its indirect dependencies to simulate old-style linking.  XXX - Should 
6890     * check for duplicates. 
6892     if (!hasKPIDependency
) { 
6895         flags
.hasBleedthrough 
= true; 
6897         count 
= getNumDependencies(); 
6899        /* We add to the dependencies array in this loop, but do not iterate 
6900         * past its original count. 
6902         for (i 
= 0; i 
< count
; i
++) { 
6903             OSKext 
* dependencyKext 
= OSDynamicCast(OSKext
, 
6904                 dependencies
->getObject(i
)); 
6905             dependencyKext
->addBleedthroughDependencies(dependencies
); 
6908 #endif /* __LP64__ */ 
6910     if (hasPrivateKPIDependency
) { 
6911         bool hasApplePrefix 
= false; 
6912         bool infoCopyrightIsValid 
= false; 
6913         bool readableCopyrightIsValid 
= false; 
6915         hasApplePrefix 
= STRING_HAS_PREFIX(getIdentifierCString(),  
6918         infoString 
= OSDynamicCast(OSString
,   
6919             getPropertyForHostArch("CFBundleGetInfoString")); 
6921             infoCopyrightIsValid 
=  
6922                 kxld_validate_copyright_string(infoString
->getCStringNoCopy()); 
6925         readableString 
= OSDynamicCast(OSString
, 
6926             getPropertyForHostArch("NSHumanReadableCopyright")); 
6927         if (readableString
) { 
6928             readableCopyrightIsValid 
=  
6929                 kxld_validate_copyright_string(readableString
->getCStringNoCopy()); 
6932         if (!hasApplePrefix 
|| (!infoCopyrightIsValid 
&& !readableCopyrightIsValid
)) { 
6934                 kOSKextLogErrorLevel 
| 
6935                 kOSKextLogDependenciesFlag
, 
6936                 "Error - kext %s declares a dependency on %s. " 
6937                   "Only Apple kexts may declare a dependency on %s.", 
6938                   getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
); 
6944     flags
.hasAllDependencies 
= 1; 
6948     if (addedToLoopStack
) { 
6949         count 
= loopStack
->getCount(); 
6950         if (count 
> 0 && (this == loopStack
->getObject(count 
- 1))) { 
6951             loopStack
->removeObject(count 
- 1);             
6954                 kOSKextLogErrorLevel 
| 
6955                 kOSKextLogDependenciesFlag
, 
6956                 "Kext %s - internal error resolving dependencies.", 
6957                 getIdentifierCString()); 
6961     if (result 
&& localLoopStack
) { 
6963             kOSKextLogStepLevel 
| 
6964             kOSKextLogDependenciesFlag
, 
6965             "Kext %s successfully resolved dependencies.", 
6966             getIdentifierCString()); 
6969     OSSafeRelease(localLoopStack
); 
6970     OSSafeRelease(libraryIterator
); 
6975 /********************************************************************* 
6976 *********************************************************************/ 
6978 OSKext::addBleedthroughDependencies(OSArray 
* anArray
) 
6980     bool result 
= false; 
6981     unsigned int dependencyIndex
, dependencyCount
; 
6983     dependencyCount 
= getNumDependencies(); 
6985     for (dependencyIndex 
= 0; 
6986          dependencyIndex 
< dependencyCount
; 
6987          dependencyIndex
++) { 
6989         OSKext 
* dependency 
= OSDynamicCast(OSKext
, 
6990             dependencies
->getObject(dependencyIndex
)); 
6993                 kOSKextLogErrorLevel 
| 
6994                 kOSKextLogDependenciesFlag
, 
6995                 "Kext %s - internal error propagating compatibility dependencies.", 
6996                 getIdentifierCString()); 
6999         if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) { 
7000             anArray
->setObject(dependency
); 
7002         dependency
->addBleedthroughDependencies(anArray
); 
7011 /********************************************************************* 
7012 *********************************************************************/ 
7014 OSKext::flushDependencies(bool forceFlag
) 
7016     bool result 
= false; 
7018    /* Only clear the dependencies if the kext isn't loaded; 
7019     * we need the info for loaded kexts to track references. 
7021     if (!isLoaded() || forceFlag
) { 
7023             // xxx - check level 
7025                 kOSKextLogProgressLevel 
| 
7026                 kOSKextLogDependenciesFlag
, 
7027                 "Kext %s flushing dependencies.", 
7028                 getIdentifierCString()); 
7029             OSSafeReleaseNULL(dependencies
); 
7032         if (!isKernelComponent()) { 
7033             flags
.hasAllDependencies 
= 0; 
7041 /********************************************************************* 
7042 *********************************************************************/ 
7044 OSKext::getNumDependencies(void) 
7046     if (!dependencies
) { 
7049     return dependencies
->getCount(); 
7052 /********************************************************************* 
7053 *********************************************************************/ 
7055 OSKext::getDependencies(void) 
7057     return dependencies
; 
7061 #pragma mark OSMetaClass Support 
7063 /********************************************************************* 
7064 *********************************************************************/ 
7067     OSMetaClass 
* aClass
, 
7068     uint32_t      numClasses
) 
7070     OSReturn result 
= kOSMetaClassNoInsKModSet
; 
7073         metaClasses 
= OSSet::withCapacity(numClasses
); 
7079     if (metaClasses
->containsObject(aClass
)) { 
7081             kOSKextLogWarningLevel 
| 
7083             "Notice - kext %s has already registered class %s.", 
7084             getIdentifierCString(), 
7085             aClass
->getClassName()); 
7086         result 
= kOSReturnSuccess
; 
7090     if (!metaClasses
->setObject(aClass
)) { 
7094             kOSKextLogDetailLevel 
| 
7096             "Kext %s registered class %s.", 
7097             getIdentifierCString(), 
7098             aClass
->getClassName()); 
7101     if (!flags
.autounloadEnabled
) { 
7102         const OSMetaClass 
* metaScan  
= NULL
;  // do not release 
7104         for (metaScan 
= aClass
; metaScan
; metaScan 
= metaScan
->getSuperClass()) { 
7105             if (metaScan 
== OSTypeID(IOService
)) { 
7108                     kOSKextLogProgressLevel 
| 
7110                     "Kext %s has IOService subclass %s; enabling autounload.", 
7111                     getIdentifierCString(), 
7112                     aClass
->getClassName()); 
7114                 flags
.autounloadEnabled 
= 1; 
7120     notifyAddClassObservers(this, aClass
, flags
); 
7122     result 
= kOSReturnSuccess
; 
7125     if (result 
!= kOSReturnSuccess
) { 
7127             kOSKextLogErrorLevel 
| 
7129             "Kext %s failed to register class %s.", 
7130             getIdentifierCString(), 
7131             aClass
->getClassName()); 
7137 /********************************************************************* 
7138 *********************************************************************/ 
7140 OSKext::removeClass( 
7141     OSMetaClass 
* aClass
) 
7143     OSReturn result 
= kOSMetaClassNoKModSet
; 
7149     if (!metaClasses
->containsObject(aClass
)) { 
7151             kOSKextLogWarningLevel 
| 
7153             "Notice - kext %s asked to unregister unknown class %s.", 
7154             getIdentifierCString(), 
7155             aClass
->getClassName()); 
7156         result 
= kOSReturnSuccess
; 
7161         kOSKextLogDetailLevel 
| 
7163         "Kext %s unregistering class %s.", 
7164         getIdentifierCString(), 
7165         aClass
->getClassName()); 
7167     metaClasses
->removeObject(aClass
); 
7169     notifyRemoveClassObservers(this, aClass
, flags
); 
7171     result 
= kOSReturnSuccess
; 
7174     if (result 
!= kOSReturnSuccess
) { 
7176             kOSKextLogErrorLevel 
| 
7178             "Failed to unregister kext %s class %s.", 
7179             getIdentifierCString(), 
7180             aClass
->getClassName()); 
7185 /********************************************************************* 
7186 *********************************************************************/ 
7188 OSKext::getMetaClasses(void) 
7193 /********************************************************************* 
7194 *********************************************************************/ 
7196 OSKext::hasOSMetaClassInstances(void) 
7198     bool                   result        
= false; 
7199     OSCollectionIterator 
* classIterator 
= NULL
;  // must release 
7200     OSMetaClass          
* checkClass    
= NULL
;  // do not release 
7206     classIterator 
= OSCollectionIterator::withCollection(metaClasses
); 
7207     if (!classIterator
) { 
7208         // xxx - log alloc failure? 
7211     while ((checkClass 
= (OSMetaClass 
*)classIterator
->getNextObject())) { 
7212         if (checkClass
->getInstanceCount()) { 
7220     OSSafeRelease(classIterator
); 
7224 /********************************************************************* 
7225 *********************************************************************/ 
7228 OSKext::reportOSMetaClassInstances( 
7229     const char     * kextIdentifier
, 
7230     OSKextLogSpec    msgLogSpec
) 
7232     OSKext 
* theKext 
= NULL
; // must release 
7234     theKext 
= OSKext::lookupKextWithIdentifier(kextIdentifier
); 
7239     theKext
->reportOSMetaClassInstances(msgLogSpec
); 
7241     OSSafeRelease(theKext
); 
7245 /********************************************************************* 
7246 *********************************************************************/ 
7248 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
) 
7250     OSCollectionIterator 
* classIterator 
= NULL
;  // must release 
7251     OSMetaClass          
* checkClass    
= NULL
;  // do not release 
7257     classIterator 
= OSCollectionIterator::withCollection(metaClasses
); 
7258     if (!classIterator
) { 
7261     while ((checkClass 
= (OSMetaClass 
*)classIterator
->getNextObject())) { 
7262         if (checkClass
->getInstanceCount()) { 
7265                 "    Kext %s class %s has %d instance%s.", 
7266                 getIdentifierCString(), 
7267                 checkClass
->getClassName(), 
7268                 checkClass
->getInstanceCount(), 
7269                 checkClass
->getInstanceCount() == 1 ? "" : "s"); 
7274     OSSafeRelease(classIterator
); 
7279 #pragma mark User-Space Requests 
7281 /********************************************************************* 
7282 * XXX - this function is a big ugly mess 
7283 *********************************************************************/ 
7286 OSKext::handleRequest( 
7287     host_priv_t     hostPriv
, 
7288     OSKextLogSpec   clientLogFilter
, 
7289     char          * requestBuffer
, 
7290     uint32_t        requestLength
, 
7291     char         ** responseOut
, 
7292     uint32_t      * responseLengthOut
, 
7294     uint32_t      * logInfoLengthOut
) 
7296     OSReturn       result             
= kOSReturnError
; 
7297     kern_return_t  kmem_result        
= KERN_FAILURE
; 
7299     char         * response           
= NULL
;  // returned by reference 
7300     uint32_t       responseLength     
= 0; 
7302     OSObject     
* parsedXML          
= NULL
;  // must release 
7303     OSDictionary 
* requestDict        
= NULL
;  // do not release 
7304     OSString     
* errorString        
= NULL
;  // must release 
7306     OSData       
* responseData       
= NULL
;  // must release 
7307     OSObject     
* responseObject     
= NULL
;  // must release 
7309     OSSerialize  
* serializer         
= NULL
;  // must release 
7311     OSArray      
* logInfoArray       
= NULL
;  // must release 
7313     OSString     
* predicate          
= NULL
;  // do not release 
7314     OSString     
* kextIdentifier     
= NULL
;  // do not release 
7315     OSArray      
* kextIdentifiers    
= NULL
;  // do not release 
7316     OSKext       
* theKext            
= NULL
;  // do not release 
7317     OSBoolean    
* boolArg            
= NULL
;  // do not release 
7319     bool           hideTheSlide       
= false;  
7321     IORecursiveLockLock(sKextLock
); 
7324         *responseOut 
= NULL
; 
7325         *responseLengthOut 
= 0; 
7329         *logInfoLengthOut 
= 0; 
7332     OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut 
? true : false); 
7334    /* XML must be nul-terminated. 
7336     if (requestBuffer
[requestLength 
- 1] != '\0') { 
7337         OSKextLog(/* kext */ NULL
, 
7338             kOSKextLogErrorLevel 
| 
7340             "Invalid request from user space (not nul-terminated)."); 
7341         result 
= kOSKextReturnBadData
; 
7344     parsedXML 
= OSUnserializeXML((const char *)requestBuffer
, &errorString
); 
7346         requestDict 
= OSDynamicCast(OSDictionary
, parsedXML
); 
7349         const char * errorCString 
= "(unknown error)"; 
7351         if (errorString 
&& errorString
->getCStringNoCopy()) { 
7352             errorCString 
= errorString
->getCStringNoCopy(); 
7353         } else if (parsedXML
) { 
7354             errorCString 
= "not a dictionary"; 
7356         OSKextLog(/* kext */ NULL
, 
7357             kOSKextLogErrorLevel 
| 
7359             "Error unserializing request from user space: %s.", 
7361         result 
= kOSKextReturnSerialization
; 
7365     predicate 
= _OSKextGetRequestPredicate(requestDict
); 
7367         OSKextLog(/* kext */ NULL
, 
7368             kOSKextLogErrorLevel 
| 
7370             "Recieved kext request from user space with no predicate."); 
7371         result 
= kOSKextReturnInvalidArgument
; 
7375     OSKextLog(/* kext */ NULL
, 
7376         kOSKextLogDebugLevel 
| 
7378         "Received '%s' request from user space.", 
7379         predicate
->getCStringNoCopy()); 
7381     result 
= kOSKextReturnNotPrivileged
; 
7382     if (hostPriv 
== HOST_PRIV_NULL
) { 
7384             hideTheSlide 
= true; 
7386             /* must be root to use these kext requests */ 
7387             if (predicate
->isEqualTo(kKextRequestPredicateGetKernelLoadAddress
) ) { 
7388                 OSKextLog(/* kext */ NULL
, 
7389                           kOSKextLogErrorLevel 
| 
7391                           "Access Failure - must be root user."); 
7397    /* Get common args in anticipation of use. 
7399     kextIdentifier 
= OSDynamicCast(OSString
, _OSKextGetRequestArgument( 
7400         requestDict
, kKextRequestArgumentBundleIdentifierKey
)); 
7401     kextIdentifiers 
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument( 
7402         requestDict
, kKextRequestArgumentBundleIdentifierKey
)); 
7403     if (kextIdentifier
) { 
7404         theKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
)); 
7406     boolArg 
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument( 
7407         requestDict
, kKextRequestArgumentValueKey
)); 
7409     result 
= kOSKextReturnInvalidArgument
; 
7411     if (predicate
->isEqualTo(kKextRequestPredicateStart
)) { 
7412         if (!kextIdentifier
) { 
7413             OSKextLog(/* kext */ NULL
, 
7414                 kOSKextLogErrorLevel 
| 
7416                 "Invalid arguments to kext start request."); 
7417         } else if (!theKext
) { 
7418             OSKextLog(/* kext */ NULL
, 
7419                 kOSKextLogErrorLevel 
| 
7421                 "Kext %s not found for start request.", 
7422                 kextIdentifier
->getCStringNoCopy()); 
7423             result 
= kOSKextReturnNotFound
; 
7425             result 
= theKext
->start(); 
7428     } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) { 
7429         if (!kextIdentifier
) { 
7430             OSKextLog(/* kext */ NULL
, 
7431                 kOSKextLogErrorLevel 
| 
7433                 "Invalid arguments to kext stop request."); 
7434         } else if (!theKext
) { 
7435             OSKextLog(/* kext */ NULL
, 
7436                 kOSKextLogErrorLevel 
| 
7438                 "Kext %s not found for stop request.", 
7439                 kextIdentifier
->getCStringNoCopy()); 
7440             result 
= kOSKextReturnNotFound
; 
7442             result 
= theKext
->stop(); 
7445     } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) { 
7446         if (!kextIdentifier
) { 
7447             OSKextLog(/* kext */ NULL
, 
7448                 kOSKextLogErrorLevel 
| 
7450                 "Invalid arguments to kext unload request."); 
7451         } else if (!theKext
) { 
7452             OSKextLog(/* kext */ NULL
, 
7453                 kOSKextLogErrorLevel 
| 
7455                 "Kext %s not found for unload request.", 
7456                 kextIdentifier
->getCStringNoCopy()); 
7457             result 
= kOSKextReturnNotFound
; 
7459             OSBoolean 
* terminateFlag 
= OSDynamicCast(OSBoolean
, 
7460                 _OSKextGetRequestArgument(requestDict
, 
7461                     kKextRequestArgumentTerminateIOServicesKey
)); 
7462             result 
= OSKext::removeKext(theKext
, terminateFlag 
== kOSBooleanTrue
); 
7465     } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) { 
7466         result 
= OSKext::dispatchResource(requestDict
); 
7468     } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) { 
7469         OSBoolean    
* delayAutounloadBool 
= NULL
; 
7470         OSObject     
* infoKeysRaw         
= NULL
; 
7471         OSArray      
* infoKeys            
= NULL
; 
7472         uint32_t       infoKeysCount       
= 0; 
7474         delayAutounloadBool 
= OSDynamicCast(OSBoolean
, 
7475             _OSKextGetRequestArgument(requestDict
, 
7476                 kKextRequestArgumentDelayAutounloadKey
)); 
7478        /* If asked to delay autounload, reset the timer if it's currently set. 
7479         * (That is, don't schedule an unload if one isn't already pending. 
7481         if (delayAutounloadBool 
== kOSBooleanTrue
) { 
7482             OSKext::considerUnloads(/* rescheduleOnly? */ true); 
7485         infoKeysRaw 
= _OSKextGetRequestArgument(requestDict
, 
7486                 kKextRequestArgumentInfoKeysKey
); 
7487         infoKeys 
= OSDynamicCast(OSArray
, infoKeysRaw
); 
7488         if (infoKeysRaw 
&& !infoKeys
) { 
7489             OSKextLog(/* kext */ NULL
, 
7490                 kOSKextLogErrorLevel 
| 
7492                 "Invalid arguments to kext info request."); 
7497             infoKeysCount 
= infoKeys
->getCount(); 
7498             for (uint32_t i 
= 0; i 
< infoKeysCount
; i
++) { 
7499                 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) { 
7500                     OSKextLog(/* kext */ NULL
, 
7501                         kOSKextLogErrorLevel 
| 
7503                         "Invalid arguments to kext info request."); 
7509         responseObject 
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
); 
7510         if (!responseObject
) { 
7511             result 
= kOSKextReturnInternalError
; 
7513             OSKextLog(/* kext */ NULL
, 
7514                 kOSKextLogDebugLevel 
| 
7516                 "Returning loaded kext info."); 
7517             result 
= kOSReturnSuccess
; 
7520     } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelLoadAddress
)) { 
7521         OSNumber 
* addressNum 
= NULL
;  // released as responseObject 
7522         kernel_segment_command_t 
* textseg 
= getsegbyname("__TEXT"); 
7525             OSKextLog(/* kext */ NULL
, 
7526                 kOSKextLogErrorLevel 
| 
7527                 kOSKextLogGeneralFlag 
| kOSKextLogIPCFlag
, 
7528                 "Can't find text segment for kernel load address."); 
7529             result 
= kOSReturnError
; 
7533         OSKextLog(/* kext */ NULL
, 
7534             kOSKextLogDebugLevel 
| 
7536             "Returning kernel load address 0x%llx.", 
7537             (unsigned long long) textseg
->vmaddr 
); 
7539         addressNum 
= OSNumber::withNumber((long long unsigned int)textseg
->vmaddr
, 
7540             8 * sizeof(long long unsigned int)); 
7541         responseObject 
= addressNum
; 
7542         result 
= kOSReturnSuccess
; 
7544     } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) { 
7546        /* Hand the current sKernelRequests array to the caller 
7547         * (who must release it), and make a new one. 
7549         responseObject 
= sKernelRequests
; 
7550         sKernelRequests 
= OSArray::withCapacity(0); 
7551         sPostedKextLoadIdentifiers
->flushCollection(); 
7552         OSKextLog(/* kext */ NULL
, 
7553             kOSKextLogDebugLevel 
| 
7555             "Returning kernel requests."); 
7556         result 
= kOSReturnSuccess
; 
7558     } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) { 
7560         /* Return the set of all requested bundle identifiers */ 
7561         responseObject 
= sAllKextLoadIdentifiers
; 
7562         responseObject
->retain(); 
7563         OSKextLog(/* kext */ NULL
, 
7564             kOSKextLogDebugLevel 
| 
7566             "Returning load requests."); 
7567         result 
= kOSReturnSuccess
; 
7571     * Now we have handle the request, or not. Gather up the response & logging 
7572     * info to ship to user space. 
7575    /* Note: Nothing in OSKext is supposed to retain requestDict, 
7576     * but you never know.... 
7578     if (requestDict
->getRetainCount() > 1) { 
7579         OSKextLog(/* kext */ NULL
, 
7580             kOSKextLogWarningLevel 
| 
7582             "Request from user space still retained by a kext; " 
7583             "probable memory leak."); 
7586     if (responseData 
&& responseObject
) { 
7587         OSKextLog(/* kext */ NULL
, 
7588             kOSKextLogErrorLevel 
| 
7590             "Mistakenly generated both data & plist responses to user request " 
7591             "(returning only data)."); 
7594     if (responseData 
&& responseData
->getLength() && responseOut
) { 
7596         response 
= (char *)responseData
->getBytesNoCopy(); 
7597         responseLength 
= responseData
->getLength(); 
7598     } else if (responseOut 
&& responseObject
) { 
7599         serializer 
= OSSerialize::withCapacity(0); 
7601             result 
= kOSKextReturnNoMemory
; 
7605         if (!responseObject
->serialize(serializer
)) { 
7606             OSKextLog(/* kext */ NULL
, 
7607                 kOSKextLogErrorLevel 
| 
7609                 "Failed to serialize response to request from user space."); 
7610             result 
= kOSKextReturnSerialization
; 
7614         response 
= (char *)serializer
->text(); 
7615         responseLength 
= serializer
->getLength(); 
7618     if (responseOut 
&& response
) { 
7621        /* This kmem_alloc sets the return value of the function. 
7623         kmem_result 
= kmem_alloc(kernel_map
, (vm_offset_t 
*)&buffer
, 
7625         if (kmem_result 
!= KERN_SUCCESS
) { 
7626             OSKextLog(/* kext */ NULL
, 
7627                 kOSKextLogErrorLevel 
| 
7629                 "Failed to copy response to request from user space."); 
7630             result 
= kmem_result
; 
7633             memcpy(buffer
, response
, responseLength
); 
7634             *responseOut 
= buffer
; 
7635             *responseLengthOut 
= responseLength
; 
7641    /* Gather up the collected log messages for user space. Any messages 
7642     * messages past this call will not make it up as log messages but 
7643     * will be in the system log. Note that we ignore the return of the 
7644     * serialize; it has no bearing on the operation at hand even if we 
7645     * fail to get the log messages. 
7647     logInfoArray 
= OSKext::clearUserSpaceLogFilter(); 
7649     if (logInfoArray 
&& logInfoOut 
&& logInfoLengthOut
) { 
7650         (void)OSKext::serializeLogInfo(logInfoArray
, 
7651             logInfoOut
, logInfoLengthOut
); 
7654     IORecursiveLockUnlock(sKextLock
); 
7656     OSSafeRelease(parsedXML
); 
7657     OSSafeRelease(errorString
); 
7658     OSSafeRelease(responseData
); 
7659     OSSafeRelease(responseObject
); 
7660     OSSafeRelease(serializer
); 
7661     OSSafeRelease(logInfoArray
); 
7666 /********************************************************************* 
7667 *********************************************************************/ 
7670 OSKext::copyLoadedKextInfo( 
7671     OSArray 
* kextIdentifiers
, 
7674     OSDictionary 
* result 
= NULL
; 
7675     OSDictionary 
* kextInfo 
= NULL
;  // must release 
7677     uint32_t       idCount 
= 0; 
7678     uint32_t       idIndex 
= 0; 
7680     IORecursiveLockLock(sKextLock
); 
7682    /* Empty list of bundle ids is equivalent to no list (get all). 
7684     if (kextIdentifiers 
&& !kextIdentifiers
->getCount()) { 
7685         kextIdentifiers 
= NULL
; 
7686     } else if (kextIdentifiers
) { 
7687         idCount 
= kextIdentifiers
->getCount(); 
7692     if (infoKeys 
&& !infoKeys
->getCount()) { 
7696     count 
= sLoadedKexts
->getCount(); 
7697     result 
= OSDictionary::withCapacity(count
); 
7701     for (i 
= 0; i 
< count
; i
++) { 
7702         OSKext   
* thisKext     
= NULL
;  // do not release 
7703         Boolean    includeThis  
= true; 
7706             kextInfo
->release(); 
7709         thisKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
7714        /* Skip current kext if we have a list of bundle IDs and 
7715         * it isn't in the list. 
7717         if (kextIdentifiers
) { 
7718             const OSString 
* thisKextID 
= thisKext
->getIdentifier(); 
7720             includeThis 
= false; 
7722             for (idIndex 
= 0; idIndex 
< idCount
; idIndex
++) { 
7723                 const OSString 
* thisRequestID 
= OSDynamicCast(OSString
, 
7724                     kextIdentifiers
->getObject(idIndex
)); 
7725                 if (thisKextID
->isEqualTo(thisRequestID
)) { 
7736         kextInfo 
= thisKext
->copyInfo(infoKeys
); 
7738             result
->setObject(thisKext
->getIdentifier(), kextInfo
); 
7743     IORecursiveLockUnlock(sKextLock
); 
7745     if (kextInfo
) kextInfo
->release(); 
7750 /********************************************************************* 
7751 * Any info that needs to do allocations must goto finish on alloc 
7752 * failure. Info that is just a lookup should just not set the object 
7753 * if the info does not exist. 
7754 *********************************************************************/ 
7755 #define _OSKextLoadInfoDictCapacity   (12) 
7758 OSKext::copyInfo(OSArray 
* infoKeys
) 
7760     OSDictionary         
* result                      
= NULL
; 
7761     bool                   success                     
= false; 
7762     OSData               
* headerData                  
= NULL
;  // must release 
7763     OSNumber             
* cpuTypeNumber               
= NULL
;  // must release 
7764     OSNumber             
* cpuSubtypeNumber            
= NULL
;  // must release 
7765     OSString             
* versionString               
= NULL
;  // do not release 
7766     uint32_t               executablePathCStringSize 
= 0; 
7767     char                 * executablePathCString       
= NULL
;  // must release 
7768     OSString             
* executablePathString        
= NULL
;  // must release 
7769     OSData               
* uuid                        
= NULL
;  // must release 
7770     OSNumber             
* scratchNumber               
= NULL
;  // must release 
7771     OSArray              
* dependencyLoadTags          
= NULL
;  // must release 
7772     OSCollectionIterator 
* metaClassIterator           
= NULL
;  // must release 
7773     OSArray              
* metaClassInfo               
= NULL
;  // must release 
7774     OSDictionary         
* metaClassDict               
= NULL
;  // must release 
7775     OSMetaClass          
* thisMetaClass               
= NULL
;  // do not release 
7776     OSString             
* metaClassName               
= NULL
;  // must release 
7777     OSString             
* superclassName              
= NULL
;  // must release 
7780     result 
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
); 
7786    /* Empty keys means no keys, but NULL is quicker to check. 
7788     if (infoKeys 
&& !infoKeys
->getCount()) { 
7792    /* Headers, CPU type, and CPU subtype. 
7795         _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) || 
7796         _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) || 
7797         _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) 
7800         if (linkedExecutable 
&& !isInterface()) { 
7802             kernel_mach_header_t 
*kext_mach_hdr 
= (kernel_mach_header_t 
*) 
7803                 linkedExecutable
->getBytesNoCopy(); 
7805             if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) { 
7806                 kernel_mach_header_t 
*  temp_kext_mach_hdr
; 
7807                 struct load_command 
*   lcp
; 
7809                 headerData 
= OSData::withBytes(kext_mach_hdr
, 
7810                     (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
)); 
7815                 // unslide any vmaddrs we return to userspace - 10726716 
7816                temp_kext_mach_hdr 
= (kernel_mach_header_t 
*) 
7817                     headerData
->getBytesNoCopy(); 
7818                 if (temp_kext_mach_hdr 
== NULL
) { 
7822                 lcp 
= (struct load_command 
*) (temp_kext_mach_hdr 
+ 1); 
7823                 for (i 
= 0; i 
< temp_kext_mach_hdr
->ncmds
; i
++) { 
7824                     if (lcp
->cmd 
== LC_SEGMENT_KERNEL
) { 
7825                         kernel_segment_command_t 
*  scp
; 
7827                         scp 
= (kernel_segment_command_t 
*) lcp
; 
7828                         // 10543468 - if we jettisoned __LINKEDIT clear size info 
7829                         if (flags
.jettisonLinkeditSeg
) { 
7830                             if (strncmp(scp
->segname
, SEG_LINKEDIT
, sizeof(scp
->segname
)) == 0) { 
7837                         OSKextLog(/* kext */ NULL
, 
7838                                   kOSKextLogErrorLevel 
| 
7839                                   kOSKextLogGeneralFlag
, 
7840                                   "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u", 
7841                                   __FUNCTION__
, scp
->segname
, scp
->vmaddr
,  
7842                                   VM_KERNEL_UNSLIDE(scp
->vmaddr
),  
7843                                   scp
->vmsize
, scp
->nsects
); 
7845                         scp
->vmaddr 
= VM_KERNEL_UNSLIDE(scp
->vmaddr
); 
7847                     lcp 
= (struct load_command 
*)((caddr_t
)lcp 
+ lcp
->cmdsize
); 
7849                 result
->setObject(kOSBundleMachOHeadersKey
, headerData
); 
7852             if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) { 
7853                 cpuTypeNumber 
= OSNumber::withNumber( 
7854                     (uint64_t) kext_mach_hdr
->cputype
, 
7855                     8 * sizeof(kext_mach_hdr
->cputype
)); 
7856                 if (!cpuTypeNumber
) { 
7859                 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
); 
7862             if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) { 
7863                 cpuSubtypeNumber 
= OSNumber::withNumber( 
7864                     (uint64_t) kext_mach_hdr
->cpusubtype
, 
7865                     8 * sizeof(kext_mach_hdr
->cpusubtype
)); 
7866                 if (!cpuSubtypeNumber
) { 
7869                 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
); 
7874    /* CFBundleIdentifier. We set this regardless because it's just stupid not to. 
7876     result
->setObject(kCFBundleIdentifierKey
, bundleID
); 
7880     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) { 
7881         versionString 
= OSDynamicCast(OSString
, 
7882             getPropertyForHostArch(kCFBundleVersionKey
)); 
7883         if (versionString
) { 
7884             result
->setObject(kCFBundleVersionKey
, versionString
); 
7888    /* OSBundleCompatibleVersion. 
7890     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) { 
7891         versionString 
= OSDynamicCast(OSString
, 
7892             getPropertyForHostArch(kOSBundleCompatibleVersionKey
)); 
7893         if (versionString
) { 
7894             result
->setObject(kOSBundleCompatibleVersionKey
, versionString
); 
7900     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) { 
7902             result
->setObject(kOSBundlePathKey
, path
); 
7907    /* OSBundleExecutablePath. 
7909     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) { 
7910          if (path 
&& executableRelPath
) { 
7912             uint32_t pathLength 
= path
->getLength();  // gets incremented below 
7914             // +1 for slash, +1 for \0 
7915             executablePathCStringSize 
= pathLength 
+ executableRelPath
->getLength() + 2; 
7917             executablePathCString 
= (char *)kalloc((executablePathCStringSize
) * 
7918                 sizeof(char)); // +1 for \0 
7919             if (!executablePathCString
) { 
7922             strlcpy(executablePathCString
, path
->getCStringNoCopy(), 
7923                 executablePathCStringSize
); 
7924             executablePathCString
[pathLength
++] = '/'; 
7925             executablePathCString
[pathLength
++] = '\0'; 
7926             strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(), 
7927                 executablePathCStringSize
); 
7929             executablePathString 
= OSString::withCString(executablePathCString
); 
7931             if (!executablePathCString
) { 
7935             result
->setObject(kOSBundleExecutablePathKey
, executablePathString
); 
7939    /* UUID, if the kext has one. 
7941     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) { 
7944             result
->setObject(kOSBundleUUIDKey
, uuid
); 
7949     * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted. 
7951     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) { 
7952         result
->setObject(kOSKernelResourceKey
, 
7953             isKernelComponent() ? kOSBooleanTrue 
: kOSBooleanFalse
); 
7956     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) { 
7957         result
->setObject(kOSBundleIsInterfaceKey
, 
7958             isInterface() ? kOSBooleanTrue 
: kOSBooleanFalse
); 
7961     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) { 
7962         result
->setObject(kOSBundlePrelinkedKey
, 
7963             isPrelinked() ? kOSBooleanTrue 
: kOSBooleanFalse
); 
7966     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) { 
7967         result
->setObject(kOSBundleStartedKey
, 
7968             isStarted() ? kOSBooleanTrue 
: kOSBooleanFalse
); 
7973     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) { 
7974         scratchNumber 
= OSNumber::withNumber((unsigned long long)loadTag
, 
7975             /* numBits */ 8 * sizeof(loadTag
)); 
7976         if (!scratchNumber
) { 
7979         result
->setObject(kOSBundleLoadTagKey
, scratchNumber
); 
7980         OSSafeReleaseNULL(scratchNumber
); 
7983    /* LoadAddress, LoadSize. 
7986         _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) || 
7987         _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) || 
7988         _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) 
7990         if (isInterface() || linkedExecutable
) { 
7991            /* These go to userspace via serialization, so we don't want any doubts 
7994             uint64_t    loadAddress 
= 0; 
7995             uint32_t    loadSize    
= 0; 
7996             uint32_t    wiredSize   
= 0; 
7998            /* Interfaces always report 0 load address & size. 
7999             * Just the way they roll. 
8001             * xxx - leaving in # when we have a linkedExecutable...a kernelcomp 
8002             * xxx - shouldn't have one! 
8004             if (linkedExecutable 
/* && !isInterface() */) { 
8005                 loadAddress 
= (uint64_t)linkedExecutable
->getBytesNoCopy(); 
8006                 loadAddress 
= VM_KERNEL_UNSLIDE(loadAddress
); 
8007                 loadSize 
= linkedExecutable
->getLength(); 
8009                /* If we have a kmod_info struct, calculated the wired size 
8010                 * from that. Otherwise it's the full load size. 
8013                     wiredSize 
= loadSize 
- kmod_info
->hdr_size
; 
8015                     wiredSize 
= loadSize
; 
8019             if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) { 
8020                 scratchNumber 
= OSNumber::withNumber( 
8021                     (unsigned long long)(loadAddress
), 
8022                     /* numBits */ 8 * sizeof(loadAddress
)); 
8023                 if (!scratchNumber
) { 
8026                 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
); 
8027                 OSSafeReleaseNULL(scratchNumber
); 
8029             if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) { 
8030                 scratchNumber 
= OSNumber::withNumber( 
8031                     (unsigned long long)(loadSize
), 
8032                     /* numBits */ 8 * sizeof(loadSize
)); 
8033                 if (!scratchNumber
) { 
8036                 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
); 
8037                 OSSafeReleaseNULL(scratchNumber
); 
8039             if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) { 
8040                 scratchNumber 
= OSNumber::withNumber( 
8041                     (unsigned long long)(wiredSize
), 
8042                     /* numBits */ 8 * sizeof(wiredSize
)); 
8043                 if (!scratchNumber
) { 
8046                 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
); 
8047                 OSSafeReleaseNULL(scratchNumber
); 
8052    /* OSBundleDependencies. In descending order for 
8053     * easy compatibility with kextstat(8). 
8055     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) { 
8056         if ((count 
= getNumDependencies())) { 
8057             dependencyLoadTags 
= OSArray::withCapacity(count
); 
8058             result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
); 
8062                 OSKext 
* dependency 
= OSDynamicCast(OSKext
, 
8063                     dependencies
->getObject(i
)); 
8065                 OSSafeReleaseNULL(scratchNumber
); 
8070                 scratchNumber 
= OSNumber::withNumber( 
8071                     (unsigned long long)dependency
->getLoadTag(), 
8072                     /* numBits*/ 8 * sizeof(loadTag
)); 
8073                 if (!scratchNumber
) { 
8076                 dependencyLoadTags
->setObject(scratchNumber
); 
8081     OSSafeReleaseNULL(scratchNumber
); 
8083    /* OSBundleMetaClasses. 
8085     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) { 
8086         if (metaClasses 
&& metaClasses
->getCount()) { 
8087             metaClassIterator 
= OSCollectionIterator::withCollection(metaClasses
); 
8088             metaClassInfo 
= OSArray::withCapacity(metaClasses
->getCount()); 
8089             if (!metaClassIterator 
|| !metaClassInfo
) { 
8092             result
->setObject(kOSBundleClassesKey
, metaClassInfo
); 
8094             while ( (thisMetaClass 
= OSDynamicCast(OSMetaClass
, 
8095                 metaClassIterator
->getNextObject())) ) { 
8097                 OSSafeReleaseNULL(metaClassDict
); 
8098                 OSSafeReleaseNULL(scratchNumber
); 
8099                 OSSafeReleaseNULL(metaClassName
); 
8100                 OSSafeReleaseNULL(superclassName
); 
8102                 metaClassDict 
= OSDictionary::withCapacity(3); 
8103                 if (!metaClassDict
) { 
8107                 metaClassName 
= OSString::withCString(thisMetaClass
->getClassName()); 
8108                 if (thisMetaClass
->getSuperClass()) { 
8109                     superclassName 
= OSString::withCString( 
8110                         thisMetaClass
->getSuperClass()->getClassName()); 
8112                 scratchNumber 
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(), 
8113                     8 * sizeof(unsigned int)); 
8115                /* Bail if any of the essentials is missing. The root class lacks a superclass, 
8118                 if (!metaClassDict 
|| !metaClassName 
|| !scratchNumber
) { 
8122                 metaClassInfo
->setObject(metaClassDict
); 
8123                 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
); 
8124                 if (superclassName
) { 
8125                     metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
); 
8127                 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
); 
8132    /* OSBundleRetainCount. 
8134     if (!infoKeys 
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) { 
8135         OSSafeReleaseNULL(scratchNumber
); 
8137             int kextRetainCount 
= getRetainCount() - 1; 
8141             scratchNumber 
= OSNumber::withNumber( 
8142                 (int)kextRetainCount
, 
8143                 /* numBits*/ 8 * sizeof(int)); 
8144             if (scratchNumber
) { 
8145                 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
); 
8153     OSSafeRelease(headerData
); 
8154     OSSafeRelease(cpuTypeNumber
); 
8155     OSSafeRelease(cpuSubtypeNumber
); 
8156     OSSafeRelease(executablePathString
); 
8157     if (executablePathString
) kfree(executablePathCString
, executablePathCStringSize
); 
8158     OSSafeRelease(uuid
); 
8159     OSSafeRelease(scratchNumber
); 
8160     OSSafeRelease(dependencyLoadTags
); 
8161     OSSafeRelease(metaClassIterator
); 
8162     OSSafeRelease(metaClassInfo
); 
8163     OSSafeRelease(metaClassDict
); 
8164     OSSafeRelease(metaClassName
); 
8165     OSSafeRelease(superclassName
); 
8167         OSSafeReleaseNULL(result
); 
8172 /********************************************************************* 
8173  *********************************************************************/ 
8176 OSKext::requestResource( 
8177     const char                    * kextIdentifierCString
, 
8178     const char                    * resourceNameCString
, 
8179     OSKextRequestResourceCallback   callback
, 
8181     OSKextRequestTag              
* requestTagOut
) 
8183     OSReturn           result          
= kOSReturnError
; 
8184     OSKext           
* callbackKext    
= NULL
;  // must release (looked up) 
8186     OSKextRequestTag   requestTag      
= -1; 
8187     OSNumber         
* requestTagNum   
= NULL
;  // must release 
8189     OSDictionary     
* requestDict     
= NULL
;  // must release 
8190     OSString         
* kextIdentifier  
= NULL
;  // must release 
8191     OSString         
* resourceName    
= NULL
;  // must release 
8193     OSDictionary     
* callbackRecord  
= NULL
;  // must release 
8194     OSData           
* callbackWrapper 
= NULL
;  // must release 
8196     OSData           
* contextWrapper  
= NULL
;  // must release 
8198     IORecursiveLockLock(sKextLock
); 
8200     if (requestTagOut
) { 
8201         *requestTagOut 
= kOSKextRequestTagInvalid
; 
8204     /* If requests to user space are disabled, don't go any further */ 
8205     if (!sKernelRequestsEnabled
) { 
8206         OSKextLog(/* kext */ NULL
,  
8207             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
8208             "Can't request resource %s for %s - requests to user space are disabled.", 
8209             resourceNameCString
, 
8210             kextIdentifierCString
); 
8211         result 
= kOSKextReturnDisabled
; 
8215     if (!kextIdentifierCString 
|| !resourceNameCString 
|| !callback
) { 
8216         result 
= kOSKextReturnInvalidArgument
; 
8220     callbackKext 
= OSKext::lookupKextWithAddress((vm_address_t
)callback
); 
8221     if (!callbackKext
) { 
8222         OSKextLog(/* kext */ NULL
, 
8223             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
8224             "Resource request has bad callback address."); 
8225         result 
= kOSKextReturnInvalidArgument
; 
8228     if (!callbackKext
->flags
.starting 
&& !callbackKext
->flags
.started
) { 
8229         OSKextLog(/* kext */ NULL
, 
8230             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
8231             "Resource request callback is in a kext that is not started."); 
8232         result 
= kOSKextReturnInvalidArgument
; 
8236    /* Do not allow any new requests to be made on a kext that is unloading. 
8238     if (callbackKext
->flags
.stopping
) { 
8239         result 
= kOSKextReturnStopping
; 
8243    /* If we're wrapped the next available request tag around to the negative 
8244     * numbers, we can't service any more requests. 
8246     if (sNextRequestTag 
== kOSKextRequestTagInvalid
) { 
8247         OSKextLog(/* kext */ NULL
, 
8248             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
8249             "No more request tags available; restart required."); 
8250         result 
= kOSKextReturnNoResources
; 
8253     requestTag 
= sNextRequestTag
++; 
8255     result 
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
, 
8257     if (result 
!= kOSReturnSuccess
) { 
8261     kextIdentifier 
= OSString::withCString(kextIdentifierCString
); 
8262     resourceName   
= OSString::withCString(resourceNameCString
); 
8263     requestTagNum  
= OSNumber::withNumber((long long unsigned int)requestTag
, 
8264         8 * sizeof(requestTag
)); 
8265     if (!kextIdentifier 
|| 
8268         !_OSKextSetRequestArgument(requestDict
, 
8269             kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) || 
8270         !_OSKextSetRequestArgument(requestDict
, 
8271             kKextRequestArgumentNameKey
, resourceName
) || 
8272         !_OSKextSetRequestArgument(requestDict
, 
8273             kKextRequestArgumentRequestTagKey
, requestTagNum
)) { 
8275         result 
= kOSKextReturnNoMemory
; 
8279     callbackRecord 
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection()); 
8280     if (!callbackRecord
) { 
8281         result 
= kOSKextReturnNoMemory
; 
8284     // we validate callback address at call time 
8285     callbackWrapper 
= OSData::withBytes((void *)&callback
, sizeof(void *)); 
8287         contextWrapper 
= OSData::withBytes((void *)&context
, sizeof(void *)); 
8289     if (!callbackWrapper 
|| !_OSKextSetRequestArgument(callbackRecord
, 
8290             kKextRequestArgumentCallbackKey
, callbackWrapper
)) { 
8292         result 
= kOSKextReturnNoMemory
; 
8297         if (!contextWrapper 
|| !_OSKextSetRequestArgument(callbackRecord
, 
8298             kKextRequestArgumentContextKey
, contextWrapper
)) { 
8300             result 
= kOSKextReturnNoMemory
; 
8305    /* Only post the requests after all the other potential failure points 
8308     if (!sKernelRequests
->setObject(requestDict
) || 
8309         !sRequestCallbackRecords
->setObject(callbackRecord
)) { 
8311         result 
= kOSKextReturnNoMemory
; 
8315     OSKext::pingKextd(); 
8317     result 
= kOSReturnSuccess
; 
8318     if (requestTagOut
) { 
8319         *requestTagOut 
= requestTag
; 
8324    /* If we didn't succeed, yank the request & callback 
8325     * from their holding arrays. 
8327     if (result 
!= kOSReturnSuccess
) { 
8330         index 
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0); 
8331         if (index 
!= (unsigned int)-1) { 
8332             sKernelRequests
->removeObject(index
); 
8334         index 
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0); 
8335         if (index 
!= (unsigned int)-1) { 
8336             sRequestCallbackRecords
->removeObject(index
); 
8340     OSKext::considerUnloads(/* rescheduleOnly? */ true); 
8342     IORecursiveLockUnlock(sKextLock
); 
8344     if (callbackKext
)    callbackKext
->release(); 
8345     if (requestTagNum
)   requestTagNum
->release(); 
8347     if (requestDict
)     requestDict
->release(); 
8348     if (kextIdentifier
)  kextIdentifier
->release(); 
8349     if (resourceName
)    resourceName
->release(); 
8351     if (callbackRecord
)  callbackRecord
->release(); 
8352     if (callbackWrapper
) callbackWrapper
->release(); 
8353     if (contextWrapper
)  contextWrapper
->release(); 
8358 /********************************************************************* 
8359 * Assumes sKextLock is held. 
8360 *********************************************************************/ 
8363 OSKext::dequeueCallbackForRequestTag( 
8364     OSKextRequestTag    requestTag
, 
8365     OSDictionary     
** callbackRecordOut
) 
8367     OSReturn   result 
= kOSReturnError
; 
8368     OSNumber 
* requestTagNum  
= NULL
;  // must release 
8370     requestTagNum  
= OSNumber::withNumber((long long unsigned int)requestTag
, 
8371         8 * sizeof(requestTag
)); 
8372     if (!requestTagNum
) { 
8376     result 
= OSKext::dequeueCallbackForRequestTag(requestTagNum
, 
8380     OSSafeRelease(requestTagNum
); 
8385 /********************************************************************* 
8386 * Assumes sKextLock is held. 
8387 *********************************************************************/ 
8390 OSKext::dequeueCallbackForRequestTag( 
8391     OSNumber     
*    requestTagNum
, 
8392     OSDictionary 
** callbackRecordOut
) 
8394     OSReturn        result          
= kOSKextReturnInvalidArgument
; 
8395     OSDictionary  
* callbackRecord  
= NULL
;  // retain if matched! 
8396     OSNumber      
* callbackTagNum  
= NULL
;  // do not release 
8397     unsigned int    count
, i
; 
8399     result 
= kOSReturnError
; 
8400     count 
= sRequestCallbackRecords
->getCount(); 
8401     for (i 
= 0; i 
< count
; i
++) { 
8402         callbackRecord 
= OSDynamicCast(OSDictionary
, 
8403             sRequestCallbackRecords
->getObject(i
)); 
8404         if (!callbackRecord
) { 
8408        /* If we don't find a tag, we basically have a leak here. Maybe 
8409         * we should just remove it. 
8411         callbackTagNum 
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument( 
8412             callbackRecord
, kKextRequestArgumentRequestTagKey
)); 
8413         if (!callbackTagNum
) { 
8417        /* We could be even more paranoid and check that all the incoming 
8418         * args match what's in the callback record. 
8420         if (callbackTagNum
->isEqualTo(requestTagNum
)) { 
8421             if (callbackRecordOut
) { 
8422                 *callbackRecordOut 
= callbackRecord
; 
8423                 callbackRecord
->retain(); 
8425             sRequestCallbackRecords
->removeObject(i
); 
8426             result 
= kOSReturnSuccess
; 
8430     result 
= kOSKextReturnNotFound
; 
8436 /********************************************************************* 
8437 * Assumes sKextLock is held. 
8438 *********************************************************************/ 
8441 OSKext::dispatchResource(OSDictionary 
* requestDict
) 
8443     OSReturn                        result          
= kOSReturnError
; 
8444     OSDictionary                  
* callbackRecord  
= NULL
;  // must release 
8445     OSNumber                      
* requestTag      
= NULL
;  // do not release 
8446     OSNumber                      
* requestResult   
= NULL
;  // do not release 
8447     OSData                        
* dataObj         
= NULL
;  // do not release 
8448     uint32_t                        dataLength      
= 0; 
8449     const void                    * dataPtr         
= NULL
;  // do not free 
8450     OSData                        
* callbackWrapper 
= NULL
;  // do not release 
8451     OSKextRequestResourceCallback   callback        
= NULL
; 
8452     OSData                        
* contextWrapper  
= NULL
;  // do not release 
8453     void                          * context         
= NULL
;  // do not free 
8454     OSKext                        
* callbackKext    
= NULL
;  // must release (looked up) 
8456    /* Get the args from the request. Right now we need the tag 
8457     * to look up the callback record, and the result for invoking the callback. 
8459     requestTag 
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
, 
8460         kKextRequestArgumentRequestTagKey
)); 
8461     requestResult 
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
, 
8462         kKextRequestArgumentResultKey
)); 
8463     if (!requestTag 
|| !requestResult
) { 
8464         result 
= kOSKextReturnInvalidArgument
; 
8468    /* Look for a callback record matching this request's tag. 
8470     result 
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
); 
8471     if (result 
!= kOSReturnSuccess
) { 
8476     * Get the context pointer of the callback record (if there is one). 
8478     contextWrapper 
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
, 
8479         kKextRequestArgumentContextKey
)); 
8480     context 
= _OSKextExtractPointer(contextWrapper
); 
8481     if (contextWrapper 
&& !context
) { 
8485     callbackWrapper 
= OSDynamicCast(OSData
, 
8486         _OSKextGetRequestArgument(callbackRecord
, 
8487             kKextRequestArgumentCallbackKey
)); 
8488     callback 
= (OSKextRequestResourceCallback
) 
8489         _OSKextExtractPointer(callbackWrapper
); 
8494    /* Check for a data obj. We might not have one and that's ok, that means 
8495     * we didn't find the requested resource, and we still have to tell the 
8496     * caller that via the callback. 
8498     dataObj 
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
, 
8499         kKextRequestArgumentValueKey
)); 
8501         dataPtr 
= dataObj
->getBytesNoCopy(); 
8502         dataLength 
= dataObj
->getLength(); 
8505     callbackKext 
= OSKext::lookupKextWithAddress((vm_address_t
)callback
); 
8506     if (!callbackKext
) { 
8507         OSKextLog(/* kext */ NULL
, 
8508             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
8509             "Can't invoke callback for resource request; "); 
8512     if (!callbackKext
->flags
.starting 
&& !callbackKext
->flags
.started
) { 
8513         OSKextLog(/* kext */ NULL
, 
8514             kOSKextLogErrorLevel 
| kOSKextLogIPCFlag
, 
8515             "Can't invoke kext resource callback; "); 
8519     (void)callback(requestTag
->unsigned32BitValue(), 
8520         (OSReturn
)requestResult
->unsigned32BitValue(), 
8521         dataPtr
, dataLength
, context
); 
8523     result 
= kOSReturnSuccess
; 
8526     if (callbackKext
)   callbackKext
->release(); 
8527     if (callbackRecord
) callbackRecord
->release(); 
8532 /********************************************************************* 
8533 *********************************************************************/ 
8536 OSKext::invokeRequestCallback( 
8537     OSDictionary 
* callbackRecord
, 
8538     OSReturn       callbackResult
) 
8540     OSString 
* predicate  
= _OSKextGetRequestPredicate(callbackRecord
); 
8541     OSNumber 
* resultNum  
= NULL
;  // must release 
8547     resultNum  
= OSNumber::withNumber((long long unsigned int)callbackResult
, 
8548         8 * sizeof(callbackResult
)); 
8553    /* Insert the result into the callback record and dispatch it as if it 
8554     * were the reply coming down from user space. 
8556     _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
, 
8559     if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) { 
8560        /* This removes the pending callback record. 
8562         OSKext::dispatchResource(callbackRecord
); 
8566     if (resultNum
) resultNum
->release(); 
8570 /********************************************************************* 
8571 * Assumes sKextLock is held. 
8572 *********************************************************************/ 
8575 OSKext::cancelRequest( 
8576     OSKextRequestTag    requestTag
, 
8579     OSReturn       result         
= kOSKextReturnNoMemory
; 
8580     OSDictionary 
* callbackRecord 
= NULL
;  // must release 
8581     OSData       
* contextWrapper 
= NULL
;  // do not release 
8583     IORecursiveLockLock(sKextLock
); 
8584     result 
= OSKext::dequeueCallbackForRequestTag(requestTag
, 
8586     IORecursiveLockUnlock(sKextLock
); 
8588     if (result 
== kOSReturnSuccess 
&& contextOut
) { 
8589         contextWrapper 
= OSDynamicCast(OSData
, 
8590             _OSKextGetRequestArgument(callbackRecord
, 
8591                 kKextRequestArgumentContextKey
)); 
8592         *contextOut 
= _OSKextExtractPointer(contextWrapper
); 
8595     if (callbackRecord
) callbackRecord
->release(); 
8600 /********************************************************************* 
8601 * Assumes sKextLock is held. 
8602 *********************************************************************/ 
8604 OSKext::invokeOrCancelRequestCallbacks( 
8605     OSReturn callbackResult
, 
8608     unsigned int count
, i
; 
8610     count 
= sRequestCallbackRecords
->getCount(); 
8617         OSDictionary 
* request 
= OSDynamicCast(OSDictionary
, 
8618             sRequestCallbackRecords
->getObject(i
)); 
8623         OSData 
* callbackWrapper 
= OSDynamicCast(OSData
, 
8624             _OSKextGetRequestArgument(request
, 
8625                 kKextRequestArgumentCallbackKey
)); 
8627         if (!callbackWrapper
) { 
8628             sRequestCallbackRecords
->removeObject(i
); 
8632         vm_address_t callbackAddress 
= (vm_address_t
) 
8633             _OSKextExtractPointer(callbackWrapper
); 
8635         if ((kmod_info
->address 
<= callbackAddress
) && 
8636             (callbackAddress 
< (kmod_info
->address 
+ kmod_info
->size
))) { 
8639                /* This removes the callback record. 
8641                 invokeRequestCallback(request
, callbackResult
); 
8643                 sRequestCallbackRecords
->removeObject(i
); 
8652 /********************************************************************* 
8653 * Assumes sKextLock is held. 
8654 *********************************************************************/ 
8656 OSKext::countRequestCallbacks(void) 
8658     uint32_t     result 
= 0; 
8659     unsigned int count
, i
; 
8661     count 
= sRequestCallbackRecords
->getCount(); 
8668         OSDictionary 
* request 
= OSDynamicCast(OSDictionary
, 
8669             sRequestCallbackRecords
->getObject(i
)); 
8674         OSData 
* callbackWrapper 
= OSDynamicCast(OSData
, 
8675             _OSKextGetRequestArgument(request
, 
8676                 kKextRequestArgumentCallbackKey
)); 
8678         if (!callbackWrapper
) { 
8682         vm_address_t callbackAddress 
= (vm_address_t
) 
8683             _OSKextExtractPointer(callbackWrapper
); 
8685         if ((kmod_info
->address 
<= callbackAddress
) && 
8686             (callbackAddress 
< (kmod_info
->address 
+ kmod_info
->size
))) { 
8696 /********************************************************************* 
8697 *********************************************************************/ 
8698 static OSReturn 
_OSKextCreateRequest( 
8699     const char    * predicate
, 
8700     OSDictionary 
** requestP
) 
8702     OSReturn result 
= kOSKextReturnNoMemory
; 
8703     OSDictionary 
* request 
= NULL
;  // must release on error 
8704     OSDictionary 
* args 
= NULL
;     // must release 
8706     request 
= OSDictionary::withCapacity(2); 
8710     result 
= _OSDictionarySetCStringValue(request
, 
8711         kKextRequestPredicateKey
, predicate
); 
8712     if (result 
!= kOSReturnSuccess
) { 
8715     result 
= kOSReturnSuccess
; 
8718     if (result 
!= kOSReturnSuccess
) { 
8719         if (request
) request
->release(); 
8721         *requestP 
= request
; 
8723     if (args
) args
->release(); 
8728 /********************************************************************* 
8729 *********************************************************************/ 
8730 static OSString 
* _OSKextGetRequestPredicate(OSDictionary 
* requestDict
) 
8732     return OSDynamicCast(OSString
, 
8733         requestDict
->getObject(kKextRequestPredicateKey
)); 
8736 /********************************************************************* 
8737 *********************************************************************/ 
8738 static OSObject 
* _OSKextGetRequestArgument( 
8739     OSDictionary 
* requestDict
, 
8740     const char   * argName
) 
8742     OSDictionary 
* args 
= OSDynamicCast(OSDictionary
, 
8743         requestDict
->getObject(kKextRequestArgumentsKey
)); 
8745         return args
->getObject(argName
); 
8750 /********************************************************************* 
8751 *********************************************************************/ 
8752 static bool _OSKextSetRequestArgument( 
8753     OSDictionary 
* requestDict
, 
8754     const char   * argName
, 
8757     OSDictionary 
* args 
= OSDynamicCast(OSDictionary
, 
8758         requestDict
->getObject(kKextRequestArgumentsKey
)); 
8760         args 
= OSDictionary::withCapacity(2); 
8764         requestDict
->setObject(kKextRequestArgumentsKey
, args
); 
8768         return args
->setObject(argName
, value
); 
8774 /********************************************************************* 
8775 *********************************************************************/ 
8776 static void * _OSKextExtractPointer(OSData 
* wrapper
) 
8778     void       * result 
= NULL
; 
8779     const void * resultPtr 
= NULL
; 
8784     resultPtr 
= wrapper
->getBytesNoCopy(); 
8785     result 
= *(void **)resultPtr
; 
8790 /********************************************************************* 
8791 *********************************************************************/ 
8792 static OSReturn 
_OSDictionarySetCStringValue( 
8793     OSDictionary 
* dict
, 
8795     const char   * cValue
) 
8797     OSReturn result 
= kOSKextReturnNoMemory
; 
8798     const OSSymbol 
* key 
= NULL
;  // must release 
8799     OSString 
* value 
= NULL
;  // must release 
8801     key 
= OSSymbol::withCString(cKey
); 
8802     value 
= OSString::withCString(cValue
); 
8803     if (!key 
|| !value
) { 
8806     if (dict
->setObject(key
, value
)) { 
8807         result 
= kOSReturnSuccess
; 
8811     if (key
)   key
->release(); 
8812     if (value
) value
->release(); 
8817 /********************************************************************* 
8818 *********************************************************************/ 
8819 static bool _OSArrayContainsCString( 
8821     const char * cString
) 
8823     bool             result 
= false; 
8824     const OSSymbol 
* symbol 
= NULL
; 
8827     if (!array 
|| !cString
) { 
8831     symbol 
= OSSymbol::withCStringNoCopy(cString
); 
8836     count 
= array
->getCount(); 
8837     for (i 
= 0; i 
< count
; i
++) { 
8838         OSObject 
* thisObject 
= array
->getObject(i
); 
8839         if (symbol
->isEqualTo(thisObject
)) { 
8846     if (symbol
) symbol
->release(); 
8850 /********************************************************************* 
8851  * We really only care about boot / system start up related kexts.  
8852  * We return true if we're less than REBUILD_MAX_TIME since start up, 
8853  * otherwise return false. 
8854  *********************************************************************/ 
8855 bool _OSKextInPrelinkRebuildWindow(void) 
8857     static bool     outside_the_window 
= false; 
8858     AbsoluteTime    my_abstime
; 
8862     if (outside_the_window
) { 
8865     clock_get_uptime(&my_abstime
); 
8866     absolutetime_to_nanoseconds(my_abstime
, &my_ns
); 
8867     my_secs 
= (SInt32
)(my_ns 
/ NSEC_PER_SEC
); 
8868     if (my_secs 
> REBUILD_MAX_TIME
) { 
8869         outside_the_window 
= true; 
8875 /********************************************************************* 
8876  *********************************************************************/ 
8877 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol 
* theBundleID 
) 
8879     int unLoadedCount
, i
; 
8880     bool result 
= false; 
8882     IORecursiveLockLock(sKextLock
); 
8884     if (sUnloadedPrelinkedKexts 
== NULL
) { 
8887     unLoadedCount 
= sUnloadedPrelinkedKexts
->getCount(); 
8888     if (unLoadedCount 
== 0) { 
8892     for (i 
= 0; i 
< unLoadedCount
; i
++) { 
8893         const OSSymbol 
*    myBundleID
;     // do not release 
8895         myBundleID 
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
)); 
8896         if (!myBundleID
) continue; 
8897         if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) { 
8903     IORecursiveLockUnlock(sKextLock
); 
8908 #pragma mark Personalities (IOKit Drivers) 
8910 /********************************************************************* 
8911 *********************************************************************/ 
8914 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
) 
8916     OSArray              
* result                
= NULL
;  // returned 
8917     OSCollectionIterator 
* kextIterator          
= NULL
;  // must release 
8918     OSArray              
* personalities         
= NULL
;  // must release 
8919     OSCollectionIterator 
* personalitiesIterator 
= NULL
;  // must release 
8921     OSString             
* kextID                
= NULL
;  // do not release 
8922     OSKext               
* theKext               
= NULL
;  // do not release 
8924     IORecursiveLockLock(sKextLock
); 
8926    /* Let's conservatively guess that any given kext has around 3 
8927     * personalities for now. 
8929     result 
= OSArray::withCapacity(sKextsByID
->getCount() * 3); 
8934     kextIterator 
= OSCollectionIterator::withCollection(sKextsByID
); 
8935     if (!kextIterator
) { 
8939     while ((kextID 
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) { 
8940         if (personalitiesIterator
) { 
8941             personalitiesIterator
->release(); 
8942             personalitiesIterator 
= NULL
; 
8944         if (personalities
) { 
8945             personalities
->release(); 
8946             personalities 
= NULL
; 
8949         theKext 
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
)); 
8950         if (!sSafeBoot 
|| !filterSafeBootFlag 
|| theKext
->isLoadableInSafeBoot()) { 
8951             personalities 
= theKext
->copyPersonalitiesArray(); 
8952             if (!personalities
) { 
8955             result
->merge(personalities
); 
8957             // xxx - check for better place to put this log msg 
8959                 kOSKextLogWarningLevel 
| 
8961                 "Kext %s is not loadable during safe boot; " 
8962                 "omitting its personalities.", 
8963                 theKext
->getIdentifierCString()); 
8969     IORecursiveLockUnlock(sKextLock
); 
8971     if (kextIterator
)          kextIterator
->release(); 
8972     if (personalitiesIterator
) personalitiesIterator
->release(); 
8973     if (personalities
)         personalities
->release(); 
8978 /********************************************************************* 
8979 *********************************************************************/ 
8982 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
) 
8984     int numPersonalities 
= 0; 
8986     OSKextLog(/* kext */ NULL
, 
8987         kOSKextLogStepLevel 
| 
8989         "Sending all eligible registered kexts' personalities " 
8990         "to the IOCatalogue %s.", 
8991         startMatching 
? "and starting matching" : "but not starting matching"); 
8993     OSArray 
* personalities 
= OSKext::copyAllKextPersonalities( 
8994         /* filterSafeBootFlag */ true); 
8996     if (personalities
) { 
8997         gIOCatalogue
->addDrivers(personalities
, startMatching
); 
8998         numPersonalities 
= personalities
->getCount(); 
8999         personalities
->release(); 
9002     OSKextLog(/* kext */ NULL
, 
9003         kOSKextLogStepLevel 
| 
9005         "%d kext personalit%s sent to the IOCatalogue; %s.", 
9006         numPersonalities
, numPersonalities 
> 0 ? "ies" : "y", 
9007         startMatching 
? "matching started" : "matching not started"); 
9011 /********************************************************************* 
9012 * Do not make a deep copy, just convert the IOKitPersonalities dict 
9013 * to an array for sending to the IOCatalogue. 
9014 *********************************************************************/ 
9016 OSKext::copyPersonalitiesArray(void) 
9018     OSArray              
* result                      
= NULL
; 
9019     OSDictionary         
* personalities               
= NULL
;  // do not release 
9020     OSCollectionIterator 
* personalitiesIterator       
= NULL
;  // must release 
9022     OSString             
* personalityName             
= NULL
;  // do not release     
9023     OSString             
* personalityBundleIdentifier 
= NULL
;  // do not release 
9025     personalities 
= OSDynamicCast(OSDictionary
, 
9026         getPropertyForHostArch(kIOKitPersonalitiesKey
)); 
9027     if (!personalities
) { 
9031     result 
= OSArray::withCapacity(personalities
->getCount()); 
9036     personalitiesIterator 
= 
9037         OSCollectionIterator::withCollection(personalities
); 
9038     if (!personalitiesIterator
) { 
9041     while ((personalityName 
= OSDynamicCast(OSString
, 
9042             personalitiesIterator
->getNextObject()))) { 
9044         OSDictionary 
* personality 
= OSDynamicCast(OSDictionary
, 
9045             personalities
->getObject(personalityName
)); 
9048         * If the personality doesn't have a CFBundleIdentifier, or if it 
9049         * differs from the kext's, insert the kext's ID so we can find it. 
9050         * The publisher ID is used to remove personalities from bundles 
9053         personalityBundleIdentifier 
= OSDynamicCast(OSString
, 
9054             personality
->getObject(kCFBundleIdentifierKey
)); 
9056         if (!personalityBundleIdentifier
) { 
9057             personality
->setObject(kCFBundleIdentifierKey
, bundleID
); 
9058         } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) { 
9059             personality
->setObject(kIOPersonalityPublisherKey
, bundleID
); 
9062         result
->setObject(personality
); 
9066     if (personalitiesIterator
) personalitiesIterator
->release(); 
9071 /********************************************************************* 
9072 Might want to change this to a bool return? 
9073 *********************************************************************/ 
9075 OSKext::sendPersonalitiesToCatalog( 
9077     OSArray 
* personalityNames
) 
9079     OSReturn       result              
= kOSReturnSuccess
; 
9080     OSArray      
* personalitiesToSend 
= NULL
;  // must release 
9081     OSDictionary 
* kextPersonalities   
= NULL
;  // do not release 
9084     if (!sLoadEnabled
) { 
9086             kOSKextLogErrorLevel 
| 
9088             "Kext loading is disabled (attempt to start matching for kext %s).", 
9089             getIdentifierCString()); 
9090         result 
= kOSKextReturnDisabled
; 
9094     if (sSafeBoot 
&& !isLoadableInSafeBoot()) { 
9096             kOSKextLogErrorLevel 
| 
9098             "Kext %s is not loadable during safe boot; " 
9099             "not sending personalities to the IOCatalogue.", 
9100             getIdentifierCString()); 
9101         result 
= kOSKextReturnNotLoadable
; 
9105     if (!personalityNames 
|| !personalityNames
->getCount()) { 
9106         personalitiesToSend 
= copyPersonalitiesArray(); 
9108         kextPersonalities 
= OSDynamicCast(OSDictionary
, 
9109             getPropertyForHostArch(kIOKitPersonalitiesKey
)); 
9110         if (!kextPersonalities 
|| !kextPersonalities
->getCount()) { 
9114         personalitiesToSend 
= OSArray::withCapacity(0); 
9115         if (!personalitiesToSend
) { 
9116             result 
= kOSKextReturnNoMemory
; 
9119         count 
= personalityNames
->getCount(); 
9120         for (i 
= 0; i 
< count
; i
++) { 
9121             OSString 
* name 
= OSDynamicCast(OSString
, 
9122                 personalityNames
->getObject(i
)); 
9126             OSDictionary 
* personality 
= OSDynamicCast(OSDictionary
, 
9127                 kextPersonalities
->getObject(name
)); 
9129                 personalitiesToSend
->setObject(personality
); 
9133     if (personalitiesToSend
) { 
9134         unsigned numPersonalities 
= personalitiesToSend
->getCount(); 
9136             kOSKextLogStepLevel 
| 
9138             "Kext %s sending %d personalit%s to the IOCatalogue%s.", 
9139             getIdentifierCString(), 
9141             numPersonalities 
> 1 ? "ies" : "y", 
9142             startMatching 
? " and starting matching" : " but not starting matching"); 
9143         gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
); 
9146     if (personalitiesToSend
) { 
9147         personalitiesToSend
->release(); 
9152 /********************************************************************* 
9153 * xxx - We should allow removing the kext's declared personalities, 
9154 * xxx - even with other bundle identifiers. 
9155 *********************************************************************/ 
9157 OSKext::removePersonalitiesFromCatalog(void) 
9159     OSDictionary 
* personality 
= NULL
;   // do not release 
9161     personality 
= OSDictionary::withCapacity(1); 
9165     personality
->setObject(kCFBundleIdentifierKey
, getIdentifier()); 
9168         kOSKextLogStepLevel 
| 
9170         "Kext %s removing all personalities naming it from the IOCatalogue.", 
9171         getIdentifierCString()); 
9173    /* Have the IOCatalog remove all personalities matching this kext's 
9174     * bundle ID and trigger matching anew. 
9176     gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true); 
9179     if (personality
) personality
->release(); 
9186 #pragma mark Logging 
9188 /********************************************************************* 
9189 * Do not call any function that takes sKextLock here! 
9190 *********************************************************************/ 
9193 OSKext::setUserSpaceLogFilter( 
9194     OSKextLogSpec   newUserLogFilter
, 
9197     OSKextLogSpec result
; 
9198     bool          allocError 
= false; 
9200    /* Do not call any function that takes sKextLoggingLock during 
9201     * this critical block. That means do logging after. 
9203     IOLockLock(sKextLoggingLock
); 
9205     result 
= sUserSpaceKextLogFilter
; 
9206     sUserSpaceKextLogFilter 
= newUserLogFilter
; 
9208     if (newUserLogFilter 
&& captureFlag 
&& 
9209         !sUserSpaceLogSpecArray 
&& !sUserSpaceLogMessageArray
) { 
9211         // xxx - do some measurements for a good initial capacity? 
9212         sUserSpaceLogSpecArray 
= OSArray::withCapacity(0); 
9213         sUserSpaceLogMessageArray 
= OSArray::withCapacity(0); 
9215         if (!sUserSpaceLogSpecArray 
|| !sUserSpaceLogMessageArray
) { 
9216             OSSafeReleaseNULL(sUserSpaceLogSpecArray
); 
9217             OSSafeReleaseNULL(sUserSpaceLogMessageArray
); 
9222     IOLockUnlock(sKextLoggingLock
); 
9224    /* If the config flag itself is changing, log the state change 
9225     * going both ways, before setting up the user-space log arrays, 
9226     * so that this is only logged in the kernel. 
9228     if (result 
!= newUserLogFilter
) { 
9229         OSKextLog(/* kext */ NULL
, 
9230             kOSKextLogDebugLevel 
| 
9231             kOSKextLogGeneralFlag
, 
9232             "User-space log flags changed from 0x%x to 0x%x.", 
9233             result
, newUserLogFilter
); 
9236         OSKextLog(/* kext */ NULL
, 
9237             kOSKextLogErrorLevel 
| 
9238             kOSKextLogGeneralFlag
, 
9239             "Failed to allocate user-space log message arrays."); 
9245 /********************************************************************* 
9246 * Do not call any function that takes sKextLock here! 
9247 *********************************************************************/ 
9250 OSKext::clearUserSpaceLogFilter(void) 
9252     OSArray       
* result       
= NULL
; 
9253     OSKextLogSpec   oldLogFilter
; 
9254     OSKextLogSpec   newLogFilter 
= kOSKextLogSilentFilter
; 
9256    /* Do not call any function that takes sKextLoggingLock during 
9257     * this critical block. That means do logging after. 
9259     IOLockLock(sKextLoggingLock
); 
9261     result 
= OSArray::withCapacity(2); 
9263         result
->setObject(sUserSpaceLogSpecArray
); 
9264         result
->setObject(sUserSpaceLogMessageArray
); 
9266     OSSafeReleaseNULL(sUserSpaceLogSpecArray
); 
9267     OSSafeReleaseNULL(sUserSpaceLogMessageArray
); 
9269     oldLogFilter 
= sUserSpaceKextLogFilter
; 
9270     sUserSpaceKextLogFilter 
= newLogFilter
; 
9272     IOLockUnlock(sKextLoggingLock
); 
9274    /* If the config flag itself is changing, log the state change 
9275     * going both ways, after tearing down the user-space log 
9276     * arrays, so this is only logged within the kernel. 
9278     if (oldLogFilter 
!= newLogFilter
) { 
9279         OSKextLog(/* kext */ NULL
, 
9280             kOSKextLogDebugLevel 
| 
9281             kOSKextLogGeneralFlag
, 
9282             "User-space log flags changed from 0x%x to 0x%x.", 
9283             oldLogFilter
, newLogFilter
); 
9290 /********************************************************************* 
9291 * Do not call any function that takes sKextLock here! 
9292 *********************************************************************/ 
9295 OSKext::getUserSpaceLogFilter(void) 
9297     OSKextLogSpec result
; 
9299     IOLockLock(sKextLoggingLock
); 
9300     result 
= sUserSpaceKextLogFilter
; 
9301     IOLockUnlock(sKextLoggingLock
); 
9306 /********************************************************************* 
9307 * This function is called by OSMetaClass during kernel C++ setup. 
9308 * Be careful what you access here; assume only OSKext::initialize() 
9311 * Do not call any function that takes sKextLock here! 
9312 *********************************************************************/ 
9313 #define VTRESET   "\033[0m" 
9315 #define VTBOLD    "\033[1m" 
9316 #define VTUNDER   "\033[4m" 
9318 #define VTRED     "\033[31m" 
9319 #define VTGREEN   "\033[32m" 
9320 #define VTYELLOW  "\033[33m" 
9321 #define VTBLUE    "\033[34m" 
9322 #define VTMAGENTA "\033[35m" 
9323 #define VTCYAN    "\033[36m" 
9325 inline const char * colorForFlags(OSKextLogSpec flags
) 
9327     OSKextLogSpec logLevel 
= flags 
& kOSKextLogLevelMask
; 
9330     case kOSKextLogErrorLevel
: 
9331         return VTRED VTBOLD
; 
9333     case kOSKextLogWarningLevel
: 
9336     case kOSKextLogBasicLevel
: 
9337         return VTYELLOW VTUNDER
; 
9339     case kOSKextLogProgressLevel
: 
9342     case kOSKextLogStepLevel
: 
9345     case kOSKextLogDetailLevel
: 
9348     case kOSKextLogDebugLevel
: 
9358 inline bool logSpecMatch( 
9359     OSKextLogSpec msgLogSpec
, 
9360     OSKextLogSpec logFilter
) 
9362     OSKextLogSpec filterKextGlobal  
= logFilter 
& kOSKextLogKextOrGlobalMask
; 
9363     OSKextLogSpec filterLevel       
= logFilter 
& kOSKextLogLevelMask
; 
9364     OSKextLogSpec filterFlags       
= logFilter 
& kOSKextLogFlagsMask
; 
9366     OSKextLogSpec msgKextGlobal    
= msgLogSpec 
& kOSKextLogKextOrGlobalMask
; 
9367     OSKextLogSpec msgLevel         
= msgLogSpec 
& kOSKextLogLevelMask
; 
9368     OSKextLogSpec msgFlags         
= msgLogSpec 
& kOSKextLogFlagsMask
; 
9370    /* Explicit messages always get logged. 
9372     if (msgLevel 
== kOSKextLogExplicitLevel
) { 
9376    /* Warnings and errors are logged regardless of the flags. 
9378     if (msgLevel 
<= kOSKextLogBasicLevel 
&& (msgLevel 
<= filterLevel
)) { 
9382    /* A verbose message that isn't for a logging-enabled kext and isn't global 
9383     * does *not* get logged. 
9385     if (!msgKextGlobal 
&& !filterKextGlobal
) { 
9389    /* Warnings and errors are logged regardless of the flags. 
9390     * All other messages must fit the flags and 
9391     * have a level at or below the filter. 
9394     if ((msgFlags 
& filterFlags
) && (msgLevel 
<= filterLevel
)) { 
9405     OSKextLogSpec    msgLogSpec
, 
9406     const char     * format
, ...) 
9410     va_start(argList
, format
); 
9411     OSKextVLog(aKext
, msgLogSpec
, format
, argList
); 
9418     OSKextLogSpec    msgLogSpec
, 
9419     const char     * format
, 
9422     extern int       disableConsoleOutput
; 
9424     bool             logForKernel       
= false; 
9425     bool             logForUser         
= false; 
9427     char             stackBuffer
[120]; 
9428     uint32_t         length            
= 0; 
9429     char           * allocBuffer       
= NULL
;         // must kfree 
9430     OSNumber       
* logSpecNum        
= NULL
;         // must release 
9431     OSString       
* logString         
= NULL
;         // must release 
9432     char           * buffer            
= stackBuffer
;  // do not free 
9434     IOLockLock(sKextLoggingLock
); 
9436    /* Set the kext/global bit in the message spec if we have no 
9437     * kext or if the kext requests logging. 
9439     if (!aKext 
|| aKext
->flags
.loggingEnabled
) { 
9440         msgLogSpec 
= msgLogSpec 
| kOSKextLogKextOrGlobalMask
; 
9443     logForKernel 
= logSpecMatch(msgLogSpec
, sKernelLogFilter
); 
9444     if (sUserSpaceLogSpecArray 
&& sUserSpaceLogMessageArray
) { 
9445         logForUser 
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
); 
9448     if (! (logForKernel 
|| logForUser
) ) { 
9452    /* No goto from here until past va_end()! 
9454     va_copy(argList
, srcArgList
); 
9455     length 
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
); 
9458     if (length 
+ 1 >= sizeof(stackBuffer
)) { 
9459         allocBuffer 
= (char *)kalloc((length 
+ 1) * sizeof(char)); 
9464        /* No goto from here until past va_end()! 
9466         va_copy(argList
, srcArgList
); 
9467         vsnprintf(allocBuffer
, length 
+ 1, format
, argList
); 
9470         buffer 
= allocBuffer
; 
9473    /* If user space wants the log message, queue it up. 
9475     if (logForUser 
&& sUserSpaceLogSpecArray 
&& sUserSpaceLogMessageArray
) { 
9476         logSpecNum 
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
)); 
9477         logString 
= OSString::withCString(buffer
); 
9478         if (logSpecNum 
&& logString
) { 
9479             sUserSpaceLogSpecArray
->setObject(logSpecNum
); 
9480             sUserSpaceLogMessageArray
->setObject(logString
); 
9484    /* Always log messages from the kernel according to the kernel's 
9489        /* If we are in console mode and have a custom log filter, 
9490         * colorize the log message. 
9492         if (!disableConsoleOutput 
&& sBootArgLogFilterFound
) { 
9493             const char * color 
= "";  // do not free 
9494             color 
= colorForFlags(msgLogSpec
); 
9495             printf("%s%s%s\n", colorForFlags(msgLogSpec
), 
9496                 buffer
, color
[0] ? VTRESET 
: ""); 
9498             printf("%s\n", buffer
); 
9503     IOLockUnlock(sKextLoggingLock
); 
9506         kfree(allocBuffer
, (length 
+ 1) * sizeof(char)); 
9508     OSSafeRelease(logString
); 
9509     OSSafeRelease(logSpecNum
); 
9513 #if KASLR_IOREG_DEBUG 
9515 #define IOLOG_INDENT( the_indention ) \ 
9518     for ( i = 0; i < (the_indention); i++ ) { \ 
9523 extern vm_offset_t       vm_kernel_stext
; 
9524 extern vm_offset_t       vm_kernel_etext
; 
9525 extern mach_vm_offset_t kext_alloc_base
;  
9526 extern mach_vm_offset_t kext_alloc_max
; 
9528 bool ScanForAddrInObject(OSObject 
* theObject
,  
9531 bool ScanForAddrInObject(OSObject 
* theObject
,  
9534     const OSMetaClass 
*     myTypeID
; 
9535     OSCollectionIterator 
*  myIter
; 
9538     bool                    myResult 
= false; 
9540     if ( theObject 
== NULL 
) { 
9541         IOLog("%s: theObject is NULL \n",  
9546     myTypeID 
= OSTypeIDInst(theObject
); 
9548     if ( myTypeID 
== OSTypeID(OSDictionary
) ) { 
9549         OSDictionary 
*      myDictionary
; 
9551         myDictionary 
= OSDynamicCast(OSDictionary
, theObject
); 
9552         myIter 
= OSCollectionIterator::withCollection( myDictionary 
); 
9553         if ( myIter 
== NULL 
)  
9557         while ( (myKey 
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) { 
9560             myValue 
= myDictionary
->getObject(myKey
); 
9561             myTempResult 
= ScanForAddrInObject(myValue
, (indent 
+ 4)); 
9563                 // if we ever get a true result return true 
9565                 IOLOG_INDENT(indent
); 
9566                 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy()); 
9571     else if ( myTypeID 
== OSTypeID(OSArray
) ) { 
9574         myArray 
= OSDynamicCast(OSArray
, theObject
); 
9575         myIter 
= OSCollectionIterator::withCollection(myArray
); 
9576         if ( myIter 
== NULL 
)  
9580         while ( (myValue 
= myIter
->getNextObject()) ) { 
9582             myTempResult 
= ScanForAddrInObject(myValue
, (indent 
+ 4)); 
9584                 // if we ever get a true result return true 
9586                 IOLOG_INDENT(indent
); 
9587                 IOLog("OSArray: \n"); 
9592     else if ( myTypeID 
== OSTypeID(OSString
) || myTypeID 
== OSTypeID(OSSymbol
) ) { 
9594         // should we look for addresses in strings? 
9596     else if ( myTypeID 
== OSTypeID(OSData
) ) { 
9602         myDataObj 
=    OSDynamicCast(OSData
, theObject
); 
9603         myPtrPtr 
= (void * *) myDataObj
->getBytesNoCopy(); 
9604         myLen 
= myDataObj
->getLength(); 
9606         if (myPtrPtr 
&& myLen 
&& myLen 
> 7) { 
9608             int     myPtrCount 
= (myLen 
/ sizeof(void *)); 
9610             for (i 
= 0; i 
< myPtrCount
; i
++) { 
9611                 UInt64 numberValue 
= (UInt64
) *(myPtrPtr
); 
9613                 if ( kext_alloc_max 
!= 0 && 
9614                     numberValue 
>= kext_alloc_base 
&&  
9615                     numberValue 
< kext_alloc_max 
) { 
9617                     OSKext 
* myKext    
= NULL
;  // must release (looked up) 
9618                                                 // IOLog("found OSData %p in kext map %p to %p  \n", 
9620                                                 //       (void *) kext_alloc_base, 
9621                                                 //       (void *) kext_alloc_max); 
9623                     myKext 
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) ); 
9625                         IOLog("found addr %p from an OSData obj within kext \"%s\"  \n", 
9627                               myKext
->getIdentifierCString()); 
9632                 if ( vm_kernel_etext 
!= 0 && 
9633                     numberValue 
>= vm_kernel_stext 
&&  
9634                     numberValue 
< vm_kernel_etext 
) { 
9635                     IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n", 
9637                           (void *) vm_kernel_stext
, 
9638                           (void *) vm_kernel_etext
); 
9645     else if ( myTypeID 
== OSTypeID(OSBoolean
) ) { 
9647         // do nothing here... 
9649     else if ( myTypeID 
== OSTypeID(OSNumber
) ) { 
9651         OSNumber 
* number 
= OSDynamicCast(OSNumber
, theObject
); 
9653         UInt64 numberValue 
= number
->unsigned64BitValue(); 
9655         if ( kext_alloc_max 
!= 0 && 
9656             numberValue 
>= kext_alloc_base 
&&  
9657             numberValue 
< kext_alloc_max 
) { 
9659             OSKext 
* myKext    
= NULL
;  // must release (looked up) 
9660             IOLog("found OSNumber in kext map %p to %p  \n", 
9661                   (void *) kext_alloc_base
, 
9662                   (void *) kext_alloc_max
); 
9663             IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
); 
9665             myKext 
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue 
); 
9667                 IOLog("found in kext \"%s\"  \n", 
9668                       myKext
->getIdentifierCString()); 
9674         if ( vm_kernel_etext 
!= 0 && 
9675             numberValue 
>= vm_kernel_stext 
&&  
9676             numberValue 
< vm_kernel_etext 
) { 
9677             IOLog("found OSNumber in kernel text segment %p to %p  \n", 
9678                   (void *) vm_kernel_stext
, 
9679                   (void *) vm_kernel_etext
); 
9680             IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
); 
9686         const OSMetaClass
* myMetaClass 
= NULL
; 
9688         myMetaClass 
= theObject
->getMetaClass(); 
9689         if ( myMetaClass 
) { 
9690             IOLog("class %s \n", myMetaClass
->getClassName() ); 
9693             IOLog("Unknown object \n" ); 
9700 #endif // KASLR_KEXT_DEBUG  
9705 #pragma mark Backtrace Dump & kmod_get_info() support 
9707 /********************************************************************* 
9708 * This function must be safe to call in panic context. 
9709 *********************************************************************/ 
9712 OSKext::printKextsInBacktrace( 
9715     int         (* printf_func
)(const char *fmt
, ...), 
9718     addr64_t    summary_page 
= 0; 
9719     addr64_t    last_summary_page 
= 0; 
9720     bool        found_kmod 
= false; 
9724         IOLockLock(sKextSummariesLock
); 
9727     if (!gLoadedKextSummaries
) { 
9728         (*printf_func
)("         can't perform kext scan: no kext summary"); 
9732     summary_page 
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
); 
9733     last_summary_page 
= round_page(summary_page 
+ sLoadedKextSummariesAllocSize
); 
9734     for (; summary_page 
< last_summary_page
; summary_page 
+= PAGE_SIZE
) { 
9735         if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) { 
9736             (*printf_func
)("         can't perform kext scan: " 
9737                 "missing kext summary page %p", summary_page
); 
9742     for (i 
= 0; i 
< gLoadedKextSummaries
->numSummaries
; ++i
) { 
9743         OSKextLoadedKextSummary 
* summary
; 
9745         summary 
= gLoadedKextSummaries
->summaries 
+ i
; 
9746         if (!summary
->address
) { 
9750         if (!summaryIsInBacktrace(summary
, addr
, cnt
)) { 
9755             (*printf_func
)("      Kernel Extensions in backtrace:\n"); 
9759         printSummary(summary
, printf_func
); 
9764         IOLockUnlock(sKextSummariesLock
); 
9770 /********************************************************************* 
9771 * This function must be safe to call in panic context. 
9772 *********************************************************************/ 
9775 OSKext::summaryIsInBacktrace( 
9776     OSKextLoadedKextSummary   
* summary
, 
9782     for (i 
= 0; i 
< cnt
; i
++) { 
9783         vm_offset_t kscan_addr 
= addr
[i
]; 
9784         if ((kscan_addr 
>= summary
->address
) && 
9785             (kscan_addr 
< (summary
->address 
+ summary
->size
)))  
9794 /********************************************************************* 
9795  * scan list of loaded kext summaries looking for a load address match and if 
9796  * found return the UUID C string.  If not found then set empty string. 
9797  *********************************************************************/ 
9798 static void findSummaryUUID( 
9800                             uuid_string_t   uuid
); 
9802 static void findSummaryUUID( 
9808     uuid
[0] = 0x00; // default to no UUID 
9810     for (i 
= 0; i 
< gLoadedKextSummaries
->numSummaries
; ++i
) { 
9811         OSKextLoadedKextSummary 
* summary
; 
9813         summary 
= gLoadedKextSummaries
->summaries 
+ i
; 
9815         if (summary
->loadTag 
== tag_ID
) { 
9816             (void) uuid_unparse(summary
->uuid
, uuid
); 
9823 /********************************************************************* 
9824 * This function must be safe to call in panic context. 
9825 *********************************************************************/ 
9826 void OSKext::printSummary( 
9827     OSKextLoadedKextSummary 
* summary
, 
9828     int                    (* printf_func
)(const char *fmt
, ...)) 
9830     kmod_reference_t 
* kmod_ref 
= NULL
; 
9832     char version
[kOSKextVersionMaxLength
]; 
9834     if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) { 
9835         strlcpy(version
, "unknown version", sizeof(version
)); 
9837     (void) uuid_unparse(summary
->uuid
, uuid
); 
9839     (*printf_func
)("         %s(%s)[%s]@0x%llx->0x%llx\n", 
9840         summary
->name
, version
, uuid
, 
9841         summary
->address
, summary
->address 
+ summary
->size 
- 1); 
9843     /* print dependency info */ 
9844     for (kmod_ref 
= (kmod_reference_t 
*) summary
->reference_list
;  
9846          kmod_ref 
= kmod_ref
->next
) { 
9847         kmod_info_t 
* rinfo
; 
9849         if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) { 
9850             (*printf_func
)("            kmod dependency scan stopped " 
9851                            "due to missing dependency page: %p\n", kmod_ref
); 
9854         rinfo 
= kmod_ref
->info
; 
9856         if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) { 
9857             (*printf_func
)("            kmod dependency scan stopped " 
9858                            "due to missing kmod page: %p\n", rinfo
); 
9862         if (!rinfo
->address
) { 
9863             continue; // skip fake entries for built-ins 
9866         /* locate UUID in gLoadedKextSummaries */ 
9867         findSummaryUUID(rinfo
->id
, uuid
); 
9869         (*printf_func
)("            dependency: %s(%s)[%s]@%p\n", 
9870                        rinfo
->name
, rinfo
->version
, uuid
, rinfo
->address
); 
9876 /******************************************************************************* 
9877 * substitute() looks at an input string (a pointer within a larger buffer) 
9878 * for a match to a substring, and on match it writes the marker & substitution 
9879 * character to an output string, updating the scan (from) and 
9880 * output (to) indexes as appropriate. 
9881 *******************************************************************************/ 
9882 static int substitute( 
9883     const char * scan_string
, 
9885     uint32_t   * to_index
, 
9886     uint32_t   * from_index
, 
9887     const char * substring
, 
9891 /* string_out must be at least KMOD_MAX_NAME bytes. 
9895     const char * scan_string
, 
9897     uint32_t   * to_index
, 
9898     uint32_t   * from_index
, 
9899     const char * substring
, 
9903     uint32_t substring_length 
= strnlen(substring
, KMOD_MAX_NAME 
- 1); 
9905    /* On a substring match, append the marker (if there is one) and then 
9906     * the substitution character, updating the output (to) index accordingly. 
9907     * Then update the input (from) length by the length of the substring 
9908     * that got replaced. 
9910     if (!strncmp(scan_string
, substring
, substring_length
)) { 
9912             string_out
[(*to_index
)++] = marker
; 
9914         string_out
[(*to_index
)++] = substitution
; 
9915         (*from_index
) += substring_length
; 
9921 /******************************************************************************* 
9922 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least 
9923 * KMOD_MAX_NAME characters and performs various substitutions of common 
9924 * prefixes & substrings as defined by tables in kext_panic_report.h. 
9925 *******************************************************************************/ 
9926 static void compactIdentifier( 
9927     const char * identifier
, 
9928     char       * identifier_out
, 
9929     char      ** identifier_out_end
); 
9933     const char * identifier
, 
9934     char       * identifier_out
, 
9935     char      ** identifier_out_end
) 
9937     uint32_t       from_index
, to_index
; 
9938     uint32_t       scan_from_index 
= 0; 
9939     uint32_t       scan_to_index   
= 0; 
9940     subs_entry_t 
* subs_entry    
= NULL
; 
9943     from_index 
= to_index 
= 0; 
9944     identifier_out
[0] = '\0'; 
9946    /* Replace certain identifier prefixes with shorter @+character sequences. 
9947     * Check the return value of substitute() so we only replace the prefix. 
9949     for (subs_entry 
= &kext_identifier_prefix_subs
[0]; 
9950          subs_entry
->substring 
&& !did_sub
; 
9953         did_sub 
= substitute(identifier
, identifier_out
, 
9954             &scan_to_index
, &scan_from_index
, 
9955             subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
); 
9959    /* Now scan through the identifier looking for the common substrings 
9960     * and replacing them with shorter !+character sequences via substitute(). 
9962     for (/* see above */; 
9963          scan_from_index 
< KMOD_MAX_NAME 
- 1 && identifier
[scan_from_index
]; 
9966         const char   * scan_string 
= &identifier
[scan_from_index
]; 
9970         if (scan_from_index
) { 
9971             for (subs_entry 
= &kext_identifier_substring_subs
[0]; 
9972                  subs_entry
->substring 
&& !did_sub
; 
9975                 did_sub 
= substitute(scan_string
, identifier_out
, 
9976                     &scan_to_index
, &scan_from_index
, 
9977                     subs_entry
->substring
, '!', subs_entry
->substitute
); 
9981        /* If we didn't substitute, copy the input character to the output. 
9984             identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++]; 
9988     identifier_out
[scan_to_index
] = '\0'; 
9989     if (identifier_out_end
) { 
9990         *identifier_out_end 
= &identifier_out
[scan_to_index
]; 
9996 /******************************************************************************* 
9997 * assemble_identifier_and_version() adds to a string buffer a compacted 
9998 * bundle identifier followed by a version string. 
9999 *******************************************************************************/ 
10001 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length. 
10003 static int assemble_identifier_and_version( 
10004     kmod_info_t 
* kmod_info
,  
10005     char        * identPlusVers
); 
10007 assemble_identifier_and_version( 
10008     kmod_info_t 
* kmod_info
,  
10009     char        * identPlusVers
) 
10013     compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
); 
10014     result 
= strnlen(identPlusVers
, KMOD_MAX_NAME 
- 1); 
10015     identPlusVers
[result
++] = '\t';  // increment for real char 
10016     identPlusVers
[result
] = '\0';    // don't increment for nul char 
10017     result 
= strlcat(identPlusVers
, kmod_info
->version
, KMOD_MAX_NAME
); 
10022 /******************************************************************************* 
10023 * Assumes sKextLock is held. 
10024 *******************************************************************************/ 
10027 OSKext::saveLoadedKextPanicListTyped( 
10028     const char * prefix
, 
10032     uint32_t     list_size
, 
10033     uint32_t   * list_length_ptr
) 
10035     uint32_t      result 
= 0; 
10037     unsigned int  count
, i
; 
10039     count 
= sLoadedKexts
->getCount(); 
10046         OSObject    
* rawKext 
= sLoadedKexts
->getObject(i
); 
10047         OSKext      
* theKext 
= OSDynamicCast(OSKext
, rawKext
); 
10049         char          identPlusVers
[2*KMOD_MAX_NAME
]; 
10050         uint32_t      identPlusVersLength
; 
10053             printf("OSKext::saveLoadedKextPanicListTyped - " 
10054                 "NULL kext in loaded kext list; continuing\n"); 
10059             printf("OSKext::saveLoadedKextPanicListTyped - " 
10060                 "Kext type cast failed in loaded kext list; continuing\n"); 
10064        /* Skip all built-in kexts. 
10066         if (theKext
->isKernelComponent()) { 
10070         kmod_info_t 
* kmod_info 
= theKext
->kmod_info
; 
10072        /* Filter for kmod name (bundle identifier). 
10074         match 
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
)); 
10075         if ((match 
&& invertFlag
) || (!match 
&& !invertFlag
)) { 
10079        /* Filter for libraries (kexts that have a compatible version). 
10081         if ((libsFlag 
== 0 && theKext
->getCompatibleVersion() > 1) || 
10082             (libsFlag 
== 1 && theKext
->getCompatibleVersion() < 1)) { 
10088             !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) { 
10090             printf("kext scan stopped due to missing kmod_info page: %p\n", 
10096         identPlusVersLength 
= assemble_identifier_and_version(kmod_info
, 
10098         if (!identPlusVersLength
) { 
10099             printf("error saving loaded kext info\n"); 
10103        /* Adding 1 for the newline. 
10105         if (*list_length_ptr 
+ identPlusVersLength 
+ 1 >= list_size
) { 
10109         *list_length_ptr 
= strlcat(paniclist
, identPlusVers
, list_size
); 
10110         *list_length_ptr 
= strlcat(paniclist
, "\n", list_size
); 
10116         if (*list_length_ptr 
+ 1 <= list_size
) { 
10117             result 
= list_size 
- (*list_length_ptr 
+ 1); 
10124 /********************************************************************* 
10125 *********************************************************************/ 
10128 OSKext::saveLoadedKextPanicList(void) 
10130     char     * newlist        
= NULL
; 
10131     uint32_t   newlist_size   
= 0; 
10132     uint32_t   newlist_length 
= 0; 
10134     newlist_length 
= 0; 
10135     newlist_size 
= KEXT_PANICLIST_SIZE
; 
10136     newlist 
= (char *)kalloc(newlist_size
); 
10139         OSKextLog(/* kext */ NULL
, 
10140             kOSKextLogErrorLevel 
| kOSKextLogGeneralFlag
, 
10141             "Couldn't allocate kext panic log buffer."); 
10147     // non-"com.apple." kexts 
10148     if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1, 
10149         /* libs? */ -1, newlist
, newlist_size
, &newlist_length
)) { 
10153     // "com.apple." nonlibrary kexts 
10154     if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 
10155         /* libs? */ 0, newlist
, newlist_size
, &newlist_length
)) { 
10159     // "com.apple." library kexts 
10160     if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 
10161         /* libs? */ 1, newlist
, newlist_size
, &newlist_length
)) { 
10166     if (loaded_kext_paniclist
) { 
10167         kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
); 
10169     loaded_kext_paniclist 
= newlist
; 
10170     loaded_kext_paniclist_size 
= newlist_size
; 
10171     loaded_kext_paniclist_length 
= newlist_length
; 
10177 /********************************************************************* 
10178 * Assumes sKextLock is held. 
10179 *********************************************************************/ 
10181 OSKext::savePanicString(bool isLoading
) 
10186         return;  // do not goto finish here b/c of lock 
10189     len 
= assemble_identifier_and_version(kmod_info
, 
10190         (isLoading
) ? last_loaded_str 
: last_unloaded_str
); 
10192         printf("error saving unloaded kext info\n"); 
10197         last_loaded_strlen 
= len
; 
10198         last_loaded_address 
= (void *)kmod_info
->address
; 
10199         last_loaded_size 
= kmod_info
->size
; 
10200         clock_get_uptime(&last_loaded_timestamp
); 
10202         last_unloaded_strlen 
= len
; 
10203         last_unloaded_address 
= (void *)kmod_info
->address
; 
10204         last_unloaded_size 
= kmod_info
->size
; 
10205         clock_get_uptime(&last_unloaded_timestamp
); 
10212 /********************************************************************* 
10213 *********************************************************************/ 
10216 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...)) 
10218     if (last_loaded_strlen
) { 
10219         printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n", 
10220             AbsoluteTime_to_scalar(&last_loaded_timestamp
), 
10221             last_loaded_strlen
, last_loaded_str
, 
10222             last_loaded_address
, last_loaded_size
); 
10225     if (last_unloaded_strlen
) { 
10226         printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n", 
10227             AbsoluteTime_to_scalar(&last_unloaded_timestamp
), 
10228             last_unloaded_strlen
, last_unloaded_str
, 
10229             last_unloaded_address
, last_unloaded_size
); 
10232     printf_func("loaded kexts:\n"); 
10233     if (loaded_kext_paniclist 
&& 
10234         pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) && 
10235         loaded_kext_paniclist
[0]) { 
10237         printf_func("%.*s", loaded_kext_paniclist_length
, loaded_kext_paniclist
); 
10239         printf_func("(none)\n"); 
10244 /********************************************************************* 
10245 * Assumes sKextLock is held. 
10246 *********************************************************************/ 
10249 OSKext::updateLoadedKextSummaries(void) 
10251     kern_return_t result 
= KERN_FAILURE
; 
10252     OSKextLoadedKextSummaryHeader 
*summaryHeader 
= NULL
; 
10253     OSKextLoadedKextSummaryHeader 
*summaryHeaderAlloc 
= NULL
; 
10255     vm_map_offset_t start
, end
; 
10256     size_t summarySize 
= 0; 
10262     IOLockLock(sKextSummariesLock
); 
10264     count 
= sLoadedKexts
->getCount(); 
10265     for (i 
= 0, numKexts 
= 0; i 
< count
; ++i
) { 
10266         aKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
10267         numKexts 
+= (aKext 
&& aKext
->isExecutable()); 
10270     if (!numKexts
) goto finish
; 
10272    /* Calculate the size needed for the new summary headers. 
10275     size 
= sizeof(*gLoadedKextSummaries
); 
10276     size 
+= numKexts 
* sizeof(*gLoadedKextSummaries
->summaries
); 
10277     size 
= round_page(size
); 
10279    /* If the previous summary is large enough, use it (and be sure to make 
10280     * it writable). If it's too small, free it and allocate a new buffer. 
10283     if (sPrevLoadedKextSummariesAllocSize 
< size
) { 
10284         if (sPrevLoadedKextSummaries
) { 
10285             kmem_free(kernel_map
, (vm_offset_t
)sPrevLoadedKextSummaries
, 
10286                 sPrevLoadedKextSummariesAllocSize
); 
10287             sPrevLoadedKextSummaries 
= NULL
; 
10288             sPrevLoadedKextSummariesAllocSize 
= 0; 
10291         result 
= kmem_alloc(kernel_map
,  
10292             (vm_offset_t
*)&summaryHeaderAlloc
, size
); 
10293         if (result 
!= KERN_SUCCESS
) goto finish
; 
10295         summaryHeader 
= summaryHeaderAlloc
; 
10296         summarySize 
= size
; 
10298         summaryHeader 
= sPrevLoadedKextSummaries
; 
10299         summarySize 
= sPrevLoadedKextSummariesAllocSize
; 
10301         start 
= (vm_map_offset_t
) summaryHeader
; 
10302         end 
= start 
+ summarySize
; 
10305    /* Populate the summary header. 
10308     bzero(summaryHeader
, summarySize
); 
10309     summaryHeader
->version 
= kOSKextLoadedKextSummaryVersion
; 
10310     summaryHeader
->entry_size 
= sizeof(OSKextLoadedKextSummary
); 
10311     summaryHeader
->numSummaries 
= numKexts
; 
10313    /* Populate each kext summary. 
10316     count 
= sLoadedKexts
->getCount(); 
10317     for (i 
= 0, j 
= 0; i 
< count
; ++i
) { 
10318         aKext 
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
)); 
10319         if (!aKext 
|| !aKext
->isExecutable()) continue; 
10321         aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]); 
10324    /* Write protect the buffer and move it into place. 
10327     start 
= (vm_map_offset_t
) summaryHeader
; 
10328     end 
= start 
+ summarySize
; 
10330     sPrevLoadedKextSummaries 
= gLoadedKextSummaries
; 
10331     sPrevLoadedKextSummariesAllocSize 
= sLoadedKextSummariesAllocSize
; 
10333     gLoadedKextSummaries 
= summaryHeader
; 
10334     sLoadedKextSummariesAllocSize 
= summarySize
; 
10336     summaryHeaderAlloc 
= NULL
; 
10338    /* Call the magic breakpoint function through a static function pointer so 
10339     * the compiler can't optimize the function away. 
10341     if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)(); 
10344     IOLockUnlock(sKextSummariesLock
); 
10346    /* If we had to allocate a new buffer but failed to generate the summaries, 
10349     if (summaryHeaderAlloc
) { 
10350         kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
); 
10356 /********************************************************************* 
10357 *********************************************************************/ 
10359 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary 
*summary
) 
10363     strlcpy(summary
->name
, getIdentifierCString(),  
10364         sizeof(summary
->name
)); 
10368         memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
)); 
10369         OSSafeRelease(uuid
); 
10372     summary
->address 
= kmod_info
->address
; 
10373     summary
->size 
= kmod_info
->size
; 
10374     summary
->version 
= getVersion(); 
10375     summary
->loadTag 
= kmod_info
->id
; 
10376     summary
->flags 
= 0; 
10377     summary
->reference_list 
= (uint64_t) kmod_info
->reference_list
; 
10382 /********************************************************************* 
10383 *********************************************************************/ 
10387 OSKext::getKmodInfo( 
10388     kmod_info_array_t      
* kmodList
, 
10389     mach_msg_type_number_t 
* kmodCount
) 
10391     kern_return_t      result 
= KERN_FAILURE
; 
10392     vm_offset_t        data   
= 0; 
10393     kmod_info_t      
* k
, * kmod_info_scan_ptr
; 
10394     kmod_reference_t 
* r
, * ref_scan_ptr
; 
10398     *kmodList 
= (kmod_info_t 
*)0; 
10401     IORecursiveLockLock(sKextLock
); 
10405         size 
+= sizeof(kmod_info_t
); 
10406         r 
= k
->reference_list
; 
10408             size 
+=sizeof(kmod_reference_t
); 
10414         result 
= KERN_SUCCESS
; 
10418     result 
= kmem_alloc(kernel_map
, &data
, size
); 
10419     if (result 
!= KERN_SUCCESS
) { 
10423    /* Copy each kmod_info struct sequentially into the data buffer. 
10424     * Set each struct's nonzero 'next' pointer back to itself as a sentinel; 
10425     * the kernel space address is used to match refs, and a zero 'next' flags 
10426     * the end of kmod_infos in the data buffer and the beginning of references. 
10429     kmod_info_scan_ptr 
= (kmod_info_t 
*)data
; 
10431         *kmod_info_scan_ptr 
= *k
; 
10433             kmod_info_scan_ptr
->next 
= k
; 
10435         kmod_info_scan_ptr
++; 
10439    /* Now add references after the kmod_info structs in the same buffer. 
10440     * Update each kmod_info with the ref_count so we can associate 
10441     * references with kmod_info structs. 
10444     ref_scan_ptr 
= (kmod_reference_t 
*)kmod_info_scan_ptr
; 
10445     kmod_info_scan_ptr 
= (kmod_info_t 
*)data
; 
10447         r 
= k
->reference_list
; 
10450            /* Note the last kmod_info in the data buffer has its next == 0. 
10451             * Since there can only be one like that,  
10452             * this case is handled by the caller. 
10454             *ref_scan_ptr 
= *r
; 
10459        /* Stuff the # of refs into the 'reference_list' field of the kmod_info 
10460         * struct for the client to interpret. 
10462         kmod_info_scan_ptr
->reference_list 
= (kmod_reference_t 
*)(long)ref_count
; 
10463         kmod_info_scan_ptr
++; 
10467     result 
= vm_map_copyin(kernel_map
, data
, size
, TRUE
, (vm_map_copy_t 
*)kmodList
); 
10468     if (result 
!= KERN_SUCCESS
) { 
10473     result 
= KERN_SUCCESS
; 
10476     IORecursiveLockUnlock(sKextLock
); 
10478     if (result 
!= KERN_SUCCESS 
&& data
) { 
10479         kmem_free(kernel_map
, data
, size
); 
10480         *kmodList 
= (kmod_info_t 
*)0; 
10485 #endif /* __i386__ */ 
10487 #if CONFIG_KEC_FIPS 
10490 #pragma mark Kernel External Components for FIPS compliance 
10493 /********************************************************************* 
10494  * Kernel External Components for FIPS compliance (KEC_FIPS) 
10495  *********************************************************************/ 
10497 GetAppleTEXTHashForKext(OSKext 
* theKext
, OSDictionary 
*theInfoDict
) 
10499     AppleTEXTHash_t         my_ath 
= {1, 0, NULL
}; 
10500     AppleTEXTHash_t 
*       my_athp 
= NULL
;         // do not release 
10501     OSDictionary 
*          textHashDict 
= NULL
;    // do not release 
10502     OSData 
*                segmentHash 
= NULL
;     // do not release 
10504     if (theKext 
== NULL 
|| theInfoDict 
== NULL
) { 
10508     textHashDict 
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
)); 
10509     if (textHashDict 
== NULL
) { 
10513     segmentHash 
= OSDynamicCast(OSData
, 
10514                                 textHashDict
->getObject(ARCHNAME
)); 
10515     if (segmentHash 
== NULL
) { 
10519     // KEC_FIPS type kexts never unload so we don't have to clean up our  
10521     if (kmem_alloc(kernel_map
, (vm_offset_t 
*) &my_athp
,  
10522                    sizeof(AppleTEXTHash_t
)) != KERN_SUCCESS
) { 
10526     memcpy(my_athp
, &my_ath
, sizeof(my_ath
)); 
10527     my_athp
->ath_length 
= segmentHash
->getLength(); 
10528     if (my_athp
->ath_length 
> 0) { 
10529         my_athp
->ath_hash 
= (void *)segmentHash
->getBytesNoCopy(); 
10534               kOSKextLogErrorLevel 
| 
10535               kOSKextLogGeneralFlag
, 
10536               "Kext %s ath_version %d ath_length %d ath_hash %p", 
10537               theKext
->getIdentifierCString(),  
10538               my_athp
->ath_version
, 
10539               my_athp
->ath_length
, 
10540               my_athp
->ath_hash
);  
10543     return( (void *) my_athp 
); 
10546 #endif // CONFIG_KEC_FIPS