1 /* 2 * Copyright (c) 2008-2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 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. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 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. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 extern "C" { 30 #include <kern/clock.h> 31 #include <kern/host.h> 32 #include <kern/kext_alloc.h> 33 #include <kextd/kextd_mach.h> 34 #include <libkern/kernel_mach_header.h> 35 #include <libkern/kext_panic_report.h> 36 #include <libkern/kext_request_keys.h> 37 #include <libkern/mkext.h> 38 #include <libkern/prelink.h> 39 #include <libkern/version.h> 40 #include <libkern/zlib.h> 41 #include <mach/mach_vm.h> 42 #include <sys/sysctl.h> 43 }; 44 45 #include <libkern/OSKextLibPrivate.h> 46 #include <libkern/c++/OSKext.h> 47 #include <libkern/c++/OSLib.h> 48 49 #include <IOKit/IOLib.h> 50 #include <IOKit/IOCatalogue.h> 51 #include <IOKit/IORegistryEntry.h> 52 #include <IOKit/IOService.h> 53 54 #if PRAGMA_MARK 55 #pragma mark External & Internal Function Protos 56 #endif 57 /********************************************************************* 58 *********************************************************************/ 59 extern "C" { 60 // in libkern/OSKextLib.cpp, not in header for a reason. 61 extern kern_return_t OSKextPingKextd(void); 62 63 extern int IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize); 64 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize); 65 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t * segment); 66 extern void OSRuntimeUnloadCPP(kmod_info_t * ki, void * data); 67 68 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */ 69 } 70 71 static OSReturn _OSKextCreateRequest( 72 const char * predicate, 73 OSDictionary ** requestP); 74 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict); 75 static OSObject * _OSKextGetRequestArgument( 76 OSDictionary * requestDict, 77 const char * argName); 78 static bool _OSKextSetRequestArgument( 79 OSDictionary * requestDict, 80 const char * argName, 81 OSObject * value); 82 static void * _OSKextExtractPointer(OSData * wrapper); 83 static OSReturn _OSDictionarySetCStringValue( 84 OSDictionary * dict, 85 const char * key, 86 const char * value); 87 #if CONFIG_MACF_KEXT 88 static void * MACFCopyModuleDataForKext( 89 OSKext * theKext, 90 mach_msg_type_number_t * datalen); 91 #endif /* CONFIG_MACF_KEXT */ 92 93 #if PRAGMA_MARK 94 #pragma mark Constants & Macros 95 #endif 96 /********************************************************************* 97 * Constants & Macros 98 *********************************************************************/ 99 100 /* A typical Snow Leopard system has a bit under 120 kexts loaded. 101 * Use this number to create containers. 102 */ 103 #define kOSKextTypicalLoadCount (120) 104 105 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict. 106 * A loaded kext will no dependents or external retains will have 2 retains. 107 */ 108 #define kOSKextMinRetainCount (1) 109 #define kOSKextMinLoadedRetainCount (2) 110 111 /********** 112 * Strings and substrings used in dependency resolution. 113 */ 114 #define APPLE_KEXT_PREFIX "com.apple." 115 #define KERNEL_LIB "com.apple.kernel" 116 117 #define PRIVATE_KPI "com.apple.kpi.private" 118 119 /* Version for compatbility pseudokexts (com.apple.kernel.*), 120 * compatible back to v6.0. 121 */ 122 #define KERNEL6_LIB "com.apple.kernel.6.0" 123 #define KERNEL6_VERSION "7.9.9" 124 125 #define KERNEL_LIB_PREFIX "com.apple.kernel." 126 #define KPI_LIB_PREFIX "com.apple.kpi." 127 128 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0) 129 130 /********************************************************************* 131 * infoDict keys for internally-stored data. Saves on ivar slots for 132 * objects we don't keep around past boot time or during active load. 133 *********************************************************************/ 134 135 /* A usable, uncompressed file is stored under this key. 136 */ 137 #define _kOSKextExecutableKey "_OSKextExecutable" 138 139 /* An indirect reference to the executable file from an mkext 140 * is stored under this key. 141 */ 142 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference" 143 144 /* If the file is contained in a larger buffer laid down by the booter or 145 * sent from user space, the OSKext stores that OSData under this key so that 146 * references are properly tracked. This is always an mkext, right now. 147 */ 148 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData" 149 150 #if PRAGMA_MARK 151 #pragma mark Typedefs 152 #endif 153 /********************************************************************* 154 * Typedefs 155 *********************************************************************/ 156 157 /********************************************************************* 158 * MkextEntryRef describes the contents of an OSData object 159 * referencing a file entry from an mkext so that we can uncompress 160 * (if necessary) and extract it on demand. 161 * 162 * It contains the mkextVersion in case we ever wind up supporting 163 * multiple mkext formats. Mkext format 1 is officially retired as of 164 * Snow Leopard. 165 *********************************************************************/ 166 typedef struct MkextEntryRef { 167 mkext_basic_header * mkext; // beginning of whole mkext file 168 void * fileinfo; // mkext2_file_entry or equiv; see mkext.h 169 } MkextEntryRef; 170 171 #if PRAGMA_MARK 172 #pragma mark Global and static Module Variables 173 #endif 174 /********************************************************************* 175 * Global & static variables, used to keep track of kexts. 176 *********************************************************************/ 177 178 static bool sPrelinkBoot = false; 179 static bool sSafeBoot = false; 180 181 /****** 182 * sKextLock is the principal lock for OSKext. Below, there is also an 183 * sKextInnerLock used to guard access to data accessed on in-calls from 184 * IOService. This 2nd lock is required to prevent a deadlock 185 * with IOService calling back into OSKext::considerUnloads() 186 * on a separate thread during a kext load operation. 187 */ 188 static IORecursiveLock * sKextLock = NULL; 189 190 static OSDictionary * sKextsByID = NULL; 191 static OSArray * sLoadedKexts = NULL; 192 193 // Requests to kextd waiting to be picked up. 194 static OSArray * sKernelRequests = NULL; 195 // Identifier of kext load requests in sKernelRequests 196 static OSSet * sPostedKextLoadIdentifiers = NULL; 197 static OSArray * sRequestCallbackRecords = NULL; 198 199 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel 200 static OSSet * sAllKextLoadIdentifiers = NULL; 201 static KXLDContext * sKxldContext = NULL; 202 static uint32_t sNextLoadTag = 0; 203 static uint32_t sNextRequestTag = 0; 204 205 static bool sUserLoadsActive = false; 206 static bool sKextdActive = false; 207 static bool sDeferredLoadSucceeded = false; 208 static bool sConsiderUnloadsExecuted = false; 209 210 static bool sKernelRequestsEnabled = true; 211 static bool sLoadEnabled = true; 212 static bool sUnloadEnabled = true; 213 214 /********************************************************************* 215 * Stuff for the OSKext representing the kernel itself. 216 **********/ 217 static OSKext * sKernelKext = NULL; 218 219 /* Set up a fake kmod_info struct for the kernel. 220 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP() 221 * before OSKext is initialized; that call only needs the name 222 * and address to be set correctly. 223 * 224 * We don't do much else with the kerne's kmod_info; we never 225 * put it into the kmod list, never adjust the reference count, 226 * and never have kernel components reference it. 227 * For that matter, we don't do much with kmod_info structs 228 * at all anymore! We just keep them filled in for gdb and 229 * binary compability. 230 */ 231 kmod_info_t g_kernel_kmod_info = { 232 /* next */ 0, 233 /* info_version */ KMOD_INFO_VERSION, 234 /* id */ 0, // loadTag: kernel is always 0 235 /* name */ kOSKextKernelIdentifier, // bundle identifier 236 /* version */ "0", // filled in in OSKext::initialize() 237 /* reference_count */ -1, // never adjusted; kernel never unloads 238 /* reference_list */ NULL, 239 /* address */ (vm_address_t)&_mh_execute_header, 240 /* size */ 0, // filled in in OSKext::initialize() 241 /* hdr_size */ 0, 242 /* start */ 0, 243 /* stop */ 0 244 }; 245 246 extern "C" { 247 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c, 248 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s, 249 // misc_protos.h, db_low_trace.c, kgmacros 250 // 'kmod' is a holdover from the old kmod system, we can't rename it. 251 kmod_info_t * kmod = NULL; 252 253 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE) 254 255 static char * unloaded_kext_paniclist = NULL; 256 static uint32_t unloaded_kext_paniclist_size = 0; 257 static uint32_t unloaded_kext_paniclist_length = 0; 258 AbsoluteTime last_loaded_timestamp; 259 260 static char * loaded_kext_paniclist = NULL; 261 static uint32_t loaded_kext_paniclist_size = 0; 262 static uint32_t loaded_kext_paniclist_length = 0; 263 AbsoluteTime last_unloaded_timestamp; 264 static void * last_unloaded_address = NULL; 265 #if __LP64__ 266 static uint64_t last_unloaded_size = 0; 267 #else 268 static uint32_t last_unloaded_size = 0; 269 #endif /* __LP64__ */ 270 271 }; 272 273 /********************************************************************* 274 * Because we can start IOService matching from OSKext (via IOCatalogue) 275 * and IOService can call into OSKext, there is potential for cross-lock 276 * contention, so OSKext needs two locks. The regular sKextLock above 277 * guards most OSKext class/static variables, and sKextInnerLock guards 278 * variables that can be accessed on in-calls from IOService, currently: 279 * 280 * * OSKext::considerUnloads() 281 * 282 * Note that sConsiderUnloadsExecuted above belongs to sKextLock! 283 * 284 * When both sKextLock and sKextInnerLock need to be taken, 285 * always lock sKextLock first and unlock it second. Never take both 286 * locks in an entry point to OSKext; if you need to do so, you must 287 * spawn an independent thread to avoid potential deadlocks for threads 288 * calling into OSKext. 289 * 290 * All static variables from here to the closing comment block fall 291 * under sKextInnerLock. 292 **********/ 293 static IORecursiveLock * sKextInnerLock = NULL; 294 295 static bool sAutounloadEnabled = true; 296 static bool sConsiderUnloadsCalled = false; 297 static bool sConsiderUnloadsPending = false; 298 299 static unsigned int sConsiderUnloadDelay = 60; // seconds 300 static thread_call_t sUnloadCallout = 0; 301 static thread_call_t sDestroyLinkContextThread = 0; // one-shot, one-at-a-time thread 302 static bool sSystemSleep = false; // true when system going to sleep 303 304 static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel | 305 kOSKextLogVerboseFlagsMask; 306 static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter; 307 static bool sBootArgLogFilterFound = false; 308 SYSCTL_INT(_debug, OID_AUTO, kextlog, CTLFLAG_RW, &sKernelLogFilter, 309 sKernelLogFilter, "kernel kext logging"); 310 311 static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter; 312 static OSArray * sUserSpaceLogSpecArray = NULL; 313 static OSArray * sUserSpaceLogMessageArray = NULL; 314 315 /********* 316 * End scope for sKextInnerLock-protected variables. 317 *********************************************************************/ 318 319 #if PRAGMA_MARK 320 #pragma mark OSData callbacks (need to move to OSData) 321 #endif 322 /********************************************************************* 323 * C functions used for callbacks. 324 *********************************************************************/ 325 extern "C" { 326 void osdata_kmem_free(void * ptr, unsigned int length) { 327 kmem_free(kernel_map, (vm_address_t)ptr, length); 328 return; 329 } 330 331 void osdata_phys_free(void * ptr, unsigned int length) { 332 ml_static_mfree((vm_offset_t)ptr, length); 333 return; 334 } 335 336 void osdata_vm_deallocate(void * ptr, unsigned int length) 337 { 338 (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length); 339 return; 340 } 341 }; 342 343 #if PRAGMA_MARK 344 #pragma mark KXLD Allocation Callback 345 #endif 346 /********************************************************************* 347 * KXLD Allocation Callback 348 *********************************************************************/ 349 kxld_addr_t 350 kern_allocate( 351 u_long size, 352 KXLDAllocateFlags * flags, 353 void * user_data) 354 { 355 vm_address_t result = 0; // returned 356 kern_return_t mach_result = KERN_FAILURE; 357 bool success = false; 358 OSKext * theKext = (OSKext *)user_data; 359 u_long roundSize = round_page(size); 360 OSData * linkBuffer = NULL; // must release 361 362 mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE); 363 if (mach_result != KERN_SUCCESS) { 364 OSKextLog(theKext, 365 kOSKextLogErrorLevel | 366 kOSKextLogGeneralFlag, 367 "Can't allocate kernel memory to link %s.", 368 theKext->getIdentifierCString()); 369 goto finish; 370 } 371 372 /* Create an OSData wrapper for the allocated buffer. 373 * Note that we do not set a dealloc function on it here. 374 * We have to call vm_map_unwire() on it in OSKext::unload() 375 * and an OSData dealloc function can't take all those parameters. 376 */ 377 linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize); 378 if (!linkBuffer) { 379 OSKextLog(theKext, 380 kOSKextLogErrorLevel | 381 kOSKextLogGeneralFlag, 382 "Can't allocate linked executable wrapper for %s.", 383 theKext->getIdentifierCString()); 384 goto finish; 385 } 386 387 OSKextLog(theKext, 388 kOSKextLogProgressLevel | 389 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 390 "Allocated link buffer for kext %s at %p (%lu bytes).", 391 theKext->getIdentifierCString(), 392 (void *)result, (unsigned long)roundSize); 393 394 theKext->setLinkedExecutable(linkBuffer); 395 396 *flags = kKxldAllocateWritable; 397 success = true; 398 399 finish: 400 if (!success && result) { 401 kext_free(result, roundSize); 402 result = 0; 403 } 404 405 OSSafeRelease(linkBuffer); 406 407 return (kxld_addr_t)result; 408 } 409 410 /********************************************************************* 411 *********************************************************************/ 412 void 413 kxld_log_callback( 414 KXLDLogSubsystem subsystem, 415 KXLDLogLevel level, 416 const char * format, 417 va_list argList, 418 void * user_data) 419 { 420 OSKext *theKext = (OSKext *) user_data; 421 OSKextLogSpec logSpec = 0; 422 423 switch (subsystem) { 424 case kKxldLogLinking: 425 logSpec |= kOSKextLogLinkFlag; 426 break; 427 case kKxldLogPatching: 428 logSpec |= kOSKextLogPatchFlag; 429 break; 430 } 431 432 switch (level) { 433 case kKxldLogExplicit: 434 logSpec |= kOSKextLogExplicitLevel; 435 break; 436 case kKxldLogErr: 437 logSpec |= kOSKextLogErrorLevel; 438 break; 439 case kKxldLogWarn: 440 logSpec |= kOSKextLogWarningLevel; 441 break; 442 case kKxldLogBasic: 443 logSpec |= kOSKextLogProgressLevel; 444 break; 445 case kKxldLogDetail: 446 logSpec |= kOSKextLogDetailLevel; 447 break; 448 case kKxldLogDebug: 449 logSpec |= kOSKextLogDebugLevel; 450 break; 451 } 452 453 OSKextVLog(theKext, logSpec, format, argList); 454 } 455 456 #if PRAGMA_MARK 457 #pragma mark Module Config (Startup & Shutdown) 458 #endif 459 /********************************************************************* 460 * Module Config (Class Definition & Class Methods) 461 *********************************************************************/ 462 #define super OSObject 463 OSDefineMetaClassAndStructors(OSKext, OSObject) 464 465 /********************************************************************* 466 *********************************************************************/ 467 /* static */ 468 void 469 OSKext::initialize(void) 470 { 471 OSData * kernelExecutable = NULL; // do not release 472 u_char * kernelStart = NULL; // do not free 473 size_t kernelLength = 0; 474 OSString * scratchString = NULL; // must release 475 IORegistryEntry * registryRoot = NULL; // do not release 476 OSNumber * kernelCPUType = NULL; // must release 477 OSNumber * kernelCPUSubtype = NULL; // must release 478 OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter; 479 bool setResult = false; 480 uint64_t * timestamp = 0; 481 char bootArgBuffer[16]; // for PE_parse_boot_argn w/strings 482 483 /* This must be the first thing allocated. Everything else grabs this lock. 484 */ 485 sKextLock = IORecursiveLockAlloc(); 486 sKextInnerLock = IORecursiveLockAlloc(); 487 assert(sKextLock); 488 assert(sKextInnerLock); 489 490 sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount); 491 sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 492 sKernelRequests = OSArray::withCapacity(0); 493 sPostedKextLoadIdentifiers = OSSet::withCapacity(0); 494 sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount); 495 sRequestCallbackRecords = OSArray::withCapacity(0); 496 assert(sKextsByID && sLoadedKexts && sKernelRequests && 497 sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers && 498 sRequestCallbackRecords); 499 500 /* Read the log flag boot-args and set the log flags. 501 */ 502 if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof("kextlog=0x00000000 "))) { 503 sBootArgLogFilterFound = true; 504 sKernelLogFilter = bootLogFilter; 505 // log this if any flags are set 506 OSKextLog(/* kext */ NULL, 507 kOSKextLogBasicLevel | 508 kOSKextLogFlagsMask, 509 "Kernel kext log filter 0x%x per kextlog boot arg.", 510 (unsigned)sKernelLogFilter); 511 } 512 513 sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer, 514 sizeof(bootArgBuffer)) ? true : false; 515 516 if (sSafeBoot) { 517 OSKextLog(/* kext */ NULL, 518 kOSKextLogWarningLevel | 519 kOSKextLogGeneralFlag, 520 "SAFE BOOT DETECTED - " 521 "only valid OSBundleRequired kexts will be loaded."); 522 } 523 524 /* Set up an OSKext instance to represent the kernel itself. 525 */ 526 sKernelKext = new OSKext; 527 assert(sKernelKext); 528 529 kernelStart = (u_char *)&_mh_execute_header; 530 kernelLength = getlastaddr() - (vm_offset_t)kernelStart; 531 kernelExecutable = OSData::withBytesNoCopy( 532 kernelStart, kernelLength); 533 assert(kernelExecutable); 534 535 sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0 536 sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier); 537 538 sKernelKext->version = OSKextParseVersionString(osrelease); 539 sKernelKext->compatibleVersion = sKernelKext->version; 540 sKernelKext->linkedExecutable = kernelExecutable; 541 // linkState will be set first time we do a link 542 543 sKernelKext->flags.hasAllDependencies = 1; 544 sKernelKext->flags.kernelComponent = 1; 545 sKernelKext->flags.prelinked = 0; 546 sKernelKext->flags.loaded = 1; 547 sKernelKext->flags.started = 1; 548 sKernelKext->flags.CPPInitialized = 0; 549 550 sKernelKext->kmod_info = &g_kernel_kmod_info; 551 strlcpy(g_kernel_kmod_info.version, osrelease, 552 sizeof(g_kernel_kmod_info.version)); 553 g_kernel_kmod_info.size = kernelLength; 554 g_kernel_kmod_info.id = sKernelKext->loadTag; 555 556 /* Cons up an info dict, so we don't have to have special-case 557 * checking all over. 558 */ 559 sKernelKext->infoDict = OSDictionary::withCapacity(5); 560 assert(sKernelKext->infoDict); 561 setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey, 562 sKernelKext->bundleID); 563 assert(setResult); 564 setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey, 565 kOSBooleanTrue); 566 assert(setResult); 567 568 scratchString = OSString::withCStringNoCopy(osrelease); 569 assert(scratchString); 570 setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey, 571 scratchString); 572 assert(setResult); 573 OSSafeReleaseNULL(scratchString); 574 575 scratchString = OSString::withCStringNoCopy("mach_kernel"); 576 assert(scratchString); 577 setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey, 578 scratchString); 579 assert(setResult); 580 OSSafeReleaseNULL(scratchString); 581 582 /* Add the kernel kext to the bookkeeping dictionaries. Note that 583 * the kernel kext doesn't have a kmod_info struct. copyInfo() 584 * gathers info from other places anyhow. 585 */ 586 setResult = sKextsByID->setObject(sKernelKext->bundleID, sKernelKext); 587 assert(setResult); 588 setResult = sLoadedKexts->setObject(sKernelKext); 589 assert(setResult); 590 sKernelKext->release(); 591 592 registryRoot = IORegistryEntry::getRegistryRoot(); 593 kernelCPUType = OSNumber::withNumber( 594 (long long unsigned int)_mh_execute_header.cputype, 595 8 * sizeof(_mh_execute_header.cputype)); 596 kernelCPUSubtype = OSNumber::withNumber( 597 (long long unsigned int)_mh_execute_header.cpusubtype, 598 8 * sizeof(_mh_execute_header.cpusubtype)); 599 assert(registryRoot && kernelCPUSubtype && kernelCPUType); 600 601 registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType); 602 registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype); 603 604 OSSafeRelease(kernelCPUType); 605 OSSafeRelease(kernelCPUSubtype); 606 607 timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp); 608 *timestamp = 0; 609 timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp); 610 *timestamp = 0; 611 612 OSKextLog(/* kext */ NULL, 613 kOSKextLogProgressLevel | 614 kOSKextLogGeneralFlag, 615 "Kext system initialized."); 616 617 return; 618 } 619 620 /********************************************************************* 621 * This could be in OSKextLib.cpp but we need to hold a lock 622 * while removing all the segments and sKextLock will do. 623 *********************************************************************/ 624 /* static */ 625 OSReturn 626 OSKext::removeKextBootstrap(void) 627 { 628 OSReturn result = kOSReturnError; 629 630 static bool alreadyDone = false; 631 boolean_t keepsyms = FALSE; 632 633 const char * dt_kernel_header_name = "Kernel-__HEADER"; 634 const char * dt_kernel_symtab_name = "Kernel-__SYMTAB"; 635 kernel_mach_header_t * dt_mach_header = NULL; 636 int dt_mach_header_size = 0; 637 struct symtab_command * dt_symtab = NULL; 638 int dt_symtab_size = 0; 639 int dt_result = 0; 640 641 kernel_segment_command_t * seg_to_remove = NULL; 642 #if __ppc__ || __arm__ 643 const char * dt_segment_name = NULL; 644 void * segment_paddress = NULL; 645 int segment_size = 0; 646 #endif 647 648 /* This must be the very first thing done by this function. 649 */ 650 IORecursiveLockLock(sKextLock); 651 652 /* If we already did this, it's a success. 653 */ 654 if (alreadyDone) { 655 result = kOSReturnSuccess; 656 goto finish; 657 } 658 659 OSKextLog(/* kext */ NULL, 660 kOSKextLogProgressLevel | 661 kOSKextLogGeneralFlag, 662 "Jettisoning kext bootstrap segments."); 663 664 PE_parse_boot_argn("keepsyms", &keepsyms, sizeof(keepsyms)); 665 666 /***** 667 * Dispose of unnecessary stuff that the booter didn't need to load. 668 */ 669 dt_result = IODTGetLoaderInfo(dt_kernel_header_name, 670 (void **)&dt_mach_header, &dt_mach_header_size); 671 if (dt_result == 0 && dt_mach_header) { 672 IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header, 673 round_page_32(dt_mach_header_size)); 674 } 675 dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name, 676 (void **)&dt_symtab, &dt_symtab_size); 677 if (dt_result == 0 && dt_symtab) { 678 IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab, 679 round_page_32(dt_symtab_size)); 680 } 681 682 /***** 683 * KLD bootstrap segment. 684 */ 685 // xxx - should rename KLD segment 686 seg_to_remove = getsegbyname("__KLD"); 687 if (seg_to_remove) { 688 OSRuntimeUnloadCPPForSegment(seg_to_remove); 689 } 690 691 #if __ppc__ || __arm__ 692 /* Free the memory that was set up by bootx. 693 */ 694 dt_segment_name = "Kernel-__KLD"; 695 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) { 696 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 697 (int)segment_size); 698 } 699 #elif __i386__ || __x86_64__ 700 /* On x86, use the mapping data from the segment load command to 701 * unload KLD directly. 702 * This may invalidate any assumptions about "avail_start" 703 * defining the lower bound for valid physical addresses. 704 */ 705 if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) { 706 ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize); 707 } 708 #else 709 #error arch 710 #endif 711 712 seg_to_remove = NULL; 713 714 /***** 715 * Prelinked kernel's symtab (if there is one). 716 */ 717 kernel_section_t * sect; 718 sect = getsectbyname("__PRELINK", "__symtab"); 719 if (sect && sect->addr && sect->size) { 720 ml_static_mfree(sect->addr, sect->size); 721 } 722 723 /***** 724 * Dump the LINKEDIT segment, unless keepsyms is set. 725 */ 726 if (!keepsyms) { 727 seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT"); 728 if (seg_to_remove) { 729 OSRuntimeUnloadCPPForSegment(seg_to_remove); 730 } 731 732 #if __ppc__ || __arm__ 733 dt_segment_name = "Kernel-__LINKEDIT"; 734 if (0 == IODTGetLoaderInfo(dt_segment_name, 735 &segment_paddress, &segment_size)) { 736 737 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 738 (int)segment_size); 739 } 740 #elif __i386__ || __x86_64__ 741 if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) { 742 ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize); 743 } 744 #else 745 #error arch 746 #endif 747 } else { 748 OSKextLog(/* kext */ NULL, 749 kOSKextLogBasicLevel | 750 kOSKextLogGeneralFlag, 751 "keepsyms boot arg specified; keeping linkedit segment for symbols."); 752 } 753 754 seg_to_remove = NULL; 755 756 alreadyDone = true; 757 result = kOSReturnSuccess; 758 759 finish: 760 761 /* This must be the very last thing done before returning. 762 */ 763 IORecursiveLockUnlock(sKextLock); 764 765 return result; 766 } 767 768 /********************************************************************* 769 *********************************************************************/ 770 void 771 OSKext::flushNonloadedKexts( 772 Boolean flushPrelinkedKexts) 773 { 774 OSSet * prelinkedKexts = NULL; // must release 775 OSCollectionIterator * kextIterator = NULL; // must release 776 OSCollectionIterator * prelinkIterator = NULL; // must release 777 const OSSymbol * thisID = NULL; // do not release 778 OSKext * thisKext = NULL; // do not release 779 uint32_t count, i; 780 781 IORecursiveLockLock(sKextLock); 782 783 OSKextLog(/* kext */ NULL, 784 kOSKextLogProgressLevel | 785 kOSKextLogKextBookkeepingFlag, 786 "Flushing nonloaded kexts and other unused data."); 787 788 OSKext::considerDestroyingLinkContext(); 789 790 /* If we aren't flushing unused prelinked kexts, we have to put them 791 * aside while we flush everything else so make a container for them. 792 */ 793 if (!flushPrelinkedKexts) { 794 prelinkedKexts = OSSet::withCapacity(0); 795 if (!prelinkedKexts) { 796 goto finish; 797 } 798 } 799 800 /* Set aside prelinked kexts (in-use or not) and break 801 * any lingering inter-kext references for nonloaded kexts 802 * so they have min. retain counts. 803 */ 804 kextIterator = OSCollectionIterator::withCollection(sKextsByID); 805 if (!kextIterator) { 806 goto finish; 807 } 808 809 while ((thisID = OSDynamicCast(OSSymbol, 810 kextIterator->getNextObject()))) { 811 812 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 813 814 if (thisKext) { 815 if (prelinkedKexts && thisKext->isPrelinked()) { 816 prelinkedKexts->setObject(thisKext); 817 } 818 thisKext->flushDependencies(/* forceIfLoaded */ false); 819 } 820 } 821 822 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly. 823 */ 824 sKextsByID->flushCollection(); 825 826 /* Now put the loaded kexts back into the ID dictionary. 827 */ 828 count = sLoadedKexts->getCount(); 829 for (i = 0; i < count; i++) { 830 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 831 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 832 } 833 834 /* Finally, put back the prelinked kexts if we saved any. 835 */ 836 if (prelinkedKexts) { 837 prelinkIterator = OSCollectionIterator::withCollection(prelinkedKexts); 838 if (!prelinkIterator) { 839 goto finish; 840 } 841 842 while ((thisKext = OSDynamicCast(OSKext, 843 prelinkIterator->getNextObject()))) { 844 845 sKextsByID->setObject(thisKext->getIdentifierCString(), 846 thisKext); 847 } 848 } 849 850 finish: 851 IORecursiveLockUnlock(sKextLock); 852 853 OSSafeRelease(prelinkedKexts); 854 OSSafeRelease(kextIterator); 855 OSSafeRelease(prelinkIterator); 856 857 return; 858 } 859 860 /********************************************************************* 861 *********************************************************************/ 862 /* static */ 863 void 864 OSKext::setKextdActive(Boolean active) 865 { 866 IORecursiveLockLock(sKextLock); 867 sKextdActive = active; 868 if (sKernelRequests->getCount()) { 869 OSKextPingKextd(); 870 } 871 IORecursiveLockUnlock(sKextLock); 872 873 return; 874 } 875 876 /********************************************************************* 877 *********************************************************************/ 878 /* static */ 879 void 880 OSKext::setDeferredLoadSucceeded(Boolean succeeded) 881 { 882 IORecursiveLockLock(sKextLock); 883 sDeferredLoadSucceeded = succeeded; 884 IORecursiveLockUnlock(sKextLock); 885 886 return; 887 } 888 889 /********************************************************************* 890 * Called from IOSystemShutdownNotification. 891 *********************************************************************/ 892 /* static */ 893 void 894 OSKext::willShutdown(void) 895 { 896 OSReturn checkResult = kOSReturnError; 897 OSDictionary * exitRequest = NULL; // must release 898 899 IORecursiveLockLock(sKextLock); 900 901 OSKext::setLoadEnabled(false); 902 OSKext::setUnloadEnabled(false); 903 OSKext::setAutounloadsEnabled(false); 904 OSKext::setKernelRequestsEnabled(false); 905 906 OSKextLog(/* kext */ NULL, 907 kOSKextLogProgressLevel | 908 kOSKextLogGeneralFlag, 909 "System shutdown; requesting immediate kextd exit."); 910 911 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit, 912 &exitRequest); 913 if (checkResult != kOSReturnSuccess) { 914 goto finish; 915 } 916 if (!sKernelRequests->setObject(exitRequest)) { 917 goto finish; 918 } 919 920 OSKextPingKextd(); 921 922 finish: 923 IORecursiveLockUnlock(sKextLock); 924 925 OSSafeRelease(exitRequest); 926 return; 927 } 928 929 /********************************************************************* 930 *********************************************************************/ 931 /* static */ 932 bool 933 OSKext::getLoadEnabled(void) 934 { 935 bool result; 936 937 IORecursiveLockLock(sKextLock); 938 result = sLoadEnabled; 939 IORecursiveLockUnlock(sKextLock); 940 return result; 941 } 942 943 /********************************************************************* 944 *********************************************************************/ 945 /* static */ 946 bool 947 OSKext::setLoadEnabled(bool flag) 948 { 949 bool result; 950 951 IORecursiveLockLock(sKextLock); 952 result = sLoadEnabled; 953 sLoadEnabled = (flag ? true : false); 954 955 if (sLoadEnabled != result) { 956 OSKextLog(/* kext */ NULL, 957 kOSKextLogBasicLevel | 958 kOSKextLogLoadFlag, 959 "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis"); 960 } 961 962 IORecursiveLockUnlock(sKextLock); 963 964 return result; 965 } 966 967 /********************************************************************* 968 *********************************************************************/ 969 /* static */ 970 bool 971 OSKext::getUnloadEnabled(void) 972 { 973 bool result; 974 975 IORecursiveLockLock(sKextLock); 976 result = sUnloadEnabled; 977 IORecursiveLockUnlock(sKextLock); 978 return result; 979 } 980 981 /********************************************************************* 982 *********************************************************************/ 983 /* static */ 984 bool 985 OSKext::setUnloadEnabled(bool flag) 986 { 987 bool result; 988 989 IORecursiveLockLock(sKextLock); 990 result = sUnloadEnabled; 991 sUnloadEnabled = (flag ? true : false); 992 IORecursiveLockUnlock(sKextLock); 993 994 if (sUnloadEnabled != result) { 995 OSKextLog(/* kext */ NULL, 996 kOSKextLogBasicLevel | 997 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 998 "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis"); 999 } 1000 1001 return result; 1002 } 1003 1004 /********************************************************************* 1005 * Do not call any function that takes sKextLock here! 1006 *********************************************************************/ 1007 /* static */ 1008 bool 1009 OSKext::getAutounloadEnabled(void) 1010 { 1011 bool result; 1012 1013 IORecursiveLockLock(sKextInnerLock); 1014 result = sAutounloadEnabled ? true : false; 1015 IORecursiveLockUnlock(sKextInnerLock); 1016 return result; 1017 } 1018 1019 /********************************************************************* 1020 * Do not call any function that takes sKextLock here! 1021 *********************************************************************/ 1022 /* static */ 1023 bool 1024 OSKext::setAutounloadsEnabled(bool flag) 1025 { 1026 bool result; 1027 1028 IORecursiveLockLock(sKextInnerLock); 1029 1030 result = sAutounloadEnabled; 1031 sAutounloadEnabled = (flag ? true : false); 1032 if (!sAutounloadEnabled && sUnloadCallout) { 1033 thread_call_cancel(sUnloadCallout); 1034 } 1035 1036 if (sAutounloadEnabled != result) { 1037 OSKextLog(/* kext */ NULL, 1038 kOSKextLogBasicLevel | 1039 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1040 "Kext autounloading now %sabled.", 1041 sAutounloadEnabled ? "en" : "dis"); 1042 } 1043 1044 IORecursiveLockUnlock(sKextInnerLock); 1045 1046 return result; 1047 } 1048 1049 /********************************************************************* 1050 *********************************************************************/ 1051 /* instance method operating on OSKext field */ 1052 bool 1053 OSKext::setAutounloadEnabled(bool flag) 1054 { 1055 bool result = flags.autounloadEnabled ? true : false; 1056 flags.autounloadEnabled = flag ? 1 : 0; 1057 1058 if (result != (flag ? true : false)) { 1059 OSKextLog(this, 1060 kOSKextLogProgressLevel | 1061 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 1062 "Autounloading for kext %s now %sabled.", 1063 getIdentifierCString(), 1064 flags.autounloadEnabled ? "en" : "dis"); 1065 } 1066 return result; 1067 } 1068 1069 /********************************************************************* 1070 *********************************************************************/ 1071 /* static */ 1072 bool 1073 OSKext::setKernelRequestsEnabled(bool flag) 1074 { 1075 bool result; 1076 1077 IORecursiveLockLock(sKextLock); 1078 result = sKernelRequestsEnabled; 1079 sKernelRequestsEnabled = flag ? true : false; 1080 1081 if (sKernelRequestsEnabled != result) { 1082 OSKextLog(/* kext */ NULL, 1083 kOSKextLogBasicLevel | 1084 kOSKextLogGeneralFlag, 1085 "Kernel requests now %sabled.", 1086 sKernelRequestsEnabled ? "en" : "dis"); 1087 } 1088 IORecursiveLockUnlock(sKextLock); 1089 return result; 1090 } 1091 1092 /********************************************************************* 1093 *********************************************************************/ 1094 /* static */ 1095 bool 1096 OSKext::getKernelRequestsEnabled(void) 1097 { 1098 bool result; 1099 1100 IORecursiveLockLock(sKextLock); 1101 result = sKernelRequestsEnabled; 1102 IORecursiveLockUnlock(sKextLock); 1103 return result; 1104 } 1105 1106 #if PRAGMA_MARK 1107 #pragma mark Kext Life Cycle 1108 #endif 1109 /********************************************************************* 1110 *********************************************************************/ 1111 OSKext * 1112 OSKext::withPrelinkedInfoDict( 1113 OSDictionary * anInfoDict) 1114 { 1115 OSKext * newKext = new OSKext; 1116 1117 if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict)) { 1118 newKext->release(); 1119 return NULL; 1120 } 1121 1122 return newKext; 1123 } 1124 1125 /********************************************************************* 1126 *********************************************************************/ 1127 bool 1128 OSKext::initWithPrelinkedInfoDict( 1129 OSDictionary * anInfoDict) 1130 { 1131 bool result = false; 1132 kern_return_t alloc_result = KERN_SUCCESS; 1133 OSString * kextPath = NULL; // do not release 1134 OSNumber * addressNum = NULL; // reused; do not release 1135 OSNumber * lengthNum = NULL; // reused; do not release 1136 void * data = NULL; // do not free 1137 void * srcData = NULL; // do not free 1138 OSData * prelinkedExecutable = NULL; // must release 1139 void * linkStateCopy = NULL; // kmem_free on error 1140 uint32_t linkStateLength = 0; 1141 uint32_t length = 0; // reused 1142 1143 if (!super::init()) { 1144 goto finish; 1145 } 1146 1147 /* Get the path. Don't look for an arch-specific path property. 1148 */ 1149 kextPath = OSDynamicCast(OSString, 1150 anInfoDict->getObject(kPrelinkBundlePathKey)); 1151 1152 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 1153 goto finish; 1154 } 1155 1156 /* Don't need the path to be in the info dictionary any more. 1157 */ 1158 anInfoDict->removeObject(kPrelinkBundlePathKey); 1159 1160 /* If we have a link state, create an OSData wrapper for it. 1161 */ 1162 addressNum = OSDynamicCast(OSNumber, 1163 anInfoDict->getObject(kPrelinkLinkStateKey)); 1164 if (addressNum) { 1165 lengthNum = OSDynamicCast(OSNumber, 1166 anInfoDict->getObject(kPrelinkLinkStateSizeKey)); 1167 if (!lengthNum) { 1168 OSKextLog(this, 1169 kOSKextLogErrorLevel | 1170 kOSKextLogArchiveFlag, 1171 "Kext %s can't find prelinked kext link state size.", 1172 getIdentifierCString()); 1173 goto finish; 1174 } 1175 1176 data = (void *) (intptr_t) (addressNum->unsigned64BitValue()); 1177 linkStateLength = (uint32_t) (lengthNum->unsigned32BitValue()); 1178 1179 anInfoDict->removeObject(kPrelinkLinkStateKey); 1180 anInfoDict->removeObject(kPrelinkLinkStateSizeKey); 1181 1182 /* Copy the link state out of the booter-provided memory so it is in 1183 * the VM system and we can page it out. 1184 */ 1185 alloc_result = kmem_alloc_pageable(kernel_map, 1186 (vm_offset_t *)&linkStateCopy, linkStateLength); 1187 if (alloc_result != KERN_SUCCESS) { 1188 OSKextLog(this, 1189 kOSKextLogErrorLevel | 1190 kOSKextLogArchiveFlag, 1191 "Kext %s failed to copy prelinked link state.", 1192 getIdentifierCString()); 1193 goto finish; 1194 } 1195 memcpy(linkStateCopy, data, linkStateLength); 1196 1197 linkState = OSData::withBytesNoCopy(linkStateCopy, linkStateLength); 1198 if (!linkState) { 1199 OSKextLog(this, 1200 kOSKextLogErrorLevel | 1201 kOSKextLogArchiveFlag, 1202 "Kext %s failed to create link state wrapper.", 1203 getIdentifierCString()); 1204 goto finish; 1205 } 1206 linkState->setDeallocFunction(osdata_kmem_free); 1207 1208 /* Clear linkStateCopy; the OSData owns it now so we mustn't free it. 1209 */ 1210 linkStateCopy = NULL; 1211 } 1212 1213 /* Create an OSData wrapper around the linked executable. 1214 */ 1215 addressNum = OSDynamicCast(OSNumber, 1216 anInfoDict->getObject(kPrelinkExecutableLoadKey)); 1217 if (addressNum) { 1218 lengthNum = OSDynamicCast(OSNumber, 1219 anInfoDict->getObject(kPrelinkExecutableSizeKey)); 1220 if (!lengthNum) { 1221 OSKextLog(this, 1222 kOSKextLogErrorLevel | 1223 kOSKextLogArchiveFlag, 1224 "Kext %s can't find prelinked kext executable size.", 1225 getIdentifierCString()); 1226 goto finish; 1227 } 1228 1229 data = (void *) (intptr_t) (addressNum->unsigned64BitValue()); 1230 length = (uint32_t) (lengthNum->unsigned32BitValue()); 1231 1232 anInfoDict->removeObject(kPrelinkExecutableLoadKey); 1233 anInfoDict->removeObject(kPrelinkExecutableSizeKey); 1234 1235 /* If the kext's load address differs from its source address, allocate 1236 * space in the kext map at the load address and copy the kext over. 1237 */ 1238 addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey)); 1239 if (addressNum) { 1240 srcData = (void *) (intptr_t) (addressNum->unsigned64BitValue()); 1241 1242 if (data != srcData) { 1243 #if __LP64__ 1244 alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE); 1245 if (alloc_result != KERN_SUCCESS) { 1246 OSKextLog(this, 1247 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 1248 "Failed to allocate space for prelinked kext %s.", 1249 getIdentifierCString()); 1250 goto finish; 1251 } 1252 memcpy(data, srcData, length); 1253 #else 1254 OSKextLog(this, 1255 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 1256 "Error: prelinked kext %s - source and load addresses " 1257 "differ on ILP32 architecture.", 1258 getIdentifierCString()); 1259 goto finish; 1260 #endif /* __LP64__ */ 1261 } 1262 1263 anInfoDict->removeObject(kPrelinkExecutableSourceKey); 1264 } 1265 1266 /* We don't need to set a dealloc function for the linked executable 1267 * because it is freed separately in OSKext::unload(), which must unwire 1268 * part of the memory. 1269 * xxx - do we *have* to do it that way? 1270 */ 1271 prelinkedExecutable = OSData::withBytesNoCopy(data, length); 1272 if (!prelinkedExecutable) { 1273 OSKextLog(this, 1274 kOSKextLogErrorLevel | 1275 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1276 "Kext %s failed to create executable wrapper.", 1277 getIdentifierCString()); 1278 goto finish; 1279 } 1280 setLinkedExecutable(prelinkedExecutable); 1281 1282 addressNum = OSDynamicCast(OSNumber, 1283 anInfoDict->getObject(kPrelinkKmodInfoKey)); 1284 if (!addressNum) { 1285 OSKextLog(this, 1286 kOSKextLogErrorLevel | 1287 kOSKextLogArchiveFlag, 1288 "Kext %s can't find prelinked kext kmod_info address.", 1289 getIdentifierCString()); 1290 goto finish; 1291 } 1292 1293 kmod_info = (kmod_info_t *) (intptr_t) (addressNum->unsigned64BitValue()); 1294 1295 anInfoDict->removeObject(kPrelinkKmodInfoKey); 1296 } 1297 1298 /* If the plist has a UUID for an interface, save that off. 1299 */ 1300 if (isInterface()) { 1301 interfaceUUID = OSDynamicCast(OSData, 1302 anInfoDict->getObject(kPrelinkInterfaceUUIDKey)); 1303 if (interfaceUUID) { 1304 interfaceUUID->retain(); 1305 anInfoDict->removeObject(kPrelinkInterfaceUUIDKey); 1306 } 1307 } 1308 1309 flags.prelinked = true; 1310 1311 /* If we created a kext from prelink info, 1312 * we must be booting from a prelinked kernel. 1313 */ 1314 sPrelinkBoot = true; 1315 1316 result = registerIdentifier(); 1317 1318 finish: 1319 1320 /* If we didn't hand linkStateCopy off to an OSData, free it. 1321 */ 1322 if (linkStateCopy) { 1323 kmem_free(kernel_map, (vm_offset_t)linkStateCopy, linkStateLength); 1324 } 1325 1326 OSSafeRelease(prelinkedExecutable); 1327 1328 return result; 1329 } 1330 1331 /********************************************************************* 1332 *********************************************************************/ 1333 OSKext * 1334 OSKext::withBooterData( 1335 OSString * deviceTreeName, 1336 OSData * booterData) 1337 { 1338 OSKext * newKext = new OSKext; 1339 1340 if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) { 1341 newKext->release(); 1342 return NULL; 1343 } 1344 1345 return newKext; 1346 } 1347 1348 /********************************************************************* 1349 *********************************************************************/ 1350 typedef struct _BooterKextFileInfo { 1351 uint32_t infoDictPhysAddr; 1352 uint32_t infoDictLength; 1353 uint32_t executablePhysAddr; 1354 uint32_t executableLength; 1355 uint32_t bundlePathPhysAddr; 1356 uint32_t bundlePathLength; 1357 } _BooterKextFileInfo; 1358 1359 bool 1360 OSKext::initWithBooterData( 1361 OSString * deviceTreeName, 1362 OSData * booterData) 1363 { 1364 bool result = false; 1365 _BooterKextFileInfo * kextFileInfo = NULL; // do not free 1366 char * infoDictAddr = NULL; // do not free 1367 void * executableAddr = NULL; // do not free 1368 char * bundlePathAddr = NULL; // do not free 1369 1370 OSObject * parsedXML = NULL; // must release 1371 OSDictionary * theInfoDict = NULL; // do not release 1372 OSString * kextPath = NULL; // must release 1373 OSString * errorString = NULL; // must release 1374 OSData * executable = NULL; // must release 1375 1376 if (!super::init()) { 1377 goto finish; 1378 } 1379 1380 kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy(); 1381 if (!kextFileInfo) { 1382 OSKextLog(this, 1383 kOSKextLogErrorLevel | 1384 kOSKextLogGeneralFlag, 1385 "No booter-provided data for kext device tree entry %s.", 1386 deviceTreeName->getCStringNoCopy()); 1387 goto finish; 1388 } 1389 1390 /* The info plist must exist or we can't read the kext. 1391 */ 1392 if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) { 1393 OSKextLog(this, 1394 kOSKextLogErrorLevel | 1395 kOSKextLogGeneralFlag, 1396 "No kext info dictionary for booter device tree entry %s.", 1397 deviceTreeName->getCStringNoCopy()); 1398 goto finish; 1399 } 1400 1401 infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 1402 if (!infoDictAddr) { 1403 OSKextLog(this, 1404 kOSKextLogErrorLevel | 1405 kOSKextLogGeneralFlag, 1406 "Can't translate physical address 0x%x of kext info dictionary " 1407 "for device tree entry %s.", 1408 (int)kextFileInfo->infoDictPhysAddr, 1409 deviceTreeName->getCStringNoCopy()); 1410 goto finish; 1411 } 1412 1413 parsedXML = OSUnserializeXML(infoDictAddr, &errorString); 1414 if (parsedXML) { 1415 theInfoDict = OSDynamicCast(OSDictionary, parsedXML); 1416 } 1417 if (!theInfoDict) { 1418 const char * errorCString = "(unknown error)"; 1419 1420 if (errorString && errorString->getCStringNoCopy()) { 1421 errorCString = errorString->getCStringNoCopy(); 1422 } else if (parsedXML) { 1423 errorCString = "not a dictionary"; 1424 } 1425 OSKextLog(this, 1426 kOSKextLogErrorLevel | 1427 kOSKextLogGeneralFlag, 1428 "Error unserializing info dictionary for device tree entry %s: %s.", 1429 deviceTreeName->getCStringNoCopy(), errorCString); 1430 goto finish; 1431 } 1432 1433 /* A bundle path is not mandatory. 1434 */ 1435 if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) { 1436 bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr); 1437 if (!bundlePathAddr) { 1438 OSKextLog(this, 1439 kOSKextLogErrorLevel | 1440 kOSKextLogGeneralFlag, 1441 "Can't translate physical address 0x%x of kext bundle path " 1442 "for device tree entry %s.", 1443 (int)kextFileInfo->bundlePathPhysAddr, 1444 deviceTreeName->getCStringNoCopy()); 1445 goto finish; 1446 } 1447 bundlePathAddr[kextFileInfo->bundlePathLength-1] = '\0'; // just in case! 1448 1449 kextPath = OSString::withCString(bundlePathAddr); 1450 if (!kextPath) { 1451 OSKextLog(this, 1452 kOSKextLogErrorLevel | 1453 kOSKextLogGeneralFlag, 1454 "Failed to create wrapper for device tree entry %s kext path %s.", 1455 deviceTreeName->getCStringNoCopy(), bundlePathAddr); 1456 goto finish; 1457 } 1458 } 1459 1460 if (!setInfoDictionaryAndPath(theInfoDict, kextPath)) { 1461 goto finish; 1462 } 1463 1464 /* An executable is not mandatory. 1465 */ 1466 if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) { 1467 executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr); 1468 if (!executableAddr) { 1469 OSKextLog(this, 1470 kOSKextLogErrorLevel | 1471 kOSKextLogGeneralFlag, 1472 "Can't translate physical address 0x%x of kext executable " 1473 "for device tree entry %s.", 1474 (int)kextFileInfo->executablePhysAddr, 1475 deviceTreeName->getCStringNoCopy()); 1476 goto finish; 1477 } 1478 1479 executable = OSData::withBytesNoCopy(executableAddr, 1480 kextFileInfo->executableLength); 1481 if (!executable) { 1482 OSKextLog(this, 1483 kOSKextLogErrorLevel | 1484 kOSKextLogGeneralFlag, 1485 "Failed to create executable wrapper for device tree entry %s.", 1486 deviceTreeName->getCStringNoCopy()); 1487 goto finish; 1488 } 1489 1490 /* A kext with an executable needs to retain the whole booterData 1491 * object to keep the executable in memory. 1492 */ 1493 if (!setExecutable(executable, booterData)) { 1494 OSKextLog(this, 1495 kOSKextLogErrorLevel | 1496 kOSKextLogGeneralFlag, 1497 "Failed to set kext executable for device tree entry %s.", 1498 deviceTreeName->getCStringNoCopy()); 1499 goto finish; 1500 } 1501 } 1502 1503 result = registerIdentifier(); 1504 1505 finish: 1506 OSSafeRelease(parsedXML); 1507 OSSafeRelease(kextPath); 1508 OSSafeRelease(errorString); 1509 OSSafeRelease(executable); 1510 1511 return result; 1512 } 1513 1514 /********************************************************************* 1515 *********************************************************************/ 1516 bool 1517 OSKext::registerIdentifier(void) 1518 { 1519 bool result = false; 1520 OSKext * existingKext = NULL; // do not release 1521 bool existingIsLoaded = false; 1522 bool existingIsPrelinked = false; 1523 OSKextVersion newVersion = -1; 1524 OSKextVersion existingVersion = -1; 1525 char newVersionCString[kOSKextVersionMaxLength]; 1526 char existingVersionCString[kOSKextVersionMaxLength]; 1527 OSData * newUUID = NULL; // must release 1528 OSData * existingUUID = NULL; // must release 1529 1530 /* Get the new kext's version for checks & log messages. 1531 */ 1532 newVersion = getVersion(); 1533 OSKextVersionGetString(newVersion, newVersionCString, 1534 kOSKextVersionMaxLength); 1535 1536 /* If we don't have an existing kext with this identifier, 1537 * just record the new kext and we're done! 1538 */ 1539 existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)); 1540 if (!existingKext) { 1541 sKextsByID->setObject(bundleID, this); 1542 result = true; 1543 goto finish; 1544 } 1545 1546 /* Get the existing kext's version for checks & log messages. 1547 */ 1548 existingVersion = existingKext->getVersion(); 1549 OSKextVersionGetString(existingVersion, 1550 existingVersionCString, kOSKextVersionMaxLength); 1551 1552 existingIsLoaded = existingKext->isLoaded(); 1553 existingIsPrelinked = existingKext->isPrelinked(); 1554 1555 /* If we have a kext with this identifier that's already loaded/prelinked, 1556 * we can't use the new one, but let's be really thorough and check how 1557 * the two are related for a precise diagnostic log message. 1558 * 1559 * Note that user space can't find out about nonloaded prelinked kexts, 1560 * so in this case we log a message when new & existing are equivalent 1561 * at the step rather than warning level, because we are always going 1562 * be getting a copy of the kext in the user load request mkext. 1563 */ 1564 if (existingIsLoaded || existingIsPrelinked) { 1565 bool sameVersion = (newVersion == existingVersion); 1566 bool sameExecutable = true; // assume true unless we have UUIDs 1567 1568 /* Only get the UUID if the existing kext is loaded. Doing so 1569 * might have to uncompress an mkext executable and we shouldn't 1570 * take that hit when neither kext is loaded. 1571 */ 1572 newUUID = copyUUID(); 1573 existingUUID = existingKext->copyUUID(); 1574 1575 /* I'm entirely too paranoid about checking equivalence of executables, 1576 * but I remember nasty problems with it in the past. 1577 * 1578 * - If we have UUIDs for both kexts, compare them. 1579 * - If only one kext has a UUID, they're definitely different. 1580 */ 1581 if (newUUID && existingUUID) { 1582 sameExecutable = newUUID->isEqualTo(existingUUID); 1583 } else if (newUUID || existingUUID) { 1584 sameExecutable = false; 1585 } 1586 1587 if (!newUUID && !existingUUID) { 1588 1589 /* If there are no UUIDs, we can't really tell that the executables 1590 * are *different* without a lot of work; the loaded kext's 1591 * unrelocated executable is no longer around (and we never had it 1592 * in-kernel for a prelinked kext). We certainly don't want to do 1593 * a whole fake link for the new kext just to compare, either. 1594 */ 1595 1596 OSKextVersionGetString(version, newVersionCString, 1597 sizeof(newVersionCString)); 1598 OSKextLog(this, 1599 kOSKextLogWarningLevel | 1600 kOSKextLogKextBookkeepingFlag, 1601 "Notice - new kext %s, v%s matches %s kext " 1602 "but can't determine if executables are the same (no UUIDs).", 1603 getIdentifierCString(), 1604 newVersionCString, 1605 (existingIsLoaded ? "loaded" : "prelinked")); 1606 } 1607 1608 if (sameVersion && sameExecutable) { 1609 OSKextLog(this, 1610 (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) | 1611 kOSKextLogKextBookkeepingFlag, 1612 "Refusing new kext %s, v%s: a %s copy is already present " 1613 "(same version and executable).", 1614 getIdentifierCString(), newVersionCString, 1615 (existingIsLoaded ? "loaded" : "prelinked")); 1616 } else { 1617 if (!sameVersion) { 1618 /* This condition is significant so log it under warnings. 1619 */ 1620 OSKextLog(this, 1621 kOSKextLogWarningLevel | 1622 kOSKextLogKextBookkeepingFlag, 1623 "Refusing new kext %s, v%s: already have %s v%s.", 1624 getIdentifierCString(), 1625 newVersionCString, 1626 (existingIsLoaded ? "loaded" : "prelinked"), 1627 existingVersionCString); 1628 } else { 1629 /* This condition is significant so log it under warnings. 1630 */ 1631 OSKextLog(this, 1632 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 1633 "Refusing new kext %s, v%s: a %s copy with a different " 1634 "executable UUID is already present.", 1635 getIdentifierCString(), newVersionCString, 1636 (existingIsLoaded ? "loaded" : "prelinked")); 1637 } 1638 } 1639 goto finish; 1640 } /* if (existingIsLoaded || existingIsPrelinked) */ 1641 1642 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether 1643 * user loads are happening or if we're still in early boot. User agents are 1644 * supposed to resolve dependencies topside and include only the exact 1645 * kexts needed; so we always accept the new kext (in fact we should never 1646 * see an older unloaded copy hanging around). 1647 */ 1648 if (sUserLoadsActive) { 1649 sKextsByID->setObject(bundleID, this); 1650 result = true; 1651 1652 OSKextLog(this, 1653 kOSKextLogStepLevel | 1654 kOSKextLogKextBookkeepingFlag, 1655 "Dropping old copy of kext %s (v%s) for newly-added (v%s).", 1656 getIdentifierCString(), 1657 existingVersionCString, 1658 newVersionCString); 1659 1660 goto finish; 1661 } 1662 1663 /* During early boot, the kext with the highest version always wins out. 1664 * Prelinked kernels will never hit this, but mkexts and booter-read 1665 * kexts might have duplicates. 1666 */ 1667 if (newVersion > existingVersion) { 1668 sKextsByID->setObject(bundleID, this); 1669 result = true; 1670 1671 OSKextLog(this, 1672 kOSKextLogStepLevel | 1673 kOSKextLogKextBookkeepingFlag, 1674 "Dropping lower version (v%s) of registered kext %s for higher (v%s).", 1675 existingVersionCString, 1676 getIdentifierCString(), 1677 newVersionCString); 1678 1679 } else { 1680 OSKextLog(this, 1681 kOSKextLogStepLevel | 1682 kOSKextLogKextBookkeepingFlag, 1683 "Kext %s is already registered with a higher/same version (v%s); " 1684 "dropping newly-added (v%s).", 1685 getIdentifierCString(), 1686 existingVersionCString, 1687 newVersionCString); 1688 } 1689 1690 /* result has been set appropriately by now. */ 1691 1692 finish: 1693 1694 if (result) { 1695 OSKextLog(this, 1696 kOSKextLogStepLevel | 1697 kOSKextLogKextBookkeepingFlag, 1698 "Kext %s, v%s registered and available for loading.", 1699 getIdentifierCString(), newVersionCString); 1700 } 1701 1702 OSSafeRelease(newUUID); 1703 OSSafeRelease(existingUUID); 1704 1705 return result; 1706 } 1707 1708 /********************************************************************* 1709 * Does the bare minimum validation to look up a kext. 1710 * All other validation is done on the spot as needed. 1711 * 1712 * No need for lock, only called from init 1713 **********************************************************************/ 1714 bool 1715 OSKext::setInfoDictionaryAndPath( 1716 OSDictionary * aDictionary, 1717 OSString * aPath) 1718 { 1719 bool result = false; 1720 OSString * bundleIDString = NULL; // do not release 1721 OSString * versionString = NULL; // do not release 1722 OSString * compatibleVersionString = NULL; // do not release 1723 const char * versionCString = NULL; // do not free 1724 const char * compatibleVersionCString = NULL; // do not free 1725 OSBoolean * scratchBool = NULL; // do not release 1726 1727 if (infoDict) { 1728 panic("Attempt to set info dictionary on a kext " 1729 "that already has one (%s).", 1730 getIdentifierCString()); 1731 } 1732 1733 if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) { 1734 goto finish; 1735 } 1736 1737 infoDict = aDictionary; 1738 infoDict->retain(); 1739 1740 /* Check right away if the info dictionary has any log flags. 1741 */ 1742 scratchBool = OSDynamicCast(OSBoolean, 1743 getPropertyForHostArch(kOSBundleEnableKextLoggingKey)); 1744 if (scratchBool == kOSBooleanTrue) { 1745 flags.loggingEnabled = 1; 1746 } 1747 1748 /* The very next thing to get is the bundle identifier. Unlike 1749 * in user space, a kext with no bundle identifier gets axed 1750 * immediately. 1751 */ 1752 bundleIDString = OSDynamicCast(OSString, 1753 getPropertyForHostArch(kCFBundleIdentifierKey)); 1754 if (!bundleIDString) { 1755 OSKextLog(this, 1756 kOSKextLogErrorLevel | 1757 kOSKextLogValidationFlag, 1758 "CFBundleIdentifier missing/invalid type in kext %s.", 1759 aPath ? aPath->getCStringNoCopy() : "(unknown)"); 1760 goto finish; 1761 } 1762 bundleID = OSSymbol::withString(bundleIDString); 1763 if (!bundleID) { 1764 OSKextLog(this, 1765 kOSKextLogErrorLevel | 1766 kOSKextLogValidationFlag, 1767 "Can't copy bundle identifier as symbol for kext %s.", 1768 bundleIDString->getCStringNoCopy()); 1769 goto finish; 1770 } 1771 1772 /* Save the path if we got one (it should always be available but it's 1773 * just something nice to have for bookkeeping). 1774 */ 1775 if (aPath) { 1776 path = aPath; 1777 path->retain(); 1778 } 1779 1780 /***** 1781 * Minimal validation to initialize. We'll do other validation on the spot. 1782 */ 1783 if (bundleID->getLength() >= KMOD_MAX_NAME) { 1784 OSKextLog(this, 1785 kOSKextLogErrorLevel | 1786 kOSKextLogValidationFlag, 1787 "Kext %s error - CFBundleIdentifier over max length %d.", 1788 getIdentifierCString(), KMOD_MAX_NAME - 1); 1789 goto finish; 1790 } 1791 1792 version = compatibleVersion = -1; 1793 1794 versionString = OSDynamicCast(OSString, 1795 getPropertyForHostArch(kCFBundleVersionKey)); 1796 if (!versionString) { 1797 OSKextLog(this, 1798 kOSKextLogErrorLevel | 1799 kOSKextLogValidationFlag, 1800 "Kext %s error - CFBundleVersion missing/invalid type.", 1801 getIdentifierCString()); 1802 goto finish; 1803 } 1804 versionCString = versionString->getCStringNoCopy(); 1805 version = OSKextParseVersionString(versionCString); 1806 if (version < 0) { 1807 OSKextLog(this, 1808 kOSKextLogErrorLevel | 1809 kOSKextLogValidationFlag, 1810 "Kext %s error - CFBundleVersion bad value '%s'.", 1811 getIdentifierCString(), versionCString); 1812 goto finish; 1813 } 1814 1815 compatibleVersion = -1; // set to illegal value for kexts that don't have 1816 1817 compatibleVersionString = OSDynamicCast(OSString, 1818 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 1819 if (compatibleVersionString) { 1820 compatibleVersionCString = compatibleVersionString->getCStringNoCopy(); 1821 compatibleVersion = OSKextParseVersionString(compatibleVersionCString); 1822 if (compatibleVersion < 0) { 1823 OSKextLog(this, 1824 kOSKextLogErrorLevel | 1825 kOSKextLogValidationFlag, 1826 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.", 1827 getIdentifierCString(), compatibleVersionCString); 1828 goto finish; 1829 } 1830 1831 if (compatibleVersion > version) { 1832 OSKextLog(this, 1833 kOSKextLogErrorLevel | 1834 kOSKextLogValidationFlag, 1835 "Kext %s error - %s %s > %s %s (must be <=).", 1836 getIdentifierCString(), 1837 kOSBundleCompatibleVersionKey, compatibleVersionCString, 1838 kCFBundleVersionKey, versionCString); 1839 goto finish; 1840 } 1841 } 1842 1843 /* Set flags for later use if the infoDict gets flushed. We only 1844 * check for true values, not false ones(!) 1845 */ 1846 scratchBool = OSDynamicCast(OSBoolean, 1847 getPropertyForHostArch(kOSBundleIsInterfaceKey)); 1848 if (scratchBool && scratchBool->isTrue()) { 1849 flags.interface = 1; 1850 } 1851 1852 scratchBool = OSDynamicCast(OSBoolean, 1853 getPropertyForHostArch(kOSKernelResourceKey)); 1854 if (scratchBool && scratchBool->isTrue()) { 1855 flags.kernelComponent = 1; 1856 flags.interface = 1; // xxx - hm. the kernel itself isn't an interface... 1857 flags.started = 1; 1858 1859 /* A kernel component has one implicit dependency on the kernel. 1860 */ 1861 flags.hasAllDependencies = 1; 1862 } 1863 1864 result = true; 1865 1866 finish: 1867 1868 return result; 1869 } 1870 1871 /********************************************************************* 1872 * Not used for prelinked kernel boot as there is no unrelocated 1873 * executable. 1874 *********************************************************************/ 1875 bool 1876 OSKext::setExecutable( 1877 OSData * anExecutable, 1878 OSData * externalData, 1879 bool externalDataIsMkext) 1880 { 1881 bool result = false; 1882 const char * executableKey = NULL; // do not free 1883 1884 if (!anExecutable) { 1885 infoDict->removeObject(_kOSKextExecutableKey); 1886 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 1887 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 1888 result = true; 1889 goto finish; 1890 } 1891 1892 if (infoDict->getObject(_kOSKextExecutableKey) || 1893 infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) { 1894 1895 panic("Attempt to set an executable on a kext " 1896 "that already has one (%s).", 1897 getIdentifierCString()); 1898 goto finish; 1899 } 1900 1901 if (externalDataIsMkext) { 1902 executableKey = _kOSKextMkextExecutableReferenceKey; 1903 } else { 1904 executableKey = _kOSKextExecutableKey; 1905 } 1906 1907 if (anExecutable) { 1908 infoDict->setObject(executableKey, anExecutable); 1909 if (externalData) { 1910 infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData); 1911 } 1912 } 1913 1914 result = true; 1915 1916 finish: 1917 return result; 1918 } 1919 1920 /********************************************************************* 1921 *********************************************************************/ 1922 void 1923 OSKext::free(void) 1924 { 1925 if (isLoaded()) { 1926 panic("Attempt to free loaded kext %s.", getIdentifierCString()); 1927 } 1928 1929 OSSafeRelease(infoDict); 1930 OSSafeRelease(bundleID); 1931 OSSafeRelease(path); 1932 OSSafeRelease(dependencies); 1933 OSSafeRelease(linkState); 1934 OSSafeRelease(linkedExecutable); 1935 OSSafeRelease(metaClasses); 1936 OSSafeRelease(interfaceUUID); 1937 1938 if (isInterface() && kmod_info) { 1939 kfree(kmod_info, sizeof(kmod_info_t)); 1940 } 1941 1942 super::free(); 1943 return; 1944 } 1945 1946 #if PRAGMA_MARK 1947 #pragma mark Mkext files 1948 #endif 1949 /********************************************************************* 1950 *********************************************************************/ 1951 OSReturn 1952 OSKext::readMkextArchive(OSData * mkextData, 1953 uint32_t * checksumPtr) 1954 { 1955 OSReturn result = kOSKextReturnBadData; 1956 uint32_t mkextLength = 0; 1957 mkext_header * mkextHeader = 0; // do not free 1958 uint32_t mkextVersion = 0; 1959 1960 /* Note default return of kOSKextReturnBadData above. 1961 */ 1962 mkextLength = mkextData->getLength(); 1963 if (mkextLength < sizeof(mkext_basic_header)) { 1964 OSKextLog(/* kext */ NULL, 1965 kOSKextLogErrorLevel | 1966 kOSKextLogArchiveFlag, 1967 "Mkext archive too small to be valid."); 1968 goto finish; 1969 } 1970 1971 mkextHeader = (mkext_header *)mkextData->getBytesNoCopy(); 1972 1973 if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC || 1974 MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) { 1975 OSKextLog(/* kext */ NULL, 1976 kOSKextLogErrorLevel | 1977 kOSKextLogArchiveFlag, 1978 "Mkext archive has invalid magic or signature."); 1979 goto finish; 1980 } 1981 1982 if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) { 1983 OSKextLog(/* kext */ NULL, 1984 kOSKextLogErrorLevel | 1985 kOSKextLogArchiveFlag, 1986 "Mkext archive recorded length doesn't match actual file length."); 1987 goto finish; 1988 } 1989 1990 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 1991 1992 if (mkextVersion == MKEXT_VERS_2) { 1993 result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr); 1994 } else if (mkextVersion == MKEXT_VERS_1) { 1995 result = OSKext::readMkext1Archive(mkextData, checksumPtr); 1996 } else { 1997 OSKextLog(/* kext */ NULL, 1998 kOSKextLogErrorLevel | 1999 kOSKextLogArchiveFlag, 2000 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion); 2001 result = kOSKextReturnUnsupported; 2002 } 2003 2004 finish: 2005 return result; 2006 } 2007 2008 /********************************************************************* 2009 * Assumes magic, signature, version, length have been checked. 2010 * 2011 * Doesn't do as much bounds-checking as it should, but we're dropping 2012 * mkext1 support from the kernel for SnowLeopard soon. 2013 * 2014 * Should keep track of all kexts created so far, and if we hit a 2015 * fatal error halfway through, remove those kexts. If we've dropped 2016 * an older version that had already been read, whoops! Might want to 2017 * add a level of buffering? 2018 *********************************************************************/ 2019 /* static */ 2020 OSReturn 2021 OSKext::readMkext1Archive( 2022 OSData * mkextData, 2023 uint32_t * checksumPtr) 2024 { 2025 OSReturn result = kOSReturnError; 2026 uint32_t mkextLength; 2027 mkext1_header * mkextHeader = 0; // do not free 2028 void * mkextEnd = 0; // do not free 2029 uint32_t mkextVersion; 2030 uint8_t * crc_address = 0; 2031 uint32_t checksum; 2032 uint32_t numKexts = 0; 2033 2034 OSData * infoDictDataObject = NULL; // must release 2035 OSObject * parsedXML = NULL; // must release 2036 OSDictionary * infoDict = NULL; // do not release 2037 OSString * errorString = NULL; // must release 2038 OSData * mkextExecutableInfo = NULL; // must release 2039 OSKext * theKext = NULL; // must release 2040 2041 mkextLength = mkextData->getLength(); 2042 mkextHeader = (mkext1_header *)mkextData->getBytesNoCopy(); 2043 mkextEnd = (char *)mkextHeader + mkextLength; 2044 mkextVersion = OSSwapBigToHostInt32(mkextHeader->version); 2045 2046 crc_address = (u_int8_t *)&mkextHeader->version; 2047 checksum = mkext_adler32(crc_address, 2048 (uintptr_t)mkextHeader + 2049 OSSwapBigToHostInt32(mkextHeader->length) - (uintptr_t)crc_address); 2050 2051 if (OSSwapBigToHostInt32(mkextHeader->adler32) != checksum) { 2052 OSKextLog(/* kext */ NULL, 2053 kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 2054 "Kext archive has a bad checksum."); 2055 result = kOSKextReturnBadData; 2056 goto finish; 2057 } 2058 2059 if (checksumPtr) { 2060 *checksumPtr = checksum; 2061 } 2062 2063 /* Check that the CPU type & subtype match that of the running kernel. */ 2064 if (OSSwapBigToHostInt32(mkextHeader->cputype) != (UInt32)CPU_TYPE_ANY) { 2065 if ((UInt32)_mh_execute_header.cputype != 2066 OSSwapBigToHostInt32(mkextHeader->cputype)) { 2067 2068 OSKextLog(/* kext */ NULL, 2069 kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 2070 "Kext archive doesn't contain software " 2071 "for this computer's CPU type."); 2072 result = kOSKextReturnArchNotFound; 2073 goto finish; 2074 } 2075 } 2076 2077 numKexts = OSSwapBigToHostInt32(mkextHeader->numkexts); 2078 2079 for (uint32_t i = 0; i < numKexts; i++) { 2080 2081 OSSafeReleaseNULL(infoDictDataObject); 2082 OSSafeReleaseNULL(infoDict); 2083 OSSafeReleaseNULL(mkextExecutableInfo); 2084 OSSafeReleaseNULL(errorString); 2085 OSSafeReleaseNULL(theKext); 2086 2087 mkext_kext * kextEntry = &mkextHeader->kext[i]; 2088 mkext_file * infoDictPtr = &kextEntry->plist; 2089 mkext_file * executablePtr = &kextEntry->module; 2090 if (kextEntry >= mkextEnd) { 2091 OSKextLog(/* kext */ NULL, 2092 kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 2093 "Mkext file overrun."); 2094 result = kOSKextReturnBadData; 2095 goto finish; 2096 } 2097 2098 /* Note that we're pretty tolerant of errors in individual entries. 2099 * As long as we can keep processing, we do. 2100 */ 2101 infoDictDataObject = OSKext::extractMkext1Entry( 2102 mkextHeader, infoDictPtr); 2103 if (!infoDictDataObject) { 2104 OSKextLog(/* kext */ NULL, 2105 kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 2106 "Can't uncompress info dictionary " 2107 "from mkext archive entry %d.", i); 2108 continue; 2109 } 2110 2111 parsedXML = OSUnserializeXML( 2112 (const char *)infoDictDataObject->getBytesNoCopy(), 2113 &errorString); 2114 if (parsedXML) { 2115 infoDict = OSDynamicCast(OSDictionary, parsedXML); 2116 } 2117 if (!infoDict) { 2118 const char * errorCString = "(unknown error)"; 2119 2120 if (errorString && errorString->getCStringNoCopy()) { 2121 errorCString = errorString->getCStringNoCopy(); 2122 } else if (parsedXML) { 2123 errorCString = "not a dictionary"; 2124 } 2125 OSKextLog(/* kext */ NULL, 2126 kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 2127 "Error: Can't read XML property list " 2128 "for mkext archive entry %d: %s.", i, errorCString); 2129 continue; 2130 } 2131 2132 theKext = new OSKext; 2133 if (!theKext) { 2134 OSKextLog(/* kext */ NULL, 2135 kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 2136 "Kext allocation failure."); 2137 continue; 2138 } 2139 2140 /***** 2141 * Prepare an entry to hold the mkext entry info for the 2142 * compressed binary module, if there is one. If all four fields 2143 * of the module entry are zero, there isn't one. 2144 */ 2145 if ((OSSwapBigToHostInt32(executablePtr->offset) || 2146 OSSwapBigToHostInt32(executablePtr->compsize) || 2147 OSSwapBigToHostInt32(executablePtr->realsize) || 2148 OSSwapBigToHostInt32(executablePtr->modifiedsecs))) { 2149 2150 MkextEntryRef entryRef; 2151 2152 mkextExecutableInfo = OSData::withCapacity(sizeof(entryRef)); 2153 if (!mkextExecutableInfo) { 2154 panic("Error: Couldn't allocate data object " 2155 "for mkext archive entry %d.\n", i); 2156 } 2157 2158 entryRef.mkext = (mkext_basic_header *)mkextHeader; 2159 entryRef.fileinfo = (uint8_t *)executablePtr; 2160 if (!mkextExecutableInfo->appendBytes(&entryRef, 2161 sizeof(entryRef))) { 2162 2163 OSKextLog(/* kext */ NULL, 2164 kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 2165 "Couldn't record executable info " 2166 "for mkext archive entry %d.", i); 2167 // we might hit a load error later but oh well 2168 // xxx - should probably remove theKext 2169 continue; 2170 } 2171 2172 } 2173 2174 /* Init can fail because of a data/runtime error, or because the 2175 * kext is a dup. Either way, we don't care here. 2176 */ 2177 if (!theKext->initWithMkext1Info(infoDict, mkextExecutableInfo, 2178 mkextData)) { 2179 2180 // theKext is released at the top of the loop or in the finish block 2181 continue; 2182 } 2183 2184 /* If we got even one kext out of the mkext archive, 2185 * we have successfully read the archive, in that we 2186 * have data references into its mapped memory. 2187 */ 2188 result = kOSReturnSuccess; 2189 } 2190 2191 finish: 2192 2193 OSSafeRelease(infoDictDataObject); 2194 OSSafeRelease(parsedXML); 2195 OSSafeRelease(errorString); 2196 OSSafeRelease(mkextExecutableInfo); 2197 OSSafeRelease(theKext); 2198 2199 return result; 2200 } 2201 2202 /********************************************************************* 2203 *********************************************************************/ 2204 bool 2205 OSKext::initWithMkext1Info( 2206 OSDictionary * anInfoDict, 2207 OSData * executableWrapper, 2208 OSData * mkextData) 2209 { 2210 bool result = false; 2211 2212 // mkext1 doesn't allow for path (might stuff in info dict) 2213 if (!setInfoDictionaryAndPath(anInfoDict, /* path */ NULL)) { 2214 goto finish; 2215 } 2216 2217 if (!registerIdentifier()) { 2218 goto finish; 2219 } 2220 2221 if (!setExecutable(executableWrapper, mkextData, true)) { 2222 goto finish; 2223 } 2224 2225 result = true; 2226 2227 finish: 2228 2229 /* If we can't init, remove the kext from the lookup dictionary. 2230 * This is safe to call in init because there's an implicit retain. 2231 */ 2232 if (!result) { 2233 OSKext::removeKext(this, /* removePersonalities? */ false); 2234 } 2235 2236 return result; 2237 } 2238 2239 /********************************************************************* 2240 * xxx - this should take the input data length 2241 *********************************************************************/ 2242 /* static */ 2243 OSData * 2244 OSKext::extractMkext1Entry( 2245 const void * mkextFileBase, 2246 const void * entry) 2247 { 2248 OSData * result = NULL; 2249 OSData * uncompressedData = NULL; // release on error 2250 const char * errmsg = NULL; 2251 2252 mkext_file * fileinfo; 2253 uint8_t * uncompressedDataBuffer = 0; // do not free (panic on alloc. fail) 2254 size_t uncompressed_size = 0; 2255 kern_return_t kern_result; 2256 2257 fileinfo = (mkext_file *)entry; 2258 2259 size_t offset = OSSwapBigToHostInt32(fileinfo->offset); 2260 size_t compressed_size = OSSwapBigToHostInt32(fileinfo->compsize); 2261 size_t expected_size = OSSwapBigToHostInt32(fileinfo->realsize); 2262 2263 // Add 1 for '\0' to terminate XML string (for plists) 2264 // (we really should have the archive format include that). 2265 size_t alloc_size = expected_size + 1; 2266 time_t modifiedsecs = OSSwapBigToHostInt32(fileinfo->modifiedsecs); 2267 2268 /* If these four fields are zero there's no file, but it's up to 2269 * the calling context to decide if that's an error. 2270 */ 2271 if (offset == 0 && compressed_size == 0 && 2272 expected_size == 0 && modifiedsecs == 0) { 2273 goto finish; 2274 } 2275 2276 kern_result = kmem_alloc(kernel_map, 2277 (vm_offset_t *)&uncompressedDataBuffer, 2278 alloc_size); 2279 if (kern_result != KERN_SUCCESS) { 2280 panic(ALLOC_FAIL); 2281 goto finish; 2282 } 2283 2284 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, 2285 alloc_size); 2286 if (uncompressedData == NULL) { 2287 /* No need to free uncompressedDataBuffer here, either. */ 2288 panic(ALLOC_FAIL); 2289 goto finish; 2290 } 2291 uncompressedData->setDeallocFunction(&osdata_kmem_free); 2292 2293 /* Do the decompression if necessary. Note that even if the file isn't 2294 * compressed, we want to make a copy so that we don't have the tie to 2295 * the larger mkext file buffer any more. 2296 * xxx - need to detect decompression overflow too 2297 */ 2298 if (compressed_size != 0) { 2299 errmsg = "OSKext::uncompressMkext - " 2300 "uncompressed file shorter than expected"; 2301 uncompressed_size = decompress_lzss(uncompressedDataBuffer, 2302 expected_size, 2303 ((uint8_t *)mkextFileBase) + offset, 2304 compressed_size); 2305 if (uncompressed_size != expected_size) { 2306 goto finish; 2307 } 2308 } else { 2309 memcpy(uncompressedDataBuffer, 2310 ((uint8_t *)mkextFileBase) + offset, 2311 expected_size); 2312 } 2313 2314 // Add a terminating nul character in case the data is XML. 2315 // (we really should have the archive format include that). 2316 uncompressedDataBuffer[expected_size] = '\0'; 2317 2318 result = uncompressedData; 2319 errmsg = NULL; 2320 2321 finish: 2322 if (!result) { 2323 OSKextLog(/* kext */ NULL, 2324 kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 2325 "%s", errmsg); 2326 2327 if (uncompressedData) { 2328 uncompressedData->release(); 2329 } 2330 } 2331 return result; 2332 } 2333 2334 /********************************************************************* 2335 * Assumes magic, signature, version, length have been checked. 2336 * xxx - need to add further bounds checking for each file entry 2337 * 2338 * Should keep track of all kexts created so far, and if we hit a 2339 * fatal error halfway through, remove those kexts. If we've dropped 2340 * an older version that had already been read, whoops! Might want to 2341 * add a level of buffering? 2342 *********************************************************************/ 2343 /* static */ 2344 OSReturn 2345 OSKext::readMkext2Archive( 2346 OSData * mkextData, 2347 OSDictionary ** mkextPlistOut, 2348 uint32_t * checksumPtr) 2349 { 2350 OSReturn result = kOSReturnError; 2351 uint32_t mkextLength; 2352 mkext2_header * mkextHeader = NULL; // do not free 2353 void * mkextEnd = NULL; // do not free 2354 uint32_t mkextVersion; 2355 uint8_t * crc_address = NULL; 2356 uint32_t checksum; 2357 uint32_t mkextPlistOffset; 2358 uint32_t mkextPlistCompressedSize; 2359 char * mkextPlistEnd = NULL; // do not free 2360 uint32_t mkextPlistFullSize; 2361 OSString * errorString = NULL; // must release 2362 OSData * mkextPlistUncompressedData = NULL; // must release 2363 const char * mkextPlistDataBuffer = NULL; // do not free 2364 OSObject * parsedXML = NULL; // must release 2365 OSDictionary * mkextPlist = NULL; // do not release 2366 OSArray * mkextInfoDictArray = NULL; // do not release 2367 uint32_t count, i; 2368 2369 mkextLength = mkextData->getLength(); 2370 mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy(); 2371 mkextEnd = (char *)mkextHeader + mkextLength; 2372 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 2373 2374 crc_address = (u_int8_t *)&mkextHeader->version; 2375 checksum = mkext_adler32(crc_address, 2376 (uintptr_t)mkextHeader + 2377 MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address); 2378 2379 if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) { 2380 OSKextLog(/* kext */ NULL, 2381 kOSKextLogErrorLevel | 2382 kOSKextLogArchiveFlag, 2383 "Mkext archive has bad checksum."); 2384 result = kOSKextReturnBadData; 2385 goto finish; 2386 } 2387 2388 if (checksumPtr) { 2389 *checksumPtr = checksum; 2390 } 2391 2392 /* Check that the CPU type & subtype match that of the running kernel. */ 2393 if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) { 2394 OSKextLog(/* kext */ NULL, 2395 kOSKextLogErrorLevel | 2396 kOSKextLogArchiveFlag, 2397 "Mkext archive must have a specific CPU type."); 2398 result = kOSKextReturnBadData; 2399 goto finish; 2400 } else { 2401 if ((UInt32)_mh_execute_header.cputype != 2402 MKEXT_GET_CPUTYPE(mkextHeader)) { 2403 2404 OSKextLog(/* kext */ NULL, 2405 kOSKextLogErrorLevel | 2406 kOSKextLogArchiveFlag, 2407 "Mkext archive does not match the running kernel's CPU type."); 2408 result = kOSKextReturnArchNotFound; 2409 goto finish; 2410 } 2411 } 2412 2413 mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader); 2414 mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader); 2415 mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset + 2416 mkextPlistCompressedSize; 2417 if (mkextPlistEnd > mkextEnd) { 2418 OSKextLog(/* kext */ NULL, 2419 kOSKextLogErrorLevel | 2420 kOSKextLogArchiveFlag, 2421 "Mkext archive file overrun."); 2422 result = kOSKextReturnBadData; 2423 } 2424 2425 mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader); 2426 if (mkextPlistCompressedSize) { 2427 mkextPlistUncompressedData = sKernelKext->extractMkext2FileData( 2428 (UInt8 *)mkextHeader + mkextPlistOffset, 2429 "plist", 2430 mkextPlistCompressedSize, mkextPlistFullSize); 2431 if (!mkextPlistUncompressedData) { 2432 goto finish; 2433 } 2434 mkextPlistDataBuffer = (const char *) 2435 mkextPlistUncompressedData->getBytesNoCopy(); 2436 } else { 2437 mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset; 2438 } 2439 2440 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it. 2441 */ 2442 parsedXML = OSUnserializeXML(mkextPlistDataBuffer, &errorString); 2443 if (parsedXML) { 2444 mkextPlist = OSDynamicCast(OSDictionary, parsedXML); 2445 } 2446 if (!mkextPlist) { 2447 const char * errorCString = "(unknown error)"; 2448 2449 if (errorString && errorString->getCStringNoCopy()) { 2450 errorCString = errorString->getCStringNoCopy(); 2451 } else if (parsedXML) { 2452 errorCString = "not a dictionary"; 2453 } 2454 OSKextLog(/* kext */ NULL, 2455 kOSKextLogErrorLevel | 2456 kOSKextLogArchiveFlag, 2457 "Error unserializing mkext plist: %s.", errorCString); 2458 goto finish; 2459 } 2460 2461 /* If the caller needs the plist, hand it back and retain it. 2462 * (This function releases it at the end.) 2463 */ 2464 if (mkextPlistOut) { 2465 *mkextPlistOut = mkextPlist; 2466 (*mkextPlistOut)->retain(); 2467 } 2468 2469 mkextInfoDictArray = OSDynamicCast(OSArray, 2470 mkextPlist->getObject(kMKEXTInfoDictionariesKey)); 2471 if (!mkextInfoDictArray) { 2472 OSKextLog(/* kext */ NULL, 2473 kOSKextLogErrorLevel | 2474 kOSKextLogArchiveFlag, 2475 "Mkext archive contains no kext info dictionaries."); 2476 goto finish; 2477 } 2478 2479 count = mkextInfoDictArray->getCount(); 2480 for (i = 0; i < count; i++) { 2481 OSDictionary * infoDict; 2482 2483 2484 infoDict = OSDynamicCast(OSDictionary, 2485 mkextInfoDictArray->getObject(i)); 2486 2487 /* Create the kext for the entry, then release it, because the 2488 * kext system keeps them around until explicitly removed. 2489 * Any creation/registration failures are already logged for us. 2490 */ 2491 OSKext * newKext = OSKext::withMkext2Info(infoDict, mkextData); 2492 OSSafeRelease(newKext); 2493 } 2494 2495 /* Even if we didn't keep any kexts from the mkext, we may have a load 2496 * request to process, so we are successful (no errors occurred). 2497 */ 2498 result = kOSReturnSuccess; 2499 2500 finish: 2501 2502 OSSafeRelease(parsedXML); 2503 OSSafeRelease(mkextPlistUncompressedData); 2504 OSSafeRelease(errorString); 2505 2506 return result; 2507 } 2508 2509 /********************************************************************* 2510 *********************************************************************/ 2511 /* static */ 2512 OSKext * 2513 OSKext::withMkext2Info( 2514 OSDictionary * anInfoDict, 2515 OSData * mkextData) 2516 { 2517 OSKext * newKext = new OSKext; 2518 2519 if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) { 2520 newKext->release(); 2521 return NULL; 2522 } 2523 2524 return newKext; 2525 } 2526 2527 /********************************************************************* 2528 *********************************************************************/ 2529 bool 2530 OSKext::initWithMkext2Info( 2531 OSDictionary * anInfoDict, 2532 OSData * mkextData) 2533 { 2534 bool result = false; 2535 OSString * kextPath = NULL; // do not release 2536 OSNumber * executableOffsetNum = NULL; // do not release 2537 OSCollectionIterator * iterator = NULL; // must release 2538 OSData * executable = NULL; // must release 2539 2540 if (!super::init()) { 2541 goto finish; 2542 } 2543 2544 /* Get the path. Don't look for an arch-specific path property. 2545 */ 2546 kextPath = OSDynamicCast(OSString, 2547 anInfoDict->getObject(kMKEXTBundlePathKey)); 2548 2549 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 2550 goto finish; 2551 } 2552 2553 /* Don't need the path to be in the info dictionary any more. 2554 */ 2555 anInfoDict->removeObject(kMKEXTBundlePathKey); 2556 2557 executableOffsetNum = OSDynamicCast(OSNumber, 2558 infoDict->getObject(kMKEXTExecutableKey)); 2559 if (executableOffsetNum) { 2560 executable = createMkext2FileEntry(mkextData, 2561 executableOffsetNum, "executable"); 2562 infoDict->removeObject(kMKEXTExecutableKey); 2563 if (!executable) { 2564 goto finish; 2565 } 2566 if (!setExecutable(executable, mkextData, true)) { 2567 goto finish; 2568 } 2569 } 2570 2571 result = registerIdentifier(); 2572 2573 finish: 2574 2575 OSSafeRelease(executable); 2576 OSSafeRelease(iterator); 2577 return result; 2578 } 2579 2580 /********************************************************************* 2581 *********************************************************************/ 2582 OSData * 2583 OSKext::createMkext2FileEntry( 2584 OSData * mkextData, 2585 OSNumber * offsetNum, 2586 const char * name) 2587 { 2588 OSData * result = NULL; 2589 MkextEntryRef entryRef; 2590 uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy(); 2591 uint32_t entryOffset = offsetNum->unsigned32BitValue(); 2592 2593 result = OSData::withCapacity(sizeof(entryRef)); 2594 if (!result) { 2595 goto finish; 2596 } 2597 2598 entryRef.mkext = (mkext_basic_header *)mkextBuffer; 2599 entryRef.fileinfo = mkextBuffer + entryOffset; 2600 if (!result->appendBytes(&entryRef, sizeof(entryRef))) { 2601 OSSafeReleaseNULL(result); 2602 goto finish; 2603 } 2604 2605 finish: 2606 if (!result) { 2607 OSKextLog(this, 2608 kOSKextLogErrorLevel | 2609 kOSKextLogArchiveFlag, 2610 "Can't create wrapper for mkext file entry '%s' of kext %s.", 2611 name, getIdentifierCString()); 2612 } 2613 return result; 2614 } 2615 2616 /********************************************************************* 2617 *********************************************************************/ 2618 extern "C" { 2619 static void * z_alloc(void *, u_int items, u_int size); 2620 static void z_free(void *, void *ptr); 2621 2622 typedef struct z_mem { 2623 uint32_t alloc_size; 2624 uint8_t data[0]; 2625 } z_mem; 2626 2627 /* 2628 * Space allocation and freeing routines for use by zlib routines. 2629 */ 2630 void * 2631 z_alloc(void * notused __unused, u_int num_items, u_int size) 2632 { 2633 void * result = NULL; 2634 z_mem * zmem = NULL; 2635 uint32_t total = num_items * size; 2636 uint32_t allocSize = total + sizeof(zmem); 2637 2638 zmem = (z_mem *)kalloc(allocSize); 2639 if (!zmem) { 2640 goto finish; 2641 } 2642 zmem->alloc_size = allocSize; 2643 result = (void *)&(zmem->data); 2644 finish: 2645 return result; 2646 } 2647 2648 void 2649 z_free(void * notused __unused, void * ptr) 2650 { 2651 uint32_t * skipper = (uint32_t *)ptr - 1; 2652 z_mem * zmem = (z_mem *)skipper; 2653 kfree((void *)zmem, zmem->alloc_size); 2654 return; 2655 } 2656 }; 2657 2658 OSData * 2659 OSKext::extractMkext2FileData( 2660 UInt8 * data, 2661 const char * name, 2662 uint32_t compressedSize, 2663 uint32_t fullSize) 2664 { 2665 OSData * result = NULL; 2666 2667 OSData * uncompressedData = NULL; // release on error 2668 2669 uint8_t * uncompressedDataBuffer = 0; // do not free 2670 unsigned long uncompressedSize; 2671 z_stream zstream; 2672 bool zstream_inited = false; 2673 int zlib_result; 2674 2675 /* If the file isn't compressed, we want to make a copy 2676 * so that we don't have the tie to the larger mkext file buffer any more. 2677 */ 2678 if (!compressedSize) { 2679 uncompressedData = OSData::withBytes(data, fullSize); 2680 // xxx - no check for failure? 2681 result = uncompressedData; 2682 goto finish; 2683 } 2684 2685 if (KERN_SUCCESS != kmem_alloc(kernel_map, 2686 (vm_offset_t*)&uncompressedDataBuffer, fullSize)) { 2687 2688 /* How's this for cheesy? The kernel is only asked to extract 2689 * kext plists so we tailor the log messages. 2690 */ 2691 if (this == sKernelKext) { 2692 OSKextLog(this, 2693 kOSKextLogErrorLevel | 2694 kOSKextLogArchiveFlag, 2695 "Allocation failure extracting %s from mkext.", name); 2696 } else { 2697 OSKextLog(this, 2698 kOSKextLogErrorLevel | 2699 kOSKextLogArchiveFlag, 2700 "Allocation failure extracting %s from mkext for kext %s.", 2701 name, getIdentifierCString()); 2702 } 2703 2704 goto finish; 2705 } 2706 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize); 2707 if (!uncompressedData) { 2708 if (this == sKernelKext) { 2709 OSKextLog(this, 2710 kOSKextLogErrorLevel | 2711 kOSKextLogArchiveFlag, 2712 "Allocation failure extracting %s from mkext.", name); 2713 } else { 2714 OSKextLog(this, 2715 kOSKextLogErrorLevel | 2716 kOSKextLogArchiveFlag, 2717 "Allocation failure extracting %s from mkext for kext %s.", 2718 name, getIdentifierCString()); 2719 } 2720 goto finish; 2721 } 2722 uncompressedData->setDeallocFunction(&osdata_kmem_free); 2723 2724 if (this == sKernelKext) { 2725 OSKextLog(this, 2726 kOSKextLogDetailLevel | 2727 kOSKextLogArchiveFlag, 2728 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.", 2729 name, compressedSize, fullSize); 2730 } else { 2731 OSKextLog(this, 2732 kOSKextLogDetailLevel | 2733 kOSKextLogArchiveFlag, 2734 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.", 2735 getIdentifierCString(), name, compressedSize, fullSize); 2736 } 2737 2738 bzero(&zstream, sizeof(zstream)); 2739 zstream.next_in = (UInt8 *)data; 2740 zstream.avail_in = compressedSize; 2741 2742 zstream.next_out = uncompressedDataBuffer; 2743 zstream.avail_out = fullSize; 2744 2745 zstream.zalloc = z_alloc; 2746 zstream.zfree = z_free; 2747 2748 zlib_result = inflateInit(&zstream); 2749 if (Z_OK != zlib_result) { 2750 if (this == sKernelKext) { 2751 OSKextLog(this, 2752 kOSKextLogErrorLevel | 2753 kOSKextLogArchiveFlag, 2754 "Mkext error; zlib inflateInit failed (%d) for %s.", 2755 zlib_result, name); 2756 } else { 2757 OSKextLog(this, 2758 kOSKextLogErrorLevel | 2759 kOSKextLogArchiveFlag, 2760 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .", 2761 getIdentifierCString(), zlib_result, name); 2762 } 2763 goto finish; 2764 } else { 2765 zstream_inited = true; 2766 } 2767 2768 zlib_result = inflate(&zstream, Z_FINISH); 2769 2770 if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) { 2771 uncompressedSize = zstream.total_out; 2772 } else { 2773 if (this == sKernelKext) { 2774 OSKextLog(this, 2775 kOSKextLogErrorLevel | 2776 kOSKextLogArchiveFlag, 2777 "Mkext error; zlib inflate failed (%d) for %s.", 2778 zlib_result, name); 2779 } else { 2780 OSKextLog(this, 2781 kOSKextLogErrorLevel | 2782 kOSKextLogArchiveFlag, 2783 "Kext %s - mkext error; zlib inflate failed (%d) for %s .", 2784 getIdentifierCString(), zlib_result, name); 2785 } 2786 if (zstream.msg) { 2787 OSKextLog(this, 2788 kOSKextLogErrorLevel | 2789 kOSKextLogArchiveFlag, 2790 "zlib error: %s.", zstream.msg); 2791 } 2792 goto finish; 2793 } 2794 2795 if (uncompressedSize != fullSize) { 2796 if (this == sKernelKext) { 2797 OSKextLog(this, 2798 kOSKextLogErrorLevel | 2799 kOSKextLogArchiveFlag, 2800 "Mkext error; zlib inflate discrepancy for %s, " 2801 "uncompressed size != original size.", name); 2802 } else { 2803 OSKextLog(this, 2804 kOSKextLogErrorLevel | 2805 kOSKextLogArchiveFlag, 2806 "Kext %s - mkext error; zlib inflate discrepancy for %s, " 2807 "uncompressed size != original size.", 2808 getIdentifierCString(), name); 2809 } 2810 goto finish; 2811 } 2812 2813 result = uncompressedData; 2814 2815 finish: 2816 /* Don't bother checking return, nothing we can do on fail. 2817 */ 2818 if (zstream_inited) inflateEnd(&zstream); 2819 2820 if (!result) { 2821 OSSafeRelease(uncompressedData); 2822 } 2823 2824 return result; 2825 } 2826 2827 /********************************************************************* 2828 *********************************************************************/ 2829 /* static */ 2830 OSReturn 2831 OSKext::loadFromMkext( 2832 OSKextLogSpec clientLogFilter, 2833 char * mkextBuffer, 2834 uint32_t mkextBufferLength, 2835 char ** logInfoOut, 2836 uint32_t * logInfoLengthOut) 2837 { 2838 OSReturn result = kOSReturnError; 2839 OSReturn tempResult = kOSReturnError; 2840 2841 OSData * mkextData = NULL; // must release 2842 OSDictionary * mkextPlist = NULL; // must release 2843 2844 OSArray * logInfoArray = NULL; // must release 2845 OSSerialize * serializer = NULL; // must release 2846 2847 OSString * predicate = NULL; // do not release 2848 OSDictionary * requestArgs = NULL; // do not release 2849 2850 OSString * kextIdentifier = NULL; // do not release 2851 OSNumber * startKextExcludeNum = NULL; // do not release 2852 OSNumber * startMatchingExcludeNum = NULL; // do not release 2853 OSBoolean * delayAutounloadBool = NULL; // do not release 2854 OSArray * personalityNames = NULL; // do not release 2855 2856 /* Default values for these two options: regular autounload behavior, 2857 * load all kexts, send no personalities. 2858 */ 2859 Boolean delayAutounload = false; 2860 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 2861 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll; 2862 2863 IORecursiveLockLock(sKextLock); 2864 2865 if (logInfoOut) { 2866 *logInfoOut = NULL; 2867 *logInfoLengthOut = 0; 2868 } 2869 2870 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 2871 2872 OSKextLog(/* kext */ NULL, 2873 kOSKextLogDebugLevel | 2874 kOSKextLogIPCFlag, 2875 "Received kext load request from user space."); 2876 2877 /* Regardless of processing, the fact that we have gotten here means some 2878 * user-space program is up and talking to us, so we'll switch our kext 2879 * registration to reflect that. 2880 */ 2881 if (!sUserLoadsActive) { 2882 OSKextLog(/* kext */ NULL, 2883 kOSKextLogProgressLevel | 2884 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 2885 "Switching to late startup (user-space) kext loading policy."); 2886 2887 sUserLoadsActive = true; 2888 } 2889 2890 if (!sLoadEnabled) { 2891 OSKextLog(/* kext */ NULL, 2892 kOSKextLogErrorLevel | 2893 kOSKextLogLoadFlag, 2894 "Kext loading is disabled."); 2895 result = kOSKextReturnDisabled; 2896 goto finish; 2897 } 2898 2899 /* Note that we do not set a dealloc function on this OSData 2900 * object! No references to it can remain after the loadFromMkext() 2901 * call since we are in a MIG function, and will vm_deallocate() 2902 * the buffer. 2903 */ 2904 mkextData = OSData::withBytesNoCopy(mkextBuffer, 2905 mkextBufferLength); 2906 if (!mkextData) { 2907 OSKextLog(/* kext */ NULL, 2908 kOSKextLogErrorLevel | 2909 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 2910 "Failed to create wrapper for kext load request."); 2911 result = kOSKextReturnNoMemory; 2912 goto finish; 2913 } 2914 2915 result = readMkext2Archive(mkextData, &mkextPlist, NULL); 2916 if (result != kOSReturnSuccess) { 2917 OSKextLog(/* kext */ NULL, 2918 kOSKextLogErrorLevel | 2919 kOSKextLogLoadFlag, 2920 "Failed to read kext load request."); 2921 goto finish; 2922 } 2923 2924 predicate = _OSKextGetRequestPredicate(mkextPlist); 2925 if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) { 2926 OSKextLog(/* kext */ NULL, 2927 kOSKextLogErrorLevel | 2928 kOSKextLogLoadFlag, 2929 "Received kext load request with no predicate; skipping."); 2930 result = kOSKextReturnInvalidArgument; 2931 goto finish; 2932 } 2933 2934 requestArgs = OSDynamicCast(OSDictionary, 2935 mkextPlist->getObject(kKextRequestArgumentsKey)); 2936 if (!requestArgs || !requestArgs->getCount()) { 2937 OSKextLog(/* kext */ NULL, 2938 kOSKextLogErrorLevel | 2939 kOSKextLogLoadFlag, 2940 "Received kext load request with no arguments."); 2941 result = kOSKextReturnInvalidArgument; 2942 goto finish; 2943 } 2944 2945 kextIdentifier = OSDynamicCast(OSString, 2946 requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey)); 2947 if (!kextIdentifier) { 2948 OSKextLog(/* kext */ NULL, 2949 kOSKextLogErrorLevel | 2950 kOSKextLogLoadFlag, 2951 "Received kext load request with no kext identifier."); 2952 result = kOSKextReturnInvalidArgument; 2953 goto finish; 2954 } 2955 2956 startKextExcludeNum = OSDynamicCast(OSNumber, 2957 requestArgs->getObject(kKextKextRequestArgumentStartExcludeKey)); 2958 startMatchingExcludeNum = OSDynamicCast(OSNumber, 2959 requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey)); 2960 delayAutounloadBool = OSDynamicCast(OSBoolean, 2961 requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey)); 2962 personalityNames = OSDynamicCast(OSArray, 2963 requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey)); 2964 2965 if (delayAutounloadBool) { 2966 delayAutounload = delayAutounloadBool->getValue(); 2967 } 2968 if (startKextExcludeNum) { 2969 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 2970 } 2971 if (startMatchingExcludeNum) { 2972 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 2973 } 2974 2975 OSKextLog(/* kext */ NULL, 2976 kOSKextLogProgressLevel | 2977 kOSKextLogIPCFlag, 2978 "Received request from user space to load kext %s.", 2979 kextIdentifier->getCStringNoCopy()); 2980 2981 /* Load the kext, with no deferral, since this is a load from outside 2982 * the kernel. 2983 * xxx - Would like a better way to handle the default values for the 2984 * xxx - start/match opt args. 2985 */ 2986 result = OSKext::loadKextWithIdentifier( 2987 kextIdentifier, 2988 /* allowDefer */ false, 2989 delayAutounload, 2990 startKextExcludeLevel, 2991 startMatchingExcludeLevel, 2992 personalityNames); 2993 if (result != kOSReturnSuccess) { 2994 goto finish; 2995 } 2996 /* If the load came down from kextd, it will shortly inform IOCatalogue 2997 * for matching via a separate IOKit calldown. 2998 */ 2999 3000 finish: 3001 3002 /* Gather up the collected log messages for user space. Any 3003 * error messages past this call will not make it up as log messages 3004 * but will be in the system log. 3005 */ 3006 logInfoArray = OSKext::clearUserSpaceLogFilter(); 3007 3008 if (logInfoArray && logInfoOut && logInfoLengthOut) { 3009 tempResult = OSKext::serializeLogInfo(logInfoArray, 3010 logInfoOut, logInfoLengthOut); 3011 if (tempResult != kOSReturnSuccess) { 3012 result = tempResult; 3013 } 3014 } 3015 3016 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false); 3017 3018 /* Note: mkextDataObject will have been retained by every kext w/an 3019 * executable in it. That should all have been flushed out at the 3020 * and of the load operation, but you never know.... 3021 */ 3022 if (mkextData && mkextData->getRetainCount() > 1) { 3023 OSKextLog(/* kext */ NULL, 3024 kOSKextLogErrorLevel | 3025 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 3026 "Kext load request buffer from user space still retained by a kext; " 3027 "probable memory leak."); 3028 } 3029 3030 IORecursiveLockUnlock(sKextLock); 3031 3032 OSSafeRelease(mkextData); 3033 OSSafeRelease(mkextPlist); 3034 OSSafeRelease(serializer); 3035 OSSafeRelease(logInfoArray); 3036 3037 return result; 3038 } 3039 3040 /********************************************************************* 3041 *********************************************************************/ 3042 /* static */ 3043 OSReturn 3044 OSKext::serializeLogInfo( 3045 OSArray * logInfoArray, 3046 char ** logInfoOut, 3047 uint32_t * logInfoLengthOut) 3048 { 3049 OSReturn result = kOSReturnError; 3050 char * buffer = NULL; 3051 kern_return_t kmem_result = KERN_FAILURE; 3052 OSSerialize * serializer = NULL; // must release; reused 3053 char * logInfo = NULL; // returned by reference 3054 uint32_t logInfoLength = 0; 3055 3056 if (!logInfoArray || !logInfoOut || !logInfoLengthOut) { 3057 OSKextLog(/* kext */ NULL, 3058 kOSKextLogErrorLevel | 3059 kOSKextLogIPCFlag, 3060 "Internal error; invalid arguments to OSKext::serializeLogInfo()."); 3061 /* Bad programmer. */ 3062 result = kOSKextReturnInvalidArgument; 3063 goto finish; 3064 } 3065 3066 serializer = OSSerialize::withCapacity(0); 3067 if (!serializer) { 3068 OSKextLog(/* kext */ NULL, 3069 kOSKextLogErrorLevel | 3070 kOSKextLogIPCFlag, 3071 "Failed to create serializer on log info for request from user space."); 3072 /* Incidental error; we're going to (try to) allow the request 3073 * itself to succeed. */ 3074 } 3075 3076 if (!logInfoArray->serialize(serializer)) { 3077 OSKextLog(/* kext */ NULL, 3078 kOSKextLogErrorLevel | 3079 kOSKextLogIPCFlag, 3080 "Failed to serialize log info for request from user space."); 3081 /* Incidental error; we're going to (try to) allow the request 3082 * itself to succeed. */ 3083 } else { 3084 logInfo = serializer->text(); 3085 logInfoLength = serializer->getLength(); 3086 3087 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, logInfoLength); 3088 if (kmem_result != KERN_SUCCESS) { 3089 OSKextLog(/* kext */ NULL, 3090 kOSKextLogErrorLevel | 3091 kOSKextLogIPCFlag, 3092 "Failed to copy log info for request from user space."); 3093 /* Incidental error; we're going to (try to) allow the request 3094 * to succeed. */ 3095 } else { 3096 memcpy(buffer, logInfo, logInfoLength); 3097 *logInfoOut = buffer; 3098 *logInfoLengthOut = logInfoLength; 3099 } 3100 } 3101 3102 result = kOSReturnSuccess; 3103 finish: 3104 OSSafeRelease(serializer); 3105 return result; 3106 } 3107 3108 #if PRAGMA_MARK 3109 #pragma mark Instance Management Methods 3110 #endif 3111 /********************************************************************* 3112 *********************************************************************/ 3113 OSKext * 3114 OSKext::lookupKextWithIdentifier(const char * kextIdentifier) 3115 { 3116 OSKext * foundKext = NULL; 3117 3118 IORecursiveLockLock(sKextLock); 3119 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 3120 if (foundKext) { 3121 foundKext->retain(); 3122 } 3123 IORecursiveLockUnlock(sKextLock); 3124 3125 return foundKext; 3126 } 3127 3128 /********************************************************************* 3129 *********************************************************************/ 3130 OSKext * 3131 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier) 3132 { 3133 return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy()); 3134 } 3135 3136 /********************************************************************* 3137 *********************************************************************/ 3138 OSKext * 3139 OSKext::lookupKextWithLoadTag(uint32_t aTag) 3140 { 3141 OSKext * foundKext = NULL; // returned 3142 uint32_t count, i; 3143 3144 IORecursiveLockLock(sKextLock); 3145 3146 count = sLoadedKexts->getCount(); 3147 for (i = 0; i < count; i++) { 3148 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 3149 if (thisKext->getLoadTag() == aTag) { 3150 foundKext = thisKext; 3151 foundKext->retain(); 3152 goto finish; 3153 } 3154 } 3155 3156 finish: 3157 IORecursiveLockUnlock(sKextLock); 3158 3159 return foundKext; 3160 } 3161 3162 /********************************************************************* 3163 *********************************************************************/ 3164 OSKext * 3165 OSKext::lookupKextWithAddress(vm_address_t address) 3166 { 3167 OSKext * foundKext = NULL; // returned 3168 uint32_t count, i; 3169 3170 IORecursiveLockLock(sKextLock); 3171 3172 count = sLoadedKexts->getCount(); 3173 for (i = 0; i < count; i++) { 3174 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 3175 if (thisKext->linkedExecutable) { 3176 vm_address_t kext_start = 3177 (vm_address_t)thisKext->linkedExecutable->getBytesNoCopy(); 3178 vm_address_t kext_end = kext_start + 3179 thisKext->linkedExecutable->getLength(); 3180 3181 if ((kext_start <= address) && (address < kext_end)) { 3182 foundKext = thisKext; 3183 foundKext->retain(); 3184 goto finish; 3185 } 3186 } 3187 } 3188 3189 finish: 3190 IORecursiveLockUnlock(sKextLock); 3191 3192 return foundKext; 3193 } 3194 3195 /********************************************************************* 3196 *********************************************************************/ 3197 /* static */ 3198 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier) 3199 { 3200 bool result = false; 3201 OSKext * foundKext = NULL; // returned 3202 3203 IORecursiveLockLock(sKextLock); 3204 3205 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 3206 if (foundKext && foundKext->isLoaded()) { 3207 result = true; 3208 } 3209 3210 IORecursiveLockUnlock(sKextLock); 3211 3212 return result; 3213 } 3214 3215 /********************************************************************* 3216 * xxx - should spawn a separate thread so a kext can safely have 3217 * xxx - itself unloaded. 3218 *********************************************************************/ 3219 /* static */ 3220 OSReturn 3221 OSKext::removeKext( 3222 OSKext * aKext, 3223 bool terminateServicesAndRemovePersonalitiesFlag) 3224 { 3225 OSReturn result = kOSKextReturnInUse; 3226 OSKext * checkKext = NULL; // do not release 3227 3228 IORecursiveLockLock(sKextLock); 3229 3230 /* If the kext has no identifier, it failed to init 3231 * so isn't in sKextsByID and it isn't loaded. 3232 */ 3233 if (!aKext->getIdentifier()) { 3234 result = kOSReturnSuccess; 3235 goto finish; 3236 } 3237 3238 checkKext = OSDynamicCast(OSKext, 3239 sKextsByID->getObject(aKext->getIdentifier())); 3240 if (checkKext != aKext) { 3241 result = kOSKextReturnNotFound; 3242 goto finish; 3243 } 3244 3245 if (aKext->isLoaded()) { 3246 /* If we are terminating, send the request to the IOCatalogue 3247 * (which will actually call us right back but that's ok we have 3248 * a recursive lock don't you know) but do not ask the IOCatalogue 3249 * to call back with an unload, we'll do that right here. 3250 */ 3251 if (terminateServicesAndRemovePersonalitiesFlag) { 3252 result = gIOCatalogue->terminateDriversForModule( 3253 aKext->getIdentifierCString(), /* unload */ false); 3254 if (result != kOSReturnSuccess) { 3255 OSKextLog(aKext, 3256 kOSKextLogProgressLevel | 3257 kOSKextLogKextBookkeepingFlag, 3258 "Can't remove kext %s; services failed to terminate - 0x%x.", 3259 aKext->getIdentifierCString(), result); 3260 goto finish; 3261 } 3262 } 3263 3264 result = aKext->unload(); 3265 if (result != kOSReturnSuccess) { 3266 goto finish; 3267 } 3268 } 3269 3270 /* Remove personalities as requested. This is a bit redundant for a loaded 3271 * kext as IOCatalogue::terminateDriversForModule() removes driver 3272 * personalities, but it doesn't restart matching, which we always want 3273 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures 3274 * that happens. 3275 */ 3276 if (terminateServicesAndRemovePersonalitiesFlag) { 3277 aKext->removePersonalitiesFromCatalog(); 3278 } 3279 3280 OSKextLog(aKext, 3281 kOSKextLogProgressLevel | 3282 kOSKextLogKextBookkeepingFlag, 3283 "Removing kext %s.", 3284 aKext->getIdentifierCString()); 3285 3286 sKextsByID->removeObject(aKext->getIdentifier()); 3287 result = kOSReturnSuccess; 3288 3289 finish: 3290 IORecursiveLockUnlock(sKextLock); 3291 return result; 3292 } 3293 3294 /********************************************************************* 3295 *********************************************************************/ 3296 /* static */ 3297 OSReturn 3298 OSKext::removeKextWithIdentifier( 3299 const char * kextIdentifier, 3300 bool terminateServicesAndRemovePersonalitiesFlag) 3301 { 3302 OSReturn result = kOSReturnError; 3303 3304 IORecursiveLockLock(sKextLock); 3305 3306 OSKext * aKext = OSDynamicCast(OSKext, 3307 sKextsByID->getObject(kextIdentifier)); 3308 if (!aKext) { 3309 result = kOSKextReturnNotFound; 3310 OSKextLog(/* kext */ NULL, 3311 kOSKextLogErrorLevel | 3312 kOSKextLogKextBookkeepingFlag, 3313 "Can't remove kext %s - not found.", 3314 kextIdentifier); 3315 goto finish; 3316 } 3317 3318 result = OSKext::removeKext(aKext, 3319 terminateServicesAndRemovePersonalitiesFlag); 3320 3321 finish: 3322 IORecursiveLockUnlock(sKextLock); 3323 3324 return result; 3325 } 3326 3327 /********************************************************************* 3328 *********************************************************************/ 3329 /* static */ 3330 OSReturn 3331 OSKext::removeKextWithLoadTag( 3332 OSKextLoadTag loadTag, 3333 bool terminateServicesAndRemovePersonalitiesFlag) 3334 { 3335 OSReturn result = kOSReturnError; 3336 OSKext * foundKext = NULL; 3337 uint32_t count, i; 3338 3339 IORecursiveLockLock(sKextLock); 3340 3341 count = sLoadedKexts->getCount(); 3342 for (i = 0; i < count; i++) { 3343 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 3344 if (thisKext->loadTag == loadTag) { 3345 foundKext = thisKext; 3346 break; 3347 } 3348 } 3349 3350 if (!foundKext) { 3351 result = kOSKextReturnNotFound; 3352 OSKextLog(/* kext */ NULL, 3353 kOSKextLogErrorLevel | 3354 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 3355 "Can't remove kext with load tag %d - not found.", 3356 loadTag); 3357 goto finish; 3358 } 3359 3360 result = OSKext::removeKext(foundKext, 3361 terminateServicesAndRemovePersonalitiesFlag); 3362 3363 finish: 3364 IORecursiveLockUnlock(sKextLock); 3365 3366 return result; 3367 } 3368 3369 /********************************************************************* 3370 *********************************************************************/ 3371 OSDictionary * 3372 OSKext::copyKexts(void) 3373 { 3374 OSDictionary * result; 3375 3376 IORecursiveLockLock(sKextLock); 3377 result = OSDynamicCast(OSDictionary, sKextsByID->copyCollection()); 3378 IORecursiveLockUnlock(sKextLock); 3379 3380 return result; 3381 } 3382 3383 #if PRAGMA_MARK 3384 #pragma mark Accessors 3385 #endif 3386 /********************************************************************* 3387 *********************************************************************/ 3388 const OSSymbol * 3389 OSKext::getIdentifier(void) 3390 { 3391 return bundleID; 3392 } 3393 3394 /********************************************************************* 3395 * A kext must have a bundle identifier to even survive initialization; 3396 * this is guaranteed to exist past then. 3397 *********************************************************************/ 3398 const char * 3399 OSKext::getIdentifierCString(void) 3400 { 3401 return bundleID->getCStringNoCopy(); 3402 } 3403 3404 /********************************************************************* 3405 *********************************************************************/ 3406 OSKextVersion 3407 OSKext::getVersion(void) 3408 { 3409 return version; 3410 } 3411 3412 /********************************************************************* 3413 *********************************************************************/ 3414 OSKextVersion 3415 OSKext::getCompatibleVersion(void) 3416 { 3417 return compatibleVersion; 3418 } 3419 3420 /********************************************************************* 3421 *********************************************************************/ 3422 bool 3423 OSKext::isCompatibleWithVersion(OSKextVersion aVersion) 3424 { 3425 if ((compatibleVersion > -1 && version > -1) && 3426 (compatibleVersion <= version && aVersion <= version)) { 3427 return true; 3428 } 3429 return false; 3430 } 3431 3432 /********************************************************************* 3433 *********************************************************************/ 3434 bool 3435 OSKext::declaresExecutable(void) 3436 { 3437 if (getPropertyForHostArch(kCFBundleExecutableKey)) { 3438 return true; 3439 } 3440 return false; 3441 } 3442 3443 /********************************************************************* 3444 *********************************************************************/ 3445 OSData * 3446 OSKext::getExecutable(void) 3447 { 3448 OSData * result = NULL; 3449 OSData * extractedExecutable = NULL; // must release 3450 OSData * mkextExecutableRef = NULL; // do not release 3451 3452 result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey)); 3453 if (result) { 3454 goto finish; 3455 } 3456 3457 mkextExecutableRef = OSDynamicCast(OSData, 3458 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey)); 3459 3460 if (mkextExecutableRef) { 3461 3462 MkextEntryRef * mkextEntryRef = (MkextEntryRef *) 3463 mkextExecutableRef->getBytesNoCopy(); 3464 uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext); 3465 if (mkextVersion == MKEXT_VERS_2) { 3466 mkext2_file_entry * fileinfo = 3467 (mkext2_file_entry *)mkextEntryRef->fileinfo; 3468 uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo); 3469 uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo); 3470 extractedExecutable = extractMkext2FileData( 3471 MKEXT2_GET_ENTRY_DATA(fileinfo), "executable", 3472 compressedSize, fullSize); 3473 } else if (mkextVersion == MKEXT_VERS_1) { 3474 extractedExecutable = extractMkext1Entry( 3475 mkextEntryRef->mkext, mkextEntryRef->fileinfo); 3476 } else { 3477 OSKextLog(this, kOSKextLogErrorLevel | 3478 kOSKextLogArchiveFlag, 3479 "Kext %s - unknown mkext version 0x%x for executable.", 3480 getIdentifierCString(), mkextVersion); 3481 } 3482 3483 /* Regardless of success, remove the mkext executable, 3484 * and drop one reference on the mkext. (setExecutable() does not 3485 * replace, it removes, or panics if asked to replace.) 3486 */ 3487 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 3488 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 3489 3490 if (extractedExecutable && extractedExecutable->getLength()) { 3491 if (!setExecutable(extractedExecutable)) { 3492 goto finish; 3493 } 3494 result = extractedExecutable; 3495 } else { 3496 goto finish; 3497 } 3498 } 3499 3500 finish: 3501 3502 OSSafeRelease(extractedExecutable); 3503 3504 return result; 3505 } 3506 3507 /********************************************************************* 3508 *********************************************************************/ 3509 bool 3510 OSKext::isInterface(void) 3511 { 3512 return flags.interface; 3513 } 3514 3515 /********************************************************************* 3516 *********************************************************************/ 3517 bool 3518 OSKext::isKernelComponent(void) 3519 { 3520 return flags.kernelComponent ? true : false; 3521 } 3522 3523 /********************************************************************* 3524 * We might want to check this recursively for all dependencies, 3525 * since a subtree of dependencies could get loaded before we hit 3526 * a dependency that isn't safe-boot-loadable. 3527 * 3528 * xxx - Might want to return false if OSBundleEnableKextLogging or 3529 * OSBundleDebugLevel 3530 * or IOKitDebug is nonzero too (we used to do that, but I don't see 3531 * the point except it's usually development drivers, which might 3532 * cause panics on startup, that have those properties). Heh; could 3533 * use a "kx" boot-arg! 3534 *********************************************************************/ 3535 bool 3536 OSKext::isLoadableInSafeBoot(void) 3537 { 3538 bool result = false; 3539 OSString * required = NULL; // do not release 3540 3541 3542 required = OSDynamicCast(OSString, 3543 getPropertyForHostArch(kOSBundleRequiredKey)); 3544 if (!required) { 3545 goto finish; 3546 } 3547 if (required->isEqualTo(kOSBundleRequiredRoot) || 3548 required->isEqualTo(kOSBundleRequiredLocalRoot) || 3549 required->isEqualTo(kOSBundleRequiredNetworkRoot) || 3550 required->isEqualTo(kOSBundleRequiredSafeBoot) || 3551 required->isEqualTo(kOSBundleRequiredConsole)) { 3552 3553 result = true; 3554 } 3555 3556 finish: 3557 return result; 3558 } 3559 3560 /********************************************************************* 3561 *********************************************************************/ 3562 bool 3563 OSKext::isPrelinked(void) 3564 { 3565 return flags.prelinked ? true : false; 3566 } 3567 3568 /********************************************************************* 3569 *********************************************************************/ 3570 bool OSKext::isLoaded(void) 3571 { 3572 return flags.loaded ? true : false; 3573 } 3574 3575 /********************************************************************* 3576 *********************************************************************/ 3577 bool 3578 OSKext::isStarted(void) 3579 { 3580 return flags.started ? true : false; 3581 } 3582 3583 /********************************************************************* 3584 *********************************************************************/ 3585 bool 3586 OSKext::isCPPInitialized(void) 3587 { 3588 return flags.CPPInitialized; 3589 } 3590 3591 /********************************************************************* 3592 *********************************************************************/ 3593 void 3594 OSKext::setCPPInitialized(bool initialized) 3595 { 3596 flags.CPPInitialized = initialized; 3597 } 3598 3599 /********************************************************************* 3600 *********************************************************************/ 3601 uint32_t 3602 OSKext::getLoadTag(void) 3603 { 3604 return loadTag; 3605 } 3606 3607 /********************************************************************* 3608 *********************************************************************/ 3609 OSData * 3610 OSKext::copyUUID(void) 3611 { 3612 OSData * result = NULL; 3613 OSData * theExecutable = NULL; // do not release 3614 const kernel_mach_header_t * header = NULL; 3615 const struct load_command * load_cmd = NULL; 3616 const struct uuid_command * uuid_cmd = NULL; 3617 uint32_t i; 3618 3619 /* An interface kext doesn't have a linked executable with an LC_UUID, 3620 * we create one when it's linked. 3621 */ 3622 if (interfaceUUID) { 3623 result = interfaceUUID; 3624 result->retain(); 3625 goto finish; 3626 } 3627 3628 /* For real kexts, try to get the UUID from the linked executable, 3629 * or if is hasn't been linked yet, the unrelocated executable. 3630 */ 3631 theExecutable = linkedExecutable; 3632 if (!theExecutable) { 3633 theExecutable = getExecutable(); 3634 } 3635 if (!theExecutable) { 3636 goto finish; 3637 } 3638 3639 header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy(); 3640 load_cmd = (const struct load_command *)&header[1]; 3641 3642 for (i = 0; i < header->ncmds; i++) { 3643 if (load_cmd->cmd == LC_UUID) { 3644 uuid_cmd = (struct uuid_command *)load_cmd; 3645 result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid)); 3646 goto finish; 3647 } 3648 load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize); 3649 } 3650 3651 finish: 3652 return result; 3653 } 3654 3655 /********************************************************************* 3656 *********************************************************************/ 3657 #if defined (__ppc__) 3658 #define ARCHNAME "ppc" 3659 #elif defined (__i386__) 3660 #define ARCHNAME "i386" 3661 #elif defined (__x86_64__) 3662 #define ARCHNAME "x86_64" 3663 #else 3664 #error architecture not supported 3665 #endif 3666 3667 #define ARCH_SEPARATOR_CHAR '_' 3668 3669 static char * makeHostArchKey(const char * key, uint32_t * keySizeOut) 3670 { 3671 char * result = NULL; 3672 uint32_t keyLength = strlen(key); 3673 uint32_t keySize; 3674 3675 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'. 3676 */ 3677 keySize = 1 + 1 + strlen(key) + strlen(ARCHNAME); 3678 result = (char *)kalloc(keySize); 3679 if (!result) { 3680 goto finish; 3681 } 3682 strlcpy(result, key, keySize); 3683 result[keyLength++] = ARCH_SEPARATOR_CHAR; 3684 result[keyLength] = '\0'; 3685 strlcat(result, ARCHNAME, keySize); 3686 *keySizeOut = keySize; 3687 3688 finish: 3689 return result; 3690 } 3691 3692 /********************************************************************* 3693 *********************************************************************/ 3694 OSObject * 3695 OSKext::getPropertyForHostArch(const char * key) 3696 { 3697 OSObject * result = NULL; // do not release 3698 uint32_t hostArchKeySize = 0; 3699 char * hostArchKey = NULL; // must kfree 3700 3701 if (!key || !infoDict) { 3702 goto finish; 3703 } 3704 3705 /* Some properties are not allowed to be arch-variant: 3706 * - Any CFBundle... property. 3707 * - OSBundleIsInterface. 3708 * - OSKernelResource. 3709 */ 3710 if (STRING_HAS_PREFIX(key, "OS") || 3711 STRING_HAS_PREFIX(key, "IO")) { 3712 3713 hostArchKey = makeHostArchKey(key, &hostArchKeySize); 3714 if (!hostArchKey) { 3715 OSKextLog(/* kext (this isn't about a kext) */ NULL, 3716 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 3717 "Allocation failure."); 3718 goto finish; 3719 } 3720 result = infoDict->getObject(hostArchKey); 3721 } 3722 3723 if (!result) { 3724 result = infoDict->getObject(key); 3725 } 3726 3727 finish: 3728 if (hostArchKey) kfree(hostArchKey, hostArchKeySize); 3729 return result; 3730 } 3731 3732 #if PRAGMA_MARK 3733 #pragma mark Load/Start/Stop/Unload 3734 #endif 3735 /********************************************************************* 3736 *********************************************************************/ 3737 OSReturn 3738 OSKext::loadKextWithIdentifier( 3739 const char * kextIdentifierCString, 3740 Boolean allowDeferFlag, 3741 Boolean delayAutounloadFlag, 3742 OSKextExcludeLevel startOpt, 3743 OSKextExcludeLevel startMatchingOpt, 3744 OSArray * personalityNames) 3745 { 3746 OSReturn result = kOSReturnError; 3747 OSString * kextIdentifier = NULL; // must release 3748 3749 kextIdentifier = OSString::withCString(kextIdentifierCString); 3750 if (!kextIdentifier) { 3751 result = kOSKextReturnNoMemory; 3752 goto finish; 3753 } 3754 result = OSKext::loadKextWithIdentifier(kextIdentifier, 3755 allowDeferFlag, delayAutounloadFlag, 3756 startOpt, startMatchingOpt, personalityNames); 3757 3758 finish: 3759 OSSafeRelease(kextIdentifier); 3760 return result; 3761 } 3762 3763 3764 /********************************************************************* 3765 *********************************************************************/ 3766 OSReturn 3767 OSKext::loadKextWithIdentifier( 3768 OSString * kextIdentifier, 3769 Boolean allowDeferFlag, 3770 Boolean delayAutounloadFlag, 3771 OSKextExcludeLevel startOpt, 3772 OSKextExcludeLevel startMatchingOpt, 3773 OSArray * personalityNames) 3774 { 3775 OSReturn result = kOSReturnError; 3776 OSKext * theKext = NULL; // do not release 3777 OSDictionary * loadRequest = NULL; // must release 3778 const OSSymbol * kextIdentifierSymbol = NULL; // must release 3779 3780 IORecursiveLockLock(sKextLock); 3781 3782 if (!kextIdentifier) { 3783 result = kOSKextReturnInvalidArgument; 3784 goto finish; 3785 } 3786 3787 OSKext::recordIdentifierRequest(kextIdentifier); 3788 3789 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 3790 if (!theKext) { 3791 if (!allowDeferFlag) { 3792 OSKextLog(/* kext */ NULL, 3793 kOSKextLogErrorLevel | 3794 kOSKextLogLoadFlag, 3795 "Can't load kext %s - not found.", 3796 kextIdentifier->getCStringNoCopy()); 3797 goto finish; 3798 } 3799 3800 if (!sKernelRequestsEnabled) { 3801 OSKextLog(theKext, 3802 kOSKextLogErrorLevel | 3803 kOSKextLogLoadFlag, 3804 "Can't load kext %s - requests to user space are disabled.", 3805 kextIdentifier->getCStringNoCopy()); 3806 result = kOSKextReturnDisabled; 3807 goto finish; 3808 } 3809 3810 /* Create a new request unless one is already sitting 3811 * in sKernelRequests for this bundle identifier 3812 */ 3813 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 3814 if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) { 3815 result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad, 3816 &loadRequest); 3817 if (result != kOSReturnSuccess) { 3818 goto finish; 3819 } 3820 if (!_OSKextSetRequestArgument(loadRequest, 3821 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 3822 3823 result = kOSKextReturnNoMemory; 3824 goto finish; 3825 } 3826 if (!sKernelRequests->setObject(loadRequest)) { 3827 result = kOSKextReturnNoMemory; 3828 goto finish; 3829 } 3830 3831 if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol)) { 3832 result = kOSKextReturnNoMemory; 3833 goto finish; 3834 } 3835 3836 OSKextLog(theKext, 3837 kOSKextLogDebugLevel | 3838 kOSKextLogLoadFlag, 3839 "Kext %s not found; queued load request to user space.", 3840 kextIdentifier->getCStringNoCopy()); 3841 } 3842 3843 if (sKextdActive) { 3844 OSKextPingKextd(); 3845 } else { 3846 OSKextLog(/* kext */ NULL, 3847 ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) | 3848 kOSKextLogLoadFlag, 3849 "Not loading kext %s - not found and kextd not available in early boot.", 3850 kextIdentifier->getCStringNoCopy()); 3851 } 3852 3853 result = kOSKextReturnDeferred; 3854 goto finish; 3855 } 3856 3857 result = theKext->load(startOpt, startMatchingOpt, personalityNames); 3858 3859 if (result != kOSReturnSuccess) { 3860 OSKextLog(theKext, 3861 kOSKextLogErrorLevel | 3862 kOSKextLogLoadFlag, 3863 "Failed to load kext %s (error 0x%x).", 3864 kextIdentifier->getCStringNoCopy(), (int)result); 3865 3866 OSKext::removeKext(theKext, 3867 /* terminateService/removePersonalities */ true); 3868 goto finish; 3869 } 3870 3871 if (delayAutounloadFlag) { 3872 OSKextLog(theKext, 3873 kOSKextLogProgressLevel | 3874 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 3875 "Setting delayed autounload for %s.", 3876 kextIdentifier->getCStringNoCopy()); 3877 theKext->flags.delayAutounload = 1; 3878 } 3879 3880 finish: 3881 OSSafeRelease(loadRequest); 3882 OSSafeRelease(kextIdentifierSymbol); 3883 3884 IORecursiveLockUnlock(sKextLock); 3885 3886 return result; 3887 } 3888 3889 /********************************************************************* 3890 *********************************************************************/ 3891 /* static */ 3892 void 3893 OSKext::recordIdentifierRequest( 3894 OSString * kextIdentifier) 3895 { 3896 const OSSymbol * kextIdentifierSymbol = NULL; // must release 3897 bool fail = false; 3898 3899 if (!sAllKextLoadIdentifiers || !kextIdentifier) { 3900 goto finish; 3901 } 3902 3903 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 3904 if (!kextIdentifierSymbol) { 3905 // xxx - this is really a basic alloc failure 3906 fail = true; 3907 goto finish; 3908 } 3909 3910 if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) { 3911 if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol)) { 3912 fail = true; 3913 } else { 3914 // xxx - need to find a way to associate this whole func w/the kext 3915 OSKextLog(/* kext */ NULL, 3916 // xxx - check level 3917 kOSKextLogStepLevel | 3918 kOSKextLogArchiveFlag, 3919 "Recorded kext %s as a candidate for inclusion in prelinked kernel.", 3920 kextIdentifier->getCStringNoCopy()); 3921 } 3922 } 3923 finish: 3924 3925 if (fail) { 3926 OSKextLog(/* kext */ NULL, 3927 kOSKextLogErrorLevel | 3928 kOSKextLogArchiveFlag, 3929 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.", 3930 kextIdentifier->getCStringNoCopy()); 3931 } 3932 OSSafeRelease(kextIdentifierSymbol); 3933 return; 3934 } 3935 3936 /********************************************************************* 3937 *********************************************************************/ 3938 OSReturn 3939 OSKext::load( 3940 OSKextExcludeLevel startOpt, 3941 OSKextExcludeLevel startMatchingOpt, 3942 OSArray * personalityNames) 3943 { 3944 OSReturn result = kOSReturnError; 3945 kern_return_t kxldResult; 3946 OSKextExcludeLevel dependenciesStartOpt = startOpt; 3947 OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt; 3948 unsigned int i, count; 3949 Boolean alreadyLoaded = false; 3950 OSKext * lastLoadedKext = NULL; 3951 3952 if (isLoaded()) { 3953 alreadyLoaded = true; 3954 result = kOSReturnSuccess; 3955 3956 OSKextLog(this, 3957 kOSKextLogDebugLevel | 3958 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 3959 "Kext %s is already loaded.", 3960 getIdentifierCString()); 3961 goto loaded; 3962 } 3963 3964 if (!sLoadEnabled) { 3965 OSKextLog(this, 3966 kOSKextLogErrorLevel | 3967 kOSKextLogLoadFlag, 3968 "Kext loading is disabled (attempt to load kext %s).", 3969 getIdentifierCString()); 3970 result = kOSKextReturnDisabled; 3971 goto finish; 3972 } 3973 3974 /* If we've pushed the next available load tag to the invalid value, 3975 * we can't load any more kexts. 3976 */ 3977 if (sNextLoadTag == kOSKextInvalidLoadTag) { 3978 OSKextLog(this, 3979 kOSKextLogErrorLevel | 3980 kOSKextLogLoadFlag, 3981 "Can't load kext %s - no more load tags to assign.", 3982 getIdentifierCString()); 3983 result = kOSKextReturnNoResources; 3984 goto finish; 3985 } 3986 3987 /* This is a bit of a hack, because we shouldn't be handling 3988 * personalities within the load function. 3989 */ 3990 if (!declaresExecutable()) { 3991 result = kOSReturnSuccess; 3992 goto loaded; 3993 } 3994 3995 /* Are we in safe boot? 3996 */ 3997 if (sSafeBoot && !isLoadableInSafeBoot()) { 3998 OSKextLog(this, 3999 kOSKextLogErrorLevel | 4000 kOSKextLogLoadFlag, 4001 "Can't load kext %s - not loadable during safe boot.", 4002 getIdentifierCString()); 4003 result = kOSKextReturnBootLevel; 4004 goto finish; 4005 } 4006 4007 OSKextLog(this, 4008 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 4009 "Loading kext %s.", 4010 getIdentifierCString()); 4011 4012 4013 if (!sKxldContext) { 4014 kxldResult = kxld_create_context(&sKxldContext, &kern_allocate, 4015 &kxld_log_callback, /* Flags */ (KXLDFlags) 0, 4016 /* cputype */ 0, /* cpusubtype */ 0); 4017 if (kxldResult) { 4018 OSKextLog(this, 4019 kOSKextLogErrorLevel | 4020 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 4021 "Can't load kext %s - failed to create link context.", 4022 getIdentifierCString()); 4023 result = kOSKextReturnNoMemory; 4024 goto finish; 4025 } 4026 } 4027 4028 /* We only need to resolve dependencies once for the whole graph, but 4029 * resolveDependencies will just return if there's no work to do, so it's 4030 * safe to call it more than once. 4031 */ 4032 if (!resolveDependencies()) { 4033 // xxx - check resolveDependencies() for log msg 4034 OSKextLog(this, 4035 kOSKextLogErrorLevel | 4036 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 4037 "Can't load kext %s - failed to resolve library dependencies.", 4038 getIdentifierCString()); 4039 result = kOSKextReturnDependencies; 4040 goto finish; 4041 } 4042 4043 /* If we are excluding just the kext being loaded now (and not its 4044 * dependencies), drop the exclusion level to none so dependencies 4045 * start and/or add their personalities. 4046 */ 4047 if (dependenciesStartOpt == kOSKextExcludeKext) { 4048 dependenciesStartOpt = kOSKextExcludeNone; 4049 } 4050 4051 if (dependenciesStartMatchingOpt == kOSKextExcludeKext) { 4052 dependenciesStartMatchingOpt = kOSKextExcludeNone; 4053 } 4054 4055 /* Load the dependencies, recursively. 4056 */ 4057 count = getNumDependencies(); 4058 for (i = 0; i < count; i++) { 4059 OSKext * dependency = OSDynamicCast(OSKext, 4060 dependencies->getObject(i)); 4061 if (dependency == NULL) { 4062 OSKextLog(this, 4063 kOSKextLogErrorLevel | 4064 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 4065 "Internal error loading kext %s; dependency disappeared.", 4066 getIdentifierCString()); 4067 result = kOSKextReturnInternalError; 4068 goto finish; 4069 } 4070 4071 /* Dependencies must be started accorting to the opt, 4072 * but not given the personality names of the main kext. 4073 */ 4074 result = dependency->load(dependenciesStartOpt, 4075 dependenciesStartMatchingOpt, 4076 /* personalityNames */ NULL); 4077 if (result != KERN_SUCCESS) { 4078 OSKextLog(this, 4079 kOSKextLogErrorLevel | 4080 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 4081 "Dependency %s of kext %s failed to load.", 4082 dependency->getIdentifierCString(), 4083 getIdentifierCString()); 4084 4085 OSKext::removeKext(dependency, 4086 /* terminateService/removePersonalities */ true); 4087 result = kOSKextReturnDependencyLoadError; 4088 4089 goto finish; 4090 } 4091 } 4092 4093 result = loadExecutable(); 4094 if (result != KERN_SUCCESS) { 4095 goto finish; 4096 } 4097 4098 flags.loaded = true; 4099 4100 /* Add the kext to the list of loaded kexts and update the kmod_info 4101 * struct to point to that of the last loaded kext (which is the way 4102 * it's always been done, though I'd rather do them in order now). 4103 */ 4104 lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 4105 sLoadedKexts->setObject(this); 4106 4107 /* Keep the kernel itself out of the kmod list. 4108 */ 4109 if (lastLoadedKext == sKernelKext) { 4110 lastLoadedKext = NULL; 4111 } 4112 4113 if (lastLoadedKext) { 4114 kmod_info->next = lastLoadedKext->kmod_info; 4115 } 4116 4117 /* Make the global kmod list point at the just-loaded kext. Note that the 4118 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard, 4119 * although we do report it in kextstat these days by using the newer 4120 * OSArray of loaded kexts, which does contain it. 4121 * 4122 * (The OSKext object representing the kernel doesn't even have a kmod_info 4123 * struct, though I suppose we could stick a pointer to it from the 4124 * static struct in OSRuntime.cpp.) 4125 */ 4126 kmod = kmod_info; 4127 4128 /* Save the list of loaded kexts in case we panic. 4129 */ 4130 clock_get_uptime(&last_loaded_timestamp); 4131 OSKext::saveLoadedKextPanicList(); 4132 4133 loaded: 4134 4135 if (declaresExecutable() && (startOpt == kOSKextExcludeNone)) { 4136 result = start(); 4137 if (result != kOSReturnSuccess) { 4138 OSKextLog(this, 4139 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 4140 "Kext %s start failed (result 0x%x).", 4141 getIdentifierCString(), result); 4142 result = kOSKextReturnStartStopError; 4143 } 4144 } 4145 4146 /* If not excluding matching, send the personalities to the kernel. 4147 * This never affects the result of the load operation. 4148 * This is a bit of a hack, because we shouldn't be handling 4149 * personalities within the load function. 4150 */ 4151 if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) { 4152 result = sendPersonalitiesToCatalog(true, personalityNames); 4153 } 4154 finish: 4155 4156 /* More hack! If the kext doesn't declare an executable, even if we 4157 * "loaded" it, we have to remove any personalities naming it, or we'll 4158 * never see the registry go quiet. Errors here do not count for the 4159 * load operation itself. 4160 * 4161 * Note that in every other regard it's perfectly ok for a kext to 4162 * not declare an executable and serve only as a package for personalities 4163 * naming another kext, so we do have to allow such kexts to be "loaded" 4164 * so that those other personalities get added & matched. 4165 */ 4166 if (!declaresExecutable()) { 4167 OSKextLog(this, 4168 kOSKextLogStepLevel | kOSKextLogLoadFlag, 4169 "Kext %s has no executable; removing any personalities naming it.", 4170 getIdentifierCString()); 4171 removePersonalitiesFromCatalog(); 4172 } 4173 4174 if (result != kOSReturnSuccess) { 4175 OSKextLog(this, 4176 kOSKextLogErrorLevel | 4177 kOSKextLogLoadFlag, 4178 "Kext %s failed to load (0x%x).", 4179 getIdentifierCString(), (int)result); 4180 } else if (!alreadyLoaded) { 4181 OSKextLog(this, 4182 kOSKextLogProgressLevel | 4183 kOSKextLogLoadFlag, 4184 "Kext %s loaded.", 4185 getIdentifierCString()); 4186 } 4187 return result; 4188 } 4189 4190 /********************************************************************* 4191 * called only by load() 4192 *********************************************************************/ 4193 OSReturn 4194 OSKext::loadExecutable() 4195 { 4196 OSReturn result = kOSReturnError; 4197 kern_return_t kxldResult; 4198 u_char ** kxlddeps = NULL; // must kfree 4199 uint32_t num_kxlddeps = 0; 4200 uint32_t num_kmod_refs = 0; 4201 u_char * linkStateBytes = NULL; // do not free 4202 u_long linkStateLength = 0; 4203 u_char ** linkStateBytesPtr = NULL; // do not free 4204 u_long * linkStateLengthPtr = NULL; // do not free 4205 struct mach_header ** kxldHeaderPtr = NULL; // do not free 4206 struct mach_header * kxld_header = NULL; // xxx - need to free here? 4207 OSData * theExecutable = NULL; // do not release 4208 OSString * versString = NULL; // do not release 4209 const char * versCString = NULL; // do not free 4210 const char * string = NULL; // do not free 4211 unsigned int i; 4212 4213 /* We need the version string for a variety of bits below. 4214 */ 4215 versString = OSDynamicCast(OSString, 4216 getPropertyForHostArch(kCFBundleVersionKey)); 4217 if (!versString) { 4218 goto finish; 4219 } 4220 versCString = versString->getCStringNoCopy(); 4221 4222 if (isKernelComponent()) { 4223 if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) { 4224 if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) { 4225 OSKextLog(this, 4226 kOSKextLogErrorLevel | 4227 kOSKextLogLoadFlag, 4228 "Kernel component %s has incorrect version %s; " 4229 "expected %s.", 4230 getIdentifierCString(), 4231 versCString, KERNEL6_VERSION); 4232 result = kOSKextReturnInternalError; 4233 goto finish; 4234 } else if (strcmp(versCString, osrelease)) { 4235 OSKextLog(this, 4236 kOSKextLogErrorLevel | 4237 kOSKextLogLoadFlag, 4238 "Kernel component %s has incorrect version %s; " 4239 "expected %s.", 4240 getIdentifierCString(), 4241 versCString, osrelease); 4242 result = kOSKextReturnInternalError; 4243 goto finish; 4244 } 4245 } 4246 } 4247 4248 if (isPrelinked()) { 4249 goto register_kmod; 4250 } 4251 4252 theExecutable = getExecutable(); 4253 if (!theExecutable) { 4254 if (declaresExecutable()) { 4255 OSKextLog(this, 4256 kOSKextLogErrorLevel | 4257 kOSKextLogLoadFlag, 4258 "Can't load kext %s - executable is missing.", 4259 getIdentifierCString()); 4260 result = kOSKextReturnValidation; 4261 goto finish; 4262 } 4263 goto register_kmod; 4264 } 4265 4266 if (isKernelComponent()) { 4267 num_kxlddeps = 1; // the kernel itself 4268 } else { 4269 num_kxlddeps = getNumDependencies(); 4270 } 4271 if (!num_kxlddeps) { 4272 OSKextLog(this, 4273 kOSKextLogErrorLevel | 4274 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 4275 "Can't load kext %s - it has no library dependencies.", 4276 getIdentifierCString()); 4277 goto finish; 4278 } 4279 kxlddeps = (u_char **)kalloc(num_kxlddeps * sizeof(*kxlddeps)); 4280 if (!kxlddeps) { 4281 OSKextLog(this, 4282 kOSKextLogErrorLevel | 4283 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 4284 "Can't allocate link context to load kext %s.", 4285 getIdentifierCString()); 4286 goto finish; 4287 } 4288 4289 if (isKernelComponent()) { 4290 OSData * kernelLinkState = OSKext::getKernelLinkState(); 4291 kxlddeps[0] = (u_char *)kernelLinkState->getBytesNoCopy(); 4292 } else for (i = 0; i < num_kxlddeps; i++) { 4293 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i)); 4294 if (!dependency->linkState) { 4295 // xxx - maybe we should panic here 4296 OSKextLog(this, 4297 kOSKextLogErrorLevel | 4298 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 4299 "Can't load kext %s - link state missing.", 4300 getIdentifierCString()); 4301 goto finish; 4302 } 4303 kxlddeps[i] = (u_char *)dependency->linkState->getBytesNoCopy(); 4304 assert(kxlddeps[i]); 4305 } 4306 4307 /* We only need link state for a library kext. 4308 */ 4309 if (compatibleVersion > -1 && (declaresExecutable() || isKernelComponent())) { 4310 linkStateBytesPtr = &linkStateBytes; 4311 linkStateLengthPtr = &linkStateLength; 4312 } 4313 4314 /* We only need the linked executable for a real kext. 4315 */ 4316 if (!isInterface()) { 4317 kxldHeaderPtr = &kxld_header; 4318 } 4319 4320 #if DEBUG 4321 OSKextLog(this, 4322 kOSKextLogExplicitLevel | 4323 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 4324 "Kext %s - calling kxld_link_file:\n" 4325 " kxld_context: %p\n" 4326 " executable: %p executable_length: %d\n" 4327 " user_data: %p\n" 4328 " kxld_dependencies: %p num_dependencies: %d\n" 4329 " kxld_header_ptr: %p kmod_info_ptr: %p\n" 4330 " link_state_ptr: %p link_state_length_ptr: %p", 4331 getIdentifierCString(), kxldContext, 4332 theExecutable->getBytesNoCopy(), theExecutable->getLength(), 4333 this, kxlddeps, num_kxlddeps, 4334 kxldHeaderPtr, kernelKmodInfoPtr, 4335 linkStateBytesPtr, linkStateLengthPtr); 4336 #endif 4337 4338 /* After this call, the linkedExecutable instance variable 4339 * should exist. 4340 */ 4341 kxldResult = kxld_link_file(sKxldContext, 4342 (u_char *)theExecutable->getBytesNoCopy(), 4343 theExecutable->getLength(), 4344 getIdentifierCString(), this, kxlddeps, num_kxlddeps, 4345 (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info, 4346 linkStateBytesPtr, linkStateLengthPtr, 4347 /* symbolFile */ NULL, /* symbolFileSize */ NULL); 4348 4349 if (kxldResult != KERN_SUCCESS) { 4350 // xxx - add kxldResult here? 4351 OSKextLog(this, 4352 kOSKextLogErrorLevel | 4353 kOSKextLogLoadFlag, 4354 "Can't load kext %s - link failed.", 4355 getIdentifierCString()); 4356 result = kOSKextReturnLinkError; 4357 goto finish; 4358 } 4359 4360 /* If we got a link state, wrap it in an OSData and keep it 4361 * around for later use linking other kexts that depend on this kext. 4362 */ 4363 if (linkStateBytes && linkStateLength > 0) { 4364 linkState = OSData::withBytesNoCopy(linkStateBytes, linkStateLength); 4365 assert(linkState); 4366 linkState->setDeallocFunction(&osdata_kmem_free); 4367 } 4368 4369 /* If this isn't an interface, We've written data & instructions into kernel 4370 * memory, so flush the data cache and invalidate the instruction cache. 4371 */ 4372 if (!isInterface()) { 4373 flush_dcache(kmod_info->address, kmod_info->size, false); 4374 invalidate_icache(kmod_info->address, kmod_info->size, false); 4375 } 4376 4377 register_kmod: 4378 4379 if (isInterface()) { 4380 4381 /* Whip up a fake kmod_info entry for the interface kext. 4382 */ 4383 kmod_info = (kmod_info_t *)kalloc(sizeof(kmod_info_t)); 4384 if (!kmod_info) { 4385 result = KERN_MEMORY_ERROR; 4386 goto finish; 4387 } 4388 4389 /* A pseudokext has almost nothing in its kmod_info struct. 4390 */ 4391 bzero(kmod_info, sizeof(kmod_info_t)); 4392 4393 kmod_info->info_version = KMOD_INFO_VERSION; 4394 4395 /* An interface kext doesn't have a linkedExecutable, so save a 4396 * copy of the UUID out of the original executable via copyUUID() 4397 * while we still have the original executable. 4398 */ 4399 interfaceUUID = copyUUID(); 4400 } 4401 4402 kmod_info->id = loadTag = sNextLoadTag++; 4403 kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid). 4404 4405 /* Stamp the bundle ID and version from the OSKext over anything 4406 * resident inside the kmod_info. 4407 */ 4408 string = getIdentifierCString(); 4409 strlcpy(kmod_info->name, string, sizeof(kmod_info->name)); 4410 4411 string = versCString; 4412 strlcpy(kmod_info->version, string, sizeof(kmod_info->version)); 4413 4414 /* Add the dependencies' kmod_info structs as kmod_references. 4415 */ 4416 num_kmod_refs = getNumDependencies(); 4417 if (num_kmod_refs) { 4418 kmod_info->reference_list = (kmod_reference_t *)kalloc( 4419 num_kmod_refs * sizeof(kmod_reference_t)); 4420 if (!kmod_info->reference_list) { 4421 result = KERN_MEMORY_ERROR; 4422 goto finish; 4423 } 4424 bzero(kmod_info->reference_list, 4425 num_kmod_refs * sizeof(kmod_reference_t)); 4426 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 4427 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 4428 OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex)); 4429 ref->info = refKext->kmod_info; 4430 ref->info->reference_count++; 4431 4432 if (refIndex + 1 < num_kmod_refs) { 4433 ref->next = kmod_info->reference_list + refIndex + 1; 4434 } 4435 } 4436 } 4437 4438 if (!isInterface() && linkedExecutable) { 4439 OSKextLog(this, 4440 kOSKextLogProgressLevel | 4441 kOSKextLogLoadFlag, 4442 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).", 4443 kmod_info->name, 4444 (unsigned)kmod_info->size / PAGE_SIZE, 4445 (unsigned long)kmod_info->address, 4446 (unsigned)kmod_info->id); 4447 } 4448 4449 result = setVMProtections(); 4450 if (result != KERN_SUCCESS) { 4451 goto finish; 4452 } 4453 4454 result = kOSReturnSuccess; 4455 4456 finish: 4457 if (kxlddeps) kfree(kxlddeps, (num_kxlddeps * sizeof(void *))); 4458 4459 /* We no longer need the unrelocated executable (which the linker 4460 * has altered anyhow). 4461 */ 4462 setExecutable(NULL); 4463 4464 if (result != kOSReturnSuccess) { 4465 OSKextLog(this, 4466 kOSKextLogErrorLevel | 4467 kOSKextLogLoadFlag, 4468 "Failed to load executable for kext %s.", 4469 getIdentifierCString()); 4470 4471 if (kmod_info && kmod_info->reference_list) { 4472 kfree(kmod_info->reference_list, 4473 num_kmod_refs * sizeof(kmod_reference_t)); 4474 } 4475 if (isInterface()) { 4476 kfree(kmod_info, sizeof(kmod_info_t)); 4477 } 4478 kmod_info = NULL; 4479 if (linkedExecutable) { 4480 linkedExecutable->release(); 4481 linkedExecutable = NULL; 4482 } 4483 } 4484 4485 return result; 4486 } 4487 4488 /********************************************************************* 4489 * xxx - initWithPrelinkedInfoDict doesn't use this 4490 *********************************************************************/ 4491 void 4492 OSKext::setLinkedExecutable(OSData * anExecutable) 4493 { 4494 if (linkedExecutable) { 4495 panic("Attempt to set linked executable on kext " 4496 "that already has one (%s).\n", 4497 getIdentifierCString()); 4498 } 4499 linkedExecutable = anExecutable; 4500 linkedExecutable->retain(); 4501 return; 4502 } 4503 4504 /********************************************************************* 4505 * called only by loadExecutable() 4506 *********************************************************************/ 4507 OSReturn 4508 OSKext::setVMProtections(void) 4509 { 4510 vm_map_t kext_map = NULL; 4511 kernel_segment_command_t * seg = NULL; 4512 vm_map_offset_t start = 0; 4513 vm_map_offset_t end = 0; 4514 OSReturn result = kOSReturnError; 4515 4516 if (!kmod_info->address && !kmod_info->size) { 4517 result = kOSReturnSuccess; 4518 goto finish; 4519 } 4520 4521 /* Get the kext's vm map */ 4522 kext_map = kext_get_vm_map(kmod_info); 4523 if (!kext_map) { 4524 result = KERN_MEMORY_ERROR; 4525 goto finish; 4526 } 4527 4528 /* XXX: On arm, the vme covering the prelinked kernel (really, the whole 4529 * range from 0xc0000000 to a little over 0xe0000000) has maxprot set to 0 4530 * so the vm_map_protect calls below fail 4531 * I believe this happens in the call to vm_map_enter in kmem_init but I 4532 * need to confirm. 4533 */ 4534 /* Protect the headers as read-only; they do not need to be wired */ 4535 result = vm_map_protect(kext_map, kmod_info->address, 4536 kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE); 4537 if (result != KERN_SUCCESS) { 4538 goto finish; 4539 } 4540 4541 /* Set the VM protections and wire down each of the segments */ 4542 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 4543 while (seg) { 4544 start = round_page(seg->vmaddr); 4545 end = trunc_page(seg->vmaddr + seg->vmsize); 4546 4547 result = vm_map_protect(kext_map, start, end, seg->maxprot, TRUE); 4548 if (result != KERN_SUCCESS) { 4549 OSKextLog(this, 4550 kOSKextLogErrorLevel | 4551 kOSKextLogLoadFlag, 4552 "Kext %s failed to set maximum VM protections " 4553 "for segment %s - 0x%x.", 4554 getIdentifierCString(), seg->segname, (int)result); 4555 goto finish; 4556 } 4557 4558 result = vm_map_protect(kext_map, start, end, seg->initprot, FALSE); 4559 if (result != KERN_SUCCESS) { 4560 OSKextLog(this, 4561 kOSKextLogErrorLevel | 4562 kOSKextLogLoadFlag, 4563 "Kext %s failed to set initial VM protections " 4564 "for segment %s - 0x%x.", 4565 getIdentifierCString(), seg->segname, (int)result); 4566 goto finish; 4567 } 4568 4569 result = vm_map_wire(kext_map, start, end, seg->initprot, FALSE); 4570 if (result != KERN_SUCCESS) { 4571 goto finish; 4572 } 4573 4574 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 4575 } 4576 4577 finish: 4578 return result; 4579 } 4580 4581 /********************************************************************* 4582 *********************************************************************/ 4583 OSReturn 4584 OSKext::validateKextMapping(bool startFlag) 4585 { 4586 OSReturn result = kOSReturnError; 4587 const char * whichOp = startFlag ? "start" : "stop"; 4588 kern_return_t kern_result = 0; 4589 vm_map_t kext_map = NULL; 4590 mach_vm_address_t address = 0; 4591 mach_vm_size_t size = 0; 4592 uint32_t depth = 0; 4593 mach_msg_type_number_t count; 4594 vm_region_submap_short_info_data_64_t info; 4595 4596 count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 4597 bzero(&info, sizeof(info)); 4598 4599 // xxx - do we need a distinct OSReturn value for these or is "bad data" 4600 // xxx - sufficient? 4601 4602 /* Verify that the kmod_info and start/stop pointers are non-NULL. 4603 */ 4604 if (!kmod_info) { 4605 OSKextLog(this, 4606 kOSKextLogErrorLevel | 4607 kOSKextLogLoadFlag, 4608 "Kext %s - NULL kmod_info pointer.", 4609 getIdentifierCString()); 4610 result = kOSKextReturnBadData; 4611 goto finish; 4612 } 4613 4614 if (startFlag) { 4615 address = (mach_vm_address_t)kmod_info->start; 4616 } else { 4617 address = (mach_vm_address_t)kmod_info->stop; 4618 } 4619 4620 if (!address) { 4621 OSKextLog(this, 4622 kOSKextLogErrorLevel | 4623 kOSKextLogLoadFlag, 4624 "Kext %s - NULL module %s pointer.", 4625 getIdentifierCString(), whichOp); 4626 result = kOSKextReturnBadData; 4627 goto finish; 4628 } 4629 4630 kext_map = kext_get_vm_map(kmod_info); 4631 depth = (kernel_map == kext_map) ? 1 : 2; 4632 4633 /* Verify that the start/stop function lies within the kext's address range. 4634 */ 4635 if (address < kmod_info->address + kmod_info->hdr_size || 4636 kmod_info->address + kmod_info->size <= address) 4637 { 4638 OSKextLog(this, 4639 kOSKextLogErrorLevel | 4640 kOSKextLogLoadFlag, 4641 "Kext %s module %s pointer is outside of kext range " 4642 "(%s %p - kext at %p-%p)..", 4643 getIdentifierCString(), 4644 whichOp, 4645 whichOp, 4646 (void *)address, 4647 (void *)kmod_info->address, 4648 (void *)(kmod_info->address + kmod_info->size)); 4649 result = kOSKextReturnBadData; 4650 goto finish; 4651 } 4652 4653 /* Only do these checks before calling the start function; 4654 * If anything goes wrong with the mapping while the kext is running, 4655 * we'll likely have panicked well before any attempt to stop the kext. 4656 */ 4657 if (startFlag) { 4658 4659 /* Verify that the start/stop function is executable. 4660 */ 4661 kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth, 4662 (vm_region_recurse_info_t)&info, &count); 4663 if (kern_result != KERN_SUCCESS) { 4664 OSKextLog(this, 4665 kOSKextLogErrorLevel | 4666 kOSKextLogLoadFlag, 4667 "Kext %s - bad %s pointer %p.", 4668 getIdentifierCString(), 4669 whichOp, (void *)address); 4670 result = kOSKextReturnBadData; 4671 goto finish; 4672 } 4673 4674 if (!(info.protection & VM_PROT_EXECUTE)) { 4675 OSKextLog(this, 4676 kOSKextLogErrorLevel | 4677 kOSKextLogLoadFlag, 4678 "Kext %s - memory region containing module %s function " 4679 "is not executable.", 4680 getIdentifierCString(), whichOp); 4681 result = kOSKextReturnBadData; 4682 goto finish; 4683 } 4684 4685 /* Verify that the kext is backed by physical memory. 4686 */ 4687 for (address = kmod_info->address; 4688 address < round_page(kmod_info->address + kmod_info->size); 4689 address += PAGE_SIZE) 4690 { 4691 if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) { 4692 OSKextLog(this, 4693 kOSKextLogErrorLevel | 4694 kOSKextLogLoadFlag, 4695 "Kext %s - page %p is not backed by physical memory.", 4696 getIdentifierCString(), 4697 (void *)address); 4698 result = kOSKextReturnBadData; 4699 goto finish; 4700 } 4701 } 4702 } 4703 4704 result = kOSReturnSuccess; 4705 finish: 4706 return result; 4707 } 4708 4709 /********************************************************************* 4710 *********************************************************************/ 4711 OSReturn 4712 OSKext::start(bool startDependenciesFlag) 4713 { 4714 OSReturn result = kOSReturnError; 4715 kern_return_t (* startfunc)(kmod_info_t *, void *); 4716 unsigned int i, count; 4717 void * kmodStartData = NULL; // special handling needed 4718 #if CONFIG_MACF_KEXT 4719 mach_msg_type_number_t kmodStartDataCount = 0; 4720 #endif /* CONFIG_MACF_KEXT */ 4721 4722 if (isStarted() || isInterface() || isKernelComponent()) { 4723 result = kOSReturnSuccess; 4724 goto finish; 4725 } 4726 4727 if (!isLoaded()) { 4728 OSKextLog(this, 4729 kOSKextLogErrorLevel | 4730 kOSKextLogLoadFlag, 4731 "Attempt to start nonloaded kext %s.", 4732 getIdentifierCString()); 4733 result = kOSKextReturnInvalidArgument; 4734 goto finish; 4735 } 4736 4737 if (!sLoadEnabled) { 4738 OSKextLog(this, 4739 kOSKextLogErrorLevel | 4740 kOSKextLogLoadFlag, 4741 "Kext loading is disabled (attempt to start kext %s).", 4742 getIdentifierCString()); 4743 result = kOSKextReturnDisabled; 4744 goto finish; 4745 } 4746 4747 result = validateKextMapping(/* start? */ true); 4748 if (result != kOSReturnSuccess) { 4749 goto finish; 4750 } 4751 4752 startfunc = kmod_info->start; 4753 4754 count = getNumDependencies(); 4755 for (i = 0; i < count; i++) { 4756 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i)); 4757 if (dependency == NULL) { 4758 OSKextLog(this, 4759 kOSKextLogErrorLevel | 4760 kOSKextLogLoadFlag, 4761 "Kext %s start - internal error, dependency disappeared.", 4762 getIdentifierCString()); 4763 goto finish; 4764 } 4765 if (!dependency->isStarted()) { 4766 if (startDependenciesFlag) { 4767 OSReturn dependencyResult = 4768 dependency->start(startDependenciesFlag); 4769 if (dependencyResult != KERN_SUCCESS) { 4770 OSKextLog(this, 4771 kOSKextLogErrorLevel | 4772 kOSKextLogLoadFlag, 4773 "Kext %s start - dependency %s failed to start (error 0x%x).", 4774 getIdentifierCString(), 4775 dependency->getIdentifierCString(), 4776 dependencyResult); 4777 goto finish; 4778 } 4779 } else { 4780 OSKextLog(this, 4781 kOSKextLogErrorLevel | 4782 kOSKextLogLoadFlag, 4783 "Not starting %s - dependency %s not started yet.", 4784 getIdentifierCString(), 4785 dependency->getIdentifierCString()); 4786 result = kOSKextReturnStartStopError; // xxx - make new return? 4787 goto finish; 4788 } 4789 } 4790 } 4791 4792 #if CONFIG_MACF_KEXT 4793 /* See if the kext has any MAC framework module data in its plist. 4794 * This is passed in as arg #2 of the kext's start routine, 4795 * which is otherwise reserved for any other kext. 4796 */ 4797 kmodStartData = MACFCopyModuleDataForKext(this, &kmodStartDataCount); 4798 #endif /* CONFIG_MACF_KEXT */ 4799 4800 OSKextLog(this, 4801 kOSKextLogDetailLevel | 4802 kOSKextLogLoadFlag, 4803 "Kext %s calling module start function.", 4804 getIdentifierCString()); 4805 4806 flags.starting = 1; 4807 4808 #if !__i386__ && !__ppc__ 4809 result = OSRuntimeInitializeCPP(kmod_info, NULL); 4810 if (result == KERN_SUCCESS) { 4811 #endif 4812 4813 result = startfunc(kmod_info, kmodStartData); 4814 4815 #if !__i386__ && !__ppc__ 4816 if (result != KERN_SUCCESS) { 4817 (void) OSRuntimeFinalizeCPP(kmod_info, NULL); 4818 } 4819 } 4820 #endif 4821 4822 flags.starting = 0; 4823 4824 /* On success overlap the setting of started/starting. On failure just 4825 * clear starting. 4826 */ 4827 if (result == KERN_SUCCESS) { 4828 flags.started = 1; 4829 4830 // xxx - log start error from kernel? 4831 OSKextLog(this, 4832 kOSKextLogProgressLevel | 4833 kOSKextLogLoadFlag, 4834 "Kext %s is now started.", 4835 getIdentifierCString()); 4836 } else { 4837 invokeOrCancelRequestCallbacks( 4838 /* result not actually used */ kOSKextReturnStartStopError, 4839 /* invokeFlag */ false); 4840 OSKextLog(this, 4841 kOSKextLogProgressLevel | 4842 kOSKextLogLoadFlag, 4843 "Kext %s did not start (return code 0x%x).", 4844 getIdentifierCString(), result); 4845 } 4846 4847 finish: 4848 #if CONFIG_MACF_KEXT 4849 /* Free the module data for a MAC framework kext. When we start using 4850 * param #2 we'll have to distinguish and free/release appropriately. 4851 * 4852 * xxx - I'm pretty sure the old codepath freed the data and that it's 4853 * xxx - up to the kext to copy it. 4854 */ 4855 if (kmodStartData) { 4856 kmem_free(kernel_map, (vm_offset_t)kmodStartData, kmodStartDataCount); 4857 } 4858 #endif /* CONFIG_MACF_KEXT */ 4859 4860 return result; 4861 } 4862 4863 /********************************************************************* 4864 *********************************************************************/ 4865 /* static */ 4866 bool OSKext::canUnloadKextWithIdentifier( 4867 OSString * kextIdentifier, 4868 bool checkClassesFlag) 4869 { 4870 bool result = false; 4871 OSKext * aKext = NULL; // do not release 4872 4873 IORecursiveLockLock(sKextLock); 4874 4875 aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 4876 4877 if (!aKext) { 4878 goto finish; // can't unload what's not loaded 4879 } 4880 4881 if (aKext->isLoaded()) { 4882 if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) { 4883 goto finish; 4884 } 4885 if (checkClassesFlag && aKext->hasOSMetaClassInstances()) { 4886 goto finish; 4887 } 4888 } 4889 4890 result = true; 4891 4892 finish: 4893 IORecursiveLockUnlock(sKextLock); 4894 return result; 4895 } 4896 4897 /********************************************************************* 4898 *********************************************************************/ 4899 OSReturn 4900 OSKext::stop(void) 4901 { 4902 OSReturn result = kOSReturnError; 4903 kern_return_t (*stopfunc)(kmod_info_t *, void *); 4904 4905 if (!isStarted() || isInterface()) { 4906 result = kOSReturnSuccess; 4907 goto finish; 4908 } 4909 4910 if (!isLoaded()) { 4911 OSKextLog(this, 4912 kOSKextLogErrorLevel | 4913 kOSKextLogLoadFlag, 4914 "Attempt to stop nonloaded kext %s.", 4915 getIdentifierCString()); 4916 result = kOSKextReturnInvalidArgument; 4917 goto finish; 4918 } 4919 4920 /* Refuse to stop if we have clients or instances. It is up to 4921 * the caller to make sure those aren't true. 4922 */ 4923 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 4924 OSKextLog(this, 4925 kOSKextLogErrorLevel | 4926 kOSKextLogLoadFlag, 4927 "Kext %s - C++ instances; can't stop.", 4928 getIdentifierCString()); 4929 result = kOSKextReturnInUse; 4930 goto finish; 4931 } 4932 4933 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 4934 4935 OSKextLog(this, 4936 kOSKextLogErrorLevel | 4937 kOSKextLogLoadFlag, 4938 "Kext %s - has references (linkage or tracking object); " 4939 "can't stop.", 4940 getIdentifierCString()); 4941 result = kOSKextReturnInUse; 4942 goto finish; 4943 } 4944 4945 /* Note: If validateKextMapping fails on the stop & unload path, 4946 * we are in serious trouble and a kernel panic is likely whether 4947 * we stop & unload the kext or not. 4948 */ 4949 result = validateKextMapping(/* start? */ false); 4950 if (result != kOSReturnSuccess) { 4951 goto finish; 4952 } 4953 4954 /* Save the list of loaded kexts in case we panic. 4955 */ 4956 OSKext::saveUnloadedKextPanicList(this); 4957 4958 stopfunc = kmod_info->stop; 4959 if (stopfunc) { 4960 OSKextLog(this, 4961 kOSKextLogDetailLevel | 4962 kOSKextLogLoadFlag, 4963 "Kext %s calling module stop function.", 4964 getIdentifierCString()); 4965 4966 flags.stopping = 1; 4967 4968 result = stopfunc(kmod_info, /* userData */ NULL); 4969 #if !__i386__ && !__ppc__ 4970 if (result == KERN_SUCCESS) { 4971 result = OSRuntimeFinalizeCPP(kmod_info, NULL); 4972 } 4973 #endif 4974 4975 flags.stopping = 0; 4976 4977 if (result == KERN_SUCCESS) { 4978 flags.started = 0; 4979 4980 OSKextLog(this, 4981 kOSKextLogDetailLevel | 4982 kOSKextLogLoadFlag, 4983 "Kext %s is now stopped and ready to unload.", 4984 getIdentifierCString()); 4985 } else { 4986 OSKextLog(this, 4987 kOSKextLogErrorLevel | 4988 kOSKextLogLoadFlag, 4989 "Kext %s did not stop (return code 0x%x).", 4990 getIdentifierCString(), result); 4991 result = kOSKextReturnStartStopError; 4992 } 4993 } 4994 4995 finish: 4996 return result; 4997 } 4998 4999 /********************************************************************* 5000 *********************************************************************/ 5001 OSReturn 5002 OSKext::unload(void) 5003 { 5004 OSReturn result = kOSReturnError; 5005 unsigned int index; 5006 uint32_t num_kmod_refs = 0; 5007 5008 if (!sUnloadEnabled) { 5009 OSKextLog(this, 5010 kOSKextLogErrorLevel | 5011 kOSKextLogLoadFlag, 5012 "Kext unloading is disabled (%s).", 5013 this->getIdentifierCString()); 5014 5015 result = kOSKextReturnDisabled; 5016 goto finish; 5017 } 5018 5019 /* Refuse to unload if we have clients or instances. It is up to 5020 * the caller to make sure those aren't true. 5021 */ 5022 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 5023 // xxx - Don't log under errors? this is more of an info thing 5024 OSKextLog(this, 5025 kOSKextLogErrorLevel | 5026 kOSKextLogKextBookkeepingFlag, 5027 "Can't unload kext %s; outstanding references (linkage or tracking object).", 5028 getIdentifierCString()); 5029 result = kOSKextReturnInUse; 5030 goto finish; 5031 } 5032 5033 5034 if (hasOSMetaClassInstances()) { 5035 OSKextLog(this, 5036 kOSKextLogErrorLevel | 5037 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 5038 "Can't unload kext %s; classes have instances:", 5039 getIdentifierCString()); 5040 reportOSMetaClassInstances(kOSKextLogErrorLevel | 5041 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag); 5042 result = kOSKextReturnInUse; 5043 goto finish; 5044 } 5045 5046 if (!isLoaded()) { 5047 result = kOSReturnSuccess; 5048 goto finish; 5049 } 5050 5051 if (isKernelComponent()) { 5052 result = kOSKextReturnInvalidArgument; 5053 goto finish; 5054 } 5055 5056 /* Note that the kext is unloading before running any code that 5057 * might be in the kext (request callbacks, module stop function). 5058 * We will deny certain requests made against a kext in the process 5059 * of unloading. 5060 */ 5061 flags.unloading = 1; 5062 5063 if (isStarted()) { 5064 result = stop(); 5065 if (result != KERN_SUCCESS) { 5066 OSKextLog(this, 5067 kOSKextLogErrorLevel | 5068 kOSKextLogLoadFlag, 5069 "Kext %s can't unload - module stop returned 0x%x.", 5070 getIdentifierCString(), (unsigned)result); 5071 result = kOSKextReturnStartStopError; 5072 goto finish; 5073 } 5074 } 5075 5076 OSKextLog(this, 5077 kOSKextLogProgressLevel | 5078 kOSKextLogLoadFlag, 5079 "Kext %s unloading.", 5080 getIdentifierCString()); 5081 5082 /* Even if we don't call the stop function, we want to be sure we 5083 * have no OSMetaClass references before unloading the kext executable 5084 * from memory. OSMetaClasses may have pointers into the kext executable 5085 * and that would cause a panic on OSKext::free() when metaClasses is freed. 5086 */ 5087 if (metaClasses) { 5088 metaClasses->flushCollection(); 5089 } 5090 5091 /* Remove the kext from the list of loaded kexts, patch the gap 5092 * in the kmod_info_t linked list, and reset "kmod" to point to the 5093 * last loaded kext that isn't the fake kernel kext (sKernelKext). 5094 */ 5095 index = sLoadedKexts->getNextIndexOfObject(this, 0); 5096 if (index != (unsigned int)-1) { 5097 5098 sLoadedKexts->removeObject(index); 5099 5100 OSKext * nextKext = OSDynamicCast(OSKext, 5101 sLoadedKexts->getObject(index)); 5102 5103 if (nextKext) { 5104 if (index > 0) { 5105 OSKext * gapKext = OSDynamicCast(OSKext, 5106 sLoadedKexts->getObject(index - 1)); 5107 5108 nextKext->kmod_info->next = gapKext->kmod_info; 5109 5110 } else /* index == 0 */ { 5111 nextKext->kmod_info->next = NULL; 5112 } 5113 } 5114 5115 OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 5116 if (lastKext && lastKext != sKernelKext) { 5117 kmod = lastKext->kmod_info; 5118 } else { 5119 kmod = NULL; // clear the global kmod variable 5120 } 5121 } 5122 5123 /* Clear out the kmod references that we're keeping for compatibility 5124 * with current panic backtrace code & kgmacros. 5125 * xxx - will want to update those bits sometime and remove this. 5126 */ 5127 num_kmod_refs = getNumDependencies(); 5128 if (num_kmod_refs && kmod_info && kmod_info->reference_list) { 5129 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 5130 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 5131 ref->info->reference_count--; 5132 } 5133 kfree(kmod_info->reference_list, 5134 num_kmod_refs * sizeof(kmod_reference_t)); 5135 } 5136 5137 /* If we have a linked executable, release & clear it, and then 5138 * unwire & deallocate the buffer the OSData wrapped. 5139 */ 5140 if (linkedExecutable) { 5141 vm_map_t kext_map; 5142 5143 /* linkedExecutable is just a wrapper for the executable and doesn't 5144 * free it. 5145 */ 5146 linkedExecutable->release(); 5147 linkedExecutable = NULL; 5148 5149 OSKextLog(this, 5150 kOSKextLogProgressLevel | 5151 kOSKextLogLoadFlag, 5152 "Kext %s unwiring and unmapping linked executable.", 5153 getIdentifierCString()); 5154 5155 kext_map = kext_get_vm_map(kmod_info); 5156 if (kext_map) { 5157 // xxx - do we have to do this before freeing? Why can't we just free it? 5158 // xxx - we should be able to set a dealloc func on the linkedExecutable 5159 result = vm_map_unwire(kext_map, 5160 kmod_info->address + kmod_info->hdr_size, 5161 kmod_info->address + kmod_info->size, FALSE); 5162 if (result == KERN_SUCCESS) { 5163 kext_free(kmod_info->address, kmod_info->size); 5164 } 5165 } 5166 } 5167 5168 /* An interface kext has a fake kmod_info that was allocated, 5169 * so we have to free it. 5170 */ 5171 if (isInterface()) { 5172 kfree(kmod_info, sizeof(kmod_info_t)); 5173 } 5174 5175 kmod_info = NULL; 5176 5177 flags.loaded = false; 5178 flushDependencies(); 5179 5180 OSKextLog(this, 5181 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5182 "Kext %s unloaded.", getIdentifierCString()); 5183 5184 finish: 5185 OSKext::saveLoadedKextPanicList(); 5186 5187 flags.unloading = 0; 5188 return result; 5189 } 5190 5191 /********************************************************************* 5192 *********************************************************************/ 5193 static void 5194 _OSKextConsiderDestroyingLinkContext( 5195 __unused thread_call_param_t p0, 5196 __unused thread_call_param_t p1) 5197 { 5198 /* Once both recursive locks are taken in correct order, we shouldn't 5199 * have to worry about further recursive lock takes. 5200 */ 5201 IORecursiveLockLock(sKextLock); 5202 IORecursiveLockLock(sKextInnerLock); 5203 5204 /* The first time we destroy the kxldContext is in the first 5205 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled 5206 * before calling this function. Thereafter any call to this function 5207 * will actually destroy the context. 5208 */ 5209 if (sConsiderUnloadsCalled && sKxldContext) { 5210 kxld_destroy_context(sKxldContext); 5211 sKxldContext = NULL; 5212 } 5213 5214 /* Free the thread_call that was allocated to execute this function. 5215 */ 5216 if (sDestroyLinkContextThread) { 5217 if (!thread_call_free(sDestroyLinkContextThread)) { 5218 OSKextLog(/* kext */ NULL, 5219 kOSKextLogErrorLevel | 5220 kOSKextLogGeneralFlag, 5221 "thread_call_free() failed for kext link context."); 5222 } 5223 sDestroyLinkContextThread = 0; 5224 } 5225 5226 IORecursiveLockUnlock(sKextInnerLock); 5227 IORecursiveLockUnlock(sKextLock); 5228 5229 return; 5230 } 5231 5232 /********************************************************************* 5233 * Destroying the kxldContext requires checking variables under both 5234 * sKextInnerLock and sKextLock, so we do it on a separate thread 5235 * to avoid deadlocks with IOService, with which OSKext has a reciprocal 5236 * call relationship. 5237 * 5238 * Do not call any function that takes sKextLock here! This function 5239 * can be invoked with sKextInnerLock, and the two must always 5240 * be taken in the order: sKextLock -> sKextInnerLock. 5241 *********************************************************************/ 5242 /* static */ 5243 void 5244 OSKext::considerDestroyingLinkContext(void) 5245 { 5246 IORecursiveLockLock(sKextInnerLock); 5247 5248 /* If we have already queued a thread to destroy the link context, 5249 * don't bother resetting; that thread will take care of it. 5250 */ 5251 if (sDestroyLinkContextThread) { 5252 goto finish; 5253 } 5254 5255 /* The function to be invoked in the thread will deallocate 5256 * this thread_call, so don't share it around. 5257 */ 5258 sDestroyLinkContextThread = thread_call_allocate( 5259 &_OSKextConsiderDestroyingLinkContext, 0); 5260 if (!sDestroyLinkContextThread) { 5261 OSKextLog(/* kext */ NULL, 5262 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag, 5263 "Can't create thread to destroy kext link context."); 5264 goto finish; 5265 } 5266 5267 thread_call_enter(sDestroyLinkContextThread); 5268 5269 finish: 5270 IORecursiveLockUnlock(sKextInnerLock); 5271 return; 5272 } 5273 5274 /********************************************************************* 5275 *********************************************************************/ 5276 OSData * 5277 OSKext::getKernelLinkState() 5278 { 5279 kern_return_t kxldResult; 5280 u_char * kernel = NULL; 5281 size_t kernelLength; 5282 u_char * linkStateBytes = NULL; 5283 u_long linkStateLength; 5284 OSData * linkState = NULL; 5285 5286 if (sKernelKext && sKernelKext->linkState) { 5287 goto finish; 5288 } 5289 5290 kernel = (u_char *)&_mh_execute_header; 5291 kernelLength = getlastaddr() - (vm_offset_t)kernel; 5292 5293 kxldResult = kxld_link_file(sKxldContext, 5294 kernel, 5295 kernelLength, 5296 kOSKextKernelIdentifier, 5297 /* callbackData */ NULL, 5298 /* dependencies */ NULL, 5299 /* numDependencies */ 0, 5300 /* linkedObjectOut */ NULL, 5301 /* kmod_info_kern out */ NULL, 5302 &linkStateBytes, 5303 &linkStateLength, 5304 /* symbolFile */ NULL, 5305 /* symbolFileSize */ NULL); 5306 if (kxldResult) { 5307 panic("Can't generate kernel link state; no kexts can be loaded."); 5308 goto finish; 5309 } 5310 5311 linkState = OSData::withBytesNoCopy(linkStateBytes, linkStateLength); 5312 linkState->setDeallocFunction(&osdata_kmem_free); 5313 sKernelKext->linkState = linkState; 5314 5315 finish: 5316 return sKernelKext->linkState; 5317 } 5318 5319 #if PRAGMA_MARK 5320 #pragma mark Autounload 5321 #endif 5322 /********************************************************************* 5323 * This is a static method because the kext will be deallocated if it 5324 * does unload! 5325 *********************************************************************/ 5326 OSReturn 5327 OSKext::autounloadKext(OSKext * aKext) 5328 { 5329 OSReturn result = kOSKextReturnInUse; 5330 5331 /* Check for external references to this kext (usu. dependents), 5332 * instances of defined classes (or classes derived from them), 5333 * outstanding requests. 5334 */ 5335 if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) || 5336 !aKext->flags.autounloadEnabled || 5337 aKext->isKernelComponent()) { 5338 5339 goto finish; 5340 } 5341 5342 /* Skip a delay-autounload kext, once. 5343 */ 5344 if (aKext->flags.delayAutounload) { 5345 OSKextLog(aKext, 5346 kOSKextLogProgressLevel | 5347 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 5348 "Kext %s has delayed autounload set; skipping and clearing flag.", 5349 aKext->getIdentifierCString()); 5350 aKext->flags.delayAutounload = 0; 5351 goto finish; 5352 } 5353 5354 if (aKext->hasOSMetaClassInstances() || 5355 aKext->countRequestCallbacks()) { 5356 goto finish; 5357 } 5358 5359 result = OSKext::removeKext(aKext); 5360 5361 finish: 5362 5363 return result; 5364 } 5365 5366 /********************************************************************* 5367 *********************************************************************/ 5368 void 5369 _OSKextConsiderUnloads( 5370 __unused thread_call_param_t p0, 5371 __unused thread_call_param_t p1) 5372 { 5373 bool didUnload = false; 5374 unsigned int count, i; 5375 5376 /* Once both recursive locks are taken in correct order, we shouldn't 5377 * have to worry about further recursive lock takes. 5378 */ 5379 IORecursiveLockLock(sKextLock); 5380 IORecursiveLockLock(sKextInnerLock); 5381 5382 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true); 5383 5384 /* If the system is powering down, don't try to unload anything. 5385 */ 5386 if (sSystemSleep) { 5387 goto finish; 5388 } 5389 5390 OSKextLog(/* kext */ NULL, 5391 kOSKextLogProgressLevel | 5392 kOSKextLogLoadFlag, 5393 "Checking for unused kexts to autounload."); 5394 5395 /***** 5396 * Remove any request callbacks marked as stale, 5397 * and mark as stale any currently in flight. 5398 */ 5399 count = sRequestCallbackRecords->getCount(); 5400 if (count) { 5401 i = count - 1; 5402 do { 5403 OSDictionary * callbackRecord = OSDynamicCast(OSDictionary, 5404 sRequestCallbackRecords->getObject(i)); 5405 OSBoolean * stale = OSDynamicCast(OSBoolean, 5406 callbackRecord->getObject(kKextRequestStaleKey)); 5407 5408 if (stale && stale->isTrue()) { 5409 OSKext::invokeRequestCallback(callbackRecord, 5410 kOSKextReturnTimeout); 5411 } else { 5412 callbackRecord->setObject(kKextRequestStaleKey, 5413 kOSBooleanTrue); 5414 } 5415 } while (i--); 5416 } 5417 5418 /***** 5419 * Make multiple passes through the array of loaded kexts until 5420 * we don't unload any. This handles unwinding of dependency 5421 * chains. We have to go *backwards* through the array because 5422 * kexts are removed from it when unloaded, and we cannot make 5423 * a copy or we'll mess up the retain counts we rely on to 5424 * check whether a kext will unload. If only we could have 5425 * nonretaining collections like CF has.... 5426 */ 5427 do { 5428 didUnload = false; 5429 5430 count = sLoadedKexts->getCount(); 5431 if (count) { 5432 i = count - 1; 5433 do { 5434 OSKext * thisKext = OSDynamicCast(OSKext, 5435 sLoadedKexts->getObject(i)); 5436 didUnload = (kOSReturnSuccess == OSKext::autounloadKext(thisKext)); 5437 } while (i--); 5438 } 5439 } while (didUnload); 5440 5441 finish: 5442 sConsiderUnloadsPending = false; 5443 sConsiderUnloadsExecuted = true; 5444 5445 (void) OSKext::considerRebuildOfPrelinkedKernel(); 5446 5447 IORecursiveLockUnlock(sKextInnerLock); 5448 IORecursiveLockUnlock(sKextLock); 5449 5450 return; 5451 } 5452 5453 /********************************************************************* 5454 * Do not call any function that takes sKextLock here! 5455 *********************************************************************/ 5456 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag) 5457 { 5458 AbsoluteTime when; 5459 5460 IORecursiveLockLock(sKextInnerLock); 5461 5462 if (!sUnloadCallout) { 5463 sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, 0); 5464 } 5465 5466 if (rescheduleOnlyFlag && !sConsiderUnloadsPending) { 5467 goto finish; 5468 } 5469 5470 thread_call_cancel(sUnloadCallout); 5471 if (OSKext::getAutounloadEnabled() && !sSystemSleep) { 5472 clock_interval_to_deadline(sConsiderUnloadDelay, 5473 1000 * 1000 * 1000, &when); 5474 5475 OSKextLog(/* kext */ NULL, 5476 kOSKextLogProgressLevel | 5477 kOSKextLogLoadFlag, 5478 "%scheduling %sscan for unused kexts in %lu seconds.", 5479 sConsiderUnloadsPending ? "Res" : "S", 5480 sConsiderUnloadsCalled ? "" : "initial ", 5481 (unsigned long)sConsiderUnloadDelay); 5482 5483 sConsiderUnloadsPending = true; 5484 thread_call_enter_delayed(sUnloadCallout, when); 5485 } 5486 5487 finish: 5488 /* The kxld context should be reused throughout boot. We mark the end of 5489 * period as the first time considerUnloads() is called, and we destroy 5490 * the first kxld context in that function. Afterwards, it will be 5491 * destroyed in flushNonloadedKexts. 5492 */ 5493 if (!sConsiderUnloadsCalled) { 5494 sConsiderUnloadsCalled = true; 5495 OSKext::considerDestroyingLinkContext(); 5496 } 5497 5498 IORecursiveLockUnlock(sKextInnerLock); 5499 return; 5500 } 5501 5502 /********************************************************************* 5503 * Do not call any function that takes sKextLock here! 5504 *********************************************************************/ 5505 extern "C" { 5506 5507 IOReturn OSKextSystemSleepOrWake(UInt32 messageType) 5508 { 5509 IORecursiveLockLock(sKextInnerLock); 5510 5511 /* If the system is going to sleep, cancel the reaper thread timer, 5512 * and note that we're in a sleep state in case it just fired but hasn't 5513 * taken the lock yet. If we are coming back from sleep, just 5514 * clear the sleep flag; IOService's normal operation will cause 5515 * unloads to be considered soon enough. 5516 */ 5517 if (messageType == kIOMessageSystemWillSleep) { 5518 if (sUnloadCallout) { 5519 thread_call_cancel(sUnloadCallout); 5520 } 5521 sSystemSleep = true; 5522 } else if (messageType == kIOMessageSystemHasPoweredOn) { 5523 sSystemSleep = false; 5524 } 5525 IORecursiveLockUnlock(sKextInnerLock); 5526 5527 return kIOReturnSuccess; 5528 } 5529 5530 }; 5531 5532 5533 #if PRAGMA_MARK 5534 #pragma mark Prelinked Kernel 5535 #endif 5536 /********************************************************************* 5537 * Do not access sConsiderUnloads... variables other than 5538 * sConsiderUnloadsExecuted in this function. They are guarded by a 5539 * different lock. 5540 *********************************************************************/ 5541 /* static */ 5542 void 5543 OSKext::considerRebuildOfPrelinkedKernel(void) 5544 { 5545 OSReturn checkResult = kOSReturnError; 5546 static bool requestedPrelink = false; 5547 OSDictionary * prelinkRequest = NULL; // must release 5548 5549 IORecursiveLockLock(sKextLock); 5550 5551 if (!sDeferredLoadSucceeded || !sConsiderUnloadsExecuted || 5552 sSafeBoot || requestedPrelink) 5553 { 5554 goto finish; 5555 } 5556 5557 OSKextLog(/* kext */ NULL, 5558 kOSKextLogProgressLevel | 5559 kOSKextLogArchiveFlag, 5560 "Requesting build of prelinked kernel."); 5561 5562 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink, 5563 &prelinkRequest); 5564 if (checkResult != kOSReturnSuccess) { 5565 goto finish; 5566 } 5567 5568 if (!sKernelRequests->setObject(prelinkRequest)) { 5569 goto finish; 5570 } 5571 5572 OSKextPingKextd(); 5573 requestedPrelink = true; 5574 5575 finish: 5576 IORecursiveLockUnlock(sKextLock); 5577 OSSafeRelease(prelinkRequest); 5578 return; 5579 } 5580 5581 #if PRAGMA_MARK 5582 #pragma mark Dependencies 5583 #endif 5584 /********************************************************************* 5585 *********************************************************************/ 5586 bool 5587 OSKext::resolveDependencies( 5588 OSArray * loopStack) 5589 { 5590 bool result = false; 5591 OSArray * localLoopStack = NULL; // must release 5592 bool addedToLoopStack = false; 5593 OSDictionary * libraries = NULL; // do not release 5594 OSCollectionIterator * libraryIterator = NULL; // must release 5595 OSString * libraryID = NULL; // do not release 5596 OSString * infoString = NULL; // do not release 5597 OSString * readableString = NULL; // do not release 5598 OSKext * libraryKext = NULL; // do not release 5599 bool hasRawKernelDependency = false; 5600 bool hasKernelDependency = false; 5601 bool hasKPIDependency = false; 5602 bool hasPrivateKPIDependency = false; 5603 unsigned int count; 5604 5605 /* A kernel component will automatically have this flag set, 5606 * and a loaded kext should also have it set (as should all its 5607 * loaded dependencies). 5608 */ 5609 if (flags.hasAllDependencies) { 5610 result = true; 5611 goto finish; 5612 } 5613 5614 /* Check for loops in the dependency graph. 5615 */ 5616 if (loopStack) { 5617 if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) { 5618 OSKextLog(this, 5619 kOSKextLogErrorLevel | 5620 kOSKextLogDependenciesFlag, 5621 "Kext %s has a dependency loop; can't resolve dependencies.", 5622 getIdentifierCString()); 5623 goto finish; 5624 } 5625 } else { 5626 OSKextLog(this, 5627 kOSKextLogStepLevel | 5628 kOSKextLogDependenciesFlag, 5629 "Kext %s resolving dependencies.", 5630 getIdentifierCString()); 5631 5632 loopStack = OSArray::withCapacity(6); // any small capacity will do 5633 if (!loopStack) { 5634 OSKextLog(this, 5635 kOSKextLogErrorLevel | 5636 kOSKextLogDependenciesFlag, 5637 "Kext %s can't create bookkeeping stack to resolve dependencies.", 5638 getIdentifierCString()); 5639 goto finish; 5640 } 5641 localLoopStack = loopStack; 5642 } 5643 if (!loopStack->setObject(this)) { 5644 OSKextLog(this, 5645 kOSKextLogErrorLevel | 5646 kOSKextLogDependenciesFlag, 5647 "Kext %s - internal error resolving dependencies.", 5648 getIdentifierCString()); 5649 goto finish; 5650 } 5651 addedToLoopStack = true; 5652 5653 /* Purge any existing kexts in the dependency list and start over. 5654 */ 5655 flushDependencies(); 5656 if (dependencies) { 5657 OSKextLog(this, 5658 kOSKextLogErrorLevel | 5659 kOSKextLogDependenciesFlag, 5660 "Kext %s - internal error resolving dependencies.", 5661 getIdentifierCString()); 5662 } 5663 5664 libraries = OSDynamicCast(OSDictionary, 5665 getPropertyForHostArch(kOSBundleLibrariesKey)); 5666 if (libraries == NULL || libraries->getCount() == 0) { 5667 OSKextLog(this, 5668 kOSKextLogErrorLevel | 5669 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 5670 "Kext %s - can't resolve dependencies; %s missing/invalid type.", 5671 getIdentifierCString(), kOSBundleLibrariesKey); 5672 goto finish; 5673 } 5674 5675 /* Make a new array to hold the dependencies (flush freed the old one). 5676 */ 5677 dependencies = OSArray::withCapacity(libraries->getCount()); 5678 if (!dependencies) { 5679 OSKextLog(this, 5680 kOSKextLogErrorLevel | 5681 kOSKextLogDependenciesFlag, 5682 "Kext %s - can't allocate dependencies array.", 5683 getIdentifierCString()); 5684 goto finish; 5685 } 5686 5687 // xxx - compat: We used to add an implicit dependency on kernel 6.0 5688 // xxx - compat: if none were declared. 5689 5690 libraryIterator = OSCollectionIterator::withCollection(libraries); 5691 if (!libraryIterator) { 5692 OSKextLog(this, 5693 kOSKextLogErrorLevel | 5694 kOSKextLogDependenciesFlag, 5695 "Kext %s - can't allocate dependencies iterator.", 5696 getIdentifierCString()); 5697 goto finish; 5698 } 5699 5700 while ((libraryID = OSDynamicCast(OSString, 5701 libraryIterator->getNextObject()))) { 5702 5703 const char * library_id = libraryID->getCStringNoCopy(); 5704 5705 OSString * libraryVersion = OSDynamicCast(OSString, 5706 libraries->getObject(libraryID)); 5707 if (libraryVersion == NULL) { 5708 OSKextLog(this, 5709 kOSKextLogErrorLevel | 5710 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 5711 "Kext %s - illegal type in OSBundleLibraries.", 5712 getIdentifierCString()); 5713 goto finish; 5714 } 5715 5716 OSKextVersion libraryVers = 5717 OSKextParseVersionString(libraryVersion->getCStringNoCopy()); 5718 if (libraryVers == -1) { 5719 OSKextLog(this, 5720 kOSKextLogErrorLevel | 5721 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 5722 "Kext %s - invalid library version %s.", 5723 getIdentifierCString(), 5724 libraryVersion->getCStringNoCopy()); 5725 goto finish; 5726 } 5727 5728 libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID)); 5729 if (libraryKext == NULL) { 5730 OSKextLog(this, 5731 kOSKextLogErrorLevel | 5732 kOSKextLogDependenciesFlag, 5733 "Kext %s - library kext %s not found.", 5734 getIdentifierCString(), library_id); 5735 goto finish; 5736 } 5737 5738 if (!libraryKext->isCompatibleWithVersion(libraryVers)) { 5739 OSKextLog(this, 5740 kOSKextLogErrorLevel | 5741 kOSKextLogDependenciesFlag, 5742 "Kext %s - library kext %s not compatible " 5743 "with requested version %s.", 5744 getIdentifierCString(), library_id, 5745 libraryVersion->getCStringNoCopy()); 5746 goto finish; 5747 } 5748 5749 if (!libraryKext->resolveDependencies(loopStack)) { 5750 goto finish; 5751 } 5752 5753 /* Add the library directly only if it has an executable to link. 5754 * Otherwise it's just used to collect other dependencies, so put 5755 * *its* dependencies on the list for this kext. 5756 */ 5757 // xxx - We are losing info here; would like to make fake entries or 5758 // xxx - keep these in the dependency graph for loaded kexts. 5759 // xxx - I really want to make kernel components not a special case! 5760 if (libraryKext->declaresExecutable() || 5761 libraryKext->isInterface()) { 5762 5763 if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) { 5764 dependencies->setObject(libraryKext); 5765 5766 OSKextLog(this, 5767 kOSKextLogDetailLevel | 5768 kOSKextLogDependenciesFlag, 5769 "Kext %s added dependency %s.", 5770 getIdentifierCString(), 5771 libraryKext->getIdentifierCString()); 5772 } 5773 } else { 5774 int numLibDependencies = libraryKext->getNumDependencies(); 5775 OSArray * libraryDependencies = libraryKext->getDependencies(); 5776 int index; 5777 5778 if (numLibDependencies) { 5779 // xxx - this msg level should be 1 lower than the per-kext one 5780 OSKextLog(this, 5781 kOSKextLogDetailLevel | 5782 kOSKextLogDependenciesFlag, 5783 "Kext %s pulling %d dependencies from codeless library %s.", 5784 getIdentifierCString(), 5785 numLibDependencies, 5786 libraryKext->getIdentifierCString()); 5787 } 5788 for (index = 0; index < numLibDependencies; index++) { 5789 OSKext * thisLibDependency = OSDynamicCast(OSKext, 5790 libraryDependencies->getObject(index)); 5791 if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) { 5792 dependencies->setObject(thisLibDependency); 5793 OSKextLog(this, 5794 kOSKextLogDetailLevel | 5795 kOSKextLogDependenciesFlag, 5796 "Kext %s added dependency %s from codeless library %s.", 5797 getIdentifierCString(), 5798 thisLibDependency->getIdentifierCString(), 5799 libraryKext->getIdentifierCString()); 5800 } 5801 } 5802 } 5803 5804 if ((strlen(library_id) == strlen(KERNEL_LIB)) && 5805 0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB)-1)) { 5806 5807 hasRawKernelDependency = true; 5808 } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) { 5809 hasKernelDependency = true; 5810 } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) { 5811 hasKPIDependency = true; 5812 if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI)-1)) { 5813 hasPrivateKPIDependency = true; 5814 } 5815 } 5816 } 5817 5818 #if __LP64__ 5819 if (hasRawKernelDependency || hasKernelDependency) { 5820 OSKextLog(this, 5821 kOSKextLogErrorLevel | 5822 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 5823 "Error - kext %s declares %s dependencies. " 5824 "Only %s* dependencies are supported for 64-bit kexts.", 5825 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 5826 goto finish; 5827 } 5828 if (!hasKPIDependency) { 5829 OSKextLog(this, 5830 kOSKextLogWarningLevel | 5831 kOSKextLogDependenciesFlag, 5832 "Warning - kext %s declares no %s* dependencies. " 5833 "If it uses any KPIs, the link may fail with undefined symbols.", 5834 getIdentifierCString(), KPI_LIB_PREFIX); 5835 } 5836 #else /* __LP64__ */ 5837 // xxx - will change to flatly disallow "kernel" dependencies at some point 5838 // xxx - is it invalid to do both "com.apple.kernel" and any 5839 // xxx - "com.apple.kernel.*"? 5840 5841 if (hasRawKernelDependency && hasKernelDependency) { 5842 OSKextLog(this, 5843 kOSKextLogErrorLevel | 5844 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 5845 "Error - kext %s declares dependencies on both " 5846 "%s and %s.", 5847 getIdentifierCString(), KERNEL_LIB, KERNEL6_LIB); 5848 goto finish; 5849 } 5850 5851 if ((hasRawKernelDependency || hasKernelDependency) && hasKPIDependency) { 5852 OSKextLog(this, 5853 kOSKextLogWarningLevel | 5854 kOSKextLogDependenciesFlag, 5855 "Warning - kext %s has immediate dependencies on both " 5856 "%s* and %s* components; use only one style.", 5857 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 5858 } 5859 5860 if (!hasRawKernelDependency && !hasKernelDependency && !hasKPIDependency) { 5861 // xxx - do we want to use validation flag for these too? 5862 OSKextLog(this, 5863 kOSKextLogWarningLevel | 5864 kOSKextLogDependenciesFlag, 5865 "Warning - %s declares no kernel dependencies; using %s.", 5866 getIdentifierCString(), KERNEL6_LIB); 5867 OSKext * kernelKext = OSDynamicCast(OSKext, 5868 sKextsByID->getObject(KERNEL6_LIB)); 5869 if (kernelKext) { 5870 dependencies->setObject(kernelKext); 5871 } else { 5872 OSKextLog(this, 5873 kOSKextLogErrorLevel | 5874 kOSKextLogDependenciesFlag, 5875 "Error - Library %s not found for %s.", 5876 KERNEL6_LIB, getIdentifierCString()); 5877 } 5878 } 5879 5880 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of 5881 * its indirect dependencies to simulate old-style linking. XXX - Should 5882 * check for duplicates. 5883 */ 5884 if (!hasRawKernelDependency && !hasKPIDependency) { 5885 unsigned int i; 5886 5887 count = getNumDependencies(); 5888 5889 /* We add to the dependencies array in this loop, but do not iterate 5890 * past its original count. 5891 */ 5892 for (i = 0; i < count; i++) { 5893 OSKext * dependencyKext = OSDynamicCast(OSKext, 5894 dependencies->getObject(i)); 5895 dependencyKext->addBleedthroughDependencies(dependencies); 5896 } 5897 } 5898 #endif /* __LP64__ */ 5899 5900 if (hasPrivateKPIDependency) { 5901 bool hasApplePrefix = false; 5902 bool infoCopyrightIsValid = false; 5903 bool readableCopyrightIsValid = false; 5904 5905 hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(), 5906 APPLE_KEXT_PREFIX); 5907 5908 infoString = OSDynamicCast(OSString, 5909 getPropertyForHostArch("CFBundleGetInfoString")); 5910 if (infoString) { 5911 infoCopyrightIsValid = 5912 kxld_validate_copyright_string(infoString->getCStringNoCopy()); 5913 } 5914 5915 readableString = OSDynamicCast(OSString, 5916 getPropertyForHostArch("NSHumanReadableCopyright")); 5917 if (readableString) { 5918 readableCopyrightIsValid = 5919 kxld_validate_copyright_string(readableString->getCStringNoCopy()); 5920 } 5921 5922 if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) { 5923 OSKextLog(this, 5924 kOSKextLogErrorLevel | 5925 kOSKextLogDependenciesFlag, 5926 "Error - kext %s declares a dependency on %s. " 5927 "Only Apple kexts may declare a dependency on %s.", 5928 getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI); 5929 goto finish; 5930 } 5931 } 5932 5933 result = true; 5934 flags.hasAllDependencies = 1; 5935 5936 finish: 5937 5938 if (addedToLoopStack) { 5939 count = loopStack->getCount(); 5940 if (count > 0 && (this == loopStack->getObject(count - 1))) { 5941 loopStack->removeObject(count - 1); 5942 } else { 5943 OSKextLog(this, 5944 kOSKextLogErrorLevel | 5945 kOSKextLogDependenciesFlag, 5946 "Kext %s - internal error resolving dependencies.", 5947 getIdentifierCString()); 5948 } 5949 } 5950 5951 if (result && localLoopStack) { 5952 OSKextLog(this, 5953 kOSKextLogStepLevel | 5954 kOSKextLogDependenciesFlag, 5955 "Kext %s successfully resolved dependencies.", 5956 getIdentifierCString()); 5957 } 5958 5959 OSSafeRelease(localLoopStack); 5960 OSSafeRelease(libraryIterator); 5961 5962 return result; 5963 } 5964 5965 /********************************************************************* 5966 *********************************************************************/ 5967 bool 5968 OSKext::addBleedthroughDependencies(OSArray * anArray) 5969 { 5970 bool result = false; 5971 unsigned int dependencyIndex, dependencyCount; 5972 5973 dependencyCount = getNumDependencies(); 5974 5975 for (dependencyIndex = 0; 5976 dependencyIndex < dependencyCount; 5977 dependencyIndex++) { 5978 5979 OSKext * dependency = OSDynamicCast(OSKext, 5980 dependencies->getObject(dependencyIndex)); 5981 if (!dependency) { 5982 OSKextLog(this, 5983 kOSKextLogErrorLevel | 5984 kOSKextLogDependenciesFlag, 5985 "Kext %s - internal error propagating compatibility dependencies.", 5986 getIdentifierCString()); 5987 goto finish; 5988 } 5989 if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) { 5990 anArray->setObject(dependency); 5991 } 5992 dependency->addBleedthroughDependencies(anArray); 5993 } 5994 5995 result = true; 5996 5997 finish: 5998 return result; 5999 } 6000 6001 /********************************************************************* 6002 *********************************************************************/ 6003 bool 6004 OSKext::flushDependencies(bool forceFlag) 6005 { 6006 bool result = false; 6007 6008 /* Only clear the dependencies if the kext isn't loaded; 6009 * we need the info for loaded kexts to track references. 6010 */ 6011 if (!isLoaded() || forceFlag) { 6012 if (dependencies) { 6013 // xxx - check level 6014 OSKextLog(this, 6015 kOSKextLogProgressLevel | 6016 kOSKextLogDependenciesFlag, 6017 "Kext %s flushing dependencies.", 6018 getIdentifierCString()); 6019 OSSafeReleaseNULL(dependencies); 6020 6021 } 6022 if (!isKernelComponent()) { 6023 flags.hasAllDependencies = 0; 6024 } 6025 result = true; 6026 } 6027 6028 return result; 6029 } 6030 6031 /********************************************************************* 6032 *********************************************************************/ 6033 uint32_t 6034 OSKext::getNumDependencies(void) 6035 { 6036 if (!dependencies) { 6037 return 0; 6038 } 6039 return dependencies->getCount(); 6040 } 6041 6042 /********************************************************************* 6043 *********************************************************************/ 6044 OSArray * 6045 OSKext::getDependencies(void) 6046 { 6047 return dependencies; 6048 } 6049 6050 #if PRAGMA_MARK 6051 #pragma mark OSMetaClass Support 6052 #endif 6053 /********************************************************************* 6054 *********************************************************************/ 6055 OSReturn 6056 OSKext::addClass( 6057 OSMetaClass * aClass, 6058 uint32_t numClasses) 6059 { 6060 OSReturn result = kOSMetaClassNoInsKModSet; 6061 6062 if (!metaClasses) { 6063 metaClasses = OSSet::withCapacity(numClasses); 6064 if (!metaClasses) { 6065 goto finish; 6066 } 6067 } 6068 6069 if (metaClasses->containsObject(aClass)) { 6070 OSKextLog(this, 6071 kOSKextLogWarningLevel | 6072 kOSKextLogLoadFlag, 6073 "Notice - kext %s has already registered class %s.", 6074 getIdentifierCString(), 6075 aClass->getClassName()); 6076 result = kOSReturnSuccess; 6077 goto finish; 6078 } 6079 6080 if (!metaClasses->setObject(aClass)) { 6081 goto finish; 6082 } else { 6083 OSKextLog(this, 6084 kOSKextLogDetailLevel | 6085 kOSKextLogLoadFlag, 6086 "Kext %s registered class %s.", 6087 getIdentifierCString(), 6088 aClass->getClassName()); 6089 } 6090 6091 if (!flags.autounloadEnabled) { 6092 const OSMetaClass * metaScan = NULL; // do not release 6093 6094 for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) { 6095 if (metaScan == OSTypeID(IOService)) { 6096 6097 OSKextLog(this, 6098 kOSKextLogProgressLevel | 6099 kOSKextLogLoadFlag, 6100 "Kext %s has IOService subclass %s; enabling autounload.", 6101 getIdentifierCString(), 6102 aClass->getClassName()); 6103 6104 flags.autounloadEnabled = 1; 6105 break; 6106 } 6107 } 6108 } 6109 6110 result = kOSReturnSuccess; 6111 6112 finish: 6113 if (result != kOSReturnSuccess) { 6114 OSKextLog(this, 6115 kOSKextLogErrorLevel | 6116 kOSKextLogLoadFlag, 6117 "Kext %s failed to register class %s.", 6118 getIdentifierCString(), 6119 aClass->getClassName()); 6120 } 6121 6122 return result; 6123 } 6124 6125 /********************************************************************* 6126 *********************************************************************/ 6127 OSReturn 6128 OSKext::removeClass( 6129 OSMetaClass * aClass) 6130 { 6131 OSReturn result = kOSMetaClassNoKModSet; 6132 6133 if (!metaClasses) { 6134 goto finish; 6135 } 6136 6137 if (!metaClasses->containsObject(aClass)) { 6138 OSKextLog(this, 6139 kOSKextLogWarningLevel | 6140 kOSKextLogLoadFlag, 6141 "Notice - kext %s asked to unregister unknown class %s.", 6142 getIdentifierCString(), 6143 aClass->getClassName()); 6144 result = kOSReturnSuccess; 6145 goto finish; 6146 } 6147 6148 OSKextLog(this, 6149 kOSKextLogDetailLevel | 6150 kOSKextLogLoadFlag, 6151 "Kext %s unregistering class %s.", 6152 getIdentifierCString(), 6153 aClass->getClassName()); 6154 6155 metaClasses->removeObject(aClass); 6156 6157 result = kOSReturnSuccess; 6158 6159 finish: 6160 if (result != kOSReturnSuccess) { 6161 OSKextLog(this, 6162 kOSKextLogErrorLevel | 6163 kOSKextLogLoadFlag, 6164 "Failed to unregister kext %s class %s.", 6165 getIdentifierCString(), 6166 aClass->getClassName()); 6167 } 6168 return result; 6169 } 6170 6171 /********************************************************************* 6172 *********************************************************************/ 6173 OSSet * 6174 OSKext::getMetaClasses(void) 6175 { 6176 return metaClasses; 6177 } 6178 6179 /********************************************************************* 6180 *********************************************************************/ 6181 bool 6182 OSKext::hasOSMetaClassInstances(void) 6183 { 6184 bool result = false; 6185 OSCollectionIterator * classIterator = NULL; // must release 6186 OSMetaClass * checkClass = NULL; // do not release 6187 6188 if (!metaClasses) { 6189 goto finish; 6190 } 6191 6192 classIterator = OSCollectionIterator::withCollection(metaClasses); 6193 if (!classIterator) { 6194 // xxx - log alloc failure? 6195 goto finish; 6196 } 6197 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 6198 if (checkClass->getInstanceCount()) { 6199 result = true; 6200 goto finish; 6201 } 6202 } 6203 6204 finish: 6205 6206 OSSafeRelease(classIterator); 6207 return result; 6208 } 6209 6210 /********************************************************************* 6211 *********************************************************************/ 6212 /* static */ 6213 void 6214 OSKext::reportOSMetaClassInstances( 6215 const char * kextIdentifier, 6216 OSKextLogSpec msgLogSpec) 6217 { 6218 OSKext * theKext = NULL; // must release 6219 6220 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 6221 if (!theKext) { 6222 goto finish; 6223 } 6224 6225 theKext->reportOSMetaClassInstances(msgLogSpec); 6226 finish: 6227 OSSafeRelease(theKext); 6228 return; 6229 } 6230 6231 /********************************************************************* 6232 *********************************************************************/ 6233 void 6234 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec) 6235 { 6236 OSCollectionIterator * classIterator = NULL; // must release 6237 OSMetaClass * checkClass = NULL; // do not release 6238 6239 if (!metaClasses) { 6240 goto finish; 6241 } 6242 6243 classIterator = OSCollectionIterator::withCollection(metaClasses); 6244 if (!classIterator) { 6245 goto finish; 6246 } 6247 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 6248 if (checkClass->getInstanceCount()) { 6249 OSKextLog(this, 6250 msgLogSpec, 6251 " Kext %s class %s has %d instance%s.", 6252 getIdentifierCString(), 6253 checkClass->getClassName(), 6254 checkClass->getInstanceCount(), 6255 checkClass->getInstanceCount() == 1 ? "" : "s"); 6256 } 6257 } 6258 6259 finish: 6260 OSSafeRelease(classIterator); 6261 return; 6262 } 6263 6264 #if PRAGMA_MARK 6265 #pragma mark User-Space Requests 6266 #endif 6267 /********************************************************************* 6268 * XXX - this function is a big ugly mess 6269 *********************************************************************/ 6270 /* static */ 6271 OSReturn 6272 OSKext::handleRequest( 6273 host_priv_t hostPriv, 6274 OSKextLogSpec clientLogFilter, 6275 char * requestBuffer, 6276 uint32_t requestLength, 6277 char ** responseOut, 6278 uint32_t * responseLengthOut, 6279 char ** logInfoOut, 6280 uint32_t * logInfoLengthOut) 6281 { 6282 OSReturn result = kOSReturnError; 6283 kern_return_t kmem_result = KERN_FAILURE; 6284 6285 char * response = NULL; // returned by reference 6286 uint32_t responseLength = 0; 6287 6288 OSObject * parsedXML = NULL; // must release 6289 OSDictionary * requestDict = NULL; // do not release 6290 OSString * errorString = NULL; // must release 6291 6292 OSData * responseData = NULL; // must release 6293 OSObject * responseObject = NULL; // must release 6294 6295 OSSerialize * serializer = NULL; // must release 6296 6297 OSArray * logInfoArray = NULL; // must release 6298 6299 OSString * predicate = NULL; // do not release 6300 OSString * kextIdentifier = NULL; // do not release 6301 OSArray * kextIdentifiers = NULL; // do not release 6302 OSKext * theKext = NULL; // do not release 6303 OSBoolean * boolArg = NULL; // do not release 6304 6305 IORecursiveLockLock(sKextLock); 6306 6307 if (responseOut) { 6308 *responseOut = NULL; 6309 *responseLengthOut = 0; 6310 } 6311 if (logInfoOut) { 6312 *logInfoOut = NULL; 6313 *logInfoLengthOut = 0; 6314 } 6315 6316 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 6317 6318 /* XML must be nul-terminated. 6319 */ 6320 if (requestBuffer[requestLength - 1] != '\0') { 6321 OSKextLog(/* kext */ NULL, 6322 kOSKextLogErrorLevel | 6323 kOSKextLogIPCFlag, 6324 "Invalid request from user space (not nul-terminated)."); 6325 result = kOSKextReturnBadData; 6326 goto finish; 6327 } 6328 parsedXML = OSUnserializeXML((const char *)requestBuffer, &errorString); 6329 if (parsedXML) { 6330 requestDict = OSDynamicCast(OSDictionary, parsedXML); 6331 } 6332 if (!requestDict) { 6333 const char * errorCString = "(unknown error)"; 6334 6335 if (errorString && errorString->getCStringNoCopy()) { 6336 errorCString = errorString->getCStringNoCopy(); 6337 } else if (parsedXML) { 6338 errorCString = "not a dictionary"; 6339 } 6340 OSKextLog(/* kext */ NULL, 6341 kOSKextLogErrorLevel | 6342 kOSKextLogIPCFlag, 6343 "Error unserializing request from user space: %s.", 6344 errorCString); 6345 result = kOSKextReturnSerialization; 6346 goto finish; 6347 } 6348 6349 predicate = _OSKextGetRequestPredicate(requestDict); 6350 if (!predicate) { 6351 OSKextLog(/* kext */ NULL, 6352 kOSKextLogErrorLevel | 6353 kOSKextLogIPCFlag, 6354 "Recieved kext request from user space with no predicate."); 6355 result = kOSKextReturnInvalidArgument; 6356 goto finish; 6357 } 6358 6359 OSKextLog(/* kext */ NULL, 6360 kOSKextLogDebugLevel | 6361 kOSKextLogIPCFlag, 6362 "Received '%s' request from user space.", 6363 predicate->getCStringNoCopy()); 6364 6365 result = kOSKextReturnNotPrivileged; 6366 if (hostPriv == HOST_PRIV_NULL) { 6367 if (!predicate->isEqualTo(kKextRequestPredicateGetLoaded) && 6368 !predicate->isEqualTo(kKextRequestPredicateGetKernelLinkState) && 6369 !predicate->isEqualTo(kKextRequestPredicateGetKernelLoadAddress)) { 6370 6371 goto finish; 6372 } 6373 } 6374 6375 /* Get common args in anticipation of use. 6376 */ 6377 kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument( 6378 requestDict, kKextRequestArgumentBundleIdentifierKey)); 6379 kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 6380 requestDict, kKextRequestArgumentBundleIdentifierKey)); 6381 if (kextIdentifier) { 6382 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 6383 } 6384 boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 6385 requestDict, kKextRequestArgumentValueKey)); 6386 6387 result = kOSKextReturnInvalidArgument; 6388 6389 if (predicate->isEqualTo(kKextRequestPredicateStart)) { 6390 if (!kextIdentifier) { 6391 OSKextLog(/* kext */ NULL, 6392 kOSKextLogErrorLevel | 6393 kOSKextLogIPCFlag, 6394 "Invalid arguments to kext start request."); 6395 } else if (!theKext) { 6396 OSKextLog(/* kext */ NULL, 6397 kOSKextLogErrorLevel | 6398 kOSKextLogIPCFlag, 6399 "Kext %s not found for start request.", 6400 kextIdentifier->getCStringNoCopy()); 6401 result = kOSKextReturnNotFound; 6402 } else { 6403 result = theKext->start(); 6404 } 6405 6406 } else if (predicate->isEqualTo(kKextRequestPredicateStop)) { 6407 if (!kextIdentifier) { 6408 OSKextLog(/* kext */ NULL, 6409 kOSKextLogErrorLevel | 6410 kOSKextLogIPCFlag, 6411 "Invalid arguments to kext stop request."); 6412 } else if (!theKext) { 6413 OSKextLog(/* kext */ NULL, 6414 kOSKextLogErrorLevel | 6415 kOSKextLogIPCFlag, 6416 "Kext %s not found for stop request.", 6417 kextIdentifier->getCStringNoCopy()); 6418 result = kOSKextReturnNotFound; 6419 } else { 6420 result = theKext->stop(); 6421 } 6422 6423 } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) { 6424 if (!kextIdentifier) { 6425 OSKextLog(/* kext */ NULL, 6426 kOSKextLogErrorLevel | 6427 kOSKextLogIPCFlag, 6428 "Invalid arguments to kext unload request."); 6429 } else if (!theKext) { 6430 OSKextLog(/* kext */ NULL, 6431 kOSKextLogErrorLevel | 6432 kOSKextLogIPCFlag, 6433 "Kext %s not found for unload request.", 6434 kextIdentifier->getCStringNoCopy()); 6435 result = kOSKextReturnNotFound; 6436 } else { 6437 OSBoolean * terminateFlag = OSDynamicCast(OSBoolean, 6438 _OSKextGetRequestArgument(requestDict, 6439 kKextRequestArgumentTerminateIOServicesKey)); 6440 result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue); 6441 } 6442 6443 } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) { 6444 result = OSKext::dispatchResource(requestDict); 6445 6446 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) { 6447 OSBoolean * delayAutounloadBool = NULL; 6448 6449 delayAutounloadBool = OSDynamicCast(OSBoolean, 6450 _OSKextGetRequestArgument(requestDict, 6451 kKextRequestArgumentDelayAutounloadKey)); 6452 6453 /* If asked to delay autounload, reset the timer if it's currently set. 6454 * (That is, don't schedule an unload if one isn't already pending. 6455 */ 6456 if (delayAutounloadBool == kOSBooleanTrue) { 6457 OSKext::considerUnloads(/* rescheduleOnly? */ true); 6458 } 6459 6460 responseObject = OSDynamicCast(OSObject, 6461 OSKext::copyLoadedKextInfo(kextIdentifiers)); 6462 if (!responseObject) { 6463 result = kOSKextReturnInternalError; 6464 } else { 6465 OSKextLog(/* kext */ NULL, 6466 kOSKextLogDebugLevel | 6467 kOSKextLogIPCFlag, 6468 "Returning loaded kext info."); 6469 result = kOSReturnSuccess; 6470 } 6471 6472 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelLoadAddress)) { 6473 OSNumber * addressNum = NULL; // released as responseObject 6474 kernel_segment_command_t * textseg = getsegbyname("__TEXT"); 6475 6476 if (!textseg) { 6477 OSKextLog(/* kext */ NULL, 6478 kOSKextLogErrorLevel | 6479 kOSKextLogGeneralFlag | kOSKextLogIPCFlag, 6480 "Can't find text segment for kernel load address."); 6481 result = kOSReturnError; 6482 goto finish; 6483 } 6484 6485 OSKextLog(/* kext */ NULL, 6486 kOSKextLogDebugLevel | 6487 kOSKextLogIPCFlag, 6488 "Returning kernel load address 0x%llx.", 6489 (unsigned long long)textseg->vmaddr); 6490 addressNum = OSNumber::withNumber((long long unsigned int)textseg->vmaddr, 6491 8 * sizeof(long long unsigned int)); 6492 responseObject = OSDynamicCast(OSObject, addressNum); 6493 result = kOSReturnSuccess; 6494 6495 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelLinkState)) { 6496 OSKextLog(/* kext */ NULL, 6497 kOSKextLogDebugLevel | 6498 kOSKextLogIPCFlag, 6499 "Returning kernel link state."); 6500 responseData = sKernelKext->linkState; 6501 responseData->retain(); 6502 result = kOSReturnSuccess; 6503 6504 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 6505 6506 /* Hand the current sKernelRequests array to the caller 6507 * (who must release it), and make a new one. 6508 */ 6509 responseObject = OSDynamicCast(OSObject, sKernelRequests); 6510 sKernelRequests = OSArray::withCapacity(0); 6511 sPostedKextLoadIdentifiers->flushCollection(); 6512 OSKextLog(/* kext */ NULL, 6513 kOSKextLogDebugLevel | 6514 kOSKextLogIPCFlag, 6515 "Returning kernel requests."); 6516 result = kOSReturnSuccess; 6517 6518 } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) { 6519 6520 /* Return the set of all requested bundle identifiers */ 6521 responseObject = OSDynamicCast(OSObject, sAllKextLoadIdentifiers); 6522 responseObject->retain(); 6523 OSKextLog(/* kext */ NULL, 6524 kOSKextLogDebugLevel | 6525 kOSKextLogIPCFlag, 6526 "Returning load requests."); 6527 result = kOSReturnSuccess; 6528 } 6529 6530 /********** 6531 * Now we have handle the request, or not. Gather up the response & logging 6532 * info to ship to user space. 6533 *********/ 6534 6535 /* Note: Nothing in OSKext is supposed to retain requestDict, 6536 * but you never know.... 6537 */ 6538 if (requestDict->getRetainCount() > 1) { 6539 OSKextLog(/* kext */ NULL, 6540 kOSKextLogWarningLevel | 6541 kOSKextLogIPCFlag, 6542 "Request from user space still retained by a kext; " 6543 "probable memory leak."); 6544 } 6545 6546 if (responseData && responseObject) { 6547 OSKextLog(/* kext */ NULL, 6548 kOSKextLogErrorLevel | 6549 kOSKextLogIPCFlag, 6550 "Mistakenly generated both data & plist responses to user request " 6551 "(returning only data)."); 6552 } 6553 6554 if (responseData && responseData->getLength() && responseOut) { 6555 6556 response = (char *)responseData->getBytesNoCopy(); 6557 responseLength = responseData->getLength(); 6558 } else if (responseOut && responseObject) { 6559 serializer = OSSerialize::withCapacity(0); 6560 if (!serializer) { 6561 result = kOSKextReturnNoMemory; 6562 goto finish; 6563 } 6564 6565 if (!responseObject->serialize(serializer)) { 6566 OSKextLog(/* kext */ NULL, 6567 kOSKextLogErrorLevel | 6568 kOSKextLogIPCFlag, 6569 "Failed to serialize response to request from user space."); 6570 result = kOSKextReturnSerialization; 6571 goto finish; 6572 } 6573 6574 response = (char *)serializer->text(); 6575 responseLength = serializer->getLength(); 6576 } 6577 6578 if (responseOut && response) { 6579 char * buffer; 6580 6581 /* This kmem_alloc sets the return value of the function. 6582 */ 6583 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, 6584 responseLength); 6585 if (kmem_result != KERN_SUCCESS) { 6586 OSKextLog(/* kext */ NULL, 6587 kOSKextLogErrorLevel | 6588 kOSKextLogIPCFlag, 6589 "Failed to copy response to request from user space."); 6590 result = kmem_result; 6591 goto finish; 6592 } else { 6593 memcpy(buffer, response, responseLength); 6594 *responseOut = buffer; 6595 *responseLengthOut = responseLength; 6596 } 6597 } 6598 6599 finish: 6600 6601 /* Gather up the collected log messages for user space. Any messages 6602 * messages past this call will not make it up as log messages but 6603 * will be in the system log. Note that we ignore the return of the 6604 * serialize; it has no bearing on the operation at hand even if we 6605 * fail to get the log messages. 6606 */ 6607 logInfoArray = OSKext::clearUserSpaceLogFilter(); 6608 6609 if (logInfoArray && logInfoOut && logInfoLengthOut) { 6610 (void)OSKext::serializeLogInfo(logInfoArray, 6611 logInfoOut, logInfoLengthOut); 6612 } 6613 6614 IORecursiveLockUnlock(sKextLock); 6615 6616 OSSafeRelease(requestDict); 6617 OSSafeRelease(errorString); 6618 OSSafeRelease(responseData); 6619 OSSafeRelease(responseObject); 6620 OSSafeRelease(serializer); 6621 OSSafeRelease(logInfoArray); 6622 6623 return result; 6624 } 6625 6626 /********************************************************************* 6627 *********************************************************************/ 6628 /* static */ 6629 OSArray * 6630 OSKext::copyLoadedKextInfo(OSArray * kextIdentifiers) 6631 { 6632 OSArray * result = NULL; 6633 OSDictionary * kextInfo = NULL; // must release 6634 uint32_t count, i; 6635 uint32_t idCount = 0; 6636 uint32_t idIndex = 0; 6637 6638 IORecursiveLockLock(sKextLock); 6639 6640 /* Empty list of bundle ids is equivalent to no list (get all). 6641 */ 6642 if (kextIdentifiers && !kextIdentifiers->getCount()) { 6643 kextIdentifiers = NULL; 6644 } else if (kextIdentifiers) { 6645 idCount = kextIdentifiers->getCount(); 6646 } 6647 6648 count = sLoadedKexts->getCount(); 6649 result = OSArray::withCapacity(count); 6650 if (!result) { 6651 goto finish; 6652 } 6653 for (i = 0; i < count; i++) { 6654 OSKext * thisKext = NULL; // do not release 6655 Boolean includeThis = true; 6656 6657 if (kextInfo) { 6658 kextInfo->release(); 6659 kextInfo = NULL; 6660 } 6661 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 6662 if (!thisKext) { 6663 continue; 6664 } 6665 6666 /* Skip current kext if we have a list of bundle IDs and 6667 * it isn't in the list. 6668 */ 6669 if (kextIdentifiers) { 6670 const OSString * thisKextID = thisKext->getIdentifier(); 6671 6672 includeThis = false; 6673 6674 for (idIndex = 0; idIndex < idCount; idIndex++) { 6675 const OSString * thisRequestID = OSDynamicCast(OSString, 6676 kextIdentifiers->getObject(idIndex)); 6677 if (thisKextID->isEqualTo(thisRequestID)) { 6678 includeThis = true; 6679 break; 6680 } 6681 } 6682 } 6683 6684 if (!includeThis) { 6685 continue; 6686 } 6687 6688 kextInfo = thisKext->copyInfo(); 6689 result->setObject(kextInfo); 6690 } 6691 6692 finish: 6693 IORecursiveLockUnlock(sKextLock); 6694 6695 if (kextInfo) kextInfo->release(); 6696 6697 return result; 6698 } 6699 6700 /********************************************************************* 6701 Load Tag 6702 Bundle ID 6703 Bundle Version 6704 Path 6705 Load Address 6706 Load Size 6707 Wired Size 6708 Version 6709 Dependency Load Tags 6710 # Dependent References 6711 UUID 6712 RetainCount 6713 *********************************************************************/ 6714 #define _OSKextLoadInfoDictCapacity (12) 6715 6716 OSDictionary * 6717 OSKext::copyInfo(void) 6718 { 6719 OSDictionary * result = NULL; 6720 bool success = false; 6721 OSNumber * cpuTypeNumber = NULL; // must release 6722 OSNumber * cpuSubtypeNumber = NULL; // must release 6723 OSString * versionString = NULL; // do not release 6724 OSData * uuid = NULL; // must release 6725 OSNumber * scratchNumber = NULL; // must release 6726 OSArray * dependencyLoadTags = NULL; // must release 6727 OSCollectionIterator * metaClassIterator = NULL; // must release 6728 OSArray * metaClassInfo = NULL; // must release 6729 OSDictionary * metaClassDict = NULL; // must release 6730 OSMetaClass * thisMetaClass = NULL; // do not release 6731 OSString * metaClassName = NULL; // must release 6732 OSString * superclassName = NULL; // must release 6733 uint32_t count, i; 6734 6735 result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity); 6736 if (!result) { 6737 goto finish; 6738 } 6739 6740 /* CPU Type & Subtype. 6741 * Use the CPU type of the kernel for all (loaded) kexts. 6742 * xxx - should we not include this for the kernel components, 6743 * xxx - or for any interface? they have mach-o files, they're just weird. 6744 */ 6745 if (linkedExecutable || (this == sKernelKext)) { 6746 6747 cpuTypeNumber = OSNumber::withNumber( 6748 (long long unsigned int)_mh_execute_header.cputype, 6749 8 * sizeof(_mh_execute_header.cputype)); 6750 if (cpuTypeNumber) { 6751 result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber); 6752 } 6753 } 6754 6755 // I don't want to rely on a mach header for nonkernel kexts, yet 6756 if (this == sKernelKext) { 6757 cpuSubtypeNumber = OSNumber::withNumber( 6758 (long long unsigned int)_mh_execute_header.cputype, 6759 8 * sizeof(_mh_execute_header.cputype)); 6760 if (cpuSubtypeNumber) { 6761 result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber); 6762 } 6763 } 6764 6765 /* CFBundleIdentifier. 6766 */ 6767 result->setObject(kCFBundleIdentifierKey, bundleID); 6768 6769 /* CFBundleVersion. 6770 */ 6771 versionString = OSDynamicCast(OSString, 6772 getPropertyForHostArch(kCFBundleVersionKey)); 6773 if (versionString) { 6774 result->setObject(kCFBundleVersionKey, versionString); 6775 } 6776 6777 /* OSBundleCompatibleVersion. 6778 */ 6779 versionString = OSDynamicCast(OSString, 6780 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 6781 if (versionString) { 6782 result->setObject(kOSBundleCompatibleVersionKey, versionString); 6783 } 6784 6785 /* Path. 6786 */ 6787 if (path) { 6788 result->setObject(kOSBundlePathKey, path); 6789 } 6790 6791 /* UUID. 6792 */ 6793 uuid = copyUUID(); 6794 if (uuid) { 6795 result->setObject(kOSBundleUUIDKey, uuid); 6796 } 6797 6798 /***** 6799 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted. 6800 */ 6801 result->setObject(kOSKernelResourceKey, 6802 isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse); 6803 6804 result->setObject(kOSBundleIsInterfaceKey, 6805 isInterface() ? kOSBooleanTrue : kOSBooleanFalse); 6806 6807 result->setObject(kOSBundlePrelinkedKey, 6808 isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse); 6809 6810 result->setObject(kOSBundleStartedKey, 6811 isStarted() ? kOSBooleanTrue : kOSBooleanFalse); 6812 6813 /* LoadTag (Index). 6814 */ 6815 scratchNumber = OSNumber::withNumber((unsigned long long)loadTag, 6816 /* numBits */ 8 * sizeof(loadTag)); 6817 if (scratchNumber) { 6818 result->setObject(kOSBundleLoadTagKey, scratchNumber); 6819 OSSafeReleaseNULL(scratchNumber); 6820 } 6821 6822 /* LoadAddress, LoadSize. 6823 */ 6824 if (isInterface() || linkedExecutable) { 6825 /* These go to userspace via serialization, so we don't want any doubts 6826 * about their size. 6827 */ 6828 uint64_t loadAddress = 0; 6829 uint32_t loadSize = 0; 6830 uint32_t wiredSize = 0; 6831 6832 /* Interfaces always report 0 load address & size. 6833 * Just the way they roll. 6834 * 6835 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp 6836 * xxx - shouldn't have one! 6837 */ 6838 if (linkedExecutable /* && !isInterface() */) { 6839 loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy(); 6840 loadSize = linkedExecutable->getLength(); 6841 6842 /* If we have a kmod_info struct, calculated the wired size 6843 * from that. Otherwise it's the full load size. 6844 */ 6845 if (kmod_info) { 6846 wiredSize = loadSize - kmod_info->hdr_size; 6847 } else { 6848 wiredSize = loadSize; 6849 } 6850 } 6851 6852 scratchNumber = OSNumber::withNumber( 6853 (unsigned long long)(loadAddress), 6854 /* numBits */ 8 * sizeof(loadAddress)); 6855 if (scratchNumber) { 6856 result->setObject(kOSBundleLoadAddressKey, scratchNumber); 6857 OSSafeReleaseNULL(scratchNumber); 6858 } 6859 scratchNumber = OSNumber::withNumber( 6860 (unsigned long long)(loadSize), 6861 /* numBits */ 8 * sizeof(loadSize)); 6862 if (scratchNumber) { 6863 result->setObject(kOSBundleLoadSizeKey, scratchNumber); 6864 OSSafeReleaseNULL(scratchNumber); 6865 } 6866 scratchNumber = OSNumber::withNumber( 6867 (unsigned long long)(wiredSize), 6868 /* numBits */ 8 * sizeof(wiredSize)); 6869 if (scratchNumber) { 6870 result->setObject(kOSBundleWiredSizeKey, scratchNumber); 6871 OSSafeReleaseNULL(scratchNumber); 6872 } 6873 } 6874 6875 /* OSBundleDependencies. In descending order for 6876 * easy compatibility with kextstat(8). 6877 */ 6878 if ((count = getNumDependencies())) { 6879 dependencyLoadTags = OSArray::withCapacity(count); 6880 result->setObject(kOSBundleDependenciesKey, dependencyLoadTags); 6881 6882 i = count - 1; 6883 do { 6884 OSKext * dependency = OSDynamicCast(OSKext, 6885 dependencies->getObject(i)); 6886 6887 OSSafeReleaseNULL(scratchNumber); 6888 6889 if (!dependency) { 6890 continue; 6891 } 6892 scratchNumber = OSNumber::withNumber( 6893 (unsigned long long)dependency->getLoadTag(), 6894 /* numBits*/ 8 * sizeof(loadTag)); 6895 if (scratchNumber) { 6896 dependencyLoadTags->setObject(scratchNumber); 6897 } 6898 } while (i--); 6899 } 6900 6901 OSSafeReleaseNULL(scratchNumber); 6902 6903 /* OSBundleMetaClasses. 6904 */ 6905 if (metaClasses && metaClasses->getCount()) { 6906 metaClassIterator = OSCollectionIterator::withCollection(metaClasses); 6907 metaClassInfo = OSArray::withCapacity(metaClasses->getCount()); 6908 if (!metaClassIterator || !metaClassInfo) { 6909 goto finish; 6910 } 6911 result->setObject(kOSBundleClassesKey, metaClassInfo); 6912 6913 while ( (thisMetaClass = OSDynamicCast(OSMetaClass, 6914 metaClassIterator->getNextObject())) ) { 6915 6916 OSSafeReleaseNULL(metaClassDict); 6917 OSSafeReleaseNULL(metaClassName); 6918 OSSafeReleaseNULL(superclassName); 6919 OSSafeReleaseNULL(scratchNumber); 6920 6921 metaClassDict = OSDictionary::withCapacity(3); 6922 if (!metaClassDict) { 6923 goto finish; 6924 } 6925 6926 metaClassName = OSString::withCString(thisMetaClass->getClassName()); 6927 if (thisMetaClass->getSuperClass()) { 6928 superclassName = OSString::withCString( 6929 thisMetaClass->getSuperClass()->getClassName()); 6930 } 6931 scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(), 6932 8 * sizeof(unsigned int)); 6933 if (!metaClassDict || !metaClassName || !superclassName || 6934 !scratchNumber) { 6935 6936 goto finish; 6937 } 6938 6939 metaClassInfo->setObject(metaClassDict); 6940 metaClassDict->setObject(kOSMetaClassNameKey, metaClassName); 6941 metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName); 6942 metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber); 6943 } 6944 } 6945 6946 /* OSBundleRetainCount. 6947 */ 6948 OSSafeReleaseNULL(scratchNumber); 6949 { 6950 int extRetainCount = getRetainCount() - 1; 6951 if (isLoaded()) { 6952 extRetainCount--; 6953 } 6954 scratchNumber = OSNumber::withNumber( 6955 (int)extRetainCount, 6956 /* numBits*/ 8 * sizeof(int)); 6957 if (scratchNumber) { 6958 result->setObject(kOSBundleRetainCountKey, scratchNumber); 6959 } 6960 } 6961 6962 success = true; 6963 finish: 6964 OSSafeRelease(cpuTypeNumber); 6965 OSSafeRelease(cpuSubtypeNumber); 6966 OSSafeRelease(uuid); 6967 OSSafeRelease(scratchNumber); 6968 OSSafeRelease(dependencyLoadTags); 6969 OSSafeRelease(metaClassIterator); 6970 OSSafeRelease(metaClassInfo); 6971 OSSafeRelease(metaClassDict); 6972 OSSafeRelease(metaClassName); 6973 OSSafeRelease(superclassName); 6974 if (!success) { 6975 OSSafeReleaseNULL(result); 6976 } 6977 return result; 6978 } 6979 6980 /********************************************************************* 6981 *********************************************************************/ 6982 /* static */ 6983 OSReturn 6984 OSKext::requestResource( 6985 const char * kextIdentifierCString, 6986 const char * resourceNameCString, 6987 OSKextRequestResourceCallback callback, 6988 void * context, 6989 OSKextRequestTag * requestTagOut) 6990 { 6991 OSReturn result = kOSReturnError; 6992 OSKext * callbackKext = NULL; // must release (looked up) 6993 6994 OSKextRequestTag requestTag = -1; 6995 OSNumber * requestTagNum = NULL; // must release 6996 6997 OSDictionary * requestDict = NULL; // must release 6998 OSString * kextIdentifier = NULL; // must release 6999 OSString * resourceName = NULL; // must release 7000 7001 OSDictionary * callbackRecord = NULL; // must release 7002 OSData * callbackWrapper = NULL; // must release 7003 7004 OSData * contextWrapper = NULL; // must release 7005 7006 IORecursiveLockLock(sKextLock); 7007 7008 if (requestTagOut) { 7009 *requestTagOut = kOSKextRequestTagInvalid; 7010 } 7011 7012 if (!kextIdentifierCString || !resourceNameCString || !callback) { 7013 result = kOSKextReturnInvalidArgument; 7014 goto finish; 7015 } 7016 7017 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 7018 if (!callbackKext) { 7019 OSKextLog(/* kext */ NULL, 7020 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 7021 "Resource request has bad callback address."); 7022 result = kOSKextReturnInvalidArgument; 7023 goto finish; 7024 } 7025 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 7026 OSKextLog(/* kext */ NULL, 7027 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 7028 "Resource request callback is in a kext that is not started."); 7029 result = kOSKextReturnInvalidArgument; 7030 goto finish; 7031 } 7032 7033 /* Do not allow any new requests to be made on a kext that is unloading. 7034 */ 7035 if (callbackKext->flags.stopping) { 7036 result = kOSKextReturnStopping; 7037 goto finish; 7038 } 7039 7040 /* If we're wrapped the next available request tag around to the negative 7041 * numbers, we can't service any more requests. 7042 */ 7043 if (sNextRequestTag == kOSKextRequestTagInvalid) { 7044 OSKextLog(/* kext */ NULL, 7045 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 7046 "No more request tags available; restart required."); 7047 result = kOSKextReturnNoResources; 7048 goto finish; 7049 } 7050 requestTag = sNextRequestTag++; 7051 7052 result = _OSKextCreateRequest(kKextRequestPredicateRequestResource, 7053 &requestDict); 7054 if (result != kOSReturnSuccess) { 7055 goto finish; 7056 } 7057 7058 kextIdentifier = OSString::withCString(kextIdentifierCString); 7059 resourceName = OSString::withCString(resourceNameCString); 7060 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 7061 8 * sizeof(requestTag)); 7062 if (!kextIdentifier || 7063 !resourceName || 7064 !requestTagNum || 7065 !_OSKextSetRequestArgument(requestDict, 7066 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) || 7067 !_OSKextSetRequestArgument(requestDict, 7068 kKextRequestArgumentNameKey, resourceName) || 7069 !_OSKextSetRequestArgument(requestDict, 7070 kKextRequestArgumentRequestTagKey, requestTagNum)) { 7071 7072 result = kOSKextReturnNoMemory; 7073 goto finish; 7074 } 7075 7076 callbackRecord = OSDynamicCast(OSDictionary, requestDict->copyCollection()); 7077 if (!callbackRecord) { 7078 result = kOSKextReturnNoMemory; 7079 goto finish; 7080 } 7081 // we validate callback address at call time 7082 callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *)); 7083 if (context) { 7084 contextWrapper = OSData::withBytes((void *)&context, sizeof(void *)); 7085 } 7086 if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord, 7087 kKextRequestArgumentCallbackKey, callbackWrapper)) { 7088 7089 result = kOSKextReturnNoMemory; 7090 goto finish; 7091 } 7092 7093 if (context) { 7094 if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord, 7095 kKextRequestArgumentContextKey, contextWrapper)) { 7096 7097 result = kOSKextReturnNoMemory; 7098 goto finish; 7099 } 7100 } 7101 7102 /* Only post the requests after all the other potential failure points 7103 * have been passed. 7104 */ 7105 if (!sKernelRequests->setObject(requestDict) || 7106 !sRequestCallbackRecords->setObject(callbackRecord)) { 7107 7108 result = kOSKextReturnNoMemory; 7109 goto finish; 7110 } 7111 7112 OSKextPingKextd(); 7113 7114 result = kOSReturnSuccess; 7115 if (requestTagOut) { 7116 *requestTagOut = requestTag; 7117 } 7118 7119 finish: 7120 7121 /* If we didn't succeed, yank the request & callback 7122 * from their holding arrays. 7123 */ 7124 if (result != kOSReturnSuccess) { 7125 unsigned int index; 7126 7127 index = sKernelRequests->getNextIndexOfObject(requestDict, 0); 7128 if (index != (unsigned int)-1) { 7129 sKernelRequests->removeObject(index); 7130 } 7131 index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord, 0); 7132 if (index != (unsigned int)-1) { 7133 sRequestCallbackRecords->removeObject(index); 7134 } 7135 } 7136 7137 OSKext::considerUnloads(/* rescheduleOnly? */ true); 7138 7139 IORecursiveLockUnlock(sKextLock); 7140 7141 if (callbackKext) callbackKext->release(); 7142 if (requestTagNum) requestTagNum->release(); 7143 7144 if (requestDict) requestDict->release(); 7145 if (kextIdentifier) kextIdentifier->release(); 7146 if (resourceName) resourceName->release(); 7147 7148 if (callbackRecord) callbackRecord->release(); 7149 if (callbackWrapper) callbackWrapper->release(); 7150 if (contextWrapper) contextWrapper->release(); 7151 7152 return result; 7153 } 7154 7155 /********************************************************************* 7156 *********************************************************************/ 7157 /* static */ 7158 OSReturn 7159 OSKext::dequeueCallbackForRequestTag( 7160 OSKextRequestTag requestTag, 7161 OSDictionary ** callbackRecordOut) 7162 { 7163 OSReturn result = kOSReturnError; 7164 OSNumber * requestTagNum = NULL; // must release 7165 7166 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 7167 8 * sizeof(requestTag)); 7168 if (!requestTagNum) { 7169 goto finish; 7170 } 7171 7172 result = OSKext::dequeueCallbackForRequestTag(requestTagNum, 7173 callbackRecordOut); 7174 7175 finish: 7176 OSSafeRelease(requestTagNum); 7177 7178 return result; 7179 } 7180 7181 /********************************************************************* 7182 *********************************************************************/ 7183 /* static */ 7184 OSReturn 7185 OSKext::dequeueCallbackForRequestTag( 7186 OSNumber * requestTagNum, 7187 OSDictionary ** callbackRecordOut) 7188 { 7189 OSReturn result = kOSKextReturnInvalidArgument; 7190 OSDictionary * callbackRecord = NULL; // retain if matched! 7191 OSNumber * callbackTagNum = NULL; // do not release 7192 unsigned int count, i; 7193 7194 IORecursiveLockLock(sKextLock); 7195 7196 result = kOSReturnError; 7197 count = sRequestCallbackRecords->getCount(); 7198 for (i = 0; i < count; i++) { 7199 callbackRecord = OSDynamicCast(OSDictionary, 7200 sRequestCallbackRecords->getObject(i)); 7201 if (!callbackRecord) { 7202 goto finish; 7203 } 7204 7205 /* If we don't find a tag, we basically have a leak here. Maybe 7206 * we should just remove it. 7207 */ 7208 callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument( 7209 callbackRecord, kKextRequestArgumentRequestTagKey)); 7210 if (!callbackTagNum) { 7211 goto finish; 7212 } 7213 7214 /* We could be even more paranoid and check that all the incoming 7215 * args match what's in the callback record. 7216 */ 7217 if (callbackTagNum->isEqualTo(requestTagNum)) { 7218 if (callbackRecordOut) { 7219 *callbackRecordOut = callbackRecord; 7220 callbackRecord->retain(); 7221 } 7222 sRequestCallbackRecords->removeObject(i); 7223 result = kOSReturnSuccess; 7224 goto finish; 7225 } 7226 } 7227 result = kOSKextReturnNotFound; 7228 7229 finish: 7230 IORecursiveLockUnlock(sKextLock); 7231 return result; 7232 } 7233 7234 /********************************************************************* 7235 *********************************************************************/ 7236 /* static */ 7237 OSReturn 7238 OSKext::dispatchResource(OSDictionary * requestDict) 7239 { 7240 OSReturn result = kOSReturnError; 7241 OSDictionary * callbackRecord = NULL; // must release 7242 OSNumber * requestTag = NULL; // do not release 7243 OSNumber * requestResult = NULL; // do not release 7244 OSData * dataObj = NULL; // do not release 7245 uint32_t dataLength = 0; 7246 const void * dataPtr = NULL; // do not free 7247 OSData * callbackWrapper = NULL; // do not release 7248 OSKextRequestResourceCallback callback = NULL; 7249 OSData * contextWrapper = NULL; // do not release 7250 void * context = NULL; // do not free 7251 OSKext * callbackKext = NULL; // must release (looked up) 7252 7253 IORecursiveLockLock(sKextLock); 7254 7255 /* Get the args from the request. Right now we need the tag 7256 * to look up the callback record, and the result for invoking the callback. 7257 */ 7258 requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 7259 kKextRequestArgumentRequestTagKey)); 7260 requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 7261 kKextRequestArgumentResultKey)); 7262 if (!requestTag || !requestResult) { 7263 result = kOSKextReturnInvalidArgument; 7264 goto finish; 7265 } 7266 7267 /* Look for a callback record matching this request's tag. 7268 */ 7269 result = dequeueCallbackForRequestTag(requestTag, &callbackRecord); 7270 if (result != kOSReturnSuccess) { 7271 goto finish; 7272 } 7273 7274 /***** 7275 * Get the context pointer of the callback record (if there is one). 7276 */ 7277 contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord, 7278 kKextRequestArgumentContextKey)); 7279 context = _OSKextExtractPointer(contextWrapper); 7280 if (contextWrapper && !context) { 7281 goto finish; 7282 } 7283 7284 callbackWrapper = OSDynamicCast(OSData, 7285 _OSKextGetRequestArgument(callbackRecord, 7286 kKextRequestArgumentCallbackKey)); 7287 callback = (OSKextRequestResourceCallback) 7288 _OSKextExtractPointer(callbackWrapper); 7289 if (!callback) { 7290 goto finish; 7291 } 7292 7293 /* Check for a data obj. We might not have one and that's ok, that means 7294 * we didn't find the requested resource, and we still have to tell the 7295 * caller that via the callback. 7296 */ 7297 dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict, 7298 kKextRequestArgumentValueKey)); 7299 if (dataObj) { 7300 dataPtr = dataObj->getBytesNoCopy(); 7301 dataLength = dataObj->getLength(); 7302 } 7303 7304 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 7305 if (!callbackKext) { 7306 OSKextLog(/* kext */ NULL, 7307 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 7308 "Can't invoke callback for resource request; " 7309 "no kext loaded at callback address %p.", 7310 callback); 7311 goto finish; 7312 } 7313 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 7314 OSKextLog(/* kext */ NULL, 7315 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 7316 "Can't invoke kext resource callback; " 7317 "kext at callback address %p is not running.", 7318 callback); 7319 goto finish; 7320 } 7321 7322 (void)callback(requestTag->unsigned32BitValue(), 7323 (OSReturn)requestResult->unsigned32BitValue(), 7324 dataPtr, dataLength, context); 7325 7326 result = kOSReturnSuccess; 7327 7328 finish: 7329 if (callbackKext) callbackKext->release(); 7330 if (callbackRecord) callbackRecord->release(); 7331 7332 IORecursiveLockUnlock(sKextLock); 7333 return result; 7334 } 7335 7336 /********************************************************************* 7337 *********************************************************************/ 7338 /* static */ 7339 void 7340 OSKext::invokeRequestCallback( 7341 OSDictionary * callbackRecord, 7342 OSReturn callbackResult) 7343 { 7344 OSString * predicate = _OSKextGetRequestPredicate(callbackRecord); 7345 OSNumber * resultNum = NULL; // must release 7346 7347 if (!predicate) { 7348 goto finish; 7349 } 7350 7351 resultNum = OSNumber::withNumber((long long unsigned int)callbackResult, 7352 8 * sizeof(callbackResult)); 7353 if (!resultNum) { 7354 goto finish; 7355 } 7356 7357 /* Insert the result into the callback record and dispatch it as if it 7358 * were the reply coming down from user space. 7359 */ 7360 _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey, 7361 resultNum); 7362 7363 if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) { 7364 /* This removes the pending callback record. 7365 */ 7366 OSKext::dispatchResource(callbackRecord); 7367 } 7368 7369 finish: 7370 if (resultNum) resultNum->release(); 7371 return; 7372 } 7373 7374 /********************************************************************* 7375 *********************************************************************/ 7376 /* static */ 7377 OSReturn 7378 OSKext::cancelRequest( 7379 OSKextRequestTag requestTag, 7380 void ** contextOut) 7381 { 7382 OSReturn result = kOSKextReturnNoMemory; 7383 OSDictionary * callbackRecord = NULL; // must release 7384 OSData * contextWrapper = NULL; // do not release 7385 7386 result = OSKext::dequeueCallbackForRequestTag(requestTag, 7387 &callbackRecord); 7388 7389 if (result == kOSReturnSuccess && contextOut) { 7390 contextWrapper = OSDynamicCast(OSData, 7391 _OSKextGetRequestArgument(callbackRecord, 7392 kKextRequestArgumentContextKey)); 7393 *contextOut = _OSKextExtractPointer(contextWrapper); 7394 } 7395 7396 if (callbackRecord) callbackRecord->release(); 7397 7398 return result; 7399 } 7400 7401 /********************************************************************* 7402 *********************************************************************/ 7403 void 7404 OSKext::invokeOrCancelRequestCallbacks( 7405 OSReturn callbackResult, 7406 bool invokeFlag) 7407 { 7408 unsigned int count, i; 7409 7410 IORecursiveLockLock(sKextLock); 7411 7412 count = sRequestCallbackRecords->getCount(); 7413 if (!count) { 7414 goto finish; 7415 } 7416 7417 i = count - 1; 7418 do { 7419 OSDictionary * request = OSDynamicCast(OSDictionary, 7420 sRequestCallbackRecords->getObject(i)); 7421 7422 if (!request) { 7423 continue; 7424 } 7425 OSData * callbackWrapper = OSDynamicCast(OSData, 7426 _OSKextGetRequestArgument(request, 7427 kKextRequestArgumentCallbackKey)); 7428 7429 if (!callbackWrapper) { 7430 sRequestCallbackRecords->removeObject(i); 7431 continue; 7432 } 7433 7434 vm_address_t callbackAddress = (vm_address_t) 7435 _OSKextExtractPointer(callbackWrapper); 7436 7437 if ((kmod_info->address <= callbackAddress) && 7438 (callbackAddress < (kmod_info->address + kmod_info->size))) { 7439 7440 if (invokeFlag) { 7441 /* This removes the callback record. 7442 */ 7443 invokeRequestCallback(request, callbackResult); 7444 } else { 7445 sRequestCallbackRecords->removeObject(i); 7446 } 7447 } 7448 } while (i--); 7449 7450 finish: 7451 IORecursiveLockUnlock(sKextLock); 7452 return; 7453 } 7454 7455 /********************************************************************* 7456 *********************************************************************/ 7457 uint32_t 7458 OSKext::countRequestCallbacks(void) 7459 { 7460 uint32_t result = 0; 7461 unsigned int count, i; 7462 7463 IORecursiveLockLock(sKextLock); 7464 7465 count = sRequestCallbackRecords->getCount(); 7466 if (!count) { 7467 goto finish; 7468 } 7469 7470 i = count - 1; 7471 do { 7472 OSDictionary * request = OSDynamicCast(OSDictionary, 7473 sRequestCallbackRecords->getObject(i)); 7474 7475 if (!request) { 7476 continue; 7477 } 7478 OSData * callbackWrapper = OSDynamicCast(OSData, 7479 _OSKextGetRequestArgument(request, 7480 kKextRequestArgumentCallbackKey)); 7481 7482 if (!callbackWrapper) { 7483 continue; 7484 } 7485 7486 vm_address_t callbackAddress = (vm_address_t) 7487 _OSKextExtractPointer(callbackWrapper); 7488 7489 if ((kmod_info->address <= callbackAddress) && 7490 (callbackAddress < (kmod_info->address + kmod_info->size))) { 7491 7492 result++; 7493 } 7494 } while (i--); 7495 7496 finish: 7497 IORecursiveLockUnlock(sKextLock); 7498 return result; 7499 } 7500 7501 /********************************************************************* 7502 *********************************************************************/ 7503 static OSReturn _OSKextCreateRequest( 7504 const char * predicate, 7505 OSDictionary ** requestP) 7506 { 7507 OSReturn result = kOSKextReturnNoMemory; 7508 OSDictionary * request = NULL; // must release on error 7509 OSDictionary * args = NULL; // must release 7510 7511 request = OSDictionary::withCapacity(2); 7512 if (!request) { 7513 goto finish; 7514 } 7515 result = _OSDictionarySetCStringValue(request, 7516 kKextRequestPredicateKey, predicate); 7517 if (result != kOSReturnSuccess) { 7518 goto finish; 7519 } 7520 result = kOSReturnSuccess; 7521 7522 finish: 7523 if (result != kOSReturnSuccess) { 7524 if (request) request->release(); 7525 } else { 7526 *requestP = request; 7527 } 7528 if (args) args->release(); 7529 7530 return result; 7531 } 7532 7533 /********************************************************************* 7534 *********************************************************************/ 7535 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict) 7536 { 7537 return OSDynamicCast(OSString, 7538 requestDict->getObject(kKextRequestPredicateKey)); 7539 } 7540 7541 /********************************************************************* 7542 *********************************************************************/ 7543 static OSObject * _OSKextGetRequestArgument( 7544 OSDictionary * requestDict, 7545 const char * argName) 7546 { 7547 OSDictionary * args = OSDynamicCast(OSDictionary, 7548 requestDict->getObject(kKextRequestArgumentsKey)); 7549 if (args) { 7550 return args->getObject(argName); 7551 } 7552 return NULL; 7553 } 7554 7555 /********************************************************************* 7556 *********************************************************************/ 7557 static bool _OSKextSetRequestArgument( 7558 OSDictionary * requestDict, 7559 const char * argName, 7560 OSObject * value) 7561 { 7562 OSDictionary * args = OSDynamicCast(OSDictionary, 7563 requestDict->getObject(kKextRequestArgumentsKey)); 7564 if (!args) { 7565 args = OSDictionary::withCapacity(2); 7566 if (!args) { 7567 goto finish; 7568 } 7569 requestDict->setObject(kKextRequestArgumentsKey, args); 7570 args->release(); 7571 } 7572 if (args) { 7573 return args->setObject(argName, value); 7574 } 7575 finish: 7576 return false; 7577 } 7578 7579 /********************************************************************* 7580 *********************************************************************/ 7581 static void * _OSKextExtractPointer(OSData * wrapper) 7582 { 7583 void * result = NULL; 7584 const void * resultPtr = NULL; 7585 7586 if (!wrapper) { 7587 goto finish; 7588 } 7589 resultPtr = wrapper->getBytesNoCopy(); 7590 result = *(void **)resultPtr; 7591 finish: 7592 return result; 7593 } 7594 7595 /********************************************************************* 7596 *********************************************************************/ 7597 static OSReturn _OSDictionarySetCStringValue( 7598 OSDictionary * dict, 7599 const char * cKey, 7600 const char * cValue) 7601 { 7602 OSReturn result = kOSKextReturnNoMemory; 7603 const OSSymbol * key = NULL; // must release 7604 OSString * value = NULL; // must release 7605 7606 key = OSSymbol::withCString(cKey); 7607 value = OSString::withCString(cValue); 7608 if (!key || !value) { 7609 goto finish; 7610 } 7611 if (dict->setObject(key, value)) { 7612 result = kOSReturnSuccess; 7613 } 7614 7615 finish: 7616 if (key) key->release(); 7617 if (value) value->release(); 7618 7619 return result; 7620 } 7621 7622 #if PRAGMA_MARK 7623 #pragma mark Personalities (IOKit Drivers) 7624 #endif 7625 /********************************************************************* 7626 *********************************************************************/ 7627 /* static */ 7628 OSArray * 7629 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag) 7630 { 7631 OSArray * result = NULL; // returned 7632 OSCollectionIterator * kextIterator = NULL; // must release 7633 OSArray * personalities = NULL; // must release 7634 OSCollectionIterator * personalitiesIterator = NULL; // must release 7635 7636 OSString * kextID = NULL; // do not release 7637 OSKext * theKext = NULL; // do not release 7638 7639 IORecursiveLockLock(sKextLock); 7640 7641 /* Let's conservatively guess that any given kext has around 3 7642 * personalities for now. 7643 */ 7644 result = OSArray::withCapacity(sKextsByID->getCount() * 3); 7645 if (!result) { 7646 goto finish; 7647 } 7648 7649 kextIterator = OSCollectionIterator::withCollection(sKextsByID); 7650 if (!kextIterator) { 7651 goto finish; 7652 } 7653 7654 while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) { 7655 if (personalitiesIterator) { 7656 personalitiesIterator->release(); 7657 personalitiesIterator = NULL; 7658 } 7659 if (personalities) { 7660 personalities->release(); 7661 personalities = NULL; 7662 } 7663 7664 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID)); 7665 if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) { 7666 personalities = theKext->copyPersonalitiesArray(); 7667 if (!personalities) { 7668 continue; 7669 } 7670 result->merge(personalities); 7671 } else { 7672 // xxx - check for better place to put this log msg 7673 OSKextLog(theKext, 7674 kOSKextLogWarningLevel | 7675 kOSKextLogLoadFlag, 7676 "Kext %s is not loadable during safe boot; " 7677 "omitting its personalities.", 7678 theKext->getIdentifierCString()); 7679 } 7680 7681 } 7682 7683 finish: 7684 IORecursiveLockUnlock(sKextLock); 7685 7686 if (kextIterator) kextIterator->release(); 7687 if (personalitiesIterator) personalitiesIterator->release(); 7688 if (personalities) personalities->release(); 7689 7690 return result; 7691 } 7692 7693 /********************************************************************* 7694 *********************************************************************/ 7695 /* static */ 7696 void 7697 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching) 7698 { 7699 int numPersonalities = 0; 7700 7701 OSKextLog(/* kext */ NULL, 7702 kOSKextLogStepLevel | 7703 kOSKextLogLoadFlag, 7704 "Sending all eligible registered kexts' personalities " 7705 "to the IOCatalogue %s.", 7706 startMatching ? "and starting matching" : "but not starting matching"); 7707 7708 OSArray * personalities = OSKext::copyAllKextPersonalities( 7709 /* filterSafeBootFlag */ true); 7710 7711 if (personalities) { 7712 gIOCatalogue->addDrivers(personalities, startMatching); 7713 numPersonalities = personalities->getCount(); 7714 personalities->release(); 7715 } 7716 7717 OSKextLog(/* kext */ NULL, 7718 kOSKextLogStepLevel | 7719 kOSKextLogLoadFlag, 7720 "%d kext personalit%s sent to the IOCatalogue; %s.", 7721 numPersonalities, numPersonalities > 0 ? "ies" : "y", 7722 startMatching ? "matching started" : "matching not started"); 7723 return; 7724 } 7725 7726 /********************************************************************* 7727 * Do not make a deep copy, just convert the IOKitPersonalities dict 7728 * to an array for sending to the IOCatalogue. 7729 *********************************************************************/ 7730 OSArray * 7731 OSKext::copyPersonalitiesArray(void) 7732 { 7733 OSArray * result = NULL; 7734 OSDictionary * personalities = NULL; // do not release 7735 OSCollectionIterator * personalitiesIterator = NULL; // must release 7736 7737 OSString * personalityName = NULL; // do not release 7738 OSString * personalityBundleIdentifier = NULL; // do not release 7739 7740 personalities = OSDynamicCast(OSDictionary, 7741 getPropertyForHostArch(kIOKitPersonalitiesKey)); 7742 if (!personalities) { 7743 goto finish; 7744 } 7745 7746 result = OSArray::withCapacity(personalities->getCount()); 7747 if (!result) { 7748 goto finish; 7749 } 7750 7751 personalitiesIterator = 7752 OSCollectionIterator::withCollection(personalities); 7753 if (!personalitiesIterator) { 7754 goto finish; 7755 } 7756 while ((personalityName = OSDynamicCast(OSString, 7757 personalitiesIterator->getNextObject()))) { 7758 7759 OSDictionary * personality = OSDynamicCast(OSDictionary, 7760 personalities->getObject(personalityName)); 7761 7762 /****** 7763 * If the personality doesn't have a CFBundleIdentifier, or if it 7764 * differs from the kext's, insert the kext's ID so we can find it. 7765 * The publisher ID is used to remove personalities from bundles 7766 * correctly. 7767 */ 7768 personalityBundleIdentifier = OSDynamicCast(OSString, 7769 personality->getObject(kCFBundleIdentifierKey)); 7770 7771 if (!personalityBundleIdentifier) { 7772 personality->setObject(kCFBundleIdentifierKey, bundleID); 7773 } else if (!personalityBundleIdentifier->isEqualTo(bundleID)) { 7774 personality->setObject(kIOPersonalityPublisherKey, bundleID); 7775 } 7776 7777 result->setObject(personality); 7778 } 7779 7780 finish: 7781 if (personalitiesIterator) personalitiesIterator->release(); 7782 7783 return result; 7784 } 7785 7786 /********************************************************************* 7787 Might want to change this to a bool return? 7788 *********************************************************************/ 7789 OSReturn 7790 OSKext::sendPersonalitiesToCatalog( 7791 bool startMatching, 7792 OSArray * personalityNames) 7793 { 7794 OSReturn result = kOSReturnSuccess; 7795 OSArray * personalitiesToSend = NULL; // must release 7796 OSDictionary * kextPersonalities = NULL; // do not release 7797 int count, i; 7798 7799 if (!sLoadEnabled) { 7800 OSKextLog(this, 7801 kOSKextLogErrorLevel | 7802 kOSKextLogLoadFlag, 7803 "Kext loading is disabled (attempt to start matching for kext %s).", 7804 getIdentifierCString()); 7805 result = kOSKextReturnDisabled; 7806 goto finish; 7807 } 7808 7809 if (sSafeBoot && !isLoadableInSafeBoot()) { 7810 OSKextLog(this, 7811 kOSKextLogErrorLevel | 7812 kOSKextLogLoadFlag, 7813 "Kext %s is not loadable during safe boot; " 7814 "not sending personalities to the IOCatalogue.", 7815 getIdentifierCString()); 7816 result = kOSKextReturnNotLoadable; 7817 goto finish; 7818 } 7819 7820 if (!personalityNames || !personalityNames->getCount()) { 7821 personalitiesToSend = copyPersonalitiesArray(); 7822 } else { 7823 kextPersonalities = OSDynamicCast(OSDictionary, 7824 getPropertyForHostArch(kIOKitPersonalitiesKey)); 7825 if (!kextPersonalities || !kextPersonalities->getCount()) { 7826 // not an error 7827 goto finish; 7828 } 7829 personalitiesToSend = OSArray::withCapacity(0); 7830 if (!personalitiesToSend) { 7831 result = kOSKextReturnNoMemory; 7832 goto finish; 7833 } 7834 count = personalityNames->getCount(); 7835 for (i = 0; i < count; i++) { 7836 OSString * name = OSDynamicCast(OSString, 7837 personalityNames->getObject(i)); 7838 if (!name) { 7839 continue; 7840 } 7841 OSDictionary * personality = OSDynamicCast(OSDictionary, 7842 kextPersonalities->getObject(name)); 7843 if (personality) { 7844 personalitiesToSend->setObject(personality); 7845 } 7846 } 7847 } 7848 if (personalitiesToSend) { 7849 unsigned numPersonalities = personalitiesToSend->getCount(); 7850 OSKextLog(this, 7851 kOSKextLogStepLevel | 7852 kOSKextLogLoadFlag, 7853 "Kext %s sending %d personalit%s to the IOCatalogue%s.", 7854 getIdentifierCString(), 7855 numPersonalities, 7856 numPersonalities > 1 ? "ies" : "y", 7857 startMatching ? " and starting matching" : " but not starting matching"); 7858 gIOCatalogue->addDrivers(personalitiesToSend, startMatching); 7859 } 7860 finish: 7861 if (personalitiesToSend) { 7862 personalitiesToSend->release(); 7863 } 7864 return result; 7865 } 7866 7867 /********************************************************************* 7868 * xxx - We should allow removing the kext's declared personalities, 7869 * xxx - even with other bundle identifiers. 7870 *********************************************************************/ 7871 void 7872 OSKext::removePersonalitiesFromCatalog(void) 7873 { 7874 OSDictionary * personality = NULL; // do not release 7875 7876 personality = OSDictionary::withCapacity(1); 7877 if (!personality) { 7878 goto finish; 7879 } 7880 personality->setObject(kCFBundleIdentifierKey, getIdentifier()); 7881 7882 OSKextLog(this, 7883 kOSKextLogStepLevel | 7884 kOSKextLogLoadFlag, 7885 "Kext %s removing all personalities naming it from the IOCatalogue.", 7886 getIdentifierCString()); 7887 7888 /* Have the IOCatalog remove all personalities matching this kext's 7889 * bundle ID and trigger matching anew. 7890 */ 7891 gIOCatalogue->removeDrivers(personality, /* startMatching */ true); 7892 7893 finish: 7894 if (personality) personality->release(); 7895 7896 return; 7897 } 7898 7899 7900 #if PRAGMA_MARK 7901 #pragma mark Logging 7902 #endif 7903 /********************************************************************* 7904 * Do not call any function that takes sKextLock here! 7905 *********************************************************************/ 7906 /* static */ 7907 OSKextLogSpec 7908 OSKext::setUserSpaceLogFilter( 7909 OSKextLogSpec userLogFilter, 7910 bool captureFlag) 7911 { 7912 OSKextLogSpec result; 7913 7914 IORecursiveLockLock(sKextInnerLock); 7915 7916 result = sUserSpaceKextLogFilter; 7917 sUserSpaceKextLogFilter = userLogFilter; 7918 7919 /* If the config flag itself is changing, log the state change 7920 * going both ways, before setting up the user-space log arrays, 7921 * so that this is only logged in the kernel. 7922 */ 7923 if (sUserSpaceKextLogFilter != result) { 7924 OSKextLog(/* kext */ NULL, 7925 kOSKextLogDebugLevel | 7926 kOSKextLogGeneralFlag, 7927 "User-space log flags changed from 0x%x to 0x%x.", 7928 result, sUserSpaceKextLogFilter); 7929 } 7930 7931 if (userLogFilter && captureFlag && 7932 !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) { 7933 7934 // xxx - do some measurements for a good initial capacity? 7935 sUserSpaceLogSpecArray = OSArray::withCapacity(0); 7936 sUserSpaceLogMessageArray = OSArray::withCapacity(0); 7937 7938 if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) { 7939 OSKextLog(/* kext */ NULL, 7940 kOSKextLogErrorLevel | 7941 kOSKextLogGeneralFlag, 7942 "Failed to allocate user-space log message arrays."); 7943 OSSafeReleaseNULL(sUserSpaceLogSpecArray); 7944 OSSafeReleaseNULL(sUserSpaceLogMessageArray); 7945 } 7946 } 7947 7948 IORecursiveLockUnlock(sKextInnerLock); 7949 7950 return result; 7951 } 7952 7953 /********************************************************************* 7954 * Do not call any function that takes sKextLock here! 7955 *********************************************************************/ 7956 /* static */ 7957 OSArray * 7958 OSKext::clearUserSpaceLogFilter(void) 7959 { 7960 OSArray * result = NULL; 7961 OSKextLogSpec oldLogFilter; 7962 7963 IORecursiveLockLock(sKextInnerLock); 7964 7965 result = OSArray::withCapacity(2); 7966 if (result) { 7967 result->setObject(sUserSpaceLogSpecArray); 7968 result->setObject(sUserSpaceLogMessageArray); 7969 } 7970 OSSafeReleaseNULL(sUserSpaceLogSpecArray); 7971 OSSafeReleaseNULL(sUserSpaceLogMessageArray); 7972 7973 oldLogFilter = sUserSpaceKextLogFilter; 7974 sUserSpaceKextLogFilter = kOSKextLogSilentFilter; 7975 7976 /* If the config flag itself is changing, log the state change 7977 * going both ways, after tearing down the user-space log 7978 * arrays, so this is only logged within the kernel. 7979 */ 7980 if (oldLogFilter != sUserSpaceKextLogFilter) { 7981 OSKextLog(/* kext */ NULL, 7982 kOSKextLogDebugLevel | 7983 kOSKextLogGeneralFlag, 7984 "User-space log flags changed from 0x%x to 0x%x.", 7985 oldLogFilter, sUserSpaceKextLogFilter); 7986 } 7987 7988 IORecursiveLockUnlock(sKextInnerLock); 7989 7990 return result; 7991 } 7992 7993 /********************************************************************* 7994 * Do not call any function that takes sKextLock here! 7995 *********************************************************************/ 7996 /* static */ 7997 OSKextLogSpec 7998 OSKext::getUserSpaceLogFilter(void) 7999 { 8000 OSKextLogSpec result; 8001 8002 IORecursiveLockLock(sKextInnerLock); 8003 result = sUserSpaceKextLogFilter; 8004 IORecursiveLockUnlock(sKextInnerLock); 8005 8006 return result; 8007 } 8008 8009 /********************************************************************* 8010 * This function is called by OSMetaClass during kernel C++ setup. 8011 * Be careful what you access here; assume only OSKext::initialize() 8012 * has been called. 8013 * 8014 * Do not call any function that takes sKextLock here! 8015 *********************************************************************/ 8016 #define VTRESET "\033[0m" 8017 8018 #define VTBOLD "\033[1m" 8019 #define VTUNDER "\033[4m" 8020 8021 #define VTRED "\033[31m" 8022 #define VTGREEN "\033[32m" 8023 #define VTYELLOW "\033[33m" 8024 #define VTBLUE "\033[34m" 8025 #define VTMAGENTA "\033[35m" 8026 #define VTCYAN "\033[36m" 8027 8028 inline const char * colorForFlags(OSKextLogSpec flags) 8029 { 8030 OSKextLogSpec logLevel = flags & kOSKextLogLevelMask; 8031 8032 switch (logLevel) { 8033 case kOSKextLogErrorLevel: 8034 return VTRED VTBOLD; 8035 break; 8036 case kOSKextLogWarningLevel: 8037 return VTRED; 8038 break; 8039 case kOSKextLogBasicLevel: 8040 return VTYELLOW VTUNDER; 8041 break; 8042 case kOSKextLogProgressLevel: 8043 return VTYELLOW; 8044 break; 8045 case kOSKextLogStepLevel: 8046 return VTGREEN; 8047 break; 8048 case kOSKextLogDetailLevel: 8049 return VTCYAN; 8050 break; 8051 case kOSKextLogDebugLevel: 8052 return VTMAGENTA; 8053 break; 8054 default: 8055 return ""; // white 8056 break; 8057 } 8058 return ""; 8059 } 8060 8061 inline bool logSpecMatch( 8062 OSKextLogSpec msgLogSpec, 8063 OSKextLogSpec logFilter) 8064 { 8065 OSKextLogSpec filterKextGlobal = logFilter & kOSKextLogKextOrGlobalMask; 8066 OSKextLogSpec filterLevel = logFilter & kOSKextLogLevelMask; 8067 OSKextLogSpec filterFlags = logFilter & kOSKextLogFlagsMask; 8068 8069 OSKextLogSpec msgKextGlobal = msgLogSpec & kOSKextLogKextOrGlobalMask; 8070 OSKextLogSpec msgLevel = msgLogSpec & kOSKextLogLevelMask; 8071 OSKextLogSpec msgFlags = msgLogSpec & kOSKextLogFlagsMask; 8072 8073 /* Explicit messages always get logged. 8074 */ 8075 if (msgLevel == kOSKextLogExplicitLevel) { 8076 return true; 8077 } 8078 8079 /* Warnings and errors are logged regardless of the flags. 8080 */ 8081 if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) { 8082 return true; 8083 } 8084 8085 /* A verbose message that isn't for a logging-enabled kext and isn't global 8086 * does *not* get logged. 8087 */ 8088 if (!msgKextGlobal && !filterKextGlobal) { 8089 return false; 8090 } 8091 8092 /* Warnings and errors are logged regardless of the flags. 8093 * All other messages must fit the flags and 8094 * have a level at or below the filter. 8095 * 8096 */ 8097 if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) { 8098 return true; 8099 } 8100 return false; 8101 } 8102 8103 extern "C" { 8104 8105 void 8106 OSKextLog( 8107 OSKext * aKext, 8108 OSKextLogSpec msgLogSpec, 8109 const char * format, ...) 8110 { 8111 va_list argList; 8112 8113 va_start(argList, format); 8114 OSKextVLog(aKext, msgLogSpec, format, argList); 8115 va_end(argList); 8116 } 8117 8118 void 8119 OSKextVLog( 8120 OSKext * aKext, 8121 OSKextLogSpec msgLogSpec, 8122 const char * format, 8123 va_list srcArgList) 8124 { 8125 extern int disableConsoleOutput; 8126 8127 bool logForKernel = false; 8128 bool logForUser = false; 8129 va_list argList; 8130 char stackBuffer[120]; 8131 uint32_t length = 0; 8132 char * allocBuffer = NULL; // must kfree 8133 OSNumber * logSpecNum = NULL; // must release 8134 OSString * logString = NULL; // must release 8135 char * buffer = stackBuffer; // do not free 8136 8137 IORecursiveLockLock(sKextInnerLock); 8138 8139 /* Set the kext/global bit in the message spec if we have no 8140 * kext or if the kext requests logging. 8141 */ 8142 if (!aKext || aKext->flags.loggingEnabled) { 8143 msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask; 8144 } 8145 8146 logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter); 8147 if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 8148 logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter); 8149 } 8150 8151 if (! (logForKernel || logForUser) ) { 8152 goto finish; 8153 } 8154 8155 /* No goto from here until past va_end()! 8156 */ 8157 va_copy(argList, srcArgList); 8158 length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList); 8159 va_end(argList); 8160 8161 if (length + 1 >= sizeof(stackBuffer)) { 8162 allocBuffer = (char *)kalloc((length + 1) * sizeof(char)); 8163 if (!allocBuffer) { 8164 goto finish; 8165 } 8166 8167 /* No goto from here until past va_end()! 8168 */ 8169 va_copy(argList, srcArgList); 8170 vsnprintf(allocBuffer, length + 1, format, argList); 8171 va_end(argList); 8172 8173 buffer = allocBuffer; 8174 } 8175 8176 /* If user space wants the log message, queue it up. 8177 */ 8178 if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 8179 logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec)); 8180 logString = OSString::withCString(buffer); 8181 if (logSpecNum && logString) { 8182 sUserSpaceLogSpecArray->setObject(logSpecNum); 8183 sUserSpaceLogMessageArray->setObject(logString); 8184 } 8185 } 8186 8187 /* Always log messages from the kernel according to the kernel's 8188 * log flags. 8189 */ 8190 if (logForKernel) { 8191 8192 /* If we are in console mode and have a custom log filter, 8193 * colorize the log message. 8194 */ 8195 if (!disableConsoleOutput && sBootArgLogFilterFound) { 8196 const char * color = ""; // do not free 8197 color = colorForFlags(msgLogSpec); 8198 printf("%s%s%s\n", colorForFlags(msgLogSpec), 8199 buffer, color[0] ? VTRESET : ""); 8200 } else { 8201 printf("%s\n", buffer); 8202 } 8203 } 8204 8205 finish: 8206 if (allocBuffer) { 8207 kfree(allocBuffer, (length + 1) * sizeof(char)); 8208 } 8209 OSSafeRelease(logString); 8210 OSSafeRelease(logSpecNum); 8211 IORecursiveLockUnlock(sKextInnerLock); 8212 return; 8213 } 8214 8215 }; /* extern "C" */ 8216 8217 #if PRAGMA_MARK 8218 #pragma mark Backtrace Dump & kmod_get_info() support 8219 #endif 8220 /********************************************************************* 8221 *********************************************************************/ 8222 /* static */ 8223 void 8224 OSKext::printKextsInBacktrace( 8225 vm_offset_t * addr, 8226 unsigned int cnt, 8227 int (* printf_func)(const char *fmt, ...), 8228 bool lockFlag) 8229 { 8230 vm_offset_t * kscan_addr = NULL; 8231 kmod_info_t * k = NULL; 8232 kmod_reference_t * r = NULL; 8233 unsigned int i; 8234 int found_kmod = 0; 8235 8236 if (lockFlag) { 8237 IORecursiveLockLock(sKextLock); 8238 } 8239 8240 for (k = kmod; k; k = k->next) { 8241 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)k)) == 0) { 8242 (*printf_func)(" kmod scan stopped due to missing " 8243 "kmod page: %p\n", k); 8244 break; 8245 } 8246 if (!k->address) { 8247 continue; // skip fake entries for built-in kernel components 8248 } 8249 for (i = 0, kscan_addr = addr; i < cnt; i++, kscan_addr++) { 8250 if ((*kscan_addr >= k->address) && 8251 (*kscan_addr < (k->address + k->size))) { 8252 8253 if (!found_kmod) { 8254 (*printf_func)(" Kernel Extensions in backtrace " 8255 "(with dependencies):\n"); 8256 } 8257 found_kmod = 1; 8258 (*printf_func)(" %s(%s)@%p->%p\n", 8259 k->name, k->version, k->address, k->address + k->size - 1); 8260 8261 for (r = k->reference_list; r; r = r->next) { 8262 kmod_info_t * rinfo; 8263 8264 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)r)) == 0) { 8265 (*printf_func)(" kmod dependency scan stopped " 8266 "due to missing dependency page: %p\n", r); 8267 break; 8268 } 8269 8270 rinfo = r->info; 8271 8272 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) { 8273 (*printf_func)(" kmod dependency scan stopped " 8274 "due to missing kmod page: %p\n", rinfo); 8275 break; 8276 } 8277 8278 if (!rinfo->address) { 8279 continue; // skip fake entries for built-ins 8280 } 8281 8282 (*printf_func)(" dependency: %s(%s)@%p\n", 8283 rinfo->name, rinfo->version, rinfo->address); 8284 } 8285 8286 break; // only report this kmod for one backtrace address 8287 } 8288 } 8289 } 8290 8291 if (lockFlag) { 8292 IORecursiveLockUnlock(sKextLock); 8293 } 8294 8295 return; 8296 } 8297 8298 /******************************************************************************* 8299 * substitute() looks at an input string (a pointer within a larger buffer) 8300 * for a match to a substring, and on match it writes the marker & substitution 8301 * character to an output string, updating the scan (from) and 8302 * output (to) indexes as appropriate. 8303 *******************************************************************************/ 8304 static int substitute( 8305 const char * scan_string, 8306 char * string_out, 8307 uint32_t * to_index, 8308 uint32_t * from_index, 8309 const char * substring, 8310 char marker, 8311 char substitution); 8312 8313 /* string_out must be at least KMOD_MAX_NAME bytes. 8314 */ 8315 static int 8316 substitute( 8317 const char * scan_string, 8318 char * string_out, 8319 uint32_t * to_index, 8320 uint32_t * from_index, 8321 const char * substring, 8322 char marker, 8323 char substitution) 8324 { 8325 uint32_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1); 8326 8327 /* On a substring match, append the marker (if there is one) and then 8328 * the substitution character, updating the output (to) index accordingly. 8329 * Then update the input (from) length by the length of the substring 8330 * that got replaced. 8331 */ 8332 if (!strncmp(scan_string, substring, substring_length)) { 8333 if (marker) { 8334 string_out[(*to_index)++] = marker; 8335 } 8336 string_out[(*to_index)++] = substitution; 8337 (*from_index) += substring_length; 8338 return 1; 8339 } 8340 return 0; 8341 } 8342 8343 /******************************************************************************* 8344 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least 8345 * KMOD_MAX_NAME characters and performs various substitutions of common 8346 * prefixes & substrings as defined by tables in kext_panic_report.h. 8347 *******************************************************************************/ 8348 static void compactIdentifier( 8349 const char * identifier, 8350 char * identifier_out, 8351 char ** identifier_out_end); 8352 8353 static void 8354 compactIdentifier( 8355 const char * identifier, 8356 char * identifier_out, 8357 char ** identifier_out_end) 8358 { 8359 uint32_t from_index, to_index; 8360 uint32_t scan_from_index = 0; 8361 uint32_t scan_to_index = 0; 8362 subs_entry_t * subs_entry = NULL; 8363 int did_sub = 0; 8364 8365 from_index = to_index = 0; 8366 identifier_out[0] = '\0'; 8367 8368 /* Replace certain identifier prefixes with shorter @+character sequences. 8369 * Check the return value of substitute() so we only replace the prefix. 8370 */ 8371 for (subs_entry = &kext_identifier_prefix_subs[0]; 8372 subs_entry->substring && !did_sub; 8373 subs_entry++) { 8374 8375 did_sub = substitute(identifier, identifier_out, 8376 &scan_to_index, &scan_from_index, 8377 subs_entry->substring, /* marker */ '\0', subs_entry->substitute); 8378 } 8379 did_sub = 0; 8380 8381 /* Now scan through the identifier looking for the common substrings 8382 * and replacing them with shorter !+character sequences via substitute(). 8383 */ 8384 for (/* see above */; 8385 scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index]; 8386 /* see loop */) { 8387 8388 const char * scan_string = &identifier[scan_from_index]; 8389 8390 did_sub = 0; 8391 8392 if (scan_from_index) { 8393 for (subs_entry = &kext_identifier_substring_subs[0]; 8394 subs_entry->substring && !did_sub; 8395 subs_entry++) { 8396 8397 did_sub = substitute(scan_string, identifier_out, 8398 &scan_to_index, &scan_from_index, 8399 subs_entry->substring, '!', subs_entry->substitute); 8400 } 8401 } 8402 8403 /* If we didn't substitute, copy the input character to the output. 8404 */ 8405 if (!did_sub) { 8406 identifier_out[scan_to_index++] = identifier[scan_from_index++]; 8407 } 8408 } 8409 8410 identifier_out[scan_to_index] = '\0'; 8411 if (identifier_out_end) { 8412 *identifier_out_end = &identifier_out[scan_to_index]; 8413 } 8414 8415 return; 8416 } 8417 8418 /******************************************************************************* 8419 * assemble_identifier_and_version() adds to a string buffer a compacted 8420 * bundle identifier followed by a version string. 8421 *******************************************************************************/ 8422 8423 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length. 8424 */ 8425 static int assemble_identifier_and_version( 8426 kmod_info_t * kmod_info, 8427 char * identPlusVers); 8428 static int 8429 assemble_identifier_and_version( 8430 kmod_info_t * kmod_info, 8431 char * identPlusVers) 8432 { 8433 int result = 0; 8434 8435 compactIdentifier(kmod_info->name, identPlusVers, NULL); 8436 result = strnlen(identPlusVers, KMOD_MAX_NAME - 1); 8437 identPlusVers[result++] = '\t'; // increment for real char 8438 identPlusVers[result] = '\0'; // don't increment for nul char 8439 result = strlcat(identPlusVers, kmod_info->version, KMOD_MAX_NAME); 8440 8441 return result; 8442 } 8443 8444 /******************************************************************************* 8445 *******************************************************************************/ 8446 #define LAST_LOADED " - last loaded " 8447 #define LAST_LOADED_TS_WIDTH (16) 8448 8449 /* static */ 8450 uint32_t 8451 OSKext::saveLoadedKextPanicListTyped( 8452 const char * prefix, 8453 int invertFlag, 8454 int libsFlag, 8455 char * paniclist, 8456 uint32_t list_size, 8457 uint32_t * list_length_ptr) 8458 { 8459 uint32_t result = 0; 8460 int error = 0; 8461 unsigned int count, i; 8462 8463 count = sLoadedKexts->getCount(); 8464 if (!count) { 8465 goto finish; 8466 } 8467 8468 i = count - 1; 8469 do { 8470 OSKext * theKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 8471 kmod_info_t * kmod_info = theKext->kmod_info; 8472 int match; 8473 char identPlusVers[2*KMOD_MAX_NAME]; 8474 uint32_t identPlusVersLength; 8475 char timestampBuffer[17]; // enough for a uint64_t 8476 8477 /* Skip all built-in kexts. 8478 */ 8479 if (theKext->isKernelComponent()) { 8480 continue; 8481 } 8482 8483 /* Filter for kmod name (bundle identifier). 8484 */ 8485 match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME)); 8486 if ((match && invertFlag) || (!match && !invertFlag)) { 8487 continue; 8488 } 8489 8490 /* Filter for libraries (kexts that have a compatible version). 8491 */ 8492 if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) || 8493 (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) { 8494 8495 continue; 8496 } 8497 8498 if (!kmod_info || 8499 !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) { 8500 8501 printf("kext scan stopped due to missing kmod_info page: %p\n", 8502 kmod_info); 8503 error = 1; 8504 goto finish; 8505 } 8506 8507 identPlusVersLength = assemble_identifier_and_version(kmod_info, 8508 identPlusVers); 8509 if (!identPlusVersLength) { 8510 printf("error saving loaded kext info\n"); 8511 goto finish; 8512 } 8513 8514 /* We're going to note the last-loaded kext in the list. 8515 */ 8516 if (i + 1 == count) { 8517 snprintf(timestampBuffer, sizeof(timestampBuffer), "%llu", 8518 AbsoluteTime_to_scalar(&last_loaded_timestamp)); 8519 identPlusVersLength += sizeof(LAST_LOADED) - 1 + 8520 strnlen(timestampBuffer, sizeof(timestampBuffer)); 8521 } 8522 8523 /* Adding 1 for the newline. 8524 */ 8525 if (*list_length_ptr + identPlusVersLength + 1 >= list_size) { 8526 goto finish; 8527 } 8528 8529 *list_length_ptr = strlcat(paniclist, identPlusVers, list_size); 8530 if (i + 1 == count) { 8531 *list_length_ptr = strlcat(paniclist, LAST_LOADED, list_size); 8532 *list_length_ptr = strlcat(paniclist, timestampBuffer, list_size); 8533 } 8534 *list_length_ptr = strlcat(paniclist, "\n", list_size); 8535 8536 } while (i--); 8537 8538 finish: 8539 if (!error) { 8540 if (*list_length_ptr + 1 <= list_size) { 8541 result = list_size - (*list_length_ptr + 1); 8542 } 8543 } 8544 8545 return result; 8546 } 8547 8548 /********************************************************************* 8549 *********************************************************************/ 8550 /* static */ 8551 void 8552 OSKext::saveLoadedKextPanicList(void) 8553 { 8554 char * newlist = NULL; 8555 uint32_t newlist_size = 0; 8556 uint32_t newlist_length = 0; 8557 8558 IORecursiveLockLock(sKextLock); 8559 8560 newlist_length = 0; 8561 newlist_size = KEXT_PANICLIST_SIZE; 8562 newlist = (char *)kalloc(newlist_size); 8563 8564 if (!newlist) { 8565 OSKextLog(/* kext */ NULL, 8566 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 8567 "Couldn't allocate kext panic log buffer."); 8568 goto finish; 8569 } 8570 8571 newlist[0] = '\0'; 8572 8573 // non-"com.apple." kexts 8574 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1, 8575 /* libs? */ -1, newlist, newlist_size, &newlist_length)) { 8576 8577 goto finish; 8578 } 8579 // "com.apple." nonlibrary kexts 8580 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 8581 /* libs? */ 0, newlist, newlist_size, &newlist_length)) { 8582 8583 goto finish; 8584 } 8585 // "com.apple." library kexts 8586 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 8587 /* libs? */ 1, newlist, newlist_size, &newlist_length)) { 8588 8589 goto finish; 8590 } 8591 8592 if (loaded_kext_paniclist) { 8593 kfree(loaded_kext_paniclist, loaded_kext_paniclist_size); 8594 } 8595 loaded_kext_paniclist = newlist; 8596 loaded_kext_paniclist_size = newlist_size; 8597 loaded_kext_paniclist_length = newlist_length; 8598 8599 finish: 8600 IORecursiveLockUnlock(sKextLock); 8601 return; 8602 } 8603 8604 /********************************************************************* 8605 *********************************************************************/ 8606 /* static */ 8607 void 8608 OSKext::saveUnloadedKextPanicList(OSKext * aKext) 8609 { 8610 char * newlist = NULL; 8611 uint32_t newlist_size = 0; 8612 uint32_t newlist_length = 0; 8613 char identPlusVers[2*KMOD_MAX_NAME]; 8614 uint32_t identPlusVersLength; 8615 8616 if (!aKext->kmod_info) { 8617 return; // do not goto finish here b/c of lock 8618 } 8619 8620 IORecursiveLockLock(sKextLock); 8621 8622 clock_get_uptime(&last_unloaded_timestamp); 8623 last_unloaded_address = (void *)aKext->kmod_info->address; 8624 last_unloaded_size = aKext->kmod_info->size; 8625 8626 8627 identPlusVersLength = assemble_identifier_and_version(aKext->kmod_info, 8628 identPlusVers); 8629 if (!identPlusVersLength) { 8630 printf("error saving unloaded kext info\n"); 8631 goto finish; 8632 } 8633 8634 newlist_length = identPlusVersLength; 8635 newlist_size = newlist_length + 1; 8636 newlist = (char *)kalloc(newlist_size); 8637 8638 if (!newlist) { 8639 printf("couldn't allocate kext panic log buffer\n"); 8640 goto finish; 8641 } 8642 8643 newlist[0] = '\0'; 8644 8645 strlcpy(newlist, identPlusVers, newlist_size); 8646 8647 if (unloaded_kext_paniclist) { 8648 kfree(unloaded_kext_paniclist, unloaded_kext_paniclist_size); 8649 } 8650 unloaded_kext_paniclist = newlist; 8651 unloaded_kext_paniclist_size = newlist_size; 8652 unloaded_kext_paniclist_length = newlist_length; 8653 8654 finish: 8655 IORecursiveLockUnlock(sKextLock); 8656 return; 8657 } 8658 8659 /********************************************************************* 8660 *********************************************************************/ 8661 #if __LP64__ 8662 #define __kLoadSizeEscape "0x%lld" 8663 #else 8664 #define __kLoadSizeEscape "0x%ld" 8665 #endif /* __LP64__ */ 8666 8667 /* static */ 8668 void 8669 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...)) 8670 { 8671 printf_func("unloaded kexts:\n"); 8672 if (unloaded_kext_paniclist && 8673 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) unloaded_kext_paniclist) && 8674 unloaded_kext_paniclist[0]) { 8675 8676 printf_func( 8677 "%.*s (addr %p, size " __kLoadSizeEscape ") - last unloaded %llu\n", 8678 unloaded_kext_paniclist_length, unloaded_kext_paniclist, 8679 last_unloaded_address, last_unloaded_size, 8680 AbsoluteTime_to_scalar(&last_unloaded_timestamp)); 8681 } else { 8682 printf_func("(none)\n"); 8683 } 8684 printf_func("loaded kexts:\n"); 8685 if (loaded_kext_paniclist && 8686 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) && 8687 loaded_kext_paniclist[0]) { 8688 8689 printf_func("%.*s", loaded_kext_paniclist_length, loaded_kext_paniclist); 8690 } else { 8691 printf_func("(none)\n"); 8692 } 8693 return; 8694 } 8695 8696 /********************************************************************* 8697 *********************************************************************/ 8698 #if __ppc__ || __i386__ 8699 /* static */ 8700 kern_return_t 8701 OSKext::getKmodInfo( 8702 kmod_info_array_t * kmodList, 8703 mach_msg_type_number_t * kmodCount) 8704 { 8705 kern_return_t result = KERN_FAILURE; 8706 vm_offset_t data; 8707 kmod_info_t * k, * kmod_info_scan_ptr; 8708 kmod_reference_t * r, * ref_scan_ptr; 8709 int ref_count; 8710 unsigned size = 0; 8711 8712 *kmodList = (kmod_info_t *)0; 8713 *kmodCount = 0; 8714 8715 IORecursiveLockLock(sKextLock); 8716 8717 k = kmod; 8718 while (k) { 8719 size += sizeof(kmod_info_t); 8720 r = k->reference_list; 8721 while (r) { 8722 size +=sizeof(kmod_reference_t); 8723 r = r->next; 8724 } 8725 k = k->next; 8726 } 8727 if (!size) { 8728 result = KERN_SUCCESS; 8729 goto finish; 8730 } 8731 8732 result = kmem_alloc(kernel_map, &data, size); 8733 if (result != KERN_SUCCESS) { 8734 goto finish; 8735 } 8736 8737 /* Copy each kmod_info struct sequentially into the data buffer. 8738 * Set each struct's nonzero 'next' pointer back to itself as a sentinel; 8739 * the kernel space address is used to match refs, and a zero 'next' flags 8740 * the end of kmod_infos in the data buffer and the beginning of references. 8741 */ 8742 k = kmod; 8743 kmod_info_scan_ptr = (kmod_info_t *)data; 8744 while (k) { 8745 *kmod_info_scan_ptr = *k; 8746 if (k->next) { 8747 kmod_info_scan_ptr->next = k; 8748 } 8749 kmod_info_scan_ptr++; 8750 k = k->next; 8751 } 8752 8753 /* Now add references after the kmod_info structs in the same buffer. 8754 * Update each kmod_info with the ref_count so we can associate 8755 * references with kmod_info structs. 8756 */ 8757 k = kmod; 8758 ref_scan_ptr = (kmod_reference_t *)kmod_info_scan_ptr; 8759 kmod_info_scan_ptr = (kmod_info_t *)data; 8760 while (k) { 8761 r = k->reference_list; 8762 ref_count = 0; 8763 while (r) { 8764 /* Note the last kmod_info in the data buffer has its next == 0. 8765 * Since there can only be one like that, 8766 * this case is handled by the caller. 8767 */ 8768 *ref_scan_ptr = *r; 8769 ref_scan_ptr++; 8770 r = r->next; 8771 ref_count++; 8772 } 8773 /* Stuff the # of refs into the 'reference_list' field of the kmod_info 8774 * struct for the client to interpret. 8775 */ 8776 kmod_info_scan_ptr->reference_list = (kmod_reference_t *)(long)ref_count; 8777 kmod_info_scan_ptr++; 8778 k = k->next; 8779 } 8780 8781 result = vm_map_copyin(kernel_map, data, size, TRUE, (vm_map_copy_t *)kmodList); 8782 if (result != KERN_SUCCESS) { 8783 goto finish; 8784 } 8785 8786 *kmodCount = size; 8787 result = KERN_SUCCESS; 8788 8789 finish: 8790 IORecursiveLockUnlock(sKextLock); 8791 8792 if (result != KERN_SUCCESS && data) { 8793 kmem_free(kernel_map, data, size); 8794 *kmodList = (kmod_info_t *)0; 8795 *kmodCount = 0; 8796 } 8797 return result; 8798 } 8799 #endif /* __ppc__ || __i386__ */ 8800 #if PRAGMA_MARK 8801 #pragma mark MAC Framework Support 8802 #endif 8803 /********************************************************************* 8804 *********************************************************************/ 8805 #if CONFIG_MACF_KEXT 8806 /* MAC Framework support */ 8807 8808 /* 8809 * define IOC_DEBUG to display run-time debugging information 8810 * #define IOC_DEBUG 1 8811 */ 8812 8813 #ifdef IOC_DEBUG 8814 #define DPRINTF(x) printf x 8815 #else 8816 #define IOC_DEBUG 8817 #define DPRINTF(x) 8818 #endif 8819 8820 /********************************************************************* 8821 *********************************************************************/ 8822 static bool 8823 MACFObjectIsPrimitiveType(OSObject * obj) 8824 { 8825 const OSMetaClass * typeID = NULL; // do not release 8826 8827 typeID = OSTypeIDInst(obj); 8828 if (typeID == OSTypeID(OSString) || typeID == OSTypeID(OSNumber) || 8829 typeID == OSTypeID(OSBoolean) || typeID == OSTypeID(OSData)) { 8830 8831 return true; 8832 } 8833 return false; 8834 } 8835 8836 /********************************************************************* 8837 *********************************************************************/ 8838 static int 8839 MACFLengthForObject(OSObject * obj) 8840 { 8841 const OSMetaClass * typeID = NULL; // do not release 8842 int len; 8843 8844 typeID = OSTypeIDInst(obj); 8845 if (typeID == OSTypeID(OSString)) { 8846 OSString * stringObj = OSDynamicCast(OSString, obj); 8847 len = stringObj->getLength() + 1; 8848 } else if (typeID == OSTypeID(OSNumber)) { 8849 len = sizeof("4294967295"); /* UINT32_MAX */ 8850 } else if (typeID == OSTypeID(OSBoolean)) { 8851 OSBoolean * boolObj = OSDynamicCast(OSBoolean, obj); 8852 len = boolObj->isTrue() ? sizeof("true") : sizeof("false"); 8853 } else if (typeID == OSTypeID(OSData)) { 8854 OSData * dataObj = OSDynamicCast(OSData, obj); 8855 len = dataObj->getLength(); 8856 } else { 8857 len = 0; 8858 } 8859 return len; 8860 } 8861 8862 /********************************************************************* 8863 *********************************************************************/ 8864 static void 8865 MACFInitElementFromObject( 8866 struct mac_module_data_element * element, 8867 OSObject * value) 8868 { 8869 const OSMetaClass * typeID = NULL; // do not release 8870 8871 typeID = OSTypeIDInst(value); 8872 if (typeID == OSTypeID(OSString)) { 8873 OSString * stringObj = OSDynamicCast(OSString, value); 8874 element->value_type = MAC_DATA_TYPE_PRIMITIVE; 8875 element->value_size = stringObj->getLength() + 1; 8876 DPRINTF(("osdict: string %s size %d\n", 8877 stringObj->getCStringNoCopy(), element->value_size)); 8878 memcpy(element->value, stringObj->getCStringNoCopy(), 8879 element->value_size); 8880 } else if (typeID == OSTypeID(OSNumber)) { 8881 OSNumber * numberObj = OSDynamicCast(OSNumber, value); 8882 element->value_type = MAC_DATA_TYPE_PRIMITIVE; 8883 element->value_size = sprintf(element->value, "%u", 8884 numberObj->unsigned32BitValue()) + 1; 8885 } else if (typeID == OSTypeID(OSBoolean)) { 8886 OSBoolean * boolObj = OSDynamicCast(OSBoolean, value); 8887 element->value_type = MAC_DATA_TYPE_PRIMITIVE; 8888 if (boolObj->isTrue()) { 8889 strcpy(element->value, "true"); 8890 element->value_size = 5; 8891 } else { 8892 strcpy(element->value, "false"); 8893 element->value_size = 6; 8894 } 8895 } else if (typeID == OSTypeID(OSData)) { 8896 OSData * dataObj = OSDynamicCast(OSData, value); 8897 element->value_type = MAC_DATA_TYPE_PRIMITIVE; 8898 element->value_size = dataObj->getLength(); 8899 DPRINTF(("osdict: data size %d\n", dataObj->getLength())); 8900 memcpy(element->value, dataObj->getBytesNoCopy(), 8901 element->value_size); 8902 } 8903 return; 8904 } 8905 8906 /********************************************************************* 8907 * This function takes an OSDictionary and returns a struct mac_module_data 8908 * list. 8909 *********************************************************************/ 8910 static struct mac_module_data * 8911 MACFEncodeOSDictionary(OSDictionary * dict) 8912 { 8913 struct mac_module_data * result = NULL; // do not free 8914 const OSMetaClass * typeID = NULL; // do not release 8915 OSString * key = NULL; // do not release 8916 OSCollectionIterator * keyIterator = NULL; // must release 8917 struct mac_module_data_element * element = NULL; // do not free 8918 unsigned int strtabsize = 0; 8919 unsigned int listtabsize = 0; 8920 unsigned int dicttabsize = 0; 8921 unsigned int nkeys = 0; 8922 unsigned int datalen = 0; 8923 char * strtab = NULL; // do not free 8924 char * listtab = NULL; // do not free 8925 char * dicttab = NULL; // do not free 8926 vm_offset_t data_addr = 0; 8927 8928 keyIterator = OSCollectionIterator::withCollection(dict); 8929 if (!keyIterator) { 8930 goto finish; 8931 } 8932 8933 /* Iterate over OSModuleData to figure out total size */ 8934 while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) { 8935 8936 // Get the key's value and determine its type 8937 OSObject * value = dict->getObject(key); 8938 if (!value) { 8939 continue; 8940 } 8941 8942 typeID = OSTypeIDInst(value); 8943 if (MACFObjectIsPrimitiveType(value)) { 8944 strtabsize += MACFLengthForObject(value); 8945 } 8946 else if (typeID == OSTypeID(OSArray)) { 8947 unsigned int k, cnt, nents; 8948 OSArray * arrayObj = OSDynamicCast(OSArray, value); 8949 8950 nents = 0; 8951 cnt = arrayObj->getCount(); 8952 for (k = 0; k < cnt; k++) { 8953 value = arrayObj->getObject(k); 8954 typeID = OSTypeIDInst(value); 8955 if (MACFObjectIsPrimitiveType(value)) { 8956 listtabsize += MACFLengthForObject(value); 8957 nents++; 8958 } 8959 else if (typeID == OSTypeID(OSDictionary)) { 8960 unsigned int dents = 0; 8961 OSDictionary * dictObj = NULL; // do not release 8962 OSString * dictkey = NULL; // do not release 8963 OSCollectionIterator * dictIterator = NULL; // must release 8964 8965 dictObj = OSDynamicCast(OSDictionary, value); 8966 dictIterator = OSCollectionIterator::withCollection(dictObj); 8967 if (!dictIterator) { 8968 goto finish; 8969 } 8970 while ((dictkey = OSDynamicCast(OSString, 8971 dictIterator->getNextObject()))) { 8972 8973 OSObject * dictvalue = NULL; // do not release 8974 8975 dictvalue = dictObj->getObject(dictkey); 8976 if (!dictvalue) { 8977 continue; 8978 } 8979 if (MACFObjectIsPrimitiveType(dictvalue)) { 8980 strtabsize += MACFLengthForObject(dictvalue); 8981 } else { 8982 continue; /* Only handle primitive types here. */ 8983 } 8984 /* 8985 * Allow for the "arraynnn/" prefix in the key length. 8986 */ 8987 strtabsize += dictkey->getLength() + 1; 8988 dents++; 8989 } 8990 dictIterator->release(); 8991 if (dents-- > 0) { 8992 dicttabsize += sizeof(struct mac_module_data_list) + 8993 dents * sizeof(struct mac_module_data_element); 8994 nents++; 8995 } 8996 } 8997 else { 8998 continue; /* Skip everything else. */ 8999 } 9000 } 9001 if (nents == 0) { 9002 continue; 9003 } 9004 listtabsize += sizeof(struct mac_module_data_list) + 9005 (nents - 1) * sizeof(struct mac_module_data_element); 9006 } else { 9007 continue; /* skip anything else */ 9008 } 9009 strtabsize += key->getLength() + 1; 9010 nkeys++; 9011 } 9012 if (nkeys == 0) { 9013 goto finish; 9014 } 9015 9016 /* 9017 * Allocate and fill in the module data structures. 9018 */ 9019 datalen = sizeof(struct mac_module_data) + 9020 sizeof(mac_module_data_element) * (nkeys - 1) + 9021 strtabsize + listtabsize + dicttabsize; 9022 DPRINTF(("osdict: datalen %d strtabsize %d listtabsize %d dicttabsize %d\n", 9023 datalen, strtabsize, listtabsize, dicttabsize)); 9024 if (kmem_alloc(kernel_map, &data_addr, datalen) != KERN_SUCCESS) { 9025 goto finish; 9026 } 9027 result = (mac_module_data *)data_addr; 9028 result->base_addr = data_addr; 9029 result->size = datalen; 9030 result->count = nkeys; 9031 strtab = (char *)&result->data[nkeys]; 9032 listtab = strtab + strtabsize; 9033 dicttab = listtab + listtabsize; 9034 DPRINTF(("osdict: data_addr %p strtab %p listtab %p dicttab %p end %p\n", 9035 data_addr, strtab, listtab, dicttab, data_addr + datalen)); 9036 9037 keyIterator->reset(); 9038 nkeys = 0; 9039 element = &result->data[0]; 9040 DPRINTF(("osdict: element %p\n", element)); 9041 while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) { 9042 9043 // Get the key's value and determine its type 9044 OSObject * value = dict->getObject(key); 9045 if (!value) { 9046 continue; 9047 } 9048 9049 /* Store key */ 9050 DPRINTF(("osdict: element @%p\n", element)); 9051 element->key = strtab; 9052 element->key_size = key->getLength() + 1; 9053 DPRINTF(("osdict: key %s size %d @%p\n", key->getCStringNoCopy(), 9054 element->key_size, strtab)); 9055 memcpy(element->key, key->getCStringNoCopy(), element->key_size); 9056 9057 typeID = OSTypeIDInst(value); 9058 if (MACFObjectIsPrimitiveType(value)) { 9059 /* Store value */ 9060 element->value = element->key + element->key_size; 9061 DPRINTF(("osdict: primitive element value %p\n", element->value)); 9062 MACFInitElementFromObject(element, value); 9063 strtab += element->key_size + element->value_size; 9064 DPRINTF(("osdict: new strtab %p\n", strtab)); 9065 } else if (typeID == OSTypeID(OSArray)) { 9066 unsigned int k, cnt, nents; 9067 char *astrtab; 9068 struct mac_module_data_list *arrayhd; 9069 struct mac_module_data_element *ele; 9070 OSArray *arrayObj = OSDynamicCast(OSArray, value); 9071 9072 element->value = listtab; 9073 DPRINTF(("osdict: array element value %p\n", element->value)); 9074 element->value_type = MAC_DATA_TYPE_ARRAY; 9075 arrayhd = (struct mac_module_data_list *)element->value; 9076 arrayhd->type = 0; 9077 DPRINTF(("osdict: arrayhd %p\n", arrayhd)); 9078 nents = 0; 9079 astrtab = strtab + element->key_size; 9080 ele = &(arrayhd->list[0]); 9081 cnt = arrayObj->getCount(); 9082 for (k = 0; k < cnt; k++) { 9083 value = arrayObj->getObject(k); 9084 DPRINTF(("osdict: array ele %d @%p\n", nents, ele)); 9085 ele->key = NULL; 9086 ele->key_size = 0; 9087 typeID = OSTypeIDInst(value); 9088 if (MACFObjectIsPrimitiveType(value)) { 9089 if (arrayhd->type != 0 && 9090 arrayhd->type != MAC_DATA_TYPE_PRIMITIVE) { 9091 9092 continue; 9093 } 9094 arrayhd->type = MAC_DATA_TYPE_PRIMITIVE; 9095 ele->value = astrtab; 9096 MACFInitElementFromObject(ele, value); 9097 astrtab += ele->value_size; 9098 DPRINTF(("osdict: array new astrtab %p\n", astrtab)); 9099 } else if (typeID == OSTypeID(OSDictionary)) { 9100 unsigned int dents; 9101 char * dstrtab = NULL; // do not free 9102 OSDictionary * dictObj = NULL; // do not release 9103 OSString * dictkey = NULL; // do not release 9104 OSCollectionIterator * dictIterator = NULL; // must release 9105 struct mac_module_data_list * dicthd = NULL; // do not free 9106 struct mac_module_data_element * dele = NULL; // do not free 9107 9108 if (arrayhd->type != 0 && 9109 arrayhd->type != MAC_DATA_TYPE_DICT) { 9110 9111 continue; 9112 } 9113 dictObj = OSDynamicCast(OSDictionary, value); 9114 dictIterator = OSCollectionIterator::withCollection(dictObj); 9115 if (!dictIterator) { 9116 goto finish; 9117 } 9118 DPRINTF(("osdict: dict\n")); 9119 ele->value = dicttab; 9120 ele->value_type = MAC_DATA_TYPE_DICT; 9121 dicthd = (struct mac_module_data_list *)ele->value; 9122 DPRINTF(("osdict: dicthd %p\n", dicthd)); 9123 dstrtab = astrtab; 9124 dents = 0; 9125 while ((dictkey = OSDynamicCast(OSString, 9126 dictIterator->getNextObject()))) { 9127 9128 OSObject * dictvalue = NULL; // do not release 9129 9130 dictvalue = dictObj->getObject(dictkey); 9131 if (!dictvalue) { 9132 continue; 9133 } 9134 dele = &(dicthd->list[dents]); 9135 DPRINTF(("osdict: dict ele %d @%p\n", dents, dele)); 9136 if (MACFObjectIsPrimitiveType(dictvalue)) { 9137 dele->key = dstrtab; 9138 dele->key_size = dictkey->getLength() + 1; 9139 DPRINTF(("osdict: dictkey %s size %d @%p\n", 9140 dictkey->getCStringNoCopy(), dictkey->getLength(), dstrtab)); 9141 memcpy(dele->key, dictkey->getCStringNoCopy(), 9142 dele->key_size); 9143 dele->value = dele->key + dele->key_size; 9144 MACFInitElementFromObject(dele, dictvalue); 9145 dstrtab += dele->key_size + dele->value_size; 9146 DPRINTF(("osdict: dict new dstrtab %p\n", dstrtab)); 9147 } else { 9148 continue; /* Only handle primitive types here. */ 9149 } 9150 dents++; 9151 } 9152 dictIterator->release(); 9153 if (dents == 0) { 9154 continue; 9155 } 9156 arrayhd->type = MAC_DATA_TYPE_DICT; 9157 ele->value_size = sizeof(struct mac_module_data_list) + 9158 (dents - 1) * sizeof(struct mac_module_data_element); 9159 DPRINTF(("osdict: dict ele size %d ents %d\n", ele->value_size, dents)); 9160 dicttab += ele->value_size; 9161 DPRINTF(("osdict: new dicttab %p\n", dicttab)); 9162 dicthd->count = dents; 9163 astrtab = dstrtab; 9164 } else { 9165 continue; /* Skip everything else. */ 9166 } 9167 nents++; 9168 ele++; 9169 } 9170 if (nents == 0) { 9171 continue; 9172 } 9173 element->value_size = sizeof(struct mac_module_data_list) + 9174 (nents - 1) * sizeof(struct mac_module_data_element); 9175 listtab += element->value_size; 9176 DPRINTF(("osdict: new listtab %p\n", listtab)); 9177 arrayhd->count = nents; 9178 strtab = astrtab; 9179 DPRINTF(("osdict: new strtab %p\n", strtab)); 9180 } else { 9181 continue; /* skip anything else */ 9182 } 9183 element++; 9184 } 9185 DPRINTF(("result list @%p, key %p value %p\n", 9186 result, result->data[0].key, result->data[0].value)); 9187 finish: 9188 if (keyIterator) keyIterator->release(); 9189 return result; 9190 } 9191 9192 /********************************************************************* 9193 * This function takes a plist and looks for an OSModuleData dictionary. 9194 * If it is found, an encoded copy is returned. The value must be 9195 * kmem_free()'d. 9196 *********************************************************************/ 9197 static void * 9198 MACFCopyModuleDataForKext( 9199 OSKext * theKext, 9200 mach_msg_type_number_t * datalen) 9201 9202 { 9203 struct mac_module_data * result = NULL; 9204 OSDictionary * kextModuleData = NULL; // do not release 9205 vm_map_copy_t copy = 0; 9206 9207 kextModuleData = OSDynamicCast(OSDictionary, 9208 theKext->getPropertyForHostArch("OSModuleData")); 9209 if (!kextModuleData) { 9210 goto finish; 9211 } 9212 9213 result = MACFEncodeOSDictionary(kextModuleData); 9214 if (!result) { 9215 goto finish; 9216 } 9217 *datalen = module_data->size; 9218 9219 finish: 9220 return (void *)result; 9221 } 9222 #endif /* CONFIG_MACF_KEXT */ 9223