1 /* 2 * Copyright (c) 2008-2012 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 <vm/vm_kern.h> 34 #include <kextd/kextd_mach.h> 35 #include <libkern/kernel_mach_header.h> 36 #include <libkern/kext_panic_report.h> 37 #include <libkern/kext_request_keys.h> 38 #include <libkern/mkext.h> 39 #include <libkern/prelink.h> 40 #include <libkern/version.h> 41 #include <libkern/zlib.h> 42 #include <mach/host_special_ports.h> 43 #include <mach/mach_vm.h> 44 #include <mach/mach_time.h> 45 #include <sys/sysctl.h> 46 #include <uuid/uuid.h> 47 // 04/18/11 - gab: <rdar://problem/9236163> 48 #include <sys/random.h> 49 50 #include <sys/pgo.h> 51 52 #if CONFIG_MACF 53 #include <sys/kauth.h> 54 #include <security/mac_framework.h> 55 #endif 56 }; 57 58 #include <libkern/OSKextLibPrivate.h> 59 #include <libkern/c++/OSKext.h> 60 #include <libkern/c++/OSLib.h> 61 62 #include <IOKit/IOLib.h> 63 #include <IOKit/IOCatalogue.h> 64 #include <IOKit/IORegistryEntry.h> 65 #include <IOKit/IOService.h> 66 67 #include <IOKit/IOStatisticsPrivate.h> 68 #include <IOKit/IOBSD.h> 69 70 #if PRAGMA_MARK 71 #pragma mark External & Internal Function Protos 72 #endif 73 /********************************************************************* 74 *********************************************************************/ 75 extern "C" { 76 extern int IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize); 77 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize); 78 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t * segment); 79 extern void OSRuntimeUnloadCPP(kmod_info_t * ki, void * data); 80 81 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */ 82 } 83 84 static OSReturn _OSKextCreateRequest( 85 const char * predicate, 86 OSDictionary ** requestP); 87 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict); 88 static OSObject * _OSKextGetRequestArgument( 89 OSDictionary * requestDict, 90 const char * argName); 91 static bool _OSKextSetRequestArgument( 92 OSDictionary * requestDict, 93 const char * argName, 94 OSObject * value); 95 static void * _OSKextExtractPointer(OSData * wrapper); 96 static OSReturn _OSDictionarySetCStringValue( 97 OSDictionary * dict, 98 const char * key, 99 const char * value); 100 static bool _OSKextInPrelinkRebuildWindow(void); 101 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID); 102 103 // We really should add containsObject() & containsCString to OSCollection & subclasses. 104 // So few pad slots, though.... 105 static bool _OSArrayContainsCString(OSArray * array, const char * cString); 106 107 #if CONFIG_KEC_FIPS 108 static void * GetAppleTEXTHashForKext(OSKext * theKext, OSDictionary *theInfoDict); 109 #endif // CONFIG_KEC_FIPS 110 111 /* Prelinked arm kexts do not have VM entries because the method we use to 112 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does 113 * not work on ARM. To get around that, we must free prelinked kext 114 * executables with ml_static_mfree() instead of kext_free(). 115 */ 116 #if __i386__ || __x86_64__ 117 #define VM_MAPPED_KEXTS 1 118 #define KASLR_KEXT_DEBUG 0 119 #define KASLR_IOREG_DEBUG 0 120 #else 121 #error Unsupported architecture 122 #endif 123 124 #if PRAGMA_MARK 125 #pragma mark Constants & Macros 126 #endif 127 /********************************************************************* 128 * Constants & Macros 129 *********************************************************************/ 130 131 /* Use this number to create containers. 132 */ 133 #define kOSKextTypicalLoadCount (150) 134 135 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict. 136 * A loaded kext will no dependents or external retains will have 2 retains. 137 */ 138 #define kOSKextMinRetainCount (1) 139 #define kOSKextMinLoadedRetainCount (2) 140 141 /********** 142 * Strings and substrings used in dependency resolution. 143 */ 144 #define APPLE_KEXT_PREFIX "com.apple." 145 #define KERNEL_LIB "com.apple.kernel" 146 147 #define PRIVATE_KPI "com.apple.kpi.private" 148 149 /* Version for compatbility pseudokexts (com.apple.kernel.*), 150 * compatible back to v6.0. 151 */ 152 #define KERNEL6_LIB "com.apple.kernel.6.0" 153 #define KERNEL6_VERSION "7.9.9" 154 155 #define KERNEL_LIB_PREFIX "com.apple.kernel." 156 #define KPI_LIB_PREFIX "com.apple.kpi." 157 158 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0) 159 160 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes 161 #define MINIMUM_WAKEUP_SECONDS (30) 162 163 /********************************************************************* 164 * infoDict keys for internally-stored data. Saves on ivar slots for 165 * objects we don't keep around past boot time or during active load. 166 *********************************************************************/ 167 168 /* A usable, uncompressed file is stored under this key. 169 */ 170 #define _kOSKextExecutableKey "_OSKextExecutable" 171 172 /* An indirect reference to the executable file from an mkext 173 * is stored under this key. 174 */ 175 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference" 176 177 /* If the file is contained in a larger buffer laid down by the booter or 178 * sent from user space, the OSKext stores that OSData under this key so that 179 * references are properly tracked. This is always an mkext, right now. 180 */ 181 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData" 182 183 #if PRAGMA_MARK 184 #pragma mark Typedefs 185 #endif 186 /********************************************************************* 187 * Typedefs 188 *********************************************************************/ 189 190 /********************************************************************* 191 * MkextEntryRef describes the contents of an OSData object 192 * referencing a file entry from an mkext so that we can uncompress 193 * (if necessary) and extract it on demand. 194 * 195 * It contains the mkextVersion in case we ever wind up supporting 196 * multiple mkext formats. Mkext format 1 is officially retired as of 197 * Snow Leopard. 198 *********************************************************************/ 199 typedef struct MkextEntryRef { 200 mkext_basic_header * mkext; // beginning of whole mkext file 201 void * fileinfo; // mkext2_file_entry or equiv; see mkext.h 202 } MkextEntryRef; 203 204 #if PRAGMA_MARK 205 #pragma mark Global and static Module Variables 206 #endif 207 /********************************************************************* 208 * Global & static variables, used to keep track of kexts. 209 *********************************************************************/ 210 211 static bool sPrelinkBoot = false; 212 static bool sSafeBoot = false; 213 static bool sKeepSymbols = false; 214 215 /********************************************************************* 216 * sKextLock is the principal lock for OSKext, and guards all static 217 * and global variables not owned by other locks (declared further 218 * below). It must be taken by any entry-point method or function, 219 * including internal functions called on scheduled threads. 220 * 221 * sKextLock and sKextInnerLock are recursive due to multiple functions 222 * that are called both externally and internally. The other locks are 223 * nonrecursive. 224 * 225 * Which locks are taken depends on what they protect, but if more than 226 * one must be taken, they must always be locked in this order 227 * (and unlocked in reverse order) to prevent deadlocks: 228 * 229 * 1. sKextLock 230 * 2. sKextInnerLock 231 * 3. sKextSummariesLock 232 * 4. sKextLoggingLock 233 */ 234 static IORecursiveLock * sKextLock = NULL; 235 236 static OSDictionary * sKextsByID = NULL; 237 static OSDictionary * sExcludeListByID = NULL; 238 static OSArray * sLoadedKexts = NULL; 239 static OSArray * sUnloadedPrelinkedKexts = NULL; 240 241 // Requests to kextd waiting to be picked up. 242 static OSArray * sKernelRequests = NULL; 243 // Identifier of kext load requests in sKernelRequests 244 static OSSet * sPostedKextLoadIdentifiers = NULL; 245 static OSArray * sRequestCallbackRecords = NULL; 246 247 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel 248 static OSSet * sAllKextLoadIdentifiers = NULL; 249 static KXLDContext * sKxldContext = NULL; 250 static uint32_t sNextLoadTag = 0; 251 static uint32_t sNextRequestTag = 0; 252 253 static bool sUserLoadsActive = false; 254 static bool sKextdActive = false; 255 static bool sDeferredLoadSucceeded = false; 256 static bool sConsiderUnloadsExecuted = false; 257 258 #if NO_KEXTD 259 static bool sKernelRequestsEnabled = false; 260 #else 261 static bool sKernelRequestsEnabled = true; 262 #endif 263 static bool sLoadEnabled = true; 264 static bool sUnloadEnabled = true; 265 266 /********************************************************************* 267 * Stuff for the OSKext representing the kernel itself. 268 **********/ 269 static OSKext * sKernelKext = NULL; 270 271 /* Set up a fake kmod_info struct for the kernel. 272 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP() 273 * before OSKext is initialized; that call only needs the name 274 * and address to be set correctly. 275 * 276 * We don't do much else with the kerne's kmod_info; we never 277 * put it into the kmod list, never adjust the reference count, 278 * and never have kernel components reference it. 279 * For that matter, we don't do much with kmod_info structs 280 * at all anymore! We just keep them filled in for gdb and 281 * binary compability. 282 */ 283 kmod_info_t g_kernel_kmod_info = { 284 /* next */ 0, 285 /* info_version */ KMOD_INFO_VERSION, 286 /* id */ 0, // loadTag: kernel is always 0 287 /* name */ kOSKextKernelIdentifier, // bundle identifier 288 /* version */ "0", // filled in in OSKext::initialize() 289 /* reference_count */ -1, // never adjusted; kernel never unloads 290 /* reference_list */ NULL, 291 /* address */ NULL, 292 /* size */ 0, // filled in in OSKext::initialize() 293 /* hdr_size */ 0, 294 /* start */ 0, 295 /* stop */ 0 296 }; 297 298 extern "C" { 299 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c, 300 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s, 301 // misc_protos.h, db_low_trace.c, kgmacros 302 // 'kmod' is a holdover from the old kmod system, we can't rename it. 303 kmod_info_t * kmod = NULL; 304 305 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE) 306 307 308 static char * loaded_kext_paniclist = NULL; 309 static uint32_t loaded_kext_paniclist_size = 0; 310 311 AbsoluteTime last_loaded_timestamp; 312 static char last_loaded_str_buf[2*KMOD_MAX_NAME]; 313 static u_long last_loaded_strlen = 0; 314 static void * last_loaded_address = NULL; 315 static u_long last_loaded_size = 0; 316 317 AbsoluteTime last_unloaded_timestamp; 318 static char last_unloaded_str_buf[2*KMOD_MAX_NAME]; 319 static u_long last_unloaded_strlen = 0; 320 static void * last_unloaded_address = NULL; 321 static u_long last_unloaded_size = 0; 322 323 /********************************************************************* 324 * sKextInnerLock protects against cross-calls with IOService and 325 * IOCatalogue, and owns the variables declared immediately below. 326 * 327 * Note that sConsiderUnloadsExecuted above belongs to sKextLock! 328 * 329 * When both sKextLock and sKextInnerLock need to be taken, 330 * always lock sKextLock first and unlock it second. Never take both 331 * locks in an entry point to OSKext; if you need to do so, you must 332 * spawn an independent thread to avoid potential deadlocks for threads 333 * calling into OSKext. 334 **********/ 335 static IORecursiveLock * sKextInnerLock = NULL; 336 337 static bool sAutounloadEnabled = true; 338 static bool sConsiderUnloadsCalled = false; 339 static bool sConsiderUnloadsPending = false; 340 341 static unsigned int sConsiderUnloadDelay = 60; // seconds 342 static thread_call_t sUnloadCallout = 0; 343 static thread_call_t sDestroyLinkContextThread = 0; // one-shot, one-at-a-time thread 344 static bool sSystemSleep = false; // true when system going to sleep 345 static AbsoluteTime sLastWakeTime; // last time we woke up 346 347 /********************************************************************* 348 * Backtraces can be printed at various times so we need a tight lock 349 * on data used for that. sKextSummariesLock protects the variables 350 * declared immediately below. 351 * 352 * gLoadedKextSummaries is accessed by other modules, but only during 353 * a panic so the lock isn't needed then. 354 * 355 * gLoadedKextSummaries has the "used" attribute in order to ensure 356 * that it remains visible even when we are performing extremely 357 * aggressive optimizations, as it is needed to allow the debugger 358 * to automatically parse the list of loaded kexts. 359 **********/ 360 static IOLock * sKextSummariesLock = NULL; 361 extern "C" lck_spin_t vm_allocation_sites_lock; 362 static IOSimpleLock * sKextAccountsLock = &vm_allocation_sites_lock; 363 364 void (*sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated; 365 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL; 366 static size_t sLoadedKextSummariesAllocSize = 0; 367 368 static OSKextActiveAccount * sKextAccounts; 369 static uint32_t sKextAccountsCount; 370 }; 371 372 /********************************************************************* 373 * sKextLoggingLock protects the logging variables declared immediately below. 374 **********/ 375 static IOLock * sKextLoggingLock = NULL; 376 377 static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel | 378 kOSKextLogVerboseFlagsMask; 379 static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter; 380 static bool sBootArgLogFilterFound = false; 381 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter, 382 sKernelLogFilter, "kernel kext logging"); 383 384 static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter; 385 static OSArray * sUserSpaceLogSpecArray = NULL; 386 static OSArray * sUserSpaceLogMessageArray = NULL; 387 388 /********* 389 * End scope for sKextInnerLock-protected variables. 390 *********************************************************************/ 391 392 393 /********************************************************************* 394 helper function used for collecting PGO data upon unload of a kext 395 */ 396 397 static int OSKextGrabPgoDataLocked(OSKext *kext, 398 bool metadata, 399 uuid_t instance_uuid, 400 uint64_t *pSize, 401 char *pBuffer, 402 uint64_t bufferSize); 403 404 /**********************************************************************/ 405 406 407 408 #if PRAGMA_MARK 409 #pragma mark OSData callbacks (need to move to OSData) 410 #endif 411 /********************************************************************* 412 * C functions used for callbacks. 413 *********************************************************************/ 414 extern "C" { 415 void osdata_kmem_free(void * ptr, unsigned int length) { 416 kmem_free(kernel_map, (vm_address_t)ptr, length); 417 return; 418 } 419 420 void osdata_phys_free(void * ptr, unsigned int length) { 421 ml_static_mfree((vm_offset_t)ptr, length); 422 return; 423 } 424 425 void osdata_vm_deallocate(void * ptr, unsigned int length) 426 { 427 (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length); 428 return; 429 } 430 431 void osdata_kext_free(void * ptr, unsigned int length) 432 { 433 (void)kext_free((vm_offset_t)ptr, length); 434 } 435 436 }; 437 438 #if PRAGMA_MARK 439 #pragma mark KXLD Allocation Callback 440 #endif 441 /********************************************************************* 442 * KXLD Allocation Callback 443 *********************************************************************/ 444 kxld_addr_t 445 kern_allocate( 446 u_long size, 447 KXLDAllocateFlags * flags, 448 void * user_data) 449 { 450 vm_address_t result = 0; // returned 451 kern_return_t mach_result = KERN_FAILURE; 452 bool success = false; 453 OSKext * theKext = (OSKext *)user_data; 454 u_long roundSize = round_page(size); 455 OSData * linkBuffer = NULL; // must release 456 457 mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE); 458 if (mach_result != KERN_SUCCESS) { 459 OSKextLog(theKext, 460 kOSKextLogErrorLevel | 461 kOSKextLogGeneralFlag, 462 "Can't allocate kernel memory to link %s.", 463 theKext->getIdentifierCString()); 464 goto finish; 465 } 466 467 /* Create an OSData wrapper for the allocated buffer. 468 */ 469 linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize); 470 if (!linkBuffer) { 471 OSKextLog(theKext, 472 kOSKextLogErrorLevel | 473 kOSKextLogGeneralFlag, 474 "Can't allocate linked executable wrapper for %s.", 475 theKext->getIdentifierCString()); 476 goto finish; 477 } 478 linkBuffer->setDeallocFunction(osdata_kext_free); 479 OSKextLog(theKext, 480 kOSKextLogProgressLevel | 481 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 482 "Allocated link buffer for kext %s at %p (%lu bytes).", 483 theKext->getIdentifierCString(), 484 (void *)result, (unsigned long)roundSize); 485 486 theKext->setLinkedExecutable(linkBuffer); 487 488 *flags = kKxldAllocateWritable; 489 success = true; 490 491 finish: 492 if (!success && result) { 493 kext_free(result, roundSize); 494 result = 0; 495 } 496 497 OSSafeRelease(linkBuffer); 498 499 return (kxld_addr_t)result; 500 } 501 502 /********************************************************************* 503 *********************************************************************/ 504 void 505 kxld_log_callback( 506 KXLDLogSubsystem subsystem, 507 KXLDLogLevel level, 508 const char * format, 509 va_list argList, 510 void * user_data) 511 { 512 OSKext *theKext = (OSKext *) user_data; 513 OSKextLogSpec logSpec = 0; 514 515 switch (subsystem) { 516 case kKxldLogLinking: 517 logSpec |= kOSKextLogLinkFlag; 518 break; 519 case kKxldLogPatching: 520 logSpec |= kOSKextLogPatchFlag; 521 break; 522 } 523 524 switch (level) { 525 case kKxldLogExplicit: 526 logSpec |= kOSKextLogExplicitLevel; 527 break; 528 case kKxldLogErr: 529 logSpec |= kOSKextLogErrorLevel; 530 break; 531 case kKxldLogWarn: 532 logSpec |= kOSKextLogWarningLevel; 533 break; 534 case kKxldLogBasic: 535 logSpec |= kOSKextLogProgressLevel; 536 break; 537 case kKxldLogDetail: 538 logSpec |= kOSKextLogDetailLevel; 539 break; 540 case kKxldLogDebug: 541 logSpec |= kOSKextLogDebugLevel; 542 break; 543 } 544 545 OSKextVLog(theKext, logSpec, format, argList); 546 } 547 548 #if PRAGMA_MARK 549 #pragma mark IOStatistics defines 550 #endif 551 552 #if IOKITSTATS 553 554 #define notifyKextLoadObservers(kext, kmod_info) \ 555 do { \ 556 IOStatistics::onKextLoad(kext, kmod_info); \ 557 } while (0) 558 559 #define notifyKextUnloadObservers(kext) \ 560 do { \ 561 IOStatistics::onKextUnload(kext); \ 562 } while (0) 563 564 #define notifyAddClassObservers(kext, addedClass, flags) \ 565 do { \ 566 IOStatistics::onClassAdded(kext, addedClass); \ 567 } while (0) 568 569 #define notifyRemoveClassObservers(kext, removedClass, flags) \ 570 do { \ 571 IOStatistics::onClassRemoved(kext, removedClass); \ 572 } while (0) 573 574 #else 575 576 #define notifyKextLoadObservers(kext, kmod_info) 577 #define notifyKextUnloadObservers(kext) 578 #define notifyAddClassObservers(kext, addedClass, flags) 579 #define notifyRemoveClassObservers(kext, removedClass, flags) 580 581 #endif /* IOKITSTATS */ 582 583 #if PRAGMA_MARK 584 #pragma mark Module Config (Startup & Shutdown) 585 #endif 586 /********************************************************************* 587 * Module Config (Class Definition & Class Methods) 588 *********************************************************************/ 589 #define super OSObject 590 OSDefineMetaClassAndStructors(OSKext, OSObject) 591 592 /********************************************************************* 593 *********************************************************************/ 594 /* static */ 595 void 596 OSKext::initialize(void) 597 { 598 OSData * kernelExecutable = NULL; // do not release 599 u_char * kernelStart = NULL; // do not free 600 size_t kernelLength = 0; 601 OSString * scratchString = NULL; // must release 602 IORegistryEntry * registryRoot = NULL; // do not release 603 OSNumber * kernelCPUType = NULL; // must release 604 OSNumber * kernelCPUSubtype = NULL; // must release 605 OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter; 606 bool setResult = false; 607 uint64_t * timestamp = 0; 608 char bootArgBuffer[16]; // for PE_parse_boot_argn w/strings 609 610 /* This must be the first thing allocated. Everything else grabs this lock. 611 */ 612 sKextLock = IORecursiveLockAlloc(); 613 sKextInnerLock = IORecursiveLockAlloc(); 614 sKextSummariesLock = IOLockAlloc(); 615 sKextLoggingLock = IOLockAlloc(); 616 assert(sKextLock); 617 assert(sKextInnerLock); 618 assert(sKextSummariesLock); 619 assert(sKextLoggingLock); 620 621 sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount); 622 sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 623 sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10); 624 sKernelRequests = OSArray::withCapacity(0); 625 sPostedKextLoadIdentifiers = OSSet::withCapacity(0); 626 sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount); 627 sRequestCallbackRecords = OSArray::withCapacity(0); 628 assert(sKextsByID && sLoadedKexts && sKernelRequests && 629 sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers && 630 sRequestCallbackRecords && sUnloadedPrelinkedKexts); 631 632 /* Read the log flag boot-args and set the log flags. 633 */ 634 if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) { 635 sBootArgLogFilterFound = true; 636 sKernelLogFilter = bootLogFilter; 637 // log this if any flags are set 638 OSKextLog(/* kext */ NULL, 639 kOSKextLogBasicLevel | 640 kOSKextLogFlagsMask, 641 "Kernel kext log filter 0x%x per kextlog boot arg.", 642 (unsigned)sKernelLogFilter); 643 } 644 645 sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer, 646 sizeof(bootArgBuffer)) ? true : false; 647 648 if (sSafeBoot) { 649 OSKextLog(/* kext */ NULL, 650 kOSKextLogWarningLevel | 651 kOSKextLogGeneralFlag, 652 "SAFE BOOT DETECTED - " 653 "only valid OSBundleRequired kexts will be loaded."); 654 } 655 656 PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols)); 657 658 /* Set up an OSKext instance to represent the kernel itself. 659 */ 660 sKernelKext = new OSKext; 661 assert(sKernelKext); 662 663 kernelStart = (u_char *)&_mh_execute_header; 664 kernelLength = getlastaddr() - (vm_offset_t)kernelStart; 665 kernelExecutable = OSData::withBytesNoCopy( 666 kernelStart, kernelLength); 667 assert(kernelExecutable); 668 669 #if KASLR_KEXT_DEBUG 670 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu \n", 671 (unsigned long)kernelStart, 672 (unsigned long)getlastaddr(), 673 kernelLength); 674 #endif 675 676 sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0 677 sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier); 678 679 sKernelKext->version = OSKextParseVersionString(osrelease); 680 sKernelKext->compatibleVersion = sKernelKext->version; 681 sKernelKext->linkedExecutable = kernelExecutable; 682 683 sKernelKext->flags.hasAllDependencies = 1; 684 sKernelKext->flags.kernelComponent = 1; 685 sKernelKext->flags.prelinked = 0; 686 sKernelKext->flags.loaded = 1; 687 sKernelKext->flags.started = 1; 688 sKernelKext->flags.CPPInitialized = 0; 689 sKernelKext->flags.jettisonLinkeditSeg = 0; 690 691 sKernelKext->kmod_info = &g_kernel_kmod_info; 692 strlcpy(g_kernel_kmod_info.version, osrelease, 693 sizeof(g_kernel_kmod_info.version)); 694 g_kernel_kmod_info.size = kernelLength; 695 g_kernel_kmod_info.id = sKernelKext->loadTag; 696 697 /* Cons up an info dict, so we don't have to have special-case 698 * checking all over. 699 */ 700 sKernelKext->infoDict = OSDictionary::withCapacity(5); 701 assert(sKernelKext->infoDict); 702 setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey, 703 sKernelKext->bundleID); 704 assert(setResult); 705 setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey, 706 kOSBooleanTrue); 707 assert(setResult); 708 709 scratchString = OSString::withCStringNoCopy(osrelease); 710 assert(scratchString); 711 setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey, 712 scratchString); 713 assert(setResult); 714 OSSafeReleaseNULL(scratchString); 715 716 scratchString = OSString::withCStringNoCopy("mach_kernel"); 717 assert(scratchString); 718 setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey, 719 scratchString); 720 assert(setResult); 721 OSSafeReleaseNULL(scratchString); 722 723 /* Add the kernel kext to the bookkeeping dictionaries. Note that 724 * the kernel kext doesn't have a kmod_info struct. copyInfo() 725 * gathers info from other places anyhow. 726 */ 727 setResult = sKextsByID->setObject(sKernelKext->bundleID, sKernelKext); 728 assert(setResult); 729 setResult = sLoadedKexts->setObject(sKernelKext); 730 assert(setResult); 731 sKernelKext->release(); 732 733 registryRoot = IORegistryEntry::getRegistryRoot(); 734 kernelCPUType = OSNumber::withNumber( 735 (long long unsigned int)_mh_execute_header.cputype, 736 8 * sizeof(_mh_execute_header.cputype)); 737 kernelCPUSubtype = OSNumber::withNumber( 738 (long long unsigned int)_mh_execute_header.cpusubtype, 739 8 * sizeof(_mh_execute_header.cpusubtype)); 740 assert(registryRoot && kernelCPUSubtype && kernelCPUType); 741 742 registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType); 743 registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype); 744 745 OSSafeRelease(kernelCPUType); 746 OSSafeRelease(kernelCPUSubtype); 747 748 timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp); 749 *timestamp = 0; 750 timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp); 751 *timestamp = 0; 752 timestamp = __OSAbsoluteTimePtr(&sLastWakeTime); 753 *timestamp = 0; 754 755 OSKextLog(/* kext */ NULL, 756 kOSKextLogProgressLevel | 757 kOSKextLogGeneralFlag, 758 "Kext system initialized."); 759 760 notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info); 761 762 return; 763 } 764 765 /********************************************************************* 766 * This could be in OSKextLib.cpp but we need to hold a lock 767 * while removing all the segments and sKextLock will do. 768 *********************************************************************/ 769 /* static */ 770 OSReturn 771 OSKext::removeKextBootstrap(void) 772 { 773 OSReturn result = kOSReturnError; 774 775 static bool alreadyDone = false; 776 777 const char * dt_kernel_header_name = "Kernel-__HEADER"; 778 const char * dt_kernel_symtab_name = "Kernel-__SYMTAB"; 779 kernel_mach_header_t * dt_mach_header = NULL; 780 int dt_mach_header_size = 0; 781 struct symtab_command * dt_symtab = NULL; 782 int dt_symtab_size = 0; 783 int dt_result = 0; 784 785 kernel_segment_command_t * seg_to_remove = NULL; 786 787 788 /* This must be the very first thing done by this function. 789 */ 790 IORecursiveLockLock(sKextLock); 791 792 /* If we already did this, it's a success. 793 */ 794 if (alreadyDone) { 795 result = kOSReturnSuccess; 796 goto finish; 797 } 798 799 OSKextLog(/* kext */ NULL, 800 kOSKextLogProgressLevel | 801 kOSKextLogGeneralFlag, 802 "Jettisoning kext bootstrap segments."); 803 804 /***** 805 * Dispose of unnecessary stuff that the booter didn't need to load. 806 */ 807 dt_result = IODTGetLoaderInfo(dt_kernel_header_name, 808 (void **)&dt_mach_header, &dt_mach_header_size); 809 if (dt_result == 0 && dt_mach_header) { 810 IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header, 811 round_page_32(dt_mach_header_size)); 812 } 813 dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name, 814 (void **)&dt_symtab, &dt_symtab_size); 815 if (dt_result == 0 && dt_symtab) { 816 IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab, 817 round_page_32(dt_symtab_size)); 818 } 819 820 /***** 821 * KLD bootstrap segment. 822 */ 823 // xxx - should rename KLD segment 824 seg_to_remove = getsegbyname("__KLD"); 825 if (seg_to_remove) { 826 OSRuntimeUnloadCPPForSegment(seg_to_remove); 827 } 828 829 #if __i386__ || __x86_64__ 830 /* On x86, use the mapping data from the segment load command to 831 * unload KLD directly. 832 * This may invalidate any assumptions about "avail_start" 833 * defining the lower bound for valid physical addresses. 834 */ 835 if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) { 836 // 04/18/11 - gab: <rdar://problem/9236163> 837 // overwrite memory occupied by KLD segment with random data before 838 // releasing it. 839 read_frandom((void *) seg_to_remove->vmaddr, seg_to_remove->vmsize); 840 ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize); 841 } 842 #else 843 #error arch 844 #endif 845 846 seg_to_remove = NULL; 847 848 /***** 849 * Prelinked kernel's symtab (if there is one). 850 */ 851 kernel_section_t * sect; 852 sect = getsectbyname("__PRELINK", "__symtab"); 853 if (sect && sect->addr && sect->size) { 854 ml_static_mfree(sect->addr, sect->size); 855 } 856 857 seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT"); 858 859 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it 860 * pageable, unless keepsyms is set. To do that, we have to copy it from 861 * its booter-allocated memory, free the booter memory, reallocate proper 862 * managed memory, then copy the segment back in. 863 */ 864 #if CONFIG_KXLD 865 if (!sKeepSymbols) { 866 kern_return_t mem_result; 867 void *seg_copy = NULL; 868 void *seg_data = NULL; 869 vm_map_offset_t seg_offset = 0; 870 vm_map_offset_t seg_copy_offset = 0; 871 vm_map_size_t seg_length = 0; 872 873 seg_data = (void *) seg_to_remove->vmaddr; 874 seg_offset = (vm_map_offset_t) seg_to_remove->vmaddr; 875 seg_length = (vm_map_size_t) seg_to_remove->vmsize; 876 877 /* Allocate space for the LINKEDIT copy. 878 */ 879 mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy, 880 seg_length, VM_KERN_MEMORY_KEXT); 881 if (mem_result != KERN_SUCCESS) { 882 OSKextLog(/* kext */ NULL, 883 kOSKextLogErrorLevel | 884 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 885 "Can't copy __LINKEDIT segment for VM reassign."); 886 goto finish; 887 } 888 seg_copy_offset = (vm_map_offset_t) seg_copy; 889 890 /* Copy it out. 891 */ 892 memcpy(seg_copy, seg_data, seg_length); 893 894 /* Dump the booter memory. 895 */ 896 ml_static_mfree(seg_offset, seg_length); 897 898 /* Set up the VM region. 899 */ 900 mem_result = vm_map_enter_mem_object( 901 kernel_map, 902 &seg_offset, 903 seg_length, /* mask */ 0, 904 VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, 905 (ipc_port_t)NULL, 906 (vm_object_offset_t) 0, 907 /* copy */ FALSE, 908 /* cur_protection */ VM_PROT_READ | VM_PROT_WRITE, 909 /* max_protection */ VM_PROT_ALL, 910 /* inheritance */ VM_INHERIT_DEFAULT); 911 if ((mem_result != KERN_SUCCESS) || 912 (seg_offset != (vm_map_offset_t) seg_data)) 913 { 914 OSKextLog(/* kext */ NULL, 915 kOSKextLogErrorLevel | 916 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 917 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).", 918 seg_data, seg_length, mem_result); 919 goto finish; 920 } 921 922 /* And copy it back. 923 */ 924 memcpy(seg_data, seg_copy, seg_length); 925 926 /* Free the copy. 927 */ 928 kmem_free(kernel_map, seg_copy_offset, seg_length); 929 } 930 #else /* we are not CONFIG_KXLD */ 931 #error CONFIG_KXLD is expected for this arch 932 933 /***** 934 * Dump the LINKEDIT segment, unless keepsyms is set. 935 */ 936 if (!sKeepSymbols) { 937 const char *dt_segment_name = "Kernel-__LINKEDIT"; 938 if (0 == IODTGetLoaderInfo(dt_segment_name, 939 &segment_paddress, &segment_size)) { 940 #ifdef SECURE_KERNEL 941 vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress); 942 bzero((void*)vmaddr, segment_size); 943 #endif 944 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 945 (int)segment_size); 946 } 947 } else { 948 OSKextLog(/* kext */ NULL, 949 kOSKextLogBasicLevel | 950 kOSKextLogGeneralFlag, 951 "keepsyms boot arg specified; keeping linkedit segment for symbols."); 952 } 953 #endif /* CONFIG_KXLD */ 954 955 seg_to_remove = NULL; 956 957 alreadyDone = true; 958 result = kOSReturnSuccess; 959 960 finish: 961 962 /* This must be the very last thing done before returning. 963 */ 964 IORecursiveLockUnlock(sKextLock); 965 966 return result; 967 } 968 969 /********************************************************************* 970 *********************************************************************/ 971 void 972 OSKext::flushNonloadedKexts( 973 Boolean flushPrelinkedKexts) 974 { 975 OSSet * prelinkedKexts = NULL; // must release 976 OSCollectionIterator * kextIterator = NULL; // must release 977 OSCollectionIterator * prelinkIterator = NULL; // must release 978 const OSSymbol * thisID = NULL; // do not release 979 OSKext * thisKext = NULL; // do not release 980 uint32_t count, i; 981 982 IORecursiveLockLock(sKextLock); 983 984 OSKextLog(/* kext */ NULL, 985 kOSKextLogProgressLevel | 986 kOSKextLogKextBookkeepingFlag, 987 "Flushing nonloaded kexts and other unused data."); 988 989 OSKext::considerDestroyingLinkContext(); 990 991 /* If we aren't flushing unused prelinked kexts, we have to put them 992 * aside while we flush everything else so make a container for them. 993 */ 994 if (!flushPrelinkedKexts) { 995 prelinkedKexts = OSSet::withCapacity(0); 996 if (!prelinkedKexts) { 997 goto finish; 998 } 999 } 1000 1001 /* Set aside prelinked kexts (in-use or not) and break 1002 * any lingering inter-kext references for nonloaded kexts 1003 * so they have min. retain counts. 1004 */ 1005 kextIterator = OSCollectionIterator::withCollection(sKextsByID); 1006 if (!kextIterator) { 1007 goto finish; 1008 } 1009 1010 while ((thisID = OSDynamicCast(OSSymbol, 1011 kextIterator->getNextObject()))) { 1012 1013 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 1014 1015 if (thisKext) { 1016 if (prelinkedKexts && thisKext->isPrelinked()) { 1017 prelinkedKexts->setObject(thisKext); 1018 } 1019 thisKext->flushDependencies(/* forceIfLoaded */ false); 1020 } 1021 } 1022 1023 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly. 1024 */ 1025 sKextsByID->flushCollection(); 1026 1027 /* Now put the loaded kexts back into the ID dictionary. 1028 */ 1029 count = sLoadedKexts->getCount(); 1030 for (i = 0; i < count; i++) { 1031 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 1032 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1033 } 1034 1035 /* Finally, put back the prelinked kexts if we saved any. 1036 */ 1037 if (prelinkedKexts) { 1038 prelinkIterator = OSCollectionIterator::withCollection(prelinkedKexts); 1039 if (!prelinkIterator) { 1040 goto finish; 1041 } 1042 1043 while ((thisKext = OSDynamicCast(OSKext, 1044 prelinkIterator->getNextObject()))) { 1045 1046 sKextsByID->setObject(thisKext->getIdentifierCString(), 1047 thisKext); 1048 } 1049 } 1050 1051 finish: 1052 IORecursiveLockUnlock(sKextLock); 1053 1054 OSSafeRelease(prelinkedKexts); 1055 OSSafeRelease(kextIterator); 1056 OSSafeRelease(prelinkIterator); 1057 1058 return; 1059 } 1060 1061 /********************************************************************* 1062 *********************************************************************/ 1063 /* static */ 1064 void 1065 OSKext::setKextdActive(Boolean active) 1066 { 1067 IORecursiveLockLock(sKextLock); 1068 sKextdActive = active; 1069 if (sKernelRequests->getCount()) { 1070 OSKext::pingKextd(); 1071 } 1072 IORecursiveLockUnlock(sKextLock); 1073 1074 return; 1075 } 1076 1077 /********************************************************************* 1078 * OSKextLib.cpp might need access to this someday but for now it's 1079 * private. 1080 *********************************************************************/ 1081 extern "C" { 1082 extern void ipc_port_release_send(ipc_port_t); 1083 }; 1084 1085 /* static */ 1086 OSReturn 1087 OSKext::pingKextd(void) 1088 { 1089 OSReturn result = kOSReturnError; 1090 #if !NO_KEXTD 1091 mach_port_t kextd_port = IPC_PORT_NULL; 1092 1093 if (!sKextdActive) { 1094 result = kOSKextReturnDisabled; // basically unavailable 1095 goto finish; 1096 } 1097 1098 result = host_get_kextd_port(host_priv_self(), &kextd_port); 1099 if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) { 1100 OSKextLog(/* kext */ NULL, 1101 kOSKextLogErrorLevel | 1102 kOSKextLogIPCFlag, 1103 "Can't get kextd port."); 1104 goto finish; 1105 } 1106 1107 result = kextd_ping(kextd_port); 1108 if (result != KERN_SUCCESS) { 1109 OSKextLog(/* kext */ NULL, 1110 kOSKextLogErrorLevel | 1111 kOSKextLogIPCFlag, 1112 "kextd ping failed (0x%x).", (int)result); 1113 goto finish; 1114 } 1115 1116 finish: 1117 if (IPC_PORT_VALID(kextd_port)) { 1118 ipc_port_release_send(kextd_port); 1119 } 1120 #endif 1121 1122 return result; 1123 } 1124 1125 /********************************************************************* 1126 *********************************************************************/ 1127 /* static */ 1128 void 1129 OSKext::setDeferredLoadSucceeded(Boolean succeeded) 1130 { 1131 IORecursiveLockLock(sKextLock); 1132 sDeferredLoadSucceeded = succeeded; 1133 IORecursiveLockUnlock(sKextLock); 1134 1135 return; 1136 } 1137 1138 /********************************************************************* 1139 * Called from IOSystemShutdownNotification. 1140 *********************************************************************/ 1141 /* static */ 1142 void 1143 OSKext::willShutdown(void) 1144 { 1145 #if !NO_KEXTD 1146 OSReturn checkResult = kOSReturnError; 1147 #endif 1148 OSDictionary * exitRequest = NULL; // must release 1149 1150 IORecursiveLockLock(sKextLock); 1151 1152 OSKext::setLoadEnabled(false); 1153 OSKext::setUnloadEnabled(false); 1154 OSKext::setAutounloadsEnabled(false); 1155 OSKext::setKernelRequestsEnabled(false); 1156 1157 #if !NO_KEXTD 1158 OSKextLog(/* kext */ NULL, 1159 kOSKextLogProgressLevel | 1160 kOSKextLogGeneralFlag, 1161 "System shutdown; requesting immediate kextd exit."); 1162 1163 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit, 1164 &exitRequest); 1165 if (checkResult != kOSReturnSuccess) { 1166 goto finish; 1167 } 1168 if (!sKernelRequests->setObject(exitRequest)) { 1169 goto finish; 1170 } 1171 1172 OSKext::pingKextd(); 1173 1174 finish: 1175 #endif 1176 1177 IORecursiveLockUnlock(sKextLock); 1178 1179 OSSafeRelease(exitRequest); 1180 return; 1181 } 1182 1183 /********************************************************************* 1184 *********************************************************************/ 1185 /* static */ 1186 bool 1187 OSKext::getLoadEnabled(void) 1188 { 1189 bool result; 1190 1191 IORecursiveLockLock(sKextLock); 1192 result = sLoadEnabled; 1193 IORecursiveLockUnlock(sKextLock); 1194 return result; 1195 } 1196 1197 /********************************************************************* 1198 *********************************************************************/ 1199 /* static */ 1200 bool 1201 OSKext::setLoadEnabled(bool flag) 1202 { 1203 bool result; 1204 1205 IORecursiveLockLock(sKextLock); 1206 result = sLoadEnabled; 1207 sLoadEnabled = (flag ? true : false); 1208 1209 if (sLoadEnabled != result) { 1210 OSKextLog(/* kext */ NULL, 1211 kOSKextLogBasicLevel | 1212 kOSKextLogLoadFlag, 1213 "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis"); 1214 } 1215 1216 IORecursiveLockUnlock(sKextLock); 1217 1218 return result; 1219 } 1220 1221 /********************************************************************* 1222 *********************************************************************/ 1223 /* static */ 1224 bool 1225 OSKext::getUnloadEnabled(void) 1226 { 1227 bool result; 1228 1229 IORecursiveLockLock(sKextLock); 1230 result = sUnloadEnabled; 1231 IORecursiveLockUnlock(sKextLock); 1232 return result; 1233 } 1234 1235 /********************************************************************* 1236 *********************************************************************/ 1237 /* static */ 1238 bool 1239 OSKext::setUnloadEnabled(bool flag) 1240 { 1241 bool result; 1242 1243 IORecursiveLockLock(sKextLock); 1244 result = sUnloadEnabled; 1245 sUnloadEnabled = (flag ? true : false); 1246 IORecursiveLockUnlock(sKextLock); 1247 1248 if (sUnloadEnabled != result) { 1249 OSKextLog(/* kext */ NULL, 1250 kOSKextLogBasicLevel | 1251 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1252 "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis"); 1253 } 1254 1255 return result; 1256 } 1257 1258 /********************************************************************* 1259 * Do not call any function that takes sKextLock here! 1260 *********************************************************************/ 1261 /* static */ 1262 bool 1263 OSKext::getAutounloadEnabled(void) 1264 { 1265 bool result; 1266 1267 IORecursiveLockLock(sKextInnerLock); 1268 result = sAutounloadEnabled ? true : false; 1269 IORecursiveLockUnlock(sKextInnerLock); 1270 return result; 1271 } 1272 1273 /********************************************************************* 1274 * Do not call any function that takes sKextLock here! 1275 *********************************************************************/ 1276 /* static */ 1277 bool 1278 OSKext::setAutounloadsEnabled(bool flag) 1279 { 1280 bool result; 1281 1282 IORecursiveLockLock(sKextInnerLock); 1283 1284 result = sAutounloadEnabled; 1285 sAutounloadEnabled = (flag ? true : false); 1286 if (!sAutounloadEnabled && sUnloadCallout) { 1287 thread_call_cancel(sUnloadCallout); 1288 } 1289 1290 if (sAutounloadEnabled != result) { 1291 OSKextLog(/* kext */ NULL, 1292 kOSKextLogBasicLevel | 1293 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1294 "Kext autounloading now %sabled.", 1295 sAutounloadEnabled ? "en" : "dis"); 1296 } 1297 1298 IORecursiveLockUnlock(sKextInnerLock); 1299 1300 return result; 1301 } 1302 1303 /********************************************************************* 1304 *********************************************************************/ 1305 /* instance method operating on OSKext field */ 1306 bool 1307 OSKext::setAutounloadEnabled(bool flag) 1308 { 1309 bool result = flags.autounloadEnabled ? true : false; 1310 flags.autounloadEnabled = flag ? 1 : 0; 1311 1312 if (result != (flag ? true : false)) { 1313 OSKextLog(this, 1314 kOSKextLogProgressLevel | 1315 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 1316 "Autounloading for kext %s now %sabled.", 1317 getIdentifierCString(), 1318 flags.autounloadEnabled ? "en" : "dis"); 1319 } 1320 return result; 1321 } 1322 1323 /********************************************************************* 1324 *********************************************************************/ 1325 /* static */ 1326 bool 1327 OSKext::setKernelRequestsEnabled(bool flag) 1328 { 1329 bool result; 1330 1331 IORecursiveLockLock(sKextLock); 1332 result = sKernelRequestsEnabled; 1333 sKernelRequestsEnabled = flag ? true : false; 1334 1335 if (sKernelRequestsEnabled != result) { 1336 OSKextLog(/* kext */ NULL, 1337 kOSKextLogBasicLevel | 1338 kOSKextLogGeneralFlag, 1339 "Kernel requests now %sabled.", 1340 sKernelRequestsEnabled ? "en" : "dis"); 1341 } 1342 IORecursiveLockUnlock(sKextLock); 1343 return result; 1344 } 1345 1346 /********************************************************************* 1347 *********************************************************************/ 1348 /* static */ 1349 bool 1350 OSKext::getKernelRequestsEnabled(void) 1351 { 1352 bool result; 1353 1354 IORecursiveLockLock(sKextLock); 1355 result = sKernelRequestsEnabled; 1356 IORecursiveLockUnlock(sKextLock); 1357 return result; 1358 } 1359 1360 #if PRAGMA_MARK 1361 #pragma mark Kext Life Cycle 1362 #endif 1363 /********************************************************************* 1364 *********************************************************************/ 1365 OSKext * 1366 OSKext::withPrelinkedInfoDict( 1367 OSDictionary * anInfoDict) 1368 { 1369 OSKext * newKext = new OSKext; 1370 1371 if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict)) { 1372 newKext->release(); 1373 return NULL; 1374 } 1375 1376 return newKext; 1377 } 1378 1379 /********************************************************************* 1380 *********************************************************************/ 1381 bool 1382 OSKext::initWithPrelinkedInfoDict( 1383 OSDictionary * anInfoDict) 1384 { 1385 bool result = false; 1386 OSString * kextPath = NULL; // do not release 1387 OSNumber * addressNum = NULL; // reused; do not release 1388 OSNumber * lengthNum = NULL; // reused; do not release 1389 void * data = NULL; // do not free 1390 void * srcData = NULL; // do not free 1391 OSData * prelinkedExecutable = NULL; // must release 1392 uint32_t length = 0; // reused 1393 1394 if (!super::init()) { 1395 goto finish; 1396 } 1397 1398 /* Get the path. Don't look for an arch-specific path property. 1399 */ 1400 kextPath = OSDynamicCast(OSString, 1401 anInfoDict->getObject(kPrelinkBundlePathKey)); 1402 1403 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 1404 goto finish; 1405 } 1406 #if KASLR_KEXT_DEBUG 1407 IOLog("kaslr: kext %s \n", getIdentifierCString()); 1408 #endif 1409 1410 /* Also get the executable's bundle-relative path if present. 1411 * Don't look for an arch-specific path property. 1412 */ 1413 executableRelPath = OSDynamicCast(OSString, 1414 anInfoDict->getObject(kPrelinkExecutableRelativePathKey)); 1415 if (executableRelPath) { 1416 executableRelPath->retain(); 1417 } 1418 1419 /* Don't need the paths to be in the info dictionary any more. 1420 */ 1421 anInfoDict->removeObject(kPrelinkBundlePathKey); 1422 anInfoDict->removeObject(kPrelinkExecutableRelativePathKey); 1423 1424 /* Create an OSData wrapper around the linked executable. 1425 */ 1426 addressNum = OSDynamicCast(OSNumber, 1427 anInfoDict->getObject(kPrelinkExecutableLoadKey)); 1428 if (addressNum) { 1429 lengthNum = OSDynamicCast(OSNumber, 1430 anInfoDict->getObject(kPrelinkExecutableSizeKey)); 1431 if (!lengthNum) { 1432 OSKextLog(this, 1433 kOSKextLogErrorLevel | 1434 kOSKextLogArchiveFlag, 1435 "Kext %s can't find prelinked kext executable size.", 1436 getIdentifierCString()); 1437 goto finish; 1438 } 1439 1440 data = (void *) ((intptr_t) (addressNum->unsigned64BitValue()) + vm_kernel_slide); 1441 length = (uint32_t) (lengthNum->unsigned32BitValue()); 1442 1443 #if KASLR_KEXT_DEBUG 1444 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n", 1445 (unsigned long)VM_KERNEL_UNSLIDE(data), 1446 (unsigned long)data, 1447 length); 1448 #endif 1449 1450 anInfoDict->removeObject(kPrelinkExecutableLoadKey); 1451 anInfoDict->removeObject(kPrelinkExecutableSizeKey); 1452 1453 /* If the kext's load address differs from its source address, allocate 1454 * space in the kext map at the load address and copy the kext over. 1455 */ 1456 addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey)); 1457 if (addressNum) { 1458 srcData = (void *) ((intptr_t) (addressNum->unsigned64BitValue()) + vm_kernel_slide); 1459 1460 #if KASLR_KEXT_DEBUG 1461 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n", 1462 (unsigned long)VM_KERNEL_UNSLIDE(srcData), 1463 (unsigned long)srcData); 1464 #endif 1465 1466 if (data != srcData) { 1467 #if __LP64__ 1468 kern_return_t alloc_result; 1469 1470 alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE); 1471 if (alloc_result != KERN_SUCCESS) { 1472 OSKextLog(this, 1473 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 1474 "Failed to allocate space for prelinked kext %s.", 1475 getIdentifierCString()); 1476 goto finish; 1477 } 1478 memcpy(data, srcData, length); 1479 #else 1480 OSKextLog(this, 1481 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 1482 "Error: prelinked kext %s - source and load addresses " 1483 "differ on ILP32 architecture.", 1484 getIdentifierCString()); 1485 goto finish; 1486 #endif /* __LP64__ */ 1487 } 1488 1489 anInfoDict->removeObject(kPrelinkExecutableSourceKey); 1490 } 1491 1492 prelinkedExecutable = OSData::withBytesNoCopy(data, length); 1493 if (!prelinkedExecutable) { 1494 OSKextLog(this, 1495 kOSKextLogErrorLevel | 1496 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1497 "Kext %s failed to create executable wrapper.", 1498 getIdentifierCString()); 1499 goto finish; 1500 } 1501 1502 #if VM_MAPPED_KEXTS 1503 prelinkedExecutable->setDeallocFunction(osdata_kext_free); 1504 #else 1505 prelinkedExecutable->setDeallocFunction(osdata_phys_free); 1506 #endif 1507 setLinkedExecutable(prelinkedExecutable); 1508 addressNum = OSDynamicCast(OSNumber, 1509 anInfoDict->getObject(kPrelinkKmodInfoKey)); 1510 if (!addressNum) { 1511 OSKextLog(this, 1512 kOSKextLogErrorLevel | 1513 kOSKextLogArchiveFlag, 1514 "Kext %s can't find prelinked kext kmod_info address.", 1515 getIdentifierCString()); 1516 goto finish; 1517 } 1518 1519 if (addressNum->unsigned64BitValue() != 0) { 1520 kmod_info = (kmod_info_t *) (intptr_t) (addressNum->unsigned64BitValue() + vm_kernel_slide); 1521 kmod_info->address += vm_kernel_slide; 1522 #if KASLR_KEXT_DEBUG 1523 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n", 1524 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info), 1525 (unsigned long)kmod_info); 1526 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n", 1527 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info->address), 1528 (unsigned long)kmod_info->address); 1529 #endif 1530 } 1531 1532 anInfoDict->removeObject(kPrelinkKmodInfoKey); 1533 } 1534 1535 /* If the plist has a UUID for an interface, save that off. 1536 */ 1537 if (isInterface()) { 1538 interfaceUUID = OSDynamicCast(OSData, 1539 anInfoDict->getObject(kPrelinkInterfaceUUIDKey)); 1540 if (interfaceUUID) { 1541 interfaceUUID->retain(); 1542 anInfoDict->removeObject(kPrelinkInterfaceUUIDKey); 1543 } 1544 } 1545 1546 result = slidePrelinkedExecutable(); 1547 if (result != kOSReturnSuccess) { 1548 goto finish; 1549 } 1550 1551 /* set VM protections now, wire later at kext load */ 1552 result = setVMAttributes(true, false); 1553 if (result != KERN_SUCCESS) { 1554 goto finish; 1555 } 1556 1557 flags.prelinked = true; 1558 1559 /* If we created a kext from prelink info, 1560 * we must be booting from a prelinked kernel. 1561 */ 1562 sPrelinkBoot = true; 1563 1564 result = registerIdentifier(); 1565 1566 finish: 1567 OSSafeRelease(prelinkedExecutable); 1568 1569 return result; 1570 } 1571 /********************************************************************* 1572 *********************************************************************/ 1573 OSKext * 1574 OSKext::withBooterData( 1575 OSString * deviceTreeName, 1576 OSData * booterData) 1577 { 1578 OSKext * newKext = new OSKext; 1579 1580 if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) { 1581 newKext->release(); 1582 return NULL; 1583 } 1584 1585 return newKext; 1586 } 1587 1588 /********************************************************************* 1589 *********************************************************************/ 1590 typedef struct _BooterKextFileInfo { 1591 uint32_t infoDictPhysAddr; 1592 uint32_t infoDictLength; 1593 uint32_t executablePhysAddr; 1594 uint32_t executableLength; 1595 uint32_t bundlePathPhysAddr; 1596 uint32_t bundlePathLength; 1597 } _BooterKextFileInfo; 1598 1599 bool 1600 OSKext::initWithBooterData( 1601 OSString * deviceTreeName, 1602 OSData * booterData) 1603 { 1604 bool result = false; 1605 _BooterKextFileInfo * kextFileInfo = NULL; // do not free 1606 char * infoDictAddr = NULL; // do not free 1607 void * executableAddr = NULL; // do not free 1608 char * bundlePathAddr = NULL; // do not free 1609 1610 OSObject * parsedXML = NULL; // must release 1611 OSDictionary * theInfoDict = NULL; // do not release 1612 OSString * kextPath = NULL; // must release 1613 OSString * errorString = NULL; // must release 1614 OSData * executable = NULL; // must release 1615 1616 if (!super::init()) { 1617 goto finish; 1618 } 1619 1620 kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy(); 1621 if (!kextFileInfo) { 1622 OSKextLog(this, 1623 kOSKextLogErrorLevel | 1624 kOSKextLogGeneralFlag, 1625 "No booter-provided data for kext device tree entry %s.", 1626 deviceTreeName->getCStringNoCopy()); 1627 goto finish; 1628 } 1629 1630 /* The info plist must exist or we can't read the kext. 1631 */ 1632 if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) { 1633 OSKextLog(this, 1634 kOSKextLogErrorLevel | 1635 kOSKextLogGeneralFlag, 1636 "No kext info dictionary for booter device tree entry %s.", 1637 deviceTreeName->getCStringNoCopy()); 1638 goto finish; 1639 } 1640 1641 infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 1642 if (!infoDictAddr) { 1643 OSKextLog(this, 1644 kOSKextLogErrorLevel | 1645 kOSKextLogGeneralFlag, 1646 "Can't translate physical address 0x%x of kext info dictionary " 1647 "for device tree entry %s.", 1648 (int)kextFileInfo->infoDictPhysAddr, 1649 deviceTreeName->getCStringNoCopy()); 1650 goto finish; 1651 } 1652 1653 parsedXML = OSUnserializeXML(infoDictAddr, &errorString); 1654 if (parsedXML) { 1655 theInfoDict = OSDynamicCast(OSDictionary, parsedXML); 1656 } 1657 if (!theInfoDict) { 1658 const char * errorCString = "(unknown error)"; 1659 1660 if (errorString && errorString->getCStringNoCopy()) { 1661 errorCString = errorString->getCStringNoCopy(); 1662 } else if (parsedXML) { 1663 errorCString = "not a dictionary"; 1664 } 1665 OSKextLog(this, 1666 kOSKextLogErrorLevel | 1667 kOSKextLogGeneralFlag, 1668 "Error unserializing info dictionary for device tree entry %s: %s.", 1669 deviceTreeName->getCStringNoCopy(), errorCString); 1670 goto finish; 1671 } 1672 1673 /* A bundle path is not mandatory. 1674 */ 1675 if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) { 1676 bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr); 1677 if (!bundlePathAddr) { 1678 OSKextLog(this, 1679 kOSKextLogErrorLevel | 1680 kOSKextLogGeneralFlag, 1681 "Can't translate physical address 0x%x of kext bundle path " 1682 "for device tree entry %s.", 1683 (int)kextFileInfo->bundlePathPhysAddr, 1684 deviceTreeName->getCStringNoCopy()); 1685 goto finish; 1686 } 1687 bundlePathAddr[kextFileInfo->bundlePathLength-1] = '\0'; // just in case! 1688 1689 kextPath = OSString::withCString(bundlePathAddr); 1690 if (!kextPath) { 1691 OSKextLog(this, 1692 kOSKextLogErrorLevel | 1693 kOSKextLogGeneralFlag, 1694 "Failed to create wrapper for device tree entry %s kext path %s.", 1695 deviceTreeName->getCStringNoCopy(), bundlePathAddr); 1696 goto finish; 1697 } 1698 } 1699 1700 if (!setInfoDictionaryAndPath(theInfoDict, kextPath)) { 1701 goto finish; 1702 } 1703 1704 /* An executable is not mandatory. 1705 */ 1706 if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) { 1707 executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr); 1708 if (!executableAddr) { 1709 OSKextLog(this, 1710 kOSKextLogErrorLevel | 1711 kOSKextLogGeneralFlag, 1712 "Can't translate physical address 0x%x of kext executable " 1713 "for device tree entry %s.", 1714 (int)kextFileInfo->executablePhysAddr, 1715 deviceTreeName->getCStringNoCopy()); 1716 goto finish; 1717 } 1718 1719 executable = OSData::withBytesNoCopy(executableAddr, 1720 kextFileInfo->executableLength); 1721 if (!executable) { 1722 OSKextLog(this, 1723 kOSKextLogErrorLevel | 1724 kOSKextLogGeneralFlag, 1725 "Failed to create executable wrapper for device tree entry %s.", 1726 deviceTreeName->getCStringNoCopy()); 1727 goto finish; 1728 } 1729 1730 /* A kext with an executable needs to retain the whole booterData 1731 * object to keep the executable in memory. 1732 */ 1733 if (!setExecutable(executable, booterData)) { 1734 OSKextLog(this, 1735 kOSKextLogErrorLevel | 1736 kOSKextLogGeneralFlag, 1737 "Failed to set kext executable for device tree entry %s.", 1738 deviceTreeName->getCStringNoCopy()); 1739 goto finish; 1740 } 1741 } 1742 1743 result = registerIdentifier(); 1744 1745 finish: 1746 OSSafeRelease(parsedXML); 1747 OSSafeRelease(kextPath); 1748 OSSafeRelease(errorString); 1749 OSSafeRelease(executable); 1750 1751 return result; 1752 } 1753 1754 /********************************************************************* 1755 *********************************************************************/ 1756 bool 1757 OSKext::registerIdentifier(void) 1758 { 1759 bool result = false; 1760 OSKext * existingKext = NULL; // do not release 1761 bool existingIsLoaded = false; 1762 bool existingIsPrelinked = false; 1763 OSKextVersion newVersion = -1; 1764 OSKextVersion existingVersion = -1; 1765 char newVersionCString[kOSKextVersionMaxLength]; 1766 char existingVersionCString[kOSKextVersionMaxLength]; 1767 OSData * newUUID = NULL; // must release 1768 OSData * existingUUID = NULL; // must release 1769 1770 IORecursiveLockLock(sKextLock); 1771 1772 /* Get the new kext's version for checks & log messages. 1773 */ 1774 newVersion = getVersion(); 1775 OSKextVersionGetString(newVersion, newVersionCString, 1776 kOSKextVersionMaxLength); 1777 1778 /* If we don't have an existing kext with this identifier, 1779 * just record the new kext and we're done! 1780 */ 1781 existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)); 1782 if (!existingKext) { 1783 sKextsByID->setObject(bundleID, this); 1784 result = true; 1785 goto finish; 1786 } 1787 1788 /* Get the existing kext's version for checks & log messages. 1789 */ 1790 existingVersion = existingKext->getVersion(); 1791 OSKextVersionGetString(existingVersion, 1792 existingVersionCString, kOSKextVersionMaxLength); 1793 1794 existingIsLoaded = existingKext->isLoaded(); 1795 existingIsPrelinked = existingKext->isPrelinked(); 1796 1797 /* If we have a kext with this identifier that's already loaded/prelinked, 1798 * we can't use the new one, but let's be really thorough and check how 1799 * the two are related for a precise diagnostic log message. 1800 * 1801 * Note that user space can't find out about nonloaded prelinked kexts, 1802 * so in this case we log a message when new & existing are equivalent 1803 * at the step rather than warning level, because we are always going 1804 * be getting a copy of the kext in the user load request mkext. 1805 */ 1806 if (existingIsLoaded || existingIsPrelinked) { 1807 bool sameVersion = (newVersion == existingVersion); 1808 bool sameExecutable = true; // assume true unless we have UUIDs 1809 1810 /* Only get the UUID if the existing kext is loaded. Doing so 1811 * might have to uncompress an mkext executable and we shouldn't 1812 * take that hit when neither kext is loaded. 1813 */ 1814 newUUID = copyUUID(); 1815 existingUUID = existingKext->copyUUID(); 1816 1817 /* I'm entirely too paranoid about checking equivalence of executables, 1818 * but I remember nasty problems with it in the past. 1819 * 1820 * - If we have UUIDs for both kexts, compare them. 1821 * - If only one kext has a UUID, they're definitely different. 1822 */ 1823 if (newUUID && existingUUID) { 1824 sameExecutable = newUUID->isEqualTo(existingUUID); 1825 } else if (newUUID || existingUUID) { 1826 sameExecutable = false; 1827 } 1828 1829 if (!newUUID && !existingUUID) { 1830 1831 /* If there are no UUIDs, we can't really tell that the executables 1832 * are *different* without a lot of work; the loaded kext's 1833 * unrelocated executable is no longer around (and we never had it 1834 * in-kernel for a prelinked kext). We certainly don't want to do 1835 * a whole fake link for the new kext just to compare, either. 1836 */ 1837 1838 OSKextVersionGetString(version, newVersionCString, 1839 sizeof(newVersionCString)); 1840 OSKextLog(this, 1841 kOSKextLogWarningLevel | 1842 kOSKextLogKextBookkeepingFlag, 1843 "Notice - new kext %s, v%s matches %s kext " 1844 "but can't determine if executables are the same (no UUIDs).", 1845 getIdentifierCString(), 1846 newVersionCString, 1847 (existingIsLoaded ? "loaded" : "prelinked")); 1848 } 1849 1850 if (sameVersion && sameExecutable) { 1851 OSKextLog(this, 1852 (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) | 1853 kOSKextLogKextBookkeepingFlag, 1854 "Refusing new kext %s, v%s: a %s copy is already present " 1855 "(same version and executable).", 1856 getIdentifierCString(), newVersionCString, 1857 (existingIsLoaded ? "loaded" : "prelinked")); 1858 } else { 1859 if (!sameVersion) { 1860 /* This condition is significant so log it under warnings. 1861 */ 1862 OSKextLog(this, 1863 kOSKextLogWarningLevel | 1864 kOSKextLogKextBookkeepingFlag, 1865 "Refusing new kext %s, v%s: already have %s v%s.", 1866 getIdentifierCString(), 1867 newVersionCString, 1868 (existingIsLoaded ? "loaded" : "prelinked"), 1869 existingVersionCString); 1870 } else { 1871 /* This condition is significant so log it under warnings. 1872 */ 1873 OSKextLog(this, 1874 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 1875 "Refusing new kext %s, v%s: a %s copy with a different " 1876 "executable UUID is already present.", 1877 getIdentifierCString(), newVersionCString, 1878 (existingIsLoaded ? "loaded" : "prelinked")); 1879 } 1880 } 1881 goto finish; 1882 } /* if (existingIsLoaded || existingIsPrelinked) */ 1883 1884 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether 1885 * user loads are happening or if we're still in early boot. User agents are 1886 * supposed to resolve dependencies topside and include only the exact 1887 * kexts needed; so we always accept the new kext (in fact we should never 1888 * see an older unloaded copy hanging around). 1889 */ 1890 if (sUserLoadsActive) { 1891 sKextsByID->setObject(bundleID, this); 1892 result = true; 1893 1894 OSKextLog(this, 1895 kOSKextLogStepLevel | 1896 kOSKextLogKextBookkeepingFlag, 1897 "Dropping old copy of kext %s (v%s) for newly-added (v%s).", 1898 getIdentifierCString(), 1899 existingVersionCString, 1900 newVersionCString); 1901 1902 goto finish; 1903 } 1904 1905 /* During early boot, the kext with the highest version always wins out. 1906 * Prelinked kernels will never hit this, but mkexts and booter-read 1907 * kexts might have duplicates. 1908 */ 1909 if (newVersion > existingVersion) { 1910 sKextsByID->setObject(bundleID, this); 1911 result = true; 1912 1913 OSKextLog(this, 1914 kOSKextLogStepLevel | 1915 kOSKextLogKextBookkeepingFlag, 1916 "Dropping lower version (v%s) of registered kext %s for higher (v%s).", 1917 existingVersionCString, 1918 getIdentifierCString(), 1919 newVersionCString); 1920 1921 } else { 1922 OSKextLog(this, 1923 kOSKextLogStepLevel | 1924 kOSKextLogKextBookkeepingFlag, 1925 "Kext %s is already registered with a higher/same version (v%s); " 1926 "dropping newly-added (v%s).", 1927 getIdentifierCString(), 1928 existingVersionCString, 1929 newVersionCString); 1930 } 1931 1932 /* result has been set appropriately by now. */ 1933 1934 finish: 1935 1936 IORecursiveLockUnlock(sKextLock); 1937 1938 if (result) { 1939 OSKextLog(this, 1940 kOSKextLogStepLevel | 1941 kOSKextLogKextBookkeepingFlag, 1942 "Kext %s, v%s registered and available for loading.", 1943 getIdentifierCString(), newVersionCString); 1944 } 1945 1946 OSSafeRelease(newUUID); 1947 OSSafeRelease(existingUUID); 1948 1949 return result; 1950 } 1951 1952 /********************************************************************* 1953 * Does the bare minimum validation to look up a kext. 1954 * All other validation is done on the spot as needed. 1955 **********************************************************************/ 1956 bool 1957 OSKext::setInfoDictionaryAndPath( 1958 OSDictionary * aDictionary, 1959 OSString * aPath) 1960 { 1961 bool result = false; 1962 OSString * bundleIDString = NULL; // do not release 1963 OSString * versionString = NULL; // do not release 1964 OSString * compatibleVersionString = NULL; // do not release 1965 const char * versionCString = NULL; // do not free 1966 const char * compatibleVersionCString = NULL; // do not free 1967 OSBoolean * scratchBool = NULL; // do not release 1968 OSDictionary * scratchDict = NULL; // do not release 1969 1970 if (infoDict) { 1971 panic("Attempt to set info dictionary on a kext " 1972 "that already has one (%s).", 1973 getIdentifierCString()); 1974 } 1975 1976 if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) { 1977 goto finish; 1978 } 1979 1980 infoDict = aDictionary; 1981 infoDict->retain(); 1982 1983 /* Check right away if the info dictionary has any log flags. 1984 */ 1985 scratchBool = OSDynamicCast(OSBoolean, 1986 getPropertyForHostArch(kOSBundleEnableKextLoggingKey)); 1987 if (scratchBool == kOSBooleanTrue) { 1988 flags.loggingEnabled = 1; 1989 } 1990 1991 /* The very next thing to get is the bundle identifier. Unlike 1992 * in user space, a kext with no bundle identifier gets axed 1993 * immediately. 1994 */ 1995 bundleIDString = OSDynamicCast(OSString, 1996 getPropertyForHostArch(kCFBundleIdentifierKey)); 1997 if (!bundleIDString) { 1998 OSKextLog(this, 1999 kOSKextLogErrorLevel | 2000 kOSKextLogValidationFlag, 2001 "CFBundleIdentifier missing/invalid type in kext %s.", 2002 aPath ? aPath->getCStringNoCopy() : "(unknown)"); 2003 goto finish; 2004 } 2005 bundleID = OSSymbol::withString(bundleIDString); 2006 if (!bundleID) { 2007 OSKextLog(this, 2008 kOSKextLogErrorLevel | 2009 kOSKextLogValidationFlag, 2010 "Can't copy bundle identifier as symbol for kext %s.", 2011 bundleIDString->getCStringNoCopy()); 2012 goto finish; 2013 } 2014 2015 /* Save the path if we got one (it should always be available but it's 2016 * just something nice to have for bookkeeping). 2017 */ 2018 if (aPath) { 2019 path = aPath; 2020 path->retain(); 2021 } 2022 2023 /***** 2024 * Minimal validation to initialize. We'll do other validation on the spot. 2025 */ 2026 if (bundleID->getLength() >= KMOD_MAX_NAME) { 2027 OSKextLog(this, 2028 kOSKextLogErrorLevel | 2029 kOSKextLogValidationFlag, 2030 "Kext %s error - CFBundleIdentifier over max length %d.", 2031 getIdentifierCString(), KMOD_MAX_NAME - 1); 2032 goto finish; 2033 } 2034 2035 version = compatibleVersion = -1; 2036 2037 versionString = OSDynamicCast(OSString, 2038 getPropertyForHostArch(kCFBundleVersionKey)); 2039 if (!versionString) { 2040 OSKextLog(this, 2041 kOSKextLogErrorLevel | 2042 kOSKextLogValidationFlag, 2043 "Kext %s error - CFBundleVersion missing/invalid type.", 2044 getIdentifierCString()); 2045 goto finish; 2046 } 2047 versionCString = versionString->getCStringNoCopy(); 2048 version = OSKextParseVersionString(versionCString); 2049 if (version < 0) { 2050 OSKextLog(this, 2051 kOSKextLogErrorLevel | 2052 kOSKextLogValidationFlag, 2053 "Kext %s error - CFBundleVersion bad value '%s'.", 2054 getIdentifierCString(), versionCString); 2055 goto finish; 2056 } 2057 2058 compatibleVersion = -1; // set to illegal value for kexts that don't have 2059 2060 compatibleVersionString = OSDynamicCast(OSString, 2061 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 2062 if (compatibleVersionString) { 2063 compatibleVersionCString = compatibleVersionString->getCStringNoCopy(); 2064 compatibleVersion = OSKextParseVersionString(compatibleVersionCString); 2065 if (compatibleVersion < 0) { 2066 OSKextLog(this, 2067 kOSKextLogErrorLevel | 2068 kOSKextLogValidationFlag, 2069 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.", 2070 getIdentifierCString(), compatibleVersionCString); 2071 goto finish; 2072 } 2073 2074 if (compatibleVersion > version) { 2075 OSKextLog(this, 2076 kOSKextLogErrorLevel | 2077 kOSKextLogValidationFlag, 2078 "Kext %s error - %s %s > %s %s (must be <=).", 2079 getIdentifierCString(), 2080 kOSBundleCompatibleVersionKey, compatibleVersionCString, 2081 kCFBundleVersionKey, versionCString); 2082 goto finish; 2083 } 2084 } 2085 2086 /* Check to see if this kext is in exclude list */ 2087 if ( isInExcludeList() ) { 2088 OSKextLog(this, 2089 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 2090 "Kext %s is in exclude list, not loadable", 2091 getIdentifierCString()); 2092 goto finish; 2093 } 2094 2095 /* Set flags for later use if the infoDict gets flushed. We only 2096 * check for true values, not false ones(!) 2097 */ 2098 scratchBool = OSDynamicCast(OSBoolean, 2099 getPropertyForHostArch(kOSBundleIsInterfaceKey)); 2100 if (scratchBool == kOSBooleanTrue) { 2101 flags.interface = 1; 2102 } 2103 2104 scratchBool = OSDynamicCast(OSBoolean, 2105 getPropertyForHostArch(kOSKernelResourceKey)); 2106 if (scratchBool == kOSBooleanTrue) { 2107 flags.kernelComponent = 1; 2108 flags.interface = 1; // xxx - hm. the kernel itself isn't an interface... 2109 flags.started = 1; 2110 2111 /* A kernel component has one implicit dependency on the kernel. 2112 */ 2113 flags.hasAllDependencies = 1; 2114 } 2115 2116 /* Make sure common string values in personalities are uniqued to OSSymbols. 2117 */ 2118 scratchDict = OSDynamicCast(OSDictionary, 2119 getPropertyForHostArch(kIOKitPersonalitiesKey)); 2120 if (scratchDict) { 2121 uniquePersonalityProperties(scratchDict); 2122 } 2123 2124 result = true; 2125 2126 finish: 2127 2128 return result; 2129 } 2130 2131 /********************************************************************* 2132 * Not used for prelinked kernel boot as there is no unrelocated 2133 * executable. 2134 *********************************************************************/ 2135 bool 2136 OSKext::setExecutable( 2137 OSData * anExecutable, 2138 OSData * externalData, 2139 bool externalDataIsMkext) 2140 { 2141 bool result = false; 2142 const char * executableKey = NULL; // do not free 2143 2144 if (!anExecutable) { 2145 infoDict->removeObject(_kOSKextExecutableKey); 2146 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 2147 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 2148 result = true; 2149 goto finish; 2150 } 2151 2152 if (infoDict->getObject(_kOSKextExecutableKey) || 2153 infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) { 2154 2155 panic("Attempt to set an executable on a kext " 2156 "that already has one (%s).", 2157 getIdentifierCString()); 2158 goto finish; 2159 } 2160 2161 if (externalDataIsMkext) { 2162 executableKey = _kOSKextMkextExecutableReferenceKey; 2163 } else { 2164 executableKey = _kOSKextExecutableKey; 2165 } 2166 2167 if (anExecutable) { 2168 infoDict->setObject(executableKey, anExecutable); 2169 if (externalData) { 2170 infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData); 2171 } 2172 } 2173 2174 result = true; 2175 2176 finish: 2177 return result; 2178 } 2179 2180 /********************************************************************* 2181 *********************************************************************/ 2182 static void 2183 uniqueStringPlistProperty(OSDictionary * dict, const char * key) 2184 { 2185 OSString * stringValue = NULL; // do not release 2186 const OSSymbol * symbolValue = NULL; // must release 2187 2188 stringValue = OSDynamicCast(OSString, dict->getObject(key)); 2189 if (!stringValue) { 2190 goto finish; 2191 } 2192 2193 symbolValue = OSSymbol::withString(stringValue); 2194 if (!symbolValue) { 2195 goto finish; 2196 } 2197 2198 dict->setObject(key, symbolValue); 2199 2200 finish: 2201 if (symbolValue) symbolValue->release(); 2202 2203 return; 2204 } 2205 2206 /********************************************************************* 2207 *********************************************************************/ 2208 static void 2209 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key) 2210 { 2211 OSString * stringValue = NULL; // do not release 2212 const OSSymbol * symbolValue = NULL; // must release 2213 2214 stringValue = OSDynamicCast(OSString, dict->getObject(key)); 2215 if (!stringValue) { 2216 goto finish; 2217 } 2218 2219 symbolValue = OSSymbol::withString(stringValue); 2220 if (!symbolValue) { 2221 goto finish; 2222 } 2223 2224 dict->setObject(key, symbolValue); 2225 2226 finish: 2227 if (symbolValue) symbolValue->release(); 2228 2229 return; 2230 } 2231 2232 /********************************************************************* 2233 * Replace common personality property values with uniqued instances 2234 * to save on wired memory. 2235 *********************************************************************/ 2236 /* static */ 2237 void 2238 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict) 2239 { 2240 /* Properties every personality has. 2241 */ 2242 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey); 2243 uniqueStringPlistProperty(personalityDict, kIOProviderClassKey); 2244 uniqueStringPlistProperty(personalityDict, gIOClassKey); 2245 2246 /* Other commonly used properties. 2247 */ 2248 uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey); 2249 uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey); 2250 uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey); 2251 2252 uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior"); 2253 uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType"); 2254 uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType"); 2255 uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType"); 2256 uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher"); 2257 uniqueStringPlistProperty(personalityDict, "Physical Interconnect"); 2258 uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location"); 2259 uniqueStringPlistProperty(personalityDict, "Vendor"); 2260 uniqueStringPlistProperty(personalityDict, "Vendor Identification"); 2261 uniqueStringPlistProperty(personalityDict, "Vendor Name"); 2262 uniqueStringPlistProperty(personalityDict, "bConfigurationValue"); 2263 uniqueStringPlistProperty(personalityDict, "bInterfaceNumber"); 2264 uniqueStringPlistProperty(personalityDict, "idProduct"); 2265 2266 return; 2267 } 2268 2269 /********************************************************************* 2270 *********************************************************************/ 2271 void 2272 OSKext::free(void) 2273 { 2274 if (isLoaded()) { 2275 panic("Attempt to free loaded kext %s.", getIdentifierCString()); 2276 } 2277 2278 OSSafeRelease(infoDict); 2279 OSSafeRelease(bundleID); 2280 OSSafeRelease(path); 2281 OSSafeRelease(executableRelPath); 2282 OSSafeRelease(dependencies); 2283 OSSafeRelease(linkedExecutable); 2284 OSSafeRelease(metaClasses); 2285 OSSafeRelease(interfaceUUID); 2286 2287 if (isInterface() && kmod_info) { 2288 kfree(kmod_info, sizeof(kmod_info_t)); 2289 } 2290 2291 super::free(); 2292 return; 2293 } 2294 2295 #if PRAGMA_MARK 2296 #pragma mark Mkext files 2297 #endif 2298 /********************************************************************* 2299 *********************************************************************/ 2300 OSReturn 2301 OSKext::readMkextArchive(OSData * mkextData, 2302 uint32_t * checksumPtr) 2303 { 2304 OSReturn result = kOSKextReturnBadData; 2305 uint32_t mkextLength = 0; 2306 mkext_header * mkextHeader = 0; // do not free 2307 uint32_t mkextVersion = 0; 2308 2309 /* Note default return of kOSKextReturnBadData above. 2310 */ 2311 mkextLength = mkextData->getLength(); 2312 if (mkextLength < sizeof(mkext_basic_header)) { 2313 OSKextLog(/* kext */ NULL, 2314 kOSKextLogErrorLevel | 2315 kOSKextLogArchiveFlag, 2316 "Mkext archive too small to be valid."); 2317 goto finish; 2318 } 2319 2320 mkextHeader = (mkext_header *)mkextData->getBytesNoCopy(); 2321 2322 if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC || 2323 MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) { 2324 OSKextLog(/* kext */ NULL, 2325 kOSKextLogErrorLevel | 2326 kOSKextLogArchiveFlag, 2327 "Mkext archive has invalid magic or signature."); 2328 goto finish; 2329 } 2330 2331 if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) { 2332 OSKextLog(/* kext */ NULL, 2333 kOSKextLogErrorLevel | 2334 kOSKextLogArchiveFlag, 2335 "Mkext archive recorded length doesn't match actual file length."); 2336 goto finish; 2337 } 2338 2339 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 2340 2341 if (mkextVersion == MKEXT_VERS_2) { 2342 result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr); 2343 } else { 2344 OSKextLog(/* kext */ NULL, 2345 kOSKextLogErrorLevel | 2346 kOSKextLogArchiveFlag, 2347 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion); 2348 result = kOSKextReturnUnsupported; 2349 } 2350 2351 finish: 2352 return result; 2353 } 2354 2355 /********************************************************************* 2356 * Assumes magic, signature, version, length have been checked. 2357 * xxx - need to add further bounds checking for each file entry 2358 * 2359 * Should keep track of all kexts created so far, and if we hit a 2360 * fatal error halfway through, remove those kexts. If we've dropped 2361 * an older version that had already been read, whoops! Might want to 2362 * add a level of buffering? 2363 *********************************************************************/ 2364 /* static */ 2365 OSReturn 2366 OSKext::readMkext2Archive( 2367 OSData * mkextData, 2368 OSDictionary ** mkextPlistOut, 2369 uint32_t * checksumPtr) 2370 { 2371 OSReturn result = kOSReturnError; 2372 uint32_t mkextLength; 2373 mkext2_header * mkextHeader = NULL; // do not free 2374 void * mkextEnd = NULL; // do not free 2375 uint32_t mkextVersion; 2376 uint8_t * crc_address = NULL; 2377 uint32_t checksum; 2378 uint32_t mkextPlistOffset; 2379 uint32_t mkextPlistCompressedSize; 2380 char * mkextPlistEnd = NULL; // do not free 2381 uint32_t mkextPlistFullSize; 2382 OSString * errorString = NULL; // must release 2383 OSData * mkextPlistUncompressedData = NULL; // must release 2384 const char * mkextPlistDataBuffer = NULL; // do not free 2385 OSObject * parsedXML = NULL; // must release 2386 OSDictionary * mkextPlist = NULL; // do not release 2387 OSArray * mkextInfoDictArray = NULL; // do not release 2388 uint32_t count, i; 2389 2390 mkextLength = mkextData->getLength(); 2391 mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy(); 2392 mkextEnd = (char *)mkextHeader + mkextLength; 2393 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 2394 2395 crc_address = (u_int8_t *)&mkextHeader->version; 2396 checksum = mkext_adler32(crc_address, 2397 (uintptr_t)mkextHeader + 2398 MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address); 2399 2400 if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) { 2401 OSKextLog(/* kext */ NULL, 2402 kOSKextLogErrorLevel | 2403 kOSKextLogArchiveFlag, 2404 "Mkext archive has bad checksum."); 2405 result = kOSKextReturnBadData; 2406 goto finish; 2407 } 2408 2409 if (checksumPtr) { 2410 *checksumPtr = checksum; 2411 } 2412 2413 /* Check that the CPU type & subtype match that of the running kernel. */ 2414 if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) { 2415 OSKextLog(/* kext */ NULL, 2416 kOSKextLogErrorLevel | 2417 kOSKextLogArchiveFlag, 2418 "Mkext archive must have a specific CPU type."); 2419 result = kOSKextReturnBadData; 2420 goto finish; 2421 } else { 2422 if ((UInt32)_mh_execute_header.cputype != 2423 MKEXT_GET_CPUTYPE(mkextHeader)) { 2424 2425 OSKextLog(/* kext */ NULL, 2426 kOSKextLogErrorLevel | 2427 kOSKextLogArchiveFlag, 2428 "Mkext archive does not match the running kernel's CPU type."); 2429 result = kOSKextReturnArchNotFound; 2430 goto finish; 2431 } 2432 } 2433 2434 mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader); 2435 mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader); 2436 mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset + 2437 mkextPlistCompressedSize; 2438 if (mkextPlistEnd > mkextEnd) { 2439 OSKextLog(/* kext */ NULL, 2440 kOSKextLogErrorLevel | 2441 kOSKextLogArchiveFlag, 2442 "Mkext archive file overrun."); 2443 result = kOSKextReturnBadData; 2444 } 2445 2446 mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader); 2447 if (mkextPlistCompressedSize) { 2448 mkextPlistUncompressedData = sKernelKext->extractMkext2FileData( 2449 (UInt8 *)mkextHeader + mkextPlistOffset, 2450 "plist", 2451 mkextPlistCompressedSize, mkextPlistFullSize); 2452 if (!mkextPlistUncompressedData) { 2453 goto finish; 2454 } 2455 mkextPlistDataBuffer = (const char *) 2456 mkextPlistUncompressedData->getBytesNoCopy(); 2457 } else { 2458 mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset; 2459 } 2460 2461 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it. 2462 */ 2463 parsedXML = OSUnserializeXML(mkextPlistDataBuffer, &errorString); 2464 if (parsedXML) { 2465 mkextPlist = OSDynamicCast(OSDictionary, parsedXML); 2466 } 2467 if (!mkextPlist) { 2468 const char * errorCString = "(unknown error)"; 2469 2470 if (errorString && errorString->getCStringNoCopy()) { 2471 errorCString = errorString->getCStringNoCopy(); 2472 } else if (parsedXML) { 2473 errorCString = "not a dictionary"; 2474 } 2475 OSKextLog(/* kext */ NULL, 2476 kOSKextLogErrorLevel | 2477 kOSKextLogArchiveFlag, 2478 "Error unserializing mkext plist: %s.", errorCString); 2479 goto finish; 2480 } 2481 2482 /* If the caller needs the plist, hand it back and retain it. 2483 * (This function releases it at the end.) 2484 */ 2485 if (mkextPlistOut) { 2486 *mkextPlistOut = mkextPlist; 2487 (*mkextPlistOut)->retain(); 2488 } 2489 2490 mkextInfoDictArray = OSDynamicCast(OSArray, 2491 mkextPlist->getObject(kMKEXTInfoDictionariesKey)); 2492 if (!mkextInfoDictArray) { 2493 OSKextLog(/* kext */ NULL, 2494 kOSKextLogErrorLevel | 2495 kOSKextLogArchiveFlag, 2496 "Mkext archive contains no kext info dictionaries."); 2497 goto finish; 2498 } 2499 2500 count = mkextInfoDictArray->getCount(); 2501 for (i = 0; i < count; i++) { 2502 OSDictionary * infoDict; 2503 2504 2505 infoDict = OSDynamicCast(OSDictionary, 2506 mkextInfoDictArray->getObject(i)); 2507 2508 /* Create the kext for the entry, then release it, because the 2509 * kext system keeps them around until explicitly removed. 2510 * Any creation/registration failures are already logged for us. 2511 */ 2512 if (infoDict) { 2513 OSKext * newKext = OSKext::withMkext2Info(infoDict, mkextData); 2514 OSSafeRelease(newKext); 2515 } 2516 } 2517 2518 /* Even if we didn't keep any kexts from the mkext, we may have a load 2519 * request to process, so we are successful (no errors occurred). 2520 */ 2521 result = kOSReturnSuccess; 2522 2523 finish: 2524 2525 OSSafeRelease(parsedXML); 2526 OSSafeRelease(mkextPlistUncompressedData); 2527 OSSafeRelease(errorString); 2528 2529 return result; 2530 } 2531 2532 /********************************************************************* 2533 *********************************************************************/ 2534 /* static */ 2535 OSKext * 2536 OSKext::withMkext2Info( 2537 OSDictionary * anInfoDict, 2538 OSData * mkextData) 2539 { 2540 OSKext * newKext = new OSKext; 2541 2542 if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) { 2543 newKext->release(); 2544 return NULL; 2545 } 2546 2547 return newKext; 2548 } 2549 2550 /********************************************************************* 2551 *********************************************************************/ 2552 bool 2553 OSKext::initWithMkext2Info( 2554 OSDictionary * anInfoDict, 2555 OSData * mkextData) 2556 { 2557 bool result = false; 2558 OSString * kextPath = NULL; // do not release 2559 OSNumber * executableOffsetNum = NULL; // do not release 2560 OSCollectionIterator * iterator = NULL; // must release 2561 OSData * executable = NULL; // must release 2562 2563 if (anInfoDict == NULL || !super::init()) { 2564 goto finish; 2565 } 2566 2567 /* Get the path. Don't look for an arch-specific path property. 2568 */ 2569 kextPath = OSDynamicCast(OSString, 2570 anInfoDict->getObject(kMKEXTBundlePathKey)); 2571 2572 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 2573 goto finish; 2574 } 2575 2576 /* If we have a path to the executable, save it. 2577 */ 2578 executableRelPath = OSDynamicCast(OSString, 2579 anInfoDict->getObject(kMKEXTExecutableRelativePathKey)); 2580 if (executableRelPath) { 2581 executableRelPath->retain(); 2582 } 2583 2584 /* Don't need the paths to be in the info dictionary any more. 2585 */ 2586 anInfoDict->removeObject(kMKEXTBundlePathKey); 2587 anInfoDict->removeObject(kMKEXTExecutableRelativePathKey); 2588 2589 executableOffsetNum = OSDynamicCast(OSNumber, 2590 infoDict->getObject(kMKEXTExecutableKey)); 2591 if (executableOffsetNum) { 2592 executable = createMkext2FileEntry(mkextData, 2593 executableOffsetNum, "executable"); 2594 infoDict->removeObject(kMKEXTExecutableKey); 2595 if (!executable) { 2596 goto finish; 2597 } 2598 if (!setExecutable(executable, mkextData, true)) { 2599 goto finish; 2600 } 2601 } 2602 2603 result = registerIdentifier(); 2604 2605 finish: 2606 2607 OSSafeRelease(executable); 2608 OSSafeRelease(iterator); 2609 return result; 2610 } 2611 2612 /********************************************************************* 2613 *********************************************************************/ 2614 OSData * 2615 OSKext::createMkext2FileEntry( 2616 OSData * mkextData, 2617 OSNumber * offsetNum, 2618 const char * name) 2619 { 2620 OSData * result = NULL; 2621 MkextEntryRef entryRef; 2622 uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy(); 2623 uint32_t entryOffset = offsetNum->unsigned32BitValue(); 2624 2625 result = OSData::withCapacity(sizeof(entryRef)); 2626 if (!result) { 2627 goto finish; 2628 } 2629 2630 entryRef.mkext = (mkext_basic_header *)mkextBuffer; 2631 entryRef.fileinfo = mkextBuffer + entryOffset; 2632 if (!result->appendBytes(&entryRef, sizeof(entryRef))) { 2633 OSSafeReleaseNULL(result); 2634 goto finish; 2635 } 2636 2637 finish: 2638 if (!result) { 2639 OSKextLog(this, 2640 kOSKextLogErrorLevel | 2641 kOSKextLogArchiveFlag, 2642 "Can't create wrapper for mkext file entry '%s' of kext %s.", 2643 name, getIdentifierCString()); 2644 } 2645 return result; 2646 } 2647 2648 /********************************************************************* 2649 *********************************************************************/ 2650 extern "C" { 2651 static void * z_alloc(void *, u_int items, u_int size); 2652 static void z_free(void *, void *ptr); 2653 2654 typedef struct z_mem { 2655 uint32_t alloc_size; 2656 uint8_t data[0]; 2657 } z_mem; 2658 2659 /* 2660 * Space allocation and freeing routines for use by zlib routines. 2661 */ 2662 void * 2663 z_alloc(void * notused __unused, u_int num_items, u_int size) 2664 { 2665 void * result = NULL; 2666 z_mem * zmem = NULL; 2667 2668 uint64_t total = ((uint64_t)num_items) * ((uint64_t)size); 2669 //Check for overflow due to multiplication 2670 if (total > UINT32_MAX){ 2671 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n", 2672 notused, num_items, size, num_items, size); 2673 } 2674 2675 uint64_t allocSize64 = total + ((uint64_t)sizeof(zmem)); 2676 //Check for overflow due to addition 2677 if (allocSize64 > UINT32_MAX){ 2678 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n", 2679 notused, num_items, size, (uint32_t)total, sizeof(zmem)); 2680 } 2681 uint32_t allocSize = (uint32_t)allocSize64; 2682 2683 zmem = (z_mem *)kalloc_tag(allocSize, VM_KERN_MEMORY_OSKEXT); 2684 if (!zmem) { 2685 goto finish; 2686 } 2687 zmem->alloc_size = allocSize; 2688 result = (void *)&(zmem->data); 2689 finish: 2690 return result; 2691 } 2692 2693 void 2694 z_free(void * notused __unused, void * ptr) 2695 { 2696 uint32_t * skipper = (uint32_t *)ptr - 1; 2697 z_mem * zmem = (z_mem *)skipper; 2698 kfree((void *)zmem, zmem->alloc_size); 2699 return; 2700 } 2701 }; 2702 2703 OSData * 2704 OSKext::extractMkext2FileData( 2705 UInt8 * data, 2706 const char * name, 2707 uint32_t compressedSize, 2708 uint32_t fullSize) 2709 { 2710 OSData * result = NULL; 2711 2712 OSData * uncompressedData = NULL; // release on error 2713 2714 uint8_t * uncompressedDataBuffer = 0; // do not free 2715 unsigned long uncompressedSize; 2716 z_stream zstream; 2717 bool zstream_inited = false; 2718 int zlib_result; 2719 2720 /* If the file isn't compressed, we want to make a copy 2721 * so that we don't have the tie to the larger mkext file buffer any more. 2722 */ 2723 if (!compressedSize) { 2724 uncompressedData = OSData::withBytes(data, fullSize); 2725 // xxx - no check for failure? 2726 result = uncompressedData; 2727 goto finish; 2728 } 2729 2730 if (KERN_SUCCESS != kmem_alloc(kernel_map, 2731 (vm_offset_t*)&uncompressedDataBuffer, fullSize, VM_KERN_MEMORY_OSKEXT)) { 2732 2733 /* How's this for cheesy? The kernel is only asked to extract 2734 * kext plists so we tailor the log messages. 2735 */ 2736 if (isKernel()) { 2737 OSKextLog(this, 2738 kOSKextLogErrorLevel | 2739 kOSKextLogArchiveFlag, 2740 "Allocation failure extracting %s from mkext.", name); 2741 } else { 2742 OSKextLog(this, 2743 kOSKextLogErrorLevel | 2744 kOSKextLogArchiveFlag, 2745 "Allocation failure extracting %s from mkext for kext %s.", 2746 name, getIdentifierCString()); 2747 } 2748 2749 goto finish; 2750 } 2751 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize); 2752 if (!uncompressedData) { 2753 if (isKernel()) { 2754 OSKextLog(this, 2755 kOSKextLogErrorLevel | 2756 kOSKextLogArchiveFlag, 2757 "Allocation failure extracting %s from mkext.", name); 2758 } else { 2759 OSKextLog(this, 2760 kOSKextLogErrorLevel | 2761 kOSKextLogArchiveFlag, 2762 "Allocation failure extracting %s from mkext for kext %s.", 2763 name, getIdentifierCString()); 2764 } 2765 goto finish; 2766 } 2767 uncompressedData->setDeallocFunction(&osdata_kmem_free); 2768 2769 if (isKernel()) { 2770 OSKextLog(this, 2771 kOSKextLogDetailLevel | 2772 kOSKextLogArchiveFlag, 2773 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.", 2774 name, compressedSize, fullSize); 2775 } else { 2776 OSKextLog(this, 2777 kOSKextLogDetailLevel | 2778 kOSKextLogArchiveFlag, 2779 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.", 2780 getIdentifierCString(), name, compressedSize, fullSize); 2781 } 2782 2783 bzero(&zstream, sizeof(zstream)); 2784 zstream.next_in = (UInt8 *)data; 2785 zstream.avail_in = compressedSize; 2786 2787 zstream.next_out = uncompressedDataBuffer; 2788 zstream.avail_out = fullSize; 2789 2790 zstream.zalloc = z_alloc; 2791 zstream.zfree = z_free; 2792 2793 zlib_result = inflateInit(&zstream); 2794 if (Z_OK != zlib_result) { 2795 if (isKernel()) { 2796 OSKextLog(this, 2797 kOSKextLogErrorLevel | 2798 kOSKextLogArchiveFlag, 2799 "Mkext error; zlib inflateInit failed (%d) for %s.", 2800 zlib_result, name); 2801 } else { 2802 OSKextLog(this, 2803 kOSKextLogErrorLevel | 2804 kOSKextLogArchiveFlag, 2805 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .", 2806 getIdentifierCString(), zlib_result, name); 2807 } 2808 goto finish; 2809 } else { 2810 zstream_inited = true; 2811 } 2812 2813 zlib_result = inflate(&zstream, Z_FINISH); 2814 2815 if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) { 2816 uncompressedSize = zstream.total_out; 2817 } else { 2818 if (isKernel()) { 2819 OSKextLog(this, 2820 kOSKextLogErrorLevel | 2821 kOSKextLogArchiveFlag, 2822 "Mkext error; zlib inflate failed (%d) for %s.", 2823 zlib_result, name); 2824 } else { 2825 OSKextLog(this, 2826 kOSKextLogErrorLevel | 2827 kOSKextLogArchiveFlag, 2828 "Kext %s - mkext error; zlib inflate failed (%d) for %s .", 2829 getIdentifierCString(), zlib_result, name); 2830 } 2831 if (zstream.msg) { 2832 OSKextLog(this, 2833 kOSKextLogErrorLevel | 2834 kOSKextLogArchiveFlag, 2835 "zlib error: %s.", zstream.msg); 2836 } 2837 goto finish; 2838 } 2839 2840 if (uncompressedSize != fullSize) { 2841 if (isKernel()) { 2842 OSKextLog(this, 2843 kOSKextLogErrorLevel | 2844 kOSKextLogArchiveFlag, 2845 "Mkext error; zlib inflate discrepancy for %s, " 2846 "uncompressed size != original size.", name); 2847 } else { 2848 OSKextLog(this, 2849 kOSKextLogErrorLevel | 2850 kOSKextLogArchiveFlag, 2851 "Kext %s - mkext error; zlib inflate discrepancy for %s, " 2852 "uncompressed size != original size.", 2853 getIdentifierCString(), name); 2854 } 2855 goto finish; 2856 } 2857 2858 result = uncompressedData; 2859 2860 finish: 2861 /* Don't bother checking return, nothing we can do on fail. 2862 */ 2863 if (zstream_inited) inflateEnd(&zstream); 2864 2865 if (!result) { 2866 OSSafeRelease(uncompressedData); 2867 } 2868 2869 return result; 2870 } 2871 2872 /********************************************************************* 2873 *********************************************************************/ 2874 /* static */ 2875 OSReturn 2876 OSKext::loadFromMkext( 2877 OSKextLogSpec clientLogFilter, 2878 char * mkextBuffer, 2879 uint32_t mkextBufferLength, 2880 char ** logInfoOut, 2881 uint32_t * logInfoLengthOut) 2882 { 2883 OSReturn result = kOSReturnError; 2884 OSReturn tempResult = kOSReturnError; 2885 2886 OSData * mkextData = NULL; // must release 2887 OSDictionary * mkextPlist = NULL; // must release 2888 2889 OSArray * logInfoArray = NULL; // must release 2890 OSSerialize * serializer = NULL; // must release 2891 2892 OSString * predicate = NULL; // do not release 2893 OSDictionary * requestArgs = NULL; // do not release 2894 2895 OSString * kextIdentifier = NULL; // do not release 2896 OSNumber * startKextExcludeNum = NULL; // do not release 2897 OSNumber * startMatchingExcludeNum = NULL; // do not release 2898 OSBoolean * delayAutounloadBool = NULL; // do not release 2899 OSArray * personalityNames = NULL; // do not release 2900 2901 /* Default values for these two options: regular autounload behavior, 2902 * load all kexts, send no personalities. 2903 */ 2904 Boolean delayAutounload = false; 2905 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 2906 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll; 2907 2908 IORecursiveLockLock(sKextLock); 2909 2910 if (logInfoOut) { 2911 *logInfoOut = NULL; 2912 *logInfoLengthOut = 0; 2913 } 2914 2915 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 2916 2917 OSKextLog(/* kext */ NULL, 2918 kOSKextLogDebugLevel | 2919 kOSKextLogIPCFlag, 2920 "Received kext load request from user space."); 2921 2922 /* Regardless of processing, the fact that we have gotten here means some 2923 * user-space program is up and talking to us, so we'll switch our kext 2924 * registration to reflect that. 2925 */ 2926 if (!sUserLoadsActive) { 2927 OSKextLog(/* kext */ NULL, 2928 kOSKextLogProgressLevel | 2929 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 2930 "Switching to late startup (user-space) kext loading policy."); 2931 2932 sUserLoadsActive = true; 2933 } 2934 2935 if (!sLoadEnabled) { 2936 OSKextLog(/* kext */ NULL, 2937 kOSKextLogErrorLevel | 2938 kOSKextLogLoadFlag, 2939 "Kext loading is disabled."); 2940 result = kOSKextReturnDisabled; 2941 goto finish; 2942 } 2943 2944 /* Note that we do not set a dealloc function on this OSData 2945 * object! No references to it can remain after the loadFromMkext() 2946 * call since we are in a MIG function, and will vm_deallocate() 2947 * the buffer. 2948 */ 2949 mkextData = OSData::withBytesNoCopy(mkextBuffer, 2950 mkextBufferLength); 2951 if (!mkextData) { 2952 OSKextLog(/* kext */ NULL, 2953 kOSKextLogErrorLevel | 2954 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 2955 "Failed to create wrapper for kext load request."); 2956 result = kOSKextReturnNoMemory; 2957 goto finish; 2958 } 2959 2960 result = readMkext2Archive(mkextData, &mkextPlist, NULL); 2961 if (result != kOSReturnSuccess) { 2962 OSKextLog(/* kext */ NULL, 2963 kOSKextLogErrorLevel | 2964 kOSKextLogLoadFlag, 2965 "Failed to read kext load request."); 2966 goto finish; 2967 } 2968 2969 predicate = _OSKextGetRequestPredicate(mkextPlist); 2970 if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) { 2971 OSKextLog(/* kext */ NULL, 2972 kOSKextLogErrorLevel | 2973 kOSKextLogLoadFlag, 2974 "Received kext load request with no predicate; skipping."); 2975 result = kOSKextReturnInvalidArgument; 2976 goto finish; 2977 } 2978 2979 requestArgs = OSDynamicCast(OSDictionary, 2980 mkextPlist->getObject(kKextRequestArgumentsKey)); 2981 if (!requestArgs || !requestArgs->getCount()) { 2982 OSKextLog(/* kext */ NULL, 2983 kOSKextLogErrorLevel | 2984 kOSKextLogLoadFlag, 2985 "Received kext load request with no arguments."); 2986 result = kOSKextReturnInvalidArgument; 2987 goto finish; 2988 } 2989 2990 kextIdentifier = OSDynamicCast(OSString, 2991 requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey)); 2992 if (!kextIdentifier) { 2993 OSKextLog(/* kext */ NULL, 2994 kOSKextLogErrorLevel | 2995 kOSKextLogLoadFlag, 2996 "Received kext load request with no kext identifier."); 2997 result = kOSKextReturnInvalidArgument; 2998 goto finish; 2999 } 3000 3001 startKextExcludeNum = OSDynamicCast(OSNumber, 3002 requestArgs->getObject(kKextRequestArgumentStartExcludeKey)); 3003 startMatchingExcludeNum = OSDynamicCast(OSNumber, 3004 requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey)); 3005 delayAutounloadBool = OSDynamicCast(OSBoolean, 3006 requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey)); 3007 personalityNames = OSDynamicCast(OSArray, 3008 requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey)); 3009 3010 if (delayAutounloadBool) { 3011 delayAutounload = delayAutounloadBool->getValue(); 3012 } 3013 if (startKextExcludeNum) { 3014 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 3015 } 3016 if (startMatchingExcludeNum) { 3017 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 3018 } 3019 3020 OSKextLog(/* kext */ NULL, 3021 kOSKextLogProgressLevel | 3022 kOSKextLogIPCFlag, 3023 "Received request from user space to load kext %s.", 3024 kextIdentifier->getCStringNoCopy()); 3025 3026 /* Load the kext, with no deferral, since this is a load from outside 3027 * the kernel. 3028 * xxx - Would like a better way to handle the default values for the 3029 * xxx - start/match opt args. 3030 */ 3031 result = OSKext::loadKextWithIdentifier( 3032 kextIdentifier, 3033 /* allowDefer */ false, 3034 delayAutounload, 3035 startKextExcludeLevel, 3036 startMatchingExcludeLevel, 3037 personalityNames); 3038 if (result != kOSReturnSuccess) { 3039 goto finish; 3040 } 3041 /* If the load came down from kextd, it will shortly inform IOCatalogue 3042 * for matching via a separate IOKit calldown. 3043 */ 3044 3045 finish: 3046 3047 /* Gather up the collected log messages for user space. Any 3048 * error messages past this call will not make it up as log messages 3049 * but will be in the system log. 3050 */ 3051 logInfoArray = OSKext::clearUserSpaceLogFilter(); 3052 3053 if (logInfoArray && logInfoOut && logInfoLengthOut) { 3054 tempResult = OSKext::serializeLogInfo(logInfoArray, 3055 logInfoOut, logInfoLengthOut); 3056 if (tempResult != kOSReturnSuccess) { 3057 result = tempResult; 3058 } 3059 } 3060 3061 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false); 3062 3063 /* Note: mkextDataObject will have been retained by every kext w/an 3064 * executable in it. That should all have been flushed out at the 3065 * and of the load operation, but you never know.... 3066 */ 3067 if (mkextData && mkextData->getRetainCount() > 1) { 3068 OSKextLog(/* kext */ NULL, 3069 kOSKextLogErrorLevel | 3070 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 3071 "Kext load request buffer from user space still retained by a kext; " 3072 "probable memory leak."); 3073 } 3074 3075 IORecursiveLockUnlock(sKextLock); 3076 3077 OSSafeRelease(mkextData); 3078 OSSafeRelease(mkextPlist); 3079 OSSafeRelease(serializer); 3080 OSSafeRelease(logInfoArray); 3081 3082 return result; 3083 } 3084 3085 /********************************************************************* 3086 *********************************************************************/ 3087 /* static */ 3088 OSReturn 3089 OSKext::serializeLogInfo( 3090 OSArray * logInfoArray, 3091 char ** logInfoOut, 3092 uint32_t * logInfoLengthOut) 3093 { 3094 OSReturn result = kOSReturnError; 3095 char * buffer = NULL; 3096 kern_return_t kmem_result = KERN_FAILURE; 3097 OSSerialize * serializer = NULL; // must release; reused 3098 char * logInfo = NULL; // returned by reference 3099 uint32_t logInfoLength = 0; 3100 3101 if (!logInfoArray || !logInfoOut || !logInfoLengthOut) { 3102 OSKextLog(/* kext */ NULL, 3103 kOSKextLogErrorLevel | 3104 kOSKextLogIPCFlag, 3105 "Internal error; invalid arguments to OSKext::serializeLogInfo()."); 3106 /* Bad programmer. */ 3107 result = kOSKextReturnInvalidArgument; 3108 goto finish; 3109 } 3110 3111 serializer = OSSerialize::withCapacity(0); 3112 if (!serializer) { 3113 OSKextLog(/* kext */ NULL, 3114 kOSKextLogErrorLevel | 3115 kOSKextLogIPCFlag, 3116 "Failed to create serializer on log info for request from user space."); 3117 /* Incidental error; we're going to (try to) allow the request 3118 * itself to succeed. */ 3119 } 3120 3121 if (!logInfoArray->serialize(serializer)) { 3122 OSKextLog(/* kext */ NULL, 3123 kOSKextLogErrorLevel | 3124 kOSKextLogIPCFlag, 3125 "Failed to serialize log info for request from user space."); 3126 /* Incidental error; we're going to (try to) allow the request 3127 * itself to succeed. */ 3128 } else { 3129 logInfo = serializer->text(); 3130 logInfoLength = serializer->getLength(); 3131 3132 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT); 3133 if (kmem_result != KERN_SUCCESS) { 3134 OSKextLog(/* kext */ NULL, 3135 kOSKextLogErrorLevel | 3136 kOSKextLogIPCFlag, 3137 "Failed to copy log info for request from user space."); 3138 /* Incidental error; we're going to (try to) allow the request 3139 * to succeed. */ 3140 } else { 3141 /* 11981737 - clear uninitialized data in last page */ 3142 bzero((void *)(buffer + logInfoLength), 3143 (round_page(logInfoLength) - logInfoLength)); 3144 memcpy(buffer, logInfo, logInfoLength); 3145 *logInfoOut = buffer; 3146 *logInfoLengthOut = logInfoLength; 3147 } 3148 } 3149 3150 result = kOSReturnSuccess; 3151 finish: 3152 OSSafeRelease(serializer); 3153 return result; 3154 } 3155 3156 #if PRAGMA_MARK 3157 #pragma mark Instance Management Methods 3158 #endif 3159 /********************************************************************* 3160 *********************************************************************/ 3161 OSKext * 3162 OSKext::lookupKextWithIdentifier(const char * kextIdentifier) 3163 { 3164 OSKext * foundKext = NULL; 3165 3166 IORecursiveLockLock(sKextLock); 3167 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 3168 if (foundKext) { 3169 foundKext->retain(); 3170 } 3171 IORecursiveLockUnlock(sKextLock); 3172 3173 return foundKext; 3174 } 3175 3176 /********************************************************************* 3177 *********************************************************************/ 3178 OSKext * 3179 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier) 3180 { 3181 return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy()); 3182 } 3183 3184 /********************************************************************* 3185 *********************************************************************/ 3186 OSKext * 3187 OSKext::lookupKextWithLoadTag(uint32_t aTag) 3188 { 3189 OSKext * foundKext = NULL; // returned 3190 uint32_t count, i; 3191 3192 IORecursiveLockLock(sKextLock); 3193 3194 count = sLoadedKexts->getCount(); 3195 for (i = 0; i < count; i++) { 3196 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 3197 if (thisKext->getLoadTag() == aTag) { 3198 foundKext = thisKext; 3199 foundKext->retain(); 3200 goto finish; 3201 } 3202 } 3203 3204 finish: 3205 IORecursiveLockUnlock(sKextLock); 3206 3207 return foundKext; 3208 } 3209 3210 /********************************************************************* 3211 *********************************************************************/ 3212 OSKext * 3213 OSKext::lookupKextWithAddress(vm_address_t address) 3214 { 3215 OSKext * foundKext = NULL; // returned 3216 uint32_t count, i; 3217 3218 IORecursiveLockLock(sKextLock); 3219 3220 count = sLoadedKexts->getCount(); 3221 for (i = 0; i < count; i++) { 3222 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 3223 if (thisKext->linkedExecutable) { 3224 vm_address_t kext_start = 3225 (vm_address_t)thisKext->linkedExecutable->getBytesNoCopy(); 3226 vm_address_t kext_end = kext_start + 3227 thisKext->linkedExecutable->getLength(); 3228 3229 if ((kext_start <= address) && (address < kext_end)) { 3230 foundKext = thisKext; 3231 foundKext->retain(); 3232 goto finish; 3233 } 3234 } 3235 } 3236 3237 finish: 3238 IORecursiveLockUnlock(sKextLock); 3239 3240 return foundKext; 3241 } 3242 3243 3244 /********************************************************************* 3245 *********************************************************************/ 3246 OSKext * 3247 OSKext::lookupKextWithUUID(uuid_t wanted) 3248 { 3249 OSKext * foundKext = NULL; // returned 3250 uint32_t count, i; 3251 3252 IORecursiveLockLock(sKextLock); 3253 3254 count = sLoadedKexts->getCount(); 3255 3256 for (i = 0; i < count; i++) { 3257 OSKext * thisKext = NULL; 3258 3259 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 3260 if (!thisKext) { 3261 continue; 3262 } 3263 3264 OSData *uuid_data = thisKext->copyUUID(); 3265 if (!uuid_data) { 3266 continue; 3267 } 3268 3269 uuid_t uuid; 3270 memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 3271 uuid_data->release(); 3272 3273 if (0 == uuid_compare(wanted, uuid)) { 3274 foundKext = thisKext; 3275 foundKext->retain(); 3276 goto finish; 3277 } 3278 3279 } 3280 3281 finish: 3282 IORecursiveLockUnlock(sKextLock); 3283 3284 return foundKext; 3285 } 3286 3287 3288 3289 3290 /********************************************************************* 3291 *********************************************************************/ 3292 /* static */ 3293 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier) 3294 { 3295 bool result = false; 3296 OSKext * foundKext = NULL; // returned 3297 3298 IORecursiveLockLock(sKextLock); 3299 3300 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 3301 if (foundKext && foundKext->isLoaded()) { 3302 result = true; 3303 } 3304 3305 IORecursiveLockUnlock(sKextLock); 3306 3307 return result; 3308 } 3309 3310 /********************************************************************* 3311 * xxx - should spawn a separate thread so a kext can safely have 3312 * xxx - itself unloaded. 3313 *********************************************************************/ 3314 /* static */ 3315 OSReturn 3316 OSKext::removeKext( 3317 OSKext * aKext, 3318 bool terminateServicesAndRemovePersonalitiesFlag) 3319 { 3320 OSReturn result = kOSKextReturnInUse; 3321 OSKext * checkKext = NULL; // do not release 3322 #if CONFIG_MACF 3323 int macCheckResult = 0; 3324 kauth_cred_t cred = NULL; 3325 #endif 3326 3327 IORecursiveLockLock(sKextLock); 3328 3329 /* If the kext has no identifier, it failed to init 3330 * so isn't in sKextsByID and it isn't loaded. 3331 */ 3332 if (!aKext->getIdentifier()) { 3333 result = kOSReturnSuccess; 3334 goto finish; 3335 } 3336 3337 checkKext = OSDynamicCast(OSKext, 3338 sKextsByID->getObject(aKext->getIdentifier())); 3339 if (checkKext != aKext) { 3340 result = kOSKextReturnNotFound; 3341 goto finish; 3342 } 3343 3344 if (aKext->isLoaded()) { 3345 #if CONFIG_MACF 3346 if (current_task() != kernel_task) { 3347 cred = kauth_cred_get_with_ref(); 3348 macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString()); 3349 kauth_cred_unref(&cred); 3350 } 3351 3352 if (macCheckResult != 0) { 3353 result = kOSReturnError; 3354 OSKextLog(aKext, 3355 kOSKextLogErrorLevel | 3356 kOSKextLogKextBookkeepingFlag, 3357 "Failed to remove kext %s (MAC policy error 0x%x).", 3358 aKext->getIdentifierCString(), macCheckResult); 3359 goto finish; 3360 } 3361 #endif 3362 3363 /* make sure there are no resource requests in flight - 17187548 */ 3364 if (aKext->countRequestCallbacks()) { 3365 goto finish; 3366 } 3367 3368 /* If we are terminating, send the request to the IOCatalogue 3369 * (which will actually call us right back but that's ok we have 3370 * a recursive lock don't you know) but do not ask the IOCatalogue 3371 * to call back with an unload, we'll do that right here. 3372 */ 3373 if (terminateServicesAndRemovePersonalitiesFlag) { 3374 result = gIOCatalogue->terminateDriversForModule( 3375 aKext->getIdentifierCString(), /* unload */ false); 3376 if (result != kOSReturnSuccess) { 3377 OSKextLog(aKext, 3378 kOSKextLogErrorLevel | 3379 kOSKextLogKextBookkeepingFlag, 3380 "Can't remove kext %s; services failed to terminate - 0x%x.", 3381 aKext->getIdentifierCString(), result); 3382 goto finish; 3383 } 3384 } 3385 3386 result = aKext->unload(); 3387 if (result != kOSReturnSuccess) { 3388 goto finish; 3389 } 3390 } 3391 3392 /* Remove personalities as requested. This is a bit redundant for a loaded 3393 * kext as IOCatalogue::terminateDriversForModule() removes driver 3394 * personalities, but it doesn't restart matching, which we always want 3395 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures 3396 * that happens. 3397 */ 3398 if (terminateServicesAndRemovePersonalitiesFlag) { 3399 aKext->removePersonalitiesFromCatalog(); 3400 } 3401 3402 OSKextLog(aKext, 3403 kOSKextLogProgressLevel | 3404 kOSKextLogKextBookkeepingFlag, 3405 "Removing kext %s.", 3406 aKext->getIdentifierCString()); 3407 3408 sKextsByID->removeObject(aKext->getIdentifier()); 3409 result = kOSReturnSuccess; 3410 3411 finish: 3412 IORecursiveLockUnlock(sKextLock); 3413 return result; 3414 } 3415 3416 /********************************************************************* 3417 *********************************************************************/ 3418 /* static */ 3419 OSReturn 3420 OSKext::removeKextWithIdentifier( 3421 const char * kextIdentifier, 3422 bool terminateServicesAndRemovePersonalitiesFlag) 3423 { 3424 OSReturn result = kOSReturnError; 3425 3426 IORecursiveLockLock(sKextLock); 3427 3428 OSKext * aKext = OSDynamicCast(OSKext, 3429 sKextsByID->getObject(kextIdentifier)); 3430 if (!aKext) { 3431 result = kOSKextReturnNotFound; 3432 OSKextLog(/* kext */ NULL, 3433 kOSKextLogErrorLevel | 3434 kOSKextLogKextBookkeepingFlag, 3435 "Can't remove kext %s - not found.", 3436 kextIdentifier); 3437 goto finish; 3438 } 3439 3440 result = OSKext::removeKext(aKext, 3441 terminateServicesAndRemovePersonalitiesFlag); 3442 3443 finish: 3444 IORecursiveLockUnlock(sKextLock); 3445 3446 return result; 3447 } 3448 3449 /********************************************************************* 3450 *********************************************************************/ 3451 /* static */ 3452 OSReturn 3453 OSKext::removeKextWithLoadTag( 3454 OSKextLoadTag loadTag, 3455 bool terminateServicesAndRemovePersonalitiesFlag) 3456 { 3457 OSReturn result = kOSReturnError; 3458 OSKext * foundKext = NULL; 3459 uint32_t count, i; 3460 3461 IORecursiveLockLock(sKextLock); 3462 3463 count = sLoadedKexts->getCount(); 3464 for (i = 0; i < count; i++) { 3465 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 3466 if (thisKext->loadTag == loadTag) { 3467 foundKext = thisKext; 3468 break; 3469 } 3470 } 3471 3472 if (!foundKext) { 3473 result = kOSKextReturnNotFound; 3474 OSKextLog(/* kext */ NULL, 3475 kOSKextLogErrorLevel | 3476 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 3477 "Can't remove kext with load tag %d - not found.", 3478 loadTag); 3479 goto finish; 3480 } 3481 3482 result = OSKext::removeKext(foundKext, 3483 terminateServicesAndRemovePersonalitiesFlag); 3484 3485 finish: 3486 IORecursiveLockUnlock(sKextLock); 3487 3488 return result; 3489 } 3490 3491 /********************************************************************* 3492 *********************************************************************/ 3493 OSDictionary * 3494 OSKext::copyKexts(void) 3495 { 3496 OSDictionary * result; 3497 3498 IORecursiveLockLock(sKextLock); 3499 result = OSDynamicCast(OSDictionary, sKextsByID->copyCollection()); 3500 IORecursiveLockUnlock(sKextLock); 3501 3502 return result; 3503 } 3504 3505 /********************************************************************* 3506 *********************************************************************/ 3507 #define BOOTER_KEXT_PREFIX "Driver-" 3508 3509 typedef struct _DeviceTreeBuffer { 3510 uint32_t paddr; 3511 uint32_t length; 3512 } _DeviceTreeBuffer; 3513 3514 /********************************************************************* 3515 * Create a dictionary of excluded kexts from the given booter data. 3516 *********************************************************************/ 3517 /* static */ 3518 void 3519 OSKext::createExcludeListFromBooterData( 3520 OSDictionary * theDictionary, 3521 OSCollectionIterator * theIterator ) 3522 { 3523 OSString * deviceTreeName = NULL; // do not release 3524 const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not release 3525 char * booterDataPtr = NULL; // do not release 3526 _BooterKextFileInfo * kextFileInfo = NULL; // do not release 3527 char * infoDictAddr = NULL; // do not release 3528 OSObject * parsedXML = NULL; // must release 3529 OSDictionary * theInfoDict = NULL; // do not release 3530 3531 theIterator->reset(); 3532 3533 /* look for AppleKextExcludeList.kext */ 3534 while ( (deviceTreeName = 3535 OSDynamicCast(OSString, theIterator->getNextObject())) ) { 3536 3537 const char * devTreeNameCString; 3538 OSData * deviceTreeEntry; 3539 OSString * myBundleID; // do not release 3540 3541 OSSafeReleaseNULL(parsedXML); 3542 3543 deviceTreeEntry = 3544 OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName)); 3545 if (!deviceTreeEntry) { 3546 continue; 3547 } 3548 3549 /* Make sure it is a kext */ 3550 devTreeNameCString = deviceTreeName->getCStringNoCopy(); 3551 if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX, 3552 (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) { 3553 OSKextLog(NULL, 3554 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 3555 "\"%s\" not a kext", 3556 devTreeNameCString); 3557 continue; 3558 } 3559 3560 deviceTreeBuffer = (const _DeviceTreeBuffer *) 3561 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer)); 3562 if (!deviceTreeBuffer) { 3563 continue; 3564 } 3565 3566 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr); 3567 if (!booterDataPtr) { 3568 continue; 3569 } 3570 3571 kextFileInfo = (_BooterKextFileInfo *) booterDataPtr; 3572 if (!kextFileInfo->infoDictPhysAddr || 3573 !kextFileInfo->infoDictLength) { 3574 continue; 3575 } 3576 3577 infoDictAddr = (char *) 3578 ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 3579 if (!infoDictAddr) { 3580 continue; 3581 } 3582 3583 parsedXML = OSUnserializeXML(infoDictAddr); 3584 if (!parsedXML) { 3585 continue; 3586 } 3587 3588 theInfoDict = OSDynamicCast(OSDictionary, parsedXML); 3589 if (!theInfoDict) { 3590 continue; 3591 } 3592 3593 myBundleID = 3594 OSDynamicCast(OSString, 3595 theInfoDict->getObject(kCFBundleIdentifierKey)); 3596 if ( myBundleID && 3597 strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) { 3598 3599 /* get copy of exclusion list dictionary */ 3600 OSDictionary * myTempDict; // do not free 3601 3602 myTempDict = OSDynamicCast( 3603 OSDictionary, 3604 theInfoDict->getObject("OSKextExcludeList")); 3605 if ( myTempDict ) { 3606 IORecursiveLockLock(sKextLock); 3607 3608 /* get rid of old exclusion list */ 3609 if (sExcludeListByID) { 3610 sExcludeListByID->flushCollection(); 3611 OSSafeRelease(sExcludeListByID); 3612 } 3613 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0); 3614 IORecursiveLockUnlock(sKextLock); 3615 } 3616 break; 3617 } 3618 3619 } // while ( (deviceTreeName = ...) ) 3620 3621 OSSafeReleaseNULL(parsedXML); 3622 return; 3623 } 3624 3625 /********************************************************************* 3626 * Create a dictionary of excluded kexts from the given prelink 3627 * info (kernelcache). 3628 *********************************************************************/ 3629 /* static */ 3630 void 3631 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray ) 3632 { 3633 OSDictionary * myInfoDict = NULL; // do not release 3634 OSString * myBundleID; // do not release 3635 u_int i; 3636 3637 /* Find com.apple.driver.KextExcludeList. */ 3638 for (i = 0; i < theInfoArray->getCount(); i++) { 3639 myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i)); 3640 if (!myInfoDict) { 3641 continue; 3642 } 3643 myBundleID = 3644 OSDynamicCast(OSString, 3645 myInfoDict->getObject(kCFBundleIdentifierKey)); 3646 if ( myBundleID && 3647 strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) { 3648 // get copy of exclude list dictionary 3649 OSDictionary * myTempDict; // do not free 3650 myTempDict = OSDynamicCast(OSDictionary, 3651 myInfoDict->getObject("OSKextExcludeList")); 3652 if ( myTempDict ) { 3653 IORecursiveLockLock(sKextLock); 3654 // get rid of old exclude list 3655 if (sExcludeListByID) { 3656 sExcludeListByID->flushCollection(); 3657 OSSafeRelease(sExcludeListByID); 3658 } 3659 3660 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0); 3661 IORecursiveLockUnlock(sKextLock); 3662 } 3663 break; 3664 } 3665 } // for (i = 0; i < theInfoArray->getCount()... 3666 3667 return; 3668 } 3669 3670 #if PRAGMA_MARK 3671 #pragma mark Accessors 3672 #endif 3673 /********************************************************************* 3674 *********************************************************************/ 3675 const OSSymbol * 3676 OSKext::getIdentifier(void) 3677 { 3678 return bundleID; 3679 } 3680 3681 /********************************************************************* 3682 * A kext must have a bundle identifier to even survive initialization; 3683 * this is guaranteed to exist past then. 3684 *********************************************************************/ 3685 const char * 3686 OSKext::getIdentifierCString(void) 3687 { 3688 return bundleID->getCStringNoCopy(); 3689 } 3690 3691 /********************************************************************* 3692 *********************************************************************/ 3693 OSKextVersion 3694 OSKext::getVersion(void) 3695 { 3696 return version; 3697 } 3698 3699 /********************************************************************* 3700 *********************************************************************/ 3701 OSKextVersion 3702 OSKext::getCompatibleVersion(void) 3703 { 3704 return compatibleVersion; 3705 } 3706 3707 /********************************************************************* 3708 *********************************************************************/ 3709 bool 3710 OSKext::isLibrary(void) 3711 { 3712 return (getCompatibleVersion() > 0); 3713 } 3714 3715 /********************************************************************* 3716 *********************************************************************/ 3717 bool 3718 OSKext::isCompatibleWithVersion(OSKextVersion aVersion) 3719 { 3720 if ((compatibleVersion > -1 && version > -1) && 3721 (compatibleVersion <= version && aVersion <= version)) { 3722 return true; 3723 } 3724 return false; 3725 } 3726 3727 /********************************************************************* 3728 *********************************************************************/ 3729 bool 3730 OSKext::declaresExecutable(void) 3731 { 3732 return (getPropertyForHostArch(kCFBundleExecutableKey) != NULL); 3733 } 3734 3735 /********************************************************************* 3736 *********************************************************************/ 3737 OSData * 3738 OSKext::getExecutable(void) 3739 { 3740 OSData * result = NULL; 3741 OSData * extractedExecutable = NULL; // must release 3742 OSData * mkextExecutableRef = NULL; // do not release 3743 3744 result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey)); 3745 if (result) { 3746 goto finish; 3747 } 3748 3749 mkextExecutableRef = OSDynamicCast(OSData, 3750 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey)); 3751 3752 if (mkextExecutableRef) { 3753 3754 MkextEntryRef * mkextEntryRef = (MkextEntryRef *) 3755 mkextExecutableRef->getBytesNoCopy(); 3756 uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext); 3757 if (mkextVersion == MKEXT_VERS_2) { 3758 mkext2_file_entry * fileinfo = 3759 (mkext2_file_entry *)mkextEntryRef->fileinfo; 3760 uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo); 3761 uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo); 3762 extractedExecutable = extractMkext2FileData( 3763 MKEXT2_GET_ENTRY_DATA(fileinfo), "executable", 3764 compressedSize, fullSize); 3765 } else { 3766 OSKextLog(this, kOSKextLogErrorLevel | 3767 kOSKextLogArchiveFlag, 3768 "Kext %s - unknown mkext version 0x%x for executable.", 3769 getIdentifierCString(), mkextVersion); 3770 } 3771 3772 /* Regardless of success, remove the mkext executable, 3773 * and drop one reference on the mkext. (setExecutable() does not 3774 * replace, it removes, or panics if asked to replace.) 3775 */ 3776 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 3777 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 3778 3779 if (extractedExecutable && extractedExecutable->getLength()) { 3780 if (!setExecutable(extractedExecutable)) { 3781 goto finish; 3782 } 3783 result = extractedExecutable; 3784 } else { 3785 goto finish; 3786 } 3787 } 3788 3789 finish: 3790 3791 OSSafeRelease(extractedExecutable); 3792 3793 return result; 3794 } 3795 3796 /********************************************************************* 3797 *********************************************************************/ 3798 bool 3799 OSKext::isInterface(void) 3800 { 3801 return flags.interface; 3802 } 3803 3804 /********************************************************************* 3805 *********************************************************************/ 3806 bool 3807 OSKext::isKernel(void) 3808 { 3809 return (this == sKernelKext); 3810 } 3811 3812 /********************************************************************* 3813 *********************************************************************/ 3814 bool 3815 OSKext::isKernelComponent(void) 3816 { 3817 return flags.kernelComponent ? true : false; 3818 } 3819 3820 /********************************************************************* 3821 *********************************************************************/ 3822 bool 3823 OSKext::isExecutable(void) 3824 { 3825 return (!isKernel() && !isInterface() && declaresExecutable()); 3826 } 3827 3828 /********************************************************************* 3829 * We might want to check this recursively for all dependencies, 3830 * since a subtree of dependencies could get loaded before we hit 3831 * a dependency that isn't safe-boot-loadable. 3832 * 3833 * xxx - Might want to return false if OSBundleEnableKextLogging or 3834 * OSBundleDebugLevel 3835 * or IOKitDebug is nonzero too (we used to do that, but I don't see 3836 * the point except it's usually development drivers, which might 3837 * cause panics on startup, that have those properties). Heh; could 3838 * use a "kx" boot-arg! 3839 *********************************************************************/ 3840 bool 3841 OSKext::isLoadableInSafeBoot(void) 3842 { 3843 bool result = false; 3844 OSString * required = NULL; // do not release 3845 3846 if (isKernel()) { 3847 result = true; 3848 goto finish; 3849 } 3850 3851 required = OSDynamicCast(OSString, 3852 getPropertyForHostArch(kOSBundleRequiredKey)); 3853 if (!required) { 3854 goto finish; 3855 } 3856 if (required->isEqualTo(kOSBundleRequiredRoot) || 3857 required->isEqualTo(kOSBundleRequiredLocalRoot) || 3858 required->isEqualTo(kOSBundleRequiredNetworkRoot) || 3859 required->isEqualTo(kOSBundleRequiredSafeBoot) || 3860 required->isEqualTo(kOSBundleRequiredConsole)) { 3861 3862 result = true; 3863 } 3864 3865 finish: 3866 return result; 3867 } 3868 3869 /********************************************************************* 3870 *********************************************************************/ 3871 bool 3872 OSKext::isPrelinked(void) 3873 { 3874 return flags.prelinked ? true : false; 3875 } 3876 3877 /********************************************************************* 3878 *********************************************************************/ 3879 bool OSKext::isLoaded(void) 3880 { 3881 return flags.loaded ? true : false; 3882 } 3883 3884 /********************************************************************* 3885 *********************************************************************/ 3886 bool 3887 OSKext::isStarted(void) 3888 { 3889 return flags.started ? true : false; 3890 } 3891 3892 /********************************************************************* 3893 *********************************************************************/ 3894 bool 3895 OSKext::isCPPInitialized(void) 3896 { 3897 return flags.CPPInitialized; 3898 } 3899 3900 /********************************************************************* 3901 *********************************************************************/ 3902 void 3903 OSKext::setCPPInitialized(bool initialized) 3904 { 3905 flags.CPPInitialized = initialized; 3906 } 3907 3908 /********************************************************************* 3909 *********************************************************************/ 3910 uint32_t 3911 OSKext::getLoadTag(void) 3912 { 3913 return loadTag; 3914 } 3915 3916 /********************************************************************* 3917 *********************************************************************/ 3918 void OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize) 3919 { 3920 if (linkedExecutable) { 3921 *loadSize = linkedExecutable->getLength(); 3922 3923 /* If we have a kmod_info struct, calculated the wired size 3924 * from that. Otherwise it's the full load size. 3925 */ 3926 if (kmod_info) { 3927 *wiredSize = *loadSize - kmod_info->hdr_size; 3928 } else { 3929 *wiredSize = *loadSize; 3930 } 3931 } 3932 else { 3933 *wiredSize = 0; 3934 *loadSize = 0; 3935 } 3936 } 3937 3938 /********************************************************************* 3939 *********************************************************************/ 3940 OSData * 3941 OSKext::copyUUID(void) 3942 { 3943 OSData * result = NULL; 3944 OSData * theExecutable = NULL; // do not release 3945 const kernel_mach_header_t * header = NULL; 3946 const struct load_command * load_cmd = NULL; 3947 const struct uuid_command * uuid_cmd = NULL; 3948 uint32_t i; 3949 3950 /* An interface kext doesn't have a linked executable with an LC_UUID, 3951 * we create one when it's linked. 3952 */ 3953 if (interfaceUUID) { 3954 result = interfaceUUID; 3955 result->retain(); 3956 goto finish; 3957 } 3958 3959 /* For real kexts, try to get the UUID from the linked executable, 3960 * or if is hasn't been linked yet, the unrelocated executable. 3961 */ 3962 theExecutable = linkedExecutable; 3963 if (!theExecutable) { 3964 theExecutable = getExecutable(); 3965 } 3966 if (!theExecutable) { 3967 goto finish; 3968 } 3969 3970 header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy(); 3971 load_cmd = (const struct load_command *)&header[1]; 3972 3973 if (header->magic != MH_MAGIC_KERNEL) { 3974 OSKextLog(NULL, 3975 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 3976 "%s: bad header %p", 3977 __func__, 3978 header); 3979 goto finish; 3980 } 3981 3982 for (i = 0; i < header->ncmds; i++) { 3983 if (load_cmd->cmd == LC_UUID) { 3984 uuid_cmd = (struct uuid_command *)load_cmd; 3985 result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid)); 3986 goto finish; 3987 } 3988 load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize); 3989 } 3990 3991 finish: 3992 return result; 3993 } 3994 3995 /********************************************************************* 3996 *********************************************************************/ 3997 3998 #if defined (__x86_64__) 3999 #define ARCHNAME "x86_64" 4000 #else 4001 #error architecture not supported 4002 #endif 4003 4004 #define ARCH_SEPARATOR_CHAR '_' 4005 4006 static char * makeHostArchKey(const char * key, uint32_t * keySizeOut) 4007 { 4008 char * result = NULL; 4009 uint32_t keyLength = strlen(key); 4010 uint32_t keySize; 4011 4012 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'. 4013 */ 4014 keySize = 1 + 1 + strlen(key) + strlen(ARCHNAME); 4015 result = (char *)kalloc_tag(keySize, VM_KERN_MEMORY_OSKEXT); 4016 if (!result) { 4017 goto finish; 4018 } 4019 strlcpy(result, key, keySize); 4020 result[keyLength++] = ARCH_SEPARATOR_CHAR; 4021 result[keyLength] = '\0'; 4022 strlcat(result, ARCHNAME, keySize); 4023 *keySizeOut = keySize; 4024 4025 finish: 4026 return result; 4027 } 4028 4029 /********************************************************************* 4030 *********************************************************************/ 4031 OSObject * 4032 OSKext::getPropertyForHostArch(const char * key) 4033 { 4034 OSObject * result = NULL; // do not release 4035 uint32_t hostArchKeySize = 0; 4036 char * hostArchKey = NULL; // must kfree 4037 4038 if (!key || !infoDict) { 4039 goto finish; 4040 } 4041 4042 /* Some properties are not allowed to be arch-variant: 4043 * - Any CFBundle... property. 4044 * - OSBundleIsInterface. 4045 * - OSKernelResource. 4046 */ 4047 if (STRING_HAS_PREFIX(key, "OS") || 4048 STRING_HAS_PREFIX(key, "IO")) { 4049 4050 hostArchKey = makeHostArchKey(key, &hostArchKeySize); 4051 if (!hostArchKey) { 4052 OSKextLog(/* kext (this isn't about a kext) */ NULL, 4053 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4054 "Allocation failure."); 4055 goto finish; 4056 } 4057 result = infoDict->getObject(hostArchKey); 4058 } 4059 4060 if (!result) { 4061 result = infoDict->getObject(key); 4062 } 4063 4064 finish: 4065 if (hostArchKey) kfree(hostArchKey, hostArchKeySize); 4066 return result; 4067 } 4068 4069 #if PRAGMA_MARK 4070 #pragma mark Load/Start/Stop/Unload 4071 #endif 4072 4073 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n') 4074 4075 /********************************************************************* 4076 * sExcludeListByID is a dictionary with keys / values of: 4077 * key = bundleID string of kext we will not allow to load 4078 * value = version string(s) of the kext that is to be denied loading. 4079 * The version strings can be comma delimited. For example if kext 4080 * com.foocompany.fookext has two versions that we want to deny 4081 * loading then the version strings might look like: 4082 * 1.0.0, 1.0.1 4083 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will 4084 * not load the kext. 4085 * 4086 * Value may also be in the form of "LE 2.0.0" (version numbers 4087 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version 4088 * number less than 2.0.0 will not load) 4089 * 4090 * NOTE - we cannot use the characters "<=" or "<" because we have code 4091 * that serializes plists and treats '<' as a special character. 4092 *********************************************************************/ 4093 bool 4094 OSKext::isInExcludeList(void) 4095 { 4096 OSString * versionString = NULL; // do not release 4097 char * versionCString = NULL; // do not free 4098 size_t i; 4099 boolean_t wantLessThan = false; 4100 boolean_t wantLessThanEqualTo = false; 4101 char myBuffer[32]; 4102 4103 if (!sExcludeListByID) { 4104 return(false); 4105 } 4106 /* look up by bundleID in our exclude list and if found get version 4107 * string (or strings) that we will not allow to load 4108 */ 4109 versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID)); 4110 if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) { 4111 return(false); 4112 } 4113 4114 /* parse version strings */ 4115 versionCString = (char *) versionString->getCStringNoCopy(); 4116 4117 /* look for "LT" or "LE" form of version string, must be in first two 4118 * positions. 4119 */ 4120 if (*versionCString == 'L' && *(versionCString + 1) == 'T') { 4121 wantLessThan = true; 4122 versionCString +=2; 4123 } 4124 else if (*versionCString == 'L' && *(versionCString + 1) == 'E') { 4125 wantLessThanEqualTo = true; 4126 versionCString +=2; 4127 } 4128 4129 for (i = 0; *versionCString != 0x00; versionCString++) { 4130 /* skip whitespace */ 4131 if (isWhiteSpace(*versionCString)) { 4132 continue; 4133 } 4134 4135 /* peek ahead for version string separator or null terminator */ 4136 if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) { 4137 4138 /* OK, we have a version string */ 4139 myBuffer[i++] = *versionCString; 4140 myBuffer[i] = 0x00; 4141 4142 OSKextVersion excludeVers; 4143 excludeVers = OSKextParseVersionString(myBuffer); 4144 4145 if (wantLessThanEqualTo) { 4146 if (version <= excludeVers) { 4147 return(true); 4148 } 4149 } 4150 else if (wantLessThan) { 4151 if (version < excludeVers) { 4152 return(true); 4153 } 4154 } 4155 else if ( version == excludeVers ) { 4156 return(true); 4157 } 4158 4159 /* reset for the next (if any) version string */ 4160 i = 0; 4161 wantLessThan = false; 4162 wantLessThanEqualTo = false; 4163 } 4164 else { 4165 /* save valid version character */ 4166 myBuffer[i++] = *versionCString; 4167 4168 /* make sure bogus version string doesn't overrun local buffer */ 4169 if ( i >= sizeof(myBuffer) ) { 4170 break; 4171 } 4172 } 4173 } 4174 4175 return(false); 4176 } 4177 4178 /********************************************************************* 4179 *********************************************************************/ 4180 /* static */ 4181 OSReturn 4182 OSKext::loadKextWithIdentifier( 4183 const char * kextIdentifierCString, 4184 Boolean allowDeferFlag, 4185 Boolean delayAutounloadFlag, 4186 OSKextExcludeLevel startOpt, 4187 OSKextExcludeLevel startMatchingOpt, 4188 OSArray * personalityNames) 4189 { 4190 OSReturn result = kOSReturnError; 4191 OSString * kextIdentifier = NULL; // must release 4192 4193 kextIdentifier = OSString::withCString(kextIdentifierCString); 4194 if (!kextIdentifier) { 4195 result = kOSKextReturnNoMemory; 4196 goto finish; 4197 } 4198 result = OSKext::loadKextWithIdentifier(kextIdentifier, 4199 allowDeferFlag, delayAutounloadFlag, 4200 startOpt, startMatchingOpt, personalityNames); 4201 4202 finish: 4203 OSSafeRelease(kextIdentifier); 4204 return result; 4205 } 4206 4207 /********************************************************************* 4208 *********************************************************************/ 4209 OSReturn 4210 OSKext::loadKextWithIdentifier( 4211 OSString * kextIdentifier, 4212 Boolean allowDeferFlag, 4213 Boolean delayAutounloadFlag, 4214 OSKextExcludeLevel startOpt, 4215 OSKextExcludeLevel startMatchingOpt, 4216 OSArray * personalityNames) 4217 { 4218 OSReturn result = kOSReturnError; 4219 OSReturn pingResult = kOSReturnError; 4220 OSKext * theKext = NULL; // do not release 4221 OSDictionary * loadRequest = NULL; // must release 4222 const OSSymbol * kextIdentifierSymbol = NULL; // must release 4223 4224 IORecursiveLockLock(sKextLock); 4225 4226 if (!kextIdentifier) { 4227 result = kOSKextReturnInvalidArgument; 4228 goto finish; 4229 } 4230 4231 OSKext::recordIdentifierRequest(kextIdentifier); 4232 4233 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 4234 if (!theKext) { 4235 if (!allowDeferFlag) { 4236 OSKextLog(/* kext */ NULL, 4237 kOSKextLogErrorLevel | 4238 kOSKextLogLoadFlag, 4239 "Can't load kext %s - not found.", 4240 kextIdentifier->getCStringNoCopy()); 4241 goto finish; 4242 } 4243 4244 if (!sKernelRequestsEnabled) { 4245 OSKextLog(theKext, 4246 kOSKextLogErrorLevel | 4247 kOSKextLogLoadFlag, 4248 "Can't load kext %s - requests to user space are disabled.", 4249 kextIdentifier->getCStringNoCopy()); 4250 result = kOSKextReturnDisabled; 4251 goto finish; 4252 } 4253 4254 /* Create a new request unless one is already sitting 4255 * in sKernelRequests for this bundle identifier 4256 */ 4257 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 4258 if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) { 4259 result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad, 4260 &loadRequest); 4261 if (result != kOSReturnSuccess) { 4262 goto finish; 4263 } 4264 if (!_OSKextSetRequestArgument(loadRequest, 4265 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 4266 4267 result = kOSKextReturnNoMemory; 4268 goto finish; 4269 } 4270 if (!sKernelRequests->setObject(loadRequest)) { 4271 result = kOSKextReturnNoMemory; 4272 goto finish; 4273 } 4274 4275 if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol)) { 4276 result = kOSKextReturnNoMemory; 4277 goto finish; 4278 } 4279 4280 OSKextLog(theKext, 4281 kOSKextLogDebugLevel | 4282 kOSKextLogLoadFlag, 4283 "Kext %s not found; queued load request to user space.", 4284 kextIdentifier->getCStringNoCopy()); 4285 } 4286 4287 pingResult = OSKext::pingKextd(); 4288 if (pingResult == kOSKextReturnDisabled) { 4289 OSKextLog(/* kext */ NULL, 4290 ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) | 4291 kOSKextLogLoadFlag, 4292 "Kext %s might not load - kextd is currently unavailable.", 4293 kextIdentifier->getCStringNoCopy()); 4294 } 4295 4296 result = kOSKextReturnDeferred; 4297 goto finish; 4298 } 4299 4300 result = theKext->load(startOpt, startMatchingOpt, personalityNames); 4301 4302 if (result != kOSReturnSuccess) { 4303 OSKextLog(theKext, 4304 kOSKextLogErrorLevel | 4305 kOSKextLogLoadFlag, 4306 "Failed to load kext %s (error 0x%x).", 4307 kextIdentifier->getCStringNoCopy(), (int)result); 4308 4309 OSKext::removeKext(theKext, 4310 /* terminateService/removePersonalities */ true); 4311 goto finish; 4312 } 4313 4314 if (delayAutounloadFlag) { 4315 OSKextLog(theKext, 4316 kOSKextLogProgressLevel | 4317 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 4318 "Setting delayed autounload for %s.", 4319 kextIdentifier->getCStringNoCopy()); 4320 theKext->flags.delayAutounload = 1; 4321 } 4322 4323 finish: 4324 OSSafeRelease(loadRequest); 4325 OSSafeRelease(kextIdentifierSymbol); 4326 4327 IORecursiveLockUnlock(sKextLock); 4328 4329 return result; 4330 } 4331 4332 /********************************************************************* 4333 *********************************************************************/ 4334 /* static */ 4335 void 4336 OSKext::recordIdentifierRequest( 4337 OSString * kextIdentifier) 4338 { 4339 const OSSymbol * kextIdentifierSymbol = NULL; // must release 4340 bool fail = false; 4341 4342 if (!sAllKextLoadIdentifiers || !kextIdentifier) { 4343 goto finish; 4344 } 4345 4346 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 4347 if (!kextIdentifierSymbol) { 4348 // xxx - this is really a basic alloc failure 4349 fail = true; 4350 goto finish; 4351 } 4352 4353 if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) { 4354 if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol)) { 4355 fail = true; 4356 } else { 4357 // xxx - need to find a way to associate this whole func w/the kext 4358 OSKextLog(/* kext */ NULL, 4359 // xxx - check level 4360 kOSKextLogStepLevel | 4361 kOSKextLogArchiveFlag, 4362 "Recorded kext %s as a candidate for inclusion in prelinked kernel.", 4363 kextIdentifier->getCStringNoCopy()); 4364 } 4365 } 4366 finish: 4367 4368 if (fail) { 4369 OSKextLog(/* kext */ NULL, 4370 kOSKextLogErrorLevel | 4371 kOSKextLogArchiveFlag, 4372 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.", 4373 kextIdentifier->getCStringNoCopy()); 4374 } 4375 OSSafeRelease(kextIdentifierSymbol); 4376 return; 4377 } 4378 4379 /********************************************************************* 4380 *********************************************************************/ 4381 OSReturn 4382 OSKext::load( 4383 OSKextExcludeLevel startOpt, 4384 OSKextExcludeLevel startMatchingOpt, 4385 OSArray * personalityNames) 4386 { 4387 OSReturn result = kOSReturnError; 4388 kern_return_t kxldResult; 4389 OSKextExcludeLevel dependenciesStartOpt = startOpt; 4390 OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt; 4391 unsigned int i, count; 4392 Boolean alreadyLoaded = false; 4393 OSKext * lastLoadedKext = NULL; 4394 4395 if (isInExcludeList()) { 4396 OSKextLog(this, 4397 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | 4398 kOSKextLogLoadFlag, 4399 "Kext %s is in exclude list, not loadable", 4400 getIdentifierCString()); 4401 4402 result = kOSKextReturnNotLoadable; 4403 goto finish; 4404 } 4405 4406 if (isLoaded()) { 4407 alreadyLoaded = true; 4408 result = kOSReturnSuccess; 4409 4410 OSKextLog(this, 4411 kOSKextLogDebugLevel | 4412 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 4413 "Kext %s is already loaded.", 4414 getIdentifierCString()); 4415 goto loaded; 4416 } 4417 4418 #if CONFIG_MACF 4419 if (current_task() != kernel_task) { 4420 int macCheckResult = 0; 4421 kauth_cred_t cred = NULL; 4422 4423 cred = kauth_cred_get_with_ref(); 4424 macCheckResult = mac_kext_check_load(cred, getIdentifierCString()); 4425 kauth_cred_unref(&cred); 4426 4427 if (macCheckResult != 0) { 4428 result = kOSReturnError; 4429 OSKextLog(this, 4430 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 4431 "Failed to load kext %s (MAC policy error 0x%x).", 4432 getIdentifierCString(), macCheckResult); 4433 goto finish; 4434 } 4435 } 4436 #endif 4437 4438 if (!sLoadEnabled) { 4439 OSKextLog(this, 4440 kOSKextLogErrorLevel | 4441 kOSKextLogLoadFlag, 4442 "Kext loading is disabled (attempt to load kext %s).", 4443 getIdentifierCString()); 4444 result = kOSKextReturnDisabled; 4445 goto finish; 4446 } 4447 4448 /* If we've pushed the next available load tag to the invalid value, 4449 * we can't load any more kexts. 4450 */ 4451 if (sNextLoadTag == kOSKextInvalidLoadTag) { 4452 OSKextLog(this, 4453 kOSKextLogErrorLevel | 4454 kOSKextLogLoadFlag, 4455 "Can't load kext %s - no more load tags to assign.", 4456 getIdentifierCString()); 4457 result = kOSKextReturnNoResources; 4458 goto finish; 4459 } 4460 4461 /* This is a bit of a hack, because we shouldn't be handling 4462 * personalities within the load function. 4463 */ 4464 if (!declaresExecutable()) { 4465 result = kOSReturnSuccess; 4466 goto loaded; 4467 } 4468 4469 /* Are we in safe boot? 4470 */ 4471 if (sSafeBoot && !isLoadableInSafeBoot()) { 4472 OSKextLog(this, 4473 kOSKextLogErrorLevel | 4474 kOSKextLogLoadFlag, 4475 "Can't load kext %s - not loadable during safe boot.", 4476 getIdentifierCString()); 4477 result = kOSKextReturnBootLevel; 4478 goto finish; 4479 } 4480 4481 OSKextLog(this, 4482 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 4483 "Loading kext %s.", 4484 getIdentifierCString()); 4485 4486 if (!sKxldContext) { 4487 kxldResult = kxld_create_context(&sKxldContext, &kern_allocate, 4488 &kxld_log_callback, /* Flags */ (KXLDFlags) 0, 4489 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0); 4490 if (kxldResult) { 4491 OSKextLog(this, 4492 kOSKextLogErrorLevel | 4493 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 4494 "Can't load kext %s - failed to create link context.", 4495 getIdentifierCString()); 4496 result = kOSKextReturnNoMemory; 4497 goto finish; 4498 } 4499 } 4500 4501 /* We only need to resolve dependencies once for the whole graph, but 4502 * resolveDependencies will just return if there's no work to do, so it's 4503 * safe to call it more than once. 4504 */ 4505 if (!resolveDependencies()) { 4506 // xxx - check resolveDependencies() for log msg 4507 OSKextLog(this, 4508 kOSKextLogErrorLevel | 4509 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 4510 "Can't load kext %s - failed to resolve library dependencies.", 4511 getIdentifierCString()); 4512 result = kOSKextReturnDependencies; 4513 goto finish; 4514 } 4515 4516 /* If we are excluding just the kext being loaded now (and not its 4517 * dependencies), drop the exclusion level to none so dependencies 4518 * start and/or add their personalities. 4519 */ 4520 if (dependenciesStartOpt == kOSKextExcludeKext) { 4521 dependenciesStartOpt = kOSKextExcludeNone; 4522 } 4523 4524 if (dependenciesStartMatchingOpt == kOSKextExcludeKext) { 4525 dependenciesStartMatchingOpt = kOSKextExcludeNone; 4526 } 4527 4528 /* Load the dependencies, recursively. 4529 */ 4530 count = getNumDependencies(); 4531 for (i = 0; i < count; i++) { 4532 OSKext * dependency = OSDynamicCast(OSKext, 4533 dependencies->getObject(i)); 4534 if (dependency == NULL) { 4535 OSKextLog(this, 4536 kOSKextLogErrorLevel | 4537 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 4538 "Internal error loading kext %s; dependency disappeared.", 4539 getIdentifierCString()); 4540 result = kOSKextReturnInternalError; 4541 goto finish; 4542 } 4543 4544 /* Dependencies must be started accorting to the opt, 4545 * but not given the personality names of the main kext. 4546 */ 4547 result = dependency->load(dependenciesStartOpt, 4548 dependenciesStartMatchingOpt, 4549 /* personalityNames */ NULL); 4550 if (result != KERN_SUCCESS) { 4551 OSKextLog(this, 4552 kOSKextLogErrorLevel | 4553 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 4554 "Dependency %s of kext %s failed to load.", 4555 dependency->getIdentifierCString(), 4556 getIdentifierCString()); 4557 4558 OSKext::removeKext(dependency, 4559 /* terminateService/removePersonalities */ true); 4560 result = kOSKextReturnDependencyLoadError; 4561 4562 goto finish; 4563 } 4564 } 4565 4566 result = loadExecutable(); 4567 if (result != KERN_SUCCESS) { 4568 goto finish; 4569 } 4570 4571 pendingPgoHead.next = &pendingPgoHead; 4572 pendingPgoHead.prev = &pendingPgoHead; 4573 4574 uuid_generate(instance_uuid); 4575 account = IONew(OSKextAccount, 1); 4576 if (!account) { 4577 result = KERN_MEMORY_ERROR; 4578 goto finish; 4579 } 4580 bzero(account, sizeof(*account)); 4581 account->loadTag = kmod_info->id; 4582 account->site.flags = VM_TAG_KMOD; 4583 4584 flags.loaded = true; 4585 4586 /* Add the kext to the list of loaded kexts and update the kmod_info 4587 * struct to point to that of the last loaded kext (which is the way 4588 * it's always been done, though I'd rather do them in order now). 4589 */ 4590 lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 4591 sLoadedKexts->setObject(this); 4592 4593 /* Keep the kernel itself out of the kmod list. 4594 */ 4595 if (lastLoadedKext->isKernel()) { 4596 lastLoadedKext = NULL; 4597 } 4598 4599 if (lastLoadedKext) { 4600 kmod_info->next = lastLoadedKext->kmod_info; 4601 } 4602 4603 notifyKextLoadObservers(this, kmod_info); 4604 4605 /* Make the global kmod list point at the just-loaded kext. Note that the 4606 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard, 4607 * although we do report it in kextstat these days by using the newer 4608 * OSArray of loaded kexts, which does contain it. 4609 * 4610 * (The OSKext object representing the kernel doesn't even have a kmod_info 4611 * struct, though I suppose we could stick a pointer to it from the 4612 * static struct in OSRuntime.cpp.) 4613 */ 4614 kmod = kmod_info; 4615 4616 /* Save the list of loaded kexts in case we panic. 4617 */ 4618 OSKext::saveLoadedKextPanicList(); 4619 4620 if (isExecutable()) { 4621 OSKext::updateLoadedKextSummaries(); 4622 savePanicString(/* isLoading */ true); 4623 4624 #if CONFIG_DTRACE 4625 registerWithDTrace(); 4626 #else 4627 jettisonLinkeditSegment(); 4628 #endif /* CONFIG_DTRACE */ 4629 4630 #if !VM_MAPPED_KEXTS 4631 /* If there is a page (or more) worth of padding after the end 4632 * of the last data section but before the end of the data segment 4633 * then free it in the same manner the LinkeditSegment is freed 4634 */ 4635 jettisonDATASegmentPadding(); 4636 #endif 4637 } 4638 4639 loaded: 4640 if (isExecutable() && !flags.started) { 4641 if (startOpt == kOSKextExcludeNone) { 4642 result = start(); 4643 if (result != kOSReturnSuccess) { 4644 OSKextLog(this, 4645 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 4646 "Kext %s start failed (result 0x%x).", 4647 getIdentifierCString(), result); 4648 result = kOSKextReturnStartStopError; 4649 } 4650 } 4651 } 4652 4653 /* If not excluding matching, send the personalities to the kernel. 4654 * This never affects the result of the load operation. 4655 * This is a bit of a hack, because we shouldn't be handling 4656 * personalities within the load function. 4657 */ 4658 if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) { 4659 result = sendPersonalitiesToCatalog(true, personalityNames); 4660 } 4661 4662 finish: 4663 4664 /* More hack! If the kext doesn't declare an executable, even if we 4665 * "loaded" it, we have to remove any personalities naming it, or we'll 4666 * never see the registry go quiet. Errors here do not count for the 4667 * load operation itself. 4668 * 4669 * Note that in every other regard it's perfectly ok for a kext to 4670 * not declare an executable and serve only as a package for personalities 4671 * naming another kext, so we do have to allow such kexts to be "loaded" 4672 * so that those other personalities get added & matched. 4673 */ 4674 if (!declaresExecutable()) { 4675 OSKextLog(this, 4676 kOSKextLogStepLevel | kOSKextLogLoadFlag, 4677 "Kext %s has no executable; removing any personalities naming it.", 4678 getIdentifierCString()); 4679 removePersonalitiesFromCatalog(); 4680 } 4681 4682 if (result != kOSReturnSuccess) { 4683 OSKextLog(this, 4684 kOSKextLogErrorLevel | 4685 kOSKextLogLoadFlag, 4686 "Kext %s failed to load (0x%x).", 4687 getIdentifierCString(), (int)result); 4688 } else if (!alreadyLoaded) { 4689 OSKextLog(this, 4690 kOSKextLogProgressLevel | 4691 kOSKextLogLoadFlag, 4692 "Kext %s loaded.", 4693 getIdentifierCString()); 4694 4695 queueKextNotification(kKextRequestPredicateLoadNotification, 4696 OSDynamicCast(OSString, bundleID)); 4697 } 4698 return result; 4699 } 4700 4701 /********************************************************************* 4702 * 4703 *********************************************************************/ 4704 static char * strdup(const char * string) 4705 { 4706 char * result = NULL; 4707 size_t size; 4708 4709 if (!string) { 4710 goto finish; 4711 } 4712 4713 size = 1 + strlen(string); 4714 result = (char *)kalloc_tag(size, VM_KERN_MEMORY_OSKEXT); 4715 if (!result) { 4716 goto finish; 4717 } 4718 4719 memcpy(result, string, size); 4720 4721 finish: 4722 return result; 4723 } 4724 4725 /********************************************************************* 4726 * 4727 *********************************************************************/ 4728 4729 kernel_section_t * 4730 OSKext::lookupSection(const char *segname, const char *secname) 4731 { 4732 kernel_section_t * found_section = NULL; 4733 kernel_mach_header_t * mh = NULL; 4734 kernel_segment_command_t * seg = NULL; 4735 kernel_section_t * sec = NULL; 4736 4737 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 4738 4739 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 4740 4741 if (0 != strcmp(seg->segname, segname)) { 4742 continue; 4743 } 4744 4745 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 4746 4747 if (0 == strcmp(sec->sectname, secname)) { 4748 found_section = sec; 4749 goto out; 4750 } 4751 } 4752 } 4753 4754 out: 4755 return found_section; 4756 } 4757 4758 /********************************************************************* 4759 * 4760 *********************************************************************/ 4761 4762 OSReturn 4763 OSKext::slidePrelinkedExecutable() 4764 { 4765 OSReturn result = kOSKextReturnBadData; 4766 kernel_mach_header_t * mh = NULL; 4767 kernel_segment_command_t * seg = NULL; 4768 kernel_segment_command_t * linkeditSeg = NULL; 4769 kernel_section_t * sec = NULL; 4770 char * linkeditBase = NULL; 4771 bool haveLinkeditBase = false; 4772 char * relocBase = NULL; 4773 bool haveRelocBase = false; 4774 struct dysymtab_command * dysymtab = NULL; 4775 struct symtab_command * symtab = NULL; 4776 kernel_nlist_t * sym = NULL; 4777 struct relocation_info * reloc = NULL; 4778 uint32_t i = 0; 4779 int reloc_size; 4780 vm_offset_t new_kextsize; 4781 4782 if (linkedExecutable == NULL || vm_kernel_slide == 0) { 4783 result = kOSReturnSuccess; 4784 goto finish; 4785 } 4786 4787 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 4788 4789 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 4790 if (!seg->vmaddr) { 4791 continue; 4792 } 4793 seg->vmaddr += vm_kernel_slide; 4794 4795 #if KASLR_KEXT_DEBUG 4796 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n", 4797 seg->segname, 4798 (unsigned long)VM_KERNEL_UNSLIDE(seg->vmaddr), 4799 (unsigned long)seg->vmaddr); 4800 #endif 4801 4802 if (!haveRelocBase) { 4803 relocBase = (char *) seg->vmaddr; 4804 haveRelocBase = true; 4805 } 4806 if (!strcmp(seg->segname, "__LINKEDIT")) { 4807 linkeditBase = (char *) seg->vmaddr - seg->fileoff; 4808 haveLinkeditBase = true; 4809 linkeditSeg = seg; 4810 } 4811 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 4812 sec->addr += vm_kernel_slide; 4813 4814 #if KASLR_KEXT_DEBUG 4815 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n", 4816 sec->sectname, 4817 (unsigned long)VM_KERNEL_UNSLIDE(sec->addr), 4818 (unsigned long)sec->addr); 4819 #endif 4820 } 4821 } 4822 4823 dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB); 4824 4825 symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB); 4826 4827 if (symtab != NULL) { 4828 /* Some pseudo-kexts have symbol tables without segments. 4829 * Ignore them. */ 4830 if (symtab->nsyms > 0 && haveLinkeditBase) { 4831 sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff); 4832 for (i = 0; i < symtab->nsyms; i++) { 4833 if (sym[i].n_type & N_STAB) { 4834 continue; 4835 } 4836 sym[i].n_value += vm_kernel_slide; 4837 4838 #if KASLR_KEXT_DEBUG 4839 #define MAX_SYMS_TO_LOG 5 4840 if ( i < MAX_SYMS_TO_LOG ) { 4841 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n", 4842 (unsigned long)VM_KERNEL_UNSLIDE(sym[i].n_value), 4843 (unsigned long)sym[i].n_value); 4844 } 4845 #endif 4846 } 4847 } 4848 } 4849 4850 if (dysymtab != NULL) { 4851 if (dysymtab->nextrel > 0) { 4852 OSKextLog(this, 4853 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 4854 kOSKextLogLinkFlag, 4855 "Sliding kext %s: External relocations found.", 4856 getIdentifierCString()); 4857 goto finish; 4858 } 4859 4860 if (dysymtab->nlocrel > 0) { 4861 if (!haveLinkeditBase) { 4862 OSKextLog(this, 4863 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 4864 kOSKextLogLinkFlag, 4865 "Sliding kext %s: No linkedit segment.", 4866 getIdentifierCString()); 4867 goto finish; 4868 } 4869 4870 if (!haveRelocBase) { 4871 OSKextLog(this, 4872 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 4873 kOSKextLogLinkFlag, 4874 #if __x86_64__ 4875 "Sliding kext %s: No writable segments.", 4876 #else 4877 "Sliding kext %s: No segments.", 4878 #endif 4879 getIdentifierCString()); 4880 goto finish; 4881 } 4882 4883 reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff); 4884 reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info); 4885 4886 for (i = 0; i < dysymtab->nlocrel; i++) { 4887 if ( reloc[i].r_extern != 0 4888 || reloc[i].r_type != 0 4889 || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2) 4890 ) { 4891 OSKextLog(this, 4892 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 4893 kOSKextLogLinkFlag, 4894 "Sliding kext %s: Unexpected relocation found.", 4895 getIdentifierCString()); 4896 goto finish; 4897 } 4898 if (reloc[i].r_pcrel != 0) { 4899 continue; 4900 } 4901 *((uintptr_t *)(relocBase + reloc[i].r_address)) += vm_kernel_slide; 4902 4903 #if KASLR_KEXT_DEBUG 4904 #define MAX_DYSYMS_TO_LOG 5 4905 if ( i < MAX_DYSYMS_TO_LOG ) { 4906 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n", 4907 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase + reloc[i].r_address))), 4908 (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address))); 4909 } 4910 #endif 4911 } 4912 4913 /* We should free these relocations, not just delete the reference to them. 4914 * <rdar://problem/10535549> Free relocations from PIE kexts. 4915 */ 4916 new_kextsize = round_page(kmod_info->size - reloc_size); 4917 4918 if ((kmod_info->size - new_kextsize) > PAGE_SIZE) { 4919 vm_offset_t endofkext = kmod_info->address + kmod_info->size; 4920 vm_offset_t new_endofkext = kmod_info->address + new_kextsize; 4921 vm_offset_t endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size); 4922 int bytes_remaining = endofkext - endofrelocInfo; 4923 OSData * new_osdata = NULL; 4924 4925 /* fix up symbol offsets if they are after the dsymtab local relocs */ 4926 if (symtab) { 4927 if (dysymtab->locreloff < symtab->symoff){ 4928 symtab->symoff -= reloc_size; 4929 } 4930 if (dysymtab->locreloff < symtab->stroff) { 4931 symtab->stroff -= reloc_size; 4932 } 4933 } 4934 if (dysymtab->locreloff < dysymtab->extreloff) { 4935 dysymtab->extreloff -= reloc_size; 4936 } 4937 4938 /* move data behind reloc info down to new offset */ 4939 if (endofrelocInfo < endofkext) { 4940 memcpy(reloc, (void *)endofrelocInfo, bytes_remaining); 4941 } 4942 4943 /* Create a new OSData for the smaller kext object and reflect 4944 * new linkedit segment size. 4945 */ 4946 linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size); 4947 linkeditSeg->filesize = linkeditSeg->vmsize; 4948 4949 new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, new_kextsize); 4950 if (new_osdata) { 4951 /* Fix up kmod info and linkedExecutable. 4952 */ 4953 kmod_info->size = new_kextsize; 4954 #if VM_MAPPED_KEXTS 4955 new_osdata->setDeallocFunction(osdata_kext_free); 4956 #else 4957 new_osdata->setDeallocFunction(osdata_phys_free); 4958 #endif 4959 linkedExecutable->setDeallocFunction(NULL); 4960 linkedExecutable->release(); 4961 linkedExecutable = new_osdata; 4962 4963 #if VM_MAPPED_KEXTS 4964 kext_free(new_endofkext, (endofkext - new_endofkext)); 4965 #else 4966 ml_static_mfree(new_endofkext, (endofkext - new_endofkext)); 4967 #endif 4968 } 4969 } 4970 dysymtab->nlocrel = 0; 4971 dysymtab->locreloff = 0; 4972 } 4973 } 4974 4975 result = kOSReturnSuccess; 4976 finish: 4977 return result; 4978 } 4979 4980 /********************************************************************* 4981 * called only by load() 4982 *********************************************************************/ 4983 OSReturn 4984 OSKext::loadExecutable() 4985 { 4986 OSReturn result = kOSReturnError; 4987 kern_return_t kxldResult; 4988 KXLDDependency * kxlddeps = NULL; // must kfree 4989 uint32_t num_kxlddeps = 0; 4990 OSArray * linkDependencies = NULL; // must release 4991 uint32_t numDirectDependencies = 0; 4992 uint32_t num_kmod_refs = 0; 4993 struct mach_header ** kxldHeaderPtr = NULL; // do not free 4994 struct mach_header * kxld_header = NULL; // xxx - need to free here? 4995 OSData * theExecutable = NULL; // do not release 4996 OSString * versString = NULL; // do not release 4997 const char * versCString = NULL; // do not free 4998 const char * string = NULL; // do not free 4999 unsigned int i; 5000 5001 /* We need the version string for a variety of bits below. 5002 */ 5003 versString = OSDynamicCast(OSString, 5004 getPropertyForHostArch(kCFBundleVersionKey)); 5005 if (!versString) { 5006 goto finish; 5007 } 5008 versCString = versString->getCStringNoCopy(); 5009 5010 if (isKernelComponent()) { 5011 if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) { 5012 5013 if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) { 5014 OSKextLog(this, 5015 kOSKextLogErrorLevel | 5016 kOSKextLogLoadFlag, 5017 "Kernel component %s has incorrect version %s; " 5018 "expected %s.", 5019 getIdentifierCString(), 5020 versCString, KERNEL6_VERSION); 5021 result = kOSKextReturnInternalError; 5022 goto finish; 5023 } else if (strcmp(versCString, osrelease)) { 5024 OSKextLog(this, 5025 kOSKextLogErrorLevel | 5026 kOSKextLogLoadFlag, 5027 "Kernel component %s has incorrect version %s; " 5028 "expected %s.", 5029 getIdentifierCString(), 5030 versCString, osrelease); 5031 result = kOSKextReturnInternalError; 5032 goto finish; 5033 } 5034 } 5035 } 5036 5037 if (isPrelinked()) { 5038 goto register_kmod; 5039 } 5040 5041 /* <rdar://problem/21444003> all callers must be entitled */ 5042 if (FALSE == IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management")) { 5043 OSKextLog(this, 5044 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5045 "Not entitled to link kext '%s'", 5046 getIdentifierCString()); 5047 result = kOSKextReturnNotPrivileged; 5048 goto finish; 5049 } 5050 5051 theExecutable = getExecutable(); 5052 if (!theExecutable) { 5053 if (declaresExecutable()) { 5054 OSKextLog(this, 5055 kOSKextLogErrorLevel | 5056 kOSKextLogLoadFlag, 5057 "Can't load kext %s - executable is missing.", 5058 getIdentifierCString()); 5059 result = kOSKextReturnValidation; 5060 goto finish; 5061 } 5062 goto register_kmod; 5063 } 5064 5065 if (isInterface()) { 5066 OSData *executableCopy = OSData::withData(theExecutable); 5067 setLinkedExecutable(executableCopy); 5068 executableCopy->release(); 5069 goto register_kmod; 5070 } 5071 5072 numDirectDependencies = getNumDependencies(); 5073 5074 if (flags.hasBleedthrough) { 5075 linkDependencies = dependencies; 5076 linkDependencies->retain(); 5077 } else { 5078 linkDependencies = OSArray::withArray(dependencies); 5079 if (!linkDependencies) { 5080 OSKextLog(this, 5081 kOSKextLogErrorLevel | 5082 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 5083 "Can't allocate link dependencies to load kext %s.", 5084 getIdentifierCString()); 5085 goto finish; 5086 } 5087 5088 for (i = 0; i < numDirectDependencies; ++i) { 5089 OSKext * dependencyKext = OSDynamicCast(OSKext, 5090 dependencies->getObject(i)); 5091 dependencyKext->addBleedthroughDependencies(linkDependencies); 5092 } 5093 } 5094 5095 num_kxlddeps = linkDependencies->getCount(); 5096 if (!num_kxlddeps) { 5097 OSKextLog(this, 5098 kOSKextLogErrorLevel | 5099 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 5100 "Can't load kext %s - it has no library dependencies.", 5101 getIdentifierCString()); 5102 goto finish; 5103 } 5104 5105 kxlddeps = (KXLDDependency *)kalloc_tag(num_kxlddeps * sizeof(*kxlddeps), VM_KERN_MEMORY_OSKEXT); 5106 if (!kxlddeps) { 5107 OSKextLog(this, 5108 kOSKextLogErrorLevel | 5109 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 5110 "Can't allocate link context to load kext %s.", 5111 getIdentifierCString()); 5112 goto finish; 5113 } 5114 bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps)); 5115 5116 for (i = 0; i < num_kxlddeps; ++i ) { 5117 OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i)); 5118 5119 if (dependency->isInterface()) { 5120 OSKext *interfaceTargetKext = NULL; 5121 OSData * interfaceTarget = NULL; 5122 5123 if (dependency->isKernelComponent()) { 5124 interfaceTargetKext = sKernelKext; 5125 interfaceTarget = sKernelKext->linkedExecutable; 5126 } else { 5127 interfaceTargetKext = OSDynamicCast(OSKext, 5128 dependency->dependencies->getObject(0)); 5129 5130 interfaceTarget = interfaceTargetKext->linkedExecutable; 5131 } 5132 5133 if (!interfaceTarget) { 5134 // panic? 5135 goto finish; 5136 } 5137 5138 /* The names set here aren't actually logged yet <rdar://problem/7941514>, 5139 * it will be useful to have them in the debugger. 5140 * strdup() failing isn't critical right here so we don't check that. 5141 */ 5142 kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy(); 5143 kxlddeps[i].kext_size = interfaceTarget->getLength(); 5144 kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString()); 5145 5146 kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 5147 kxlddeps[i].interface_size = dependency->linkedExecutable->getLength(); 5148 kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString()); 5149 } else { 5150 kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 5151 kxlddeps[i].kext_size = dependency->linkedExecutable->getLength(); 5152 kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString()); 5153 } 5154 5155 kxlddeps[i].is_direct_dependency = (i < numDirectDependencies); 5156 } 5157 5158 kxldHeaderPtr = &kxld_header; 5159 5160 #if DEBUG 5161 OSKextLog(this, 5162 kOSKextLogExplicitLevel | 5163 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 5164 "Kext %s - calling kxld_link_file:\n" 5165 " kxld_context: %p\n" 5166 " executable: %p executable_length: %d\n" 5167 " user_data: %p\n" 5168 " kxld_dependencies: %p num_dependencies: %d\n" 5169 " kxld_header_ptr: %p kmod_info_ptr: %p\n", 5170 getIdentifierCString(), sKxldContext, 5171 theExecutable->getBytesNoCopy(), theExecutable->getLength(), 5172 this, kxlddeps, num_kxlddeps, 5173 kxldHeaderPtr, &kmod_info); 5174 #endif 5175 5176 /* After this call, the linkedExecutable instance variable 5177 * should exist. 5178 */ 5179 kxldResult = kxld_link_file(sKxldContext, 5180 (u_char *)theExecutable->getBytesNoCopy(), 5181 theExecutable->getLength(), 5182 getIdentifierCString(), this, kxlddeps, num_kxlddeps, 5183 (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info); 5184 5185 if (kxldResult != KERN_SUCCESS) { 5186 // xxx - add kxldResult here? 5187 OSKextLog(this, 5188 kOSKextLogErrorLevel | 5189 kOSKextLogLoadFlag, 5190 "Can't load kext %s - link failed.", 5191 getIdentifierCString()); 5192 result = kOSKextReturnLinkError; 5193 goto finish; 5194 } 5195 5196 /* We've written data & instructions into kernel memory, so flush the data 5197 * cache and invalidate the instruction cache. 5198 * I/D caches are coherent on x86 5199 */ 5200 #if !defined(__i386__) && !defined(__x86_64__) 5201 flush_dcache(kmod_info->address, kmod_info->size, false); 5202 invalidate_icache(kmod_info->address, kmod_info->size, false); 5203 #endif 5204 register_kmod: 5205 5206 if (isInterface()) { 5207 5208 /* Whip up a fake kmod_info entry for the interface kext. 5209 */ 5210 kmod_info = (kmod_info_t *)kalloc_tag(sizeof(kmod_info_t), VM_KERN_MEMORY_OSKEXT); 5211 if (!kmod_info) { 5212 result = KERN_MEMORY_ERROR; 5213 goto finish; 5214 } 5215 5216 /* A pseudokext has almost nothing in its kmod_info struct. 5217 */ 5218 bzero(kmod_info, sizeof(kmod_info_t)); 5219 5220 kmod_info->info_version = KMOD_INFO_VERSION; 5221 5222 /* An interface kext doesn't have a linkedExecutable, so save a 5223 * copy of the UUID out of the original executable via copyUUID() 5224 * while we still have the original executable. 5225 */ 5226 interfaceUUID = copyUUID(); 5227 } 5228 5229 kmod_info->id = loadTag = sNextLoadTag++; 5230 kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid). 5231 5232 /* Stamp the bundle ID and version from the OSKext over anything 5233 * resident inside the kmod_info. 5234 */ 5235 string = getIdentifierCString(); 5236 strlcpy(kmod_info->name, string, sizeof(kmod_info->name)); 5237 5238 string = versCString; 5239 strlcpy(kmod_info->version, string, sizeof(kmod_info->version)); 5240 5241 /* Add the dependencies' kmod_info structs as kmod_references. 5242 */ 5243 num_kmod_refs = getNumDependencies(); 5244 if (num_kmod_refs) { 5245 kmod_info->reference_list = (kmod_reference_t *)kalloc_tag( 5246 num_kmod_refs * sizeof(kmod_reference_t), VM_KERN_MEMORY_OSKEXT); 5247 if (!kmod_info->reference_list) { 5248 result = KERN_MEMORY_ERROR; 5249 goto finish; 5250 } 5251 bzero(kmod_info->reference_list, 5252 num_kmod_refs * sizeof(kmod_reference_t)); 5253 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 5254 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 5255 OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex)); 5256 ref->info = refKext->kmod_info; 5257 ref->info->reference_count++; 5258 5259 if (refIndex + 1 < num_kmod_refs) { 5260 ref->next = kmod_info->reference_list + refIndex + 1; 5261 } 5262 } 5263 } 5264 5265 if (!isInterface() && linkedExecutable) { 5266 OSKextLog(this, 5267 kOSKextLogProgressLevel | 5268 kOSKextLogLoadFlag, 5269 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).", 5270 kmod_info->name, 5271 (unsigned)kmod_info->size / PAGE_SIZE, 5272 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info->address), 5273 (unsigned)kmod_info->id); 5274 } 5275 5276 /* if prelinked, VM protections are already set */ 5277 result = setVMAttributes(!isPrelinked(), true); 5278 if (result != KERN_SUCCESS) { 5279 goto finish; 5280 } 5281 5282 result = kOSReturnSuccess; 5283 5284 finish: 5285 OSSafeRelease(linkDependencies); 5286 5287 /* Clear up locally allocated dependency info. 5288 */ 5289 for (i = 0; i < num_kxlddeps; ++i ) { 5290 size_t size; 5291 5292 if (kxlddeps[i].kext_name) { 5293 size = 1 + strlen(kxlddeps[i].kext_name); 5294 kfree(kxlddeps[i].kext_name, size); 5295 } 5296 if (kxlddeps[i].interface_name) { 5297 size = 1 + strlen(kxlddeps[i].interface_name); 5298 kfree(kxlddeps[i].interface_name, size); 5299 } 5300 } 5301 if (kxlddeps) kfree(kxlddeps, (num_kxlddeps * sizeof(*kxlddeps))); 5302 5303 /* We no longer need the unrelocated executable (which the linker 5304 * has altered anyhow). 5305 */ 5306 setExecutable(NULL); 5307 5308 if (result != kOSReturnSuccess) { 5309 OSKextLog(this, 5310 kOSKextLogErrorLevel | 5311 kOSKextLogLoadFlag, 5312 "Failed to load executable for kext %s.", 5313 getIdentifierCString()); 5314 5315 if (kmod_info && kmod_info->reference_list) { 5316 kfree(kmod_info->reference_list, 5317 num_kmod_refs * sizeof(kmod_reference_t)); 5318 } 5319 if (isInterface()) { 5320 kfree(kmod_info, sizeof(kmod_info_t)); 5321 } 5322 kmod_info = NULL; 5323 if (linkedExecutable) { 5324 linkedExecutable->release(); 5325 linkedExecutable = NULL; 5326 } 5327 } 5328 5329 return result; 5330 } 5331 5332 /********************************************************************* 5333 * The linkedit segment is used by the kext linker for dependency 5334 * resolution, and by dtrace for probe initialization. We can free it 5335 * for non-library kexts, since no kexts depend on non-library kexts 5336 * by definition, once dtrace has been initialized. 5337 *********************************************************************/ 5338 void 5339 OSKext::jettisonLinkeditSegment(void) 5340 { 5341 kernel_mach_header_t * machhdr = (kernel_mach_header_t *)kmod_info->address; 5342 kernel_segment_command_t * linkedit = NULL; 5343 vm_offset_t start; 5344 vm_size_t linkeditsize, kextsize; 5345 OSData * data = NULL; 5346 5347 #if NO_KEXTD 5348 /* We can free symbol tables for all embedded kexts because we don't 5349 * support runtime kext linking. 5350 */ 5351 if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 5352 #else 5353 if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 5354 #endif 5355 goto finish; 5356 } 5357 5358 /* Find the linkedit segment. If it's not the last segment, then freeing 5359 * it will fragment the kext into multiple VM regions, which OSKext is not 5360 * designed to handle, so we'll have to skip it. 5361 */ 5362 linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT); 5363 if (!linkedit) { 5364 goto finish; 5365 } 5366 5367 if (round_page(kmod_info->address + kmod_info->size) != 5368 round_page(linkedit->vmaddr + linkedit->vmsize)) 5369 { 5370 goto finish; 5371 } 5372 5373 /* Create a new OSData for the smaller kext object. 5374 */ 5375 linkeditsize = round_page(linkedit->vmsize); 5376 kextsize = kmod_info->size - linkeditsize; 5377 start = linkedit->vmaddr; 5378 5379 data = OSData::withBytesNoCopy((void *)kmod_info->address, kextsize); 5380 if (!data) { 5381 goto finish; 5382 } 5383 5384 /* Fix the kmod info and linkedExecutable. 5385 */ 5386 kmod_info->size = kextsize; 5387 5388 #if VM_MAPPED_KEXTS 5389 data->setDeallocFunction(osdata_kext_free); 5390 #else 5391 data->setDeallocFunction(osdata_phys_free); 5392 #endif 5393 linkedExecutable->setDeallocFunction(NULL); 5394 linkedExecutable->release(); 5395 linkedExecutable = data; 5396 flags.jettisonLinkeditSeg = 1; 5397 5398 /* Free the linkedit segment. 5399 */ 5400 #if VM_MAPPED_KEXTS 5401 kext_free(start, linkeditsize); 5402 #else 5403 ml_static_mfree(start, linkeditsize); 5404 #endif 5405 5406 finish: 5407 return; 5408 } 5409 5410 /********************************************************************* 5411 * If there are whole pages that are unused betweem the last section 5412 * of the DATA segment and the end of the DATA segment then we can free 5413 * them 5414 *********************************************************************/ 5415 void 5416 OSKext::jettisonDATASegmentPadding(void) 5417 { 5418 kernel_mach_header_t * mh; 5419 kernel_segment_command_t * dataSeg; 5420 kernel_section_t * sec, * lastSec; 5421 vm_offset_t dataSegEnd, lastSecEnd; 5422 vm_size_t padSize; 5423 5424 mh = (kernel_mach_header_t *)kmod_info->address; 5425 5426 dataSeg = getsegbynamefromheader(mh, SEG_DATA); 5427 if (dataSeg == NULL) { 5428 return; 5429 } 5430 5431 lastSec = NULL; 5432 sec = firstsect(dataSeg); 5433 while (sec != NULL) { 5434 lastSec = sec; 5435 sec = nextsect(dataSeg, sec); 5436 } 5437 5438 if (lastSec == NULL) { 5439 return; 5440 } 5441 5442 if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) || 5443 (dataSeg->vmsize != round_page(dataSeg->vmsize))) { 5444 return; 5445 } 5446 5447 dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize; 5448 lastSecEnd = round_page(lastSec->addr + lastSec->size); 5449 5450 if (dataSegEnd <= lastSecEnd) { 5451 return; 5452 } 5453 5454 padSize = dataSegEnd - lastSecEnd; 5455 5456 if (padSize >= PAGE_SIZE) { 5457 #if VM_MAPPED_KEXTS 5458 kext_free(lastSecEnd, padSize); 5459 #else 5460 ml_static_mfree(lastSecEnd, padSize); 5461 #endif 5462 } 5463 } 5464 5465 /********************************************************************* 5466 *********************************************************************/ 5467 void 5468 OSKext::setLinkedExecutable(OSData * anExecutable) 5469 { 5470 if (linkedExecutable) { 5471 panic("Attempt to set linked executable on kext " 5472 "that already has one (%s).\n", 5473 getIdentifierCString()); 5474 } 5475 linkedExecutable = anExecutable; 5476 linkedExecutable->retain(); 5477 return; 5478 } 5479 5480 #if CONFIG_DTRACE 5481 /********************************************************************* 5482 * Go through all loaded kexts and tell them to register with dtrace. 5483 * The instance method only registers if necessary. 5484 *********************************************************************/ 5485 /* static */ 5486 void 5487 OSKext::registerKextsWithDTrace(void) 5488 { 5489 uint32_t count = sLoadedKexts->getCount(); 5490 uint32_t i; 5491 5492 IORecursiveLockLock(sKextLock); 5493 5494 for (i = 0; i < count; i++) { 5495 OSKext * thisKext = NULL; // do not release 5496 5497 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 5498 if (!thisKext || !thisKext->isExecutable()) { 5499 continue; 5500 } 5501 5502 thisKext->registerWithDTrace(); 5503 } 5504 5505 IORecursiveLockUnlock(sKextLock); 5506 5507 return; 5508 } 5509 5510 extern "C" { 5511 extern int (*dtrace_modload)(struct kmod_info *, uint32_t); 5512 extern int (*dtrace_modunload)(struct kmod_info *); 5513 }; 5514 5515 /********************************************************************* 5516 *********************************************************************/ 5517 void 5518 OSKext::registerWithDTrace(void) 5519 { 5520 /* Register kext with dtrace. A dtrace_modload failure should not 5521 * prevent a kext from loading, so we ignore the return code. 5522 */ 5523 if (!flags.dtraceInitialized && (dtrace_modload != NULL)) { 5524 uint32_t modflag = 0; 5525 OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit"); 5526 if (forceInit == kOSBooleanTrue) { 5527 modflag |= KMOD_DTRACE_FORCE_INIT; 5528 } 5529 5530 (void)(*dtrace_modload)(kmod_info, modflag); 5531 flags.dtraceInitialized = true; 5532 jettisonLinkeditSegment(); 5533 } 5534 return; 5535 } 5536 /********************************************************************* 5537 *********************************************************************/ 5538 void 5539 OSKext::unregisterWithDTrace(void) 5540 { 5541 /* Unregister kext with dtrace. A dtrace_modunload failure should not 5542 * prevent a kext from loading, so we ignore the return code. 5543 */ 5544 if (flags.dtraceInitialized && (dtrace_modunload != NULL)) { 5545 (void)(*dtrace_modunload)(kmod_info); 5546 flags.dtraceInitialized = false; 5547 } 5548 return; 5549 } 5550 #endif /* CONFIG_DTRACE */ 5551 5552 5553 /********************************************************************* 5554 * called only by loadExecutable() 5555 *********************************************************************/ 5556 #if !VM_MAPPED_KEXTS 5557 #error Unrecognized architecture 5558 #else 5559 static inline kern_return_t 5560 OSKext_protect( 5561 vm_map_t map, 5562 vm_map_offset_t start, 5563 vm_map_offset_t end, 5564 vm_prot_t new_prot, 5565 boolean_t set_max) 5566 { 5567 if (start == end) { // 10538581 5568 return(KERN_SUCCESS); 5569 } 5570 return vm_map_protect(map, start, end, new_prot, set_max); 5571 } 5572 5573 static inline kern_return_t 5574 OSKext_wire( 5575 vm_map_t map, 5576 vm_map_offset_t start, 5577 vm_map_offset_t end, 5578 vm_prot_t access_type, 5579 boolean_t user_wire) 5580 { 5581 return vm_map_wire(map, start, end, access_type | VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_KEXT), user_wire); 5582 } 5583 #endif 5584 5585 OSReturn 5586 OSKext::setVMAttributes(bool protect, bool wire) 5587 { 5588 vm_map_t kext_map = NULL; 5589 kernel_segment_command_t * seg = NULL; 5590 vm_map_offset_t start = 0; 5591 vm_map_offset_t end = 0; 5592 OSReturn result = kOSReturnError; 5593 5594 if (isInterface() || !declaresExecutable()) { 5595 result = kOSReturnSuccess; 5596 goto finish; 5597 } 5598 5599 /* Get the kext's vm map */ 5600 kext_map = kext_get_vm_map(kmod_info); 5601 if (!kext_map) { 5602 result = KERN_MEMORY_ERROR; 5603 goto finish; 5604 } 5605 5606 /* Protect the headers as read-only; they do not need to be wired */ 5607 result = (protect) ? OSKext_protect(kext_map, kmod_info->address, 5608 kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE) 5609 : KERN_SUCCESS; 5610 if (result != KERN_SUCCESS) { 5611 goto finish; 5612 } 5613 5614 /* Set the VM protections and wire down each of the segments */ 5615 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 5616 while (seg) { 5617 5618 5619 start = round_page(seg->vmaddr); 5620 end = trunc_page(seg->vmaddr + seg->vmsize); 5621 5622 if (protect) { 5623 result = OSKext_protect(kext_map, start, end, seg->maxprot, TRUE); 5624 if (result != KERN_SUCCESS) { 5625 OSKextLog(this, 5626 kOSKextLogErrorLevel | 5627 kOSKextLogLoadFlag, 5628 "Kext %s failed to set maximum VM protections " 5629 "for segment %s - 0x%x.", 5630 getIdentifierCString(), seg->segname, (int)result); 5631 goto finish; 5632 } 5633 5634 result = OSKext_protect(kext_map, start, end, seg->initprot, FALSE); 5635 if (result != KERN_SUCCESS) { 5636 OSKextLog(this, 5637 kOSKextLogErrorLevel | 5638 kOSKextLogLoadFlag, 5639 "Kext %s failed to set initial VM protections " 5640 "for segment %s - 0x%x.", 5641 getIdentifierCString(), seg->segname, (int)result); 5642 goto finish; 5643 } 5644 } 5645 5646 if (segmentShouldBeWired(seg) && wire) { 5647 result = OSKext_wire(kext_map, start, end, seg->initprot, FALSE); 5648 if (result != KERN_SUCCESS) { 5649 goto finish; 5650 } 5651 } 5652 5653 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 5654 } 5655 5656 finish: 5657 return result; 5658 } 5659 5660 /********************************************************************* 5661 *********************************************************************/ 5662 boolean_t 5663 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg) 5664 { 5665 return (sKeepSymbols || strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname))); 5666 } 5667 5668 /********************************************************************* 5669 *********************************************************************/ 5670 OSReturn 5671 OSKext::validateKextMapping(bool startFlag) 5672 { 5673 OSReturn result = kOSReturnError; 5674 const char * whichOp = startFlag ? "start" : "stop"; 5675 kern_return_t kern_result = 0; 5676 vm_map_t kext_map = NULL; 5677 kernel_segment_command_t * seg = NULL; 5678 mach_vm_address_t address = 0; 5679 mach_vm_size_t size = 0; 5680 uint32_t depth = 0; 5681 mach_msg_type_number_t count; 5682 vm_region_submap_short_info_data_64_t info; 5683 5684 count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 5685 bzero(&info, sizeof(info)); 5686 5687 // xxx - do we need a distinct OSReturn value for these or is "bad data" 5688 // xxx - sufficient? 5689 5690 /* Verify that the kmod_info and start/stop pointers are non-NULL. 5691 */ 5692 if (!kmod_info) { 5693 OSKextLog(this, 5694 kOSKextLogErrorLevel | 5695 kOSKextLogLoadFlag, 5696 "Kext %s - NULL kmod_info pointer.", 5697 getIdentifierCString()); 5698 result = kOSKextReturnBadData; 5699 goto finish; 5700 } 5701 5702 if (startFlag) { 5703 address = (mach_vm_address_t)kmod_info->start; 5704 } else { 5705 address = (mach_vm_address_t)kmod_info->stop; 5706 } 5707 5708 if (!address) { 5709 OSKextLog(this, 5710 kOSKextLogErrorLevel | 5711 kOSKextLogLoadFlag, 5712 "Kext %s - NULL module %s pointer.", 5713 getIdentifierCString(), whichOp); 5714 result = kOSKextReturnBadData; 5715 goto finish; 5716 } 5717 5718 kext_map = kext_get_vm_map(kmod_info); 5719 depth = (kernel_map == kext_map) ? 1 : 2; 5720 5721 /* Verify that the start/stop function lies within the kext's address range. 5722 */ 5723 if (address < kmod_info->address + kmod_info->hdr_size || 5724 kmod_info->address + kmod_info->size <= address) 5725 { 5726 OSKextLog(this, 5727 kOSKextLogErrorLevel | 5728 kOSKextLogLoadFlag, 5729 "Kext %s module %s pointer is outside of kext range " 5730 "(%s %p - kext at %p-%p)..", 5731 getIdentifierCString(), 5732 whichOp, 5733 whichOp, 5734 (void *)VM_KERNEL_UNSLIDE(address), 5735 (void *)VM_KERNEL_UNSLIDE(kmod_info->address), 5736 (void *)(VM_KERNEL_UNSLIDE(kmod_info->address) + kmod_info->size)); 5737 result = kOSKextReturnBadData; 5738 goto finish; 5739 } 5740 5741 /* Only do these checks before calling the start function; 5742 * If anything goes wrong with the mapping while the kext is running, 5743 * we'll likely have panicked well before any attempt to stop the kext. 5744 */ 5745 if (startFlag) { 5746 5747 /* Verify that the start/stop function is executable. 5748 */ 5749 kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth, 5750 (vm_region_recurse_info_t)&info, &count); 5751 if (kern_result != KERN_SUCCESS) { 5752 OSKextLog(this, 5753 kOSKextLogErrorLevel | 5754 kOSKextLogLoadFlag, 5755 "Kext %s - bad %s pointer %p.", 5756 getIdentifierCString(), 5757 whichOp, (void *)VM_KERNEL_UNSLIDE(address)); 5758 result = kOSKextReturnBadData; 5759 goto finish; 5760 } 5761 5762 #if VM_MAPPED_KEXTS 5763 if (!(info.protection & VM_PROT_EXECUTE)) { 5764 OSKextLog(this, 5765 kOSKextLogErrorLevel | 5766 kOSKextLogLoadFlag, 5767 "Kext %s - memory region containing module %s function " 5768 "is not executable.", 5769 getIdentifierCString(), whichOp); 5770 result = kOSKextReturnBadData; 5771 goto finish; 5772 } 5773 #endif 5774 5775 /* Verify that the kext's segments are backed by physical memory. 5776 */ 5777 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 5778 while (seg) { 5779 if (!verifySegmentMapping(seg)) { 5780 result = kOSKextReturnBadData; 5781 goto finish; 5782 } 5783 5784 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 5785 } 5786 5787 } 5788 5789 result = kOSReturnSuccess; 5790 finish: 5791 return result; 5792 } 5793 5794 /********************************************************************* 5795 *********************************************************************/ 5796 boolean_t 5797 OSKext::verifySegmentMapping(kernel_segment_command_t *seg) 5798 { 5799 mach_vm_address_t address = 0; 5800 5801 if (!segmentShouldBeWired(seg)) return true; 5802 5803 for (address = seg->vmaddr; 5804 address < round_page(seg->vmaddr + seg->vmsize); 5805 address += PAGE_SIZE) 5806 { 5807 if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) { 5808 OSKextLog(this, 5809 kOSKextLogErrorLevel | 5810 kOSKextLogLoadFlag, 5811 "Kext %s - page %p is not backed by physical memory.", 5812 getIdentifierCString(), 5813 (void *)address); 5814 return false; 5815 } 5816 } 5817 5818 return true; 5819 } 5820 5821 /********************************************************************* 5822 *********************************************************************/ 5823 OSReturn 5824 OSKext::start(bool startDependenciesFlag) 5825 { 5826 OSReturn result = kOSReturnError; 5827 kern_return_t (* startfunc)(kmod_info_t *, void *); 5828 unsigned int i, count; 5829 void * kmodStartData = NULL; 5830 5831 if (isStarted() || isInterface() || isKernelComponent()) { 5832 result = kOSReturnSuccess; 5833 goto finish; 5834 } 5835 5836 if (!isLoaded()) { 5837 OSKextLog(this, 5838 kOSKextLogErrorLevel | 5839 kOSKextLogLoadFlag, 5840 "Attempt to start nonloaded kext %s.", 5841 getIdentifierCString()); 5842 result = kOSKextReturnInvalidArgument; 5843 goto finish; 5844 } 5845 5846 if (!sLoadEnabled) { 5847 OSKextLog(this, 5848 kOSKextLogErrorLevel | 5849 kOSKextLogLoadFlag, 5850 "Kext loading is disabled (attempt to start kext %s).", 5851 getIdentifierCString()); 5852 result = kOSKextReturnDisabled; 5853 goto finish; 5854 } 5855 5856 result = validateKextMapping(/* start? */ true); 5857 if (result != kOSReturnSuccess) { 5858 goto finish; 5859 } 5860 5861 startfunc = kmod_info->start; 5862 5863 count = getNumDependencies(); 5864 for (i = 0; i < count; i++) { 5865 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i)); 5866 if (dependency == NULL) { 5867 OSKextLog(this, 5868 kOSKextLogErrorLevel | 5869 kOSKextLogLoadFlag, 5870 "Kext %s start - internal error, dependency disappeared.", 5871 getIdentifierCString()); 5872 goto finish; 5873 } 5874 if (!dependency->isStarted()) { 5875 if (startDependenciesFlag) { 5876 OSReturn dependencyResult = 5877 dependency->start(startDependenciesFlag); 5878 if (dependencyResult != KERN_SUCCESS) { 5879 OSKextLog(this, 5880 kOSKextLogErrorLevel | 5881 kOSKextLogLoadFlag, 5882 "Kext %s start - dependency %s failed to start (error 0x%x).", 5883 getIdentifierCString(), 5884 dependency->getIdentifierCString(), 5885 dependencyResult); 5886 goto finish; 5887 } 5888 } else { 5889 OSKextLog(this, 5890 kOSKextLogErrorLevel | 5891 kOSKextLogLoadFlag, 5892 "Not starting %s - dependency %s not started yet.", 5893 getIdentifierCString(), 5894 dependency->getIdentifierCString()); 5895 result = kOSKextReturnStartStopError; // xxx - make new return? 5896 goto finish; 5897 } 5898 } 5899 } 5900 5901 OSKextLog(this, 5902 kOSKextLogDetailLevel | 5903 kOSKextLogLoadFlag, 5904 "Kext %s calling module start function.", 5905 getIdentifierCString()); 5906 5907 flags.starting = 1; 5908 5909 #if !CONFIG_STATIC_CPPINIT 5910 result = OSRuntimeInitializeCPP(kmod_info, NULL); 5911 if (result == KERN_SUCCESS) { 5912 #endif 5913 5914 #if CONFIG_KEC_FIPS 5915 kmodStartData = GetAppleTEXTHashForKext(this, this->infoDict); 5916 5917 #if 0 5918 if (kmodStartData) { 5919 OSKextLog(this, 5920 kOSKextLogErrorLevel | 5921 kOSKextLogGeneralFlag, 5922 "Kext %s calling module start function. kmodStartData %p. arch %s", 5923 getIdentifierCString(), kmodStartData, ARCHNAME); 5924 } 5925 #endif 5926 #endif // CONFIG_KEC_FIPS 5927 5928 result = startfunc(kmod_info, kmodStartData); 5929 5930 #if !CONFIG_STATIC_CPPINIT 5931 if (result != KERN_SUCCESS) { 5932 (void) OSRuntimeFinalizeCPP(kmod_info, NULL); 5933 } 5934 } 5935 #endif 5936 5937 flags.starting = 0; 5938 5939 /* On success overlap the setting of started/starting. On failure just 5940 * clear starting. 5941 */ 5942 if (result == KERN_SUCCESS) { 5943 flags.started = 1; 5944 5945 // xxx - log start error from kernel? 5946 OSKextLog(this, 5947 kOSKextLogProgressLevel | 5948 kOSKextLogLoadFlag, 5949 "Kext %s is now started.", 5950 getIdentifierCString()); 5951 } else { 5952 invokeOrCancelRequestCallbacks( 5953 /* result not actually used */ kOSKextReturnStartStopError, 5954 /* invokeFlag */ false); 5955 OSKextLog(this, 5956 kOSKextLogProgressLevel | 5957 kOSKextLogLoadFlag, 5958 "Kext %s did not start (return code 0x%x).", 5959 getIdentifierCString(), result); 5960 } 5961 5962 finish: 5963 return result; 5964 } 5965 5966 /********************************************************************* 5967 *********************************************************************/ 5968 /* static */ 5969 bool OSKext::canUnloadKextWithIdentifier( 5970 OSString * kextIdentifier, 5971 bool checkClassesFlag) 5972 { 5973 bool result = false; 5974 OSKext * aKext = NULL; // do not release 5975 5976 IORecursiveLockLock(sKextLock); 5977 5978 aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 5979 5980 if (!aKext) { 5981 goto finish; // can't unload what's not loaded 5982 } 5983 5984 if (aKext->isLoaded()) { 5985 if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) { 5986 goto finish; 5987 } 5988 if (checkClassesFlag && aKext->hasOSMetaClassInstances()) { 5989 goto finish; 5990 } 5991 } 5992 5993 result = true; 5994 5995 finish: 5996 IORecursiveLockUnlock(sKextLock); 5997 return result; 5998 } 5999 6000 /********************************************************************* 6001 *********************************************************************/ 6002 OSReturn 6003 OSKext::stop(void) 6004 { 6005 OSReturn result = kOSReturnError; 6006 kern_return_t (*stopfunc)(kmod_info_t *, void *); 6007 6008 if (!isStarted() || isInterface()) { 6009 result = kOSReturnSuccess; 6010 goto finish; 6011 } 6012 6013 if (!isLoaded()) { 6014 OSKextLog(this, 6015 kOSKextLogErrorLevel | 6016 kOSKextLogLoadFlag, 6017 "Attempt to stop nonloaded kext %s.", 6018 getIdentifierCString()); 6019 result = kOSKextReturnInvalidArgument; 6020 goto finish; 6021 } 6022 6023 /* Refuse to stop if we have clients or instances. It is up to 6024 * the caller to make sure those aren't true. 6025 */ 6026 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 6027 OSKextLog(this, 6028 kOSKextLogErrorLevel | 6029 kOSKextLogLoadFlag, 6030 "Kext %s - C++ instances; can't stop.", 6031 getIdentifierCString()); 6032 result = kOSKextReturnInUse; 6033 goto finish; 6034 } 6035 6036 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 6037 6038 OSKextLog(this, 6039 kOSKextLogErrorLevel | 6040 kOSKextLogLoadFlag, 6041 "Kext %s - has references (linkage or tracking object); " 6042 "can't stop.", 6043 getIdentifierCString()); 6044 result = kOSKextReturnInUse; 6045 goto finish; 6046 } 6047 6048 /* Note: If validateKextMapping fails on the stop & unload path, 6049 * we are in serious trouble and a kernel panic is likely whether 6050 * we stop & unload the kext or not. 6051 */ 6052 result = validateKextMapping(/* start? */ false); 6053 if (result != kOSReturnSuccess) { 6054 goto finish; 6055 } 6056 6057 stopfunc = kmod_info->stop; 6058 if (stopfunc) { 6059 OSKextLog(this, 6060 kOSKextLogDetailLevel | 6061 kOSKextLogLoadFlag, 6062 "Kext %s calling module stop function.", 6063 getIdentifierCString()); 6064 6065 flags.stopping = 1; 6066 6067 result = stopfunc(kmod_info, /* userData */ NULL); 6068 #if !CONFIG_STATIC_CPPINIT 6069 if (result == KERN_SUCCESS) { 6070 result = OSRuntimeFinalizeCPP(kmod_info, NULL); 6071 } 6072 #endif 6073 6074 flags.stopping = 0; 6075 6076 if (result == KERN_SUCCESS) { 6077 flags.started = 0; 6078 6079 OSKextLog(this, 6080 kOSKextLogDetailLevel | 6081 kOSKextLogLoadFlag, 6082 "Kext %s is now stopped and ready to unload.", 6083 getIdentifierCString()); 6084 } else { 6085 OSKextLog(this, 6086 kOSKextLogErrorLevel | 6087 kOSKextLogLoadFlag, 6088 "Kext %s did not stop (return code 0x%x).", 6089 getIdentifierCString(), result); 6090 result = kOSKextReturnStartStopError; 6091 } 6092 } 6093 6094 finish: 6095 return result; 6096 } 6097 6098 /********************************************************************* 6099 *********************************************************************/ 6100 OSReturn 6101 OSKext::unload(void) 6102 { 6103 OSReturn result = kOSReturnError; 6104 unsigned int index; 6105 uint32_t num_kmod_refs = 0; 6106 OSKextAccount * freeAccount; 6107 6108 if (!sUnloadEnabled) { 6109 OSKextLog(this, 6110 kOSKextLogErrorLevel | 6111 kOSKextLogLoadFlag, 6112 "Kext unloading is disabled (%s).", 6113 this->getIdentifierCString()); 6114 6115 result = kOSKextReturnDisabled; 6116 goto finish; 6117 } 6118 6119 /* Refuse to unload if we have clients or instances. It is up to 6120 * the caller to make sure those aren't true. 6121 */ 6122 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 6123 // xxx - Don't log under errors? this is more of an info thing 6124 OSKextLog(this, 6125 kOSKextLogErrorLevel | 6126 kOSKextLogKextBookkeepingFlag, 6127 "Can't unload kext %s; outstanding references (linkage or tracking object).", 6128 getIdentifierCString()); 6129 result = kOSKextReturnInUse; 6130 goto finish; 6131 } 6132 6133 if (hasOSMetaClassInstances()) { 6134 OSKextLog(this, 6135 kOSKextLogErrorLevel | 6136 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 6137 "Can't unload kext %s; classes have instances:", 6138 getIdentifierCString()); 6139 reportOSMetaClassInstances(kOSKextLogErrorLevel | 6140 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag); 6141 result = kOSKextReturnInUse; 6142 goto finish; 6143 } 6144 6145 if (!isLoaded()) { 6146 result = kOSReturnSuccess; 6147 goto finish; 6148 } 6149 6150 if (isKernelComponent()) { 6151 result = kOSKextReturnInvalidArgument; 6152 goto finish; 6153 } 6154 6155 /* Note that the kext is unloading before running any code that 6156 * might be in the kext (request callbacks, module stop function). 6157 * We will deny certain requests made against a kext in the process 6158 * of unloading. 6159 */ 6160 flags.unloading = 1; 6161 6162 /* Update the string describing the last kext to unload in case we panic. 6163 */ 6164 savePanicString(/* isLoading */ false); 6165 6166 if (isStarted()) { 6167 result = stop(); 6168 if (result != KERN_SUCCESS) { 6169 OSKextLog(this, 6170 kOSKextLogErrorLevel | 6171 kOSKextLogLoadFlag, 6172 "Kext %s can't unload - module stop returned 0x%x.", 6173 getIdentifierCString(), (unsigned)result); 6174 result = kOSKextReturnStartStopError; 6175 goto finish; 6176 } 6177 } 6178 6179 OSKextLog(this, 6180 kOSKextLogProgressLevel | 6181 kOSKextLogLoadFlag, 6182 "Kext %s unloading.", 6183 getIdentifierCString()); 6184 6185 { 6186 struct list_head *p; 6187 struct list_head *prev; 6188 struct list_head *next; 6189 for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) { 6190 OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head); 6191 s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize); 6192 prev = p->prev; 6193 next = p->next; 6194 prev->next = next; 6195 next->prev = prev; 6196 p->prev = p; 6197 p->next = p; 6198 IORecursiveLockWakeup(sKextLock, s, false); 6199 } 6200 } 6201 6202 6203 /* Even if we don't call the stop function, we want to be sure we 6204 * have no OSMetaClass references before unloading the kext executable 6205 * from memory. OSMetaClasses may have pointers into the kext executable 6206 * and that would cause a panic on OSKext::free() when metaClasses is freed. 6207 */ 6208 if (metaClasses) { 6209 metaClasses->flushCollection(); 6210 } 6211 6212 /* Remove the kext from the list of loaded kexts, patch the gap 6213 * in the kmod_info_t linked list, and reset "kmod" to point to the 6214 * last loaded kext that isn't the fake kernel kext (sKernelKext). 6215 */ 6216 index = sLoadedKexts->getNextIndexOfObject(this, 0); 6217 if (index != (unsigned int)-1) { 6218 6219 sLoadedKexts->removeObject(index); 6220 6221 OSKext * nextKext = OSDynamicCast(OSKext, 6222 sLoadedKexts->getObject(index)); 6223 6224 if (nextKext) { 6225 if (index > 0) { 6226 OSKext * gapKext = OSDynamicCast(OSKext, 6227 sLoadedKexts->getObject(index - 1)); 6228 6229 nextKext->kmod_info->next = gapKext->kmod_info; 6230 6231 } else /* index == 0 */ { 6232 nextKext->kmod_info->next = NULL; 6233 } 6234 } 6235 6236 OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 6237 if (lastKext && !lastKext->isKernel()) { 6238 kmod = lastKext->kmod_info; 6239 } else { 6240 kmod = NULL; // clear the global kmod variable 6241 } 6242 } 6243 6244 /* Clear out the kmod references that we're keeping for compatibility 6245 * with current panic backtrace code & kgmacros. 6246 * xxx - will want to update those bits sometime and remove this. 6247 */ 6248 num_kmod_refs = getNumDependencies(); 6249 if (num_kmod_refs && kmod_info && kmod_info->reference_list) { 6250 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 6251 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 6252 ref->info->reference_count--; 6253 } 6254 kfree(kmod_info->reference_list, 6255 num_kmod_refs * sizeof(kmod_reference_t)); 6256 } 6257 6258 #if CONFIG_DTRACE 6259 unregisterWithDTrace(); 6260 #endif /* CONFIG_DTRACE */ 6261 6262 notifyKextUnloadObservers(this); 6263 6264 freeAccount = NULL; 6265 IOSimpleLockLock(sKextAccountsLock); 6266 if (account->site.tag) account->site.flags |= VM_TAG_UNLOAD; 6267 else freeAccount = account; 6268 IOSimpleLockUnlock(sKextAccountsLock); 6269 if (freeAccount) IODelete(freeAccount, OSKextAccount, 1); 6270 6271 /* Unwire and free the linked executable. 6272 */ 6273 if (linkedExecutable) { 6274 #if VM_MAPPED_KEXTS 6275 if (!isInterface()) { 6276 kernel_segment_command_t *seg = NULL; 6277 vm_map_t kext_map = kext_get_vm_map(kmod_info); 6278 6279 if (!kext_map) { 6280 OSKextLog(this, 6281 kOSKextLogErrorLevel | 6282 kOSKextLogLoadFlag, 6283 "Failed to free kext %s; couldn't find the kext map.", 6284 getIdentifierCString()); 6285 result = kOSKextReturnInternalError; 6286 goto finish; 6287 } 6288 6289 OSKextLog(this, 6290 kOSKextLogProgressLevel | 6291 kOSKextLogLoadFlag, 6292 "Kext %s unwiring and unmapping linked executable.", 6293 getIdentifierCString()); 6294 6295 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 6296 while (seg) { 6297 if (segmentShouldBeWired(seg)) { 6298 result = vm_map_unwire(kext_map, seg->vmaddr, 6299 seg->vmaddr + seg->vmsize, FALSE); 6300 if (result != KERN_SUCCESS) { 6301 OSKextLog(this, 6302 kOSKextLogErrorLevel | 6303 kOSKextLogLoadFlag, 6304 "Failed to unwire kext %s.", 6305 getIdentifierCString()); 6306 result = kOSKextReturnInternalError; 6307 goto finish; 6308 } 6309 } 6310 6311 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 6312 } 6313 } 6314 #endif 6315 OSSafeReleaseNULL(linkedExecutable); 6316 } 6317 6318 /* An interface kext has a fake kmod_info that was allocated, 6319 * so we have to free it. 6320 */ 6321 if (isInterface()) { 6322 kfree(kmod_info, sizeof(kmod_info_t)); 6323 } 6324 6325 kmod_info = NULL; 6326 6327 flags.loaded = false; 6328 flushDependencies(); 6329 6330 /* save a copy of the bundle ID for us to check when deciding to 6331 * rebuild the kernel cache file. If a kext was already in the kernel 6332 * cache and unloaded then later loaded we do not need to rebuild the 6333 * kernel cache. 9055303 6334 */ 6335 if (isPrelinked()) { 6336 if (!_OSKextInUnloadedPrelinkedKexts(bundleID)) { 6337 IORecursiveLockLock(sKextLock); 6338 if (sUnloadedPrelinkedKexts) { 6339 sUnloadedPrelinkedKexts->setObject(bundleID); 6340 } 6341 IORecursiveLockUnlock(sKextLock); 6342 } 6343 } 6344 6345 OSKextLog(this, 6346 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 6347 "Kext %s unloaded.", getIdentifierCString()); 6348 6349 queueKextNotification(kKextRequestPredicateUnloadNotification, 6350 OSDynamicCast(OSString, bundleID)); 6351 6352 finish: 6353 OSKext::saveLoadedKextPanicList(); 6354 OSKext::updateLoadedKextSummaries(); 6355 6356 flags.unloading = 0; 6357 return result; 6358 } 6359 6360 /********************************************************************* 6361 * Assumes sKextLock is held. 6362 *********************************************************************/ 6363 /* static */ 6364 OSReturn 6365 OSKext::queueKextNotification( 6366 const char * notificationName, 6367 OSString * kextIdentifier) 6368 { 6369 OSReturn result = kOSReturnError; 6370 OSDictionary * loadRequest = NULL; // must release 6371 6372 if (!kextIdentifier) { 6373 result = kOSKextReturnInvalidArgument; 6374 goto finish; 6375 } 6376 6377 /* Create a new request unless one is already sitting 6378 * in sKernelRequests for this bundle identifier 6379 */ 6380 result = _OSKextCreateRequest(notificationName, &loadRequest); 6381 if (result != kOSReturnSuccess) { 6382 goto finish; 6383 } 6384 if (!_OSKextSetRequestArgument(loadRequest, 6385 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 6386 6387 result = kOSKextReturnNoMemory; 6388 goto finish; 6389 } 6390 if (!sKernelRequests->setObject(loadRequest)) { 6391 result = kOSKextReturnNoMemory; 6392 goto finish; 6393 } 6394 6395 /* We might want to only queue the notification if kextd is active, 6396 * but that wouldn't work for embedded. Note that we don't care if 6397 * the ping immediately succeeds here so don't do anything with the 6398 * result of this call. 6399 */ 6400 OSKext::pingKextd(); 6401 6402 result = kOSReturnSuccess; 6403 6404 finish: 6405 OSSafeRelease(loadRequest); 6406 6407 return result; 6408 } 6409 6410 /********************************************************************* 6411 *********************************************************************/ 6412 static void 6413 _OSKextConsiderDestroyingLinkContext( 6414 __unused thread_call_param_t p0, 6415 __unused thread_call_param_t p1) 6416 { 6417 /* Take multiple locks in the correct order. 6418 */ 6419 IORecursiveLockLock(sKextLock); 6420 IORecursiveLockLock(sKextInnerLock); 6421 6422 /* The first time we destroy the kxldContext is in the first 6423 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled 6424 * before calling this function. Thereafter any call to this function 6425 * will actually destroy the context. 6426 */ 6427 if (sConsiderUnloadsCalled && sKxldContext) { 6428 kxld_destroy_context(sKxldContext); 6429 sKxldContext = NULL; 6430 } 6431 6432 /* Free the thread_call that was allocated to execute this function. 6433 */ 6434 if (sDestroyLinkContextThread) { 6435 if (!thread_call_free(sDestroyLinkContextThread)) { 6436 OSKextLog(/* kext */ NULL, 6437 kOSKextLogErrorLevel | 6438 kOSKextLogGeneralFlag, 6439 "thread_call_free() failed for kext link context."); 6440 } 6441 sDestroyLinkContextThread = 0; 6442 } 6443 6444 IORecursiveLockUnlock(sKextInnerLock); 6445 IORecursiveLockUnlock(sKextLock); 6446 6447 return; 6448 } 6449 6450 /********************************************************************* 6451 * Destroying the kxldContext requires checking variables under both 6452 * sKextInnerLock and sKextLock, so we do it on a separate thread 6453 * to avoid deadlocks with IOService, with which OSKext has a reciprocal 6454 * call relationship. 6455 * 6456 * This function must be invoked with sKextInnerLock held. 6457 * Do not call any function that takes sKextLock here! 6458 *********************************************************************/ 6459 /* static */ 6460 void 6461 OSKext::considerDestroyingLinkContext(void) 6462 { 6463 IORecursiveLockLock(sKextInnerLock); 6464 6465 /* If we have already queued a thread to destroy the link context, 6466 * don't bother resetting; that thread will take care of it. 6467 */ 6468 if (sDestroyLinkContextThread) { 6469 goto finish; 6470 } 6471 6472 /* The function to be invoked in the thread will deallocate 6473 * this thread_call, so don't share it around. 6474 */ 6475 sDestroyLinkContextThread = thread_call_allocate( 6476 &_OSKextConsiderDestroyingLinkContext, 0); 6477 if (!sDestroyLinkContextThread) { 6478 OSKextLog(/* kext */ NULL, 6479 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag, 6480 "Can't create thread to destroy kext link context."); 6481 goto finish; 6482 } 6483 6484 thread_call_enter(sDestroyLinkContextThread); 6485 6486 finish: 6487 IORecursiveLockUnlock(sKextInnerLock); 6488 return; 6489 } 6490 6491 #if PRAGMA_MARK 6492 #pragma mark Autounload 6493 #endif 6494 /********************************************************************* 6495 * This is a static method because the kext will be deallocated if it 6496 * does unload! 6497 *********************************************************************/ 6498 /* static */ 6499 OSReturn 6500 OSKext::autounloadKext(OSKext * aKext) 6501 { 6502 OSReturn result = kOSKextReturnInUse; 6503 6504 /* Check for external references to this kext (usu. dependents), 6505 * instances of defined classes (or classes derived from them), 6506 * outstanding requests. 6507 */ 6508 if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) || 6509 !aKext->flags.autounloadEnabled || 6510 aKext->isKernelComponent()) { 6511 6512 goto finish; 6513 } 6514 6515 /* Skip a delay-autounload kext, once. 6516 */ 6517 if (aKext->flags.delayAutounload) { 6518 OSKextLog(aKext, 6519 kOSKextLogProgressLevel | 6520 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 6521 "Kext %s has delayed autounload set; skipping and clearing flag.", 6522 aKext->getIdentifierCString()); 6523 aKext->flags.delayAutounload = 0; 6524 goto finish; 6525 } 6526 6527 if (aKext->hasOSMetaClassInstances() || 6528 aKext->countRequestCallbacks()) { 6529 goto finish; 6530 } 6531 6532 result = OSKext::removeKext(aKext); 6533 6534 finish: 6535 return result; 6536 } 6537 6538 /********************************************************************* 6539 *********************************************************************/ 6540 void 6541 _OSKextConsiderUnloads( 6542 __unused thread_call_param_t p0, 6543 __unused thread_call_param_t p1) 6544 { 6545 bool didUnload = false; 6546 unsigned int count, i; 6547 6548 /* Take multiple locks in the correct order 6549 * (note also sKextSummaries lock further down). 6550 */ 6551 IORecursiveLockLock(sKextLock); 6552 IORecursiveLockLock(sKextInnerLock); 6553 6554 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true); 6555 6556 /* If the system is powering down, don't try to unload anything. 6557 */ 6558 if (sSystemSleep) { 6559 goto finish; 6560 } 6561 6562 OSKextLog(/* kext */ NULL, 6563 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 6564 "Checking for unused kexts to autounload."); 6565 6566 /***** 6567 * Remove any request callbacks marked as stale, 6568 * and mark as stale any currently in flight. 6569 */ 6570 count = sRequestCallbackRecords->getCount(); 6571 if (count) { 6572 i = count - 1; 6573 do { 6574 OSDictionary * callbackRecord = OSDynamicCast(OSDictionary, 6575 sRequestCallbackRecords->getObject(i)); 6576 OSBoolean * stale = OSDynamicCast(OSBoolean, 6577 callbackRecord->getObject(kKextRequestStaleKey)); 6578 6579 if (stale == kOSBooleanTrue) { 6580 OSKext::invokeRequestCallback(callbackRecord, 6581 kOSKextReturnTimeout); 6582 } else { 6583 callbackRecord->setObject(kKextRequestStaleKey, 6584 kOSBooleanTrue); 6585 } 6586 } while (i--); 6587 } 6588 6589 /***** 6590 * Make multiple passes through the array of loaded kexts until 6591 * we don't unload any. This handles unwinding of dependency 6592 * chains. We have to go *backwards* through the array because 6593 * kexts are removed from it when unloaded, and we cannot make 6594 * a copy or we'll mess up the retain counts we rely on to 6595 * check whether a kext will unload. If only we could have 6596 * nonretaining collections like CF has.... 6597 */ 6598 do { 6599 didUnload = false; 6600 6601 count = sLoadedKexts->getCount(); 6602 if (count) { 6603 i = count - 1; 6604 do { 6605 OSKext * thisKext = OSDynamicCast(OSKext, 6606 sLoadedKexts->getObject(i)); 6607 didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext)); 6608 } while (i--); 6609 } 6610 } while (didUnload); 6611 6612 finish: 6613 sConsiderUnloadsPending = false; 6614 sConsiderUnloadsExecuted = true; 6615 6616 (void) OSKext::considerRebuildOfPrelinkedKernel(); 6617 6618 IORecursiveLockUnlock(sKextInnerLock); 6619 IORecursiveLockUnlock(sKextLock); 6620 6621 return; 6622 } 6623 6624 /********************************************************************* 6625 * Do not call any function that takes sKextLock here! 6626 *********************************************************************/ 6627 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag) 6628 { 6629 AbsoluteTime when; 6630 6631 IORecursiveLockLock(sKextInnerLock); 6632 6633 if (!sUnloadCallout) { 6634 sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, 0); 6635 } 6636 6637 /* we only reset delay value for unloading if we already have something 6638 * pending. rescheduleOnlyFlag should not start the count down. 6639 */ 6640 if (rescheduleOnlyFlag && !sConsiderUnloadsPending) { 6641 goto finish; 6642 } 6643 6644 thread_call_cancel(sUnloadCallout); 6645 if (OSKext::getAutounloadEnabled() && !sSystemSleep) { 6646 clock_interval_to_deadline(sConsiderUnloadDelay, 6647 1000 * 1000 * 1000, &when); 6648 6649 OSKextLog(/* kext */ NULL, 6650 kOSKextLogProgressLevel | 6651 kOSKextLogLoadFlag, 6652 "%scheduling %sscan for unused kexts in %lu seconds.", 6653 sConsiderUnloadsPending ? "Res" : "S", 6654 sConsiderUnloadsCalled ? "" : "initial ", 6655 (unsigned long)sConsiderUnloadDelay); 6656 6657 sConsiderUnloadsPending = true; 6658 thread_call_enter_delayed(sUnloadCallout, when); 6659 } 6660 6661 finish: 6662 /* The kxld context should be reused throughout boot. We mark the end of 6663 * period as the first time considerUnloads() is called, and we destroy 6664 * the first kxld context in that function. Afterwards, it will be 6665 * destroyed in flushNonloadedKexts. 6666 */ 6667 if (!sConsiderUnloadsCalled) { 6668 sConsiderUnloadsCalled = true; 6669 OSKext::considerDestroyingLinkContext(); 6670 } 6671 6672 IORecursiveLockUnlock(sKextInnerLock); 6673 return; 6674 } 6675 6676 /********************************************************************* 6677 * Do not call any function that takes sKextLock here! 6678 *********************************************************************/ 6679 extern "C" { 6680 6681 IOReturn OSKextSystemSleepOrWake(UInt32 messageType) 6682 { 6683 IORecursiveLockLock(sKextInnerLock); 6684 6685 /* If the system is going to sleep, cancel the reaper thread timer, 6686 * and note that we're in a sleep state in case it just fired but hasn't 6687 * taken the lock yet. If we are coming back from sleep, just 6688 * clear the sleep flag; IOService's normal operation will cause 6689 * unloads to be considered soon enough. 6690 */ 6691 if (messageType == kIOMessageSystemWillSleep) { 6692 if (sUnloadCallout) { 6693 thread_call_cancel(sUnloadCallout); 6694 } 6695 sSystemSleep = true; 6696 AbsoluteTime_to_scalar(&sLastWakeTime) = 0; 6697 } else if (messageType == kIOMessageSystemHasPoweredOn) { 6698 sSystemSleep = false; 6699 clock_get_uptime(&sLastWakeTime); 6700 } 6701 IORecursiveLockUnlock(sKextInnerLock); 6702 6703 return kIOReturnSuccess; 6704 } 6705 6706 }; 6707 6708 6709 #if PRAGMA_MARK 6710 #pragma mark Prelinked Kernel 6711 #endif 6712 /********************************************************************* 6713 * Do not access sConsiderUnloads... variables other than 6714 * sConsiderUnloadsExecuted in this function. They are guarded by a 6715 * different lock. 6716 *********************************************************************/ 6717 /* static */ 6718 void 6719 OSKext::considerRebuildOfPrelinkedKernel(void) 6720 { 6721 static bool requestedPrelink = false; 6722 OSReturn checkResult = kOSReturnError; 6723 OSDictionary * prelinkRequest = NULL; // must release 6724 OSCollectionIterator * kextIterator = NULL; // must release 6725 const OSSymbol * thisID = NULL; // do not release 6726 bool doRebuild = false; 6727 AbsoluteTime my_abstime; 6728 UInt64 my_ns; 6729 SInt32 delta_secs; 6730 6731 /* Only one auto rebuild per boot and only on boot from prelinked kernel */ 6732 if (requestedPrelink || !sPrelinkBoot) { 6733 return; 6734 } 6735 6736 /* no direct return from this point */ 6737 IORecursiveLockLock(sKextLock); 6738 6739 /* We need to wait for kextd to get up and running with unloads already done 6740 * and any new startup kexts loaded. 6741 */ 6742 if (!sConsiderUnloadsExecuted || 6743 !sDeferredLoadSucceeded) { 6744 goto finish; 6745 } 6746 6747 /* we really only care about boot / system start up related kexts so bail 6748 * if we're here after REBUILD_MAX_TIME. 6749 */ 6750 if (!_OSKextInPrelinkRebuildWindow()) { 6751 OSKextLog(/* kext */ NULL, 6752 kOSKextLogArchiveFlag, 6753 "%s prebuild rebuild has expired", 6754 __FUNCTION__); 6755 requestedPrelink = true; 6756 goto finish; 6757 } 6758 6759 /* we do not want to trigger a rebuild if we get here too close to waking 6760 * up. (see radar 10233768) 6761 */ 6762 IORecursiveLockLock(sKextInnerLock); 6763 6764 clock_get_uptime(&my_abstime); 6765 delta_secs = MINIMUM_WAKEUP_SECONDS + 1; 6766 if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) { 6767 SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime); 6768 absolutetime_to_nanoseconds(my_abstime, &my_ns); 6769 delta_secs = (SInt32)(my_ns / NSEC_PER_SEC); 6770 } 6771 IORecursiveLockUnlock(sKextInnerLock); 6772 6773 if (delta_secs < MINIMUM_WAKEUP_SECONDS) { 6774 /* too close to time of last wake from sleep */ 6775 goto finish; 6776 } 6777 requestedPrelink = true; 6778 6779 /* Now it's time to see if we have a reason to rebuild. We may have done 6780 * some loads and unloads but the kernel cache didn't actually change. 6781 * We will rebuild if any kext is not marked prelinked AND is not in our 6782 * list of prelinked kexts that got unloaded. (see radar 9055303) 6783 */ 6784 kextIterator = OSCollectionIterator::withCollection(sKextsByID); 6785 if (!kextIterator) { 6786 goto finish; 6787 } 6788 6789 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 6790 OSKext * thisKext; // do not release 6791 6792 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 6793 if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) { 6794 continue; 6795 } 6796 6797 if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID)) { 6798 continue; 6799 } 6800 /* kext is loaded and was not in current kernel cache so let's rebuild 6801 */ 6802 doRebuild = true; 6803 OSKextLog(/* kext */ NULL, 6804 kOSKextLogArchiveFlag, 6805 "considerRebuildOfPrelinkedKernel %s triggered rebuild", 6806 thisKext->bundleID->getCStringNoCopy()); 6807 break; 6808 } 6809 sUnloadedPrelinkedKexts->flushCollection(); 6810 6811 if (!doRebuild) { 6812 goto finish; 6813 } 6814 6815 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink, 6816 &prelinkRequest); 6817 if (checkResult != kOSReturnSuccess) { 6818 goto finish; 6819 } 6820 6821 if (!sKernelRequests->setObject(prelinkRequest)) { 6822 goto finish; 6823 } 6824 6825 OSKext::pingKextd(); 6826 6827 finish: 6828 IORecursiveLockUnlock(sKextLock); 6829 OSSafeRelease(prelinkRequest); 6830 OSSafeRelease(kextIterator); 6831 6832 return; 6833 } 6834 6835 #if PRAGMA_MARK 6836 #pragma mark Dependencies 6837 #endif 6838 /********************************************************************* 6839 *********************************************************************/ 6840 bool 6841 OSKext::resolveDependencies( 6842 OSArray * loopStack) 6843 { 6844 bool result = false; 6845 OSArray * localLoopStack = NULL; // must release 6846 bool addedToLoopStack = false; 6847 OSDictionary * libraries = NULL; // do not release 6848 OSCollectionIterator * libraryIterator = NULL; // must release 6849 OSString * libraryID = NULL; // do not release 6850 OSString * infoString = NULL; // do not release 6851 OSString * readableString = NULL; // do not release 6852 OSKext * libraryKext = NULL; // do not release 6853 bool hasRawKernelDependency = false; 6854 bool hasKernelDependency = false; 6855 bool hasKPIDependency = false; 6856 bool hasPrivateKPIDependency = false; 6857 unsigned int count; 6858 6859 /* A kernel component will automatically have this flag set, 6860 * and a loaded kext should also have it set (as should all its 6861 * loaded dependencies). 6862 */ 6863 if (flags.hasAllDependencies) { 6864 result = true; 6865 goto finish; 6866 } 6867 6868 /* Check for loops in the dependency graph. 6869 */ 6870 if (loopStack) { 6871 if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) { 6872 OSKextLog(this, 6873 kOSKextLogErrorLevel | 6874 kOSKextLogDependenciesFlag, 6875 "Kext %s has a dependency loop; can't resolve dependencies.", 6876 getIdentifierCString()); 6877 goto finish; 6878 } 6879 } else { 6880 OSKextLog(this, 6881 kOSKextLogStepLevel | 6882 kOSKextLogDependenciesFlag, 6883 "Kext %s resolving dependencies.", 6884 getIdentifierCString()); 6885 6886 loopStack = OSArray::withCapacity(6); // any small capacity will do 6887 if (!loopStack) { 6888 OSKextLog(this, 6889 kOSKextLogErrorLevel | 6890 kOSKextLogDependenciesFlag, 6891 "Kext %s can't create bookkeeping stack to resolve dependencies.", 6892 getIdentifierCString()); 6893 goto finish; 6894 } 6895 localLoopStack = loopStack; 6896 } 6897 if (!loopStack->setObject(this)) { 6898 OSKextLog(this, 6899 kOSKextLogErrorLevel | 6900 kOSKextLogDependenciesFlag, 6901 "Kext %s - internal error resolving dependencies.", 6902 getIdentifierCString()); 6903 goto finish; 6904 } 6905 addedToLoopStack = true; 6906 6907 /* Purge any existing kexts in the dependency list and start over. 6908 */ 6909 flushDependencies(); 6910 if (dependencies) { 6911 OSKextLog(this, 6912 kOSKextLogErrorLevel | 6913 kOSKextLogDependenciesFlag, 6914 "Kext %s - internal error resolving dependencies.", 6915 getIdentifierCString()); 6916 } 6917 6918 libraries = OSDynamicCast(OSDictionary, 6919 getPropertyForHostArch(kOSBundleLibrariesKey)); 6920 if (libraries == NULL || libraries->getCount() == 0) { 6921 OSKextLog(this, 6922 kOSKextLogErrorLevel | 6923 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 6924 "Kext %s - can't resolve dependencies; %s missing/invalid type.", 6925 getIdentifierCString(), kOSBundleLibrariesKey); 6926 goto finish; 6927 } 6928 6929 /* Make a new array to hold the dependencies (flush freed the old one). 6930 */ 6931 dependencies = OSArray::withCapacity(libraries->getCount()); 6932 if (!dependencies) { 6933 OSKextLog(this, 6934 kOSKextLogErrorLevel | 6935 kOSKextLogDependenciesFlag, 6936 "Kext %s - can't allocate dependencies array.", 6937 getIdentifierCString()); 6938 goto finish; 6939 } 6940 6941 // xxx - compat: We used to add an implicit dependency on kernel 6.0 6942 // xxx - compat: if none were declared. 6943 6944 libraryIterator = OSCollectionIterator::withCollection(libraries); 6945 if (!libraryIterator) { 6946 OSKextLog(this, 6947 kOSKextLogErrorLevel | 6948 kOSKextLogDependenciesFlag, 6949 "Kext %s - can't allocate dependencies iterator.", 6950 getIdentifierCString()); 6951 goto finish; 6952 } 6953 6954 while ((libraryID = OSDynamicCast(OSString, 6955 libraryIterator->getNextObject()))) { 6956 6957 const char * library_id = libraryID->getCStringNoCopy(); 6958 6959 OSString * libraryVersion = OSDynamicCast(OSString, 6960 libraries->getObject(libraryID)); 6961 if (libraryVersion == NULL) { 6962 OSKextLog(this, 6963 kOSKextLogErrorLevel | 6964 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 6965 "Kext %s - illegal type in OSBundleLibraries.", 6966 getIdentifierCString()); 6967 goto finish; 6968 } 6969 6970 OSKextVersion libraryVers = 6971 OSKextParseVersionString(libraryVersion->getCStringNoCopy()); 6972 if (libraryVers == -1) { 6973 OSKextLog(this, 6974 kOSKextLogErrorLevel | 6975 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 6976 "Kext %s - invalid library version %s.", 6977 getIdentifierCString(), 6978 libraryVersion->getCStringNoCopy()); 6979 goto finish; 6980 } 6981 6982 libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID)); 6983 if (libraryKext == NULL) { 6984 OSKextLog(this, 6985 kOSKextLogErrorLevel | 6986 kOSKextLogDependenciesFlag, 6987 "Kext %s - library kext %s not found.", 6988 getIdentifierCString(), library_id); 6989 goto finish; 6990 } 6991 6992 if (!libraryKext->isCompatibleWithVersion(libraryVers)) { 6993 OSKextLog(this, 6994 kOSKextLogErrorLevel | 6995 kOSKextLogDependenciesFlag, 6996 "Kext %s - library kext %s not compatible " 6997 "with requested version %s.", 6998 getIdentifierCString(), library_id, 6999 libraryVersion->getCStringNoCopy()); 7000 goto finish; 7001 } 7002 7003 /* If a nonprelinked library somehow got into the mix for a 7004 * prelinked kext, at any point in the chain, we must fail 7005 * because the prelinked relocs for the library will be all wrong. 7006 */ 7007 if (this->isPrelinked() && 7008 libraryKext->declaresExecutable() && 7009 !libraryKext->isPrelinked()) { 7010 7011 OSKextLog(this, 7012 kOSKextLogErrorLevel | 7013 kOSKextLogDependenciesFlag, 7014 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.", 7015 getIdentifierCString(), library_id, 7016 libraryVersion->getCStringNoCopy()); 7017 goto finish; 7018 } 7019 7020 if (!libraryKext->resolveDependencies(loopStack)) { 7021 goto finish; 7022 } 7023 7024 /* Add the library directly only if it has an executable to link. 7025 * Otherwise it's just used to collect other dependencies, so put 7026 * *its* dependencies on the list for this kext. 7027 */ 7028 // xxx - We are losing info here; would like to make fake entries or 7029 // xxx - keep these in the dependency graph for loaded kexts. 7030 // xxx - I really want to make kernel components not a special case! 7031 if (libraryKext->declaresExecutable() || 7032 libraryKext->isInterface()) { 7033 7034 if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) { 7035 dependencies->setObject(libraryKext); 7036 7037 OSKextLog(this, 7038 kOSKextLogDetailLevel | 7039 kOSKextLogDependenciesFlag, 7040 "Kext %s added dependency %s.", 7041 getIdentifierCString(), 7042 libraryKext->getIdentifierCString()); 7043 } 7044 } else { 7045 int numLibDependencies = libraryKext->getNumDependencies(); 7046 OSArray * libraryDependencies = libraryKext->getDependencies(); 7047 int index; 7048 7049 if (numLibDependencies) { 7050 // xxx - this msg level should be 1 lower than the per-kext one 7051 OSKextLog(this, 7052 kOSKextLogDetailLevel | 7053 kOSKextLogDependenciesFlag, 7054 "Kext %s pulling %d dependencies from codeless library %s.", 7055 getIdentifierCString(), 7056 numLibDependencies, 7057 libraryKext->getIdentifierCString()); 7058 } 7059 for (index = 0; index < numLibDependencies; index++) { 7060 OSKext * thisLibDependency = OSDynamicCast(OSKext, 7061 libraryDependencies->getObject(index)); 7062 if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) { 7063 dependencies->setObject(thisLibDependency); 7064 OSKextLog(this, 7065 kOSKextLogDetailLevel | 7066 kOSKextLogDependenciesFlag, 7067 "Kext %s added dependency %s from codeless library %s.", 7068 getIdentifierCString(), 7069 thisLibDependency->getIdentifierCString(), 7070 libraryKext->getIdentifierCString()); 7071 } 7072 } 7073 } 7074 7075 if ((strlen(library_id) == strlen(KERNEL_LIB)) && 7076 0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB)-1)) { 7077 7078 hasRawKernelDependency = true; 7079 } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) { 7080 hasKernelDependency = true; 7081 } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) { 7082 hasKPIDependency = true; 7083 if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI)-1)) { 7084 hasPrivateKPIDependency = true; 7085 } 7086 } 7087 } 7088 7089 if (hasRawKernelDependency) { 7090 OSKextLog(this, 7091 kOSKextLogErrorLevel | 7092 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 7093 "Error - kext %s declares a dependency on %s, which is not permitted.", 7094 getIdentifierCString(), KERNEL_LIB); 7095 goto finish; 7096 } 7097 #if __LP64__ 7098 if (hasKernelDependency) { 7099 OSKextLog(this, 7100 kOSKextLogErrorLevel | 7101 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 7102 "Error - kext %s declares %s dependencies. " 7103 "Only %s* dependencies are supported for 64-bit kexts.", 7104 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 7105 goto finish; 7106 } 7107 if (!hasKPIDependency) { 7108 OSKextLog(this, 7109 kOSKextLogWarningLevel | 7110 kOSKextLogDependenciesFlag, 7111 "Warning - kext %s declares no %s* dependencies. " 7112 "If it uses any KPIs, the link may fail with undefined symbols.", 7113 getIdentifierCString(), KPI_LIB_PREFIX); 7114 } 7115 #else /* __LP64__ */ 7116 // xxx - will change to flatly disallow "kernel" dependencies at some point 7117 // xxx - is it invalid to do both "com.apple.kernel" and any 7118 // xxx - "com.apple.kernel.*"? 7119 7120 if (hasKernelDependency && hasKPIDependency) { 7121 OSKextLog(this, 7122 kOSKextLogWarningLevel | 7123 kOSKextLogDependenciesFlag, 7124 "Warning - kext %s has immediate dependencies on both " 7125 "%s* and %s* components; use only one style.", 7126 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 7127 } 7128 7129 if (!hasKernelDependency && !hasKPIDependency) { 7130 // xxx - do we want to use validation flag for these too? 7131 OSKextLog(this, 7132 kOSKextLogWarningLevel | 7133 kOSKextLogDependenciesFlag, 7134 "Warning - %s declares no kernel dependencies; using %s.", 7135 getIdentifierCString(), KERNEL6_LIB); 7136 OSKext * kernelKext = OSDynamicCast(OSKext, 7137 sKextsByID->getObject(KERNEL6_LIB)); 7138 if (kernelKext) { 7139 dependencies->setObject(kernelKext); 7140 } else { 7141 OSKextLog(this, 7142 kOSKextLogErrorLevel | 7143 kOSKextLogDependenciesFlag, 7144 "Error - Library %s not found for %s.", 7145 KERNEL6_LIB, getIdentifierCString()); 7146 } 7147 } 7148 7149 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of 7150 * its indirect dependencies to simulate old-style linking. XXX - Should 7151 * check for duplicates. 7152 */ 7153 if (!hasKPIDependency) { 7154 unsigned int i; 7155 7156 flags.hasBleedthrough = true; 7157 7158 count = getNumDependencies(); 7159 7160 /* We add to the dependencies array in this loop, but do not iterate 7161 * past its original count. 7162 */ 7163 for (i = 0; i < count; i++) { 7164 OSKext * dependencyKext = OSDynamicCast(OSKext, 7165 dependencies->getObject(i)); 7166 dependencyKext->addBleedthroughDependencies(dependencies); 7167 } 7168 } 7169 #endif /* __LP64__ */ 7170 7171 if (hasPrivateKPIDependency) { 7172 bool hasApplePrefix = false; 7173 bool infoCopyrightIsValid = false; 7174 bool readableCopyrightIsValid = false; 7175 7176 hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(), 7177 APPLE_KEXT_PREFIX); 7178 7179 infoString = OSDynamicCast(OSString, 7180 getPropertyForHostArch("CFBundleGetInfoString")); 7181 if (infoString) { 7182 infoCopyrightIsValid = 7183 kxld_validate_copyright_string(infoString->getCStringNoCopy()); 7184 } 7185 7186 readableString = OSDynamicCast(OSString, 7187 getPropertyForHostArch("NSHumanReadableCopyright")); 7188 if (readableString) { 7189 readableCopyrightIsValid = 7190 kxld_validate_copyright_string(readableString->getCStringNoCopy()); 7191 } 7192 7193 if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) { 7194 OSKextLog(this, 7195 kOSKextLogErrorLevel | 7196 kOSKextLogDependenciesFlag, 7197 "Error - kext %s declares a dependency on %s. " 7198 "Only Apple kexts may declare a dependency on %s.", 7199 getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI); 7200 goto finish; 7201 } 7202 } 7203 7204 result = true; 7205 flags.hasAllDependencies = 1; 7206 7207 finish: 7208 7209 if (addedToLoopStack) { 7210 count = loopStack->getCount(); 7211 if (count > 0 && (this == loopStack->getObject(count - 1))) { 7212 loopStack->removeObject(count - 1); 7213 } else { 7214 OSKextLog(this, 7215 kOSKextLogErrorLevel | 7216 kOSKextLogDependenciesFlag, 7217 "Kext %s - internal error resolving dependencies.", 7218 getIdentifierCString()); 7219 } 7220 } 7221 7222 if (result && localLoopStack) { 7223 OSKextLog(this, 7224 kOSKextLogStepLevel | 7225 kOSKextLogDependenciesFlag, 7226 "Kext %s successfully resolved dependencies.", 7227 getIdentifierCString()); 7228 } 7229 7230 OSSafeRelease(localLoopStack); 7231 OSSafeRelease(libraryIterator); 7232 7233 return result; 7234 } 7235 7236 /********************************************************************* 7237 *********************************************************************/ 7238 bool 7239 OSKext::addBleedthroughDependencies(OSArray * anArray) 7240 { 7241 bool result = false; 7242 unsigned int dependencyIndex, dependencyCount; 7243 7244 dependencyCount = getNumDependencies(); 7245 7246 for (dependencyIndex = 0; 7247 dependencyIndex < dependencyCount; 7248 dependencyIndex++) { 7249 7250 OSKext * dependency = OSDynamicCast(OSKext, 7251 dependencies->getObject(dependencyIndex)); 7252 if (!dependency) { 7253 OSKextLog(this, 7254 kOSKextLogErrorLevel | 7255 kOSKextLogDependenciesFlag, 7256 "Kext %s - internal error propagating compatibility dependencies.", 7257 getIdentifierCString()); 7258 goto finish; 7259 } 7260 if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) { 7261 anArray->setObject(dependency); 7262 } 7263 dependency->addBleedthroughDependencies(anArray); 7264 } 7265 7266 result = true; 7267 7268 finish: 7269 return result; 7270 } 7271 7272 /********************************************************************* 7273 *********************************************************************/ 7274 bool 7275 OSKext::flushDependencies(bool forceFlag) 7276 { 7277 bool result = false; 7278 7279 /* Only clear the dependencies if the kext isn't loaded; 7280 * we need the info for loaded kexts to track references. 7281 */ 7282 if (!isLoaded() || forceFlag) { 7283 if (dependencies) { 7284 // xxx - check level 7285 OSKextLog(this, 7286 kOSKextLogProgressLevel | 7287 kOSKextLogDependenciesFlag, 7288 "Kext %s flushing dependencies.", 7289 getIdentifierCString()); 7290 OSSafeReleaseNULL(dependencies); 7291 7292 } 7293 if (!isKernelComponent()) { 7294 flags.hasAllDependencies = 0; 7295 } 7296 result = true; 7297 } 7298 7299 return result; 7300 } 7301 7302 /********************************************************************* 7303 *********************************************************************/ 7304 uint32_t 7305 OSKext::getNumDependencies(void) 7306 { 7307 if (!dependencies) { 7308 return 0; 7309 } 7310 return dependencies->getCount(); 7311 } 7312 7313 /********************************************************************* 7314 *********************************************************************/ 7315 OSArray * 7316 OSKext::getDependencies(void) 7317 { 7318 return dependencies; 7319 } 7320 7321 #if PRAGMA_MARK 7322 #pragma mark OSMetaClass Support 7323 #endif 7324 /********************************************************************* 7325 *********************************************************************/ 7326 OSReturn 7327 OSKext::addClass( 7328 OSMetaClass * aClass, 7329 uint32_t numClasses) 7330 { 7331 OSReturn result = kOSMetaClassNoInsKModSet; 7332 7333 if (!metaClasses) { 7334 metaClasses = OSSet::withCapacity(numClasses); 7335 if (!metaClasses) { 7336 goto finish; 7337 } 7338 } 7339 7340 if (metaClasses->containsObject(aClass)) { 7341 OSKextLog(this, 7342 kOSKextLogWarningLevel | 7343 kOSKextLogLoadFlag, 7344 "Notice - kext %s has already registered class %s.", 7345 getIdentifierCString(), 7346 aClass->getClassName()); 7347 result = kOSReturnSuccess; 7348 goto finish; 7349 } 7350 7351 if (!metaClasses->setObject(aClass)) { 7352 goto finish; 7353 } else { 7354 OSKextLog(this, 7355 kOSKextLogDetailLevel | 7356 kOSKextLogLoadFlag, 7357 "Kext %s registered class %s.", 7358 getIdentifierCString(), 7359 aClass->getClassName()); 7360 } 7361 7362 if (!flags.autounloadEnabled) { 7363 const OSMetaClass * metaScan = NULL; // do not release 7364 7365 for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) { 7366 if (metaScan == OSTypeID(IOService)) { 7367 7368 OSKextLog(this, 7369 kOSKextLogProgressLevel | 7370 kOSKextLogLoadFlag, 7371 "Kext %s has IOService subclass %s; enabling autounload.", 7372 getIdentifierCString(), 7373 aClass->getClassName()); 7374 7375 flags.autounloadEnabled = 1; 7376 break; 7377 } 7378 } 7379 } 7380 7381 notifyAddClassObservers(this, aClass, flags); 7382 7383 result = kOSReturnSuccess; 7384 7385 finish: 7386 if (result != kOSReturnSuccess) { 7387 OSKextLog(this, 7388 kOSKextLogErrorLevel | 7389 kOSKextLogLoadFlag, 7390 "Kext %s failed to register class %s.", 7391 getIdentifierCString(), 7392 aClass->getClassName()); 7393 } 7394 7395 return result; 7396 } 7397 7398 /********************************************************************* 7399 *********************************************************************/ 7400 OSReturn 7401 OSKext::removeClass( 7402 OSMetaClass * aClass) 7403 { 7404 OSReturn result = kOSMetaClassNoKModSet; 7405 7406 if (!metaClasses) { 7407 goto finish; 7408 } 7409 7410 if (!metaClasses->containsObject(aClass)) { 7411 OSKextLog(this, 7412 kOSKextLogWarningLevel | 7413 kOSKextLogLoadFlag, 7414 "Notice - kext %s asked to unregister unknown class %s.", 7415 getIdentifierCString(), 7416 aClass->getClassName()); 7417 result = kOSReturnSuccess; 7418 goto finish; 7419 } 7420 7421 OSKextLog(this, 7422 kOSKextLogDetailLevel | 7423 kOSKextLogLoadFlag, 7424 "Kext %s unregistering class %s.", 7425 getIdentifierCString(), 7426 aClass->getClassName()); 7427 7428 metaClasses->removeObject(aClass); 7429 7430 notifyRemoveClassObservers(this, aClass, flags); 7431 7432 result = kOSReturnSuccess; 7433 7434 finish: 7435 if (result != kOSReturnSuccess) { 7436 OSKextLog(this, 7437 kOSKextLogErrorLevel | 7438 kOSKextLogLoadFlag, 7439 "Failed to unregister kext %s class %s.", 7440 getIdentifierCString(), 7441 aClass->getClassName()); 7442 } 7443 return result; 7444 } 7445 7446 /********************************************************************* 7447 *********************************************************************/ 7448 OSSet * 7449 OSKext::getMetaClasses(void) 7450 { 7451 return metaClasses; 7452 } 7453 7454 /********************************************************************* 7455 *********************************************************************/ 7456 bool 7457 OSKext::hasOSMetaClassInstances(void) 7458 { 7459 bool result = false; 7460 OSCollectionIterator * classIterator = NULL; // must release 7461 OSMetaClass * checkClass = NULL; // do not release 7462 7463 if (!metaClasses) { 7464 goto finish; 7465 } 7466 7467 classIterator = OSCollectionIterator::withCollection(metaClasses); 7468 if (!classIterator) { 7469 // xxx - log alloc failure? 7470 goto finish; 7471 } 7472 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 7473 if (checkClass->getInstanceCount()) { 7474 result = true; 7475 goto finish; 7476 } 7477 } 7478 7479 finish: 7480 7481 OSSafeRelease(classIterator); 7482 return result; 7483 } 7484 7485 /********************************************************************* 7486 *********************************************************************/ 7487 /* static */ 7488 void 7489 OSKext::reportOSMetaClassInstances( 7490 const char * kextIdentifier, 7491 OSKextLogSpec msgLogSpec) 7492 { 7493 OSKext * theKext = NULL; // must release 7494 7495 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 7496 if (!theKext) { 7497 goto finish; 7498 } 7499 7500 theKext->reportOSMetaClassInstances(msgLogSpec); 7501 finish: 7502 OSSafeRelease(theKext); 7503 return; 7504 } 7505 7506 /********************************************************************* 7507 *********************************************************************/ 7508 void 7509 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec) 7510 { 7511 OSCollectionIterator * classIterator = NULL; // must release 7512 OSMetaClass * checkClass = NULL; // do not release 7513 7514 if (!metaClasses) { 7515 goto finish; 7516 } 7517 7518 classIterator = OSCollectionIterator::withCollection(metaClasses); 7519 if (!classIterator) { 7520 goto finish; 7521 } 7522 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 7523 if (checkClass->getInstanceCount()) { 7524 OSKextLog(this, 7525 msgLogSpec, 7526 " Kext %s class %s has %d instance%s.", 7527 getIdentifierCString(), 7528 checkClass->getClassName(), 7529 checkClass->getInstanceCount(), 7530 checkClass->getInstanceCount() == 1 ? "" : "s"); 7531 } 7532 } 7533 7534 finish: 7535 OSSafeRelease(classIterator); 7536 return; 7537 } 7538 7539 #if PRAGMA_MARK 7540 #pragma mark User-Space Requests 7541 #endif 7542 /********************************************************************* 7543 * XXX - this function is a big ugly mess 7544 *********************************************************************/ 7545 /* static */ 7546 OSReturn 7547 OSKext::handleRequest( 7548 host_priv_t hostPriv, 7549 OSKextLogSpec clientLogFilter, 7550 char * requestBuffer, 7551 uint32_t requestLength, 7552 char ** responseOut, 7553 uint32_t * responseLengthOut, 7554 char ** logInfoOut, 7555 uint32_t * logInfoLengthOut) 7556 { 7557 OSReturn result = kOSReturnError; 7558 kern_return_t kmem_result = KERN_FAILURE; 7559 7560 char * response = NULL; // returned by reference 7561 uint32_t responseLength = 0; 7562 7563 OSObject * parsedXML = NULL; // must release 7564 OSDictionary * requestDict = NULL; // do not release 7565 OSString * errorString = NULL; // must release 7566 7567 OSObject * responseObject = NULL; // must release 7568 7569 OSSerialize * serializer = NULL; // must release 7570 7571 OSArray * logInfoArray = NULL; // must release 7572 7573 OSString * predicate = NULL; // do not release 7574 OSString * kextIdentifier = NULL; // do not release 7575 OSArray * kextIdentifiers = NULL; // do not release 7576 OSKext * theKext = NULL; // do not release 7577 OSBoolean * boolArg = NULL; // do not release 7578 7579 IORecursiveLockLock(sKextLock); 7580 7581 if (responseOut) { 7582 *responseOut = NULL; 7583 *responseLengthOut = 0; 7584 } 7585 if (logInfoOut) { 7586 *logInfoOut = NULL; 7587 *logInfoLengthOut = 0; 7588 } 7589 7590 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 7591 7592 /* XML must be nul-terminated. 7593 */ 7594 if (requestBuffer[requestLength - 1] != '\0') { 7595 OSKextLog(/* kext */ NULL, 7596 kOSKextLogErrorLevel | 7597 kOSKextLogIPCFlag, 7598 "Invalid request from user space (not nul-terminated)."); 7599 result = kOSKextReturnBadData; 7600 goto finish; 7601 } 7602 parsedXML = OSUnserializeXML((const char *)requestBuffer, &errorString); 7603 if (parsedXML) { 7604 requestDict = OSDynamicCast(OSDictionary, parsedXML); 7605 } 7606 if (!requestDict) { 7607 const char * errorCString = "(unknown error)"; 7608 7609 if (errorString && errorString->getCStringNoCopy()) { 7610 errorCString = errorString->getCStringNoCopy(); 7611 } else if (parsedXML) { 7612 errorCString = "not a dictionary"; 7613 } 7614 OSKextLog(/* kext */ NULL, 7615 kOSKextLogErrorLevel | 7616 kOSKextLogIPCFlag, 7617 "Error unserializing request from user space: %s.", 7618 errorCString); 7619 result = kOSKextReturnSerialization; 7620 goto finish; 7621 } 7622 7623 predicate = _OSKextGetRequestPredicate(requestDict); 7624 if (!predicate) { 7625 OSKextLog(/* kext */ NULL, 7626 kOSKextLogErrorLevel | 7627 kOSKextLogIPCFlag, 7628 "Recieved kext request from user space with no predicate."); 7629 result = kOSKextReturnInvalidArgument; 7630 goto finish; 7631 } 7632 7633 OSKextLog(/* kext */ NULL, 7634 kOSKextLogDebugLevel | 7635 kOSKextLogIPCFlag, 7636 "Received '%s' request from user space.", 7637 predicate->getCStringNoCopy()); 7638 7639 result = kOSKextReturnNotPrivileged; 7640 if (hostPriv == HOST_PRIV_NULL) { 7641 /* must be root to use these kext requests */ 7642 if (predicate->isEqualTo(kKextRequestPredicateUnload) || 7643 predicate->isEqualTo(kKextRequestPredicateStart) || 7644 predicate->isEqualTo(kKextRequestPredicateStop) || 7645 predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) || 7646 predicate->isEqualTo(kKextRequestPredicateSendResource) ) { 7647 OSKextLog(/* kext */ NULL, 7648 kOSKextLogErrorLevel | 7649 kOSKextLogIPCFlag, 7650 "Access Failure - must be root user."); 7651 goto finish; 7652 } 7653 } 7654 7655 /* Get common args in anticipation of use. 7656 */ 7657 kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument( 7658 requestDict, kKextRequestArgumentBundleIdentifierKey)); 7659 kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 7660 requestDict, kKextRequestArgumentBundleIdentifierKey)); 7661 if (kextIdentifier) { 7662 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 7663 } 7664 boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 7665 requestDict, kKextRequestArgumentValueKey)); 7666 7667 result = kOSKextReturnInvalidArgument; 7668 7669 if (predicate->isEqualTo(kKextRequestPredicateStart)) { 7670 if (!kextIdentifier) { 7671 OSKextLog(/* kext */ NULL, 7672 kOSKextLogErrorLevel | 7673 kOSKextLogIPCFlag, 7674 "Invalid arguments to kext start request."); 7675 } else if (!theKext) { 7676 OSKextLog(/* kext */ NULL, 7677 kOSKextLogErrorLevel | 7678 kOSKextLogIPCFlag, 7679 "Kext %s not found for start request.", 7680 kextIdentifier->getCStringNoCopy()); 7681 result = kOSKextReturnNotFound; 7682 } else { 7683 result = theKext->start(); 7684 } 7685 7686 } else if (predicate->isEqualTo(kKextRequestPredicateStop)) { 7687 if (!kextIdentifier) { 7688 OSKextLog(/* kext */ NULL, 7689 kOSKextLogErrorLevel | 7690 kOSKextLogIPCFlag, 7691 "Invalid arguments to kext stop request."); 7692 } else if (!theKext) { 7693 OSKextLog(/* kext */ NULL, 7694 kOSKextLogErrorLevel | 7695 kOSKextLogIPCFlag, 7696 "Kext %s not found for stop request.", 7697 kextIdentifier->getCStringNoCopy()); 7698 result = kOSKextReturnNotFound; 7699 } else { 7700 result = theKext->stop(); 7701 } 7702 7703 } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) { 7704 if (!kextIdentifier) { 7705 OSKextLog(/* kext */ NULL, 7706 kOSKextLogErrorLevel | 7707 kOSKextLogIPCFlag, 7708 "Invalid arguments to kext unload request."); 7709 } else if (!theKext) { 7710 OSKextLog(/* kext */ NULL, 7711 kOSKextLogErrorLevel | 7712 kOSKextLogIPCFlag, 7713 "Kext %s not found for unload request.", 7714 kextIdentifier->getCStringNoCopy()); 7715 result = kOSKextReturnNotFound; 7716 } else { 7717 OSBoolean * terminateFlag = OSDynamicCast(OSBoolean, 7718 _OSKextGetRequestArgument(requestDict, 7719 kKextRequestArgumentTerminateIOServicesKey)); 7720 result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue); 7721 } 7722 7723 } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) { 7724 result = OSKext::dispatchResource(requestDict); 7725 7726 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) { 7727 OSBoolean * delayAutounloadBool = NULL; 7728 OSObject * infoKeysRaw = NULL; 7729 OSArray * infoKeys = NULL; 7730 uint32_t infoKeysCount = 0; 7731 7732 delayAutounloadBool = OSDynamicCast(OSBoolean, 7733 _OSKextGetRequestArgument(requestDict, 7734 kKextRequestArgumentDelayAutounloadKey)); 7735 7736 /* If asked to delay autounload, reset the timer if it's currently set. 7737 * (That is, don't schedule an unload if one isn't already pending. 7738 */ 7739 if (delayAutounloadBool == kOSBooleanTrue) { 7740 OSKext::considerUnloads(/* rescheduleOnly? */ true); 7741 } 7742 7743 infoKeysRaw = _OSKextGetRequestArgument(requestDict, 7744 kKextRequestArgumentInfoKeysKey); 7745 infoKeys = OSDynamicCast(OSArray, infoKeysRaw); 7746 if (infoKeysRaw && !infoKeys) { 7747 OSKextLog(/* kext */ NULL, 7748 kOSKextLogErrorLevel | 7749 kOSKextLogIPCFlag, 7750 "Invalid arguments to kext info request."); 7751 goto finish; 7752 } 7753 7754 if (infoKeys) { 7755 infoKeysCount = infoKeys->getCount(); 7756 for (uint32_t i = 0; i < infoKeysCount; i++) { 7757 if (!OSDynamicCast(OSString, infoKeys->getObject(i))) { 7758 OSKextLog(/* kext */ NULL, 7759 kOSKextLogErrorLevel | 7760 kOSKextLogIPCFlag, 7761 "Invalid arguments to kext info request."); 7762 goto finish; 7763 } 7764 } 7765 } 7766 7767 responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys); 7768 if (!responseObject) { 7769 result = kOSKextReturnInternalError; 7770 } else { 7771 OSKextLog(/* kext */ NULL, 7772 kOSKextLogDebugLevel | 7773 kOSKextLogIPCFlag, 7774 "Returning loaded kext info."); 7775 result = kOSReturnSuccess; 7776 } 7777 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 7778 7779 /* Hand the current sKernelRequests array to the caller 7780 * (who must release it), and make a new one. 7781 */ 7782 responseObject = sKernelRequests; 7783 sKernelRequests = OSArray::withCapacity(0); 7784 sPostedKextLoadIdentifiers->flushCollection(); 7785 OSKextLog(/* kext */ NULL, 7786 kOSKextLogDebugLevel | 7787 kOSKextLogIPCFlag, 7788 "Returning kernel requests."); 7789 result = kOSReturnSuccess; 7790 7791 } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) { 7792 7793 /* Return the set of all requested bundle identifiers */ 7794 responseObject = sAllKextLoadIdentifiers; 7795 responseObject->retain(); 7796 OSKextLog(/* kext */ NULL, 7797 kOSKextLogDebugLevel | 7798 kOSKextLogIPCFlag, 7799 "Returning load requests."); 7800 result = kOSReturnSuccess; 7801 } 7802 else { 7803 OSKextLog(/* kext */ NULL, 7804 kOSKextLogDebugLevel | 7805 kOSKextLogIPCFlag, 7806 "Received '%s' invalid request from user space.", 7807 predicate->getCStringNoCopy()); 7808 goto finish; 7809 } 7810 7811 /********** 7812 * Now we have handle the request, or not. Gather up the response & logging 7813 * info to ship to user space. 7814 *********/ 7815 7816 /* Note: Nothing in OSKext is supposed to retain requestDict, 7817 * but you never know.... 7818 */ 7819 if (requestDict->getRetainCount() > 1) { 7820 OSKextLog(/* kext */ NULL, 7821 kOSKextLogWarningLevel | 7822 kOSKextLogIPCFlag, 7823 "Request from user space still retained by a kext; " 7824 "probable memory leak."); 7825 } 7826 7827 if (responseOut && responseObject) { 7828 serializer = OSSerialize::withCapacity(0); 7829 if (!serializer) { 7830 result = kOSKextReturnNoMemory; 7831 goto finish; 7832 } 7833 7834 if (!responseObject->serialize(serializer)) { 7835 OSKextLog(/* kext */ NULL, 7836 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 7837 "Failed to serialize response to request from user space."); 7838 result = kOSKextReturnSerialization; 7839 goto finish; 7840 } 7841 7842 response = (char *)serializer->text(); 7843 responseLength = serializer->getLength(); 7844 } 7845 7846 if (responseOut && response) { 7847 char * buffer; 7848 7849 /* This kmem_alloc sets the return value of the function. 7850 */ 7851 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, 7852 round_page(responseLength), VM_KERN_MEMORY_OSKEXT); 7853 if (kmem_result != KERN_SUCCESS) { 7854 OSKextLog(/* kext */ NULL, 7855 kOSKextLogErrorLevel | 7856 kOSKextLogIPCFlag, 7857 "Failed to copy response to request from user space."); 7858 result = kmem_result; 7859 goto finish; 7860 } else { 7861 /* 11981737 - clear uninitialized data in last page */ 7862 bzero((void *)(buffer + responseLength), 7863 (round_page(responseLength) - responseLength)); 7864 memcpy(buffer, response, responseLength); 7865 *responseOut = buffer; 7866 *responseLengthOut = responseLength; 7867 } 7868 } 7869 7870 finish: 7871 7872 /* Gather up the collected log messages for user space. Any messages 7873 * messages past this call will not make it up as log messages but 7874 * will be in the system log. Note that we ignore the return of the 7875 * serialize; it has no bearing on the operation at hand even if we 7876 * fail to get the log messages. 7877 */ 7878 logInfoArray = OSKext::clearUserSpaceLogFilter(); 7879 7880 if (logInfoArray && logInfoOut && logInfoLengthOut) { 7881 (void)OSKext::serializeLogInfo(logInfoArray, 7882 logInfoOut, logInfoLengthOut); 7883 } 7884 7885 IORecursiveLockUnlock(sKextLock); 7886 7887 OSSafeRelease(parsedXML); 7888 OSSafeRelease(errorString); 7889 OSSafeRelease(responseObject); 7890 OSSafeRelease(serializer); 7891 OSSafeRelease(logInfoArray); 7892 7893 return result; 7894 } 7895 7896 7897 // #include <InstrProfiling.h> 7898 extern "C" { 7899 7900 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin, 7901 const char *DataEnd, 7902 const char *CountersBegin, 7903 const char *CountersEnd , 7904 const char *NamesBegin, 7905 const char *NamesEnd); 7906 int __llvm_profile_write_buffer_internal(char *Buffer, 7907 const char *DataBegin, 7908 const char *DataEnd, 7909 const char *CountersBegin, 7910 const char *CountersEnd , 7911 const char *NamesBegin, 7912 const char *NamesEnd); 7913 } 7914 7915 7916 static 7917 void OSKextPgoMetadataPut(char *pBuffer, 7918 size_t *position, 7919 size_t bufferSize, 7920 uint32_t *num_pairs, 7921 const char *key, 7922 const char *value) 7923 { 7924 size_t strlen_key = strlen(key); 7925 size_t strlen_value = strlen(value); 7926 size_t len = strlen(key) + 1 + strlen(value) + 1; 7927 char *pos = pBuffer + *position; 7928 *position += len; 7929 if (pBuffer && bufferSize && *position <= bufferSize) { 7930 memcpy(pos, key, strlen_key); pos += strlen_key; 7931 *(pos++) = '='; 7932 memcpy(pos, value, strlen_value); pos += strlen_value; 7933 *(pos++) = 0; 7934 if (num_pairs) { 7935 (*num_pairs)++; 7936 } 7937 } 7938 } 7939 7940 7941 static 7942 void OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max) 7943 { 7944 *position += strlen(key) + 1 + value_max + 1; 7945 } 7946 7947 7948 static 7949 void OSKextPgoMetadataPutAll(OSKext *kext, 7950 uuid_t instance_uuid, 7951 char *pBuffer, 7952 size_t *position, 7953 size_t bufferSize, 7954 uint32_t *num_pairs) 7955 { 7956 assert_static(sizeof(clock_sec_t) % 2 == 0); 7957 //log_10 2^16 ≈ 4.82 7958 const size_t max_secs_string_size = 5 * sizeof(clock_sec_t)/2; 7959 const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6; 7960 7961 if (!pBuffer) { 7962 OSKextPgoMetadataPutMax(position, "INSTANCE", 36); 7963 OSKextPgoMetadataPutMax(position, "UUID", 36); 7964 OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size); 7965 } else { 7966 uuid_string_t instance_uuid_string; 7967 uuid_unparse(instance_uuid, instance_uuid_string); 7968 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 7969 "INSTANCE", instance_uuid_string); 7970 7971 OSData *uuid_data; 7972 uuid_t uuid; 7973 uuid_string_t uuid_string; 7974 uuid_data = kext->copyUUID(); 7975 if (uuid_data) { 7976 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 7977 OSSafeRelease(uuid_data); 7978 uuid_unparse(uuid, uuid_string); 7979 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 7980 "UUID", uuid_string); 7981 } 7982 7983 clock_sec_t secs; 7984 clock_usec_t usecs; 7985 clock_get_calendar_microtime(&secs, &usecs); 7986 assert(usecs < 1000000); 7987 char timestamp[max_timestamp_string_size + 1]; 7988 assert_static(sizeof(long) >= sizeof(clock_sec_t)); 7989 snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs); 7990 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 7991 "TIMESTAMP", timestamp); 7992 } 7993 7994 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 7995 "NAME", kext->getIdentifierCString()); 7996 7997 char versionCString[kOSKextVersionMaxLength]; 7998 OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength); 7999 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 8000 "VERSION", versionCString); 8001 8002 } 8003 8004 static 8005 size_t OSKextPgoMetadataSize(OSKext *kext) 8006 { 8007 size_t position = 0; 8008 uuid_t fakeuuid = {}; 8009 OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL); 8010 return position; 8011 } 8012 8013 8014 int OSKextGrabPgoDataLocked(OSKext *kext, 8015 bool metadata, 8016 uuid_t instance_uuid, 8017 uint64_t *pSize, 8018 char *pBuffer, 8019 uint64_t bufferSize) 8020 { 8021 8022 int err = 0; 8023 8024 kernel_section_t *sect_prf_data = NULL; 8025 kernel_section_t *sect_prf_name = NULL; 8026 kernel_section_t *sect_prf_cnts = NULL; 8027 uint64_t size; 8028 size_t metadata_size = 0; 8029 8030 sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data"); 8031 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name"); 8032 sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 8033 8034 if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) { 8035 err = ENOTSUP; 8036 goto out; 8037 } 8038 8039 size = __llvm_profile_get_size_for_buffer_internal( 8040 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 8041 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 8042 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 8043 8044 if (metadata) { 8045 metadata_size = OSKextPgoMetadataSize(kext); 8046 size += metadata_size; 8047 size += sizeof(pgo_metadata_footer); 8048 } 8049 8050 8051 if (pSize) { 8052 *pSize = size; 8053 } 8054 8055 if (pBuffer && bufferSize) { 8056 if (bufferSize < size) { 8057 err = ERANGE; 8058 goto out; 8059 } 8060 8061 err = __llvm_profile_write_buffer_internal( 8062 pBuffer, 8063 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 8064 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 8065 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 8066 8067 if (err) { 8068 err = EIO; 8069 goto out; 8070 } 8071 8072 if (metadata) { 8073 char *end_of_buffer = pBuffer + size; 8074 struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer)); 8075 char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size); 8076 8077 size_t metadata_position = 0; 8078 uint32_t num_pairs = 0; 8079 OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs); 8080 while (metadata_position < metadata_size) { 8081 metadata_buffer[metadata_position++] = 0; 8082 } 8083 8084 struct pgo_metadata_footer footer; 8085 footer.magic = htonl(0x6d657461); 8086 footer.number_of_pairs = htonl( num_pairs ); 8087 footer.offset_to_pairs = htonl( sizeof(struct pgo_metadata_footer) + metadata_size ); 8088 memcpy(footerp, &footer, sizeof(footer)); 8089 } 8090 8091 } 8092 8093 out: 8094 return err; 8095 } 8096 8097 8098 int 8099 OSKextGrabPgoData(uuid_t uuid, 8100 uint64_t *pSize, 8101 char *pBuffer, 8102 uint64_t bufferSize, 8103 int wait_for_unload, 8104 int metadata) 8105 { 8106 int err = 0; 8107 OSKext *kext = NULL; 8108 8109 8110 IORecursiveLockLock(sKextLock); 8111 8112 kext = OSKext::lookupKextWithUUID(uuid); 8113 if (!kext) { 8114 err = ENOENT; 8115 goto out; 8116 } 8117 8118 if (wait_for_unload) { 8119 OSKextGrabPgoStruct s; 8120 8121 s.metadata = metadata; 8122 s.pSize = pSize; 8123 s.pBuffer = pBuffer; 8124 s.bufferSize = bufferSize; 8125 s.err = EINTR; 8126 8127 struct list_head *prev = &kext->pendingPgoHead; 8128 struct list_head *next = kext->pendingPgoHead.next; 8129 8130 s.list_head.prev = prev; 8131 s.list_head.next = next; 8132 8133 prev->next = &s.list_head; 8134 next->prev = &s.list_head; 8135 8136 kext->release(); 8137 kext = NULL; 8138 8139 IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE); 8140 8141 prev = s.list_head.prev; 8142 next = s.list_head.next; 8143 8144 prev->next = next; 8145 next->prev = prev; 8146 8147 err = s.err; 8148 8149 } else { 8150 err = OSKextGrabPgoDataLocked(kext, metadata, kext->instance_uuid, pSize, pBuffer, bufferSize); 8151 } 8152 8153 out: 8154 if (kext) { 8155 kext->release(); 8156 } 8157 8158 IORecursiveLockUnlock(sKextLock); 8159 8160 return err; 8161 } 8162 8163 8164 /********************************************************************* 8165 *********************************************************************/ 8166 /* static */ 8167 OSDictionary * 8168 OSKext::copyLoadedKextInfo( 8169 OSArray * kextIdentifiers, 8170 OSArray * infoKeys) 8171 { 8172 OSDictionary * result = NULL; 8173 OSDictionary * kextInfo = NULL; // must release 8174 uint32_t count, i; 8175 uint32_t idCount = 0; 8176 uint32_t idIndex = 0; 8177 8178 IORecursiveLockLock(sKextLock); 8179 8180 #if CONFIG_MACF 8181 /* Is the calling process allowed to query kext info? */ 8182 if (current_task() != kernel_task) { 8183 int macCheckResult = 0; 8184 kauth_cred_t cred = NULL; 8185 8186 cred = kauth_cred_get_with_ref(); 8187 macCheckResult = mac_kext_check_query(cred); 8188 kauth_cred_unref(&cred); 8189 8190 if (macCheckResult != 0) { 8191 OSKextLog(/* kext */ NULL, 8192 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 8193 "Failed to query kext info (MAC policy error 0x%x).", 8194 macCheckResult); 8195 goto finish; 8196 } 8197 } 8198 #endif 8199 8200 /* Empty list of bundle ids is equivalent to no list (get all). 8201 */ 8202 if (kextIdentifiers && !kextIdentifiers->getCount()) { 8203 kextIdentifiers = NULL; 8204 } else if (kextIdentifiers) { 8205 idCount = kextIdentifiers->getCount(); 8206 } 8207 8208 /* Same for keys. 8209 */ 8210 if (infoKeys && !infoKeys->getCount()) { 8211 infoKeys = NULL; 8212 } 8213 8214 count = sLoadedKexts->getCount(); 8215 result = OSDictionary::withCapacity(count); 8216 if (!result) { 8217 goto finish; 8218 } 8219 8220 #if 0 8221 OSKextLog(/* kext */ NULL, 8222 kOSKextLogErrorLevel | 8223 kOSKextLogGeneralFlag, 8224 "kaslr: vm_kernel_slide 0x%lx \n", 8225 vm_kernel_slide); 8226 OSKextLog(/* kext */ NULL, 8227 kOSKextLogErrorLevel | 8228 kOSKextLogGeneralFlag, 8229 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n", 8230 vm_kernel_stext, vm_kernel_etext); 8231 OSKextLog(/* kext */ NULL, 8232 kOSKextLogErrorLevel | 8233 kOSKextLogGeneralFlag, 8234 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n", 8235 vm_kernel_base, vm_kernel_top); 8236 OSKextLog(/* kext */ NULL, 8237 kOSKextLogErrorLevel | 8238 kOSKextLogGeneralFlag, 8239 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n", 8240 vm_kext_base, vm_kext_top); 8241 OSKextLog(/* kext */ NULL, 8242 kOSKextLogErrorLevel | 8243 kOSKextLogGeneralFlag, 8244 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n", 8245 vm_prelink_stext, vm_prelink_etext); 8246 OSKextLog(/* kext */ NULL, 8247 kOSKextLogErrorLevel | 8248 kOSKextLogGeneralFlag, 8249 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n", 8250 vm_prelink_sinfo, vm_prelink_einfo); 8251 OSKextLog(/* kext */ NULL, 8252 kOSKextLogErrorLevel | 8253 kOSKextLogGeneralFlag, 8254 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n", 8255 vm_slinkedit, vm_elinkedit); 8256 #endif 8257 8258 for (i = 0; i < count; i++) { 8259 OSKext * thisKext = NULL; // do not release 8260 Boolean includeThis = true; 8261 8262 if (kextInfo) { 8263 kextInfo->release(); 8264 kextInfo = NULL; 8265 } 8266 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 8267 if (!thisKext) { 8268 continue; 8269 } 8270 8271 /* Skip current kext if we have a list of bundle IDs and 8272 * it isn't in the list. 8273 */ 8274 if (kextIdentifiers) { 8275 const OSString * thisKextID = thisKext->getIdentifier(); 8276 8277 includeThis = false; 8278 8279 for (idIndex = 0; idIndex < idCount; idIndex++) { 8280 const OSString * thisRequestID = OSDynamicCast(OSString, 8281 kextIdentifiers->getObject(idIndex)); 8282 if (thisKextID->isEqualTo(thisRequestID)) { 8283 includeThis = true; 8284 break; 8285 } 8286 } 8287 } 8288 8289 if (!includeThis) { 8290 continue; 8291 } 8292 8293 kextInfo = thisKext->copyInfo(infoKeys); 8294 if (kextInfo) { 8295 result->setObject(thisKext->getIdentifier(), kextInfo); 8296 } 8297 } 8298 8299 finish: 8300 IORecursiveLockUnlock(sKextLock); 8301 8302 if (kextInfo) kextInfo->release(); 8303 8304 return result; 8305 } 8306 8307 /********************************************************************* 8308 * Any info that needs to do allocations must goto finish on alloc 8309 * failure. Info that is just a lookup should just not set the object 8310 * if the info does not exist. 8311 *********************************************************************/ 8312 #define _OSKextLoadInfoDictCapacity (12) 8313 8314 OSDictionary * 8315 OSKext::copyInfo(OSArray * infoKeys) 8316 { 8317 OSDictionary * result = NULL; 8318 bool success = false; 8319 OSData * headerData = NULL; // must release 8320 OSNumber * cpuTypeNumber = NULL; // must release 8321 OSNumber * cpuSubtypeNumber = NULL; // must release 8322 OSString * versionString = NULL; // do not release 8323 uint32_t executablePathCStringSize = 0; 8324 char * executablePathCString = NULL; // must release 8325 OSString * executablePathString = NULL; // must release 8326 OSData * uuid = NULL; // must release 8327 OSNumber * scratchNumber = NULL; // must release 8328 OSArray * dependencyLoadTags = NULL; // must release 8329 OSCollectionIterator * metaClassIterator = NULL; // must release 8330 OSArray * metaClassInfo = NULL; // must release 8331 OSDictionary * metaClassDict = NULL; // must release 8332 OSMetaClass * thisMetaClass = NULL; // do not release 8333 OSString * metaClassName = NULL; // must release 8334 OSString * superclassName = NULL; // must release 8335 uint32_t count, i; 8336 8337 result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity); 8338 if (!result) { 8339 goto finish; 8340 } 8341 8342 8343 /* Empty keys means no keys, but NULL is quicker to check. 8344 */ 8345 if (infoKeys && !infoKeys->getCount()) { 8346 infoKeys = NULL; 8347 } 8348 8349 /* Headers, CPU type, and CPU subtype. 8350 */ 8351 if (!infoKeys || 8352 _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) || 8353 _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) || 8354 _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) 8355 { 8356 8357 if (linkedExecutable && !isInterface()) { 8358 8359 kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *) 8360 linkedExecutable->getBytesNoCopy(); 8361 8362 #if !SECURE_KERNEL 8363 // do not return macho header info on shipping iOS - 19095897 8364 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) { 8365 kernel_mach_header_t * temp_kext_mach_hdr; 8366 struct load_command * lcp; 8367 8368 headerData = OSData::withBytes(kext_mach_hdr, 8369 (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds)); 8370 if (!headerData) { 8371 goto finish; 8372 } 8373 8374 // unslide any vmaddrs we return to userspace - 10726716 8375 temp_kext_mach_hdr = (kernel_mach_header_t *) 8376 headerData->getBytesNoCopy(); 8377 if (temp_kext_mach_hdr == NULL) { 8378 goto finish; 8379 } 8380 8381 lcp = (struct load_command *) (temp_kext_mach_hdr + 1); 8382 for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) { 8383 if (lcp->cmd == LC_SEGMENT_KERNEL) { 8384 kernel_segment_command_t * segp; 8385 kernel_section_t * secp; 8386 8387 segp = (kernel_segment_command_t *) lcp; 8388 // 10543468 - if we jettisoned __LINKEDIT clear size info 8389 if (flags.jettisonLinkeditSeg) { 8390 if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) { 8391 segp->vmsize = 0; 8392 segp->fileoff = 0; 8393 segp->filesize = 0; 8394 } 8395 } 8396 #if 0 8397 OSKextLog(/* kext */ NULL, 8398 kOSKextLogErrorLevel | 8399 kOSKextLogGeneralFlag, 8400 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u", 8401 __FUNCTION__, segp->segname, segp->vmaddr, 8402 VM_KERNEL_UNSLIDE(segp->vmaddr), 8403 segp->vmsize, segp->nsects); 8404 if ( (VM_KERNEL_IS_SLID(segp->vmaddr) == false) && 8405 (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) && 8406 (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) && 8407 (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) && 8408 (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false) ) { 8409 OSKextLog(/* kext */ NULL, 8410 kOSKextLogErrorLevel | 8411 kOSKextLogGeneralFlag, 8412 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX", 8413 __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top); 8414 } 8415 #endif 8416 segp->vmaddr = VM_KERNEL_UNSLIDE(segp->vmaddr); 8417 8418 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { 8419 secp->addr = VM_KERNEL_UNSLIDE(secp->addr); 8420 } 8421 } 8422 lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize); 8423 } 8424 result->setObject(kOSBundleMachOHeadersKey, headerData); 8425 } 8426 #endif // SECURE_KERNEL 8427 8428 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) { 8429 cpuTypeNumber = OSNumber::withNumber( 8430 (uint64_t) kext_mach_hdr->cputype, 8431 8 * sizeof(kext_mach_hdr->cputype)); 8432 if (!cpuTypeNumber) { 8433 goto finish; 8434 } 8435 result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber); 8436 } 8437 8438 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 8439 cpuSubtypeNumber = OSNumber::withNumber( 8440 (uint64_t) kext_mach_hdr->cpusubtype, 8441 8 * sizeof(kext_mach_hdr->cpusubtype)); 8442 if (!cpuSubtypeNumber) { 8443 goto finish; 8444 } 8445 result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber); 8446 } 8447 } 8448 } 8449 8450 /* CFBundleIdentifier. We set this regardless because it's just stupid not to. 8451 */ 8452 result->setObject(kCFBundleIdentifierKey, bundleID); 8453 8454 /* CFBundleVersion. 8455 */ 8456 if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) { 8457 versionString = OSDynamicCast(OSString, 8458 getPropertyForHostArch(kCFBundleVersionKey)); 8459 if (versionString) { 8460 result->setObject(kCFBundleVersionKey, versionString); 8461 } 8462 } 8463 8464 /* OSBundleCompatibleVersion. 8465 */ 8466 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) { 8467 versionString = OSDynamicCast(OSString, 8468 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 8469 if (versionString) { 8470 result->setObject(kOSBundleCompatibleVersionKey, versionString); 8471 } 8472 } 8473 8474 /* Path. 8475 */ 8476 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) { 8477 if (path) { 8478 result->setObject(kOSBundlePathKey, path); 8479 } 8480 } 8481 8482 8483 /* OSBundleExecutablePath. 8484 */ 8485 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) { 8486 if (path && executableRelPath) { 8487 8488 uint32_t pathLength = path->getLength(); // gets incremented below 8489 8490 // +1 for slash, +1 for \0 8491 executablePathCStringSize = pathLength + executableRelPath->getLength() + 2; 8492 8493 executablePathCString = (char *)kalloc_tag((executablePathCStringSize) * 8494 sizeof(char), VM_KERN_MEMORY_OSKEXT); // +1 for \0 8495 if (!executablePathCString) { 8496 goto finish; 8497 } 8498 strlcpy(executablePathCString, path->getCStringNoCopy(), 8499 executablePathCStringSize); 8500 executablePathCString[pathLength++] = '/'; 8501 executablePathCString[pathLength++] = '\0'; 8502 strlcat(executablePathCString, executableRelPath->getCStringNoCopy(), 8503 executablePathCStringSize); 8504 8505 executablePathString = OSString::withCString(executablePathCString); 8506 8507 if (!executablePathCString) { 8508 goto finish; 8509 } 8510 8511 result->setObject(kOSBundleExecutablePathKey, executablePathString); 8512 } 8513 } 8514 8515 /* UUID, if the kext has one. 8516 */ 8517 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) { 8518 uuid = copyUUID(); 8519 if (uuid) { 8520 result->setObject(kOSBundleUUIDKey, uuid); 8521 } 8522 } 8523 8524 /***** 8525 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted. 8526 */ 8527 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) { 8528 result->setObject(kOSKernelResourceKey, 8529 isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse); 8530 } 8531 8532 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) { 8533 result->setObject(kOSBundleIsInterfaceKey, 8534 isInterface() ? kOSBooleanTrue : kOSBooleanFalse); 8535 } 8536 8537 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) { 8538 result->setObject(kOSBundlePrelinkedKey, 8539 isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse); 8540 } 8541 8542 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) { 8543 result->setObject(kOSBundleStartedKey, 8544 isStarted() ? kOSBooleanTrue : kOSBooleanFalse); 8545 } 8546 8547 /* LoadTag (Index). 8548 */ 8549 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) { 8550 scratchNumber = OSNumber::withNumber((unsigned long long)loadTag, 8551 /* numBits */ 8 * sizeof(loadTag)); 8552 if (!scratchNumber) { 8553 goto finish; 8554 } 8555 result->setObject(kOSBundleLoadTagKey, scratchNumber); 8556 OSSafeReleaseNULL(scratchNumber); 8557 } 8558 8559 /* LoadAddress, LoadSize. 8560 */ 8561 if (!infoKeys || 8562 _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) || 8563 _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) || 8564 _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) 8565 { 8566 if (isInterface() || linkedExecutable) { 8567 /* These go to userspace via serialization, so we don't want any doubts 8568 * about their size. 8569 */ 8570 uint64_t loadAddress = 0; 8571 uint32_t loadSize = 0; 8572 uint32_t wiredSize = 0; 8573 8574 /* Interfaces always report 0 load address & size. 8575 * Just the way they roll. 8576 * 8577 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp 8578 * xxx - shouldn't have one! 8579 */ 8580 if (linkedExecutable /* && !isInterface() */) { 8581 loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy(); 8582 loadAddress = VM_KERNEL_UNSLIDE(loadAddress); 8583 loadSize = linkedExecutable->getLength(); 8584 8585 /* If we have a kmod_info struct, calculated the wired size 8586 * from that. Otherwise it's the full load size. 8587 */ 8588 if (kmod_info) { 8589 wiredSize = loadSize - kmod_info->hdr_size; 8590 } else { 8591 wiredSize = loadSize; 8592 } 8593 } 8594 8595 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) { 8596 scratchNumber = OSNumber::withNumber( 8597 (unsigned long long)(loadAddress), 8598 /* numBits */ 8 * sizeof(loadAddress)); 8599 if (!scratchNumber) { 8600 goto finish; 8601 } 8602 result->setObject(kOSBundleLoadAddressKey, scratchNumber); 8603 OSSafeReleaseNULL(scratchNumber); 8604 } 8605 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) { 8606 scratchNumber = OSNumber::withNumber( 8607 (unsigned long long)(loadSize), 8608 /* numBits */ 8 * sizeof(loadSize)); 8609 if (!scratchNumber) { 8610 goto finish; 8611 } 8612 result->setObject(kOSBundleLoadSizeKey, scratchNumber); 8613 OSSafeReleaseNULL(scratchNumber); 8614 } 8615 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 8616 scratchNumber = OSNumber::withNumber( 8617 (unsigned long long)(wiredSize), 8618 /* numBits */ 8 * sizeof(wiredSize)); 8619 if (!scratchNumber) { 8620 goto finish; 8621 } 8622 result->setObject(kOSBundleWiredSizeKey, scratchNumber); 8623 OSSafeReleaseNULL(scratchNumber); 8624 } 8625 } 8626 } 8627 8628 /* OSBundleDependencies. In descending order for 8629 * easy compatibility with kextstat(8). 8630 */ 8631 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) { 8632 if ((count = getNumDependencies())) { 8633 dependencyLoadTags = OSArray::withCapacity(count); 8634 result->setObject(kOSBundleDependenciesKey, dependencyLoadTags); 8635 8636 i = count - 1; 8637 do { 8638 OSKext * dependency = OSDynamicCast(OSKext, 8639 dependencies->getObject(i)); 8640 8641 OSSafeReleaseNULL(scratchNumber); 8642 8643 if (!dependency) { 8644 continue; 8645 } 8646 scratchNumber = OSNumber::withNumber( 8647 (unsigned long long)dependency->getLoadTag(), 8648 /* numBits*/ 8 * sizeof(loadTag)); 8649 if (!scratchNumber) { 8650 goto finish; 8651 } 8652 dependencyLoadTags->setObject(scratchNumber); 8653 } while (i--); 8654 } 8655 } 8656 8657 OSSafeReleaseNULL(scratchNumber); 8658 8659 /* OSBundleMetaClasses. 8660 */ 8661 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) { 8662 if (metaClasses && metaClasses->getCount()) { 8663 metaClassIterator = OSCollectionIterator::withCollection(metaClasses); 8664 metaClassInfo = OSArray::withCapacity(metaClasses->getCount()); 8665 if (!metaClassIterator || !metaClassInfo) { 8666 goto finish; 8667 } 8668 result->setObject(kOSBundleClassesKey, metaClassInfo); 8669 8670 while ( (thisMetaClass = OSDynamicCast(OSMetaClass, 8671 metaClassIterator->getNextObject())) ) { 8672 8673 OSSafeReleaseNULL(metaClassDict); 8674 OSSafeReleaseNULL(scratchNumber); 8675 OSSafeReleaseNULL(metaClassName); 8676 OSSafeReleaseNULL(superclassName); 8677 8678 metaClassDict = OSDictionary::withCapacity(3); 8679 if (!metaClassDict) { 8680 goto finish; 8681 } 8682 8683 metaClassName = OSString::withCString(thisMetaClass->getClassName()); 8684 if (thisMetaClass->getSuperClass()) { 8685 superclassName = OSString::withCString( 8686 thisMetaClass->getSuperClass()->getClassName()); 8687 } 8688 scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(), 8689 8 * sizeof(unsigned int)); 8690 8691 /* Bail if any of the essentials is missing. The root class lacks a superclass, 8692 * of course. 8693 */ 8694 if (!metaClassDict || !metaClassName || !scratchNumber) { 8695 goto finish; 8696 } 8697 8698 metaClassInfo->setObject(metaClassDict); 8699 metaClassDict->setObject(kOSMetaClassNameKey, metaClassName); 8700 if (superclassName) { 8701 metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName); 8702 } 8703 metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber); 8704 } 8705 } 8706 } 8707 8708 /* OSBundleRetainCount. 8709 */ 8710 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) { 8711 OSSafeReleaseNULL(scratchNumber); 8712 { 8713 int kextRetainCount = getRetainCount() - 1; 8714 if (isLoaded()) { 8715 kextRetainCount--; 8716 } 8717 scratchNumber = OSNumber::withNumber( 8718 (int)kextRetainCount, 8719 /* numBits*/ 8 * sizeof(int)); 8720 if (scratchNumber) { 8721 result->setObject(kOSBundleRetainCountKey, scratchNumber); 8722 } 8723 } 8724 } 8725 8726 success = true; 8727 8728 finish: 8729 OSSafeRelease(headerData); 8730 OSSafeRelease(cpuTypeNumber); 8731 OSSafeRelease(cpuSubtypeNumber); 8732 OSSafeRelease(executablePathString); 8733 if (executablePathString) kfree(executablePathCString, executablePathCStringSize); 8734 OSSafeRelease(uuid); 8735 OSSafeRelease(scratchNumber); 8736 OSSafeRelease(dependencyLoadTags); 8737 OSSafeRelease(metaClassIterator); 8738 OSSafeRelease(metaClassInfo); 8739 OSSafeRelease(metaClassDict); 8740 OSSafeRelease(metaClassName); 8741 OSSafeRelease(superclassName); 8742 if (!success) { 8743 OSSafeReleaseNULL(result); 8744 } 8745 return result; 8746 } 8747 8748 /********************************************************************* 8749 *********************************************************************/ 8750 /* static */ 8751 OSReturn 8752 OSKext::requestResource( 8753 const char * kextIdentifierCString, 8754 const char * resourceNameCString, 8755 OSKextRequestResourceCallback callback, 8756 void * context, 8757 OSKextRequestTag * requestTagOut) 8758 { 8759 OSReturn result = kOSReturnError; 8760 OSKext * callbackKext = NULL; // must release (looked up) 8761 8762 OSKextRequestTag requestTag = -1; 8763 OSNumber * requestTagNum = NULL; // must release 8764 8765 OSDictionary * requestDict = NULL; // must release 8766 OSString * kextIdentifier = NULL; // must release 8767 OSString * resourceName = NULL; // must release 8768 8769 OSDictionary * callbackRecord = NULL; // must release 8770 OSData * callbackWrapper = NULL; // must release 8771 8772 OSData * contextWrapper = NULL; // must release 8773 8774 IORecursiveLockLock(sKextLock); 8775 8776 if (requestTagOut) { 8777 *requestTagOut = kOSKextRequestTagInvalid; 8778 } 8779 8780 /* If requests to user space are disabled, don't go any further */ 8781 if (!sKernelRequestsEnabled) { 8782 OSKextLog(/* kext */ NULL, 8783 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 8784 "Can't request resource %s for %s - requests to user space are disabled.", 8785 resourceNameCString, 8786 kextIdentifierCString); 8787 result = kOSKextReturnDisabled; 8788 goto finish; 8789 } 8790 8791 if (!kextIdentifierCString || !resourceNameCString || !callback) { 8792 result = kOSKextReturnInvalidArgument; 8793 goto finish; 8794 } 8795 8796 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 8797 if (!callbackKext) { 8798 OSKextLog(/* kext */ NULL, 8799 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 8800 "Resource request has bad callback address."); 8801 result = kOSKextReturnInvalidArgument; 8802 goto finish; 8803 } 8804 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 8805 OSKextLog(/* kext */ NULL, 8806 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 8807 "Resource request callback is in a kext that is not started."); 8808 result = kOSKextReturnInvalidArgument; 8809 goto finish; 8810 } 8811 8812 /* Do not allow any new requests to be made on a kext that is unloading. 8813 */ 8814 if (callbackKext->flags.stopping) { 8815 result = kOSKextReturnStopping; 8816 goto finish; 8817 } 8818 8819 /* If we're wrapped the next available request tag around to the negative 8820 * numbers, we can't service any more requests. 8821 */ 8822 if (sNextRequestTag == kOSKextRequestTagInvalid) { 8823 OSKextLog(/* kext */ NULL, 8824 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 8825 "No more request tags available; restart required."); 8826 result = kOSKextReturnNoResources; 8827 goto finish; 8828 } 8829 requestTag = sNextRequestTag++; 8830 8831 result = _OSKextCreateRequest(kKextRequestPredicateRequestResource, 8832 &requestDict); 8833 if (result != kOSReturnSuccess) { 8834 goto finish; 8835 } 8836 8837 kextIdentifier = OSString::withCString(kextIdentifierCString); 8838 resourceName = OSString::withCString(resourceNameCString); 8839 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 8840 8 * sizeof(requestTag)); 8841 if (!kextIdentifier || 8842 !resourceName || 8843 !requestTagNum || 8844 !_OSKextSetRequestArgument(requestDict, 8845 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) || 8846 !_OSKextSetRequestArgument(requestDict, 8847 kKextRequestArgumentNameKey, resourceName) || 8848 !_OSKextSetRequestArgument(requestDict, 8849 kKextRequestArgumentRequestTagKey, requestTagNum)) { 8850 8851 result = kOSKextReturnNoMemory; 8852 goto finish; 8853 } 8854 8855 callbackRecord = OSDynamicCast(OSDictionary, requestDict->copyCollection()); 8856 if (!callbackRecord) { 8857 result = kOSKextReturnNoMemory; 8858 goto finish; 8859 } 8860 // we validate callback address at call time 8861 callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *)); 8862 if (context) { 8863 contextWrapper = OSData::withBytes((void *)&context, sizeof(void *)); 8864 } 8865 if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord, 8866 kKextRequestArgumentCallbackKey, callbackWrapper)) { 8867 8868 result = kOSKextReturnNoMemory; 8869 goto finish; 8870 } 8871 8872 if (context) { 8873 if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord, 8874 kKextRequestArgumentContextKey, contextWrapper)) { 8875 8876 result = kOSKextReturnNoMemory; 8877 goto finish; 8878 } 8879 } 8880 8881 /* Only post the requests after all the other potential failure points 8882 * have been passed. 8883 */ 8884 if (!sKernelRequests->setObject(requestDict) || 8885 !sRequestCallbackRecords->setObject(callbackRecord)) { 8886 8887 result = kOSKextReturnNoMemory; 8888 goto finish; 8889 } 8890 8891 OSKext::pingKextd(); 8892 8893 result = kOSReturnSuccess; 8894 if (requestTagOut) { 8895 *requestTagOut = requestTag; 8896 } 8897 8898 finish: 8899 8900 /* If we didn't succeed, yank the request & callback 8901 * from their holding arrays. 8902 */ 8903 if (result != kOSReturnSuccess) { 8904 unsigned int index; 8905 8906 index = sKernelRequests->getNextIndexOfObject(requestDict, 0); 8907 if (index != (unsigned int)-1) { 8908 sKernelRequests->removeObject(index); 8909 } 8910 index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord, 0); 8911 if (index != (unsigned int)-1) { 8912 sRequestCallbackRecords->removeObject(index); 8913 } 8914 } 8915 8916 OSKext::considerUnloads(/* rescheduleOnly? */ true); 8917 8918 IORecursiveLockUnlock(sKextLock); 8919 8920 if (callbackKext) callbackKext->release(); 8921 if (requestTagNum) requestTagNum->release(); 8922 8923 if (requestDict) requestDict->release(); 8924 if (kextIdentifier) kextIdentifier->release(); 8925 if (resourceName) resourceName->release(); 8926 8927 if (callbackRecord) callbackRecord->release(); 8928 if (callbackWrapper) callbackWrapper->release(); 8929 if (contextWrapper) contextWrapper->release(); 8930 8931 return result; 8932 } 8933 8934 /********************************************************************* 8935 * Assumes sKextLock is held. 8936 *********************************************************************/ 8937 /* static */ 8938 OSReturn 8939 OSKext::dequeueCallbackForRequestTag( 8940 OSKextRequestTag requestTag, 8941 OSDictionary ** callbackRecordOut) 8942 { 8943 OSReturn result = kOSReturnError; 8944 OSNumber * requestTagNum = NULL; // must release 8945 8946 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 8947 8 * sizeof(requestTag)); 8948 if (!requestTagNum) { 8949 goto finish; 8950 } 8951 8952 result = OSKext::dequeueCallbackForRequestTag(requestTagNum, 8953 callbackRecordOut); 8954 8955 finish: 8956 OSSafeRelease(requestTagNum); 8957 8958 return result; 8959 } 8960 8961 /********************************************************************* 8962 * Assumes sKextLock is held. 8963 *********************************************************************/ 8964 /* static */ 8965 OSReturn 8966 OSKext::dequeueCallbackForRequestTag( 8967 OSNumber * requestTagNum, 8968 OSDictionary ** callbackRecordOut) 8969 { 8970 OSReturn result = kOSKextReturnInvalidArgument; 8971 OSDictionary * callbackRecord = NULL; // retain if matched! 8972 OSNumber * callbackTagNum = NULL; // do not release 8973 unsigned int count, i; 8974 8975 result = kOSReturnError; 8976 count = sRequestCallbackRecords->getCount(); 8977 for (i = 0; i < count; i++) { 8978 callbackRecord = OSDynamicCast(OSDictionary, 8979 sRequestCallbackRecords->getObject(i)); 8980 if (!callbackRecord) { 8981 goto finish; 8982 } 8983 8984 /* If we don't find a tag, we basically have a leak here. Maybe 8985 * we should just remove it. 8986 */ 8987 callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument( 8988 callbackRecord, kKextRequestArgumentRequestTagKey)); 8989 if (!callbackTagNum) { 8990 goto finish; 8991 } 8992 8993 /* We could be even more paranoid and check that all the incoming 8994 * args match what's in the callback record. 8995 */ 8996 if (callbackTagNum->isEqualTo(requestTagNum)) { 8997 if (callbackRecordOut) { 8998 *callbackRecordOut = callbackRecord; 8999 callbackRecord->retain(); 9000 } 9001 sRequestCallbackRecords->removeObject(i); 9002 result = kOSReturnSuccess; 9003 goto finish; 9004 } 9005 } 9006 result = kOSKextReturnNotFound; 9007 9008 finish: 9009 return result; 9010 } 9011 9012 /********************************************************************* 9013 * Assumes sKextLock is held. 9014 *********************************************************************/ 9015 /* static */ 9016 OSReturn 9017 OSKext::dispatchResource(OSDictionary * requestDict) 9018 { 9019 OSReturn result = kOSReturnError; 9020 OSDictionary * callbackRecord = NULL; // must release 9021 OSNumber * requestTag = NULL; // do not release 9022 OSNumber * requestResult = NULL; // do not release 9023 OSData * dataObj = NULL; // do not release 9024 uint32_t dataLength = 0; 9025 const void * dataPtr = NULL; // do not free 9026 OSData * callbackWrapper = NULL; // do not release 9027 OSKextRequestResourceCallback callback = NULL; 9028 OSData * contextWrapper = NULL; // do not release 9029 void * context = NULL; // do not free 9030 OSKext * callbackKext = NULL; // must release (looked up) 9031 9032 /* Get the args from the request. Right now we need the tag 9033 * to look up the callback record, and the result for invoking the callback. 9034 */ 9035 requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 9036 kKextRequestArgumentRequestTagKey)); 9037 requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 9038 kKextRequestArgumentResultKey)); 9039 if (!requestTag || !requestResult) { 9040 result = kOSKextReturnInvalidArgument; 9041 goto finish; 9042 } 9043 9044 /* Look for a callback record matching this request's tag. 9045 */ 9046 result = dequeueCallbackForRequestTag(requestTag, &callbackRecord); 9047 if (result != kOSReturnSuccess) { 9048 goto finish; 9049 } 9050 9051 /***** 9052 * Get the context pointer of the callback record (if there is one). 9053 */ 9054 contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord, 9055 kKextRequestArgumentContextKey)); 9056 context = _OSKextExtractPointer(contextWrapper); 9057 if (contextWrapper && !context) { 9058 goto finish; 9059 } 9060 9061 callbackWrapper = OSDynamicCast(OSData, 9062 _OSKextGetRequestArgument(callbackRecord, 9063 kKextRequestArgumentCallbackKey)); 9064 callback = (OSKextRequestResourceCallback) 9065 _OSKextExtractPointer(callbackWrapper); 9066 if (!callback) { 9067 goto finish; 9068 } 9069 9070 /* Check for a data obj. We might not have one and that's ok, that means 9071 * we didn't find the requested resource, and we still have to tell the 9072 * caller that via the callback. 9073 */ 9074 dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict, 9075 kKextRequestArgumentValueKey)); 9076 if (dataObj) { 9077 dataPtr = dataObj->getBytesNoCopy(); 9078 dataLength = dataObj->getLength(); 9079 } 9080 9081 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 9082 if (!callbackKext) { 9083 OSKextLog(/* kext */ NULL, 9084 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 9085 "Can't invoke callback for resource request; "); 9086 goto finish; 9087 } 9088 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 9089 OSKextLog(/* kext */ NULL, 9090 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 9091 "Can't invoke kext resource callback; "); 9092 goto finish; 9093 } 9094 9095 (void)callback(requestTag->unsigned32BitValue(), 9096 (OSReturn)requestResult->unsigned32BitValue(), 9097 dataPtr, dataLength, context); 9098 9099 result = kOSReturnSuccess; 9100 9101 finish: 9102 if (callbackKext) callbackKext->release(); 9103 if (callbackRecord) callbackRecord->release(); 9104 9105 return result; 9106 } 9107 9108 /********************************************************************* 9109 *********************************************************************/ 9110 /* static */ 9111 void 9112 OSKext::invokeRequestCallback( 9113 OSDictionary * callbackRecord, 9114 OSReturn callbackResult) 9115 { 9116 OSString * predicate = _OSKextGetRequestPredicate(callbackRecord); 9117 OSNumber * resultNum = NULL; // must release 9118 9119 if (!predicate) { 9120 goto finish; 9121 } 9122 9123 resultNum = OSNumber::withNumber((long long unsigned int)callbackResult, 9124 8 * sizeof(callbackResult)); 9125 if (!resultNum) { 9126 goto finish; 9127 } 9128 9129 /* Insert the result into the callback record and dispatch it as if it 9130 * were the reply coming down from user space. 9131 */ 9132 _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey, 9133 resultNum); 9134 9135 if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) { 9136 /* This removes the pending callback record. 9137 */ 9138 OSKext::dispatchResource(callbackRecord); 9139 } 9140 9141 finish: 9142 if (resultNum) resultNum->release(); 9143 return; 9144 } 9145 9146 /********************************************************************* 9147 * Assumes sKextLock is held. 9148 *********************************************************************/ 9149 /* static */ 9150 OSReturn 9151 OSKext::cancelRequest( 9152 OSKextRequestTag requestTag, 9153 void ** contextOut) 9154 { 9155 OSReturn result = kOSKextReturnNoMemory; 9156 OSDictionary * callbackRecord = NULL; // must release 9157 OSData * contextWrapper = NULL; // do not release 9158 9159 IORecursiveLockLock(sKextLock); 9160 result = OSKext::dequeueCallbackForRequestTag(requestTag, 9161 &callbackRecord); 9162 IORecursiveLockUnlock(sKextLock); 9163 9164 if (result == kOSReturnSuccess && contextOut) { 9165 contextWrapper = OSDynamicCast(OSData, 9166 _OSKextGetRequestArgument(callbackRecord, 9167 kKextRequestArgumentContextKey)); 9168 *contextOut = _OSKextExtractPointer(contextWrapper); 9169 } 9170 9171 if (callbackRecord) callbackRecord->release(); 9172 9173 return result; 9174 } 9175 9176 /********************************************************************* 9177 * Assumes sKextLock is held. 9178 *********************************************************************/ 9179 void 9180 OSKext::invokeOrCancelRequestCallbacks( 9181 OSReturn callbackResult, 9182 bool invokeFlag) 9183 { 9184 unsigned int count, i; 9185 9186 count = sRequestCallbackRecords->getCount(); 9187 if (!count) { 9188 goto finish; 9189 } 9190 9191 i = count - 1; 9192 do { 9193 OSDictionary * request = OSDynamicCast(OSDictionary, 9194 sRequestCallbackRecords->getObject(i)); 9195 9196 if (!request) { 9197 continue; 9198 } 9199 OSData * callbackWrapper = OSDynamicCast(OSData, 9200 _OSKextGetRequestArgument(request, 9201 kKextRequestArgumentCallbackKey)); 9202 9203 if (!callbackWrapper) { 9204 sRequestCallbackRecords->removeObject(i); 9205 continue; 9206 } 9207 9208 vm_address_t callbackAddress = (vm_address_t) 9209 _OSKextExtractPointer(callbackWrapper); 9210 9211 if ((kmod_info->address <= callbackAddress) && 9212 (callbackAddress < (kmod_info->address + kmod_info->size))) { 9213 9214 if (invokeFlag) { 9215 /* This removes the callback record. 9216 */ 9217 invokeRequestCallback(request, callbackResult); 9218 } else { 9219 sRequestCallbackRecords->removeObject(i); 9220 } 9221 } 9222 } while (i--); 9223 9224 finish: 9225 return; 9226 } 9227 9228 /********************************************************************* 9229 * Assumes sKextLock is held. 9230 *********************************************************************/ 9231 uint32_t 9232 OSKext::countRequestCallbacks(void) 9233 { 9234 uint32_t result = 0; 9235 unsigned int count, i; 9236 9237 count = sRequestCallbackRecords->getCount(); 9238 if (!count) { 9239 goto finish; 9240 } 9241 9242 i = count - 1; 9243 do { 9244 OSDictionary * request = OSDynamicCast(OSDictionary, 9245 sRequestCallbackRecords->getObject(i)); 9246 9247 if (!request) { 9248 continue; 9249 } 9250 OSData * callbackWrapper = OSDynamicCast(OSData, 9251 _OSKextGetRequestArgument(request, 9252 kKextRequestArgumentCallbackKey)); 9253 9254 if (!callbackWrapper) { 9255 continue; 9256 } 9257 9258 vm_address_t callbackAddress = (vm_address_t) 9259 _OSKextExtractPointer(callbackWrapper); 9260 9261 if ((kmod_info->address <= callbackAddress) && 9262 (callbackAddress < (kmod_info->address + kmod_info->size))) { 9263 9264 result++; 9265 } 9266 } while (i--); 9267 9268 finish: 9269 return result; 9270 } 9271 9272 /********************************************************************* 9273 *********************************************************************/ 9274 static OSReturn _OSKextCreateRequest( 9275 const char * predicate, 9276 OSDictionary ** requestP) 9277 { 9278 OSReturn result = kOSKextReturnNoMemory; 9279 OSDictionary * request = NULL; // must release on error 9280 9281 request = OSDictionary::withCapacity(2); 9282 if (!request) { 9283 goto finish; 9284 } 9285 result = _OSDictionarySetCStringValue(request, 9286 kKextRequestPredicateKey, predicate); 9287 if (result != kOSReturnSuccess) { 9288 goto finish; 9289 } 9290 result = kOSReturnSuccess; 9291 9292 finish: 9293 if (result != kOSReturnSuccess) { 9294 if (request) request->release(); 9295 } else { 9296 *requestP = request; 9297 } 9298 9299 return result; 9300 } 9301 9302 /********************************************************************* 9303 *********************************************************************/ 9304 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict) 9305 { 9306 return OSDynamicCast(OSString, 9307 requestDict->getObject(kKextRequestPredicateKey)); 9308 } 9309 9310 /********************************************************************* 9311 *********************************************************************/ 9312 static OSObject * _OSKextGetRequestArgument( 9313 OSDictionary * requestDict, 9314 const char * argName) 9315 { 9316 OSDictionary * args = OSDynamicCast(OSDictionary, 9317 requestDict->getObject(kKextRequestArgumentsKey)); 9318 if (args) { 9319 return args->getObject(argName); 9320 } 9321 return NULL; 9322 } 9323 9324 /********************************************************************* 9325 *********************************************************************/ 9326 static bool _OSKextSetRequestArgument( 9327 OSDictionary * requestDict, 9328 const char * argName, 9329 OSObject * value) 9330 { 9331 OSDictionary * args = OSDynamicCast(OSDictionary, 9332 requestDict->getObject(kKextRequestArgumentsKey)); 9333 if (!args) { 9334 args = OSDictionary::withCapacity(2); 9335 if (!args) { 9336 goto finish; 9337 } 9338 requestDict->setObject(kKextRequestArgumentsKey, args); 9339 args->release(); 9340 } 9341 if (args) { 9342 return args->setObject(argName, value); 9343 } 9344 finish: 9345 return false; 9346 } 9347 9348 /********************************************************************* 9349 *********************************************************************/ 9350 static void * _OSKextExtractPointer(OSData * wrapper) 9351 { 9352 void * result = NULL; 9353 const void * resultPtr = NULL; 9354 9355 if (!wrapper) { 9356 goto finish; 9357 } 9358 resultPtr = wrapper->getBytesNoCopy(); 9359 result = *(void **)resultPtr; 9360 finish: 9361 return result; 9362 } 9363 9364 /********************************************************************* 9365 *********************************************************************/ 9366 static OSReturn _OSDictionarySetCStringValue( 9367 OSDictionary * dict, 9368 const char * cKey, 9369 const char * cValue) 9370 { 9371 OSReturn result = kOSKextReturnNoMemory; 9372 const OSSymbol * key = NULL; // must release 9373 OSString * value = NULL; // must release 9374 9375 key = OSSymbol::withCString(cKey); 9376 value = OSString::withCString(cValue); 9377 if (!key || !value) { 9378 goto finish; 9379 } 9380 if (dict->setObject(key, value)) { 9381 result = kOSReturnSuccess; 9382 } 9383 9384 finish: 9385 if (key) key->release(); 9386 if (value) value->release(); 9387 9388 return result; 9389 } 9390 9391 /********************************************************************* 9392 *********************************************************************/ 9393 static bool _OSArrayContainsCString( 9394 OSArray * array, 9395 const char * cString) 9396 { 9397 bool result = false; 9398 const OSSymbol * symbol = NULL; 9399 uint32_t count, i; 9400 9401 if (!array || !cString) { 9402 goto finish; 9403 } 9404 9405 symbol = OSSymbol::withCStringNoCopy(cString); 9406 if (!symbol) { 9407 goto finish; 9408 } 9409 9410 count = array->getCount(); 9411 for (i = 0; i < count; i++) { 9412 OSObject * thisObject = array->getObject(i); 9413 if (symbol->isEqualTo(thisObject)) { 9414 result = true; 9415 goto finish; 9416 } 9417 } 9418 9419 finish: 9420 if (symbol) symbol->release(); 9421 return result; 9422 } 9423 9424 /********************************************************************* 9425 * We really only care about boot / system start up related kexts. 9426 * We return true if we're less than REBUILD_MAX_TIME since start up, 9427 * otherwise return false. 9428 *********************************************************************/ 9429 bool _OSKextInPrelinkRebuildWindow(void) 9430 { 9431 static bool outside_the_window = false; 9432 AbsoluteTime my_abstime; 9433 UInt64 my_ns; 9434 SInt32 my_secs; 9435 9436 if (outside_the_window) { 9437 return(false); 9438 } 9439 clock_get_uptime(&my_abstime); 9440 absolutetime_to_nanoseconds(my_abstime, &my_ns); 9441 my_secs = (SInt32)(my_ns / NSEC_PER_SEC); 9442 if (my_secs > REBUILD_MAX_TIME) { 9443 outside_the_window = true; 9444 return(false); 9445 } 9446 return(true); 9447 } 9448 9449 /********************************************************************* 9450 *********************************************************************/ 9451 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID ) 9452 { 9453 int unLoadedCount, i; 9454 bool result = false; 9455 9456 IORecursiveLockLock(sKextLock); 9457 9458 if (sUnloadedPrelinkedKexts == NULL) { 9459 goto finish; 9460 } 9461 unLoadedCount = sUnloadedPrelinkedKexts->getCount(); 9462 if (unLoadedCount == 0) { 9463 goto finish; 9464 } 9465 9466 for (i = 0; i < unLoadedCount; i++) { 9467 const OSSymbol * myBundleID; // do not release 9468 9469 myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i)); 9470 if (!myBundleID) continue; 9471 if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) { 9472 result = true; 9473 break; 9474 } 9475 } 9476 finish: 9477 IORecursiveLockUnlock(sKextLock); 9478 return(result); 9479 } 9480 9481 #if PRAGMA_MARK 9482 #pragma mark Personalities (IOKit Drivers) 9483 #endif 9484 /********************************************************************* 9485 *********************************************************************/ 9486 /* static */ 9487 OSArray * 9488 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag) 9489 { 9490 OSArray * result = NULL; // returned 9491 OSCollectionIterator * kextIterator = NULL; // must release 9492 OSArray * personalities = NULL; // must release 9493 OSCollectionIterator * personalitiesIterator = NULL; // must release 9494 9495 OSString * kextID = NULL; // do not release 9496 OSKext * theKext = NULL; // do not release 9497 9498 IORecursiveLockLock(sKextLock); 9499 9500 /* Let's conservatively guess that any given kext has around 3 9501 * personalities for now. 9502 */ 9503 result = OSArray::withCapacity(sKextsByID->getCount() * 3); 9504 if (!result) { 9505 goto finish; 9506 } 9507 9508 kextIterator = OSCollectionIterator::withCollection(sKextsByID); 9509 if (!kextIterator) { 9510 goto finish; 9511 } 9512 9513 while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) { 9514 if (personalitiesIterator) { 9515 personalitiesIterator->release(); 9516 personalitiesIterator = NULL; 9517 } 9518 if (personalities) { 9519 personalities->release(); 9520 personalities = NULL; 9521 } 9522 9523 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID)); 9524 if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) { 9525 personalities = theKext->copyPersonalitiesArray(); 9526 if (!personalities) { 9527 continue; 9528 } 9529 result->merge(personalities); 9530 } else { 9531 // xxx - check for better place to put this log msg 9532 OSKextLog(theKext, 9533 kOSKextLogWarningLevel | 9534 kOSKextLogLoadFlag, 9535 "Kext %s is not loadable during safe boot; " 9536 "omitting its personalities.", 9537 theKext->getIdentifierCString()); 9538 } 9539 9540 } 9541 9542 finish: 9543 IORecursiveLockUnlock(sKextLock); 9544 9545 if (kextIterator) kextIterator->release(); 9546 if (personalitiesIterator) personalitiesIterator->release(); 9547 if (personalities) personalities->release(); 9548 9549 return result; 9550 } 9551 9552 /********************************************************************* 9553 *********************************************************************/ 9554 /* static */ 9555 void 9556 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching) 9557 { 9558 int numPersonalities = 0; 9559 9560 OSKextLog(/* kext */ NULL, 9561 kOSKextLogStepLevel | 9562 kOSKextLogLoadFlag, 9563 "Sending all eligible registered kexts' personalities " 9564 "to the IOCatalogue %s.", 9565 startMatching ? "and starting matching" : "but not starting matching"); 9566 9567 OSArray * personalities = OSKext::copyAllKextPersonalities( 9568 /* filterSafeBootFlag */ true); 9569 9570 if (personalities) { 9571 gIOCatalogue->addDrivers(personalities, startMatching); 9572 numPersonalities = personalities->getCount(); 9573 personalities->release(); 9574 } 9575 9576 OSKextLog(/* kext */ NULL, 9577 kOSKextLogStepLevel | 9578 kOSKextLogLoadFlag, 9579 "%d kext personalit%s sent to the IOCatalogue; %s.", 9580 numPersonalities, numPersonalities > 0 ? "ies" : "y", 9581 startMatching ? "matching started" : "matching not started"); 9582 return; 9583 } 9584 9585 /********************************************************************* 9586 * Do not make a deep copy, just convert the IOKitPersonalities dict 9587 * to an array for sending to the IOCatalogue. 9588 *********************************************************************/ 9589 OSArray * 9590 OSKext::copyPersonalitiesArray(void) 9591 { 9592 OSArray * result = NULL; 9593 OSDictionary * personalities = NULL; // do not release 9594 OSCollectionIterator * personalitiesIterator = NULL; // must release 9595 9596 OSString * personalityName = NULL; // do not release 9597 OSString * personalityBundleIdentifier = NULL; // do not release 9598 9599 personalities = OSDynamicCast(OSDictionary, 9600 getPropertyForHostArch(kIOKitPersonalitiesKey)); 9601 if (!personalities) { 9602 goto finish; 9603 } 9604 9605 result = OSArray::withCapacity(personalities->getCount()); 9606 if (!result) { 9607 goto finish; 9608 } 9609 9610 personalitiesIterator = 9611 OSCollectionIterator::withCollection(personalities); 9612 if (!personalitiesIterator) { 9613 goto finish; 9614 } 9615 while ((personalityName = OSDynamicCast(OSString, 9616 personalitiesIterator->getNextObject()))) { 9617 9618 OSDictionary * personality = OSDynamicCast(OSDictionary, 9619 personalities->getObject(personalityName)); 9620 9621 /****** 9622 * If the personality doesn't have a CFBundleIdentifier, or if it 9623 * differs from the kext's, insert the kext's ID so we can find it. 9624 * The publisher ID is used to remove personalities from bundles 9625 * correctly. 9626 */ 9627 personalityBundleIdentifier = OSDynamicCast(OSString, 9628 personality->getObject(kCFBundleIdentifierKey)); 9629 9630 if (!personalityBundleIdentifier) { 9631 personality->setObject(kCFBundleIdentifierKey, bundleID); 9632 } else if (!personalityBundleIdentifier->isEqualTo(bundleID)) { 9633 personality->setObject(kIOPersonalityPublisherKey, bundleID); 9634 } 9635 9636 result->setObject(personality); 9637 } 9638 9639 finish: 9640 if (personalitiesIterator) personalitiesIterator->release(); 9641 9642 return result; 9643 } 9644 9645 /********************************************************************* 9646 Might want to change this to a bool return? 9647 *********************************************************************/ 9648 OSReturn 9649 OSKext::sendPersonalitiesToCatalog( 9650 bool startMatching, 9651 OSArray * personalityNames) 9652 { 9653 OSReturn result = kOSReturnSuccess; 9654 OSArray * personalitiesToSend = NULL; // must release 9655 OSDictionary * kextPersonalities = NULL; // do not release 9656 int count, i; 9657 9658 if (!sLoadEnabled) { 9659 OSKextLog(this, 9660 kOSKextLogErrorLevel | 9661 kOSKextLogLoadFlag, 9662 "Kext loading is disabled (attempt to start matching for kext %s).", 9663 getIdentifierCString()); 9664 result = kOSKextReturnDisabled; 9665 goto finish; 9666 } 9667 9668 if (sSafeBoot && !isLoadableInSafeBoot()) { 9669 OSKextLog(this, 9670 kOSKextLogErrorLevel | 9671 kOSKextLogLoadFlag, 9672 "Kext %s is not loadable during safe boot; " 9673 "not sending personalities to the IOCatalogue.", 9674 getIdentifierCString()); 9675 result = kOSKextReturnNotLoadable; 9676 goto finish; 9677 } 9678 9679 if (!personalityNames || !personalityNames->getCount()) { 9680 personalitiesToSend = copyPersonalitiesArray(); 9681 } else { 9682 kextPersonalities = OSDynamicCast(OSDictionary, 9683 getPropertyForHostArch(kIOKitPersonalitiesKey)); 9684 if (!kextPersonalities || !kextPersonalities->getCount()) { 9685 // not an error 9686 goto finish; 9687 } 9688 personalitiesToSend = OSArray::withCapacity(0); 9689 if (!personalitiesToSend) { 9690 result = kOSKextReturnNoMemory; 9691 goto finish; 9692 } 9693 count = personalityNames->getCount(); 9694 for (i = 0; i < count; i++) { 9695 OSString * name = OSDynamicCast(OSString, 9696 personalityNames->getObject(i)); 9697 if (!name) { 9698 continue; 9699 } 9700 OSDictionary * personality = OSDynamicCast(OSDictionary, 9701 kextPersonalities->getObject(name)); 9702 if (personality) { 9703 personalitiesToSend->setObject(personality); 9704 } 9705 } 9706 } 9707 if (personalitiesToSend) { 9708 unsigned numPersonalities = personalitiesToSend->getCount(); 9709 OSKextLog(this, 9710 kOSKextLogStepLevel | 9711 kOSKextLogLoadFlag, 9712 "Kext %s sending %d personalit%s to the IOCatalogue%s.", 9713 getIdentifierCString(), 9714 numPersonalities, 9715 numPersonalities > 1 ? "ies" : "y", 9716 startMatching ? " and starting matching" : " but not starting matching"); 9717 gIOCatalogue->addDrivers(personalitiesToSend, startMatching); 9718 } 9719 finish: 9720 if (personalitiesToSend) { 9721 personalitiesToSend->release(); 9722 } 9723 return result; 9724 } 9725 9726 /********************************************************************* 9727 * xxx - We should allow removing the kext's declared personalities, 9728 * xxx - even with other bundle identifiers. 9729 *********************************************************************/ 9730 void 9731 OSKext::removePersonalitiesFromCatalog(void) 9732 { 9733 OSDictionary * personality = NULL; // do not release 9734 9735 personality = OSDictionary::withCapacity(1); 9736 if (!personality) { 9737 goto finish; 9738 } 9739 personality->setObject(kCFBundleIdentifierKey, getIdentifier()); 9740 9741 OSKextLog(this, 9742 kOSKextLogStepLevel | 9743 kOSKextLogLoadFlag, 9744 "Kext %s removing all personalities naming it from the IOCatalogue.", 9745 getIdentifierCString()); 9746 9747 /* Have the IOCatalog remove all personalities matching this kext's 9748 * bundle ID and trigger matching anew. 9749 */ 9750 gIOCatalogue->removeDrivers(personality, /* startMatching */ true); 9751 9752 finish: 9753 if (personality) personality->release(); 9754 9755 return; 9756 } 9757 9758 9759 #if PRAGMA_MARK 9760 #pragma mark Logging 9761 #endif 9762 /********************************************************************* 9763 * Do not call any function that takes sKextLock here! 9764 *********************************************************************/ 9765 /* static */ 9766 OSKextLogSpec 9767 OSKext::setUserSpaceLogFilter( 9768 OSKextLogSpec newUserLogFilter, 9769 bool captureFlag) 9770 { 9771 OSKextLogSpec result; 9772 bool allocError = false; 9773 9774 /* Do not call any function that takes sKextLoggingLock during 9775 * this critical block. That means do logging after. 9776 */ 9777 IOLockLock(sKextLoggingLock); 9778 9779 result = sUserSpaceKextLogFilter; 9780 sUserSpaceKextLogFilter = newUserLogFilter; 9781 9782 if (newUserLogFilter && captureFlag && 9783 !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) { 9784 9785 // xxx - do some measurements for a good initial capacity? 9786 sUserSpaceLogSpecArray = OSArray::withCapacity(0); 9787 sUserSpaceLogMessageArray = OSArray::withCapacity(0); 9788 9789 if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) { 9790 OSSafeReleaseNULL(sUserSpaceLogSpecArray); 9791 OSSafeReleaseNULL(sUserSpaceLogMessageArray); 9792 allocError = true; 9793 } 9794 } 9795 9796 IOLockUnlock(sKextLoggingLock); 9797 9798 /* If the config flag itself is changing, log the state change 9799 * going both ways, before setting up the user-space log arrays, 9800 * so that this is only logged in the kernel. 9801 */ 9802 if (result != newUserLogFilter) { 9803 OSKextLog(/* kext */ NULL, 9804 kOSKextLogDebugLevel | 9805 kOSKextLogGeneralFlag, 9806 "User-space log flags changed from 0x%x to 0x%x.", 9807 result, newUserLogFilter); 9808 } 9809 if (allocError) { 9810 OSKextLog(/* kext */ NULL, 9811 kOSKextLogErrorLevel | 9812 kOSKextLogGeneralFlag, 9813 "Failed to allocate user-space log message arrays."); 9814 } 9815 9816 return result; 9817 } 9818 9819 /********************************************************************* 9820 * Do not call any function that takes sKextLock here! 9821 *********************************************************************/ 9822 /* static */ 9823 OSArray * 9824 OSKext::clearUserSpaceLogFilter(void) 9825 { 9826 OSArray * result = NULL; 9827 OSKextLogSpec oldLogFilter; 9828 OSKextLogSpec newLogFilter = kOSKextLogSilentFilter; 9829 9830 /* Do not call any function that takes sKextLoggingLock during 9831 * this critical block. That means do logging after. 9832 */ 9833 IOLockLock(sKextLoggingLock); 9834 9835 result = OSArray::withCapacity(2); 9836 if (result) { 9837 result->setObject(sUserSpaceLogSpecArray); 9838 result->setObject(sUserSpaceLogMessageArray); 9839 } 9840 OSSafeReleaseNULL(sUserSpaceLogSpecArray); 9841 OSSafeReleaseNULL(sUserSpaceLogMessageArray); 9842 9843 oldLogFilter = sUserSpaceKextLogFilter; 9844 sUserSpaceKextLogFilter = newLogFilter; 9845 9846 IOLockUnlock(sKextLoggingLock); 9847 9848 /* If the config flag itself is changing, log the state change 9849 * going both ways, after tearing down the user-space log 9850 * arrays, so this is only logged within the kernel. 9851 */ 9852 if (oldLogFilter != newLogFilter) { 9853 OSKextLog(/* kext */ NULL, 9854 kOSKextLogDebugLevel | 9855 kOSKextLogGeneralFlag, 9856 "User-space log flags changed from 0x%x to 0x%x.", 9857 oldLogFilter, newLogFilter); 9858 } 9859 9860 return result; 9861 } 9862 9863 9864 /********************************************************************* 9865 * Do not call any function that takes sKextLock here! 9866 *********************************************************************/ 9867 /* static */ 9868 OSKextLogSpec 9869 OSKext::getUserSpaceLogFilter(void) 9870 { 9871 OSKextLogSpec result; 9872 9873 IOLockLock(sKextLoggingLock); 9874 result = sUserSpaceKextLogFilter; 9875 IOLockUnlock(sKextLoggingLock); 9876 9877 return result; 9878 } 9879 9880 /********************************************************************* 9881 * This function is called by OSMetaClass during kernel C++ setup. 9882 * Be careful what you access here; assume only OSKext::initialize() 9883 * has been called. 9884 * 9885 * Do not call any function that takes sKextLock here! 9886 *********************************************************************/ 9887 #define VTRESET "\033[0m" 9888 9889 #define VTBOLD "\033[1m" 9890 #define VTUNDER "\033[4m" 9891 9892 #define VTRED "\033[31m" 9893 #define VTGREEN "\033[32m" 9894 #define VTYELLOW "\033[33m" 9895 #define VTBLUE "\033[34m" 9896 #define VTMAGENTA "\033[35m" 9897 #define VTCYAN "\033[36m" 9898 9899 inline const char * colorForFlags(OSKextLogSpec flags) 9900 { 9901 OSKextLogSpec logLevel = flags & kOSKextLogLevelMask; 9902 9903 switch (logLevel) { 9904 case kOSKextLogErrorLevel: 9905 return VTRED VTBOLD; 9906 break; 9907 case kOSKextLogWarningLevel: 9908 return VTRED; 9909 break; 9910 case kOSKextLogBasicLevel: 9911 return VTYELLOW VTUNDER; 9912 break; 9913 case kOSKextLogProgressLevel: 9914 return VTYELLOW; 9915 break; 9916 case kOSKextLogStepLevel: 9917 return VTGREEN; 9918 break; 9919 case kOSKextLogDetailLevel: 9920 return VTCYAN; 9921 break; 9922 case kOSKextLogDebugLevel: 9923 return VTMAGENTA; 9924 break; 9925 default: 9926 return ""; // white 9927 break; 9928 } 9929 return ""; 9930 } 9931 9932 inline bool logSpecMatch( 9933 OSKextLogSpec msgLogSpec, 9934 OSKextLogSpec logFilter) 9935 { 9936 OSKextLogSpec filterKextGlobal = logFilter & kOSKextLogKextOrGlobalMask; 9937 OSKextLogSpec filterLevel = logFilter & kOSKextLogLevelMask; 9938 OSKextLogSpec filterFlags = logFilter & kOSKextLogFlagsMask; 9939 9940 OSKextLogSpec msgKextGlobal = msgLogSpec & kOSKextLogKextOrGlobalMask; 9941 OSKextLogSpec msgLevel = msgLogSpec & kOSKextLogLevelMask; 9942 OSKextLogSpec msgFlags = msgLogSpec & kOSKextLogFlagsMask; 9943 9944 /* Explicit messages always get logged. 9945 */ 9946 if (msgLevel == kOSKextLogExplicitLevel) { 9947 return true; 9948 } 9949 9950 /* Warnings and errors are logged regardless of the flags. 9951 */ 9952 if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) { 9953 return true; 9954 } 9955 9956 /* A verbose message that isn't for a logging-enabled kext and isn't global 9957 * does *not* get logged. 9958 */ 9959 if (!msgKextGlobal && !filterKextGlobal) { 9960 return false; 9961 } 9962 9963 /* Warnings and errors are logged regardless of the flags. 9964 * All other messages must fit the flags and 9965 * have a level at or below the filter. 9966 * 9967 */ 9968 if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) { 9969 return true; 9970 } 9971 return false; 9972 } 9973 9974 extern "C" { 9975 9976 void 9977 OSKextLog( 9978 OSKext * aKext, 9979 OSKextLogSpec msgLogSpec, 9980 const char * format, ...) 9981 { 9982 va_list argList; 9983 9984 va_start(argList, format); 9985 OSKextVLog(aKext, msgLogSpec, format, argList); 9986 va_end(argList); 9987 } 9988 9989 void 9990 OSKextVLog( 9991 OSKext * aKext, 9992 OSKextLogSpec msgLogSpec, 9993 const char * format, 9994 va_list srcArgList) 9995 { 9996 extern int disableConsoleOutput; 9997 9998 bool logForKernel = false; 9999 bool logForUser = false; 10000 va_list argList; 10001 char stackBuffer[120]; 10002 uint32_t length = 0; 10003 char * allocBuffer = NULL; // must kfree 10004 OSNumber * logSpecNum = NULL; // must release 10005 OSString * logString = NULL; // must release 10006 char * buffer = stackBuffer; // do not free 10007 10008 IOLockLock(sKextLoggingLock); 10009 10010 /* Set the kext/global bit in the message spec if we have no 10011 * kext or if the kext requests logging. 10012 */ 10013 if (!aKext || aKext->flags.loggingEnabled) { 10014 msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask; 10015 } 10016 10017 logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter); 10018 if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 10019 logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter); 10020 } 10021 10022 if (! (logForKernel || logForUser) ) { 10023 goto finish; 10024 } 10025 10026 /* No goto from here until past va_end()! 10027 */ 10028 va_copy(argList, srcArgList); 10029 length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList); 10030 va_end(argList); 10031 10032 if (length + 1 >= sizeof(stackBuffer)) { 10033 allocBuffer = (char *)kalloc_tag((length + 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT); 10034 if (!allocBuffer) { 10035 goto finish; 10036 } 10037 10038 /* No goto from here until past va_end()! 10039 */ 10040 va_copy(argList, srcArgList); 10041 vsnprintf(allocBuffer, length + 1, format, argList); 10042 va_end(argList); 10043 10044 buffer = allocBuffer; 10045 } 10046 10047 /* If user space wants the log message, queue it up. 10048 */ 10049 if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 10050 logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec)); 10051 logString = OSString::withCString(buffer); 10052 if (logSpecNum && logString) { 10053 sUserSpaceLogSpecArray->setObject(logSpecNum); 10054 sUserSpaceLogMessageArray->setObject(logString); 10055 } 10056 } 10057 10058 /* Always log messages from the kernel according to the kernel's 10059 * log flags. 10060 */ 10061 if (logForKernel) { 10062 10063 /* If we are in console mode and have a custom log filter, 10064 * colorize the log message. 10065 */ 10066 if (!disableConsoleOutput && sBootArgLogFilterFound) { 10067 const char * color = ""; // do not free 10068 color = colorForFlags(msgLogSpec); 10069 printf("%s%s%s\n", colorForFlags(msgLogSpec), 10070 buffer, color[0] ? VTRESET : ""); 10071 } else { 10072 printf("%s\n", buffer); 10073 } 10074 } 10075 10076 finish: 10077 IOLockUnlock(sKextLoggingLock); 10078 10079 if (allocBuffer) { 10080 kfree(allocBuffer, (length + 1) * sizeof(char)); 10081 } 10082 OSSafeRelease(logString); 10083 OSSafeRelease(logSpecNum); 10084 return; 10085 } 10086 10087 #if KASLR_IOREG_DEBUG 10088 10089 #define IOLOG_INDENT( the_indention ) \ 10090 { \ 10091 int i; \ 10092 for ( i = 0; i < (the_indention); i++ ) { \ 10093 IOLog(" "); \ 10094 } \ 10095 } 10096 10097 extern vm_offset_t vm_kernel_stext; 10098 extern vm_offset_t vm_kernel_etext; 10099 extern mach_vm_offset_t kext_alloc_base; 10100 extern mach_vm_offset_t kext_alloc_max; 10101 10102 bool ScanForAddrInObject(OSObject * theObject, 10103 int indent ); 10104 10105 bool ScanForAddrInObject(OSObject * theObject, 10106 int indent) 10107 { 10108 const OSMetaClass * myTypeID; 10109 OSCollectionIterator * myIter; 10110 OSSymbol * myKey; 10111 OSObject * myValue; 10112 bool myResult = false; 10113 10114 if ( theObject == NULL ) { 10115 IOLog("%s: theObject is NULL \n", 10116 __FUNCTION__); 10117 return myResult; 10118 } 10119 10120 myTypeID = OSTypeIDInst(theObject); 10121 10122 if ( myTypeID == OSTypeID(OSDictionary) ) { 10123 OSDictionary * myDictionary; 10124 10125 myDictionary = OSDynamicCast(OSDictionary, theObject); 10126 myIter = OSCollectionIterator::withCollection( myDictionary ); 10127 if ( myIter == NULL ) 10128 return myResult; 10129 myIter->reset(); 10130 10131 while ( (myKey = OSDynamicCast(OSSymbol, myIter->getNextObject())) ) { 10132 bool myTempResult; 10133 10134 myValue = myDictionary->getObject(myKey); 10135 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 10136 if (myTempResult) { 10137 // if we ever get a true result return true 10138 myResult = true; 10139 IOLOG_INDENT(indent); 10140 IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy()); 10141 } 10142 } 10143 myIter->release(); 10144 } 10145 else if ( myTypeID == OSTypeID(OSArray) ) { 10146 OSArray * myArray; 10147 10148 myArray = OSDynamicCast(OSArray, theObject); 10149 myIter = OSCollectionIterator::withCollection(myArray); 10150 if ( myIter == NULL ) 10151 return myResult; 10152 myIter->reset(); 10153 10154 while ( (myValue = myIter->getNextObject()) ) { 10155 bool myTempResult; 10156 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 10157 if (myTempResult) { 10158 // if we ever get a true result return true 10159 myResult = true; 10160 IOLOG_INDENT(indent); 10161 IOLog("OSArray: \n"); 10162 } 10163 } 10164 myIter->release(); 10165 } 10166 else if ( myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol) ) { 10167 10168 // should we look for addresses in strings? 10169 } 10170 else if ( myTypeID == OSTypeID(OSData) ) { 10171 10172 void * * myPtrPtr; 10173 unsigned int myLen; 10174 OSData * myDataObj; 10175 10176 myDataObj = OSDynamicCast(OSData, theObject); 10177 myPtrPtr = (void * *) myDataObj->getBytesNoCopy(); 10178 myLen = myDataObj->getLength(); 10179 10180 if (myPtrPtr && myLen && myLen > 7) { 10181 int i; 10182 int myPtrCount = (myLen / sizeof(void *)); 10183 10184 for (i = 0; i < myPtrCount; i++) { 10185 UInt64 numberValue = (UInt64) *(myPtrPtr); 10186 10187 if ( kext_alloc_max != 0 && 10188 numberValue >= kext_alloc_base && 10189 numberValue < kext_alloc_max ) { 10190 10191 OSKext * myKext = NULL; // must release (looked up) 10192 // IOLog("found OSData %p in kext map %p to %p \n", 10193 // *(myPtrPtr), 10194 // (void *) kext_alloc_base, 10195 // (void *) kext_alloc_max); 10196 10197 myKext = OSKext::lookupKextWithAddress( (vm_address_t) *(myPtrPtr) ); 10198 if (myKext) { 10199 IOLog("found addr %p from an OSData obj within kext \"%s\" \n", 10200 *(myPtrPtr), 10201 myKext->getIdentifierCString()); 10202 myKext->release(); 10203 } 10204 myResult = true; 10205 } 10206 if ( vm_kernel_etext != 0 && 10207 numberValue >= vm_kernel_stext && 10208 numberValue < vm_kernel_etext ) { 10209 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n", 10210 *(myPtrPtr), 10211 (void *) vm_kernel_stext, 10212 (void *) vm_kernel_etext); 10213 myResult = true; 10214 } 10215 myPtrPtr++; 10216 } 10217 } 10218 } 10219 else if ( myTypeID == OSTypeID(OSBoolean) ) { 10220 10221 // do nothing here... 10222 } 10223 else if ( myTypeID == OSTypeID(OSNumber) ) { 10224 10225 OSNumber * number = OSDynamicCast(OSNumber, theObject); 10226 10227 UInt64 numberValue = number->unsigned64BitValue(); 10228 10229 if ( kext_alloc_max != 0 && 10230 numberValue >= kext_alloc_base && 10231 numberValue < kext_alloc_max ) { 10232 10233 OSKext * myKext = NULL; // must release (looked up) 10234 IOLog("found OSNumber in kext map %p to %p \n", 10235 (void *) kext_alloc_base, 10236 (void *) kext_alloc_max); 10237 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 10238 10239 myKext = OSKext::lookupKextWithAddress( (vm_address_t) numberValue ); 10240 if (myKext) { 10241 IOLog("found in kext \"%s\" \n", 10242 myKext->getIdentifierCString()); 10243 myKext->release(); 10244 } 10245 10246 myResult = true; 10247 } 10248 if ( vm_kernel_etext != 0 && 10249 numberValue >= vm_kernel_stext && 10250 numberValue < vm_kernel_etext ) { 10251 IOLog("found OSNumber in kernel text segment %p to %p \n", 10252 (void *) vm_kernel_stext, 10253 (void *) vm_kernel_etext); 10254 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 10255 myResult = true; 10256 } 10257 } 10258 #if 0 10259 else { 10260 const OSMetaClass* myMetaClass = NULL; 10261 10262 myMetaClass = theObject->getMetaClass(); 10263 if ( myMetaClass ) { 10264 IOLog("class %s \n", myMetaClass->getClassName() ); 10265 } 10266 else { 10267 IOLog("Unknown object \n" ); 10268 } 10269 } 10270 #endif 10271 10272 return myResult; 10273 } 10274 #endif // KASLR_KEXT_DEBUG 10275 10276 }; /* extern "C" */ 10277 10278 #if PRAGMA_MARK 10279 #pragma mark Backtrace Dump & kmod_get_info() support 10280 #endif 10281 /********************************************************************* 10282 * This function must be safe to call in panic context. 10283 *********************************************************************/ 10284 /* static */ 10285 void 10286 OSKext::printKextsInBacktrace( 10287 vm_offset_t * addr, 10288 unsigned int cnt, 10289 int (* printf_func)(const char *fmt, ...), 10290 bool lockFlag, 10291 bool doUnslide) 10292 { 10293 addr64_t summary_page = 0; 10294 addr64_t last_summary_page = 0; 10295 bool found_kmod = false; 10296 u_int i = 0; 10297 10298 if (lockFlag) { 10299 if (!sKextSummariesLock) return; 10300 IOLockLock(sKextSummariesLock); 10301 } 10302 10303 if (!gLoadedKextSummaries) { 10304 (*printf_func)(" can't perform kext scan: no kext summary"); 10305 goto finish; 10306 } 10307 10308 summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries); 10309 last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize); 10310 for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) { 10311 if (pmap_find_phys(kernel_pmap, summary_page) == 0) { 10312 (*printf_func)(" can't perform kext scan: " 10313 "missing kext summary page %p", summary_page); 10314 goto finish; 10315 } 10316 } 10317 10318 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 10319 OSKextLoadedKextSummary * summary; 10320 10321 summary = gLoadedKextSummaries->summaries + i; 10322 if (!summary->address) { 10323 continue; 10324 } 10325 10326 if (!summaryIsInBacktrace(summary, addr, cnt)) { 10327 continue; 10328 } 10329 10330 if (!found_kmod) { 10331 (*printf_func)(" Kernel Extensions in backtrace:\n"); 10332 found_kmod = true; 10333 } 10334 10335 printSummary(summary, printf_func, doUnslide); 10336 } 10337 10338 finish: 10339 if (lockFlag) { 10340 IOLockUnlock(sKextSummariesLock); 10341 } 10342 10343 return; 10344 } 10345 10346 /********************************************************************* 10347 * This function must be safe to call in panic context. 10348 *********************************************************************/ 10349 /* static */ 10350 boolean_t 10351 OSKext::summaryIsInBacktrace( 10352 OSKextLoadedKextSummary * summary, 10353 vm_offset_t * addr, 10354 unsigned int cnt) 10355 { 10356 u_int i = 0; 10357 10358 for (i = 0; i < cnt; i++) { 10359 vm_offset_t kscan_addr = addr[i]; 10360 if ((kscan_addr >= summary->address) && 10361 (kscan_addr < (summary->address + summary->size))) 10362 { 10363 return TRUE; 10364 } 10365 } 10366 10367 return FALSE; 10368 } 10369 10370 /********************************************************************* 10371 * scan list of loaded kext summaries looking for a load address match and if 10372 * found return the UUID C string. If not found then set empty string. 10373 *********************************************************************/ 10374 static void findSummaryUUID( 10375 uint32_t tag_ID, 10376 uuid_string_t uuid); 10377 10378 static void findSummaryUUID( 10379 uint32_t tag_ID, 10380 uuid_string_t uuid) 10381 { 10382 u_int i; 10383 10384 uuid[0] = 0x00; // default to no UUID 10385 10386 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 10387 OSKextLoadedKextSummary * summary; 10388 10389 summary = gLoadedKextSummaries->summaries + i; 10390 10391 if (summary->loadTag == tag_ID) { 10392 (void) uuid_unparse(summary->uuid, uuid); 10393 break; 10394 } 10395 } 10396 return; 10397 } 10398 10399 /********************************************************************* 10400 * This function must be safe to call in panic context. 10401 *********************************************************************/ 10402 void OSKext::printSummary( 10403 OSKextLoadedKextSummary * summary, 10404 int (* printf_func)(const char *fmt, ...), 10405 bool doUnslide) 10406 { 10407 kmod_reference_t * kmod_ref = NULL; 10408 uuid_string_t uuid; 10409 char version[kOSKextVersionMaxLength]; 10410 uint64_t tmpAddr; 10411 10412 if (!OSKextVersionGetString(summary->version, version, sizeof(version))) { 10413 strlcpy(version, "unknown version", sizeof(version)); 10414 } 10415 (void) uuid_unparse(summary->uuid, uuid); 10416 10417 if (doUnslide) { 10418 tmpAddr = VM_KERNEL_UNSLIDE(summary->address); 10419 } 10420 else { 10421 tmpAddr = summary->address; 10422 } 10423 (*printf_func)(" %s(%s)[%s]@0x%llx->0x%llx\n", 10424 summary->name, version, uuid, 10425 tmpAddr, tmpAddr + summary->size - 1); 10426 10427 /* print dependency info */ 10428 for (kmod_ref = (kmod_reference_t *) summary->reference_list; 10429 kmod_ref; 10430 kmod_ref = kmod_ref->next) { 10431 kmod_info_t * rinfo; 10432 10433 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) { 10434 (*printf_func)(" kmod dependency scan stopped " 10435 "due to missing dependency page: %p\n", kmod_ref); 10436 break; 10437 } 10438 rinfo = kmod_ref->info; 10439 10440 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) { 10441 (*printf_func)(" kmod dependency scan stopped " 10442 "due to missing kmod page: %p\n", rinfo); 10443 break; 10444 } 10445 10446 if (!rinfo->address) { 10447 continue; // skip fake entries for built-ins 10448 } 10449 10450 /* locate UUID in gLoadedKextSummaries */ 10451 findSummaryUUID(rinfo->id, uuid); 10452 10453 if (doUnslide) { 10454 tmpAddr = VM_KERNEL_UNSLIDE(rinfo->address); 10455 } 10456 else { 10457 tmpAddr = rinfo->address; 10458 } 10459 (*printf_func)(" dependency: %s(%s)[%s]@%p\n", 10460 rinfo->name, rinfo->version, uuid, tmpAddr); 10461 } 10462 return; 10463 } 10464 10465 10466 /******************************************************************************* 10467 * substitute() looks at an input string (a pointer within a larger buffer) 10468 * for a match to a substring, and on match it writes the marker & substitution 10469 * character to an output string, updating the scan (from) and 10470 * output (to) indexes as appropriate. 10471 *******************************************************************************/ 10472 static int substitute( 10473 const char * scan_string, 10474 char * string_out, 10475 uint32_t * to_index, 10476 uint32_t * from_index, 10477 const char * substring, 10478 char marker, 10479 char substitution); 10480 10481 /* string_out must be at least KMOD_MAX_NAME bytes. 10482 */ 10483 static int 10484 substitute( 10485 const char * scan_string, 10486 char * string_out, 10487 uint32_t * to_index, 10488 uint32_t * from_index, 10489 const char * substring, 10490 char marker, 10491 char substitution) 10492 { 10493 uint32_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1); 10494 10495 /* On a substring match, append the marker (if there is one) and then 10496 * the substitution character, updating the output (to) index accordingly. 10497 * Then update the input (from) length by the length of the substring 10498 * that got replaced. 10499 */ 10500 if (!strncmp(scan_string, substring, substring_length)) { 10501 if (marker) { 10502 string_out[(*to_index)++] = marker; 10503 } 10504 string_out[(*to_index)++] = substitution; 10505 (*from_index) += substring_length; 10506 return 1; 10507 } 10508 return 0; 10509 } 10510 10511 /******************************************************************************* 10512 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least 10513 * KMOD_MAX_NAME characters and performs various substitutions of common 10514 * prefixes & substrings as defined by tables in kext_panic_report.h. 10515 *******************************************************************************/ 10516 static void compactIdentifier( 10517 const char * identifier, 10518 char * identifier_out, 10519 char ** identifier_out_end); 10520 10521 static void 10522 compactIdentifier( 10523 const char * identifier, 10524 char * identifier_out, 10525 char ** identifier_out_end) 10526 { 10527 uint32_t from_index, to_index; 10528 uint32_t scan_from_index = 0; 10529 uint32_t scan_to_index = 0; 10530 subs_entry_t * subs_entry = NULL; 10531 int did_sub = 0; 10532 10533 from_index = to_index = 0; 10534 identifier_out[0] = '\0'; 10535 10536 /* Replace certain identifier prefixes with shorter @+character sequences. 10537 * Check the return value of substitute() so we only replace the prefix. 10538 */ 10539 for (subs_entry = &kext_identifier_prefix_subs[0]; 10540 subs_entry->substring && !did_sub; 10541 subs_entry++) { 10542 10543 did_sub = substitute(identifier, identifier_out, 10544 &scan_to_index, &scan_from_index, 10545 subs_entry->substring, /* marker */ '\0', subs_entry->substitute); 10546 } 10547 did_sub = 0; 10548 10549 /* Now scan through the identifier looking for the common substrings 10550 * and replacing them with shorter !+character sequences via substitute(). 10551 */ 10552 for (/* see above */; 10553 scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index]; 10554 /* see loop */) { 10555 10556 const char * scan_string = &identifier[scan_from_index]; 10557 10558 did_sub = 0; 10559 10560 if (scan_from_index) { 10561 for (subs_entry = &kext_identifier_substring_subs[0]; 10562 subs_entry->substring && !did_sub; 10563 subs_entry++) { 10564 10565 did_sub = substitute(scan_string, identifier_out, 10566 &scan_to_index, &scan_from_index, 10567 subs_entry->substring, '!', subs_entry->substitute); 10568 } 10569 } 10570 10571 /* If we didn't substitute, copy the input character to the output. 10572 */ 10573 if (!did_sub) { 10574 identifier_out[scan_to_index++] = identifier[scan_from_index++]; 10575 } 10576 } 10577 10578 identifier_out[scan_to_index] = '\0'; 10579 if (identifier_out_end) { 10580 *identifier_out_end = &identifier_out[scan_to_index]; 10581 } 10582 10583 return; 10584 } 10585 10586 /******************************************************************************* 10587 * assemble_identifier_and_version() adds to a string buffer a compacted 10588 * bundle identifier followed by a version string. 10589 *******************************************************************************/ 10590 10591 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length. 10592 */ 10593 static int assemble_identifier_and_version( 10594 kmod_info_t * kmod_info, 10595 char * identPlusVers, 10596 int bufSize); 10597 10598 static int 10599 assemble_identifier_and_version( 10600 kmod_info_t * kmod_info, 10601 char * identPlusVers, 10602 int bufSize) 10603 { 10604 int result = 0; 10605 10606 compactIdentifier(kmod_info->name, identPlusVers, NULL); 10607 result = strnlen(identPlusVers, KMOD_MAX_NAME - 1); 10608 identPlusVers[result++] = '\t'; // increment for real char 10609 identPlusVers[result] = '\0'; // don't increment for nul char 10610 result = strlcat(identPlusVers, kmod_info->version, bufSize); 10611 if (result >= bufSize) { 10612 identPlusVers[bufSize - 1] = '\0'; 10613 result = bufSize - 1; 10614 } 10615 10616 return result; 10617 } 10618 10619 /******************************************************************************* 10620 * Assumes sKextLock is held. 10621 *******************************************************************************/ 10622 /* static */ 10623 int 10624 OSKext::saveLoadedKextPanicListTyped( 10625 const char * prefix, 10626 int invertFlag, 10627 int libsFlag, 10628 char * paniclist, 10629 uint32_t list_size) 10630 { 10631 int result = -1; 10632 unsigned int count, i; 10633 10634 count = sLoadedKexts->getCount(); 10635 if (!count) { 10636 goto finish; 10637 } 10638 10639 i = count - 1; 10640 do { 10641 OSObject * rawKext = sLoadedKexts->getObject(i); 10642 OSKext * theKext = OSDynamicCast(OSKext, rawKext); 10643 int match; 10644 uint32_t identPlusVersLength; 10645 uint32_t tempLen; 10646 char identPlusVers[2*KMOD_MAX_NAME]; 10647 10648 if (!rawKext) { 10649 printf("OSKext::saveLoadedKextPanicListTyped - " 10650 "NULL kext in loaded kext list; continuing\n"); 10651 continue; 10652 } 10653 10654 if (!theKext) { 10655 printf("OSKext::saveLoadedKextPanicListTyped - " 10656 "Kext type cast failed in loaded kext list; continuing\n"); 10657 continue; 10658 } 10659 10660 /* Skip all built-in kexts. 10661 */ 10662 if (theKext->isKernelComponent()) { 10663 continue; 10664 } 10665 10666 kmod_info_t * kmod_info = theKext->kmod_info; 10667 10668 /* Filter for kmod name (bundle identifier). 10669 */ 10670 match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME)); 10671 if ((match && invertFlag) || (!match && !invertFlag)) { 10672 continue; 10673 } 10674 10675 /* Filter for libraries (kexts that have a compatible version). 10676 */ 10677 if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) || 10678 (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) { 10679 10680 continue; 10681 } 10682 10683 if (!kmod_info || 10684 !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) { 10685 10686 printf("kext scan stopped due to missing kmod_info page: %p\n", 10687 kmod_info); 10688 goto finish; 10689 } 10690 10691 identPlusVersLength = assemble_identifier_and_version(kmod_info, 10692 identPlusVers, 10693 sizeof(identPlusVers)); 10694 if (!identPlusVersLength) { 10695 printf("error saving loaded kext info\n"); 10696 goto finish; 10697 } 10698 10699 /* make sure everything fits and we null terminate. 10700 */ 10701 tempLen = strlcat(paniclist, identPlusVers, list_size); 10702 if (tempLen >= list_size) { 10703 // panic list is full, keep it and null terminate 10704 paniclist[list_size - 1] = 0x00; 10705 result = 0; 10706 goto finish; 10707 } 10708 tempLen = strlcat(paniclist, "\n", list_size); 10709 if (tempLen >= list_size) { 10710 // panic list is full, keep it and null terminate 10711 paniclist[list_size - 1] = 0x00; 10712 result = 0; 10713 goto finish; 10714 } 10715 } while (i--); 10716 10717 result = 0; 10718 finish: 10719 10720 return result; 10721 } 10722 10723 /********************************************************************* 10724 *********************************************************************/ 10725 /* static */ 10726 void 10727 OSKext::saveLoadedKextPanicList(void) 10728 { 10729 char * newlist = NULL; 10730 uint32_t newlist_size = 0; 10731 10732 newlist_size = KEXT_PANICLIST_SIZE; 10733 newlist = (char *)kalloc_tag(newlist_size, VM_KERN_MEMORY_OSKEXT); 10734 10735 if (!newlist) { 10736 OSKextLog(/* kext */ NULL, 10737 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 10738 "Couldn't allocate kext panic log buffer."); 10739 goto finish; 10740 } 10741 10742 newlist[0] = '\0'; 10743 10744 // non-"com.apple." kexts 10745 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1, 10746 /* libs? */ -1, newlist, newlist_size) != 0) { 10747 10748 goto finish; 10749 } 10750 // "com.apple." nonlibrary kexts 10751 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 10752 /* libs? */ 0, newlist, newlist_size) != 0) { 10753 10754 goto finish; 10755 } 10756 // "com.apple." library kexts 10757 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 10758 /* libs? */ 1, newlist, newlist_size) != 0) { 10759 10760 goto finish; 10761 } 10762 10763 if (loaded_kext_paniclist) { 10764 kfree(loaded_kext_paniclist, loaded_kext_paniclist_size); 10765 } 10766 loaded_kext_paniclist = newlist; 10767 newlist = NULL; 10768 loaded_kext_paniclist_size = newlist_size; 10769 10770 finish: 10771 if (newlist) { 10772 kfree(newlist, newlist_size); 10773 } 10774 return; 10775 } 10776 10777 /********************************************************************* 10778 * Assumes sKextLock is held. 10779 *********************************************************************/ 10780 void 10781 OSKext::savePanicString(bool isLoading) 10782 { 10783 u_long len; 10784 10785 if (!kmod_info) { 10786 return; // do not goto finish here b/c of lock 10787 } 10788 10789 len = assemble_identifier_and_version( kmod_info, 10790 (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf, 10791 (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf) ); 10792 if (!len) { 10793 printf("error saving unloaded kext info\n"); 10794 goto finish; 10795 } 10796 10797 if (isLoading) { 10798 last_loaded_strlen = len; 10799 last_loaded_address = (void *)kmod_info->address; 10800 last_loaded_size = kmod_info->size; 10801 clock_get_uptime(&last_loaded_timestamp); 10802 } else { 10803 last_unloaded_strlen = len; 10804 last_unloaded_address = (void *)kmod_info->address; 10805 last_unloaded_size = kmod_info->size; 10806 clock_get_uptime(&last_unloaded_timestamp); 10807 } 10808 10809 finish: 10810 return; 10811 } 10812 10813 /********************************************************************* 10814 *********************************************************************/ 10815 /* static */ 10816 void 10817 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...)) 10818 { 10819 if (last_loaded_strlen) { 10820 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n", 10821 AbsoluteTime_to_scalar(&last_loaded_timestamp), 10822 last_loaded_strlen, last_loaded_str_buf, 10823 last_loaded_address, last_loaded_size); 10824 } 10825 10826 if (last_unloaded_strlen) { 10827 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n", 10828 AbsoluteTime_to_scalar(&last_unloaded_timestamp), 10829 last_unloaded_strlen, last_unloaded_str_buf, 10830 last_unloaded_address, last_unloaded_size); 10831 } 10832 10833 printf_func("loaded kexts:\n"); 10834 if (loaded_kext_paniclist && 10835 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) && 10836 loaded_kext_paniclist[0]) { 10837 10838 printf_func("%.*s", 10839 strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size), 10840 loaded_kext_paniclist); 10841 } else { 10842 printf_func("(none)\n"); 10843 } 10844 return; 10845 } 10846 10847 /********************************************************************* 10848 * Assumes sKextLock is held. 10849 *********************************************************************/ 10850 /* static */ 10851 void 10852 OSKext::updateLoadedKextSummaries(void) 10853 { 10854 kern_return_t result = KERN_FAILURE; 10855 OSKextLoadedKextSummaryHeader *summaryHeader = NULL; 10856 OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL; 10857 OSKext *aKext; 10858 vm_map_offset_t start, end; 10859 size_t summarySize = 0; 10860 size_t size; 10861 u_int count; 10862 u_int maxKexts; 10863 u_int i, j; 10864 OSKextActiveAccount * accountingList; 10865 OSKextActiveAccount * prevAccountingList; 10866 uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount; 10867 10868 prevAccountingList = NULL; 10869 prevAccountingListCount = 0; 10870 10871 #if DEVELOPMENT || DEBUG 10872 if (IORecursiveLockHaveLock(sKextLock) == false) { 10873 panic("sKextLock must be held"); 10874 } 10875 #endif 10876 10877 IOLockLock(sKextSummariesLock); 10878 10879 count = sLoadedKexts->getCount(); 10880 for (i = 0, maxKexts = 0; i < count; ++i) { 10881 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 10882 maxKexts += (aKext && aKext->isExecutable()); 10883 } 10884 10885 if (!maxKexts) goto finish; 10886 if (maxKexts < kOSKextTypicalLoadCount) maxKexts = kOSKextTypicalLoadCount; 10887 10888 /* Calculate the size needed for the new summary headers. 10889 */ 10890 10891 size = sizeof(*gLoadedKextSummaries); 10892 size += maxKexts * sizeof(*gLoadedKextSummaries->summaries); 10893 size = round_page(size); 10894 10895 if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) { 10896 if (gLoadedKextSummaries) { 10897 kmem_free(kernel_map, 10898 (vm_offset_t)gLoadedKextSummaries, 10899 sLoadedKextSummariesAllocSize); 10900 gLoadedKextSummaries = NULL; 10901 sLoadedKextSummariesAllocSize = 0; 10902 } 10903 result = kmem_alloc(kernel_map, 10904 (vm_offset_t*)&summaryHeaderAlloc, 10905 size, VM_KERN_MEMORY_OSKEXT); 10906 if (result != KERN_SUCCESS) goto finish; 10907 summaryHeader = summaryHeaderAlloc; 10908 summarySize = size; 10909 } 10910 else { 10911 summaryHeader = gLoadedKextSummaries; 10912 summarySize = sLoadedKextSummariesAllocSize; 10913 10914 start = (vm_map_offset_t) summaryHeader; 10915 end = start + summarySize; 10916 result = vm_map_protect(kernel_map, 10917 start, 10918 end, 10919 VM_PROT_DEFAULT, 10920 FALSE); 10921 if (result != KERN_SUCCESS) goto finish; 10922 } 10923 10924 /* Populate the summary header. 10925 */ 10926 10927 bzero(summaryHeader, summarySize); 10928 summaryHeader->version = kOSKextLoadedKextSummaryVersion; 10929 summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary); 10930 10931 /* Populate each kext summary. 10932 */ 10933 10934 count = sLoadedKexts->getCount(); 10935 accountingListAlloc = 0; 10936 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 10937 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 10938 if (!aKext || !aKext->isExecutable()) { 10939 continue; 10940 } 10941 10942 aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]); 10943 summaryHeader->numSummaries++; 10944 accountingListAlloc++; 10945 } 10946 10947 accountingList = IONew(typeof(accountingList[0]), accountingListAlloc); 10948 accountingListCount = 0; 10949 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 10950 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 10951 if (!aKext || !aKext->isExecutable()) { 10952 continue; 10953 } 10954 10955 OSKextActiveAccount activeAccount; 10956 aKext->updateActiveAccount(&activeAccount); 10957 // order by address 10958 for (idx = 0; idx < accountingListCount; idx++) 10959 { 10960 if (activeAccount.address < accountingList[idx].address) break; 10961 } 10962 bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0])); 10963 accountingList[idx] = activeAccount; 10964 accountingListCount++; 10965 } 10966 assert(accountingListCount == accountingListAlloc); 10967 /* Write protect the buffer and move it into place. 10968 */ 10969 10970 start = (vm_map_offset_t) summaryHeader; 10971 end = start + summarySize; 10972 10973 result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE); 10974 if (result != KERN_SUCCESS) goto finish; 10975 10976 gLoadedKextSummaries = summaryHeader; 10977 sLoadedKextSummariesAllocSize = summarySize; 10978 summaryHeaderAlloc = NULL; 10979 10980 /* Call the magic breakpoint function through a static function pointer so 10981 * the compiler can't optimize the function away. 10982 */ 10983 if (sLoadedKextSummariesUpdated) (*sLoadedKextSummariesUpdated)(); 10984 10985 IOSimpleLockLock(sKextAccountsLock); 10986 prevAccountingList = sKextAccounts; 10987 prevAccountingListCount = sKextAccountsCount; 10988 sKextAccounts = accountingList; 10989 sKextAccountsCount = accountingListCount; 10990 IOSimpleLockUnlock(sKextAccountsLock); 10991 10992 finish: 10993 IOLockUnlock(sKextSummariesLock); 10994 10995 /* If we had to allocate a new buffer but failed to generate the summaries, 10996 * free that now. 10997 */ 10998 if (summaryHeaderAlloc) { 10999 kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize); 11000 } 11001 if (prevAccountingList) { 11002 IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount); 11003 } 11004 11005 return; 11006 } 11007 11008 /********************************************************************* 11009 *********************************************************************/ 11010 void 11011 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary) 11012 { 11013 OSData *uuid; 11014 11015 strlcpy(summary->name, getIdentifierCString(), 11016 sizeof(summary->name)); 11017 11018 uuid = copyUUID(); 11019 if (uuid) { 11020 memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid)); 11021 OSSafeRelease(uuid); 11022 } 11023 11024 summary->address = kmod_info->address; 11025 summary->size = kmod_info->size; 11026 summary->version = getVersion(); 11027 summary->loadTag = kmod_info->id; 11028 summary->flags = 0; 11029 summary->reference_list = (uint64_t) kmod_info->reference_list; 11030 11031 return; 11032 } 11033 11034 /********************************************************************* 11035 *********************************************************************/ 11036 11037 void 11038 OSKext::updateActiveAccount(OSKextActiveAccount *account) 11039 { 11040 bzero(account, sizeof(*account)); 11041 account->address = kmod_info->address; 11042 if (account->address) { 11043 account->address_end = kmod_info->address + kmod_info->size; 11044 } 11045 account->account = this->account; 11046 } 11047 11048 extern "C" const vm_allocation_site_t * 11049 OSKextGetAllocationSiteForCaller(uintptr_t address) 11050 { 11051 OSKextActiveAccount * active; 11052 vm_allocation_site_t * site; 11053 uint32_t baseIdx; 11054 uint32_t lim; 11055 11056 IOSimpleLockLock(sKextAccountsLock); 11057 site = NULL; 11058 // bsearch sKextAccounts list 11059 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) 11060 { 11061 active = &sKextAccounts[baseIdx + (lim >> 1)]; 11062 if ((address >= active->address) && (address < active->address_end)) 11063 { 11064 site = &active->account->site; 11065 if (!site->tag) vm_tag_alloc_locked(site); 11066 break; 11067 } 11068 else if (address > active->address) 11069 { 11070 // move right 11071 baseIdx += (lim >> 1) + 1; 11072 lim--; 11073 } 11074 // else move left 11075 } 11076 IOSimpleLockUnlock(sKextAccountsLock); 11077 11078 return (site); 11079 } 11080 11081 extern "C" uint32_t 11082 OSKextGetKmodIDForSite(vm_allocation_site_t * site) 11083 { 11084 OSKextAccount * account = (typeof(account)) site; 11085 return (account->loadTag); 11086 } 11087 11088 extern "C" void 11089 OSKextFreeSite(vm_allocation_site_t * site) 11090 { 11091 OSKextAccount * freeAccount = (typeof(freeAccount)) site; 11092 IODelete(freeAccount, OSKextAccount, 1); 11093 } 11094 11095 /********************************************************************* 11096 *********************************************************************/ 11097 11098 #if CONFIG_KEC_FIPS 11099 11100 #if PRAGMA_MARK 11101 #pragma mark Kernel External Components for FIPS compliance 11102 #endif 11103 11104 /********************************************************************* 11105 * Kernel External Components for FIPS compliance (KEC_FIPS) 11106 *********************************************************************/ 11107 static void * 11108 GetAppleTEXTHashForKext(OSKext * theKext, OSDictionary *theInfoDict) 11109 { 11110 AppleTEXTHash_t my_ath = {1, 0, NULL}; 11111 AppleTEXTHash_t * my_athp = NULL; // do not release 11112 OSDictionary * textHashDict = NULL; // do not release 11113 OSData * segmentHash = NULL; // do not release 11114 11115 if (theKext == NULL || theInfoDict == NULL) { 11116 return(NULL); 11117 } 11118 11119 textHashDict = OSDynamicCast(OSDictionary, theInfoDict->getObject(kAppleTextHashesKey)); 11120 if (textHashDict == NULL) { 11121 return(NULL); 11122 } 11123 11124 segmentHash = OSDynamicCast(OSData, 11125 textHashDict->getObject(ARCHNAME)); 11126 if (segmentHash == NULL) { 11127 return(NULL); 11128 } 11129 11130 // KEC_FIPS type kexts never unload so we don't have to clean up our 11131 // AppleTEXTHash_t 11132 if (kmem_alloc(kernel_map, (vm_offset_t *) &my_athp, 11133 sizeof(AppleTEXTHash_t), VM_KERN_MEMORY_OSKEXT) != KERN_SUCCESS) { 11134 return(NULL); 11135 } 11136 11137 memcpy(my_athp, &my_ath, sizeof(my_ath)); 11138 my_athp->ath_length = segmentHash->getLength(); 11139 if (my_athp->ath_length > 0) { 11140 my_athp->ath_hash = (void *)segmentHash->getBytesNoCopy(); 11141 } 11142 11143 #if 0 11144 OSKextLog(theKext, 11145 kOSKextLogErrorLevel | 11146 kOSKextLogGeneralFlag, 11147 "Kext %s ath_version %d ath_length %d ath_hash %p", 11148 theKext->getIdentifierCString(), 11149 my_athp->ath_version, 11150 my_athp->ath_length, 11151 my_athp->ath_hash); 11152 #endif 11153 11154 return( (void *) my_athp ); 11155 } 11156 11157 #endif // CONFIG_KEC_FIPS 11158 11159