1 /* 2 * Copyright (c) 2008-2016 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 <string.h> 31 #include <kern/clock.h> 32 #include <kern/host.h> 33 #include <kern/kext_alloc.h> 34 #include <firehose/tracepoint_private.h> 35 #include <firehose/chunk_private.h> 36 #include <os/firehose_buffer_private.h> 37 #include <vm/vm_kern.h> 38 #include <kextd/kextd_mach.h> 39 #include <libkern/kernel_mach_header.h> 40 #include <libkern/kext_panic_report.h> 41 #include <libkern/kext_request_keys.h> 42 #include <libkern/mkext.h> 43 #include <libkern/prelink.h> 44 #include <libkern/version.h> 45 #include <libkern/zlib.h> 46 #include <mach/host_special_ports.h> 47 #include <mach/mach_vm.h> 48 #include <mach/mach_time.h> 49 #include <sys/sysctl.h> 50 #include <uuid/uuid.h> 51 #include <sys/random.h> 52 53 #include <sys/pgo.h> 54 55 #if CONFIG_MACF 56 #include <sys/kauth.h> 57 #include <security/mac_framework.h> 58 #endif 59 }; 60 61 #include <libkern/OSKextLibPrivate.h> 62 #include <libkern/c++/OSKext.h> 63 #include <libkern/c++/OSLib.h> 64 65 #include <IOKit/IOLib.h> 66 #include <IOKit/IOCatalogue.h> 67 #include <IOKit/IORegistryEntry.h> 68 #include <IOKit/IOService.h> 69 70 #include <IOKit/IOStatisticsPrivate.h> 71 #include <IOKit/IOBSD.h> 72 73 #include <san/kasan.h> 74 75 #if PRAGMA_MARK 76 #pragma mark External & Internal Function Protos 77 #endif 78 /********************************************************************* 79 *********************************************************************/ 80 extern "C" { 81 extern int IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize); 82 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize); 83 84 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */ 85 extern int dtrace_keep_kernel_symbols(void); 86 } 87 88 extern unsigned long gVirtBase; 89 extern unsigned long gPhysBase; 90 #if CONFIG_EMBEDDED 91 extern vm_offset_t segLOWESTTEXT; 92 #endif /* CONFIG_EMBEDDED */ 93 94 static OSReturn _OSKextCreateRequest( 95 const char * predicate, 96 OSDictionary ** requestP); 97 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict); 98 static OSObject * _OSKextGetRequestArgument( 99 OSDictionary * requestDict, 100 const char * argName); 101 static bool _OSKextSetRequestArgument( 102 OSDictionary * requestDict, 103 const char * argName, 104 OSObject * value); 105 static void * _OSKextExtractPointer(OSData * wrapper); 106 static OSReturn _OSDictionarySetCStringValue( 107 OSDictionary * dict, 108 const char * key, 109 const char * value); 110 static bool _OSKextInPrelinkRebuildWindow(void); 111 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID); 112 113 // We really should add containsObject() & containsCString to OSCollection & subclasses. 114 // So few pad slots, though.... 115 static bool _OSArrayContainsCString(OSArray * array, const char * cString); 116 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code); 117 118 /* Prelinked arm kexts do not have VM entries because the method we use to 119 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does 120 * not work on ARM. To get around that, we must free prelinked kext 121 * executables with ml_static_mfree() instead of kext_free(). 122 */ 123 #if __i386__ || __x86_64__ 124 #define VM_MAPPED_KEXTS 1 125 #define KASLR_KEXT_DEBUG 0 126 #define KASLR_IOREG_DEBUG 0 127 #elif __arm__ || __arm64__ 128 #define VM_MAPPED_KEXTS 0 129 #define KASLR_KEXT_DEBUG 0 130 #else 131 #error Unsupported architecture 132 #endif 133 134 #if PRAGMA_MARK 135 #pragma mark Constants & Macros 136 #endif 137 /********************************************************************* 138 * Constants & Macros 139 *********************************************************************/ 140 141 /* Use this number to create containers. 142 */ 143 #define kOSKextTypicalLoadCount (150) 144 145 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict. 146 * A loaded kext will no dependents or external retains will have 2 retains. 147 */ 148 #define kOSKextMinRetainCount (1) 149 #define kOSKextMinLoadedRetainCount (2) 150 151 /********** 152 * Strings and substrings used in dependency resolution. 153 */ 154 #define APPLE_KEXT_PREFIX "com.apple." 155 #define KERNEL_LIB "com.apple.kernel" 156 157 #define PRIVATE_KPI "com.apple.kpi.private" 158 159 /* Version for compatbility pseudokexts (com.apple.kernel.*), 160 * compatible back to v6.0. 161 */ 162 #define KERNEL6_LIB "com.apple.kernel.6.0" 163 #define KERNEL6_VERSION "7.9.9" 164 165 #define KERNEL_LIB_PREFIX "com.apple.kernel." 166 #define KPI_LIB_PREFIX "com.apple.kpi." 167 168 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0) 169 170 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes 171 #define MINIMUM_WAKEUP_SECONDS (30) 172 173 /********************************************************************* 174 * infoDict keys for internally-stored data. Saves on ivar slots for 175 * objects we don't keep around past boot time or during active load. 176 *********************************************************************/ 177 178 /* A usable, uncompressed file is stored under this key. 179 */ 180 #define _kOSKextExecutableKey "_OSKextExecutable" 181 182 /* An indirect reference to the executable file from an mkext 183 * is stored under this key. 184 */ 185 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference" 186 187 /* If the file is contained in a larger buffer laid down by the booter or 188 * sent from user space, the OSKext stores that OSData under this key so that 189 * references are properly tracked. This is always an mkext, right now. 190 */ 191 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData" 192 193 #define OS_LOG_HDR_VERSION 1 194 #define NUM_OS_LOG_SECTIONS 2 195 196 #define OS_LOG_SECT_IDX 0 197 #define CSTRING_SECT_IDX 1 198 199 #if PRAGMA_MARK 200 #pragma mark Typedefs 201 #endif 202 /********************************************************************* 203 * Typedefs 204 *********************************************************************/ 205 206 /********************************************************************* 207 * osLogDataHeaderRef describes the header information of an OSData 208 * object that is returned when querying for kOSBundleLogStringsKey. 209 * We currently return information regarding 2 sections - os_log and 210 * cstring. In the case that the os_log section doesn't exist, we just 211 * return an offset and length of 0 for that section. 212 *********************************************************************/ 213 typedef struct osLogDataHeader { 214 uint32_t version; 215 uint32_t sect_count; 216 struct { 217 uint32_t sect_offset; 218 uint32_t sect_size; 219 } sections[0]; 220 } osLogDataHeaderRef; 221 222 /********************************************************************* 223 * MkextEntryRef describes the contents of an OSData object 224 * referencing a file entry from an mkext so that we can uncompress 225 * (if necessary) and extract it on demand. 226 * 227 * It contains the mkextVersion in case we ever wind up supporting 228 * multiple mkext formats. Mkext format 1 is officially retired as of 229 * Snow Leopard. 230 *********************************************************************/ 231 typedef struct MkextEntryRef { 232 mkext_basic_header * mkext; // beginning of whole mkext file 233 void * fileinfo;// mkext2_file_entry or equiv; see mkext.h 234 } MkextEntryRef; 235 236 #if PRAGMA_MARK 237 #pragma mark Global and static Module Variables 238 #endif 239 /********************************************************************* 240 * Global & static variables, used to keep track of kexts. 241 *********************************************************************/ 242 243 static bool sPrelinkBoot = false; 244 static bool sSafeBoot = false; 245 static bool sKeepSymbols = false; 246 247 /********************************************************************* 248 * sKextLock is the principal lock for OSKext, and guards all static 249 * and global variables not owned by other locks (declared further 250 * below). It must be taken by any entry-point method or function, 251 * including internal functions called on scheduled threads. 252 * 253 * sKextLock and sKextInnerLock are recursive due to multiple functions 254 * that are called both externally and internally. The other locks are 255 * nonrecursive. 256 * 257 * Which locks are taken depends on what they protect, but if more than 258 * one must be taken, they must always be locked in this order 259 * (and unlocked in reverse order) to prevent deadlocks: 260 * 261 * 1. sKextLock 262 * 2. sKextInnerLock 263 * 3. sKextSummariesLock 264 * 4. sKextLoggingLock 265 */ 266 static IORecursiveLock * sKextLock = NULL; 267 268 static OSDictionary * sKextsByID = NULL; 269 static OSDictionary * sExcludeListByID = NULL; 270 static OSKextVersion sExcludeListVersion = 0; 271 static OSArray * sLoadedKexts = NULL; 272 static OSArray * sUnloadedPrelinkedKexts = NULL; 273 static OSArray * sLoadedDriverKitKexts = NULL; 274 275 // Requests to kextd waiting to be picked up. 276 static OSArray * sKernelRequests = NULL; 277 // Identifier of kext load requests in sKernelRequests 278 static OSSet * sPostedKextLoadIdentifiers = NULL; 279 static OSArray * sRequestCallbackRecords = NULL; 280 281 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel 282 static OSSet * sAllKextLoadIdentifiers = NULL; 283 static KXLDContext * sKxldContext = NULL; 284 static uint32_t sNextLoadTag = 0; 285 static uint32_t sNextRequestTag = 0; 286 287 static bool sUserLoadsActive = false; 288 static bool sKextdActive = false; 289 static bool sDeferredLoadSucceeded = false; 290 static bool sConsiderUnloadsExecuted = false; 291 292 #if NO_KEXTD 293 static bool sKernelRequestsEnabled = false; 294 #else 295 static bool sKernelRequestsEnabled = true; 296 #endif 297 static bool sLoadEnabled = true; 298 static bool sUnloadEnabled = true; 299 300 /********************************************************************* 301 * Stuff for the OSKext representing the kernel itself. 302 **********/ 303 static OSKext * sKernelKext = NULL; 304 305 /* Set up a fake kmod_info struct for the kernel. 306 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP() 307 * before OSKext is initialized; that call only needs the name 308 * and address to be set correctly. 309 * 310 * We don't do much else with the kerne's kmod_info; we never 311 * put it into the kmod list, never adjust the reference count, 312 * and never have kernel components reference it. 313 * For that matter, we don't do much with kmod_info structs 314 * at all anymore! We just keep them filled in for gdb and 315 * binary compability. 316 */ 317 kmod_info_t g_kernel_kmod_info = { 318 .next = NULL, 319 .info_version = KMOD_INFO_VERSION, 320 .id = 0, // loadTag: kernel is always 0 321 .name = kOSKextKernelIdentifier,// bundle identifier 322 .version = "0", // filled in in OSKext::initialize() 323 .reference_count = -1, // never adjusted; kernel never unloads 324 .reference_list = NULL, 325 .address = 0, 326 .size = 0, // filled in in OSKext::initialize() 327 .hdr_size = 0, 328 .start = NULL, 329 .stop = NULL 330 }; 331 332 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */ 333 334 kmod_info_t invalid_kmod_info = { 335 .next = NULL, 336 .info_version = KMOD_INFO_VERSION, 337 .id = UINT32_MAX, 338 .name = "invalid", 339 .version = "0", 340 .reference_count = -1, 341 .reference_list = NULL, 342 .address = 0, 343 .size = 0, 344 .hdr_size = 0, 345 .start = NULL, 346 .stop = NULL 347 }; 348 349 extern "C" { 350 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c, 351 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s, 352 // misc_protos.h, db_low_trace.c, kgmacros 353 // 'kmod' is a holdover from the old kmod system, we can't rename it. 354 kmod_info_t * kmod = NULL; 355 356 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE) 357 358 359 static char * loaded_kext_paniclist = NULL; 360 static uint32_t loaded_kext_paniclist_size = 0; 361 362 AbsoluteTime last_loaded_timestamp; 363 static char last_loaded_str_buf[2 * KMOD_MAX_NAME]; 364 static u_long last_loaded_strlen = 0; 365 static void * last_loaded_address = NULL; 366 static u_long last_loaded_size = 0; 367 368 AbsoluteTime last_unloaded_timestamp; 369 static char last_unloaded_str_buf[2 * KMOD_MAX_NAME]; 370 static u_long last_unloaded_strlen = 0; 371 static void * last_unloaded_address = NULL; 372 static u_long last_unloaded_size = 0; 373 374 // Statically linked kmods described by several mach-o sections: 375 // 376 // kPrelinkInfoSegment:kBuiltinInfoSection 377 // Array of pointers to kmod_info_t structs. 378 // 379 // kPrelinkInfoSegment:kBuiltinInfoSection 380 // Array of pointers to an embedded mach-o header. 381 // 382 // __DATA:kBuiltinInitSection, kBuiltinTermSection 383 // Structors for all kmods. Has to be filtered by proc address. 384 // 385 386 static uint32_t gBuiltinKmodsCount; 387 static kernel_section_t * gBuiltinKmodsSectionInfo; 388 static kernel_section_t * gBuiltinKmodsSectionStart; 389 390 static const OSSymbol * gIOSurfaceIdentifier; 391 vm_tag_t gIOSurfaceTag; 392 393 /********************************************************************* 394 * sKextInnerLock protects against cross-calls with IOService and 395 * IOCatalogue, and owns the variables declared immediately below. 396 * 397 * Note that sConsiderUnloadsExecuted above belongs to sKextLock! 398 * 399 * When both sKextLock and sKextInnerLock need to be taken, 400 * always lock sKextLock first and unlock it second. Never take both 401 * locks in an entry point to OSKext; if you need to do so, you must 402 * spawn an independent thread to avoid potential deadlocks for threads 403 * calling into OSKext. 404 **********/ 405 static IORecursiveLock * sKextInnerLock = NULL; 406 407 static bool sAutounloadEnabled = true; 408 static bool sConsiderUnloadsCalled = false; 409 static bool sConsiderUnloadsPending = false; 410 411 static unsigned int sConsiderUnloadDelay = 60; // seconds 412 static thread_call_t sUnloadCallout = NULL; 413 static thread_call_t sDestroyLinkContextThread = NULL; // one-shot, one-at-a-time thread 414 static bool sSystemSleep = false; // true when system going to sleep 415 static AbsoluteTime sLastWakeTime; // last time we woke up 416 417 /********************************************************************* 418 * Backtraces can be printed at various times so we need a tight lock 419 * on data used for that. sKextSummariesLock protects the variables 420 * declared immediately below. 421 * 422 * gLoadedKextSummaries is accessed by other modules, but only during 423 * a panic so the lock isn't needed then. 424 * 425 * gLoadedKextSummaries has the "used" attribute in order to ensure 426 * that it remains visible even when we are performing extremely 427 * aggressive optimizations, as it is needed to allow the debugger 428 * to automatically parse the list of loaded kexts. 429 **********/ 430 static IOLock * sKextSummariesLock = NULL; 431 extern "C" lck_spin_t vm_allocation_sites_lock; 432 static IOSimpleLock * sKextAccountsLock = &vm_allocation_sites_lock; 433 434 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated; 435 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL; 436 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0; 437 static size_t sLoadedKextSummariesAllocSize = 0; 438 439 static OSKextActiveAccount * sKextAccounts; 440 static uint32_t sKextAccountsCount; 441 }; 442 443 /********************************************************************* 444 * sKextLoggingLock protects the logging variables declared immediately below. 445 **********/ 446 static IOLock * sKextLoggingLock = NULL; 447 448 static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel | 449 kOSKextLogVerboseFlagsMask; 450 static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter; 451 static bool sBootArgLogFilterFound = false; 452 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter, 453 0, "kernel kext logging"); 454 455 static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter; 456 static OSArray * sUserSpaceLogSpecArray = NULL; 457 static OSArray * sUserSpaceLogMessageArray = NULL; 458 459 /********* 460 * End scope for sKextInnerLock-protected variables. 461 *********************************************************************/ 462 463 464 /********************************************************************* 465 * helper function used for collecting PGO data upon unload of a kext 466 */ 467 468 static int OSKextGrabPgoDataLocked(OSKext *kext, 469 bool metadata, 470 uuid_t instance_uuid, 471 uint64_t *pSize, 472 char *pBuffer, 473 uint64_t bufferSize); 474 475 /**********************************************************************/ 476 477 478 479 #if PRAGMA_MARK 480 #pragma mark OSData callbacks (need to move to OSData) 481 #endif 482 /********************************************************************* 483 * C functions used for callbacks. 484 *********************************************************************/ 485 extern "C" { 486 void 487 osdata_kmem_free(void * ptr, unsigned int length) 488 { 489 kmem_free(kernel_map, (vm_address_t)ptr, length); 490 return; 491 } 492 493 void 494 osdata_phys_free(void * ptr, unsigned int length) 495 { 496 ml_static_mfree((vm_offset_t)ptr, length); 497 return; 498 } 499 500 void 501 osdata_vm_deallocate(void * ptr, unsigned int length) 502 { 503 (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length); 504 return; 505 } 506 507 void 508 osdata_kext_free(void * ptr, unsigned int length) 509 { 510 (void)kext_free((vm_offset_t)ptr, length); 511 } 512 }; 513 514 #if PRAGMA_MARK 515 #pragma mark KXLD Allocation Callback 516 #endif 517 /********************************************************************* 518 * KXLD Allocation Callback 519 *********************************************************************/ 520 kxld_addr_t 521 kern_allocate( 522 u_long size, 523 KXLDAllocateFlags * flags, 524 void * user_data) 525 { 526 vm_address_t result = 0; // returned 527 kern_return_t mach_result = KERN_FAILURE; 528 bool success = false; 529 OSKext * theKext = (OSKext *)user_data; 530 u_long roundSize = round_page(size); 531 OSData * linkBuffer = NULL;// must release 532 533 mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE); 534 if (mach_result != KERN_SUCCESS) { 535 OSKextLog(theKext, 536 kOSKextLogErrorLevel | 537 kOSKextLogGeneralFlag, 538 "Can't allocate kernel memory to link %s.", 539 theKext->getIdentifierCString()); 540 goto finish; 541 } 542 543 /* Create an OSData wrapper for the allocated buffer. 544 */ 545 linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize); 546 if (!linkBuffer) { 547 OSKextLog(theKext, 548 kOSKextLogErrorLevel | 549 kOSKextLogGeneralFlag, 550 "Can't allocate linked executable wrapper for %s.", 551 theKext->getIdentifierCString()); 552 goto finish; 553 } 554 linkBuffer->setDeallocFunction(osdata_kext_free); 555 OSKextLog(theKext, 556 kOSKextLogProgressLevel | 557 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 558 "Allocated link buffer for kext %s at %p (%lu bytes).", 559 theKext->getIdentifierCString(), 560 (void *)result, (unsigned long)roundSize); 561 562 theKext->setLinkedExecutable(linkBuffer); 563 564 *flags = kKxldAllocateWritable; 565 success = true; 566 567 finish: 568 if (!success && result) { 569 kext_free(result, roundSize); 570 result = 0; 571 } 572 573 OSSafeReleaseNULL(linkBuffer); 574 575 return (kxld_addr_t)result; 576 } 577 578 /********************************************************************* 579 *********************************************************************/ 580 void 581 kxld_log_callback( 582 KXLDLogSubsystem subsystem, 583 KXLDLogLevel level, 584 const char * format, 585 va_list argList, 586 void * user_data) 587 { 588 OSKext *theKext = (OSKext *) user_data; 589 OSKextLogSpec logSpec = 0; 590 591 switch (subsystem) { 592 case kKxldLogLinking: 593 logSpec |= kOSKextLogLinkFlag; 594 break; 595 case kKxldLogPatching: 596 logSpec |= kOSKextLogPatchFlag; 597 break; 598 } 599 600 switch (level) { 601 case kKxldLogExplicit: 602 logSpec |= kOSKextLogExplicitLevel; 603 break; 604 case kKxldLogErr: 605 logSpec |= kOSKextLogErrorLevel; 606 break; 607 case kKxldLogWarn: 608 logSpec |= kOSKextLogWarningLevel; 609 break; 610 case kKxldLogBasic: 611 logSpec |= kOSKextLogProgressLevel; 612 break; 613 case kKxldLogDetail: 614 logSpec |= kOSKextLogDetailLevel; 615 break; 616 case kKxldLogDebug: 617 logSpec |= kOSKextLogDebugLevel; 618 break; 619 } 620 621 OSKextVLog(theKext, logSpec, format, argList); 622 } 623 624 #if PRAGMA_MARK 625 #pragma mark IOStatistics defines 626 #endif 627 628 #if IOKITSTATS 629 630 #define notifyKextLoadObservers(kext, kmod_info) \ 631 do { \ 632 IOStatistics::onKextLoad(kext, kmod_info); \ 633 } while (0) 634 635 #define notifyKextUnloadObservers(kext) \ 636 do { \ 637 IOStatistics::onKextUnload(kext); \ 638 } while (0) 639 640 #define notifyAddClassObservers(kext, addedClass, flags) \ 641 do { \ 642 IOStatistics::onClassAdded(kext, addedClass); \ 643 } while (0) 644 645 #define notifyRemoveClassObservers(kext, removedClass, flags) \ 646 do { \ 647 IOStatistics::onClassRemoved(kext, removedClass); \ 648 } while (0) 649 650 #else 651 652 #define notifyKextLoadObservers(kext, kmod_info) 653 #define notifyKextUnloadObservers(kext) 654 #define notifyAddClassObservers(kext, addedClass, flags) 655 #define notifyRemoveClassObservers(kext, removedClass, flags) 656 657 #endif /* IOKITSTATS */ 658 659 #if PRAGMA_MARK 660 #pragma mark Module Config (Startup & Shutdown) 661 #endif 662 /********************************************************************* 663 * Module Config (Class Definition & Class Methods) 664 *********************************************************************/ 665 #define super OSObject 666 OSDefineMetaClassAndStructors(OSKext, OSObject) 667 668 /********************************************************************* 669 *********************************************************************/ 670 /* static */ 671 void 672 OSKext::initialize(void) 673 { 674 OSData * kernelExecutable = NULL;// do not release 675 u_char * kernelStart = NULL;// do not free 676 size_t kernelLength = 0; 677 OSString * scratchString = NULL;// must release 678 IORegistryEntry * registryRoot = NULL;// do not release 679 OSNumber * kernelCPUType = NULL;// must release 680 OSNumber * kernelCPUSubtype = NULL;// must release 681 OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter; 682 bool setResult = false; 683 uint64_t * timestamp = NULL; 684 char bootArgBuffer[16];// for PE_parse_boot_argn w/strings 685 686 /* This must be the first thing allocated. Everything else grabs this lock. 687 */ 688 sKextLock = IORecursiveLockAlloc(); 689 sKextInnerLock = IORecursiveLockAlloc(); 690 sKextSummariesLock = IOLockAlloc(); 691 sKextLoggingLock = IOLockAlloc(); 692 assert(sKextLock); 693 assert(sKextInnerLock); 694 assert(sKextSummariesLock); 695 assert(sKextLoggingLock); 696 697 sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount); 698 sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 699 sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 700 sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10); 701 sKernelRequests = OSArray::withCapacity(0); 702 sPostedKextLoadIdentifiers = OSSet::withCapacity(0); 703 sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount); 704 sRequestCallbackRecords = OSArray::withCapacity(0); 705 assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests && 706 sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers && 707 sRequestCallbackRecords && sUnloadedPrelinkedKexts); 708 709 /* Read the log flag boot-args and set the log flags. 710 */ 711 if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) { 712 sBootArgLogFilterFound = true; 713 sKernelLogFilter = bootLogFilter; 714 // log this if any flags are set 715 OSKextLog(/* kext */ NULL, 716 kOSKextLogBasicLevel | 717 kOSKextLogFlagsMask, 718 "Kernel kext log filter 0x%x per kextlog boot arg.", 719 (unsigned)sKernelLogFilter); 720 } 721 722 sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer, 723 sizeof(bootArgBuffer)) ? true : false; 724 725 if (sSafeBoot) { 726 OSKextLog(/* kext */ NULL, 727 kOSKextLogWarningLevel | 728 kOSKextLogGeneralFlag, 729 "SAFE BOOT DETECTED - " 730 "only valid OSBundleRequired kexts will be loaded."); 731 } 732 733 PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols)); 734 #if CONFIG_DTRACE 735 if (dtrace_keep_kernel_symbols()) { 736 sKeepSymbols = true; 737 } 738 #endif /* CONFIG_DTRACE */ 739 #if KASAN_DYNAMIC_BLACKLIST 740 /* needed for function lookup */ 741 sKeepSymbols = true; 742 #endif 743 744 /* Set up an OSKext instance to represent the kernel itself. 745 */ 746 sKernelKext = new OSKext; 747 assert(sKernelKext); 748 749 kernelStart = (u_char *)&_mh_execute_header; 750 kernelLength = getlastaddr() - (vm_offset_t)kernelStart; 751 kernelExecutable = OSData::withBytesNoCopy( 752 kernelStart, kernelLength); 753 assert(kernelExecutable); 754 755 #if KASLR_KEXT_DEBUG 756 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %lu (0x%016lx) \n", 757 (unsigned long)kernelStart, 758 (unsigned long)getlastaddr(), 759 kernelLength, 760 (unsigned long)vm_kernel_slide, 761 (unsigned long)vm_kernel_slide); 762 #endif 763 764 sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0 765 sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier); 766 767 sKernelKext->version = OSKextParseVersionString(osrelease); 768 sKernelKext->compatibleVersion = sKernelKext->version; 769 sKernelKext->linkedExecutable = kernelExecutable; 770 sKernelKext->interfaceUUID = sKernelKext->copyUUID(); 771 772 sKernelKext->flags.hasAllDependencies = 1; 773 sKernelKext->flags.kernelComponent = 1; 774 sKernelKext->flags.prelinked = 0; 775 sKernelKext->flags.loaded = 1; 776 sKernelKext->flags.started = 1; 777 sKernelKext->flags.CPPInitialized = 0; 778 sKernelKext->flags.jettisonLinkeditSeg = 0; 779 780 sKernelKext->kmod_info = &g_kernel_kmod_info; 781 strlcpy(g_kernel_kmod_info.version, osrelease, 782 sizeof(g_kernel_kmod_info.version)); 783 g_kernel_kmod_info.size = kernelLength; 784 g_kernel_kmod_info.id = sKernelKext->loadTag; 785 786 /* Cons up an info dict, so we don't have to have special-case 787 * checking all over. 788 */ 789 sKernelKext->infoDict = OSDictionary::withCapacity(5); 790 assert(sKernelKext->infoDict); 791 setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey, 792 sKernelKext->bundleID); 793 assert(setResult); 794 setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey, 795 kOSBooleanTrue); 796 assert(setResult); 797 798 scratchString = OSString::withCStringNoCopy(osrelease); 799 assert(scratchString); 800 setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey, 801 scratchString); 802 assert(setResult); 803 OSSafeReleaseNULL(scratchString); 804 805 scratchString = OSString::withCStringNoCopy("mach_kernel"); 806 assert(scratchString); 807 setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey, 808 scratchString); 809 assert(setResult); 810 OSSafeReleaseNULL(scratchString); 811 812 /* Add the kernel kext to the bookkeeping dictionaries. Note that 813 * the kernel kext doesn't have a kmod_info struct. copyInfo() 814 * gathers info from other places anyhow. 815 */ 816 setResult = sKextsByID->setObject(sKernelKext->bundleID, sKernelKext); 817 assert(setResult); 818 setResult = sLoadedKexts->setObject(sKernelKext); 819 assert(setResult); 820 sKernelKext->release(); 821 822 registryRoot = IORegistryEntry::getRegistryRoot(); 823 kernelCPUType = OSNumber::withNumber( 824 (long long unsigned int)_mh_execute_header.cputype, 825 8 * sizeof(_mh_execute_header.cputype)); 826 kernelCPUSubtype = OSNumber::withNumber( 827 (long long unsigned int)_mh_execute_header.cpusubtype, 828 8 * sizeof(_mh_execute_header.cpusubtype)); 829 assert(registryRoot && kernelCPUSubtype && kernelCPUType); 830 831 registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType); 832 registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype); 833 834 OSSafeReleaseNULL(kernelCPUType); 835 OSSafeReleaseNULL(kernelCPUSubtype); 836 837 gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection); 838 if (gBuiltinKmodsSectionInfo) { 839 uint32_t count; 840 841 assert(gBuiltinKmodsSectionInfo->addr); 842 assert(gBuiltinKmodsSectionInfo->size); 843 gBuiltinKmodsCount = (gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *)); 844 845 gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection); 846 assert(gBuiltinKmodsSectionStart); 847 assert(gBuiltinKmodsSectionStart->addr); 848 assert(gBuiltinKmodsSectionStart->size); 849 count = (gBuiltinKmodsSectionStart->size / sizeof(uintptr_t)); 850 // one extra pointer for the end of last kmod 851 assert(count == (gBuiltinKmodsCount + 1)); 852 853 vm_kernel_builtinkmod_text = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0]; 854 vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1]; 855 } 856 gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface"); 857 858 timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp); 859 *timestamp = 0; 860 timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp); 861 *timestamp = 0; 862 timestamp = __OSAbsoluteTimePtr(&sLastWakeTime); 863 *timestamp = 0; 864 865 OSKextLog(/* kext */ NULL, 866 kOSKextLogProgressLevel | 867 kOSKextLogGeneralFlag, 868 "Kext system initialized."); 869 870 notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info); 871 872 return; 873 } 874 875 /********************************************************************* 876 * This is expected to be called exactly once, from exactly one thread 877 * context, during kernel bootstrap. 878 *********************************************************************/ 879 /* static */ 880 OSReturn 881 OSKext::removeKextBootstrap(void) 882 { 883 OSReturn result = kOSReturnError; 884 885 const char * dt_kernel_header_name = "Kernel-__HEADER"; 886 const char * dt_kernel_symtab_name = "Kernel-__SYMTAB"; 887 kernel_mach_header_t * dt_mach_header = NULL; 888 int dt_mach_header_size = 0; 889 struct symtab_command * dt_symtab = NULL; 890 int dt_symtab_size = 0; 891 int dt_result = 0; 892 893 kernel_segment_command_t * seg_to_remove = NULL; 894 895 #if __arm__ || __arm64__ 896 const char * dt_segment_name = NULL; 897 void * segment_paddress = NULL; 898 int segment_size = 0; 899 #endif 900 901 OSKextLog(/* kext */ NULL, 902 kOSKextLogProgressLevel | 903 kOSKextLogGeneralFlag, 904 "Jettisoning kext bootstrap segments."); 905 906 /***** 907 * Dispose of unnecessary stuff that the booter didn't need to load. 908 */ 909 dt_result = IODTGetLoaderInfo(dt_kernel_header_name, 910 (void **)&dt_mach_header, &dt_mach_header_size); 911 if (dt_result == 0 && dt_mach_header) { 912 IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header, 913 round_page_32(dt_mach_header_size)); 914 } 915 dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name, 916 (void **)&dt_symtab, &dt_symtab_size); 917 if (dt_result == 0 && dt_symtab) { 918 IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab, 919 round_page_32(dt_symtab_size)); 920 } 921 922 /***** 923 * KLD bootstrap segment. 924 */ 925 // xxx - should rename KLD segment 926 seg_to_remove = getsegbyname("__KLD"); 927 if (seg_to_remove) { 928 OSRuntimeUnloadCPPForSegment(seg_to_remove); 929 } 930 931 #if __arm__ || __arm64__ 932 /* Free the memory that was set up by bootx. 933 */ 934 dt_segment_name = "Kernel-__KLD"; 935 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) { 936 /* We cannot free this with KTRR enabled, as we cannot 937 * update the permissions on the KLD range this late 938 * in the boot process. 939 */ 940 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 941 (int)segment_size); 942 } 943 #elif __i386__ || __x86_64__ 944 /* On x86, use the mapping data from the segment load command to 945 * unload KLD directly. 946 * This may invalidate any assumptions about "avail_start" 947 * defining the lower bound for valid physical addresses. 948 */ 949 if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) { 950 // 04/18/11 - gab: <rdar://problem/9236163> 951 // overwrite memory occupied by KLD segment with random data before 952 // releasing it. 953 read_frandom((void *) seg_to_remove->vmaddr, seg_to_remove->vmsize); 954 ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize); 955 } 956 #else 957 #error arch 958 #endif 959 960 seg_to_remove = NULL; 961 962 /***** 963 * Prelinked kernel's symtab (if there is one). 964 */ 965 kernel_section_t * sect; 966 sect = getsectbyname("__PRELINK", "__symtab"); 967 if (sect && sect->addr && sect->size) { 968 ml_static_mfree(sect->addr, sect->size); 969 } 970 971 seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT"); 972 973 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it 974 * pageable, unless keepsyms is set. To do that, we have to copy it from 975 * its booter-allocated memory, free the booter memory, reallocate proper 976 * managed memory, then copy the segment back in. 977 */ 978 #if CONFIG_KXLD 979 #if (__arm__ || __arm64__) 980 #error CONFIG_KXLD not expected for this arch 981 #endif 982 if (!sKeepSymbols) { 983 kern_return_t mem_result; 984 void *seg_copy = NULL; 985 void *seg_data = NULL; 986 vm_map_offset_t seg_offset = 0; 987 vm_map_offset_t seg_copy_offset = 0; 988 vm_map_size_t seg_length = 0; 989 990 seg_data = (void *) seg_to_remove->vmaddr; 991 seg_offset = (vm_map_offset_t) seg_to_remove->vmaddr; 992 seg_length = (vm_map_size_t) seg_to_remove->vmsize; 993 994 /* Allocate space for the LINKEDIT copy. 995 */ 996 mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy, 997 seg_length, VM_KERN_MEMORY_KEXT); 998 if (mem_result != KERN_SUCCESS) { 999 OSKextLog(/* kext */ NULL, 1000 kOSKextLogErrorLevel | 1001 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1002 "Can't copy __LINKEDIT segment for VM reassign."); 1003 return result; 1004 } 1005 seg_copy_offset = (vm_map_offset_t) seg_copy; 1006 1007 /* Copy it out. 1008 */ 1009 memcpy(seg_copy, seg_data, seg_length); 1010 1011 /* Dump the booter memory. 1012 */ 1013 ml_static_mfree(seg_offset, seg_length); 1014 1015 /* Set up the VM region. 1016 */ 1017 mem_result = vm_map_enter_mem_object( 1018 kernel_map, 1019 &seg_offset, 1020 seg_length, /* mask */ 0, 1021 VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, 1022 VM_MAP_KERNEL_FLAGS_NONE, 1023 VM_KERN_MEMORY_NONE, 1024 (ipc_port_t)NULL, 1025 (vm_object_offset_t) 0, 1026 /* copy */ FALSE, 1027 /* cur_protection */ VM_PROT_READ | VM_PROT_WRITE, 1028 /* max_protection */ VM_PROT_ALL, 1029 /* inheritance */ VM_INHERIT_DEFAULT); 1030 if ((mem_result != KERN_SUCCESS) || 1031 (seg_offset != (vm_map_offset_t) seg_data)) { 1032 OSKextLog(/* kext */ NULL, 1033 kOSKextLogErrorLevel | 1034 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1035 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).", 1036 seg_data, seg_length, mem_result); 1037 return result; 1038 } 1039 1040 /* And copy it back. 1041 */ 1042 memcpy(seg_data, seg_copy, seg_length); 1043 1044 /* Free the copy. 1045 */ 1046 kmem_free(kernel_map, seg_copy_offset, seg_length); 1047 } 1048 #else /* we are not CONFIG_KXLD */ 1049 #if !(__arm__ || __arm64__) 1050 #error CONFIG_KXLD is expected for this arch 1051 #endif 1052 1053 /***** 1054 * Dump the LINKEDIT segment, unless keepsyms is set. 1055 */ 1056 if (!sKeepSymbols) { 1057 dt_segment_name = "Kernel-__LINKEDIT"; 1058 if (0 == IODTGetLoaderInfo(dt_segment_name, 1059 &segment_paddress, &segment_size)) { 1060 #ifdef SECURE_KERNEL 1061 vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress); 1062 bzero((void*)vmaddr, segment_size); 1063 #endif 1064 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1065 (int)segment_size); 1066 } 1067 } else { 1068 OSKextLog(/* kext */ NULL, 1069 kOSKextLogBasicLevel | 1070 kOSKextLogGeneralFlag, 1071 "keepsyms boot arg specified; keeping linkedit segment for symbols."); 1072 } 1073 #endif /* CONFIG_KXLD */ 1074 1075 seg_to_remove = NULL; 1076 1077 result = kOSReturnSuccess; 1078 1079 return result; 1080 } 1081 1082 /********************************************************************* 1083 *********************************************************************/ 1084 void 1085 OSKext::flushNonloadedKexts( 1086 Boolean flushPrelinkedKexts) 1087 { 1088 OSSet * keepKexts = NULL;// must release 1089 1090 IORecursiveLockLock(sKextLock); 1091 1092 OSKextLog(/* kext */ NULL, 1093 kOSKextLogProgressLevel | 1094 kOSKextLogKextBookkeepingFlag, 1095 "Flushing nonloaded kexts and other unused data."); 1096 1097 OSKext::considerDestroyingLinkContext(); 1098 1099 /* If we aren't flushing unused prelinked kexts, we have to put them 1100 * aside while we flush everything else so make a container for them. 1101 */ 1102 keepKexts = OSSet::withCapacity(16); 1103 if (!keepKexts) { 1104 goto finish; 1105 } 1106 1107 /* Set aside prelinked kexts (in-use or not) and break 1108 * any lingering inter-kext references for nonloaded kexts 1109 * so they have min. retain counts. 1110 */ 1111 sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) { 1112 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1113 if (!thisKext) { 1114 return false; 1115 } 1116 if (!flushPrelinkedKexts && thisKext->isPrelinked()) { 1117 keepKexts->setObject(thisKext); 1118 } 1119 if (!thisKext->declaresExecutable()) { 1120 /* 1121 * Don't unload codeless kexts, because they never appear in the loadedKexts array. 1122 * Requesting one from kextd will load it and then immediately remove it by calling 1123 * flushNonloadedKexts(). 1124 * And adding one to loadedKexts breaks code assuming they have kmod_info etc. 1125 */ 1126 keepKexts->setObject(thisKext); 1127 } 1128 1129 thisKext->flushDependencies(/* forceIfLoaded */ false); 1130 return false; 1131 }); 1132 1133 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly. 1134 */ 1135 sKextsByID->flushCollection(); 1136 1137 /* Now put the loaded kexts back into the ID dictionary. 1138 */ 1139 sLoadedKexts->iterateObjects(^bool (OSObject * obj) { 1140 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1141 if (!thisKext) { 1142 return false; 1143 } 1144 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1145 return false; 1146 }); 1147 1148 /* Finally, put back the kept kexts if we saved any. 1149 */ 1150 keepKexts->iterateObjects(^bool (OSObject * obj) { 1151 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1152 if (!thisKext) { 1153 return false; 1154 } 1155 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1156 return false; 1157 }); 1158 1159 finish: 1160 IORecursiveLockUnlock(sKextLock); 1161 1162 OSSafeReleaseNULL(keepKexts); 1163 1164 return; 1165 } 1166 1167 /********************************************************************* 1168 *********************************************************************/ 1169 /* static */ 1170 void 1171 OSKext::setKextdActive(Boolean active) 1172 { 1173 IORecursiveLockLock(sKextLock); 1174 sKextdActive = active; 1175 if (sKernelRequests->getCount()) { 1176 OSKext::pingKextd(); 1177 } 1178 IORecursiveLockUnlock(sKextLock); 1179 1180 return; 1181 } 1182 1183 /********************************************************************* 1184 * OSKextLib.cpp might need access to this someday but for now it's 1185 * private. 1186 *********************************************************************/ 1187 extern "C" { 1188 extern void ipc_port_release_send(ipc_port_t); 1189 }; 1190 1191 /* static */ 1192 OSReturn 1193 OSKext::pingKextd(void) 1194 { 1195 OSReturn result = kOSReturnError; 1196 #if !NO_KEXTD 1197 mach_port_t kextd_port = IPC_PORT_NULL; 1198 1199 if (!sKextdActive) { 1200 result = kOSKextReturnDisabled; // basically unavailable 1201 goto finish; 1202 } 1203 1204 result = host_get_kextd_port(host_priv_self(), &kextd_port); 1205 if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) { 1206 OSKextLog(/* kext */ NULL, 1207 kOSKextLogErrorLevel | 1208 kOSKextLogIPCFlag, 1209 "Can't get kextd port."); 1210 goto finish; 1211 } 1212 1213 result = kextd_ping(kextd_port); 1214 if (result != KERN_SUCCESS) { 1215 OSKextLog(/* kext */ NULL, 1216 kOSKextLogErrorLevel | 1217 kOSKextLogIPCFlag, 1218 "kextd ping failed (0x%x).", (int)result); 1219 goto finish; 1220 } 1221 1222 finish: 1223 if (IPC_PORT_VALID(kextd_port)) { 1224 ipc_port_release_send(kextd_port); 1225 } 1226 #endif 1227 1228 return result; 1229 } 1230 1231 /********************************************************************* 1232 *********************************************************************/ 1233 /* static */ 1234 void 1235 OSKext::setDeferredLoadSucceeded(Boolean succeeded) 1236 { 1237 IORecursiveLockLock(sKextLock); 1238 sDeferredLoadSucceeded = succeeded; 1239 IORecursiveLockUnlock(sKextLock); 1240 1241 return; 1242 } 1243 1244 /********************************************************************* 1245 * Called from IOSystemShutdownNotification. 1246 *********************************************************************/ 1247 /* static */ 1248 void 1249 OSKext::willShutdown(void) 1250 { 1251 #if !NO_KEXTD 1252 OSReturn checkResult = kOSReturnError; 1253 #endif 1254 OSDictionary * exitRequest = NULL; // must release 1255 1256 IORecursiveLockLock(sKextLock); 1257 1258 OSKext::setLoadEnabled(false); 1259 OSKext::setUnloadEnabled(false); 1260 OSKext::setAutounloadsEnabled(false); 1261 OSKext::setKernelRequestsEnabled(false); 1262 1263 #if !NO_KEXTD 1264 OSKextLog(/* kext */ NULL, 1265 kOSKextLogProgressLevel | 1266 kOSKextLogGeneralFlag, 1267 "System shutdown; requesting immediate kextd exit."); 1268 1269 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit, 1270 &exitRequest); 1271 if (checkResult != kOSReturnSuccess) { 1272 goto finish; 1273 } 1274 if (!sKernelRequests->setObject(exitRequest)) { 1275 goto finish; 1276 } 1277 1278 OSKext::pingKextd(); 1279 1280 finish: 1281 #endif 1282 1283 IORecursiveLockUnlock(sKextLock); 1284 1285 OSSafeReleaseNULL(exitRequest); 1286 return; 1287 } 1288 1289 /********************************************************************* 1290 *********************************************************************/ 1291 /* static */ 1292 bool 1293 OSKext::getLoadEnabled(void) 1294 { 1295 bool result; 1296 1297 IORecursiveLockLock(sKextLock); 1298 result = sLoadEnabled; 1299 IORecursiveLockUnlock(sKextLock); 1300 return result; 1301 } 1302 1303 /********************************************************************* 1304 *********************************************************************/ 1305 /* static */ 1306 bool 1307 OSKext::setLoadEnabled(bool flag) 1308 { 1309 bool result; 1310 1311 IORecursiveLockLock(sKextLock); 1312 result = sLoadEnabled; 1313 sLoadEnabled = (flag ? true : false); 1314 1315 if (sLoadEnabled != result) { 1316 OSKextLog(/* kext */ NULL, 1317 kOSKextLogBasicLevel | 1318 kOSKextLogLoadFlag, 1319 "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis"); 1320 } 1321 1322 IORecursiveLockUnlock(sKextLock); 1323 1324 return result; 1325 } 1326 1327 /********************************************************************* 1328 *********************************************************************/ 1329 /* static */ 1330 bool 1331 OSKext::getUnloadEnabled(void) 1332 { 1333 bool result; 1334 1335 IORecursiveLockLock(sKextLock); 1336 result = sUnloadEnabled; 1337 IORecursiveLockUnlock(sKextLock); 1338 return result; 1339 } 1340 1341 /********************************************************************* 1342 *********************************************************************/ 1343 /* static */ 1344 bool 1345 OSKext::setUnloadEnabled(bool flag) 1346 { 1347 bool result; 1348 1349 IORecursiveLockLock(sKextLock); 1350 result = sUnloadEnabled; 1351 sUnloadEnabled = (flag ? true : false); 1352 IORecursiveLockUnlock(sKextLock); 1353 1354 if (sUnloadEnabled != result) { 1355 OSKextLog(/* kext */ NULL, 1356 kOSKextLogBasicLevel | 1357 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1358 "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis"); 1359 } 1360 1361 return result; 1362 } 1363 1364 /********************************************************************* 1365 * Do not call any function that takes sKextLock here! 1366 *********************************************************************/ 1367 /* static */ 1368 bool 1369 OSKext::getAutounloadEnabled(void) 1370 { 1371 bool result; 1372 1373 IORecursiveLockLock(sKextInnerLock); 1374 result = sAutounloadEnabled ? true : false; 1375 IORecursiveLockUnlock(sKextInnerLock); 1376 return result; 1377 } 1378 1379 /********************************************************************* 1380 * Do not call any function that takes sKextLock here! 1381 *********************************************************************/ 1382 /* static */ 1383 bool 1384 OSKext::setAutounloadsEnabled(bool flag) 1385 { 1386 bool result; 1387 1388 IORecursiveLockLock(sKextInnerLock); 1389 1390 result = sAutounloadEnabled; 1391 sAutounloadEnabled = (flag ? true : false); 1392 if (!sAutounloadEnabled && sUnloadCallout) { 1393 thread_call_cancel(sUnloadCallout); 1394 } 1395 1396 if (sAutounloadEnabled != result) { 1397 OSKextLog(/* kext */ NULL, 1398 kOSKextLogBasicLevel | 1399 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1400 "Kext autounloading now %sabled.", 1401 sAutounloadEnabled ? "en" : "dis"); 1402 } 1403 1404 IORecursiveLockUnlock(sKextInnerLock); 1405 1406 return result; 1407 } 1408 1409 /********************************************************************* 1410 *********************************************************************/ 1411 /* instance method operating on OSKext field */ 1412 bool 1413 OSKext::setAutounloadEnabled(bool flag) 1414 { 1415 bool result = flags.autounloadEnabled ? true : false; 1416 flags.autounloadEnabled = flag ? 1 : 0; 1417 1418 if (result != (flag ? true : false)) { 1419 OSKextLog(this, 1420 kOSKextLogProgressLevel | 1421 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 1422 "Autounloading for kext %s now %sabled.", 1423 getIdentifierCString(), 1424 flags.autounloadEnabled ? "en" : "dis"); 1425 } 1426 return result; 1427 } 1428 1429 /********************************************************************* 1430 *********************************************************************/ 1431 /* static */ 1432 bool 1433 OSKext::setKernelRequestsEnabled(bool flag) 1434 { 1435 bool result; 1436 1437 IORecursiveLockLock(sKextLock); 1438 result = sKernelRequestsEnabled; 1439 sKernelRequestsEnabled = flag ? true : false; 1440 1441 if (sKernelRequestsEnabled != result) { 1442 OSKextLog(/* kext */ NULL, 1443 kOSKextLogBasicLevel | 1444 kOSKextLogGeneralFlag, 1445 "Kernel requests now %sabled.", 1446 sKernelRequestsEnabled ? "en" : "dis"); 1447 } 1448 IORecursiveLockUnlock(sKextLock); 1449 return result; 1450 } 1451 1452 /********************************************************************* 1453 *********************************************************************/ 1454 /* static */ 1455 bool 1456 OSKext::getKernelRequestsEnabled(void) 1457 { 1458 bool result; 1459 1460 IORecursiveLockLock(sKextLock); 1461 result = sKernelRequestsEnabled; 1462 IORecursiveLockUnlock(sKextLock); 1463 return result; 1464 } 1465 1466 #if PRAGMA_MARK 1467 #pragma mark Kext Life Cycle 1468 #endif 1469 /********************************************************************* 1470 *********************************************************************/ 1471 OSKext * 1472 OSKext::withPrelinkedInfoDict( 1473 OSDictionary * anInfoDict, 1474 bool doCoalesedSlides) 1475 { 1476 OSKext * newKext = new OSKext; 1477 1478 if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalesedSlides)) { 1479 newKext->release(); 1480 return NULL; 1481 } 1482 1483 return newKext; 1484 } 1485 1486 /********************************************************************* 1487 *********************************************************************/ 1488 bool 1489 OSKext::initWithPrelinkedInfoDict( 1490 OSDictionary * anInfoDict, 1491 bool doCoalesedSlides) 1492 { 1493 bool result = false; 1494 OSString * kextPath = NULL;// do not release 1495 OSNumber * addressNum = NULL;// reused; do not release 1496 OSNumber * lengthNum = NULL;// reused; do not release 1497 void * data = NULL;// do not free 1498 void * srcData = NULL;// do not free 1499 OSData * prelinkedExecutable = NULL;// must release 1500 uint32_t length = 0; // reused 1501 1502 if (!super::init()) { 1503 goto finish; 1504 } 1505 1506 /* Get the path. Don't look for an arch-specific path property. 1507 */ 1508 kextPath = OSDynamicCast(OSString, 1509 anInfoDict->getObject(kPrelinkBundlePathKey)); 1510 1511 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 1512 goto finish; 1513 } 1514 #if KASLR_KEXT_DEBUG 1515 IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides, getIdentifierCString()); 1516 #endif 1517 1518 /* Also get the executable's bundle-relative path if present. 1519 * Don't look for an arch-specific path property. 1520 */ 1521 executableRelPath = OSDynamicCast(OSString, 1522 anInfoDict->getObject(kPrelinkExecutableRelativePathKey)); 1523 if (executableRelPath) { 1524 executableRelPath->retain(); 1525 } 1526 1527 userExecutableRelPath = OSDynamicCast(OSString, 1528 anInfoDict->getObject("CFBundleUEXTExecutable")); 1529 if (userExecutableRelPath) { 1530 userExecutableRelPath->retain(); 1531 } 1532 1533 /* Don't need the paths to be in the info dictionary any more. 1534 */ 1535 anInfoDict->removeObject(kPrelinkBundlePathKey); 1536 anInfoDict->removeObject(kPrelinkExecutableRelativePathKey); 1537 1538 /* Create an OSData wrapper around the linked executable. 1539 */ 1540 addressNum = OSDynamicCast(OSNumber, 1541 anInfoDict->getObject(kPrelinkExecutableLoadKey)); 1542 if (addressNum) { 1543 lengthNum = OSDynamicCast(OSNumber, 1544 anInfoDict->getObject(kPrelinkExecutableSizeKey)); 1545 if (!lengthNum) { 1546 OSKextLog(this, 1547 kOSKextLogErrorLevel | 1548 kOSKextLogArchiveFlag, 1549 "Kext %s can't find prelinked kext executable size.", 1550 getIdentifierCString()); 1551 goto finish; 1552 } 1553 1554 data = (void *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue())); 1555 length = (uint32_t) (lengthNum->unsigned32BitValue()); 1556 1557 #if KASLR_KEXT_DEBUG 1558 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n", 1559 (unsigned long)ml_static_unslide((vm_offset_t)data), 1560 (unsigned long)data, 1561 length); 1562 #endif 1563 1564 anInfoDict->removeObject(kPrelinkExecutableLoadKey); 1565 anInfoDict->removeObject(kPrelinkExecutableSizeKey); 1566 1567 /* If the kext's load address differs from its source address, allocate 1568 * space in the kext map at the load address and copy the kext over. 1569 */ 1570 addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey)); 1571 if (addressNum) { 1572 srcData = (void *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue())); 1573 1574 #if KASLR_KEXT_DEBUG 1575 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n", 1576 (unsigned long)ml_static_unslide((vm_offset_t)srcData), 1577 (unsigned long)srcData); 1578 #endif 1579 1580 if (data != srcData) { 1581 #if __LP64__ 1582 kern_return_t alloc_result; 1583 1584 alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE); 1585 if (alloc_result != KERN_SUCCESS) { 1586 OSKextLog(this, 1587 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 1588 "Failed to allocate space for prelinked kext %s.", 1589 getIdentifierCString()); 1590 goto finish; 1591 } 1592 memcpy(data, srcData, length); 1593 #else 1594 OSKextLog(this, 1595 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 1596 "Error: prelinked kext %s - source and load addresses " 1597 "differ on ILP32 architecture.", 1598 getIdentifierCString()); 1599 goto finish; 1600 #endif /* __LP64__ */ 1601 } 1602 1603 anInfoDict->removeObject(kPrelinkExecutableSourceKey); 1604 } 1605 1606 prelinkedExecutable = OSData::withBytesNoCopy(data, length); 1607 if (!prelinkedExecutable) { 1608 OSKextLog(this, 1609 kOSKextLogErrorLevel | 1610 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1611 "Kext %s failed to create executable wrapper.", 1612 getIdentifierCString()); 1613 goto finish; 1614 } 1615 1616 #if VM_MAPPED_KEXTS 1617 prelinkedExecutable->setDeallocFunction(osdata_kext_free); 1618 #else 1619 prelinkedExecutable->setDeallocFunction(osdata_phys_free); 1620 #endif 1621 setLinkedExecutable(prelinkedExecutable); 1622 addressNum = OSDynamicCast(OSNumber, 1623 anInfoDict->getObject(kPrelinkKmodInfoKey)); 1624 if (!addressNum) { 1625 OSKextLog(this, 1626 kOSKextLogErrorLevel | 1627 kOSKextLogArchiveFlag, 1628 "Kext %s can't find prelinked kext kmod_info address.", 1629 getIdentifierCString()); 1630 goto finish; 1631 } 1632 1633 if (addressNum->unsigned64BitValue() != 0) { 1634 kmod_info = (kmod_info_t *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue())); 1635 kmod_info->address = ml_static_slide(kmod_info->address); 1636 #if KASLR_KEXT_DEBUG 1637 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n", 1638 (unsigned long)ml_static_unslide((vm_offset_t)kmod_info), 1639 (unsigned long)kmod_info); 1640 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n", 1641 (unsigned long)ml_static_unslide(kmod_info->address), 1642 (unsigned long)kmod_info->address); 1643 #endif 1644 } 1645 1646 anInfoDict->removeObject(kPrelinkKmodInfoKey); 1647 } 1648 1649 if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) { 1650 uintptr_t builtinTextStart; 1651 uintptr_t builtinTextEnd; 1652 1653 flags.builtin = true; 1654 builtinKmodIdx = addressNum->unsigned32BitValue(); 1655 assert(builtinKmodIdx < gBuiltinKmodsCount); 1656 1657 builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx]; 1658 builtinTextEnd = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1]; 1659 1660 kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx]; 1661 kmod_info->address = builtinTextStart; 1662 kmod_info->size = builtinTextEnd - builtinTextStart; 1663 } 1664 1665 /* If the plist has a UUID for an interface, save that off. 1666 */ 1667 if (isInterface()) { 1668 interfaceUUID = OSDynamicCast(OSData, 1669 anInfoDict->getObject(kPrelinkInterfaceUUIDKey)); 1670 if (interfaceUUID) { 1671 interfaceUUID->retain(); 1672 anInfoDict->removeObject(kPrelinkInterfaceUUIDKey); 1673 } 1674 } 1675 1676 result = slidePrelinkedExecutable(doCoalesedSlides); 1677 if (result != kOSReturnSuccess) { 1678 goto finish; 1679 } 1680 1681 if (doCoalesedSlides == false) { 1682 /* set VM protections now, wire later at kext load */ 1683 result = setVMAttributes(true, false); 1684 if (result != KERN_SUCCESS) { 1685 goto finish; 1686 } 1687 } 1688 1689 flags.prelinked = true; 1690 1691 /* If we created a kext from prelink info, 1692 * we must be booting from a prelinked kernel. 1693 */ 1694 sPrelinkBoot = true; 1695 1696 result = registerIdentifier(); 1697 1698 finish: 1699 OSSafeReleaseNULL(prelinkedExecutable); 1700 1701 return result; 1702 } 1703 1704 /********************************************************************* 1705 *********************************************************************/ 1706 /* static */ 1707 void 1708 OSKext::setAllVMAttributes(void) 1709 { 1710 OSCollectionIterator * kextIterator = NULL;// must release 1711 const OSSymbol * thisID = NULL;// do not release 1712 1713 IORecursiveLockLock(sKextLock); 1714 1715 kextIterator = OSCollectionIterator::withCollection(sKextsByID); 1716 if (!kextIterator) { 1717 goto finish; 1718 } 1719 1720 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 1721 OSKext * thisKext;// do not release 1722 1723 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 1724 if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) { 1725 continue; 1726 } 1727 1728 /* set VM protections now, wire later at kext load */ 1729 thisKext->setVMAttributes(true, false); 1730 } 1731 1732 finish: 1733 IORecursiveLockUnlock(sKextLock); 1734 OSSafeReleaseNULL(kextIterator); 1735 1736 return; 1737 } 1738 1739 /********************************************************************* 1740 *********************************************************************/ 1741 OSKext * 1742 OSKext::withBooterData( 1743 OSString * deviceTreeName, 1744 OSData * booterData) 1745 { 1746 OSKext * newKext = new OSKext; 1747 1748 if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) { 1749 newKext->release(); 1750 return NULL; 1751 } 1752 1753 return newKext; 1754 } 1755 1756 /********************************************************************* 1757 *********************************************************************/ 1758 typedef struct _BooterKextFileInfo { 1759 uint32_t infoDictPhysAddr; 1760 uint32_t infoDictLength; 1761 uint32_t executablePhysAddr; 1762 uint32_t executableLength; 1763 uint32_t bundlePathPhysAddr; 1764 uint32_t bundlePathLength; 1765 } _BooterKextFileInfo; 1766 1767 bool 1768 OSKext::initWithBooterData( 1769 OSString * deviceTreeName, 1770 OSData * booterData) 1771 { 1772 bool result = false; 1773 _BooterKextFileInfo * kextFileInfo = NULL;// do not free 1774 char * infoDictAddr = NULL;// do not free 1775 void * executableAddr = NULL;// do not free 1776 char * bundlePathAddr = NULL;// do not free 1777 1778 OSObject * parsedXML = NULL;// must release 1779 OSDictionary * theInfoDict = NULL;// do not release 1780 OSString * kextPath = NULL;// must release 1781 OSString * errorString = NULL;// must release 1782 OSData * executable = NULL;// must release 1783 1784 if (!super::init()) { 1785 goto finish; 1786 } 1787 1788 kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy(); 1789 if (!kextFileInfo) { 1790 OSKextLog(this, 1791 kOSKextLogErrorLevel | 1792 kOSKextLogGeneralFlag, 1793 "No booter-provided data for kext device tree entry %s.", 1794 deviceTreeName->getCStringNoCopy()); 1795 goto finish; 1796 } 1797 1798 /* The info plist must exist or we can't read the kext. 1799 */ 1800 if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) { 1801 OSKextLog(this, 1802 kOSKextLogErrorLevel | 1803 kOSKextLogGeneralFlag, 1804 "No kext info dictionary for booter device tree entry %s.", 1805 deviceTreeName->getCStringNoCopy()); 1806 goto finish; 1807 } 1808 1809 infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 1810 if (!infoDictAddr) { 1811 OSKextLog(this, 1812 kOSKextLogErrorLevel | 1813 kOSKextLogGeneralFlag, 1814 "Can't translate physical address 0x%x of kext info dictionary " 1815 "for device tree entry %s.", 1816 (int)kextFileInfo->infoDictPhysAddr, 1817 deviceTreeName->getCStringNoCopy()); 1818 goto finish; 1819 } 1820 1821 parsedXML = OSUnserializeXML(infoDictAddr, &errorString); 1822 if (parsedXML) { 1823 theInfoDict = OSDynamicCast(OSDictionary, parsedXML); 1824 } 1825 if (!theInfoDict) { 1826 const char * errorCString = "(unknown error)"; 1827 1828 if (errorString && errorString->getCStringNoCopy()) { 1829 errorCString = errorString->getCStringNoCopy(); 1830 } else if (parsedXML) { 1831 errorCString = "not a dictionary"; 1832 } 1833 OSKextLog(this, 1834 kOSKextLogErrorLevel | 1835 kOSKextLogGeneralFlag, 1836 "Error unserializing info dictionary for device tree entry %s: %s.", 1837 deviceTreeName->getCStringNoCopy(), errorCString); 1838 goto finish; 1839 } 1840 1841 /* A bundle path is not mandatory. 1842 */ 1843 if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) { 1844 bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr); 1845 if (!bundlePathAddr) { 1846 OSKextLog(this, 1847 kOSKextLogErrorLevel | 1848 kOSKextLogGeneralFlag, 1849 "Can't translate physical address 0x%x of kext bundle path " 1850 "for device tree entry %s.", 1851 (int)kextFileInfo->bundlePathPhysAddr, 1852 deviceTreeName->getCStringNoCopy()); 1853 goto finish; 1854 } 1855 bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0'; // just in case! 1856 1857 kextPath = OSString::withCString(bundlePathAddr); 1858 if (!kextPath) { 1859 OSKextLog(this, 1860 kOSKextLogErrorLevel | 1861 kOSKextLogGeneralFlag, 1862 "Failed to create wrapper for device tree entry %s kext path %s.", 1863 deviceTreeName->getCStringNoCopy(), bundlePathAddr); 1864 goto finish; 1865 } 1866 } 1867 1868 if (!setInfoDictionaryAndPath(theInfoDict, kextPath)) { 1869 goto finish; 1870 } 1871 1872 /* An executable is not mandatory. 1873 */ 1874 if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) { 1875 executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr); 1876 if (!executableAddr) { 1877 OSKextLog(this, 1878 kOSKextLogErrorLevel | 1879 kOSKextLogGeneralFlag, 1880 "Can't translate physical address 0x%x of kext executable " 1881 "for device tree entry %s.", 1882 (int)kextFileInfo->executablePhysAddr, 1883 deviceTreeName->getCStringNoCopy()); 1884 goto finish; 1885 } 1886 1887 executable = OSData::withBytesNoCopy(executableAddr, 1888 kextFileInfo->executableLength); 1889 if (!executable) { 1890 OSKextLog(this, 1891 kOSKextLogErrorLevel | 1892 kOSKextLogGeneralFlag, 1893 "Failed to create executable wrapper for device tree entry %s.", 1894 deviceTreeName->getCStringNoCopy()); 1895 goto finish; 1896 } 1897 1898 /* A kext with an executable needs to retain the whole booterData 1899 * object to keep the executable in memory. 1900 */ 1901 if (!setExecutable(executable, booterData)) { 1902 OSKextLog(this, 1903 kOSKextLogErrorLevel | 1904 kOSKextLogGeneralFlag, 1905 "Failed to set kext executable for device tree entry %s.", 1906 deviceTreeName->getCStringNoCopy()); 1907 goto finish; 1908 } 1909 } 1910 1911 result = registerIdentifier(); 1912 1913 finish: 1914 OSSafeReleaseNULL(parsedXML); 1915 OSSafeReleaseNULL(kextPath); 1916 OSSafeReleaseNULL(errorString); 1917 OSSafeReleaseNULL(executable); 1918 1919 return result; 1920 } 1921 1922 /********************************************************************* 1923 *********************************************************************/ 1924 bool 1925 OSKext::registerIdentifier(void) 1926 { 1927 bool result = false; 1928 OSKext * existingKext = NULL;// do not release 1929 bool existingIsLoaded = false; 1930 bool existingIsPrelinked = false; 1931 OSKextVersion newVersion = -1; 1932 OSKextVersion existingVersion = -1; 1933 char newVersionCString[kOSKextVersionMaxLength]; 1934 char existingVersionCString[kOSKextVersionMaxLength]; 1935 OSData * newUUID = NULL;// must release 1936 OSData * existingUUID = NULL;// must release 1937 1938 IORecursiveLockLock(sKextLock); 1939 1940 /* Get the new kext's version for checks & log messages. 1941 */ 1942 newVersion = getVersion(); 1943 OSKextVersionGetString(newVersion, newVersionCString, 1944 kOSKextVersionMaxLength); 1945 1946 /* If we don't have an existing kext with this identifier, 1947 * just record the new kext and we're done! 1948 */ 1949 existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)); 1950 if (!existingKext) { 1951 sKextsByID->setObject(bundleID, this); 1952 result = true; 1953 goto finish; 1954 } 1955 1956 /* Get the existing kext's version for checks & log messages. 1957 */ 1958 existingVersion = existingKext->getVersion(); 1959 OSKextVersionGetString(existingVersion, 1960 existingVersionCString, kOSKextVersionMaxLength); 1961 1962 existingIsLoaded = existingKext->isLoaded(); 1963 existingIsPrelinked = existingKext->isPrelinked(); 1964 1965 /* If we have a kext with this identifier that's already loaded/prelinked, 1966 * we can't use the new one, but let's be really thorough and check how 1967 * the two are related for a precise diagnostic log message. 1968 * 1969 * Note that user space can't find out about nonloaded prelinked kexts, 1970 * so in this case we log a message when new & existing are equivalent 1971 * at the step rather than warning level, because we are always going 1972 * be getting a copy of the kext in the user load request mkext. 1973 */ 1974 if (existingIsLoaded || existingIsPrelinked) { 1975 bool sameVersion = (newVersion == existingVersion); 1976 bool sameExecutable = true; // assume true unless we have UUIDs 1977 1978 /* Only get the UUID if the existing kext is loaded. Doing so 1979 * might have to uncompress an mkext executable and we shouldn't 1980 * take that hit when neither kext is loaded. 1981 */ 1982 newUUID = copyUUID(); 1983 existingUUID = existingKext->copyUUID(); 1984 1985 /* I'm entirely too paranoid about checking equivalence of executables, 1986 * but I remember nasty problems with it in the past. 1987 * 1988 * - If we have UUIDs for both kexts, compare them. 1989 * - If only one kext has a UUID, they're definitely different. 1990 */ 1991 if (newUUID && existingUUID) { 1992 sameExecutable = newUUID->isEqualTo(existingUUID); 1993 } else if (newUUID || existingUUID) { 1994 sameExecutable = false; 1995 } 1996 1997 if (!newUUID && !existingUUID) { 1998 /* If there are no UUIDs, we can't really tell that the executables 1999 * are *different* without a lot of work; the loaded kext's 2000 * unrelocated executable is no longer around (and we never had it 2001 * in-kernel for a prelinked kext). We certainly don't want to do 2002 * a whole fake link for the new kext just to compare, either. 2003 */ 2004 2005 OSKextVersionGetString(version, newVersionCString, 2006 sizeof(newVersionCString)); 2007 OSKextLog(this, 2008 kOSKextLogWarningLevel | 2009 kOSKextLogKextBookkeepingFlag, 2010 "Notice - new kext %s, v%s matches %s kext " 2011 "but can't determine if executables are the same (no UUIDs).", 2012 getIdentifierCString(), 2013 newVersionCString, 2014 (existingIsLoaded ? "loaded" : "prelinked")); 2015 } 2016 2017 if (sameVersion && sameExecutable) { 2018 OSKextLog(this, 2019 (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) | 2020 kOSKextLogKextBookkeepingFlag, 2021 "Refusing new kext %s, v%s: a %s copy is already present " 2022 "(same version and executable).", 2023 getIdentifierCString(), newVersionCString, 2024 (existingIsLoaded ? "loaded" : "prelinked")); 2025 } else { 2026 if (!sameVersion) { 2027 /* This condition is significant so log it under warnings. 2028 */ 2029 OSKextLog(this, 2030 kOSKextLogWarningLevel | 2031 kOSKextLogKextBookkeepingFlag, 2032 "Refusing new kext %s, v%s: already have %s v%s.", 2033 getIdentifierCString(), 2034 newVersionCString, 2035 (existingIsLoaded ? "loaded" : "prelinked"), 2036 existingVersionCString); 2037 } else { 2038 /* This condition is significant so log it under warnings. 2039 */ 2040 OSKextLog(this, 2041 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 2042 "Refusing new kext %s, v%s: a %s copy with a different " 2043 "executable UUID is already present.", 2044 getIdentifierCString(), newVersionCString, 2045 (existingIsLoaded ? "loaded" : "prelinked")); 2046 } 2047 } 2048 goto finish; 2049 } /* if (existingIsLoaded || existingIsPrelinked) */ 2050 2051 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether 2052 * user loads are happening or if we're still in early boot. User agents are 2053 * supposed to resolve dependencies topside and include only the exact 2054 * kexts needed; so we always accept the new kext (in fact we should never 2055 * see an older unloaded copy hanging around). 2056 */ 2057 if (sUserLoadsActive) { 2058 sKextsByID->setObject(bundleID, this); 2059 result = true; 2060 2061 OSKextLog(this, 2062 kOSKextLogStepLevel | 2063 kOSKextLogKextBookkeepingFlag, 2064 "Dropping old copy of kext %s (v%s) for newly-added (v%s).", 2065 getIdentifierCString(), 2066 existingVersionCString, 2067 newVersionCString); 2068 2069 goto finish; 2070 } 2071 2072 /* During early boot, the kext with the highest version always wins out. 2073 * Prelinked kernels will never hit this, but mkexts and booter-read 2074 * kexts might have duplicates. 2075 */ 2076 if (newVersion > existingVersion) { 2077 sKextsByID->setObject(bundleID, this); 2078 result = true; 2079 2080 OSKextLog(this, 2081 kOSKextLogStepLevel | 2082 kOSKextLogKextBookkeepingFlag, 2083 "Dropping lower version (v%s) of registered kext %s for higher (v%s).", 2084 existingVersionCString, 2085 getIdentifierCString(), 2086 newVersionCString); 2087 } else { 2088 OSKextLog(this, 2089 kOSKextLogStepLevel | 2090 kOSKextLogKextBookkeepingFlag, 2091 "Kext %s is already registered with a higher/same version (v%s); " 2092 "dropping newly-added (v%s).", 2093 getIdentifierCString(), 2094 existingVersionCString, 2095 newVersionCString); 2096 } 2097 2098 /* result has been set appropriately by now. */ 2099 2100 finish: 2101 2102 IORecursiveLockUnlock(sKextLock); 2103 2104 if (result) { 2105 OSKextLog(this, 2106 kOSKextLogStepLevel | 2107 kOSKextLogKextBookkeepingFlag, 2108 "Kext %s, v%s registered and available for loading.", 2109 getIdentifierCString(), newVersionCString); 2110 } 2111 2112 OSSafeReleaseNULL(newUUID); 2113 OSSafeReleaseNULL(existingUUID); 2114 2115 return result; 2116 } 2117 2118 /********************************************************************* 2119 * Does the bare minimum validation to look up a kext. 2120 * All other validation is done on the spot as needed. 2121 **********************************************************************/ 2122 bool 2123 OSKext::setInfoDictionaryAndPath( 2124 OSDictionary * aDictionary, 2125 OSString * aPath) 2126 { 2127 bool result = false; 2128 OSString * bundleIDString = NULL;// do not release 2129 OSString * versionString = NULL;// do not release 2130 OSString * compatibleVersionString = NULL;// do not release 2131 const char * versionCString = NULL;// do not free 2132 const char * compatibleVersionCString = NULL;// do not free 2133 OSBoolean * scratchBool = NULL;// do not release 2134 OSDictionary * scratchDict = NULL;// do not release 2135 2136 if (infoDict) { 2137 panic("Attempt to set info dictionary on a kext " 2138 "that already has one (%s).", 2139 getIdentifierCString()); 2140 } 2141 2142 if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) { 2143 goto finish; 2144 } 2145 2146 infoDict = aDictionary; 2147 infoDict->retain(); 2148 2149 /* Check right away if the info dictionary has any log flags. 2150 */ 2151 scratchBool = OSDynamicCast(OSBoolean, 2152 getPropertyForHostArch(kOSBundleEnableKextLoggingKey)); 2153 if (scratchBool == kOSBooleanTrue) { 2154 flags.loggingEnabled = 1; 2155 } 2156 2157 /* The very next thing to get is the bundle identifier. Unlike 2158 * in user space, a kext with no bundle identifier gets axed 2159 * immediately. 2160 */ 2161 bundleIDString = OSDynamicCast(OSString, 2162 getPropertyForHostArch(kCFBundleIdentifierKey)); 2163 if (!bundleIDString) { 2164 OSKextLog(this, 2165 kOSKextLogErrorLevel | 2166 kOSKextLogValidationFlag, 2167 "CFBundleIdentifier missing/invalid type in kext %s.", 2168 aPath ? aPath->getCStringNoCopy() : "(unknown)"); 2169 goto finish; 2170 } 2171 bundleID = OSSymbol::withString(bundleIDString); 2172 if (!bundleID) { 2173 OSKextLog(this, 2174 kOSKextLogErrorLevel | 2175 kOSKextLogValidationFlag, 2176 "Can't copy bundle identifier as symbol for kext %s.", 2177 bundleIDString->getCStringNoCopy()); 2178 goto finish; 2179 } 2180 2181 /* Save the path if we got one (it should always be available but it's 2182 * just something nice to have for bookkeeping). 2183 */ 2184 if (aPath) { 2185 path = aPath; 2186 path->retain(); 2187 } 2188 2189 /***** 2190 * Minimal validation to initialize. We'll do other validation on the spot. 2191 */ 2192 if (bundleID->getLength() >= KMOD_MAX_NAME) { 2193 OSKextLog(this, 2194 kOSKextLogErrorLevel | 2195 kOSKextLogValidationFlag, 2196 "Kext %s error - CFBundleIdentifier over max length %d.", 2197 getIdentifierCString(), KMOD_MAX_NAME - 1); 2198 goto finish; 2199 } 2200 2201 version = compatibleVersion = -1; 2202 2203 versionString = OSDynamicCast(OSString, 2204 getPropertyForHostArch(kCFBundleVersionKey)); 2205 if (!versionString) { 2206 OSKextLog(this, 2207 kOSKextLogErrorLevel | 2208 kOSKextLogValidationFlag, 2209 "Kext %s error - CFBundleVersion missing/invalid type.", 2210 getIdentifierCString()); 2211 goto finish; 2212 } 2213 versionCString = versionString->getCStringNoCopy(); 2214 version = OSKextParseVersionString(versionCString); 2215 if (version < 0) { 2216 OSKextLog(this, 2217 kOSKextLogErrorLevel | 2218 kOSKextLogValidationFlag, 2219 "Kext %s error - CFBundleVersion bad value '%s'.", 2220 getIdentifierCString(), versionCString); 2221 goto finish; 2222 } 2223 2224 compatibleVersion = -1; // set to illegal value for kexts that don't have 2225 2226 compatibleVersionString = OSDynamicCast(OSString, 2227 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 2228 if (compatibleVersionString) { 2229 compatibleVersionCString = compatibleVersionString->getCStringNoCopy(); 2230 compatibleVersion = OSKextParseVersionString(compatibleVersionCString); 2231 if (compatibleVersion < 0) { 2232 OSKextLog(this, 2233 kOSKextLogErrorLevel | 2234 kOSKextLogValidationFlag, 2235 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.", 2236 getIdentifierCString(), compatibleVersionCString); 2237 goto finish; 2238 } 2239 2240 if (compatibleVersion > version) { 2241 OSKextLog(this, 2242 kOSKextLogErrorLevel | 2243 kOSKextLogValidationFlag, 2244 "Kext %s error - %s %s > %s %s (must be <=).", 2245 getIdentifierCString(), 2246 kOSBundleCompatibleVersionKey, compatibleVersionCString, 2247 kCFBundleVersionKey, versionCString); 2248 goto finish; 2249 } 2250 } 2251 2252 /* Check to see if this kext is in exclude list */ 2253 if (isInExcludeList()) { 2254 OSKextLog(this, 2255 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 2256 "Kext %s is in exclude list, not loadable", 2257 getIdentifierCString()); 2258 goto finish; 2259 } 2260 2261 /* Set flags for later use if the infoDict gets flushed. We only 2262 * check for true values, not false ones(!) 2263 */ 2264 scratchBool = OSDynamicCast(OSBoolean, 2265 getPropertyForHostArch(kOSBundleIsInterfaceKey)); 2266 if (scratchBool == kOSBooleanTrue) { 2267 flags.interface = 1; 2268 } 2269 2270 scratchBool = OSDynamicCast(OSBoolean, 2271 getPropertyForHostArch(kOSKernelResourceKey)); 2272 if (scratchBool == kOSBooleanTrue) { 2273 flags.kernelComponent = 1; 2274 flags.interface = 1; // xxx - hm. the kernel itself isn't an interface... 2275 flags.started = 1; 2276 2277 /* A kernel component has one implicit dependency on the kernel. 2278 */ 2279 flags.hasAllDependencies = 1; 2280 } 2281 2282 /* Make sure common string values in personalities are uniqued to OSSymbols. 2283 */ 2284 scratchDict = OSDynamicCast(OSDictionary, 2285 getPropertyForHostArch(kIOKitPersonalitiesKey)); 2286 if (scratchDict) { 2287 uniquePersonalityProperties(scratchDict); 2288 } 2289 2290 result = true; 2291 2292 finish: 2293 2294 return result; 2295 } 2296 2297 /********************************************************************* 2298 * Not used for prelinked kernel boot as there is no unrelocated 2299 * executable. 2300 *********************************************************************/ 2301 bool 2302 OSKext::setExecutable( 2303 OSData * anExecutable, 2304 OSData * externalData, 2305 bool externalDataIsMkext) 2306 { 2307 bool result = false; 2308 const char * executableKey = NULL; // do not free 2309 2310 if (!anExecutable) { 2311 infoDict->removeObject(_kOSKextExecutableKey); 2312 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 2313 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 2314 result = true; 2315 goto finish; 2316 } 2317 2318 if (infoDict->getObject(_kOSKextExecutableKey) || 2319 infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) { 2320 panic("Attempt to set an executable on a kext " 2321 "that already has one (%s).", 2322 getIdentifierCString()); 2323 goto finish; 2324 } 2325 2326 if (externalDataIsMkext) { 2327 executableKey = _kOSKextMkextExecutableReferenceKey; 2328 } else { 2329 executableKey = _kOSKextExecutableKey; 2330 } 2331 2332 if (anExecutable) { 2333 infoDict->setObject(executableKey, anExecutable); 2334 if (externalData) { 2335 infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData); 2336 } 2337 } 2338 2339 result = true; 2340 2341 finish: 2342 return result; 2343 } 2344 2345 /********************************************************************* 2346 *********************************************************************/ 2347 static void 2348 uniqueStringPlistProperty(OSDictionary * dict, const char * key) 2349 { 2350 OSString * stringValue = NULL;// do not release 2351 const OSSymbol * symbolValue = NULL; // must release 2352 2353 stringValue = OSDynamicCast(OSString, dict->getObject(key)); 2354 if (!stringValue) { 2355 goto finish; 2356 } 2357 2358 symbolValue = OSSymbol::withString(stringValue); 2359 if (!symbolValue) { 2360 goto finish; 2361 } 2362 2363 dict->setObject(key, symbolValue); 2364 2365 finish: 2366 if (symbolValue) { 2367 symbolValue->release(); 2368 } 2369 2370 return; 2371 } 2372 2373 /********************************************************************* 2374 *********************************************************************/ 2375 static void 2376 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key) 2377 { 2378 OSString * stringValue = NULL;// do not release 2379 const OSSymbol * symbolValue = NULL; // must release 2380 2381 stringValue = OSDynamicCast(OSString, dict->getObject(key)); 2382 if (!stringValue) { 2383 goto finish; 2384 } 2385 2386 symbolValue = OSSymbol::withString(stringValue); 2387 if (!symbolValue) { 2388 goto finish; 2389 } 2390 2391 dict->setObject(key, symbolValue); 2392 2393 finish: 2394 if (symbolValue) { 2395 symbolValue->release(); 2396 } 2397 2398 return; 2399 } 2400 2401 /********************************************************************* 2402 * Replace common personality property values with uniqued instances 2403 * to save on wired memory. 2404 *********************************************************************/ 2405 /* static */ 2406 void 2407 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict) 2408 { 2409 /* Properties every personality has. 2410 */ 2411 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey); 2412 uniqueStringPlistProperty(personalityDict, kIOProviderClassKey); 2413 uniqueStringPlistProperty(personalityDict, gIOClassKey); 2414 if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) { 2415 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey); 2416 } else { 2417 personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey)); 2418 } 2419 2420 /* Other commonly used properties. 2421 */ 2422 uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey); 2423 uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey); 2424 uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey); 2425 2426 uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior"); 2427 uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType"); 2428 uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType"); 2429 uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType"); 2430 uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher"); 2431 uniqueStringPlistProperty(personalityDict, "Physical Interconnect"); 2432 uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location"); 2433 uniqueStringPlistProperty(personalityDict, "Vendor"); 2434 uniqueStringPlistProperty(personalityDict, "Vendor Identification"); 2435 uniqueStringPlistProperty(personalityDict, "Vendor Name"); 2436 uniqueStringPlistProperty(personalityDict, "bConfigurationValue"); 2437 uniqueStringPlistProperty(personalityDict, "bInterfaceNumber"); 2438 uniqueStringPlistProperty(personalityDict, "idProduct"); 2439 2440 return; 2441 } 2442 2443 /********************************************************************* 2444 *********************************************************************/ 2445 void 2446 OSKext::free(void) 2447 { 2448 if (isLoaded()) { 2449 panic("Attempt to free loaded kext %s.", getIdentifierCString()); 2450 } 2451 2452 OSSafeReleaseNULL(infoDict); 2453 OSSafeReleaseNULL(bundleID); 2454 OSSafeReleaseNULL(path); 2455 OSSafeReleaseNULL(executableRelPath); 2456 OSSafeReleaseNULL(userExecutableRelPath); 2457 OSSafeReleaseNULL(dependencies); 2458 OSSafeReleaseNULL(linkedExecutable); 2459 OSSafeReleaseNULL(metaClasses); 2460 OSSafeReleaseNULL(interfaceUUID); 2461 OSSafeReleaseNULL(driverKitUUID); 2462 2463 if (isInterface() && kmod_info) { 2464 kfree(kmod_info, sizeof(kmod_info_t)); 2465 } 2466 2467 super::free(); 2468 return; 2469 } 2470 2471 #if PRAGMA_MARK 2472 #pragma mark Mkext files 2473 #endif 2474 /********************************************************************* 2475 *********************************************************************/ 2476 OSReturn 2477 OSKext::readMkextArchive(OSData * mkextData, 2478 uint32_t * checksumPtr) 2479 { 2480 OSReturn result = kOSKextReturnBadData; 2481 uint32_t mkextLength = 0; 2482 mkext_header * mkextHeader = NULL;// do not free 2483 uint32_t mkextVersion = 0; 2484 2485 /* Note default return of kOSKextReturnBadData above. 2486 */ 2487 mkextLength = mkextData->getLength(); 2488 if (mkextLength < sizeof(mkext_basic_header)) { 2489 OSKextLog(/* kext */ NULL, 2490 kOSKextLogErrorLevel | 2491 kOSKextLogArchiveFlag, 2492 "Mkext archive too small to be valid."); 2493 goto finish; 2494 } 2495 2496 mkextHeader = (mkext_header *)mkextData->getBytesNoCopy(); 2497 2498 if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC || 2499 MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) { 2500 OSKextLog(/* kext */ NULL, 2501 kOSKextLogErrorLevel | 2502 kOSKextLogArchiveFlag, 2503 "Mkext archive has invalid magic or signature."); 2504 goto finish; 2505 } 2506 2507 if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) { 2508 OSKextLog(/* kext */ NULL, 2509 kOSKextLogErrorLevel | 2510 kOSKextLogArchiveFlag, 2511 "Mkext archive recorded length doesn't match actual file length."); 2512 goto finish; 2513 } 2514 2515 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 2516 2517 if (mkextVersion == MKEXT_VERS_2) { 2518 result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr); 2519 } else { 2520 OSKextLog(/* kext */ NULL, 2521 kOSKextLogErrorLevel | 2522 kOSKextLogArchiveFlag, 2523 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion); 2524 result = kOSKextReturnUnsupported; 2525 } 2526 2527 finish: 2528 return result; 2529 } 2530 2531 /********************************************************************* 2532 * Assumes magic, signature, version, length have been checked. 2533 * xxx - need to add further bounds checking for each file entry 2534 * 2535 * Should keep track of all kexts created so far, and if we hit a 2536 * fatal error halfway through, remove those kexts. If we've dropped 2537 * an older version that had already been read, whoops! Might want to 2538 * add a level of buffering? 2539 *********************************************************************/ 2540 /* static */ 2541 OSReturn 2542 OSKext::readMkext2Archive( 2543 OSData * mkextData, 2544 OSDictionary ** mkextPlistOut, 2545 uint32_t * checksumPtr) 2546 { 2547 OSReturn result = kOSReturnError; 2548 uint32_t mkextLength; 2549 mkext2_header * mkextHeader = NULL;// do not free 2550 void * mkextEnd = NULL;// do not free 2551 uint32_t mkextVersion; 2552 uint8_t * crc_address = NULL; 2553 uint32_t checksum; 2554 uint32_t mkextPlistOffset; 2555 uint32_t mkextPlistCompressedSize; 2556 char * mkextPlistEnd = NULL;// do not free 2557 uint32_t mkextPlistFullSize; 2558 OSString * errorString = NULL;// must release 2559 OSData * mkextPlistUncompressedData = NULL;// must release 2560 const char * mkextPlistDataBuffer = NULL;// do not free 2561 OSObject * parsedXML = NULL;// must release 2562 OSDictionary * mkextPlist = NULL;// do not release 2563 OSArray * mkextInfoDictArray = NULL;// do not release 2564 uint32_t count, i; 2565 2566 mkextLength = mkextData->getLength(); 2567 mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy(); 2568 mkextEnd = (char *)mkextHeader + mkextLength; 2569 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 2570 2571 crc_address = (u_int8_t *)&mkextHeader->version; 2572 checksum = mkext_adler32(crc_address, 2573 (uintptr_t)mkextHeader + 2574 MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address); 2575 2576 if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) { 2577 OSKextLog(/* kext */ NULL, 2578 kOSKextLogErrorLevel | 2579 kOSKextLogArchiveFlag, 2580 "Mkext archive has bad checksum."); 2581 result = kOSKextReturnBadData; 2582 goto finish; 2583 } 2584 2585 if (checksumPtr) { 2586 *checksumPtr = checksum; 2587 } 2588 2589 /* Check that the CPU type & subtype match that of the running kernel. */ 2590 if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) { 2591 OSKextLog(/* kext */ NULL, 2592 kOSKextLogErrorLevel | 2593 kOSKextLogArchiveFlag, 2594 "Mkext archive must have a specific CPU type."); 2595 result = kOSKextReturnBadData; 2596 goto finish; 2597 } else { 2598 if ((UInt32)_mh_execute_header.cputype != 2599 MKEXT_GET_CPUTYPE(mkextHeader)) { 2600 OSKextLog(/* kext */ NULL, 2601 kOSKextLogErrorLevel | 2602 kOSKextLogArchiveFlag, 2603 "Mkext archive does not match the running kernel's CPU type."); 2604 result = kOSKextReturnArchNotFound; 2605 goto finish; 2606 } 2607 } 2608 2609 mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader); 2610 mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader); 2611 mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset + 2612 mkextPlistCompressedSize; 2613 if (mkextPlistEnd > mkextEnd) { 2614 OSKextLog(/* kext */ NULL, 2615 kOSKextLogErrorLevel | 2616 kOSKextLogArchiveFlag, 2617 "Mkext archive file overrun."); 2618 result = kOSKextReturnBadData; 2619 } 2620 2621 mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader); 2622 if (mkextPlistCompressedSize) { 2623 mkextPlistUncompressedData = sKernelKext->extractMkext2FileData( 2624 (UInt8 *)mkextHeader + mkextPlistOffset, 2625 "plist", 2626 mkextPlistCompressedSize, mkextPlistFullSize); 2627 if (!mkextPlistUncompressedData) { 2628 goto finish; 2629 } 2630 mkextPlistDataBuffer = (const char *) 2631 mkextPlistUncompressedData->getBytesNoCopy(); 2632 } else { 2633 mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset; 2634 } 2635 2636 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it. 2637 */ 2638 parsedXML = OSUnserializeXML(mkextPlistDataBuffer, &errorString); 2639 if (parsedXML) { 2640 mkextPlist = OSDynamicCast(OSDictionary, parsedXML); 2641 } 2642 if (!mkextPlist) { 2643 const char * errorCString = "(unknown error)"; 2644 2645 if (errorString && errorString->getCStringNoCopy()) { 2646 errorCString = errorString->getCStringNoCopy(); 2647 } else if (parsedXML) { 2648 errorCString = "not a dictionary"; 2649 } 2650 OSKextLog(/* kext */ NULL, 2651 kOSKextLogErrorLevel | 2652 kOSKextLogArchiveFlag, 2653 "Error unserializing mkext plist: %s.", errorCString); 2654 goto finish; 2655 } 2656 2657 /* If the caller needs the plist, hand it back and retain it. 2658 * (This function releases it at the end.) 2659 */ 2660 if (mkextPlistOut) { 2661 *mkextPlistOut = mkextPlist; 2662 (*mkextPlistOut)->retain(); 2663 } 2664 2665 mkextInfoDictArray = OSDynamicCast(OSArray, 2666 mkextPlist->getObject(kMKEXTInfoDictionariesKey)); 2667 if (!mkextInfoDictArray) { 2668 OSKextLog(/* kext */ NULL, 2669 kOSKextLogErrorLevel | 2670 kOSKextLogArchiveFlag, 2671 "Mkext archive contains no kext info dictionaries."); 2672 goto finish; 2673 } 2674 2675 count = mkextInfoDictArray->getCount(); 2676 for (i = 0; i < count; i++) { 2677 OSDictionary * infoDict; 2678 2679 2680 infoDict = OSDynamicCast(OSDictionary, 2681 mkextInfoDictArray->getObject(i)); 2682 2683 /* Create the kext for the entry, then release it, because the 2684 * kext system keeps them around until explicitly removed. 2685 * Any creation/registration failures are already logged for us. 2686 */ 2687 if (infoDict) { 2688 OSKext * newKext = OSKext::withMkext2Info(infoDict, mkextData); 2689 OSSafeReleaseNULL(newKext); 2690 } 2691 } 2692 2693 /* Even if we didn't keep any kexts from the mkext, we may have a load 2694 * request to process, so we are successful (no errors occurred). 2695 */ 2696 result = kOSReturnSuccess; 2697 2698 finish: 2699 2700 OSSafeReleaseNULL(parsedXML); 2701 OSSafeReleaseNULL(mkextPlistUncompressedData); 2702 OSSafeReleaseNULL(errorString); 2703 2704 return result; 2705 } 2706 2707 /********************************************************************* 2708 *********************************************************************/ 2709 /* static */ 2710 OSKext * 2711 OSKext::withMkext2Info( 2712 OSDictionary * anInfoDict, 2713 OSData * mkextData) 2714 { 2715 OSKext * newKext = new OSKext; 2716 2717 if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) { 2718 newKext->release(); 2719 return NULL; 2720 } 2721 2722 return newKext; 2723 } 2724 2725 /********************************************************************* 2726 *********************************************************************/ 2727 bool 2728 OSKext::initWithMkext2Info( 2729 OSDictionary * anInfoDict, 2730 OSData * mkextData) 2731 { 2732 bool result = false; 2733 OSString * kextPath = NULL;// do not release 2734 OSNumber * executableOffsetNum = NULL;// do not release 2735 OSCollectionIterator * iterator = NULL;// must release 2736 OSData * executable = NULL;// must release 2737 2738 if (anInfoDict == NULL || !super::init()) { 2739 goto finish; 2740 } 2741 2742 /* Get the path. Don't look for an arch-specific path property. 2743 */ 2744 kextPath = OSDynamicCast(OSString, 2745 anInfoDict->getObject(kMKEXTBundlePathKey)); 2746 2747 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 2748 goto finish; 2749 } 2750 2751 /* If we have a path to the executable, save it. 2752 */ 2753 executableRelPath = OSDynamicCast(OSString, 2754 anInfoDict->getObject(kMKEXTExecutableRelativePathKey)); 2755 if (executableRelPath) { 2756 executableRelPath->retain(); 2757 } 2758 2759 /* Don't need the paths to be in the info dictionary any more. 2760 */ 2761 anInfoDict->removeObject(kMKEXTBundlePathKey); 2762 anInfoDict->removeObject(kMKEXTExecutableRelativePathKey); 2763 2764 executableOffsetNum = OSDynamicCast(OSNumber, 2765 infoDict->getObject(kMKEXTExecutableKey)); 2766 if (executableOffsetNum) { 2767 executable = createMkext2FileEntry(mkextData, 2768 executableOffsetNum, "executable"); 2769 infoDict->removeObject(kMKEXTExecutableKey); 2770 if (!executable) { 2771 goto finish; 2772 } 2773 if (!setExecutable(executable, mkextData, true)) { 2774 goto finish; 2775 } 2776 } 2777 2778 result = registerIdentifier(); 2779 2780 finish: 2781 2782 OSSafeReleaseNULL(executable); 2783 OSSafeReleaseNULL(iterator); 2784 return result; 2785 } 2786 2787 /********************************************************************* 2788 *********************************************************************/ 2789 OSData * 2790 OSKext::createMkext2FileEntry( 2791 OSData * mkextData, 2792 OSNumber * offsetNum, 2793 const char * name) 2794 { 2795 OSData * result = NULL; 2796 MkextEntryRef entryRef; 2797 uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy(); 2798 uint32_t entryOffset = offsetNum->unsigned32BitValue(); 2799 2800 result = OSData::withCapacity(sizeof(entryRef)); 2801 if (!result) { 2802 goto finish; 2803 } 2804 2805 entryRef.mkext = (mkext_basic_header *)mkextBuffer; 2806 entryRef.fileinfo = mkextBuffer + entryOffset; 2807 if (!result->appendBytes(&entryRef, sizeof(entryRef))) { 2808 OSSafeReleaseNULL(result); 2809 goto finish; 2810 } 2811 2812 finish: 2813 if (!result) { 2814 OSKextLog(this, 2815 kOSKextLogErrorLevel | 2816 kOSKextLogArchiveFlag, 2817 "Can't create wrapper for mkext file entry '%s' of kext %s.", 2818 name, getIdentifierCString()); 2819 } 2820 return result; 2821 } 2822 2823 /********************************************************************* 2824 *********************************************************************/ 2825 extern "C" { 2826 static void * z_alloc(void *, u_int items, u_int size); 2827 static void z_free(void *, void *ptr); 2828 2829 typedef struct z_mem { 2830 uint32_t alloc_size; 2831 uint8_t data[0]; 2832 } z_mem; 2833 2834 /* 2835 * Space allocation and freeing routines for use by zlib routines. 2836 */ 2837 void * 2838 z_alloc(void * notused __unused, u_int num_items, u_int size) 2839 { 2840 void * result = NULL; 2841 z_mem * zmem = NULL; 2842 2843 uint64_t total = ((uint64_t)num_items) * ((uint64_t)size); 2844 //Check for overflow due to multiplication 2845 if (total > UINT32_MAX) { 2846 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n", 2847 notused, num_items, size, num_items, size); 2848 } 2849 2850 uint64_t allocSize64 = total + ((uint64_t)sizeof(zmem)); 2851 //Check for overflow due to addition 2852 if (allocSize64 > UINT32_MAX) { 2853 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n", 2854 notused, num_items, size, (uint32_t)total, sizeof(zmem)); 2855 } 2856 uint32_t allocSize = (uint32_t)allocSize64; 2857 2858 zmem = (z_mem *)kalloc_tag(allocSize, VM_KERN_MEMORY_OSKEXT); 2859 if (!zmem) { 2860 goto finish; 2861 } 2862 zmem->alloc_size = allocSize; 2863 result = (void *)&(zmem->data); 2864 finish: 2865 return result; 2866 } 2867 2868 void 2869 z_free(void * notused __unused, void * ptr) 2870 { 2871 uint32_t * skipper = (uint32_t *)ptr - 1; 2872 z_mem * zmem = (z_mem *)skipper; 2873 kfree(zmem, zmem->alloc_size); 2874 return; 2875 } 2876 }; 2877 2878 OSData * 2879 OSKext::extractMkext2FileData( 2880 UInt8 * data, 2881 const char * name, 2882 uint32_t compressedSize, 2883 uint32_t fullSize) 2884 { 2885 OSData * result = NULL; 2886 2887 OSData * uncompressedData = NULL;// release on error 2888 2889 uint8_t * uncompressedDataBuffer = NULL;// do not free 2890 unsigned long uncompressedSize; 2891 z_stream zstream; 2892 bool zstream_inited = false; 2893 int zlib_result; 2894 2895 /* If the file isn't compressed, we want to make a copy 2896 * so that we don't have the tie to the larger mkext file buffer any more. 2897 */ 2898 if (!compressedSize) { 2899 uncompressedData = OSData::withBytes(data, fullSize); 2900 // xxx - no check for failure? 2901 result = uncompressedData; 2902 goto finish; 2903 } 2904 2905 if (KERN_SUCCESS != kmem_alloc(kernel_map, 2906 (vm_offset_t*)&uncompressedDataBuffer, fullSize, VM_KERN_MEMORY_OSKEXT)) { 2907 /* How's this for cheesy? The kernel is only asked to extract 2908 * kext plists so we tailor the log messages. 2909 */ 2910 if (isKernel()) { 2911 OSKextLog(this, 2912 kOSKextLogErrorLevel | 2913 kOSKextLogArchiveFlag, 2914 "Allocation failure extracting %s from mkext.", name); 2915 } else { 2916 OSKextLog(this, 2917 kOSKextLogErrorLevel | 2918 kOSKextLogArchiveFlag, 2919 "Allocation failure extracting %s from mkext for kext %s.", 2920 name, getIdentifierCString()); 2921 } 2922 2923 goto finish; 2924 } 2925 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize); 2926 if (!uncompressedData) { 2927 if (isKernel()) { 2928 OSKextLog(this, 2929 kOSKextLogErrorLevel | 2930 kOSKextLogArchiveFlag, 2931 "Allocation failure extracting %s from mkext.", name); 2932 } else { 2933 OSKextLog(this, 2934 kOSKextLogErrorLevel | 2935 kOSKextLogArchiveFlag, 2936 "Allocation failure extracting %s from mkext for kext %s.", 2937 name, getIdentifierCString()); 2938 } 2939 goto finish; 2940 } 2941 uncompressedData->setDeallocFunction(&osdata_kmem_free); 2942 2943 if (isKernel()) { 2944 OSKextLog(this, 2945 kOSKextLogDetailLevel | 2946 kOSKextLogArchiveFlag, 2947 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.", 2948 name, compressedSize, fullSize); 2949 } else { 2950 OSKextLog(this, 2951 kOSKextLogDetailLevel | 2952 kOSKextLogArchiveFlag, 2953 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.", 2954 getIdentifierCString(), name, compressedSize, fullSize); 2955 } 2956 2957 bzero(&zstream, sizeof(zstream)); 2958 zstream.next_in = (UInt8 *)data; 2959 zstream.avail_in = compressedSize; 2960 2961 zstream.next_out = uncompressedDataBuffer; 2962 zstream.avail_out = fullSize; 2963 2964 zstream.zalloc = z_alloc; 2965 zstream.zfree = z_free; 2966 2967 zlib_result = inflateInit(&zstream); 2968 if (Z_OK != zlib_result) { 2969 if (isKernel()) { 2970 OSKextLog(this, 2971 kOSKextLogErrorLevel | 2972 kOSKextLogArchiveFlag, 2973 "Mkext error; zlib inflateInit failed (%d) for %s.", 2974 zlib_result, name); 2975 } else { 2976 OSKextLog(this, 2977 kOSKextLogErrorLevel | 2978 kOSKextLogArchiveFlag, 2979 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .", 2980 getIdentifierCString(), zlib_result, name); 2981 } 2982 goto finish; 2983 } else { 2984 zstream_inited = true; 2985 } 2986 2987 zlib_result = inflate(&zstream, Z_FINISH); 2988 2989 if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) { 2990 uncompressedSize = zstream.total_out; 2991 } else { 2992 if (isKernel()) { 2993 OSKextLog(this, 2994 kOSKextLogErrorLevel | 2995 kOSKextLogArchiveFlag, 2996 "Mkext error; zlib inflate failed (%d) for %s.", 2997 zlib_result, name); 2998 } else { 2999 OSKextLog(this, 3000 kOSKextLogErrorLevel | 3001 kOSKextLogArchiveFlag, 3002 "Kext %s - mkext error; zlib inflate failed (%d) for %s .", 3003 getIdentifierCString(), zlib_result, name); 3004 } 3005 if (zstream.msg) { 3006 OSKextLog(this, 3007 kOSKextLogErrorLevel | 3008 kOSKextLogArchiveFlag, 3009 "zlib error: %s.", zstream.msg); 3010 } 3011 goto finish; 3012 } 3013 3014 if (uncompressedSize != fullSize) { 3015 if (isKernel()) { 3016 OSKextLog(this, 3017 kOSKextLogErrorLevel | 3018 kOSKextLogArchiveFlag, 3019 "Mkext error; zlib inflate discrepancy for %s, " 3020 "uncompressed size != original size.", name); 3021 } else { 3022 OSKextLog(this, 3023 kOSKextLogErrorLevel | 3024 kOSKextLogArchiveFlag, 3025 "Kext %s - mkext error; zlib inflate discrepancy for %s, " 3026 "uncompressed size != original size.", 3027 getIdentifierCString(), name); 3028 } 3029 goto finish; 3030 } 3031 3032 result = uncompressedData; 3033 3034 finish: 3035 /* Don't bother checking return, nothing we can do on fail. 3036 */ 3037 if (zstream_inited) { 3038 inflateEnd(&zstream); 3039 } 3040 3041 if (!result) { 3042 OSSafeReleaseNULL(uncompressedData); 3043 } 3044 3045 return result; 3046 } 3047 3048 /********************************************************************* 3049 *********************************************************************/ 3050 /* static */ 3051 OSReturn 3052 OSKext::loadFromMkext( 3053 OSKextLogSpec clientLogFilter, 3054 char * mkextBuffer, 3055 uint32_t mkextBufferLength, 3056 char ** logInfoOut, 3057 uint32_t * logInfoLengthOut) 3058 { 3059 OSReturn result = kOSReturnError; 3060 OSReturn tempResult = kOSReturnError; 3061 3062 OSData * mkextData = NULL;// must release 3063 OSDictionary * mkextPlist = NULL;// must release 3064 3065 OSArray * logInfoArray = NULL;// must release 3066 OSSerialize * serializer = NULL;// must release 3067 3068 OSString * predicate = NULL;// do not release 3069 OSDictionary * requestArgs = NULL;// do not release 3070 3071 OSString * kextIdentifier = NULL;// do not release 3072 OSNumber * startKextExcludeNum = NULL;// do not release 3073 OSNumber * startMatchingExcludeNum = NULL;// do not release 3074 OSBoolean * delayAutounloadBool = NULL;// do not release 3075 OSArray * personalityNames = NULL;// do not release 3076 3077 /* Default values for these two options: regular autounload behavior, 3078 * load all kexts, send no personalities. 3079 */ 3080 Boolean delayAutounload = false; 3081 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 3082 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll; 3083 3084 IORecursiveLockLock(sKextLock); 3085 3086 if (logInfoOut) { 3087 *logInfoOut = NULL; 3088 *logInfoLengthOut = 0; 3089 } 3090 3091 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 3092 3093 OSKextLog(/* kext */ NULL, 3094 kOSKextLogDebugLevel | 3095 kOSKextLogIPCFlag, 3096 "Received kext load request from user space."); 3097 3098 /* Regardless of processing, the fact that we have gotten here means some 3099 * user-space program is up and talking to us, so we'll switch our kext 3100 * registration to reflect that. 3101 */ 3102 if (!sUserLoadsActive) { 3103 OSKextLog(/* kext */ NULL, 3104 kOSKextLogProgressLevel | 3105 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 3106 "Switching to late startup (user-space) kext loading policy."); 3107 3108 sUserLoadsActive = true; 3109 } 3110 3111 if (!sLoadEnabled) { 3112 OSKextLog(/* kext */ NULL, 3113 kOSKextLogErrorLevel | 3114 kOSKextLogLoadFlag, 3115 "Kext loading is disabled."); 3116 result = kOSKextReturnDisabled; 3117 goto finish; 3118 } 3119 3120 /* Note that we do not set a dealloc function on this OSData 3121 * object! No references to it can remain after the loadFromMkext() 3122 * call since we are in a MIG function, and will vm_deallocate() 3123 * the buffer. 3124 */ 3125 mkextData = OSData::withBytesNoCopy(mkextBuffer, 3126 mkextBufferLength); 3127 if (!mkextData) { 3128 OSKextLog(/* kext */ NULL, 3129 kOSKextLogErrorLevel | 3130 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 3131 "Failed to create wrapper for kext load request."); 3132 result = kOSKextReturnNoMemory; 3133 goto finish; 3134 } 3135 3136 result = readMkext2Archive(mkextData, &mkextPlist, NULL); 3137 if (result != kOSReturnSuccess) { 3138 OSKextLog(/* kext */ NULL, 3139 kOSKextLogErrorLevel | 3140 kOSKextLogLoadFlag, 3141 "Failed to read kext load request."); 3142 goto finish; 3143 } 3144 3145 predicate = _OSKextGetRequestPredicate(mkextPlist); 3146 if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) { 3147 OSKextLog(/* kext */ NULL, 3148 kOSKextLogErrorLevel | 3149 kOSKextLogLoadFlag, 3150 "Received kext load request with no predicate; skipping."); 3151 result = kOSKextReturnInvalidArgument; 3152 goto finish; 3153 } 3154 3155 requestArgs = OSDynamicCast(OSDictionary, 3156 mkextPlist->getObject(kKextRequestArgumentsKey)); 3157 if (!requestArgs || !requestArgs->getCount()) { 3158 OSKextLog(/* kext */ NULL, 3159 kOSKextLogErrorLevel | 3160 kOSKextLogLoadFlag, 3161 "Received kext load request with no arguments."); 3162 result = kOSKextReturnInvalidArgument; 3163 goto finish; 3164 } 3165 3166 kextIdentifier = OSDynamicCast(OSString, 3167 requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey)); 3168 3169 if (!kextIdentifier) { 3170 OSKextLog(/* kext */ NULL, 3171 kOSKextLogErrorLevel | 3172 kOSKextLogLoadFlag, 3173 "Received kext load request with no kext identifier."); 3174 result = kOSKextReturnInvalidArgument; 3175 goto finish; 3176 } 3177 3178 startKextExcludeNum = OSDynamicCast(OSNumber, 3179 requestArgs->getObject(kKextRequestArgumentStartExcludeKey)); 3180 startMatchingExcludeNum = OSDynamicCast(OSNumber, 3181 requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey)); 3182 delayAutounloadBool = OSDynamicCast(OSBoolean, 3183 requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey)); 3184 personalityNames = OSDynamicCast(OSArray, 3185 requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey)); 3186 3187 if (delayAutounloadBool) { 3188 delayAutounload = delayAutounloadBool->getValue(); 3189 } 3190 if (startKextExcludeNum) { 3191 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 3192 } 3193 if (startMatchingExcludeNum) { 3194 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 3195 } 3196 3197 OSKextLog(/* kext */ NULL, 3198 kOSKextLogProgressLevel | 3199 kOSKextLogIPCFlag, 3200 "Received request from user space to load kext %s.", 3201 kextIdentifier->getCStringNoCopy()); 3202 3203 /* Load the kext, with no deferral, since this is a load from outside 3204 * the kernel. 3205 * xxx - Would like a better way to handle the default values for the 3206 * xxx - start/match opt args. 3207 */ 3208 result = OSKext::loadKextWithIdentifier( 3209 kextIdentifier, 3210 /* kextRef */ NULL, 3211 /* allowDefer */ false, 3212 delayAutounload, 3213 startKextExcludeLevel, 3214 startMatchingExcludeLevel, 3215 personalityNames); 3216 if (result != kOSReturnSuccess) { 3217 goto finish; 3218 } 3219 /* If the load came down from kextd, it will shortly inform IOCatalogue 3220 * for matching via a separate IOKit calldown. 3221 */ 3222 3223 finish: 3224 3225 /* Gather up the collected log messages for user space. Any 3226 * error messages past this call will not make it up as log messages 3227 * but will be in the system log. 3228 */ 3229 logInfoArray = OSKext::clearUserSpaceLogFilter(); 3230 3231 if (logInfoArray && logInfoOut && logInfoLengthOut) { 3232 tempResult = OSKext::serializeLogInfo(logInfoArray, 3233 logInfoOut, logInfoLengthOut); 3234 if (tempResult != kOSReturnSuccess) { 3235 result = tempResult; 3236 } 3237 } 3238 3239 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false); 3240 3241 /* Note: mkextDataObject will have been retained by every kext w/an 3242 * executable in it. That should all have been flushed out at the 3243 * and of the load operation, but you never know.... 3244 */ 3245 if (mkextData && mkextData->getRetainCount() > 1) { 3246 OSKextLog(/* kext */ NULL, 3247 kOSKextLogErrorLevel | 3248 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 3249 "Kext load request buffer from user space still retained by a kext; " 3250 "probable memory leak."); 3251 } 3252 3253 IORecursiveLockUnlock(sKextLock); 3254 3255 OSSafeReleaseNULL(mkextData); 3256 OSSafeReleaseNULL(mkextPlist); 3257 OSSafeReleaseNULL(serializer); 3258 OSSafeReleaseNULL(logInfoArray); 3259 3260 return result; 3261 } 3262 3263 /********************************************************************* 3264 *********************************************************************/ 3265 /* static */ 3266 OSReturn 3267 OSKext::serializeLogInfo( 3268 OSArray * logInfoArray, 3269 char ** logInfoOut, 3270 uint32_t * logInfoLengthOut) 3271 { 3272 OSReturn result = kOSReturnError; 3273 char * buffer = NULL; 3274 kern_return_t kmem_result = KERN_FAILURE; 3275 OSSerialize * serializer = NULL;// must release; reused 3276 char * logInfo = NULL;// returned by reference 3277 uint32_t logInfoLength = 0; 3278 3279 if (!logInfoArray || !logInfoOut || !logInfoLengthOut) { 3280 OSKextLog(/* kext */ NULL, 3281 kOSKextLogErrorLevel | 3282 kOSKextLogIPCFlag, 3283 "Internal error; invalid arguments to OSKext::serializeLogInfo()."); 3284 /* Bad programmer. */ 3285 result = kOSKextReturnInvalidArgument; 3286 goto finish; 3287 } 3288 3289 serializer = OSSerialize::withCapacity(0); 3290 if (!serializer) { 3291 OSKextLog(/* kext */ NULL, 3292 kOSKextLogErrorLevel | 3293 kOSKextLogIPCFlag, 3294 "Failed to create serializer on log info for request from user space."); 3295 /* Incidental error; we're going to (try to) allow the request 3296 * itself to succeed. */ 3297 } 3298 3299 if (!logInfoArray->serialize(serializer)) { 3300 OSKextLog(/* kext */ NULL, 3301 kOSKextLogErrorLevel | 3302 kOSKextLogIPCFlag, 3303 "Failed to serialize log info for request from user space."); 3304 /* Incidental error; we're going to (try to) allow the request 3305 * itself to succeed. */ 3306 } else { 3307 logInfo = serializer->text(); 3308 logInfoLength = serializer->getLength(); 3309 3310 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT); 3311 if (kmem_result != KERN_SUCCESS) { 3312 OSKextLog(/* kext */ NULL, 3313 kOSKextLogErrorLevel | 3314 kOSKextLogIPCFlag, 3315 "Failed to copy log info for request from user space."); 3316 /* Incidental error; we're going to (try to) allow the request 3317 * to succeed. */ 3318 } else { 3319 /* 11981737 - clear uninitialized data in last page */ 3320 bzero((void *)(buffer + logInfoLength), 3321 (round_page(logInfoLength) - logInfoLength)); 3322 memcpy(buffer, logInfo, logInfoLength); 3323 *logInfoOut = buffer; 3324 *logInfoLengthOut = logInfoLength; 3325 } 3326 } 3327 3328 result = kOSReturnSuccess; 3329 finish: 3330 OSSafeReleaseNULL(serializer); 3331 return result; 3332 } 3333 3334 #if PRAGMA_MARK 3335 #pragma mark Instance Management Methods 3336 #endif 3337 /********************************************************************* 3338 *********************************************************************/ 3339 OSKext * 3340 OSKext::lookupKextWithIdentifier(const char * kextIdentifier) 3341 { 3342 OSKext * foundKext = NULL; 3343 3344 IORecursiveLockLock(sKextLock); 3345 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 3346 if (foundKext) { 3347 foundKext->retain(); 3348 } 3349 IORecursiveLockUnlock(sKextLock); 3350 3351 return foundKext; 3352 } 3353 3354 /********************************************************************* 3355 *********************************************************************/ 3356 OSKext * 3357 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier) 3358 { 3359 return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy()); 3360 } 3361 3362 /********************************************************************* 3363 *********************************************************************/ 3364 OSKext * 3365 OSKext::lookupKextWithLoadTag(uint32_t aTag) 3366 { 3367 OSKext * foundKext = NULL; // returned 3368 uint32_t i, j; 3369 OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts}; 3370 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 3371 3372 IORecursiveLockLock(sKextLock); 3373 3374 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 3375 for (i = 0; i < count[j]; i++) { 3376 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 3377 if (thisKext->getLoadTag() == aTag) { 3378 foundKext = thisKext; 3379 foundKext->retain(); 3380 goto finish; 3381 } 3382 } 3383 } 3384 3385 finish: 3386 IORecursiveLockUnlock(sKextLock); 3387 3388 return foundKext; 3389 } 3390 3391 /********************************************************************* 3392 *********************************************************************/ 3393 OSKext * 3394 OSKext::lookupKextWithAddress(vm_address_t address) 3395 { 3396 OSKext * foundKext = NULL; // returned 3397 uint32_t count, i; 3398 3399 IORecursiveLockLock(sKextLock); 3400 3401 count = sLoadedKexts->getCount(); 3402 for (i = 0; i < count; i++) { 3403 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 3404 if (thisKext->linkedExecutable) { 3405 vm_address_t kext_start = 3406 (vm_address_t)thisKext->linkedExecutable->getBytesNoCopy(); 3407 vm_address_t kext_end = kext_start + 3408 thisKext->linkedExecutable->getLength(); 3409 if ((kext_start <= address) && (address < kext_end)) { 3410 foundKext = thisKext; 3411 foundKext->retain(); 3412 goto finish; 3413 } 3414 } 3415 } 3416 3417 count = sLoadedDriverKitKexts->getCount(); 3418 for (i = 0; i < count; i++) { 3419 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i)); 3420 /* 3421 * DriverKitKexts do not have a linkedExecutable, 3422 * so we "fake" their address with the LoadTag 3423 */ 3424 if (thisKext->getLoadTag() == address) { 3425 foundKext = thisKext; 3426 foundKext->retain(); 3427 } 3428 } 3429 3430 finish: 3431 IORecursiveLockUnlock(sKextLock); 3432 3433 return foundKext; 3434 } 3435 3436 OSData * 3437 OSKext::copyKextUUIDForAddress(OSNumber *address) 3438 { 3439 OSData * uuid = NULL; 3440 OSKextActiveAccount * active; 3441 OSKext * kext = NULL; 3442 uint32_t baseIdx; 3443 uint32_t lim; 3444 uint32_t count, i; 3445 3446 if (!address) { 3447 return NULL; 3448 } 3449 3450 uintptr_t addr = ml_static_slide((uintptr_t)address->unsigned64BitValue()); 3451 3452 #if CONFIG_MACF 3453 /* Is the calling process allowed to query kext info? */ 3454 if (current_task() != kernel_task) { 3455 int macCheckResult = 0; 3456 kauth_cred_t cred = NULL; 3457 3458 cred = kauth_cred_get_with_ref(); 3459 macCheckResult = mac_kext_check_query(cred); 3460 kauth_cred_unref(&cred); 3461 3462 if (macCheckResult != 0) { 3463 OSKextLog(/* kext */ NULL, 3464 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 3465 "Failed to query kext UUID (MAC policy error 0x%x).", 3466 macCheckResult); 3467 return NULL; 3468 } 3469 } 3470 #endif 3471 3472 IOSimpleLockLock(sKextAccountsLock); 3473 // bsearch sKextAccounts list 3474 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 3475 active = &sKextAccounts[baseIdx + (lim >> 1)]; 3476 if ((addr >= active->address) && (addr < active->address_end)) { 3477 kext = active->account->kext; 3478 if (kext) { 3479 kext->retain(); 3480 } 3481 break; 3482 } else if (addr > active->address) { 3483 // move right 3484 baseIdx += (lim >> 1) + 1; 3485 lim--; 3486 } 3487 // else move left 3488 } 3489 IOSimpleLockUnlock(sKextAccountsLock); 3490 3491 if (!kext) { 3492 /* 3493 * Maybe it is a Dext. 3494 * DriverKit userspace executables do not have a kernel linkedExecutable, 3495 * so we "fake" their address range with the LoadTag. 3496 * 3497 * This is supposed to be used for logging reasons only. When logd 3498 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we 3499 * remove it here before checking it against the LoadTag. 3500 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line. 3501 */ 3502 addr = (uintptr_t)address->unsigned64BitValue() & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT); 3503 IORecursiveLockLock(sKextLock); 3504 count = sLoadedDriverKitKexts->getCount(); 3505 for (i = 0; i < count; i++) { 3506 OSKext * thisKext = NULL; 3507 3508 thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i)); 3509 if (!thisKext) { 3510 continue; 3511 } 3512 if (thisKext->getLoadTag() == addr) { 3513 kext = thisKext; 3514 kext->retain(); 3515 break; 3516 } 3517 } 3518 IORecursiveLockUnlock(sKextLock); 3519 } 3520 3521 if (kext) { 3522 uuid = kext->copyTextUUID(); 3523 kext->release(); 3524 } else if (((vm_offset_t)addr >= vm_kernel_stext) && ((vm_offset_t)addr < vm_kernel_etext)) { 3525 uuid = sKernelKext->copyTextUUID(); 3526 } 3527 3528 return uuid; 3529 } 3530 3531 /********************************************************************* 3532 *********************************************************************/ 3533 OSKext * 3534 OSKext::lookupKextWithUUID(uuid_t wanted) 3535 { 3536 OSKext * foundKext = NULL; // returned 3537 uint32_t j, i; 3538 OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts}; 3539 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 3540 3541 3542 IORecursiveLockLock(sKextLock); 3543 3544 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 3545 for (i = 0; i < count[j]; i++) { 3546 OSKext * thisKext = NULL; 3547 3548 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 3549 if (!thisKext) { 3550 continue; 3551 } 3552 3553 OSData *uuid_data = thisKext->copyUUID(); 3554 if (!uuid_data) { 3555 continue; 3556 } 3557 3558 uuid_t uuid; 3559 memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 3560 uuid_data->release(); 3561 3562 if (0 == uuid_compare(wanted, uuid)) { 3563 foundKext = thisKext; 3564 foundKext->retain(); 3565 goto finish; 3566 } 3567 } 3568 } 3569 finish: 3570 IORecursiveLockUnlock(sKextLock); 3571 3572 return foundKext; 3573 } 3574 3575 3576 3577 3578 /********************************************************************* 3579 *********************************************************************/ 3580 /* static */ 3581 bool 3582 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier) 3583 { 3584 bool result = false; 3585 OSKext * foundKext = NULL; // returned 3586 3587 IORecursiveLockLock(sKextLock); 3588 3589 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 3590 if (foundKext && foundKext->isLoaded()) { 3591 result = true; 3592 } 3593 3594 IORecursiveLockUnlock(sKextLock); 3595 3596 return result; 3597 } 3598 3599 /********************************************************************* 3600 * xxx - should spawn a separate thread so a kext can safely have 3601 * xxx - itself unloaded. 3602 *********************************************************************/ 3603 /* static */ 3604 OSReturn 3605 OSKext::removeKext( 3606 OSKext * aKext, 3607 #if CONFIG_EMBEDDED 3608 __unused 3609 #endif 3610 bool terminateServicesAndRemovePersonalitiesFlag) 3611 { 3612 #if CONFIG_EMBEDDED 3613 OSKextLog(aKext, 3614 kOSKextLogErrorLevel | 3615 kOSKextLogKextBookkeepingFlag, 3616 "removeKext() called for %s, not supported on embedded", 3617 aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext"); 3618 3619 return kOSReturnSuccess; 3620 #else /* CONFIG_EMBEDDED */ 3621 3622 OSReturn result = kOSKextReturnInUse; 3623 OSKext * checkKext = NULL; // do not release 3624 #if CONFIG_MACF 3625 int macCheckResult = 0; 3626 kauth_cred_t cred = NULL; 3627 #endif 3628 3629 IORecursiveLockLock(sKextLock); 3630 3631 /* If the kext has no identifier, it failed to init 3632 * so isn't in sKextsByID and it isn't loaded. 3633 */ 3634 if (!aKext->getIdentifier()) { 3635 result = kOSReturnSuccess; 3636 goto finish; 3637 } 3638 3639 checkKext = OSDynamicCast(OSKext, 3640 sKextsByID->getObject(aKext->getIdentifier())); 3641 if (checkKext != aKext) { 3642 result = kOSKextReturnNotFound; 3643 goto finish; 3644 } 3645 3646 if (aKext->isLoaded()) { 3647 #if CONFIG_MACF 3648 if (current_task() != kernel_task) { 3649 cred = kauth_cred_get_with_ref(); 3650 macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString()); 3651 kauth_cred_unref(&cred); 3652 } 3653 3654 if (macCheckResult != 0) { 3655 result = kOSReturnError; 3656 OSKextLog(aKext, 3657 kOSKextLogErrorLevel | 3658 kOSKextLogKextBookkeepingFlag, 3659 "Failed to remove kext %s (MAC policy error 0x%x).", 3660 aKext->getIdentifierCString(), macCheckResult); 3661 goto finish; 3662 } 3663 #endif 3664 3665 /* make sure there are no resource requests in flight - 17187548 */ 3666 if (aKext->countRequestCallbacks()) { 3667 goto finish; 3668 } 3669 3670 /* If we are terminating, send the request to the IOCatalogue 3671 * (which will actually call us right back but that's ok we have 3672 * a recursive lock don't you know) but do not ask the IOCatalogue 3673 * to call back with an unload, we'll do that right here. 3674 */ 3675 if (terminateServicesAndRemovePersonalitiesFlag) { 3676 result = gIOCatalogue->terminateDriversForModule( 3677 aKext->getIdentifierCString(), /* unload */ false); 3678 if (result != kOSReturnSuccess) { 3679 OSKextLog(aKext, 3680 kOSKextLogErrorLevel | 3681 kOSKextLogKextBookkeepingFlag, 3682 "Can't remove kext %s; services failed to terminate - 0x%x.", 3683 aKext->getIdentifierCString(), result); 3684 goto finish; 3685 } 3686 } 3687 3688 result = aKext->unload(); 3689 if (result != kOSReturnSuccess) { 3690 goto finish; 3691 } 3692 } 3693 3694 /* Remove personalities as requested. This is a bit redundant for a loaded 3695 * kext as IOCatalogue::terminateDriversForModule() removes driver 3696 * personalities, but it doesn't restart matching, which we always want 3697 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures 3698 * that happens. 3699 */ 3700 if (terminateServicesAndRemovePersonalitiesFlag) { 3701 aKext->removePersonalitiesFromCatalog(); 3702 } 3703 3704 OSKextLog(aKext, 3705 kOSKextLogProgressLevel | 3706 kOSKextLogKextBookkeepingFlag, 3707 "Removing kext %s.", 3708 aKext->getIdentifierCString()); 3709 3710 sKextsByID->removeObject(aKext->getIdentifier()); 3711 result = kOSReturnSuccess; 3712 3713 finish: 3714 IORecursiveLockUnlock(sKextLock); 3715 return result; 3716 #endif /* CONFIG_EMBEDDED */ 3717 } 3718 3719 /********************************************************************* 3720 *********************************************************************/ 3721 /* static */ 3722 OSReturn 3723 OSKext::removeKextWithIdentifier( 3724 const char * kextIdentifier, 3725 bool terminateServicesAndRemovePersonalitiesFlag) 3726 { 3727 OSReturn result = kOSReturnError; 3728 3729 IORecursiveLockLock(sKextLock); 3730 3731 OSKext * aKext = OSDynamicCast(OSKext, 3732 sKextsByID->getObject(kextIdentifier)); 3733 if (!aKext) { 3734 result = kOSKextReturnNotFound; 3735 OSKextLog(/* kext */ NULL, 3736 kOSKextLogErrorLevel | 3737 kOSKextLogKextBookkeepingFlag, 3738 "Can't remove kext %s - not found.", 3739 kextIdentifier); 3740 goto finish; 3741 } 3742 3743 result = OSKext::removeKext(aKext, 3744 terminateServicesAndRemovePersonalitiesFlag); 3745 3746 finish: 3747 IORecursiveLockUnlock(sKextLock); 3748 3749 return result; 3750 } 3751 3752 /********************************************************************* 3753 *********************************************************************/ 3754 /* static */ 3755 OSReturn 3756 OSKext::removeKextWithLoadTag( 3757 OSKextLoadTag loadTag, 3758 bool terminateServicesAndRemovePersonalitiesFlag) 3759 { 3760 OSReturn result = kOSReturnError; 3761 OSKext * foundKext = NULL; 3762 uint32_t i, j; 3763 OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts}; 3764 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 3765 3766 3767 IORecursiveLockLock(sKextLock); 3768 3769 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 3770 for (i = 0; i < count[j]; i++) { 3771 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 3772 if (thisKext->loadTag == loadTag) { 3773 foundKext = thisKext; 3774 break; 3775 } 3776 } 3777 } 3778 3779 if (!foundKext) { 3780 result = kOSKextReturnNotFound; 3781 OSKextLog(/* kext */ NULL, 3782 kOSKextLogErrorLevel | 3783 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 3784 "Can't remove kext with load tag %d - not found.", 3785 loadTag); 3786 goto finish; 3787 } 3788 3789 result = OSKext::removeKext(foundKext, 3790 terminateServicesAndRemovePersonalitiesFlag); 3791 3792 finish: 3793 IORecursiveLockUnlock(sKextLock); 3794 3795 return result; 3796 } 3797 3798 /********************************************************************* 3799 *********************************************************************/ 3800 OSDictionary * 3801 OSKext::copyKexts(void) 3802 { 3803 OSDictionary * result; 3804 3805 IORecursiveLockLock(sKextLock); 3806 result = OSDynamicCast(OSDictionary, sKextsByID->copyCollection()); 3807 IORecursiveLockUnlock(sKextLock); 3808 3809 return result; 3810 } 3811 3812 /********************************************************************* 3813 *********************************************************************/ 3814 #define BOOTER_KEXT_PREFIX "Driver-" 3815 3816 typedef struct _DeviceTreeBuffer { 3817 uint32_t paddr; 3818 uint32_t length; 3819 } _DeviceTreeBuffer; 3820 3821 /********************************************************************* 3822 * Create a dictionary of excluded kexts from the given booter data. 3823 *********************************************************************/ 3824 /* static */ 3825 void 3826 OSKext::createExcludeListFromBooterData( 3827 OSDictionary * theDictionary, 3828 OSCollectionIterator * theIterator ) 3829 { 3830 OSString * deviceTreeName = NULL;// do not release 3831 const _DeviceTreeBuffer * deviceTreeBuffer = NULL;// do not release 3832 char * booterDataPtr = NULL;// do not release 3833 _BooterKextFileInfo * kextFileInfo = NULL;// do not release 3834 char * infoDictAddr = NULL;// do not release 3835 OSObject * parsedXML = NULL;// must release 3836 OSDictionary * theInfoDict = NULL;// do not release 3837 3838 theIterator->reset(); 3839 3840 /* look for AppleKextExcludeList.kext */ 3841 while ((deviceTreeName = 3842 OSDynamicCast(OSString, theIterator->getNextObject()))) { 3843 const char * devTreeNameCString; 3844 OSData * deviceTreeEntry; 3845 OSString * myBundleID;// do not release 3846 3847 OSSafeReleaseNULL(parsedXML); 3848 3849 deviceTreeEntry = 3850 OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName)); 3851 if (!deviceTreeEntry) { 3852 continue; 3853 } 3854 3855 /* Make sure it is a kext */ 3856 devTreeNameCString = deviceTreeName->getCStringNoCopy(); 3857 if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX, 3858 (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) { 3859 OSKextLog(NULL, 3860 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 3861 "\"%s\" not a kext", 3862 devTreeNameCString); 3863 continue; 3864 } 3865 3866 deviceTreeBuffer = (const _DeviceTreeBuffer *) 3867 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer)); 3868 if (!deviceTreeBuffer) { 3869 continue; 3870 } 3871 3872 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr); 3873 if (!booterDataPtr) { 3874 continue; 3875 } 3876 3877 kextFileInfo = (_BooterKextFileInfo *) booterDataPtr; 3878 if (!kextFileInfo->infoDictPhysAddr || 3879 !kextFileInfo->infoDictLength) { 3880 continue; 3881 } 3882 3883 infoDictAddr = (char *) 3884 ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 3885 if (!infoDictAddr) { 3886 continue; 3887 } 3888 3889 parsedXML = OSUnserializeXML(infoDictAddr); 3890 if (!parsedXML) { 3891 continue; 3892 } 3893 3894 theInfoDict = OSDynamicCast(OSDictionary, parsedXML); 3895 if (!theInfoDict) { 3896 continue; 3897 } 3898 3899 myBundleID = 3900 OSDynamicCast(OSString, 3901 theInfoDict->getObject(kCFBundleIdentifierKey)); 3902 if (myBundleID && 3903 strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) { 3904 boolean_t updated = updateExcludeList(theInfoDict); 3905 if (!updated) { 3906 /* 25322874 */ 3907 panic("Missing OSKextExcludeList dictionary\n"); 3908 } 3909 break; 3910 } 3911 } // while ( (deviceTreeName = ...) ) 3912 3913 OSSafeReleaseNULL(parsedXML); 3914 return; 3915 } 3916 3917 /********************************************************************* 3918 * Create a dictionary of excluded kexts from the given prelink 3919 * info (kernelcache). 3920 *********************************************************************/ 3921 /* static */ 3922 void 3923 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray ) 3924 { 3925 OSDictionary * myInfoDict = NULL;// do not release 3926 OSString * myBundleID; // do not release 3927 u_int i; 3928 3929 /* Find com.apple.driver.KextExcludeList. */ 3930 for (i = 0; i < theInfoArray->getCount(); i++) { 3931 myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i)); 3932 if (!myInfoDict) { 3933 continue; 3934 } 3935 myBundleID = 3936 OSDynamicCast(OSString, 3937 myInfoDict->getObject(kCFBundleIdentifierKey)); 3938 if (myBundleID && 3939 strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) { 3940 boolean_t updated = updateExcludeList(myInfoDict); 3941 if (!updated) { 3942 /* 25322874 */ 3943 panic("Missing OSKextExcludeList dictionary\n"); 3944 } 3945 break; 3946 } 3947 } // for (i = 0; i < theInfoArray->getCount()... 3948 3949 return; 3950 } 3951 3952 /* static */ 3953 boolean_t 3954 OSKext::updateExcludeList(OSDictionary *infoDict) 3955 { 3956 OSDictionary *myTempDict = NULL; // do not free 3957 OSString *myTempString = NULL;// do not free 3958 OSKextVersion newVersion = 0; 3959 boolean_t updated = false; 3960 3961 if (!infoDict) { 3962 return false; 3963 } 3964 3965 myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList")); 3966 if (!myTempDict) { 3967 return false; 3968 } 3969 3970 myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey)); 3971 if (!myTempString) { 3972 return false; 3973 } 3974 3975 newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy()); 3976 if (newVersion == 0) { 3977 return false; 3978 } 3979 3980 IORecursiveLockLock(sKextLock); 3981 3982 if (newVersion > sExcludeListVersion) { 3983 OSSafeReleaseNULL(sExcludeListByID); 3984 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0); 3985 sExcludeListVersion = newVersion; 3986 updated = true; 3987 } 3988 3989 IORecursiveLockUnlock(sKextLock); 3990 return updated; 3991 } 3992 3993 #if PRAGMA_MARK 3994 #pragma mark Accessors 3995 #endif 3996 /********************************************************************* 3997 *********************************************************************/ 3998 const OSSymbol * 3999 OSKext::getIdentifier(void) 4000 { 4001 return bundleID; 4002 } 4003 4004 /********************************************************************* 4005 * A kext must have a bundle identifier to even survive initialization; 4006 * this is guaranteed to exist past then. 4007 *********************************************************************/ 4008 const char * 4009 OSKext::getIdentifierCString(void) 4010 { 4011 return bundleID->getCStringNoCopy(); 4012 } 4013 4014 /********************************************************************* 4015 *********************************************************************/ 4016 OSKextVersion 4017 OSKext::getVersion(void) 4018 { 4019 return version; 4020 } 4021 4022 /********************************************************************* 4023 *********************************************************************/ 4024 OSKextVersion 4025 OSKext::getCompatibleVersion(void) 4026 { 4027 return compatibleVersion; 4028 } 4029 4030 /********************************************************************* 4031 *********************************************************************/ 4032 bool 4033 OSKext::isLibrary(void) 4034 { 4035 return getCompatibleVersion() > 0; 4036 } 4037 4038 /********************************************************************* 4039 *********************************************************************/ 4040 bool 4041 OSKext::isCompatibleWithVersion(OSKextVersion aVersion) 4042 { 4043 if ((compatibleVersion > -1 && version > -1) && 4044 (compatibleVersion <= version && aVersion <= version)) { 4045 return true; 4046 } 4047 return false; 4048 } 4049 4050 /********************************************************************* 4051 *********************************************************************/ 4052 bool 4053 OSKext::declaresExecutable(void) 4054 { 4055 if (isDriverKit()) { 4056 return false; 4057 } 4058 return getPropertyForHostArch(kCFBundleExecutableKey) != NULL; 4059 } 4060 4061 /********************************************************************* 4062 *********************************************************************/ 4063 OSData * 4064 OSKext::getExecutable(void) 4065 { 4066 OSData * result = NULL; 4067 OSData * extractedExecutable = NULL; // must release 4068 OSData * mkextExecutableRef = NULL;// do not release 4069 4070 if (flags.builtin) { 4071 return sKernelKext->linkedExecutable; 4072 } 4073 4074 result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey)); 4075 if (result) { 4076 goto finish; 4077 } 4078 4079 mkextExecutableRef = OSDynamicCast(OSData, 4080 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey)); 4081 4082 if (mkextExecutableRef) { 4083 MkextEntryRef * mkextEntryRef = (MkextEntryRef *) 4084 mkextExecutableRef->getBytesNoCopy(); 4085 uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext); 4086 if (mkextVersion == MKEXT_VERS_2) { 4087 mkext2_file_entry * fileinfo = 4088 (mkext2_file_entry *)mkextEntryRef->fileinfo; 4089 uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo); 4090 uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo); 4091 extractedExecutable = extractMkext2FileData( 4092 MKEXT2_GET_ENTRY_DATA(fileinfo), "executable", 4093 compressedSize, fullSize); 4094 } else { 4095 OSKextLog(this, kOSKextLogErrorLevel | 4096 kOSKextLogArchiveFlag, 4097 "Kext %s - unknown mkext version 0x%x for executable.", 4098 getIdentifierCString(), mkextVersion); 4099 } 4100 4101 /* Regardless of success, remove the mkext executable, 4102 * and drop one reference on the mkext. (setExecutable() does not 4103 * replace, it removes, or panics if asked to replace.) 4104 */ 4105 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 4106 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 4107 4108 if (extractedExecutable && extractedExecutable->getLength()) { 4109 if (!setExecutable(extractedExecutable)) { 4110 goto finish; 4111 } 4112 result = extractedExecutable; 4113 } else { 4114 goto finish; 4115 } 4116 } 4117 4118 finish: 4119 4120 OSSafeReleaseNULL(extractedExecutable); 4121 4122 return result; 4123 } 4124 4125 /********************************************************************* 4126 *********************************************************************/ 4127 bool 4128 OSKext::isInterface(void) 4129 { 4130 return flags.interface; 4131 } 4132 4133 /********************************************************************* 4134 *********************************************************************/ 4135 bool 4136 OSKext::isKernel(void) 4137 { 4138 return this == sKernelKext; 4139 } 4140 4141 /********************************************************************* 4142 *********************************************************************/ 4143 bool 4144 OSKext::isKernelComponent(void) 4145 { 4146 return flags.kernelComponent ? true : false; 4147 } 4148 4149 /********************************************************************* 4150 *********************************************************************/ 4151 bool 4152 OSKext::isExecutable(void) 4153 { 4154 return !isKernel() && !isInterface() && declaresExecutable(); 4155 } 4156 4157 /********************************************************************* 4158 * We might want to check this recursively for all dependencies, 4159 * since a subtree of dependencies could get loaded before we hit 4160 * a dependency that isn't safe-boot-loadable. 4161 * 4162 * xxx - Might want to return false if OSBundleEnableKextLogging or 4163 * OSBundleDebugLevel 4164 * or IOKitDebug is nonzero too (we used to do that, but I don't see 4165 * the point except it's usually development drivers, which might 4166 * cause panics on startup, that have those properties). Heh; could 4167 * use a "kx" boot-arg! 4168 *********************************************************************/ 4169 bool 4170 OSKext::isLoadableInSafeBoot(void) 4171 { 4172 bool result = false; 4173 OSString * required = NULL; // do not release 4174 4175 if (isKernel()) { 4176 result = true; 4177 goto finish; 4178 } 4179 4180 required = OSDynamicCast(OSString, 4181 getPropertyForHostArch(kOSBundleRequiredKey)); 4182 if (!required) { 4183 goto finish; 4184 } 4185 if (required->isEqualTo(kOSBundleRequiredRoot) || 4186 required->isEqualTo(kOSBundleRequiredLocalRoot) || 4187 required->isEqualTo(kOSBundleRequiredNetworkRoot) || 4188 required->isEqualTo(kOSBundleRequiredSafeBoot) || 4189 required->isEqualTo(kOSBundleRequiredConsole)) { 4190 result = true; 4191 } 4192 4193 finish: 4194 return result; 4195 } 4196 4197 /********************************************************************* 4198 *********************************************************************/ 4199 bool 4200 OSKext::isPrelinked(void) 4201 { 4202 return flags.prelinked ? true : false; 4203 } 4204 4205 /********************************************************************* 4206 *********************************************************************/ 4207 bool 4208 OSKext::isLoaded(void) 4209 { 4210 return flags.loaded ? true : false; 4211 } 4212 4213 /********************************************************************* 4214 *********************************************************************/ 4215 bool 4216 OSKext::isStarted(void) 4217 { 4218 return flags.started ? true : false; 4219 } 4220 4221 /********************************************************************* 4222 *********************************************************************/ 4223 bool 4224 OSKext::isCPPInitialized(void) 4225 { 4226 return flags.CPPInitialized; 4227 } 4228 4229 /********************************************************************* 4230 *********************************************************************/ 4231 void 4232 OSKext::setCPPInitialized(bool initialized) 4233 { 4234 flags.CPPInitialized = initialized; 4235 } 4236 4237 /********************************************************************* 4238 *********************************************************************/ 4239 uint32_t 4240 OSKext::getLoadTag(void) 4241 { 4242 return loadTag; 4243 } 4244 4245 /********************************************************************* 4246 *********************************************************************/ 4247 void 4248 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize) 4249 { 4250 if (linkedExecutable) { 4251 *loadSize = linkedExecutable->getLength(); 4252 4253 /* If we have a kmod_info struct, calculated the wired size 4254 * from that. Otherwise it's the full load size. 4255 */ 4256 if (kmod_info) { 4257 *wiredSize = *loadSize - kmod_info->hdr_size; 4258 } else { 4259 *wiredSize = *loadSize; 4260 } 4261 } else { 4262 *wiredSize = 0; 4263 *loadSize = 0; 4264 } 4265 } 4266 4267 /********************************************************************* 4268 *********************************************************************/ 4269 OSData * 4270 OSKext::copyUUID(void) 4271 { 4272 OSData * result = NULL; 4273 OSData * theExecutable = NULL;// do not release 4274 const kernel_mach_header_t * header; 4275 4276 /* An interface kext doesn't have a linked executable with an LC_UUID, 4277 * we create one when it's linked. 4278 */ 4279 if (interfaceUUID) { 4280 result = interfaceUUID; 4281 result->retain(); 4282 goto finish; 4283 } 4284 4285 if (flags.builtin || isInterface()) { 4286 return sKernelKext->copyUUID(); 4287 } 4288 4289 if (isDriverKit() && infoDict) { 4290 if (driverKitUUID) { 4291 driverKitUUID->retain(); 4292 return driverKitUUID; 4293 } else { 4294 return NULL; 4295 } 4296 } 4297 4298 /* For real kexts, try to get the UUID from the linked executable, 4299 * or if is hasn't been linked yet, the unrelocated executable. 4300 */ 4301 theExecutable = linkedExecutable; 4302 if (!theExecutable) { 4303 theExecutable = getExecutable(); 4304 } 4305 4306 if (!theExecutable) { 4307 goto finish; 4308 } 4309 4310 header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy(); 4311 result = copyMachoUUID(header); 4312 4313 finish: 4314 return result; 4315 } 4316 4317 /********************************************************************* 4318 *********************************************************************/ 4319 OSData * 4320 OSKext::copyTextUUID(void) 4321 { 4322 if (flags.builtin) { 4323 return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address); 4324 } 4325 return copyUUID(); 4326 } 4327 4328 /********************************************************************* 4329 *********************************************************************/ 4330 OSData * 4331 OSKext::copyMachoUUID(const kernel_mach_header_t * header) 4332 { 4333 OSData * result = NULL; 4334 const struct load_command * load_cmd = NULL; 4335 const struct uuid_command * uuid_cmd = NULL; 4336 uint32_t i; 4337 4338 load_cmd = (const struct load_command *)&header[1]; 4339 4340 if (header->magic != MH_MAGIC_KERNEL) { 4341 OSKextLog(NULL, 4342 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4343 "%s: bad header %p", 4344 __func__, 4345 header); 4346 goto finish; 4347 } 4348 4349 for (i = 0; i < header->ncmds; i++) { 4350 if (load_cmd->cmd == LC_UUID) { 4351 uuid_cmd = (struct uuid_command *)load_cmd; 4352 result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid)); 4353 goto finish; 4354 } 4355 load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize); 4356 } 4357 4358 finish: 4359 return result; 4360 } 4361 4362 void 4363 OSKext::setDriverKitUUID(OSData *uuid) 4364 { 4365 if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) { 4366 OSSafeReleaseNULL(uuid); 4367 } 4368 } 4369 4370 /********************************************************************* 4371 *********************************************************************/ 4372 #if defined (__arm__) 4373 #include <arm/arch.h> 4374 #endif 4375 4376 #if defined (__x86_64__) 4377 #define ARCHNAME "x86_64" 4378 #elif defined (__arm64__) 4379 #define ARCHNAME "arm64" 4380 #elif defined (__arm__) 4381 4382 #if defined (__ARM_ARCH_7S__) 4383 #define ARCHNAME "armv7s" 4384 #elif defined (__ARM_ARCH_7F__) 4385 #define ARCHNAME "armv7f" 4386 #elif defined (__ARM_ARCH_7K__) 4387 #define ARCHNAME "armv7k" 4388 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */ 4389 #define ARCHNAME "armv7" 4390 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */ 4391 #define ARCHNAME "armv6" 4392 #endif 4393 4394 #elif defined (__arm64__) 4395 #define ARCHNAME "arm64" 4396 #else 4397 #error architecture not supported 4398 #endif 4399 4400 #define ARCH_SEPARATOR_CHAR '_' 4401 4402 static char * 4403 makeHostArchKey(const char * key, uint32_t * keySizeOut) 4404 { 4405 char * result = NULL; 4406 uint32_t keyLength = strlen(key); 4407 uint32_t keySize; 4408 4409 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'. 4410 */ 4411 keySize = 1 + 1 + strlen(key) + strlen(ARCHNAME); 4412 result = (char *)kalloc_tag(keySize, VM_KERN_MEMORY_OSKEXT); 4413 if (!result) { 4414 goto finish; 4415 } 4416 strlcpy(result, key, keySize); 4417 result[keyLength++] = ARCH_SEPARATOR_CHAR; 4418 result[keyLength] = '\0'; 4419 strlcat(result, ARCHNAME, keySize); 4420 *keySizeOut = keySize; 4421 4422 finish: 4423 return result; 4424 } 4425 4426 /********************************************************************* 4427 *********************************************************************/ 4428 OSObject * 4429 OSKext::getPropertyForHostArch(const char * key) 4430 { 4431 OSObject * result = NULL;// do not release 4432 uint32_t hostArchKeySize = 0; 4433 char * hostArchKey = NULL;// must kfree 4434 4435 if (!key || !infoDict) { 4436 goto finish; 4437 } 4438 4439 /* Some properties are not allowed to be arch-variant: 4440 * - Any CFBundle... property. 4441 * - OSBundleIsInterface. 4442 * - OSKernelResource. 4443 */ 4444 if (STRING_HAS_PREFIX(key, "OS") || 4445 STRING_HAS_PREFIX(key, "IO")) { 4446 hostArchKey = makeHostArchKey(key, &hostArchKeySize); 4447 if (!hostArchKey) { 4448 OSKextLog(/* kext (this isn't about a kext) */ NULL, 4449 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4450 "Allocation failure."); 4451 goto finish; 4452 } 4453 result = infoDict->getObject(hostArchKey); 4454 } 4455 4456 if (!result) { 4457 result = infoDict->getObject(key); 4458 } 4459 4460 finish: 4461 if (hostArchKey) { 4462 kfree(hostArchKey, hostArchKeySize); 4463 } 4464 return result; 4465 } 4466 4467 #if PRAGMA_MARK 4468 #pragma mark Load/Start/Stop/Unload 4469 #endif 4470 4471 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n') 4472 4473 /********************************************************************* 4474 * sExcludeListByID is a dictionary with keys / values of: 4475 * key = bundleID string of kext we will not allow to load 4476 * value = version string(s) of the kext that is to be denied loading. 4477 * The version strings can be comma delimited. For example if kext 4478 * com.foocompany.fookext has two versions that we want to deny 4479 * loading then the version strings might look like: 4480 * 1.0.0, 1.0.1 4481 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will 4482 * not load the kext. 4483 * 4484 * Value may also be in the form of "LE 2.0.0" (version numbers 4485 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version 4486 * number less than 2.0.0 will not load) 4487 * 4488 * NOTE - we cannot use the characters "<=" or "<" because we have code 4489 * that serializes plists and treats '<' as a special character. 4490 *********************************************************************/ 4491 bool 4492 OSKext::isInExcludeList(void) 4493 { 4494 OSString * versionString = NULL;// do not release 4495 char * versionCString = NULL;// do not free 4496 size_t i; 4497 boolean_t wantLessThan = false; 4498 boolean_t wantLessThanEqualTo = false; 4499 boolean_t isInExcludeList = true; 4500 char myBuffer[32]; 4501 4502 IORecursiveLockLock(sKextLock); 4503 4504 if (!sExcludeListByID) { 4505 isInExcludeList = false; 4506 } else { 4507 /* look up by bundleID in our exclude list and if found get version 4508 * string (or strings) that we will not allow to load 4509 */ 4510 versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID)); 4511 if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) { 4512 isInExcludeList = false; 4513 } 4514 } 4515 4516 IORecursiveLockUnlock(sKextLock); 4517 4518 if (!isInExcludeList) { 4519 return false; 4520 } 4521 4522 /* parse version strings */ 4523 versionCString = (char *) versionString->getCStringNoCopy(); 4524 4525 /* look for "LT" or "LE" form of version string, must be in first two 4526 * positions. 4527 */ 4528 if (*versionCString == 'L' && *(versionCString + 1) == 'T') { 4529 wantLessThan = true; 4530 versionCString += 2; 4531 } else if (*versionCString == 'L' && *(versionCString + 1) == 'E') { 4532 wantLessThanEqualTo = true; 4533 versionCString += 2; 4534 } 4535 4536 for (i = 0; *versionCString != 0x00; versionCString++) { 4537 /* skip whitespace */ 4538 if (isWhiteSpace(*versionCString)) { 4539 continue; 4540 } 4541 4542 /* peek ahead for version string separator or null terminator */ 4543 if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) { 4544 /* OK, we have a version string */ 4545 myBuffer[i++] = *versionCString; 4546 myBuffer[i] = 0x00; 4547 4548 OSKextVersion excludeVers; 4549 excludeVers = OSKextParseVersionString(myBuffer); 4550 4551 if (wantLessThanEqualTo) { 4552 if (version <= excludeVers) { 4553 return true; 4554 } 4555 } else if (wantLessThan) { 4556 if (version < excludeVers) { 4557 return true; 4558 } 4559 } else if (version == excludeVers) { 4560 return true; 4561 } 4562 4563 /* reset for the next (if any) version string */ 4564 i = 0; 4565 wantLessThan = false; 4566 wantLessThanEqualTo = false; 4567 } else { 4568 /* save valid version character */ 4569 myBuffer[i++] = *versionCString; 4570 4571 /* make sure bogus version string doesn't overrun local buffer */ 4572 if (i >= sizeof(myBuffer)) { 4573 break; 4574 } 4575 } 4576 } 4577 4578 return false; 4579 } 4580 4581 /********************************************************************* 4582 *********************************************************************/ 4583 /* static */ 4584 OSReturn 4585 OSKext::loadKextWithIdentifier( 4586 const char * kextIdentifierCString, 4587 Boolean allowDeferFlag, 4588 Boolean delayAutounloadFlag, 4589 OSKextExcludeLevel startOpt, 4590 OSKextExcludeLevel startMatchingOpt, 4591 OSArray * personalityNames) 4592 { 4593 OSReturn result = kOSReturnError; 4594 OSString * kextIdentifier = NULL; // must release 4595 4596 kextIdentifier = OSString::withCString(kextIdentifierCString); 4597 if (!kextIdentifier) { 4598 result = kOSKextReturnNoMemory; 4599 goto finish; 4600 } 4601 result = OSKext::loadKextWithIdentifier(kextIdentifier, 4602 NULL /* kextRef */, 4603 allowDeferFlag, delayAutounloadFlag, 4604 startOpt, startMatchingOpt, personalityNames); 4605 4606 finish: 4607 OSSafeReleaseNULL(kextIdentifier); 4608 return result; 4609 } 4610 4611 /********************************************************************* 4612 *********************************************************************/ 4613 OSReturn 4614 OSKext::loadKextWithIdentifier( 4615 OSString * kextIdentifier, 4616 OSObject ** kextRef, 4617 Boolean allowDeferFlag, 4618 Boolean delayAutounloadFlag, 4619 OSKextExcludeLevel startOpt, 4620 OSKextExcludeLevel startMatchingOpt, 4621 OSArray * personalityNames) 4622 { 4623 OSReturn result = kOSReturnError; 4624 OSReturn pingResult = kOSReturnError; 4625 OSKext * theKext = NULL;// do not release 4626 OSDictionary * loadRequest = NULL;// must release 4627 const OSSymbol * kextIdentifierSymbol = NULL;// must release 4628 4629 if (kextRef) { 4630 *kextRef = NULL; 4631 } 4632 4633 IORecursiveLockLock(sKextLock); 4634 4635 if (!kextIdentifier) { 4636 result = kOSKextReturnInvalidArgument; 4637 goto finish; 4638 } 4639 4640 OSKext::recordIdentifierRequest(kextIdentifier); 4641 4642 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 4643 if (!theKext) { 4644 if (!allowDeferFlag) { 4645 OSKextLog(/* kext */ NULL, 4646 kOSKextLogErrorLevel | 4647 kOSKextLogLoadFlag, 4648 "Can't load kext %s - not found.", 4649 kextIdentifier->getCStringNoCopy()); 4650 goto finish; 4651 } 4652 4653 if (!sKernelRequestsEnabled) { 4654 OSKextLog(theKext, 4655 kOSKextLogErrorLevel | 4656 kOSKextLogLoadFlag, 4657 "Can't load kext %s - requests to user space are disabled.", 4658 kextIdentifier->getCStringNoCopy()); 4659 result = kOSKextReturnDisabled; 4660 goto finish; 4661 } 4662 4663 /* Create a new request unless one is already sitting 4664 * in sKernelRequests for this bundle identifier 4665 */ 4666 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 4667 if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) { 4668 result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad, 4669 &loadRequest); 4670 if (result != kOSReturnSuccess) { 4671 goto finish; 4672 } 4673 if (!_OSKextSetRequestArgument(loadRequest, 4674 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 4675 result = kOSKextReturnNoMemory; 4676 goto finish; 4677 } 4678 if (!sKernelRequests->setObject(loadRequest)) { 4679 result = kOSKextReturnNoMemory; 4680 goto finish; 4681 } 4682 4683 if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol)) { 4684 result = kOSKextReturnNoMemory; 4685 goto finish; 4686 } 4687 4688 OSKextLog(theKext, 4689 kOSKextLogDebugLevel | 4690 kOSKextLogLoadFlag, 4691 "Kext %s not found; queued load request to user space.", 4692 kextIdentifier->getCStringNoCopy()); 4693 } 4694 4695 pingResult = OSKext::pingKextd(); 4696 if (pingResult == kOSKextReturnDisabled) { 4697 OSKextLog(/* kext */ NULL, 4698 ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) | 4699 kOSKextLogLoadFlag, 4700 "Kext %s might not load - kextd is currently unavailable.", 4701 kextIdentifier->getCStringNoCopy()); 4702 } 4703 4704 result = kOSKextReturnDeferred; 4705 goto finish; 4706 } 4707 4708 result = theKext->load(startOpt, startMatchingOpt, personalityNames); 4709 4710 if (result != kOSReturnSuccess) { 4711 OSKextLog(theKext, 4712 kOSKextLogErrorLevel | 4713 kOSKextLogLoadFlag, 4714 "Failed to load kext %s (error 0x%x).", 4715 kextIdentifier->getCStringNoCopy(), (int)result); 4716 4717 OSKext::removeKext(theKext, 4718 /* terminateService/removePersonalities */ true); 4719 goto finish; 4720 } 4721 4722 if (delayAutounloadFlag) { 4723 OSKextLog(theKext, 4724 kOSKextLogProgressLevel | 4725 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 4726 "Setting delayed autounload for %s.", 4727 kextIdentifier->getCStringNoCopy()); 4728 theKext->flags.delayAutounload = 1; 4729 } 4730 4731 finish: 4732 OSSafeReleaseNULL(loadRequest); 4733 OSSafeReleaseNULL(kextIdentifierSymbol); 4734 4735 if ((kOSReturnSuccess == result) && kextRef) { 4736 theKext->retain(); 4737 theKext->matchingRefCount++; 4738 *kextRef = theKext; 4739 } 4740 4741 IORecursiveLockUnlock(sKextLock); 4742 4743 return result; 4744 } 4745 /********************************************************************* 4746 *********************************************************************/ 4747 /* static */ 4748 void 4749 OSKext::dropMatchingReferences( 4750 OSSet * kexts) 4751 { 4752 IORecursiveLockLock(sKextLock); 4753 kexts->iterateObjects(^bool (OSObject * obj) { 4754 OSKext * thisKext = OSDynamicCast(OSKext, obj); 4755 if (!thisKext) { 4756 return false; 4757 } 4758 thisKext->matchingRefCount--; 4759 return false; 4760 }); 4761 IORecursiveLockUnlock(sKextLock); 4762 } 4763 4764 /********************************************************************* 4765 *********************************************************************/ 4766 /* static */ 4767 void 4768 OSKext::recordIdentifierRequest( 4769 OSString * kextIdentifier) 4770 { 4771 const OSSymbol * kextIdentifierSymbol = NULL; // must release 4772 bool fail = false; 4773 4774 if (!sAllKextLoadIdentifiers || !kextIdentifier) { 4775 goto finish; 4776 } 4777 4778 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 4779 if (!kextIdentifierSymbol) { 4780 // xxx - this is really a basic alloc failure 4781 fail = true; 4782 goto finish; 4783 } 4784 4785 IORecursiveLockLock(sKextLock); 4786 if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) { 4787 if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol)) { 4788 fail = true; 4789 } else { 4790 // xxx - need to find a way to associate this whole func w/the kext 4791 OSKextLog(/* kext */ NULL, 4792 // xxx - check level 4793 kOSKextLogStepLevel | 4794 kOSKextLogArchiveFlag, 4795 "Recorded kext %s as a candidate for inclusion in prelinked kernel.", 4796 kextIdentifier->getCStringNoCopy()); 4797 } 4798 } 4799 IORecursiveLockUnlock(sKextLock); 4800 4801 finish: 4802 4803 if (fail) { 4804 OSKextLog(/* kext */ NULL, 4805 kOSKextLogErrorLevel | 4806 kOSKextLogArchiveFlag, 4807 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.", 4808 kextIdentifier->getCStringNoCopy()); 4809 } 4810 OSSafeReleaseNULL(kextIdentifierSymbol); 4811 return; 4812 } 4813 4814 /********************************************************************* 4815 *********************************************************************/ 4816 OSReturn 4817 OSKext::load( 4818 OSKextExcludeLevel startOpt, 4819 OSKextExcludeLevel startMatchingOpt, 4820 OSArray * personalityNames) 4821 { 4822 OSReturn result = kOSReturnError; 4823 kern_return_t kxldResult; 4824 OSKextExcludeLevel dependenciesStartOpt = startOpt; 4825 OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt; 4826 unsigned int i, count; 4827 Boolean alreadyLoaded = false; 4828 OSKext * lastLoadedKext = NULL; 4829 4830 if (isInExcludeList()) { 4831 OSKextLog(this, 4832 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | 4833 kOSKextLogLoadFlag, 4834 "Kext %s is in exclude list, not loadable", 4835 getIdentifierCString()); 4836 4837 result = kOSKextReturnNotLoadable; 4838 goto finish; 4839 } 4840 4841 if (isLoaded()) { 4842 alreadyLoaded = true; 4843 result = kOSReturnSuccess; 4844 4845 OSKextLog(this, 4846 kOSKextLogDebugLevel | 4847 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 4848 "Kext %s is already loaded.", 4849 getIdentifierCString()); 4850 goto loaded; 4851 } 4852 4853 #if CONFIG_MACF 4854 if (current_task() != kernel_task) { 4855 int macCheckResult = 0; 4856 kauth_cred_t cred = NULL; 4857 4858 cred = kauth_cred_get_with_ref(); 4859 macCheckResult = mac_kext_check_load(cred, getIdentifierCString()); 4860 kauth_cred_unref(&cred); 4861 4862 if (macCheckResult != 0) { 4863 result = kOSReturnError; 4864 OSKextLog(this, 4865 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 4866 "Failed to load kext %s (MAC policy error 0x%x).", 4867 getIdentifierCString(), macCheckResult); 4868 goto finish; 4869 } 4870 } 4871 #endif 4872 4873 if (!sLoadEnabled) { 4874 OSKextLog(this, 4875 kOSKextLogErrorLevel | 4876 kOSKextLogLoadFlag, 4877 "Kext loading is disabled (attempt to load kext %s).", 4878 getIdentifierCString()); 4879 result = kOSKextReturnDisabled; 4880 goto finish; 4881 } 4882 4883 /* If we've pushed the next available load tag to the invalid value, 4884 * we can't load any more kexts. 4885 */ 4886 if (sNextLoadTag == kOSKextInvalidLoadTag) { 4887 OSKextLog(this, 4888 kOSKextLogErrorLevel | 4889 kOSKextLogLoadFlag, 4890 "Can't load kext %s - no more load tags to assign.", 4891 getIdentifierCString()); 4892 result = kOSKextReturnNoResources; 4893 goto finish; 4894 } 4895 4896 /* This is a bit of a hack, because we shouldn't be handling 4897 * personalities within the load function. 4898 */ 4899 if (!declaresExecutable()) { 4900 /* There is a special case where a non-executable kext can be loaded: the 4901 * AppleKextExcludeList. Detect that special kext by bundle identifier and 4902 * load its metadata into the global data structures, if appropriate 4903 */ 4904 if (strcmp(getIdentifierCString(), "com.apple.driver.KextExcludeList") == 0) { 4905 boolean_t updated = updateExcludeList(infoDict); 4906 if (updated) { 4907 OSKextLog(this, 4908 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 4909 "KextExcludeList was updated to version: %lld", sExcludeListVersion); 4910 } 4911 } 4912 4913 if (isDriverKit()) { 4914 if (loadTag == 0) { 4915 sLoadedDriverKitKexts->setObject(this); 4916 loadTag = sNextLoadTag++; 4917 } 4918 } 4919 result = kOSReturnSuccess; 4920 goto loaded; 4921 } 4922 4923 /* Are we in safe boot? 4924 */ 4925 if (sSafeBoot && !isLoadableInSafeBoot()) { 4926 OSKextLog(this, 4927 kOSKextLogErrorLevel | 4928 kOSKextLogLoadFlag, 4929 "Can't load kext %s - not loadable during safe boot.", 4930 getIdentifierCString()); 4931 result = kOSKextReturnBootLevel; 4932 goto finish; 4933 } 4934 4935 OSKextLog(this, 4936 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 4937 "Loading kext %s.", 4938 getIdentifierCString()); 4939 4940 if (!sKxldContext) { 4941 kxldResult = kxld_create_context(&sKxldContext, &kern_allocate, 4942 &kxld_log_callback, /* Flags */ (KXLDFlags) 0, 4943 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0); 4944 if (kxldResult) { 4945 OSKextLog(this, 4946 kOSKextLogErrorLevel | 4947 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 4948 "Can't load kext %s - failed to create link context.", 4949 getIdentifierCString()); 4950 result = kOSKextReturnNoMemory; 4951 goto finish; 4952 } 4953 } 4954 4955 /* We only need to resolve dependencies once for the whole graph, but 4956 * resolveDependencies will just return if there's no work to do, so it's 4957 * safe to call it more than once. 4958 */ 4959 if (!resolveDependencies()) { 4960 // xxx - check resolveDependencies() for log msg 4961 OSKextLog(this, 4962 kOSKextLogErrorLevel | 4963 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 4964 "Can't load kext %s - failed to resolve library dependencies.", 4965 getIdentifierCString()); 4966 result = kOSKextReturnDependencies; 4967 goto finish; 4968 } 4969 4970 /* If we are excluding just the kext being loaded now (and not its 4971 * dependencies), drop the exclusion level to none so dependencies 4972 * start and/or add their personalities. 4973 */ 4974 if (dependenciesStartOpt == kOSKextExcludeKext) { 4975 dependenciesStartOpt = kOSKextExcludeNone; 4976 } 4977 4978 if (dependenciesStartMatchingOpt == kOSKextExcludeKext) { 4979 dependenciesStartMatchingOpt = kOSKextExcludeNone; 4980 } 4981 4982 /* Load the dependencies, recursively. 4983 */ 4984 count = getNumDependencies(); 4985 for (i = 0; i < count; i++) { 4986 OSKext * dependency = OSDynamicCast(OSKext, 4987 dependencies->getObject(i)); 4988 if (dependency == NULL) { 4989 OSKextLog(this, 4990 kOSKextLogErrorLevel | 4991 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 4992 "Internal error loading kext %s; dependency disappeared.", 4993 getIdentifierCString()); 4994 result = kOSKextReturnInternalError; 4995 goto finish; 4996 } 4997 4998 /* Dependencies must be started accorting to the opt, 4999 * but not given the personality names of the main kext. 5000 */ 5001 result = dependency->load(dependenciesStartOpt, 5002 dependenciesStartMatchingOpt, 5003 /* personalityNames */ NULL); 5004 if (result != KERN_SUCCESS) { 5005 OSKextLog(this, 5006 kOSKextLogErrorLevel | 5007 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 5008 "Dependency %s of kext %s failed to load.", 5009 dependency->getIdentifierCString(), 5010 getIdentifierCString()); 5011 5012 OSKext::removeKext(dependency, 5013 /* terminateService/removePersonalities */ true); 5014 result = kOSKextReturnDependencyLoadError; 5015 5016 goto finish; 5017 } 5018 } 5019 5020 result = loadExecutable(); 5021 if (result != KERN_SUCCESS) { 5022 goto finish; 5023 } 5024 5025 pendingPgoHead.next = &pendingPgoHead; 5026 pendingPgoHead.prev = &pendingPgoHead; 5027 5028 // The kernel PRNG is not initialized when the first kext is 5029 // loaded, so use early random 5030 uuid_generate_early_random(instance_uuid); 5031 account = IONew(OSKextAccount, 1); 5032 if (!account) { 5033 result = KERN_MEMORY_ERROR; 5034 goto finish; 5035 } 5036 bzero(account, sizeof(*account)); 5037 account->loadTag = kmod_info->id; 5038 account->site.refcount = 0; 5039 account->site.flags = VM_TAG_KMOD; 5040 account->kext = this; 5041 if (gIOSurfaceIdentifier == bundleID) { 5042 vm_tag_alloc(&account->site); 5043 gIOSurfaceTag = account->site.tag; 5044 } 5045 5046 flags.loaded = true; 5047 5048 /* Add the kext to the list of loaded kexts and update the kmod_info 5049 * struct to point to that of the last loaded kext (which is the way 5050 * it's always been done, though I'd rather do them in order now). 5051 */ 5052 lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 5053 sLoadedKexts->setObject(this); 5054 5055 /* Keep the kernel itself out of the kmod list. 5056 */ 5057 if (lastLoadedKext->isKernel()) { 5058 lastLoadedKext = NULL; 5059 } 5060 5061 if (lastLoadedKext) { 5062 kmod_info->next = lastLoadedKext->kmod_info; 5063 } 5064 5065 notifyKextLoadObservers(this, kmod_info); 5066 5067 /* Make the global kmod list point at the just-loaded kext. Note that the 5068 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard, 5069 * although we do report it in kextstat these days by using the newer 5070 * OSArray of loaded kexts, which does contain it. 5071 * 5072 * (The OSKext object representing the kernel doesn't even have a kmod_info 5073 * struct, though I suppose we could stick a pointer to it from the 5074 * static struct in OSRuntime.cpp.) 5075 */ 5076 kmod = kmod_info; 5077 5078 /* Save the list of loaded kexts in case we panic. 5079 */ 5080 OSKext::saveLoadedKextPanicList(); 5081 5082 if (isExecutable()) { 5083 OSKext::updateLoadedKextSummaries(); 5084 savePanicString(/* isLoading */ true); 5085 5086 #if CONFIG_DTRACE 5087 registerWithDTrace(); 5088 #else 5089 jettisonLinkeditSegment(); 5090 #endif /* CONFIG_DTRACE */ 5091 5092 #if !VM_MAPPED_KEXTS 5093 /* If there is a page (or more) worth of padding after the end 5094 * of the last data section but before the end of the data segment 5095 * then free it in the same manner the LinkeditSegment is freed 5096 */ 5097 jettisonDATASegmentPadding(); 5098 #endif 5099 } 5100 5101 loaded: 5102 if (isExecutable() && !flags.started) { 5103 if (startOpt == kOSKextExcludeNone) { 5104 result = start(); 5105 if (result != kOSReturnSuccess) { 5106 OSKextLog(this, 5107 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5108 "Kext %s start failed (result 0x%x).", 5109 getIdentifierCString(), result); 5110 result = kOSKextReturnStartStopError; 5111 } 5112 } 5113 } 5114 5115 /* If not excluding matching, send the personalities to the kernel. 5116 * This never affects the result of the load operation. 5117 * This is a bit of a hack, because we shouldn't be handling 5118 * personalities within the load function. 5119 */ 5120 if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) { 5121 result = sendPersonalitiesToCatalog(true, personalityNames); 5122 } 5123 5124 finish: 5125 5126 if (result != kOSReturnSuccess) { 5127 OSKextLog(this, 5128 kOSKextLogErrorLevel | 5129 kOSKextLogLoadFlag, 5130 "Kext %s failed to load (0x%x).", 5131 getIdentifierCString(), (int)result); 5132 } else if (!alreadyLoaded) { 5133 OSKextLog(this, 5134 kOSKextLogProgressLevel | 5135 kOSKextLogLoadFlag, 5136 "Kext %s loaded.", 5137 getIdentifierCString()); 5138 5139 queueKextNotification(kKextRequestPredicateLoadNotification, 5140 OSDynamicCast(OSString, bundleID)); 5141 } 5142 return result; 5143 } 5144 5145 /********************************************************************* 5146 * 5147 *********************************************************************/ 5148 static char * 5149 strdup(const char * string) 5150 { 5151 char * result = NULL; 5152 size_t size; 5153 5154 if (!string) { 5155 goto finish; 5156 } 5157 5158 size = 1 + strlen(string); 5159 result = (char *)kalloc_tag(size, VM_KERN_MEMORY_OSKEXT); 5160 if (!result) { 5161 goto finish; 5162 } 5163 5164 memcpy(result, string, size); 5165 5166 finish: 5167 return result; 5168 } 5169 5170 /********************************************************************* 5171 * 5172 *********************************************************************/ 5173 5174 kernel_section_t * 5175 OSKext::lookupSection(const char *segname, const char *secname) 5176 { 5177 kernel_section_t * found_section = NULL; 5178 kernel_mach_header_t * mh = NULL; 5179 kernel_segment_command_t * seg = NULL; 5180 kernel_section_t * sec = NULL; 5181 5182 if (!linkedExecutable) { 5183 return NULL; 5184 } 5185 5186 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 5187 5188 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 5189 if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) { 5190 continue; 5191 } 5192 5193 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 5194 if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) { 5195 found_section = sec; 5196 goto out; 5197 } 5198 } 5199 } 5200 5201 out: 5202 return found_section; 5203 } 5204 5205 /********************************************************************* 5206 * 5207 *********************************************************************/ 5208 5209 OSReturn 5210 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides) 5211 { 5212 OSReturn result = kOSKextReturnBadData; 5213 kernel_mach_header_t * mh = NULL; 5214 kernel_segment_command_t * seg = NULL; 5215 kernel_segment_command_t * linkeditSeg = NULL; 5216 kernel_section_t * sec = NULL; 5217 char * linkeditBase = NULL; 5218 bool haveLinkeditBase = false; 5219 char * relocBase = NULL; 5220 bool haveRelocBase = false; 5221 struct dysymtab_command * dysymtab = NULL; 5222 struct linkedit_data_command * segmentSplitInfo = NULL; 5223 struct symtab_command * symtab = NULL; 5224 kernel_nlist_t * sym = NULL; 5225 struct relocation_info * reloc = NULL; 5226 uint32_t i = 0; 5227 int reloc_size; 5228 vm_offset_t new_kextsize; 5229 5230 if (linkedExecutable == NULL || flags.builtin) { 5231 result = kOSReturnSuccess; 5232 goto finish; 5233 } 5234 5235 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 5236 segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO); 5237 5238 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 5239 if (!seg->vmaddr) { 5240 continue; 5241 } 5242 5243 seg->vmaddr = ml_static_slide(seg->vmaddr); 5244 5245 #if KASLR_KEXT_DEBUG 5246 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n", 5247 seg->segname, 5248 (unsigned long)ml_static_unslide(seg->vmaddr), 5249 (unsigned long)seg->vmaddr); 5250 #endif 5251 5252 if (!haveRelocBase) { 5253 relocBase = (char *) seg->vmaddr; 5254 haveRelocBase = true; 5255 } 5256 if (!strcmp(seg->segname, "__LINKEDIT")) { 5257 linkeditBase = (char *) seg->vmaddr - seg->fileoff; 5258 haveLinkeditBase = true; 5259 linkeditSeg = seg; 5260 } 5261 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 5262 sec->addr = ml_static_slide(sec->addr); 5263 5264 #if KASLR_KEXT_DEBUG 5265 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n", 5266 sec->sectname, 5267 (unsigned long)ml_static_unslide(sec->addr), 5268 (unsigned long)sec->addr); 5269 #endif 5270 } 5271 } 5272 5273 dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB); 5274 5275 symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB); 5276 5277 if (symtab != NULL && doCoalesedSlides == false) { 5278 /* Some pseudo-kexts have symbol tables without segments. 5279 * Ignore them. */ 5280 if (symtab->nsyms > 0 && haveLinkeditBase) { 5281 sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff); 5282 for (i = 0; i < symtab->nsyms; i++) { 5283 if (sym[i].n_type & N_STAB) { 5284 continue; 5285 } 5286 sym[i].n_value = ml_static_slide(sym[i].n_value); 5287 5288 #if KASLR_KEXT_DEBUG 5289 #define MAX_SYMS_TO_LOG 5 5290 if (i < MAX_SYMS_TO_LOG) { 5291 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n", 5292 (unsigned long)ml_static_unslide(sym[i].n_value), 5293 (unsigned long)sym[i].n_value); 5294 } 5295 #endif 5296 } 5297 } 5298 } 5299 5300 if (dysymtab != NULL && doCoalesedSlides == false) { 5301 if (dysymtab->nextrel > 0) { 5302 OSKextLog(this, 5303 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 5304 kOSKextLogLinkFlag, 5305 "Sliding kext %s: External relocations found.", 5306 getIdentifierCString()); 5307 goto finish; 5308 } 5309 5310 if (dysymtab->nlocrel > 0) { 5311 if (!haveLinkeditBase) { 5312 OSKextLog(this, 5313 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 5314 kOSKextLogLinkFlag, 5315 "Sliding kext %s: No linkedit segment.", 5316 getIdentifierCString()); 5317 goto finish; 5318 } 5319 5320 if (!haveRelocBase) { 5321 OSKextLog(this, 5322 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 5323 kOSKextLogLinkFlag, 5324 #if __x86_64__ 5325 "Sliding kext %s: No writable segments.", 5326 #else 5327 "Sliding kext %s: No segments.", 5328 #endif 5329 getIdentifierCString()); 5330 goto finish; 5331 } 5332 5333 reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff); 5334 reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info); 5335 5336 for (i = 0; i < dysymtab->nlocrel; i++) { 5337 if (reloc[i].r_extern != 0 5338 || reloc[i].r_type != 0 5339 || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2) 5340 ) { 5341 OSKextLog(this, 5342 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 5343 kOSKextLogLinkFlag, 5344 "Sliding kext %s: Unexpected relocation found.", 5345 getIdentifierCString()); 5346 goto finish; 5347 } 5348 if (reloc[i].r_pcrel != 0) { 5349 continue; 5350 } 5351 uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address); 5352 *relocAddr = ml_static_slide(*relocAddr); 5353 5354 #if KASLR_KEXT_DEBUG 5355 #define MAX_DYSYMS_TO_LOG 5 5356 if (i < MAX_DYSYMS_TO_LOG) { 5357 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n", 5358 (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))), 5359 (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address))); 5360 } 5361 #endif 5362 } 5363 5364 /* We should free these relocations, not just delete the reference to them. 5365 * <rdar://problem/10535549> Free relocations from PIE kexts. 5366 * 5367 * For now, we do not free LINKEDIT for kexts with split segments. 5368 */ 5369 new_kextsize = round_page(kmod_info->size - reloc_size); 5370 if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) { 5371 vm_offset_t endofkext = kmod_info->address + kmod_info->size; 5372 vm_offset_t new_endofkext = kmod_info->address + new_kextsize; 5373 vm_offset_t endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size); 5374 int bytes_remaining = endofkext - endofrelocInfo; 5375 OSData * new_osdata = NULL; 5376 5377 /* fix up symbol offsets if they are after the dsymtab local relocs */ 5378 if (symtab) { 5379 if (dysymtab->locreloff < symtab->symoff) { 5380 symtab->symoff -= reloc_size; 5381 } 5382 if (dysymtab->locreloff < symtab->stroff) { 5383 symtab->stroff -= reloc_size; 5384 } 5385 } 5386 if (dysymtab->locreloff < dysymtab->extreloff) { 5387 dysymtab->extreloff -= reloc_size; 5388 } 5389 5390 /* move data behind reloc info down to new offset */ 5391 if (endofrelocInfo < endofkext) { 5392 memcpy(reloc, (void *)endofrelocInfo, bytes_remaining); 5393 } 5394 5395 /* Create a new OSData for the smaller kext object and reflect 5396 * new linkedit segment size. 5397 */ 5398 linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size); 5399 linkeditSeg->filesize = linkeditSeg->vmsize; 5400 5401 new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, new_kextsize); 5402 if (new_osdata) { 5403 /* Fix up kmod info and linkedExecutable. 5404 */ 5405 kmod_info->size = new_kextsize; 5406 #if VM_MAPPED_KEXTS 5407 new_osdata->setDeallocFunction(osdata_kext_free); 5408 #else 5409 new_osdata->setDeallocFunction(osdata_phys_free); 5410 #endif 5411 linkedExecutable->setDeallocFunction(NULL); 5412 linkedExecutable->release(); 5413 linkedExecutable = new_osdata; 5414 5415 #if VM_MAPPED_KEXTS 5416 kext_free(new_endofkext, (endofkext - new_endofkext)); 5417 #else 5418 ml_static_mfree(new_endofkext, (endofkext - new_endofkext)); 5419 #endif 5420 } 5421 } 5422 dysymtab->nlocrel = 0; 5423 dysymtab->locreloff = 0; 5424 } 5425 } 5426 5427 result = kOSReturnSuccess; 5428 finish: 5429 return result; 5430 } 5431 5432 /********************************************************************* 5433 * called only by load() 5434 *********************************************************************/ 5435 OSReturn 5436 OSKext::loadExecutable() 5437 { 5438 OSReturn result = kOSReturnError; 5439 kern_return_t kxldResult; 5440 KXLDDependency * kxlddeps = NULL;// must kfree 5441 uint32_t num_kxlddeps = 0; 5442 OSArray * linkDependencies = NULL;// must release 5443 uint32_t numDirectDependencies = 0; 5444 uint32_t num_kmod_refs = 0; 5445 struct mach_header ** kxldHeaderPtr = NULL;// do not free 5446 struct mach_header * kxld_header = NULL;// xxx - need to free here? 5447 OSData * theExecutable = NULL;// do not release 5448 OSString * versString = NULL;// do not release 5449 const char * versCString = NULL;// do not free 5450 const char * string = NULL;// do not free 5451 unsigned int i; 5452 5453 /* We need the version string for a variety of bits below. 5454 */ 5455 versString = OSDynamicCast(OSString, 5456 getPropertyForHostArch(kCFBundleVersionKey)); 5457 if (!versString) { 5458 goto finish; 5459 } 5460 versCString = versString->getCStringNoCopy(); 5461 5462 if (isKernelComponent()) { 5463 if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) { 5464 if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) { 5465 OSKextLog(this, 5466 kOSKextLogErrorLevel | 5467 kOSKextLogLoadFlag, 5468 "Kernel component %s has incorrect version %s; " 5469 "expected %s.", 5470 getIdentifierCString(), 5471 versCString, KERNEL6_VERSION); 5472 result = kOSKextReturnInternalError; 5473 goto finish; 5474 } else if (strcmp(versCString, osrelease)) { 5475 OSKextLog(this, 5476 kOSKextLogErrorLevel | 5477 kOSKextLogLoadFlag, 5478 "Kernel component %s has incorrect version %s; " 5479 "expected %s.", 5480 getIdentifierCString(), 5481 versCString, osrelease); 5482 result = kOSKextReturnInternalError; 5483 goto finish; 5484 } 5485 } 5486 } 5487 5488 if (isPrelinked()) { 5489 goto register_kmod; 5490 } 5491 5492 /* <rdar://problem/21444003> all callers must be entitled */ 5493 if (FALSE == IOTaskHasEntitlement(current_task(), kOSKextManagementEntitlement)) { 5494 OSKextLog(this, 5495 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5496 "Not entitled to link kext '%s'", 5497 getIdentifierCString()); 5498 result = kOSKextReturnNotPrivileged; 5499 goto finish; 5500 } 5501 5502 theExecutable = getExecutable(); 5503 if (!theExecutable) { 5504 if (declaresExecutable()) { 5505 OSKextLog(this, 5506 kOSKextLogErrorLevel | 5507 kOSKextLogLoadFlag, 5508 "Can't load kext %s - executable is missing.", 5509 getIdentifierCString()); 5510 result = kOSKextReturnValidation; 5511 goto finish; 5512 } 5513 goto register_kmod; 5514 } 5515 5516 if (isInterface()) { 5517 OSData *executableCopy = OSData::withData(theExecutable); 5518 setLinkedExecutable(executableCopy); 5519 executableCopy->release(); 5520 goto register_kmod; 5521 } 5522 5523 numDirectDependencies = getNumDependencies(); 5524 5525 if (flags.hasBleedthrough) { 5526 linkDependencies = dependencies; 5527 linkDependencies->retain(); 5528 } else { 5529 linkDependencies = OSArray::withArray(dependencies); 5530 if (!linkDependencies) { 5531 OSKextLog(this, 5532 kOSKextLogErrorLevel | 5533 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 5534 "Can't allocate link dependencies to load kext %s.", 5535 getIdentifierCString()); 5536 goto finish; 5537 } 5538 5539 for (i = 0; i < numDirectDependencies; ++i) { 5540 OSKext * dependencyKext = OSDynamicCast(OSKext, 5541 dependencies->getObject(i)); 5542 dependencyKext->addBleedthroughDependencies(linkDependencies); 5543 } 5544 } 5545 5546 num_kxlddeps = linkDependencies->getCount(); 5547 if (!num_kxlddeps) { 5548 OSKextLog(this, 5549 kOSKextLogErrorLevel | 5550 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 5551 "Can't load kext %s - it has no library dependencies.", 5552 getIdentifierCString()); 5553 goto finish; 5554 } 5555 5556 kxlddeps = (KXLDDependency *)kalloc_tag(num_kxlddeps * sizeof(*kxlddeps), VM_KERN_MEMORY_OSKEXT); 5557 if (!kxlddeps) { 5558 OSKextLog(this, 5559 kOSKextLogErrorLevel | 5560 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 5561 "Can't allocate link context to load kext %s.", 5562 getIdentifierCString()); 5563 goto finish; 5564 } 5565 bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps)); 5566 5567 for (i = 0; i < num_kxlddeps; ++i) { 5568 OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i)); 5569 5570 if (dependency->isInterface()) { 5571 OSKext *interfaceTargetKext = NULL; 5572 OSData * interfaceTarget = NULL; 5573 5574 if (dependency->isKernelComponent()) { 5575 interfaceTargetKext = sKernelKext; 5576 interfaceTarget = sKernelKext->linkedExecutable; 5577 } else { 5578 interfaceTargetKext = OSDynamicCast(OSKext, 5579 dependency->dependencies->getObject(0)); 5580 5581 interfaceTarget = interfaceTargetKext->linkedExecutable; 5582 } 5583 5584 if (!interfaceTarget) { 5585 // panic? 5586 goto finish; 5587 } 5588 5589 /* The names set here aren't actually logged yet <rdar://problem/7941514>, 5590 * it will be useful to have them in the debugger. 5591 * strdup() failing isn't critical right here so we don't check that. 5592 */ 5593 kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy(); 5594 kxlddeps[i].kext_size = interfaceTarget->getLength(); 5595 kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString()); 5596 5597 kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 5598 kxlddeps[i].interface_size = dependency->linkedExecutable->getLength(); 5599 kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString()); 5600 } else { 5601 kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 5602 kxlddeps[i].kext_size = dependency->linkedExecutable->getLength(); 5603 kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString()); 5604 } 5605 5606 kxlddeps[i].is_direct_dependency = (i < numDirectDependencies); 5607 } 5608 5609 kxldHeaderPtr = &kxld_header; 5610 5611 #if DEBUG 5612 OSKextLog(this, 5613 kOSKextLogExplicitLevel | 5614 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 5615 "Kext %s - calling kxld_link_file:\n" 5616 " kxld_context: %p\n" 5617 " executable: %p executable_length: %d\n" 5618 " user_data: %p\n" 5619 " kxld_dependencies: %p num_dependencies: %d\n" 5620 " kxld_header_ptr: %p kmod_info_ptr: %p\n", 5621 getIdentifierCString(), sKxldContext, 5622 theExecutable->getBytesNoCopy(), theExecutable->getLength(), 5623 this, kxlddeps, num_kxlddeps, 5624 kxldHeaderPtr, &kmod_info); 5625 #endif 5626 5627 /* After this call, the linkedExecutable instance variable 5628 * should exist. 5629 */ 5630 kxldResult = kxld_link_file(sKxldContext, 5631 (u_char *)theExecutable->getBytesNoCopy(), 5632 theExecutable->getLength(), 5633 getIdentifierCString(), this, kxlddeps, num_kxlddeps, 5634 (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info); 5635 5636 if (kxldResult != KERN_SUCCESS) { 5637 // xxx - add kxldResult here? 5638 OSKextLog(this, 5639 kOSKextLogErrorLevel | 5640 kOSKextLogLoadFlag, 5641 "Can't load kext %s - link failed.", 5642 getIdentifierCString()); 5643 result = kOSKextReturnLinkError; 5644 goto finish; 5645 } 5646 5647 /* We've written data & instructions into kernel memory, so flush the data 5648 * cache and invalidate the instruction cache. 5649 * I/D caches are coherent on x86 5650 */ 5651 #if !defined(__i386__) && !defined(__x86_64__) 5652 flush_dcache(kmod_info->address, kmod_info->size, false); 5653 invalidate_icache(kmod_info->address, kmod_info->size, false); 5654 #endif 5655 register_kmod: 5656 5657 if (isInterface()) { 5658 /* Whip up a fake kmod_info entry for the interface kext. 5659 */ 5660 kmod_info = (kmod_info_t *)kalloc_tag(sizeof(kmod_info_t), VM_KERN_MEMORY_OSKEXT); 5661 if (!kmod_info) { 5662 result = KERN_MEMORY_ERROR; 5663 goto finish; 5664 } 5665 5666 /* A pseudokext has almost nothing in its kmod_info struct. 5667 */ 5668 bzero(kmod_info, sizeof(kmod_info_t)); 5669 5670 kmod_info->info_version = KMOD_INFO_VERSION; 5671 5672 /* An interface kext doesn't have a linkedExecutable, so save a 5673 * copy of the UUID out of the original executable via copyUUID() 5674 * while we still have the original executable. 5675 */ 5676 interfaceUUID = copyUUID(); 5677 } 5678 5679 kmod_info->id = loadTag = sNextLoadTag++; 5680 kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid). 5681 5682 /* Stamp the bundle ID and version from the OSKext over anything 5683 * resident inside the kmod_info. 5684 */ 5685 string = getIdentifierCString(); 5686 strlcpy(kmod_info->name, string, sizeof(kmod_info->name)); 5687 5688 string = versCString; 5689 strlcpy(kmod_info->version, string, sizeof(kmod_info->version)); 5690 5691 /* Add the dependencies' kmod_info structs as kmod_references. 5692 */ 5693 num_kmod_refs = getNumDependencies(); 5694 if (num_kmod_refs) { 5695 kmod_info->reference_list = (kmod_reference_t *)kalloc_tag( 5696 num_kmod_refs * sizeof(kmod_reference_t), VM_KERN_MEMORY_OSKEXT); 5697 if (!kmod_info->reference_list) { 5698 result = KERN_MEMORY_ERROR; 5699 goto finish; 5700 } 5701 bzero(kmod_info->reference_list, 5702 num_kmod_refs * sizeof(kmod_reference_t)); 5703 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 5704 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 5705 OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex)); 5706 ref->info = refKext->kmod_info; 5707 ref->info->reference_count++; 5708 5709 if (refIndex + 1 < num_kmod_refs) { 5710 ref->next = kmod_info->reference_list + refIndex + 1; 5711 } 5712 } 5713 } 5714 5715 if (!isInterface() && linkedExecutable) { 5716 OSKextLog(this, 5717 kOSKextLogProgressLevel | 5718 kOSKextLogLoadFlag, 5719 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).", 5720 kmod_info->name, 5721 (unsigned)kmod_info->size / PAGE_SIZE, 5722 (unsigned long)ml_static_unslide(kmod_info->address), 5723 (unsigned)kmod_info->id); 5724 } 5725 5726 /* if prelinked, VM protections are already set */ 5727 result = setVMAttributes(!isPrelinked(), true); 5728 if (result != KERN_SUCCESS) { 5729 goto finish; 5730 } 5731 5732 #if KASAN 5733 if (linkedExecutable) { 5734 kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), 5735 linkedExecutable->getLength(), getIdentifierCString()); 5736 } 5737 #else 5738 if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) { 5739 OSKextLog(this, 5740 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5741 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n", 5742 getIdentifierCString() 5743 ); 5744 result = KERN_FAILURE; 5745 goto finish; 5746 } 5747 #endif 5748 5749 result = kOSReturnSuccess; 5750 5751 finish: 5752 OSSafeReleaseNULL(linkDependencies); 5753 5754 /* Clear up locally allocated dependency info. 5755 */ 5756 for (i = 0; i < num_kxlddeps; ++i) { 5757 size_t size; 5758 5759 if (kxlddeps[i].kext_name) { 5760 size = 1 + strlen(kxlddeps[i].kext_name); 5761 kfree(kxlddeps[i].kext_name, size); 5762 } 5763 if (kxlddeps[i].interface_name) { 5764 size = 1 + strlen(kxlddeps[i].interface_name); 5765 kfree(kxlddeps[i].interface_name, size); 5766 } 5767 } 5768 if (kxlddeps) { 5769 kfree(kxlddeps, (num_kxlddeps * sizeof(*kxlddeps))); 5770 } 5771 5772 /* We no longer need the unrelocated executable (which the linker 5773 * has altered anyhow). 5774 */ 5775 setExecutable(NULL); 5776 5777 if (result != kOSReturnSuccess) { 5778 OSKextLog(this, 5779 kOSKextLogErrorLevel | 5780 kOSKextLogLoadFlag, 5781 "Failed to load executable for kext %s.", 5782 getIdentifierCString()); 5783 5784 if (kmod_info && kmod_info->reference_list) { 5785 kfree(kmod_info->reference_list, 5786 num_kmod_refs * sizeof(kmod_reference_t)); 5787 } 5788 if (isInterface()) { 5789 kfree(kmod_info, sizeof(kmod_info_t)); 5790 } 5791 kmod_info = NULL; 5792 if (linkedExecutable) { 5793 linkedExecutable->release(); 5794 linkedExecutable = NULL; 5795 } 5796 } 5797 5798 return result; 5799 } 5800 5801 /********************************************************************* 5802 * The linkedit segment is used by the kext linker for dependency 5803 * resolution, and by dtrace for probe initialization. We can free it 5804 * for non-library kexts, since no kexts depend on non-library kexts 5805 * by definition, once dtrace has been initialized. 5806 *********************************************************************/ 5807 void 5808 OSKext::jettisonLinkeditSegment(void) 5809 { 5810 kernel_mach_header_t * machhdr = (kernel_mach_header_t *)kmod_info->address; 5811 kernel_segment_command_t * linkedit = NULL; 5812 vm_offset_t start; 5813 vm_size_t linkeditsize, kextsize; 5814 OSData * data = NULL; 5815 5816 #if NO_KEXTD 5817 /* We can free symbol tables for all embedded kexts because we don't 5818 * support runtime kext linking. 5819 */ 5820 if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 5821 #else 5822 if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 5823 #endif 5824 goto finish; 5825 } 5826 5827 /* Find the linkedit segment. If it's not the last segment, then freeing 5828 * it will fragment the kext into multiple VM regions, which OSKext is not 5829 * designed to handle, so we'll have to skip it. 5830 */ 5831 linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT); 5832 if (!linkedit) { 5833 goto finish; 5834 } 5835 5836 if (round_page(kmod_info->address + kmod_info->size) != 5837 round_page(linkedit->vmaddr + linkedit->vmsize)) { 5838 goto finish; 5839 } 5840 5841 /* Create a new OSData for the smaller kext object. 5842 */ 5843 linkeditsize = round_page(linkedit->vmsize); 5844 kextsize = kmod_info->size - linkeditsize; 5845 start = linkedit->vmaddr; 5846 5847 data = OSData::withBytesNoCopy((void *)kmod_info->address, kextsize); 5848 if (!data) { 5849 goto finish; 5850 } 5851 5852 /* Fix the kmod info and linkedExecutable. 5853 */ 5854 kmod_info->size = kextsize; 5855 5856 #if VM_MAPPED_KEXTS 5857 data->setDeallocFunction(osdata_kext_free); 5858 #else 5859 data->setDeallocFunction(osdata_phys_free); 5860 #endif 5861 linkedExecutable->setDeallocFunction(NULL); 5862 linkedExecutable->release(); 5863 linkedExecutable = data; 5864 flags.jettisonLinkeditSeg = 1; 5865 5866 /* Free the linkedit segment. 5867 */ 5868 #if VM_MAPPED_KEXTS 5869 kext_free(start, linkeditsize); 5870 #else 5871 ml_static_mfree(start, linkeditsize); 5872 #endif 5873 5874 finish: 5875 return; 5876 } 5877 5878 /********************************************************************* 5879 * If there are whole pages that are unused betweem the last section 5880 * of the DATA segment and the end of the DATA segment then we can free 5881 * them 5882 *********************************************************************/ 5883 void 5884 OSKext::jettisonDATASegmentPadding(void) 5885 { 5886 kernel_mach_header_t * mh; 5887 kernel_segment_command_t * dataSeg; 5888 kernel_section_t * sec, * lastSec; 5889 vm_offset_t dataSegEnd, lastSecEnd; 5890 vm_size_t padSize; 5891 5892 if (flags.builtin) { 5893 return; 5894 } 5895 mh = (kernel_mach_header_t *)kmod_info->address; 5896 5897 dataSeg = getsegbynamefromheader(mh, SEG_DATA); 5898 if (dataSeg == NULL) { 5899 return; 5900 } 5901 5902 lastSec = NULL; 5903 sec = firstsect(dataSeg); 5904 while (sec != NULL) { 5905 lastSec = sec; 5906 sec = nextsect(dataSeg, sec); 5907 } 5908 5909 if (lastSec == NULL) { 5910 return; 5911 } 5912 5913 if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) || 5914 (dataSeg->vmsize != round_page(dataSeg->vmsize))) { 5915 return; 5916 } 5917 5918 dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize; 5919 lastSecEnd = round_page(lastSec->addr + lastSec->size); 5920 5921 if (dataSegEnd <= lastSecEnd) { 5922 return; 5923 } 5924 5925 padSize = dataSegEnd - lastSecEnd; 5926 5927 if (padSize >= PAGE_SIZE) { 5928 #if VM_MAPPED_KEXTS 5929 kext_free(lastSecEnd, padSize); 5930 #else 5931 ml_static_mfree(lastSecEnd, padSize); 5932 #endif 5933 } 5934 } 5935 5936 /********************************************************************* 5937 *********************************************************************/ 5938 void 5939 OSKext::setLinkedExecutable(OSData * anExecutable) 5940 { 5941 if (linkedExecutable) { 5942 panic("Attempt to set linked executable on kext " 5943 "that already has one (%s).\n", 5944 getIdentifierCString()); 5945 } 5946 linkedExecutable = anExecutable; 5947 linkedExecutable->retain(); 5948 return; 5949 } 5950 5951 #if CONFIG_DTRACE 5952 /********************************************************************* 5953 * Go through all loaded kexts and tell them to register with dtrace. 5954 * The instance method only registers if necessary. 5955 *********************************************************************/ 5956 /* static */ 5957 void 5958 OSKext::registerKextsWithDTrace(void) 5959 { 5960 uint32_t count = sLoadedKexts->getCount(); 5961 uint32_t i; 5962 5963 IORecursiveLockLock(sKextLock); 5964 5965 for (i = 0; i < count; i++) { 5966 OSKext * thisKext = NULL;// do not release 5967 5968 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 5969 if (!thisKext || !thisKext->isExecutable()) { 5970 continue; 5971 } 5972 5973 thisKext->registerWithDTrace(); 5974 } 5975 5976 IORecursiveLockUnlock(sKextLock); 5977 5978 return; 5979 } 5980 5981 extern "C" { 5982 extern int (*dtrace_modload)(struct kmod_info *, uint32_t); 5983 extern int (*dtrace_modunload)(struct kmod_info *); 5984 }; 5985 5986 /********************************************************************* 5987 *********************************************************************/ 5988 void 5989 OSKext::registerWithDTrace(void) 5990 { 5991 /* Register kext with dtrace. A dtrace_modload failure should not 5992 * prevent a kext from loading, so we ignore the return code. 5993 */ 5994 if (!flags.dtraceInitialized && (dtrace_modload != NULL)) { 5995 uint32_t modflag = 0; 5996 OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit"); 5997 if (forceInit == kOSBooleanTrue) { 5998 modflag |= KMOD_DTRACE_FORCE_INIT; 5999 } 6000 if (flags.builtin) { 6001 modflag |= KMOD_DTRACE_STATIC_KEXT; 6002 } 6003 6004 (void)(*dtrace_modload)(kmod_info, modflag); 6005 flags.dtraceInitialized = true; 6006 jettisonLinkeditSegment(); 6007 } 6008 return; 6009 } 6010 /********************************************************************* 6011 *********************************************************************/ 6012 void 6013 OSKext::unregisterWithDTrace(void) 6014 { 6015 /* Unregister kext with dtrace. A dtrace_modunload failure should not 6016 * prevent a kext from loading, so we ignore the return code. 6017 */ 6018 if (flags.dtraceInitialized && (dtrace_modunload != NULL)) { 6019 (void)(*dtrace_modunload)(kmod_info); 6020 flags.dtraceInitialized = false; 6021 } 6022 return; 6023 } 6024 #endif /* CONFIG_DTRACE */ 6025 6026 6027 /********************************************************************* 6028 * called only by loadExecutable() 6029 *********************************************************************/ 6030 #if !VM_MAPPED_KEXTS 6031 #if defined(__arm__) || defined(__arm64__) 6032 static inline kern_return_t 6033 OSKext_protect( 6034 vm_map_t map, 6035 vm_map_offset_t start, 6036 vm_map_offset_t end, 6037 vm_prot_t new_prot, 6038 boolean_t set_max) 6039 { 6040 #pragma unused(map) 6041 assert(map == kernel_map); // we can handle KEXTs arising from the PRELINK segment and no others 6042 assert(start <= end); 6043 if (start >= end) { 6044 return KERN_SUCCESS; // Punt segments of length zero (e.g., headers) or less (i.e., blunders) 6045 } else if (set_max) { 6046 return KERN_SUCCESS; // Punt set_max, as there's no mechanism to record that state 6047 } else { 6048 return ml_static_protect(start, end - start, new_prot); 6049 } 6050 } 6051 6052 static inline kern_return_t 6053 OSKext_wire( 6054 vm_map_t map, 6055 vm_map_offset_t start, 6056 vm_map_offset_t end, 6057 vm_prot_t access_type, 6058 boolean_t user_wire) 6059 { 6060 #pragma unused(map,start,end,access_type,user_wire) 6061 return KERN_SUCCESS; // No-op as PRELINK kexts are cemented into physical memory at boot 6062 } 6063 #else 6064 #error Unrecognized architecture 6065 #endif 6066 #else 6067 static inline kern_return_t 6068 OSKext_protect( 6069 vm_map_t map, 6070 vm_map_offset_t start, 6071 vm_map_offset_t end, 6072 vm_prot_t new_prot, 6073 boolean_t set_max) 6074 { 6075 if (start == end) { // 10538581 6076 return KERN_SUCCESS; 6077 } 6078 return vm_map_protect(map, start, end, new_prot, set_max); 6079 } 6080 6081 static inline kern_return_t 6082 OSKext_wire( 6083 vm_map_t map, 6084 vm_map_offset_t start, 6085 vm_map_offset_t end, 6086 vm_prot_t access_type, 6087 boolean_t user_wire) 6088 { 6089 return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire); 6090 } 6091 #endif 6092 6093 OSReturn 6094 OSKext::setVMAttributes(bool protect, bool wire) 6095 { 6096 vm_map_t kext_map = NULL; 6097 kernel_segment_command_t * seg = NULL; 6098 vm_map_offset_t start = 0; 6099 vm_map_offset_t end = 0; 6100 OSReturn result = kOSReturnError; 6101 6102 if (isInterface() || !declaresExecutable() || flags.builtin) { 6103 result = kOSReturnSuccess; 6104 goto finish; 6105 } 6106 6107 /* Get the kext's vm map */ 6108 kext_map = kext_get_vm_map(kmod_info); 6109 if (!kext_map) { 6110 result = KERN_MEMORY_ERROR; 6111 goto finish; 6112 } 6113 6114 #if !VM_MAPPED_KEXTS 6115 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) { 6116 /* This is a split kext in a prelinked kernelcache; we'll let the 6117 * platform code take care of protecting it. It is already wired. 6118 */ 6119 /* TODO: Should this still allow protections for the first segment 6120 * to go through, in the event that we have a mix of split and 6121 * unsplit kexts? 6122 */ 6123 result = KERN_SUCCESS; 6124 goto finish; 6125 } 6126 #endif 6127 6128 /* Protect the headers as read-only; they do not need to be wired */ 6129 result = (protect) ? OSKext_protect(kext_map, kmod_info->address, 6130 kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE) 6131 : KERN_SUCCESS; 6132 if (result != KERN_SUCCESS) { 6133 goto finish; 6134 } 6135 6136 /* Set the VM protections and wire down each of the segments */ 6137 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 6138 while (seg) { 6139 #if __arm__ 6140 /* We build all ARM kexts, so we can ensure they are aligned */ 6141 assert((seg->vmaddr & PAGE_MASK) == 0); 6142 assert((seg->vmsize & PAGE_MASK) == 0); 6143 #endif 6144 6145 start = round_page(seg->vmaddr); 6146 end = trunc_page(seg->vmaddr + seg->vmsize); 6147 6148 if (protect) { 6149 result = OSKext_protect(kext_map, start, end, seg->maxprot, TRUE); 6150 if (result != KERN_SUCCESS) { 6151 OSKextLog(this, 6152 kOSKextLogErrorLevel | 6153 kOSKextLogLoadFlag, 6154 "Kext %s failed to set maximum VM protections " 6155 "for segment %s - 0x%x.", 6156 getIdentifierCString(), seg->segname, (int)result); 6157 goto finish; 6158 } 6159 6160 result = OSKext_protect(kext_map, start, end, seg->initprot, FALSE); 6161 if (result != KERN_SUCCESS) { 6162 OSKextLog(this, 6163 kOSKextLogErrorLevel | 6164 kOSKextLogLoadFlag, 6165 "Kext %s failed to set initial VM protections " 6166 "for segment %s - 0x%x.", 6167 getIdentifierCString(), seg->segname, (int)result); 6168 goto finish; 6169 } 6170 } 6171 6172 if (segmentShouldBeWired(seg) && wire) { 6173 result = OSKext_wire(kext_map, start, end, seg->initprot, FALSE); 6174 if (result != KERN_SUCCESS) { 6175 goto finish; 6176 } 6177 } 6178 6179 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 6180 } 6181 6182 finish: 6183 return result; 6184 } 6185 6186 /********************************************************************* 6187 *********************************************************************/ 6188 boolean_t 6189 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg) 6190 { 6191 return sKeepSymbols || strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)); 6192 } 6193 6194 /********************************************************************* 6195 *********************************************************************/ 6196 OSReturn 6197 OSKext::validateKextMapping(bool startFlag) 6198 { 6199 OSReturn result = kOSReturnError; 6200 const char * whichOp = startFlag ? "start" : "stop"; 6201 kern_return_t kern_result = 0; 6202 vm_map_t kext_map = NULL; 6203 kernel_segment_command_t * seg = NULL; 6204 mach_vm_address_t address = 0; 6205 mach_vm_size_t size = 0; 6206 uint32_t depth = 0; 6207 mach_msg_type_number_t count; 6208 vm_region_submap_short_info_data_64_t info; 6209 6210 if (flags.builtin) { 6211 return kOSReturnSuccess; 6212 } 6213 6214 count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 6215 bzero(&info, sizeof(info)); 6216 6217 // xxx - do we need a distinct OSReturn value for these or is "bad data" 6218 // xxx - sufficient? 6219 6220 /* Verify that the kmod_info and start/stop pointers are non-NULL. 6221 */ 6222 if (!kmod_info) { 6223 OSKextLog(this, 6224 kOSKextLogErrorLevel | 6225 kOSKextLogLoadFlag, 6226 "Kext %s - NULL kmod_info pointer.", 6227 getIdentifierCString()); 6228 result = kOSKextReturnBadData; 6229 goto finish; 6230 } 6231 6232 if (startFlag) { 6233 address = (mach_vm_address_t)kmod_info->start; 6234 } else { 6235 address = (mach_vm_address_t)kmod_info->stop; 6236 } 6237 6238 if (!address) { 6239 OSKextLog(this, 6240 kOSKextLogErrorLevel | 6241 kOSKextLogLoadFlag, 6242 "Kext %s - NULL module %s pointer.", 6243 getIdentifierCString(), whichOp); 6244 result = kOSKextReturnBadData; 6245 goto finish; 6246 } 6247 6248 kext_map = kext_get_vm_map(kmod_info); 6249 depth = (kernel_map == kext_map) ? 1 : 2; 6250 6251 /* Verify that the start/stop function lies within the kext's address range. 6252 */ 6253 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) { 6254 /* This will likely be how we deal with split kexts; walk the segments to 6255 * check that the function lies inside one of the segments of this kext. 6256 */ 6257 for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 6258 seg != NULL; 6259 seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) { 6260 if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) { 6261 break; 6262 } 6263 } 6264 6265 if (!seg) { 6266 OSKextLog(this, 6267 kOSKextLogErrorLevel | 6268 kOSKextLogLoadFlag, 6269 "Kext %s module %s pointer is outside of kext range " 6270 "(%s %p - kext starts at %p).", 6271 getIdentifierCString(), 6272 whichOp, 6273 whichOp, 6274 (void *)ml_static_unslide(address), 6275 (void *)ml_static_unslide(kmod_info->address)); 6276 result = kOSKextReturnBadData; 6277 goto finish; 6278 } 6279 6280 seg = NULL; 6281 } else { 6282 if (address < kmod_info->address + kmod_info->hdr_size || 6283 kmod_info->address + kmod_info->size <= address) { 6284 OSKextLog(this, 6285 kOSKextLogErrorLevel | 6286 kOSKextLogLoadFlag, 6287 "Kext %s module %s pointer is outside of kext range " 6288 "(%s %p - kext at %p-%p).", 6289 getIdentifierCString(), 6290 whichOp, 6291 whichOp, 6292 (void *)ml_static_unslide(address), 6293 (void *)ml_static_unslide(kmod_info->address), 6294 (void *)(ml_static_unslide(kmod_info->address) + kmod_info->size)); 6295 result = kOSKextReturnBadData; 6296 goto finish; 6297 } 6298 } 6299 6300 /* Only do these checks before calling the start function; 6301 * If anything goes wrong with the mapping while the kext is running, 6302 * we'll likely have panicked well before any attempt to stop the kext. 6303 */ 6304 if (startFlag) { 6305 /* Verify that the start/stop function is executable. 6306 */ 6307 kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth, 6308 (vm_region_recurse_info_t)&info, &count); 6309 if (kern_result != KERN_SUCCESS) { 6310 OSKextLog(this, 6311 kOSKextLogErrorLevel | 6312 kOSKextLogLoadFlag, 6313 "Kext %s - bad %s pointer %p.", 6314 getIdentifierCString(), 6315 whichOp, (void *)ml_static_unslide(address)); 6316 result = kOSKextReturnBadData; 6317 goto finish; 6318 } 6319 6320 #if VM_MAPPED_KEXTS 6321 if (!(info.protection & VM_PROT_EXECUTE)) { 6322 OSKextLog(this, 6323 kOSKextLogErrorLevel | 6324 kOSKextLogLoadFlag, 6325 "Kext %s - memory region containing module %s function " 6326 "is not executable.", 6327 getIdentifierCString(), whichOp); 6328 result = kOSKextReturnBadData; 6329 goto finish; 6330 } 6331 #endif 6332 6333 /* Verify that the kext's segments are backed by physical memory. 6334 */ 6335 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 6336 while (seg) { 6337 if (!verifySegmentMapping(seg)) { 6338 result = kOSKextReturnBadData; 6339 goto finish; 6340 } 6341 6342 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 6343 } 6344 } 6345 6346 result = kOSReturnSuccess; 6347 finish: 6348 return result; 6349 } 6350 6351 /********************************************************************* 6352 *********************************************************************/ 6353 boolean_t 6354 OSKext::verifySegmentMapping(kernel_segment_command_t *seg) 6355 { 6356 mach_vm_address_t address = 0; 6357 6358 if (!segmentShouldBeWired(seg)) { 6359 return true; 6360 } 6361 6362 for (address = seg->vmaddr; 6363 address < round_page(seg->vmaddr + seg->vmsize); 6364 address += PAGE_SIZE) { 6365 if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) { 6366 OSKextLog(this, 6367 kOSKextLogErrorLevel | 6368 kOSKextLogLoadFlag, 6369 "Kext %s - page %p is not backed by physical memory.", 6370 getIdentifierCString(), 6371 (void *)address); 6372 return false; 6373 } 6374 } 6375 6376 return true; 6377 } 6378 6379 /********************************************************************* 6380 *********************************************************************/ 6381 static void 6382 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code) 6383 { 6384 uint64_t stamp = 0; 6385 firehose_tracepoint_id_u trace_id; 6386 struct firehose_trace_uuid_info_s uuid_info_s; 6387 firehose_trace_uuid_info_t uuid_info = &uuid_info_s; 6388 size_t uuid_info_len = sizeof(struct firehose_trace_uuid_info_s); 6389 OSData *uuid_data; 6390 6391 stamp = firehose_tracepoint_time(firehose_activity_flags_default); 6392 trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code); 6393 6394 uuid_data = aKext->copyTextUUID(); 6395 if (uuid_data) { 6396 memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid)); 6397 OSSafeReleaseNULL(uuid_data); 6398 } 6399 6400 uuid_info->ftui_size = size; 6401 if (aKext->isDriverKit()) { 6402 uuid_info->ftui_address = address; 6403 } else { 6404 uuid_info->ftui_address = ml_static_unslide(address); 6405 } 6406 firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len); 6407 return; 6408 } 6409 6410 void 6411 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext) 6412 { 6413 OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load); 6414 } 6415 6416 /********************************************************************* 6417 *********************************************************************/ 6418 OSReturn 6419 OSKext::start(bool startDependenciesFlag) 6420 { 6421 OSReturn result = kOSReturnError; 6422 kern_return_t (* startfunc)(kmod_info_t *, void *); 6423 unsigned int i, count; 6424 void * kmodStartData = NULL; 6425 6426 if (isStarted() || isInterface() || isKernelComponent()) { 6427 result = kOSReturnSuccess; 6428 goto finish; 6429 } 6430 6431 if (!isLoaded()) { 6432 OSKextLog(this, 6433 kOSKextLogErrorLevel | 6434 kOSKextLogLoadFlag, 6435 "Attempt to start nonloaded kext %s.", 6436 getIdentifierCString()); 6437 result = kOSKextReturnInvalidArgument; 6438 goto finish; 6439 } 6440 6441 if (!sLoadEnabled) { 6442 OSKextLog(this, 6443 kOSKextLogErrorLevel | 6444 kOSKextLogLoadFlag, 6445 "Kext loading is disabled (attempt to start kext %s).", 6446 getIdentifierCString()); 6447 result = kOSKextReturnDisabled; 6448 goto finish; 6449 } 6450 6451 result = validateKextMapping(/* start? */ true); 6452 if (result != kOSReturnSuccess) { 6453 goto finish; 6454 } 6455 6456 startfunc = kmod_info->start; 6457 6458 count = getNumDependencies(); 6459 for (i = 0; i < count; i++) { 6460 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i)); 6461 if (dependency == NULL) { 6462 OSKextLog(this, 6463 kOSKextLogErrorLevel | 6464 kOSKextLogLoadFlag, 6465 "Kext %s start - internal error, dependency disappeared.", 6466 getIdentifierCString()); 6467 goto finish; 6468 } 6469 if (!dependency->isStarted()) { 6470 if (startDependenciesFlag) { 6471 OSReturn dependencyResult = 6472 dependency->start(startDependenciesFlag); 6473 if (dependencyResult != KERN_SUCCESS) { 6474 OSKextLog(this, 6475 kOSKextLogErrorLevel | 6476 kOSKextLogLoadFlag, 6477 "Kext %s start - dependency %s failed to start (error 0x%x).", 6478 getIdentifierCString(), 6479 dependency->getIdentifierCString(), 6480 dependencyResult); 6481 goto finish; 6482 } 6483 } else { 6484 OSKextLog(this, 6485 kOSKextLogErrorLevel | 6486 kOSKextLogLoadFlag, 6487 "Not starting %s - dependency %s not started yet.", 6488 getIdentifierCString(), 6489 dependency->getIdentifierCString()); 6490 result = kOSKextReturnStartStopError; // xxx - make new return? 6491 goto finish; 6492 } 6493 } 6494 } 6495 6496 OSKextLog(this, 6497 kOSKextLogDetailLevel | 6498 kOSKextLogLoadFlag, 6499 "Kext %s calling module start function.", 6500 getIdentifierCString()); 6501 6502 flags.starting = 1; 6503 6504 // Drop a log message so logd can grab the needed information to decode this kext 6505 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load); 6506 result = OSRuntimeInitializeCPP(this); 6507 if (result == KERN_SUCCESS) { 6508 result = startfunc(kmod_info, kmodStartData); 6509 } 6510 6511 flags.starting = 0; 6512 6513 /* On success overlap the setting of started/starting. On failure just 6514 * clear starting. 6515 */ 6516 if (result == KERN_SUCCESS) { 6517 flags.started = 1; 6518 6519 // xxx - log start error from kernel? 6520 OSKextLog(this, 6521 kOSKextLogProgressLevel | 6522 kOSKextLogLoadFlag, 6523 "Kext %s is now started.", 6524 getIdentifierCString()); 6525 } else { 6526 invokeOrCancelRequestCallbacks( 6527 /* result not actually used */ kOSKextReturnStartStopError, 6528 /* invokeFlag */ false); 6529 OSKextLog(this, 6530 kOSKextLogProgressLevel | 6531 kOSKextLogLoadFlag, 6532 "Kext %s did not start (return code 0x%x).", 6533 getIdentifierCString(), result); 6534 } 6535 6536 finish: 6537 return result; 6538 } 6539 6540 /********************************************************************* 6541 *********************************************************************/ 6542 /* static */ 6543 bool 6544 OSKext::canUnloadKextWithIdentifier( 6545 OSString * kextIdentifier, 6546 bool checkClassesFlag) 6547 { 6548 bool result = false; 6549 OSKext * aKext = NULL;// do not release 6550 6551 IORecursiveLockLock(sKextLock); 6552 6553 aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 6554 6555 if (!aKext) { 6556 goto finish; // can't unload what's not loaded 6557 } 6558 6559 if (aKext->isLoaded()) { 6560 if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) { 6561 goto finish; 6562 } 6563 if (checkClassesFlag && aKext->hasOSMetaClassInstances()) { 6564 goto finish; 6565 } 6566 } 6567 6568 result = true; 6569 6570 finish: 6571 IORecursiveLockUnlock(sKextLock); 6572 return result; 6573 } 6574 6575 /********************************************************************* 6576 *********************************************************************/ 6577 OSReturn 6578 OSKext::stop(void) 6579 { 6580 OSReturn result = kOSReturnError; 6581 kern_return_t (*stopfunc)(kmod_info_t *, void *); 6582 6583 if (!isStarted() || isInterface()) { 6584 result = kOSReturnSuccess; 6585 goto finish; 6586 } 6587 6588 if (!isLoaded()) { 6589 OSKextLog(this, 6590 kOSKextLogErrorLevel | 6591 kOSKextLogLoadFlag, 6592 "Attempt to stop nonloaded kext %s.", 6593 getIdentifierCString()); 6594 result = kOSKextReturnInvalidArgument; 6595 goto finish; 6596 } 6597 6598 /* Refuse to stop if we have clients or instances. It is up to 6599 * the caller to make sure those aren't true. 6600 */ 6601 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 6602 OSKextLog(this, 6603 kOSKextLogErrorLevel | 6604 kOSKextLogLoadFlag, 6605 "Kext %s - C++ instances; can't stop.", 6606 getIdentifierCString()); 6607 result = kOSKextReturnInUse; 6608 goto finish; 6609 } 6610 6611 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 6612 OSKextLog(this, 6613 kOSKextLogErrorLevel | 6614 kOSKextLogLoadFlag, 6615 "Kext %s - has references (linkage or tracking object); " 6616 "can't stop.", 6617 getIdentifierCString()); 6618 result = kOSKextReturnInUse; 6619 goto finish; 6620 } 6621 6622 /* Note: If validateKextMapping fails on the stop & unload path, 6623 * we are in serious trouble and a kernel panic is likely whether 6624 * we stop & unload the kext or not. 6625 */ 6626 result = validateKextMapping(/* start? */ false); 6627 if (result != kOSReturnSuccess) { 6628 goto finish; 6629 } 6630 6631 stopfunc = kmod_info->stop; 6632 if (stopfunc) { 6633 OSKextLog(this, 6634 kOSKextLogDetailLevel | 6635 kOSKextLogLoadFlag, 6636 "Kext %s calling module stop function.", 6637 getIdentifierCString()); 6638 6639 flags.stopping = 1; 6640 6641 result = stopfunc(kmod_info, /* userData */ NULL); 6642 if (result == KERN_SUCCESS) { 6643 result = OSRuntimeFinalizeCPP(this); 6644 } 6645 6646 flags.stopping = 0; 6647 6648 if (result == KERN_SUCCESS) { 6649 flags.started = 0; 6650 6651 OSKextLog(this, 6652 kOSKextLogDetailLevel | 6653 kOSKextLogLoadFlag, 6654 "Kext %s is now stopped and ready to unload.", 6655 getIdentifierCString()); 6656 } else { 6657 OSKextLog(this, 6658 kOSKextLogErrorLevel | 6659 kOSKextLogLoadFlag, 6660 "Kext %s did not stop (return code 0x%x).", 6661 getIdentifierCString(), result); 6662 result = kOSKextReturnStartStopError; 6663 } 6664 } 6665 6666 finish: 6667 // Drop a log message so logd can update this kext's metadata 6668 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload); 6669 return result; 6670 } 6671 6672 /********************************************************************* 6673 *********************************************************************/ 6674 OSReturn 6675 OSKext::unload(void) 6676 { 6677 OSReturn result = kOSReturnError; 6678 unsigned int index; 6679 uint32_t num_kmod_refs = 0; 6680 OSKextAccount * freeAccount; 6681 6682 if (!sUnloadEnabled) { 6683 OSKextLog(this, 6684 kOSKextLogErrorLevel | 6685 kOSKextLogLoadFlag, 6686 "Kext unloading is disabled (%s).", 6687 this->getIdentifierCString()); 6688 6689 result = kOSKextReturnDisabled; 6690 goto finish; 6691 } 6692 6693 /* Refuse to unload if we have clients or instances. It is up to 6694 * the caller to make sure those aren't true. 6695 */ 6696 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 6697 // xxx - Don't log under errors? this is more of an info thing 6698 OSKextLog(this, 6699 kOSKextLogErrorLevel | 6700 kOSKextLogKextBookkeepingFlag, 6701 "Can't unload kext %s; outstanding references (linkage or tracking object).", 6702 getIdentifierCString()); 6703 result = kOSKextReturnInUse; 6704 goto finish; 6705 } 6706 6707 if (isDriverKit()) { 6708 index = sLoadedKexts->getNextIndexOfObject(this, 0); 6709 if (index != (unsigned int)-1) { 6710 sLoadedDriverKitKexts->removeObject(index); 6711 OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload); 6712 loadTag = 0; 6713 } 6714 } 6715 6716 if (!isLoaded()) { 6717 result = kOSReturnSuccess; 6718 goto finish; 6719 } 6720 6721 if (isKernelComponent()) { 6722 result = kOSKextReturnInvalidArgument; 6723 goto finish; 6724 } 6725 6726 if (metaClasses && !OSMetaClass::removeClasses(metaClasses)) { 6727 OSKextLog(this, 6728 kOSKextLogErrorLevel | 6729 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 6730 "Can't unload kext %s; classes have instances:", 6731 getIdentifierCString()); 6732 reportOSMetaClassInstances(kOSKextLogErrorLevel | 6733 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag); 6734 result = kOSKextReturnInUse; 6735 goto finish; 6736 } 6737 6738 /* Note that the kext is unloading before running any code that 6739 * might be in the kext (request callbacks, module stop function). 6740 * We will deny certain requests made against a kext in the process 6741 * of unloading. 6742 */ 6743 flags.unloading = 1; 6744 6745 /* Update the string describing the last kext to unload in case we panic. 6746 */ 6747 savePanicString(/* isLoading */ false); 6748 6749 if (isStarted()) { 6750 result = stop(); 6751 if (result != KERN_SUCCESS) { 6752 OSKextLog(this, 6753 kOSKextLogErrorLevel | 6754 kOSKextLogLoadFlag, 6755 "Kext %s can't unload - module stop returned 0x%x.", 6756 getIdentifierCString(), (unsigned)result); 6757 result = kOSKextReturnStartStopError; 6758 goto finish; 6759 } 6760 } 6761 6762 OSKextLog(this, 6763 kOSKextLogProgressLevel | 6764 kOSKextLogLoadFlag, 6765 "Kext %s unloading.", 6766 getIdentifierCString()); 6767 6768 { 6769 struct list_head *p; 6770 struct list_head *prev; 6771 struct list_head *next; 6772 for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) { 6773 OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head); 6774 s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize); 6775 prev = p->prev; 6776 next = p->next; 6777 prev->next = next; 6778 next->prev = prev; 6779 p->prev = p; 6780 p->next = p; 6781 IORecursiveLockWakeup(sKextLock, s, false); 6782 } 6783 } 6784 6785 6786 /* Even if we don't call the stop function, we want to be sure we 6787 * have no OSMetaClass references before unloading the kext executable 6788 * from memory. OSMetaClasses may have pointers into the kext executable 6789 * and that would cause a panic on OSKext::free() when metaClasses is freed. 6790 */ 6791 if (metaClasses) { 6792 metaClasses->flushCollection(); 6793 } 6794 (void) OSRuntimeFinalizeCPP(this); 6795 6796 /* Remove the kext from the list of loaded kexts, patch the gap 6797 * in the kmod_info_t linked list, and reset "kmod" to point to the 6798 * last loaded kext that isn't the fake kernel kext (sKernelKext). 6799 */ 6800 index = sLoadedKexts->getNextIndexOfObject(this, 0); 6801 if (index != (unsigned int)-1) { 6802 sLoadedKexts->removeObject(index); 6803 6804 OSKext * nextKext = OSDynamicCast(OSKext, 6805 sLoadedKexts->getObject(index)); 6806 6807 if (nextKext) { 6808 if (index > 0) { 6809 OSKext * gapKext = OSDynamicCast(OSKext, 6810 sLoadedKexts->getObject(index - 1)); 6811 6812 nextKext->kmod_info->next = gapKext->kmod_info; 6813 } else { /* index == 0 */ 6814 nextKext->kmod_info->next = NULL; 6815 } 6816 } 6817 6818 OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 6819 if (lastKext && !lastKext->isKernel()) { 6820 kmod = lastKext->kmod_info; 6821 } else { 6822 kmod = NULL; // clear the global kmod variable 6823 } 6824 } 6825 6826 /* Clear out the kmod references that we're keeping for compatibility 6827 * with current panic backtrace code & kgmacros. 6828 * xxx - will want to update those bits sometime and remove this. 6829 */ 6830 num_kmod_refs = getNumDependencies(); 6831 if (num_kmod_refs && kmod_info && kmod_info->reference_list) { 6832 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 6833 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 6834 ref->info->reference_count--; 6835 } 6836 kfree(kmod_info->reference_list, 6837 num_kmod_refs * sizeof(kmod_reference_t)); 6838 } 6839 6840 #if CONFIG_DTRACE 6841 unregisterWithDTrace(); 6842 #endif /* CONFIG_DTRACE */ 6843 6844 notifyKextUnloadObservers(this); 6845 6846 freeAccount = NULL; 6847 IOSimpleLockLock(sKextAccountsLock); 6848 account->kext = NULL; 6849 if (account->site.tag) { 6850 account->site.flags |= VM_TAG_UNLOAD; 6851 } else { 6852 freeAccount = account; 6853 } 6854 IOSimpleLockUnlock(sKextAccountsLock); 6855 if (freeAccount) { 6856 IODelete(freeAccount, OSKextAccount, 1); 6857 } 6858 6859 /* Unwire and free the linked executable. 6860 */ 6861 if (linkedExecutable) { 6862 #if KASAN 6863 kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength()); 6864 #endif 6865 6866 #if VM_MAPPED_KEXTS 6867 if (!isInterface()) { 6868 kernel_segment_command_t *seg = NULL; 6869 vm_map_t kext_map = kext_get_vm_map(kmod_info); 6870 6871 if (!kext_map) { 6872 OSKextLog(this, 6873 kOSKextLogErrorLevel | 6874 kOSKextLogLoadFlag, 6875 "Failed to free kext %s; couldn't find the kext map.", 6876 getIdentifierCString()); 6877 result = kOSKextReturnInternalError; 6878 goto finish; 6879 } 6880 6881 OSKextLog(this, 6882 kOSKextLogProgressLevel | 6883 kOSKextLogLoadFlag, 6884 "Kext %s unwiring and unmapping linked executable.", 6885 getIdentifierCString()); 6886 6887 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 6888 while (seg) { 6889 if (segmentShouldBeWired(seg)) { 6890 result = vm_map_unwire(kext_map, seg->vmaddr, 6891 seg->vmaddr + seg->vmsize, FALSE); 6892 if (result != KERN_SUCCESS) { 6893 OSKextLog(this, 6894 kOSKextLogErrorLevel | 6895 kOSKextLogLoadFlag, 6896 "Failed to unwire kext %s.", 6897 getIdentifierCString()); 6898 result = kOSKextReturnInternalError; 6899 goto finish; 6900 } 6901 } 6902 6903 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 6904 } 6905 } 6906 #endif 6907 OSSafeReleaseNULL(linkedExecutable); 6908 } 6909 6910 /* An interface kext has a fake kmod_info that was allocated, 6911 * so we have to free it. 6912 */ 6913 if (isInterface()) { 6914 kfree(kmod_info, sizeof(kmod_info_t)); 6915 } 6916 6917 kmod_info = NULL; 6918 6919 flags.loaded = false; 6920 flushDependencies(); 6921 6922 /* save a copy of the bundle ID for us to check when deciding to 6923 * rebuild the kernel cache file. If a kext was already in the kernel 6924 * cache and unloaded then later loaded we do not need to rebuild the 6925 * kernel cache. 9055303 6926 */ 6927 if (isPrelinked()) { 6928 if (!_OSKextInUnloadedPrelinkedKexts(bundleID)) { 6929 IORecursiveLockLock(sKextLock); 6930 if (sUnloadedPrelinkedKexts) { 6931 sUnloadedPrelinkedKexts->setObject(bundleID); 6932 } 6933 IORecursiveLockUnlock(sKextLock); 6934 } 6935 } 6936 6937 OSKextLog(this, 6938 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 6939 "Kext %s unloaded.", getIdentifierCString()); 6940 6941 queueKextNotification(kKextRequestPredicateUnloadNotification, 6942 OSDynamicCast(OSString, bundleID)); 6943 6944 finish: 6945 OSKext::saveLoadedKextPanicList(); 6946 OSKext::updateLoadedKextSummaries(); 6947 6948 flags.unloading = 0; 6949 return result; 6950 } 6951 6952 /********************************************************************* 6953 * Assumes sKextLock is held. 6954 *********************************************************************/ 6955 /* static */ 6956 OSReturn 6957 OSKext::queueKextNotification( 6958 const char * notificationName, 6959 OSString * kextIdentifier) 6960 { 6961 OSReturn result = kOSReturnError; 6962 OSDictionary * loadRequest = NULL;// must release 6963 6964 if (!kextIdentifier) { 6965 result = kOSKextReturnInvalidArgument; 6966 goto finish; 6967 } 6968 6969 /* Create a new request unless one is already sitting 6970 * in sKernelRequests for this bundle identifier 6971 */ 6972 result = _OSKextCreateRequest(notificationName, &loadRequest); 6973 if (result != kOSReturnSuccess) { 6974 goto finish; 6975 } 6976 if (!_OSKextSetRequestArgument(loadRequest, 6977 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 6978 result = kOSKextReturnNoMemory; 6979 goto finish; 6980 } 6981 if (!sKernelRequests->setObject(loadRequest)) { 6982 result = kOSKextReturnNoMemory; 6983 goto finish; 6984 } 6985 6986 /* We might want to only queue the notification if kextd is active, 6987 * but that wouldn't work for embedded. Note that we don't care if 6988 * the ping immediately succeeds here so don't do anything with the 6989 * result of this call. 6990 */ 6991 OSKext::pingKextd(); 6992 6993 result = kOSReturnSuccess; 6994 6995 finish: 6996 OSSafeReleaseNULL(loadRequest); 6997 6998 return result; 6999 } 7000 7001 /********************************************************************* 7002 *********************************************************************/ 7003 static void 7004 _OSKextConsiderDestroyingLinkContext( 7005 __unused thread_call_param_t p0, 7006 __unused thread_call_param_t p1) 7007 { 7008 /* Take multiple locks in the correct order. 7009 */ 7010 IORecursiveLockLock(sKextLock); 7011 IORecursiveLockLock(sKextInnerLock); 7012 7013 /* The first time we destroy the kxldContext is in the first 7014 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled 7015 * before calling this function. Thereafter any call to this function 7016 * will actually destroy the context. 7017 */ 7018 if (sConsiderUnloadsCalled && sKxldContext) { 7019 kxld_destroy_context(sKxldContext); 7020 sKxldContext = NULL; 7021 } 7022 7023 /* Free the thread_call that was allocated to execute this function. 7024 */ 7025 if (sDestroyLinkContextThread) { 7026 if (!thread_call_free(sDestroyLinkContextThread)) { 7027 OSKextLog(/* kext */ NULL, 7028 kOSKextLogErrorLevel | 7029 kOSKextLogGeneralFlag, 7030 "thread_call_free() failed for kext link context."); 7031 } 7032 sDestroyLinkContextThread = NULL; 7033 } 7034 7035 IORecursiveLockUnlock(sKextInnerLock); 7036 IORecursiveLockUnlock(sKextLock); 7037 7038 return; 7039 } 7040 7041 /********************************************************************* 7042 * Destroying the kxldContext requires checking variables under both 7043 * sKextInnerLock and sKextLock, so we do it on a separate thread 7044 * to avoid deadlocks with IOService, with which OSKext has a reciprocal 7045 * call relationship. 7046 * 7047 * This function must be invoked with sKextInnerLock held. 7048 * Do not call any function that takes sKextLock here! 7049 *********************************************************************/ 7050 /* static */ 7051 void 7052 OSKext::considerDestroyingLinkContext(void) 7053 { 7054 IORecursiveLockLock(sKextInnerLock); 7055 7056 /* If we have already queued a thread to destroy the link context, 7057 * don't bother resetting; that thread will take care of it. 7058 */ 7059 if (sDestroyLinkContextThread) { 7060 goto finish; 7061 } 7062 7063 /* The function to be invoked in the thread will deallocate 7064 * this thread_call, so don't share it around. 7065 */ 7066 sDestroyLinkContextThread = thread_call_allocate( 7067 &_OSKextConsiderDestroyingLinkContext, NULL); 7068 if (!sDestroyLinkContextThread) { 7069 OSKextLog(/* kext */ NULL, 7070 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag, 7071 "Can't create thread to destroy kext link context."); 7072 goto finish; 7073 } 7074 7075 thread_call_enter(sDestroyLinkContextThread); 7076 7077 finish: 7078 IORecursiveLockUnlock(sKextInnerLock); 7079 return; 7080 } 7081 7082 #if PRAGMA_MARK 7083 #pragma mark Autounload 7084 #endif 7085 /********************************************************************* 7086 * This is a static method because the kext will be deallocated if it 7087 * does unload! 7088 *********************************************************************/ 7089 /* static */ 7090 OSReturn 7091 OSKext::autounloadKext(OSKext * aKext) 7092 { 7093 OSReturn result = kOSKextReturnInUse; 7094 7095 /* Check for external references to this kext (usu. dependents), 7096 * instances of defined classes (or classes derived from them), 7097 * outstanding requests. 7098 */ 7099 if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) || 7100 !aKext->flags.autounloadEnabled || 7101 aKext->isKernelComponent()) { 7102 goto finish; 7103 } 7104 7105 /* Skip a delay-autounload kext, once. 7106 */ 7107 if (aKext->flags.delayAutounload) { 7108 OSKextLog(aKext, 7109 kOSKextLogProgressLevel | 7110 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 7111 "Kext %s has delayed autounload set; skipping and clearing flag.", 7112 aKext->getIdentifierCString()); 7113 aKext->flags.delayAutounload = 0; 7114 goto finish; 7115 } 7116 7117 if (aKext->hasOSMetaClassInstances() || 7118 aKext->countRequestCallbacks()) { 7119 goto finish; 7120 } 7121 7122 result = OSKext::removeKext(aKext); 7123 7124 finish: 7125 return result; 7126 } 7127 7128 /********************************************************************* 7129 *********************************************************************/ 7130 void 7131 _OSKextConsiderUnloads( 7132 __unused thread_call_param_t p0, 7133 __unused thread_call_param_t p1) 7134 { 7135 bool didUnload = false; 7136 unsigned int count, i; 7137 7138 /* Take multiple locks in the correct order 7139 * (note also sKextSummaries lock further down). 7140 */ 7141 IORecursiveLockLock(sKextLock); 7142 IORecursiveLockLock(sKextInnerLock); 7143 7144 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true); 7145 7146 /* If the system is powering down, don't try to unload anything. 7147 */ 7148 if (sSystemSleep) { 7149 goto finish; 7150 } 7151 7152 OSKextLog(/* kext */ NULL, 7153 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 7154 "Checking for unused kexts to autounload."); 7155 7156 /***** 7157 * Remove any request callbacks marked as stale, 7158 * and mark as stale any currently in flight. 7159 */ 7160 count = sRequestCallbackRecords->getCount(); 7161 if (count) { 7162 i = count - 1; 7163 do { 7164 OSDictionary * callbackRecord = OSDynamicCast(OSDictionary, 7165 sRequestCallbackRecords->getObject(i)); 7166 OSBoolean * stale = OSDynamicCast(OSBoolean, 7167 callbackRecord->getObject(kKextRequestStaleKey)); 7168 7169 if (stale == kOSBooleanTrue) { 7170 OSKext::invokeRequestCallback(callbackRecord, 7171 kOSKextReturnTimeout); 7172 } else { 7173 callbackRecord->setObject(kKextRequestStaleKey, 7174 kOSBooleanTrue); 7175 } 7176 } while (i--); 7177 } 7178 7179 /***** 7180 * Make multiple passes through the array of loaded kexts until 7181 * we don't unload any. This handles unwinding of dependency 7182 * chains. We have to go *backwards* through the array because 7183 * kexts are removed from it when unloaded, and we cannot make 7184 * a copy or we'll mess up the retain counts we rely on to 7185 * check whether a kext will unload. If only we could have 7186 * nonretaining collections like CF has.... 7187 */ 7188 do { 7189 didUnload = false; 7190 7191 count = sLoadedKexts->getCount(); 7192 if (count) { 7193 i = count - 1; 7194 do { 7195 OSKext * thisKext = OSDynamicCast(OSKext, 7196 sLoadedKexts->getObject(i)); 7197 didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext)); 7198 } while (i--); 7199 } 7200 } while (didUnload); 7201 7202 finish: 7203 sConsiderUnloadsPending = false; 7204 sConsiderUnloadsExecuted = true; 7205 7206 (void) OSKext::considerRebuildOfPrelinkedKernel(); 7207 7208 IORecursiveLockUnlock(sKextInnerLock); 7209 IORecursiveLockUnlock(sKextLock); 7210 7211 return; 7212 } 7213 7214 /********************************************************************* 7215 * Do not call any function that takes sKextLock here! 7216 *********************************************************************/ 7217 void 7218 OSKext::considerUnloads(Boolean rescheduleOnlyFlag) 7219 { 7220 AbsoluteTime when; 7221 7222 IORecursiveLockLock(sKextInnerLock); 7223 7224 if (!sUnloadCallout) { 7225 sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL); 7226 } 7227 7228 /* we only reset delay value for unloading if we already have something 7229 * pending. rescheduleOnlyFlag should not start the count down. 7230 */ 7231 if (rescheduleOnlyFlag && !sConsiderUnloadsPending) { 7232 goto finish; 7233 } 7234 7235 thread_call_cancel(sUnloadCallout); 7236 if (OSKext::getAutounloadEnabled() && !sSystemSleep) { 7237 clock_interval_to_deadline(sConsiderUnloadDelay, 7238 1000 * 1000 * 1000, &when); 7239 7240 OSKextLog(/* kext */ NULL, 7241 kOSKextLogProgressLevel | 7242 kOSKextLogLoadFlag, 7243 "%scheduling %sscan for unused kexts in %lu seconds.", 7244 sConsiderUnloadsPending ? "Res" : "S", 7245 sConsiderUnloadsCalled ? "" : "initial ", 7246 (unsigned long)sConsiderUnloadDelay); 7247 7248 sConsiderUnloadsPending = true; 7249 thread_call_enter_delayed(sUnloadCallout, when); 7250 } 7251 7252 finish: 7253 /* The kxld context should be reused throughout boot. We mark the end of 7254 * period as the first time considerUnloads() is called, and we destroy 7255 * the first kxld context in that function. Afterwards, it will be 7256 * destroyed in flushNonloadedKexts. 7257 */ 7258 if (!sConsiderUnloadsCalled) { 7259 sConsiderUnloadsCalled = true; 7260 OSKext::considerDestroyingLinkContext(); 7261 } 7262 7263 IORecursiveLockUnlock(sKextInnerLock); 7264 return; 7265 } 7266 7267 /********************************************************************* 7268 * Do not call any function that takes sKextLock here! 7269 *********************************************************************/ 7270 extern "C" { 7271 IOReturn OSKextSystemSleepOrWake(UInt32 messageType); 7272 IOReturn 7273 OSKextSystemSleepOrWake(UInt32 messageType) 7274 { 7275 IORecursiveLockLock(sKextInnerLock); 7276 7277 /* If the system is going to sleep, cancel the reaper thread timer, 7278 * and note that we're in a sleep state in case it just fired but hasn't 7279 * taken the lock yet. If we are coming back from sleep, just 7280 * clear the sleep flag; IOService's normal operation will cause 7281 * unloads to be considered soon enough. 7282 */ 7283 if (messageType == kIOMessageSystemWillSleep) { 7284 if (sUnloadCallout) { 7285 thread_call_cancel(sUnloadCallout); 7286 } 7287 sSystemSleep = true; 7288 AbsoluteTime_to_scalar(&sLastWakeTime) = 0; 7289 } else if (messageType == kIOMessageSystemHasPoweredOn) { 7290 sSystemSleep = false; 7291 clock_get_uptime(&sLastWakeTime); 7292 } 7293 IORecursiveLockUnlock(sKextInnerLock); 7294 7295 return kIOReturnSuccess; 7296 } 7297 }; 7298 7299 7300 #if PRAGMA_MARK 7301 #pragma mark Prelinked Kernel 7302 #endif 7303 /********************************************************************* 7304 * Do not access sConsiderUnloads... variables other than 7305 * sConsiderUnloadsExecuted in this function. They are guarded by a 7306 * different lock. 7307 *********************************************************************/ 7308 /* static */ 7309 void 7310 OSKext::considerRebuildOfPrelinkedKernel(void) 7311 { 7312 static bool requestedPrelink = false; 7313 OSReturn checkResult = kOSReturnError; 7314 OSDictionary * prelinkRequest = NULL;// must release 7315 OSCollectionIterator * kextIterator = NULL;// must release 7316 const OSSymbol * thisID = NULL;// do not release 7317 bool doRebuild = false; 7318 AbsoluteTime my_abstime; 7319 UInt64 my_ns; 7320 SInt32 delta_secs; 7321 7322 /* Only one auto rebuild per boot and only on boot from prelinked kernel */ 7323 if (requestedPrelink || !sPrelinkBoot) { 7324 return; 7325 } 7326 7327 /* no direct return from this point */ 7328 IORecursiveLockLock(sKextLock); 7329 7330 /* We need to wait for kextd to get up and running with unloads already done 7331 * and any new startup kexts loaded. 7332 */ 7333 if (!sConsiderUnloadsExecuted || 7334 !sDeferredLoadSucceeded) { 7335 goto finish; 7336 } 7337 7338 /* we really only care about boot / system start up related kexts so bail 7339 * if we're here after REBUILD_MAX_TIME. 7340 */ 7341 if (!_OSKextInPrelinkRebuildWindow()) { 7342 OSKextLog(/* kext */ NULL, 7343 kOSKextLogArchiveFlag, 7344 "%s prebuild rebuild has expired", 7345 __FUNCTION__); 7346 requestedPrelink = true; 7347 goto finish; 7348 } 7349 7350 /* we do not want to trigger a rebuild if we get here too close to waking 7351 * up. (see radar 10233768) 7352 */ 7353 IORecursiveLockLock(sKextInnerLock); 7354 7355 clock_get_uptime(&my_abstime); 7356 delta_secs = MINIMUM_WAKEUP_SECONDS + 1; 7357 if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) { 7358 SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime); 7359 absolutetime_to_nanoseconds(my_abstime, &my_ns); 7360 delta_secs = (SInt32)(my_ns / NSEC_PER_SEC); 7361 } 7362 IORecursiveLockUnlock(sKextInnerLock); 7363 7364 if (delta_secs < MINIMUM_WAKEUP_SECONDS) { 7365 /* too close to time of last wake from sleep */ 7366 goto finish; 7367 } 7368 requestedPrelink = true; 7369 7370 /* Now it's time to see if we have a reason to rebuild. We may have done 7371 * some loads and unloads but the kernel cache didn't actually change. 7372 * We will rebuild if any kext is not marked prelinked AND is not in our 7373 * list of prelinked kexts that got unloaded. (see radar 9055303) 7374 */ 7375 kextIterator = OSCollectionIterator::withCollection(sKextsByID); 7376 if (!kextIterator) { 7377 goto finish; 7378 } 7379 7380 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 7381 OSKext * thisKext;// do not release 7382 7383 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 7384 if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) { 7385 continue; 7386 } 7387 7388 if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID)) { 7389 continue; 7390 } 7391 /* kext is loaded and was not in current kernel cache so let's rebuild 7392 */ 7393 doRebuild = true; 7394 OSKextLog(/* kext */ NULL, 7395 kOSKextLogArchiveFlag, 7396 "considerRebuildOfPrelinkedKernel %s triggered rebuild", 7397 thisKext->bundleID->getCStringNoCopy()); 7398 break; 7399 } 7400 sUnloadedPrelinkedKexts->flushCollection(); 7401 7402 if (!doRebuild) { 7403 goto finish; 7404 } 7405 7406 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink, 7407 &prelinkRequest); 7408 if (checkResult != kOSReturnSuccess) { 7409 goto finish; 7410 } 7411 7412 if (!sKernelRequests->setObject(prelinkRequest)) { 7413 goto finish; 7414 } 7415 7416 OSKext::pingKextd(); 7417 7418 finish: 7419 IORecursiveLockUnlock(sKextLock); 7420 OSSafeReleaseNULL(prelinkRequest); 7421 OSSafeReleaseNULL(kextIterator); 7422 7423 return; 7424 } 7425 7426 #if PRAGMA_MARK 7427 #pragma mark Dependencies 7428 #endif 7429 /********************************************************************* 7430 *********************************************************************/ 7431 bool 7432 OSKext::resolveDependencies( 7433 OSArray * loopStack) 7434 { 7435 bool result = false; 7436 OSArray * localLoopStack = NULL;// must release 7437 bool addedToLoopStack = false; 7438 OSDictionary * libraries = NULL;// do not release 7439 OSCollectionIterator * libraryIterator = NULL;// must release 7440 OSString * libraryID = NULL;// do not release 7441 OSString * infoString = NULL;// do not release 7442 OSString * readableString = NULL;// do not release 7443 OSKext * libraryKext = NULL;// do not release 7444 bool hasRawKernelDependency = false; 7445 bool hasKernelDependency = false; 7446 bool hasKPIDependency = false; 7447 bool hasPrivateKPIDependency = false; 7448 unsigned int count; 7449 7450 /* A kernel component will automatically have this flag set, 7451 * and a loaded kext should also have it set (as should all its 7452 * loaded dependencies). 7453 */ 7454 if (flags.hasAllDependencies) { 7455 result = true; 7456 goto finish; 7457 } 7458 7459 /* Check for loops in the dependency graph. 7460 */ 7461 if (loopStack) { 7462 if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) { 7463 OSKextLog(this, 7464 kOSKextLogErrorLevel | 7465 kOSKextLogDependenciesFlag, 7466 "Kext %s has a dependency loop; can't resolve dependencies.", 7467 getIdentifierCString()); 7468 goto finish; 7469 } 7470 } else { 7471 OSKextLog(this, 7472 kOSKextLogStepLevel | 7473 kOSKextLogDependenciesFlag, 7474 "Kext %s resolving dependencies.", 7475 getIdentifierCString()); 7476 7477 loopStack = OSArray::withCapacity(6); // any small capacity will do 7478 if (!loopStack) { 7479 OSKextLog(this, 7480 kOSKextLogErrorLevel | 7481 kOSKextLogDependenciesFlag, 7482 "Kext %s can't create bookkeeping stack to resolve dependencies.", 7483 getIdentifierCString()); 7484 goto finish; 7485 } 7486 localLoopStack = loopStack; 7487 } 7488 if (!loopStack->setObject(this)) { 7489 OSKextLog(this, 7490 kOSKextLogErrorLevel | 7491 kOSKextLogDependenciesFlag, 7492 "Kext %s - internal error resolving dependencies.", 7493 getIdentifierCString()); 7494 goto finish; 7495 } 7496 addedToLoopStack = true; 7497 7498 /* Purge any existing kexts in the dependency list and start over. 7499 */ 7500 flushDependencies(); 7501 if (dependencies) { 7502 OSKextLog(this, 7503 kOSKextLogErrorLevel | 7504 kOSKextLogDependenciesFlag, 7505 "Kext %s - internal error resolving dependencies.", 7506 getIdentifierCString()); 7507 } 7508 7509 libraries = OSDynamicCast(OSDictionary, 7510 getPropertyForHostArch(kOSBundleLibrariesKey)); 7511 if (libraries == NULL || libraries->getCount() == 0) { 7512 OSKextLog(this, 7513 kOSKextLogErrorLevel | 7514 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 7515 "Kext %s - can't resolve dependencies; %s missing/invalid type.", 7516 getIdentifierCString(), kOSBundleLibrariesKey); 7517 goto finish; 7518 } 7519 7520 /* Make a new array to hold the dependencies (flush freed the old one). 7521 */ 7522 dependencies = OSArray::withCapacity(libraries->getCount()); 7523 if (!dependencies) { 7524 OSKextLog(this, 7525 kOSKextLogErrorLevel | 7526 kOSKextLogDependenciesFlag, 7527 "Kext %s - can't allocate dependencies array.", 7528 getIdentifierCString()); 7529 goto finish; 7530 } 7531 7532 // xxx - compat: We used to add an implicit dependency on kernel 6.0 7533 // xxx - compat: if none were declared. 7534 7535 libraryIterator = OSCollectionIterator::withCollection(libraries); 7536 if (!libraryIterator) { 7537 OSKextLog(this, 7538 kOSKextLogErrorLevel | 7539 kOSKextLogDependenciesFlag, 7540 "Kext %s - can't allocate dependencies iterator.", 7541 getIdentifierCString()); 7542 goto finish; 7543 } 7544 7545 while ((libraryID = OSDynamicCast(OSString, 7546 libraryIterator->getNextObject()))) { 7547 const char * library_id = libraryID->getCStringNoCopy(); 7548 7549 OSString * libraryVersion = OSDynamicCast(OSString, 7550 libraries->getObject(libraryID)); 7551 if (libraryVersion == NULL) { 7552 OSKextLog(this, 7553 kOSKextLogErrorLevel | 7554 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 7555 "Kext %s - illegal type in OSBundleLibraries.", 7556 getIdentifierCString()); 7557 goto finish; 7558 } 7559 7560 OSKextVersion libraryVers = 7561 OSKextParseVersionString(libraryVersion->getCStringNoCopy()); 7562 if (libraryVers == -1) { 7563 OSKextLog(this, 7564 kOSKextLogErrorLevel | 7565 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 7566 "Kext %s - invalid library version %s.", 7567 getIdentifierCString(), 7568 libraryVersion->getCStringNoCopy()); 7569 goto finish; 7570 } 7571 7572 libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID)); 7573 if (libraryKext == NULL) { 7574 OSKextLog(this, 7575 kOSKextLogErrorLevel | 7576 kOSKextLogDependenciesFlag, 7577 "Kext %s - library kext %s not found.", 7578 getIdentifierCString(), library_id); 7579 goto finish; 7580 } 7581 7582 if (!libraryKext->isCompatibleWithVersion(libraryVers)) { 7583 OSKextLog(this, 7584 kOSKextLogErrorLevel | 7585 kOSKextLogDependenciesFlag, 7586 "Kext %s - library kext %s not compatible " 7587 "with requested version %s.", 7588 getIdentifierCString(), library_id, 7589 libraryVersion->getCStringNoCopy()); 7590 goto finish; 7591 } 7592 7593 /* If a nonprelinked library somehow got into the mix for a 7594 * prelinked kext, at any point in the chain, we must fail 7595 * because the prelinked relocs for the library will be all wrong. 7596 */ 7597 if (this->isPrelinked() && 7598 libraryKext->declaresExecutable() && 7599 !libraryKext->isPrelinked()) { 7600 OSKextLog(this, 7601 kOSKextLogErrorLevel | 7602 kOSKextLogDependenciesFlag, 7603 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.", 7604 getIdentifierCString(), library_id, 7605 libraryVersion->getCStringNoCopy()); 7606 goto finish; 7607 } 7608 7609 if (!libraryKext->resolveDependencies(loopStack)) { 7610 goto finish; 7611 } 7612 7613 /* Add the library directly only if it has an executable to link. 7614 * Otherwise it's just used to collect other dependencies, so put 7615 * *its* dependencies on the list for this kext. 7616 */ 7617 // xxx - We are losing info here; would like to make fake entries or 7618 // xxx - keep these in the dependency graph for loaded kexts. 7619 // xxx - I really want to make kernel components not a special case! 7620 if (libraryKext->declaresExecutable() || 7621 libraryKext->isInterface()) { 7622 if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) { 7623 dependencies->setObject(libraryKext); 7624 7625 OSKextLog(this, 7626 kOSKextLogDetailLevel | 7627 kOSKextLogDependenciesFlag, 7628 "Kext %s added dependency %s.", 7629 getIdentifierCString(), 7630 libraryKext->getIdentifierCString()); 7631 } 7632 } else { 7633 int numLibDependencies = libraryKext->getNumDependencies(); 7634 OSArray * libraryDependencies = libraryKext->getDependencies(); 7635 int index; 7636 7637 if (numLibDependencies) { 7638 // xxx - this msg level should be 1 lower than the per-kext one 7639 OSKextLog(this, 7640 kOSKextLogDetailLevel | 7641 kOSKextLogDependenciesFlag, 7642 "Kext %s pulling %d dependencies from codeless library %s.", 7643 getIdentifierCString(), 7644 numLibDependencies, 7645 libraryKext->getIdentifierCString()); 7646 } 7647 for (index = 0; index < numLibDependencies; index++) { 7648 OSKext * thisLibDependency = OSDynamicCast(OSKext, 7649 libraryDependencies->getObject(index)); 7650 if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) { 7651 dependencies->setObject(thisLibDependency); 7652 OSKextLog(this, 7653 kOSKextLogDetailLevel | 7654 kOSKextLogDependenciesFlag, 7655 "Kext %s added dependency %s from codeless library %s.", 7656 getIdentifierCString(), 7657 thisLibDependency->getIdentifierCString(), 7658 libraryKext->getIdentifierCString()); 7659 } 7660 } 7661 } 7662 7663 if ((strlen(library_id) == strlen(KERNEL_LIB)) && 7664 0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) { 7665 hasRawKernelDependency = true; 7666 } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) { 7667 hasKernelDependency = true; 7668 } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) { 7669 hasKPIDependency = true; 7670 if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) { 7671 hasPrivateKPIDependency = true; 7672 } 7673 } 7674 } 7675 7676 if (hasRawKernelDependency) { 7677 OSKextLog(this, 7678 kOSKextLogErrorLevel | 7679 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 7680 "Error - kext %s declares a dependency on %s, which is not permitted.", 7681 getIdentifierCString(), KERNEL_LIB); 7682 goto finish; 7683 } 7684 #if __LP64__ 7685 if (hasKernelDependency) { 7686 OSKextLog(this, 7687 kOSKextLogErrorLevel | 7688 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 7689 "Error - kext %s declares %s dependencies. " 7690 "Only %s* dependencies are supported for 64-bit kexts.", 7691 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 7692 goto finish; 7693 } 7694 if (!hasKPIDependency) { 7695 OSKextLog(this, 7696 kOSKextLogWarningLevel | 7697 kOSKextLogDependenciesFlag, 7698 "Warning - kext %s declares no %s* dependencies. " 7699 "If it uses any KPIs, the link may fail with undefined symbols.", 7700 getIdentifierCString(), KPI_LIB_PREFIX); 7701 } 7702 #else /* __LP64__ */ 7703 // xxx - will change to flatly disallow "kernel" dependencies at some point 7704 // xxx - is it invalid to do both "com.apple.kernel" and any 7705 // xxx - "com.apple.kernel.*"? 7706 7707 if (hasKernelDependency && hasKPIDependency) { 7708 OSKextLog(this, 7709 kOSKextLogWarningLevel | 7710 kOSKextLogDependenciesFlag, 7711 "Warning - kext %s has immediate dependencies on both " 7712 "%s* and %s* components; use only one style.", 7713 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 7714 } 7715 7716 if (!hasKernelDependency && !hasKPIDependency) { 7717 // xxx - do we want to use validation flag for these too? 7718 OSKextLog(this, 7719 kOSKextLogWarningLevel | 7720 kOSKextLogDependenciesFlag, 7721 "Warning - %s declares no kernel dependencies; using %s.", 7722 getIdentifierCString(), KERNEL6_LIB); 7723 OSKext * kernelKext = OSDynamicCast(OSKext, 7724 sKextsByID->getObject(KERNEL6_LIB)); 7725 if (kernelKext) { 7726 dependencies->setObject(kernelKext); 7727 } else { 7728 OSKextLog(this, 7729 kOSKextLogErrorLevel | 7730 kOSKextLogDependenciesFlag, 7731 "Error - Library %s not found for %s.", 7732 KERNEL6_LIB, getIdentifierCString()); 7733 } 7734 } 7735 7736 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of 7737 * its indirect dependencies to simulate old-style linking. XXX - Should 7738 * check for duplicates. 7739 */ 7740 if (!hasKPIDependency) { 7741 unsigned int i; 7742 7743 flags.hasBleedthrough = true; 7744 7745 count = getNumDependencies(); 7746 7747 /* We add to the dependencies array in this loop, but do not iterate 7748 * past its original count. 7749 */ 7750 for (i = 0; i < count; i++) { 7751 OSKext * dependencyKext = OSDynamicCast(OSKext, 7752 dependencies->getObject(i)); 7753 dependencyKext->addBleedthroughDependencies(dependencies); 7754 } 7755 } 7756 #endif /* __LP64__ */ 7757 7758 if (hasPrivateKPIDependency) { 7759 bool hasApplePrefix = false; 7760 bool infoCopyrightIsValid = false; 7761 bool readableCopyrightIsValid = false; 7762 7763 hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(), 7764 APPLE_KEXT_PREFIX); 7765 7766 infoString = OSDynamicCast(OSString, 7767 getPropertyForHostArch("CFBundleGetInfoString")); 7768 if (infoString) { 7769 infoCopyrightIsValid = 7770 kxld_validate_copyright_string(infoString->getCStringNoCopy()); 7771 } 7772 7773 readableString = OSDynamicCast(OSString, 7774 getPropertyForHostArch("NSHumanReadableCopyright")); 7775 if (readableString) { 7776 readableCopyrightIsValid = 7777 kxld_validate_copyright_string(readableString->getCStringNoCopy()); 7778 } 7779 7780 if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) { 7781 OSKextLog(this, 7782 kOSKextLogErrorLevel | 7783 kOSKextLogDependenciesFlag, 7784 "Error - kext %s declares a dependency on %s. " 7785 "Only Apple kexts may declare a dependency on %s.", 7786 getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI); 7787 goto finish; 7788 } 7789 } 7790 7791 result = true; 7792 flags.hasAllDependencies = 1; 7793 7794 finish: 7795 7796 if (addedToLoopStack) { 7797 count = loopStack->getCount(); 7798 if (count > 0 && (this == loopStack->getObject(count - 1))) { 7799 loopStack->removeObject(count - 1); 7800 } else { 7801 OSKextLog(this, 7802 kOSKextLogErrorLevel | 7803 kOSKextLogDependenciesFlag, 7804 "Kext %s - internal error resolving dependencies.", 7805 getIdentifierCString()); 7806 } 7807 } 7808 7809 if (result && localLoopStack) { 7810 OSKextLog(this, 7811 kOSKextLogStepLevel | 7812 kOSKextLogDependenciesFlag, 7813 "Kext %s successfully resolved dependencies.", 7814 getIdentifierCString()); 7815 } 7816 7817 OSSafeReleaseNULL(localLoopStack); 7818 OSSafeReleaseNULL(libraryIterator); 7819 7820 return result; 7821 } 7822 7823 /********************************************************************* 7824 *********************************************************************/ 7825 bool 7826 OSKext::addBleedthroughDependencies(OSArray * anArray) 7827 { 7828 bool result = false; 7829 unsigned int dependencyIndex, dependencyCount; 7830 7831 dependencyCount = getNumDependencies(); 7832 7833 for (dependencyIndex = 0; 7834 dependencyIndex < dependencyCount; 7835 dependencyIndex++) { 7836 OSKext * dependency = OSDynamicCast(OSKext, 7837 dependencies->getObject(dependencyIndex)); 7838 if (!dependency) { 7839 OSKextLog(this, 7840 kOSKextLogErrorLevel | 7841 kOSKextLogDependenciesFlag, 7842 "Kext %s - internal error propagating compatibility dependencies.", 7843 getIdentifierCString()); 7844 goto finish; 7845 } 7846 if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) { 7847 anArray->setObject(dependency); 7848 } 7849 dependency->addBleedthroughDependencies(anArray); 7850 } 7851 7852 result = true; 7853 7854 finish: 7855 return result; 7856 } 7857 7858 /********************************************************************* 7859 *********************************************************************/ 7860 bool 7861 OSKext::flushDependencies(bool forceFlag) 7862 { 7863 bool result = false; 7864 7865 /* Only clear the dependencies if the kext isn't loaded; 7866 * we need the info for loaded kexts to track references. 7867 */ 7868 if (!isLoaded() || forceFlag) { 7869 if (dependencies) { 7870 // xxx - check level 7871 OSKextLog(this, 7872 kOSKextLogProgressLevel | 7873 kOSKextLogDependenciesFlag, 7874 "Kext %s flushing dependencies.", 7875 getIdentifierCString()); 7876 OSSafeReleaseNULL(dependencies); 7877 } 7878 if (!isKernelComponent()) { 7879 flags.hasAllDependencies = 0; 7880 } 7881 result = true; 7882 } 7883 7884 return result; 7885 } 7886 7887 /********************************************************************* 7888 *********************************************************************/ 7889 uint32_t 7890 OSKext::getNumDependencies(void) 7891 { 7892 if (!dependencies) { 7893 return 0; 7894 } 7895 return dependencies->getCount(); 7896 } 7897 7898 /********************************************************************* 7899 *********************************************************************/ 7900 OSArray * 7901 OSKext::getDependencies(void) 7902 { 7903 return dependencies; 7904 } 7905 7906 #if PRAGMA_MARK 7907 #pragma mark OSMetaClass Support 7908 #endif 7909 /********************************************************************* 7910 *********************************************************************/ 7911 OSReturn 7912 OSKext::addClass( 7913 OSMetaClass * aClass, 7914 uint32_t numClasses) 7915 { 7916 OSReturn result = kOSMetaClassNoInsKModSet; 7917 7918 if (!metaClasses) { 7919 metaClasses = OSSet::withCapacity(numClasses); 7920 if (!metaClasses) { 7921 goto finish; 7922 } 7923 } 7924 7925 if (metaClasses->containsObject(aClass)) { 7926 OSKextLog(this, 7927 kOSKextLogWarningLevel | 7928 kOSKextLogLoadFlag, 7929 "Notice - kext %s has already registered class %s.", 7930 getIdentifierCString(), 7931 aClass->getClassName()); 7932 result = kOSReturnSuccess; 7933 goto finish; 7934 } 7935 7936 if (!metaClasses->setObject(aClass)) { 7937 goto finish; 7938 } else { 7939 OSKextLog(this, 7940 kOSKextLogDetailLevel | 7941 kOSKextLogLoadFlag, 7942 "Kext %s registered class %s.", 7943 getIdentifierCString(), 7944 aClass->getClassName()); 7945 } 7946 7947 if (!flags.autounloadEnabled) { 7948 const OSMetaClass * metaScan = NULL;// do not release 7949 7950 for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) { 7951 if (metaScan == OSTypeID(IOService)) { 7952 OSKextLog(this, 7953 kOSKextLogProgressLevel | 7954 kOSKextLogLoadFlag, 7955 "Kext %s has IOService subclass %s; enabling autounload.", 7956 getIdentifierCString(), 7957 aClass->getClassName()); 7958 7959 flags.autounloadEnabled = 1; 7960 break; 7961 } 7962 } 7963 } 7964 7965 notifyAddClassObservers(this, aClass, flags); 7966 7967 result = kOSReturnSuccess; 7968 7969 finish: 7970 if (result != kOSReturnSuccess) { 7971 OSKextLog(this, 7972 kOSKextLogErrorLevel | 7973 kOSKextLogLoadFlag, 7974 "Kext %s failed to register class %s.", 7975 getIdentifierCString(), 7976 aClass->getClassName()); 7977 } 7978 7979 return result; 7980 } 7981 7982 /********************************************************************* 7983 *********************************************************************/ 7984 OSReturn 7985 OSKext::removeClass( 7986 OSMetaClass * aClass) 7987 { 7988 OSReturn result = kOSMetaClassNoKModSet; 7989 7990 if (!metaClasses) { 7991 goto finish; 7992 } 7993 7994 if (!metaClasses->containsObject(aClass)) { 7995 OSKextLog(this, 7996 kOSKextLogWarningLevel | 7997 kOSKextLogLoadFlag, 7998 "Notice - kext %s asked to unregister unknown class %s.", 7999 getIdentifierCString(), 8000 aClass->getClassName()); 8001 result = kOSReturnSuccess; 8002 goto finish; 8003 } 8004 8005 OSKextLog(this, 8006 kOSKextLogDetailLevel | 8007 kOSKextLogLoadFlag, 8008 "Kext %s unregistering class %s.", 8009 getIdentifierCString(), 8010 aClass->getClassName()); 8011 8012 metaClasses->removeObject(aClass); 8013 8014 notifyRemoveClassObservers(this, aClass, flags); 8015 8016 result = kOSReturnSuccess; 8017 8018 finish: 8019 if (result != kOSReturnSuccess) { 8020 OSKextLog(this, 8021 kOSKextLogErrorLevel | 8022 kOSKextLogLoadFlag, 8023 "Failed to unregister kext %s class %s.", 8024 getIdentifierCString(), 8025 aClass->getClassName()); 8026 } 8027 return result; 8028 } 8029 8030 /********************************************************************* 8031 *********************************************************************/ 8032 OSSet * 8033 OSKext::getMetaClasses(void) 8034 { 8035 return metaClasses; 8036 } 8037 8038 /********************************************************************* 8039 *********************************************************************/ 8040 bool 8041 OSKext::hasOSMetaClassInstances(void) 8042 { 8043 bool result = false; 8044 OSCollectionIterator * classIterator = NULL; // must release 8045 OSMetaClass * checkClass = NULL;// do not release 8046 8047 if (!metaClasses) { 8048 goto finish; 8049 } 8050 8051 classIterator = OSCollectionIterator::withCollection(metaClasses); 8052 if (!classIterator) { 8053 // xxx - log alloc failure? 8054 goto finish; 8055 } 8056 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 8057 if (checkClass->getInstanceCount()) { 8058 result = true; 8059 goto finish; 8060 } 8061 } 8062 8063 finish: 8064 8065 OSSafeReleaseNULL(classIterator); 8066 return result; 8067 } 8068 8069 /********************************************************************* 8070 *********************************************************************/ 8071 /* static */ 8072 void 8073 OSKext::reportOSMetaClassInstances( 8074 const char * kextIdentifier, 8075 OSKextLogSpec msgLogSpec) 8076 { 8077 OSKext * theKext = NULL; // must release 8078 8079 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 8080 if (!theKext) { 8081 goto finish; 8082 } 8083 8084 theKext->reportOSMetaClassInstances(msgLogSpec); 8085 finish: 8086 OSSafeReleaseNULL(theKext); 8087 return; 8088 } 8089 8090 /********************************************************************* 8091 *********************************************************************/ 8092 void 8093 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec) 8094 { 8095 OSCollectionIterator * classIterator = NULL; // must release 8096 OSMetaClass * checkClass = NULL;// do not release 8097 8098 if (!metaClasses) { 8099 goto finish; 8100 } 8101 8102 classIterator = OSCollectionIterator::withCollection(metaClasses); 8103 if (!classIterator) { 8104 goto finish; 8105 } 8106 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 8107 if (checkClass->getInstanceCount()) { 8108 OSKextLog(this, 8109 msgLogSpec, 8110 " Kext %s class %s has %d instance%s.", 8111 getIdentifierCString(), 8112 checkClass->getClassName(), 8113 checkClass->getInstanceCount(), 8114 checkClass->getInstanceCount() == 1 ? "" : "s"); 8115 } 8116 } 8117 8118 finish: 8119 OSSafeReleaseNULL(classIterator); 8120 return; 8121 } 8122 8123 #if PRAGMA_MARK 8124 #pragma mark User-Space Requests 8125 #endif 8126 /********************************************************************* 8127 * XXX - this function is a big ugly mess 8128 *********************************************************************/ 8129 /* static */ 8130 OSReturn 8131 OSKext::handleRequest( 8132 host_priv_t hostPriv, 8133 OSKextLogSpec clientLogFilter, 8134 char * requestBuffer, 8135 uint32_t requestLength, 8136 char ** responseOut, 8137 uint32_t * responseLengthOut, 8138 char ** logInfoOut, 8139 uint32_t * logInfoLengthOut) 8140 { 8141 OSReturn result = kOSReturnError; 8142 kern_return_t kmem_result = KERN_FAILURE; 8143 8144 char * response = NULL;// returned by reference 8145 uint32_t responseLength = 0; 8146 8147 OSObject * parsedXML = NULL;// must release 8148 OSDictionary * requestDict = NULL;// do not release 8149 OSString * errorString = NULL;// must release 8150 8151 OSObject * responseObject = NULL;// must release 8152 8153 OSSerialize * serializer = NULL;// must release 8154 8155 OSArray * logInfoArray = NULL;// must release 8156 8157 OSString * predicate = NULL;// do not release 8158 OSString * kextIdentifier = NULL;// do not release 8159 OSArray * kextIdentifiers = NULL;// do not release 8160 OSKext * theKext = NULL;// do not release 8161 OSBoolean * boolArg = NULL;// do not release 8162 8163 IORecursiveLockLock(sKextLock); 8164 8165 if (responseOut) { 8166 *responseOut = NULL; 8167 *responseLengthOut = 0; 8168 } 8169 if (logInfoOut) { 8170 *logInfoOut = NULL; 8171 *logInfoLengthOut = 0; 8172 } 8173 8174 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 8175 8176 /* XML must be nul-terminated. 8177 */ 8178 if (requestBuffer[requestLength - 1] != '\0') { 8179 OSKextLog(/* kext */ NULL, 8180 kOSKextLogErrorLevel | 8181 kOSKextLogIPCFlag, 8182 "Invalid request from user space (not nul-terminated)."); 8183 result = kOSKextReturnBadData; 8184 goto finish; 8185 } 8186 parsedXML = OSUnserializeXML((const char *)requestBuffer, &errorString); 8187 if (parsedXML) { 8188 requestDict = OSDynamicCast(OSDictionary, parsedXML); 8189 } 8190 if (!requestDict) { 8191 const char * errorCString = "(unknown error)"; 8192 8193 if (errorString && errorString->getCStringNoCopy()) { 8194 errorCString = errorString->getCStringNoCopy(); 8195 } else if (parsedXML) { 8196 errorCString = "not a dictionary"; 8197 } 8198 OSKextLog(/* kext */ NULL, 8199 kOSKextLogErrorLevel | 8200 kOSKextLogIPCFlag, 8201 "Error unserializing request from user space: %s.", 8202 errorCString); 8203 result = kOSKextReturnSerialization; 8204 goto finish; 8205 } 8206 8207 predicate = _OSKextGetRequestPredicate(requestDict); 8208 if (!predicate) { 8209 OSKextLog(/* kext */ NULL, 8210 kOSKextLogErrorLevel | 8211 kOSKextLogIPCFlag, 8212 "Recieved kext request from user space with no predicate."); 8213 result = kOSKextReturnInvalidArgument; 8214 goto finish; 8215 } 8216 8217 OSKextLog(/* kext */ NULL, 8218 kOSKextLogDebugLevel | 8219 kOSKextLogIPCFlag, 8220 "Received '%s' request from user space.", 8221 predicate->getCStringNoCopy()); 8222 8223 result = kOSKextReturnNotPrivileged; 8224 if (hostPriv == HOST_PRIV_NULL) { 8225 /* must be root to use these kext requests */ 8226 if (predicate->isEqualTo(kKextRequestPredicateUnload) || 8227 predicate->isEqualTo(kKextRequestPredicateStart) || 8228 predicate->isEqualTo(kKextRequestPredicateStop) || 8229 predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) || 8230 predicate->isEqualTo(kKextRequestPredicateSendResource)) { 8231 OSKextLog(/* kext */ NULL, 8232 kOSKextLogErrorLevel | 8233 kOSKextLogIPCFlag, 8234 "Access Failure - must be root user."); 8235 goto finish; 8236 } 8237 } 8238 8239 /* Get common args in anticipation of use. 8240 */ 8241 kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument( 8242 requestDict, kKextRequestArgumentBundleIdentifierKey)); 8243 kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 8244 requestDict, kKextRequestArgumentBundleIdentifierKey)); 8245 if (kextIdentifier) { 8246 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 8247 } 8248 boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 8249 requestDict, kKextRequestArgumentValueKey)); 8250 8251 result = kOSKextReturnInvalidArgument; 8252 8253 if (predicate->isEqualTo(kKextRequestPredicateStart)) { 8254 if (!kextIdentifier) { 8255 OSKextLog(/* kext */ NULL, 8256 kOSKextLogErrorLevel | 8257 kOSKextLogIPCFlag, 8258 "Invalid arguments to kext start request."); 8259 } else if (!theKext) { 8260 OSKextLog(/* kext */ NULL, 8261 kOSKextLogErrorLevel | 8262 kOSKextLogIPCFlag, 8263 "Kext %s not found for start request.", 8264 kextIdentifier->getCStringNoCopy()); 8265 result = kOSKextReturnNotFound; 8266 } else { 8267 result = theKext->start(); 8268 } 8269 } else if (predicate->isEqualTo(kKextRequestPredicateStop)) { 8270 if (!kextIdentifier) { 8271 OSKextLog(/* kext */ NULL, 8272 kOSKextLogErrorLevel | 8273 kOSKextLogIPCFlag, 8274 "Invalid arguments to kext stop request."); 8275 } else if (!theKext) { 8276 OSKextLog(/* kext */ NULL, 8277 kOSKextLogErrorLevel | 8278 kOSKextLogIPCFlag, 8279 "Kext %s not found for stop request.", 8280 kextIdentifier->getCStringNoCopy()); 8281 result = kOSKextReturnNotFound; 8282 } else { 8283 result = theKext->stop(); 8284 } 8285 } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) { 8286 if (!kextIdentifier) { 8287 OSKextLog(/* kext */ NULL, 8288 kOSKextLogErrorLevel | 8289 kOSKextLogIPCFlag, 8290 "Invalid arguments to kext unload request."); 8291 } else if (!theKext) { 8292 OSKextLog(/* kext */ NULL, 8293 kOSKextLogErrorLevel | 8294 kOSKextLogIPCFlag, 8295 "Kext %s not found for unload request.", 8296 kextIdentifier->getCStringNoCopy()); 8297 result = kOSKextReturnNotFound; 8298 } else { 8299 OSBoolean * terminateFlag = OSDynamicCast(OSBoolean, 8300 _OSKextGetRequestArgument(requestDict, 8301 kKextRequestArgumentTerminateIOServicesKey)); 8302 result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue); 8303 } 8304 } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) { 8305 result = OSKext::dispatchResource(requestDict); 8306 } else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) { 8307 OSNumber *lookupNum = NULL; 8308 lookupNum = OSDynamicCast(OSNumber, 8309 _OSKextGetRequestArgument(requestDict, 8310 kKextRequestArgumentLookupAddressKey)); 8311 8312 responseObject = OSKext::copyKextUUIDForAddress(lookupNum); 8313 if (responseObject) { 8314 result = kOSReturnSuccess; 8315 } else { 8316 goto finish; 8317 } 8318 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) || 8319 predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) { 8320 OSBoolean * delayAutounloadBool = NULL; 8321 OSObject * infoKeysRaw = NULL; 8322 OSArray * infoKeys = NULL; 8323 uint32_t infoKeysCount = 0; 8324 8325 delayAutounloadBool = OSDynamicCast(OSBoolean, 8326 _OSKextGetRequestArgument(requestDict, 8327 kKextRequestArgumentDelayAutounloadKey)); 8328 8329 /* If asked to delay autounload, reset the timer if it's currently set. 8330 * (That is, don't schedule an unload if one isn't already pending. 8331 */ 8332 if (delayAutounloadBool == kOSBooleanTrue) { 8333 OSKext::considerUnloads(/* rescheduleOnly? */ true); 8334 } 8335 8336 infoKeysRaw = _OSKextGetRequestArgument(requestDict, 8337 kKextRequestArgumentInfoKeysKey); 8338 infoKeys = OSDynamicCast(OSArray, infoKeysRaw); 8339 if (infoKeysRaw && !infoKeys) { 8340 OSKextLog(/* kext */ NULL, 8341 kOSKextLogErrorLevel | 8342 kOSKextLogIPCFlag, 8343 "Invalid arguments to kext info request."); 8344 goto finish; 8345 } 8346 8347 if (infoKeys) { 8348 infoKeysCount = infoKeys->getCount(); 8349 for (uint32_t i = 0; i < infoKeysCount; i++) { 8350 if (!OSDynamicCast(OSString, infoKeys->getObject(i))) { 8351 OSKextLog(/* kext */ NULL, 8352 kOSKextLogErrorLevel | 8353 kOSKextLogIPCFlag, 8354 "Invalid arguments to kext info request."); 8355 goto finish; 8356 } 8357 } 8358 } 8359 8360 if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) { 8361 responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys); 8362 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) { 8363 responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys); 8364 } 8365 if (!responseObject) { 8366 result = kOSKextReturnInternalError; 8367 } else { 8368 OSKextLog(/* kext */ NULL, 8369 kOSKextLogDebugLevel | 8370 kOSKextLogIPCFlag, 8371 "Returning loaded kext info."); 8372 result = kOSReturnSuccess; 8373 } 8374 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 8375 /* Hand the current sKernelRequests array to the caller 8376 * (who must release it), and make a new one. 8377 */ 8378 responseObject = sKernelRequests; 8379 sKernelRequests = OSArray::withCapacity(0); 8380 sPostedKextLoadIdentifiers->flushCollection(); 8381 OSKextLog(/* kext */ NULL, 8382 kOSKextLogDebugLevel | 8383 kOSKextLogIPCFlag, 8384 "Returning kernel requests."); 8385 result = kOSReturnSuccess; 8386 } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) { 8387 /* Return the set of all requested bundle identifiers */ 8388 responseObject = sAllKextLoadIdentifiers; 8389 responseObject->retain(); 8390 OSKextLog(/* kext */ NULL, 8391 kOSKextLogDebugLevel | 8392 kOSKextLogIPCFlag, 8393 "Returning load requests."); 8394 result = kOSReturnSuccess; 8395 } else { 8396 OSKextLog(/* kext */ NULL, 8397 kOSKextLogDebugLevel | 8398 kOSKextLogIPCFlag, 8399 "Received '%s' invalid request from user space.", 8400 predicate->getCStringNoCopy()); 8401 goto finish; 8402 } 8403 8404 /********** 8405 * Now we have handle the request, or not. Gather up the response & logging 8406 * info to ship to user space. 8407 *********/ 8408 8409 /* Note: Nothing in OSKext is supposed to retain requestDict, 8410 * but you never know.... 8411 */ 8412 if (requestDict->getRetainCount() > 1) { 8413 OSKextLog(/* kext */ NULL, 8414 kOSKextLogWarningLevel | 8415 kOSKextLogIPCFlag, 8416 "Request from user space still retained by a kext; " 8417 "probable memory leak."); 8418 } 8419 8420 if (responseOut && responseObject) { 8421 serializer = OSSerialize::withCapacity(0); 8422 if (!serializer) { 8423 result = kOSKextReturnNoMemory; 8424 goto finish; 8425 } 8426 8427 if (!responseObject->serialize(serializer)) { 8428 OSKextLog(/* kext */ NULL, 8429 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 8430 "Failed to serialize response to request from user space."); 8431 result = kOSKextReturnSerialization; 8432 goto finish; 8433 } 8434 8435 response = (char *)serializer->text(); 8436 responseLength = serializer->getLength(); 8437 } 8438 8439 if (responseOut && response) { 8440 char * buffer; 8441 8442 /* This kmem_alloc sets the return value of the function. 8443 */ 8444 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, 8445 round_page(responseLength), VM_KERN_MEMORY_OSKEXT); 8446 if (kmem_result != KERN_SUCCESS) { 8447 OSKextLog(/* kext */ NULL, 8448 kOSKextLogErrorLevel | 8449 kOSKextLogIPCFlag, 8450 "Failed to copy response to request from user space."); 8451 result = kmem_result; 8452 goto finish; 8453 } else { 8454 /* 11981737 - clear uninitialized data in last page */ 8455 bzero((void *)(buffer + responseLength), 8456 (round_page(responseLength) - responseLength)); 8457 memcpy(buffer, response, responseLength); 8458 *responseOut = buffer; 8459 *responseLengthOut = responseLength; 8460 } 8461 } 8462 8463 finish: 8464 8465 /* Gather up the collected log messages for user space. Any messages 8466 * messages past this call will not make it up as log messages but 8467 * will be in the system log. Note that we ignore the return of the 8468 * serialize; it has no bearing on the operation at hand even if we 8469 * fail to get the log messages. 8470 */ 8471 logInfoArray = OSKext::clearUserSpaceLogFilter(); 8472 8473 if (logInfoArray && logInfoOut && logInfoLengthOut) { 8474 (void)OSKext::serializeLogInfo(logInfoArray, 8475 logInfoOut, logInfoLengthOut); 8476 } 8477 8478 IORecursiveLockUnlock(sKextLock); 8479 8480 OSSafeReleaseNULL(parsedXML); 8481 OSSafeReleaseNULL(errorString); 8482 OSSafeReleaseNULL(responseObject); 8483 OSSafeReleaseNULL(serializer); 8484 OSSafeReleaseNULL(logInfoArray); 8485 8486 return result; 8487 } 8488 8489 8490 // #include <InstrProfiling.h> 8491 extern "C" { 8492 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin, 8493 const char *DataEnd, 8494 const char *CountersBegin, 8495 const char *CountersEnd, 8496 const char *NamesBegin, 8497 const char *NamesEnd); 8498 int __llvm_profile_write_buffer_internal(char *Buffer, 8499 const char *DataBegin, 8500 const char *DataEnd, 8501 const char *CountersBegin, 8502 const char *CountersEnd, 8503 const char *NamesBegin, 8504 const char *NamesEnd); 8505 } 8506 8507 8508 static 8509 void 8510 OSKextPgoMetadataPut(char *pBuffer, 8511 size_t *position, 8512 size_t bufferSize, 8513 uint32_t *num_pairs, 8514 const char *key, 8515 const char *value) 8516 { 8517 size_t strlen_key = strlen(key); 8518 size_t strlen_value = strlen(value); 8519 size_t len = strlen(key) + 1 + strlen(value) + 1; 8520 char *pos = pBuffer + *position; 8521 *position += len; 8522 if (pBuffer && bufferSize && *position <= bufferSize) { 8523 memcpy(pos, key, strlen_key); pos += strlen_key; 8524 *(pos++) = '='; 8525 memcpy(pos, value, strlen_value); pos += strlen_value; 8526 *(pos++) = 0; 8527 if (num_pairs) { 8528 (*num_pairs)++; 8529 } 8530 } 8531 } 8532 8533 8534 static 8535 void 8536 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max) 8537 { 8538 *position += strlen(key) + 1 + value_max + 1; 8539 } 8540 8541 8542 static 8543 void 8544 OSKextPgoMetadataPutAll(OSKext *kext, 8545 uuid_t instance_uuid, 8546 char *pBuffer, 8547 size_t *position, 8548 size_t bufferSize, 8549 uint32_t *num_pairs) 8550 { 8551 _static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0); 8552 //log_10 2^16 ≈ 4.82 8553 const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2; 8554 const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6; 8555 8556 if (!pBuffer) { 8557 OSKextPgoMetadataPutMax(position, "INSTANCE", 36); 8558 OSKextPgoMetadataPutMax(position, "UUID", 36); 8559 OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size); 8560 } else { 8561 uuid_string_t instance_uuid_string; 8562 uuid_unparse(instance_uuid, instance_uuid_string); 8563 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 8564 "INSTANCE", instance_uuid_string); 8565 8566 OSData *uuid_data; 8567 uuid_t uuid; 8568 uuid_string_t uuid_string; 8569 uuid_data = kext->copyUUID(); 8570 if (uuid_data) { 8571 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 8572 OSSafeReleaseNULL(uuid_data); 8573 uuid_unparse(uuid, uuid_string); 8574 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 8575 "UUID", uuid_string); 8576 } 8577 8578 clock_sec_t secs; 8579 clock_usec_t usecs; 8580 clock_get_calendar_microtime(&secs, &usecs); 8581 assert(usecs < 1000000); 8582 char timestamp[max_timestamp_string_size + 1]; 8583 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t)); 8584 snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs); 8585 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 8586 "TIMESTAMP", timestamp); 8587 } 8588 8589 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 8590 "NAME", kext->getIdentifierCString()); 8591 8592 char versionCString[kOSKextVersionMaxLength]; 8593 OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength); 8594 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 8595 "VERSION", versionCString); 8596 } 8597 8598 static 8599 size_t 8600 OSKextPgoMetadataSize(OSKext *kext) 8601 { 8602 size_t position = 0; 8603 uuid_t fakeuuid = {}; 8604 OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL); 8605 return position; 8606 } 8607 8608 int 8609 OSKextGrabPgoDataLocked(OSKext *kext, 8610 bool metadata, 8611 uuid_t instance_uuid, 8612 uint64_t *pSize, 8613 char *pBuffer, 8614 uint64_t bufferSize) 8615 { 8616 int err = 0; 8617 8618 kernel_section_t *sect_prf_data = NULL; 8619 kernel_section_t *sect_prf_name = NULL; 8620 kernel_section_t *sect_prf_cnts = NULL; 8621 uint64_t size; 8622 size_t metadata_size = 0; 8623 8624 sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data"); 8625 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names"); 8626 if (!sect_prf_name) { 8627 // kextcache sometimes truncates the section name to 15 chars 8628 // <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache 8629 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name"); 8630 } 8631 sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 8632 8633 if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) { 8634 err = ENOTSUP; 8635 goto out; 8636 } 8637 8638 size = __llvm_profile_get_size_for_buffer_internal( 8639 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 8640 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 8641 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 8642 8643 if (metadata) { 8644 metadata_size = OSKextPgoMetadataSize(kext); 8645 size += metadata_size; 8646 size += sizeof(pgo_metadata_footer); 8647 } 8648 8649 8650 if (pSize) { 8651 *pSize = size; 8652 } 8653 8654 if (pBuffer && bufferSize) { 8655 if (bufferSize < size) { 8656 err = ERANGE; 8657 goto out; 8658 } 8659 8660 err = __llvm_profile_write_buffer_internal( 8661 pBuffer, 8662 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 8663 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 8664 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 8665 8666 if (err) { 8667 err = EIO; 8668 goto out; 8669 } 8670 8671 if (metadata) { 8672 char *end_of_buffer = pBuffer + size; 8673 struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer)); 8674 char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size); 8675 8676 size_t metadata_position = 0; 8677 uint32_t num_pairs = 0; 8678 OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs); 8679 while (metadata_position < metadata_size) { 8680 metadata_buffer[metadata_position++] = 0; 8681 } 8682 8683 struct pgo_metadata_footer footer; 8684 footer.magic = htonl(0x6d657461); 8685 footer.number_of_pairs = htonl( num_pairs ); 8686 footer.offset_to_pairs = htonl( sizeof(struct pgo_metadata_footer) + metadata_size ); 8687 memcpy(footerp, &footer, sizeof(footer)); 8688 } 8689 } 8690 8691 out: 8692 return err; 8693 } 8694 8695 8696 int 8697 OSKextGrabPgoData(uuid_t uuid, 8698 uint64_t *pSize, 8699 char *pBuffer, 8700 uint64_t bufferSize, 8701 int wait_for_unload, 8702 int metadata) 8703 { 8704 int err = 0; 8705 OSKext *kext = NULL; 8706 8707 8708 IORecursiveLockLock(sKextLock); 8709 8710 kext = OSKext::lookupKextWithUUID(uuid); 8711 if (!kext) { 8712 err = ENOENT; 8713 goto out; 8714 } 8715 8716 if (wait_for_unload) { 8717 OSKextGrabPgoStruct s; 8718 8719 s.metadata = metadata; 8720 s.pSize = pSize; 8721 s.pBuffer = pBuffer; 8722 s.bufferSize = bufferSize; 8723 s.err = EINTR; 8724 8725 struct list_head *prev = &kext->pendingPgoHead; 8726 struct list_head *next = kext->pendingPgoHead.next; 8727 8728 s.list_head.prev = prev; 8729 s.list_head.next = next; 8730 8731 prev->next = &s.list_head; 8732 next->prev = &s.list_head; 8733 8734 kext->release(); 8735 kext = NULL; 8736 8737 IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE); 8738 8739 prev = s.list_head.prev; 8740 next = s.list_head.next; 8741 8742 prev->next = next; 8743 next->prev = prev; 8744 8745 err = s.err; 8746 } else { 8747 err = OSKextGrabPgoDataLocked(kext, metadata, kext->instance_uuid, pSize, pBuffer, bufferSize); 8748 } 8749 8750 out: 8751 if (kext) { 8752 kext->release(); 8753 } 8754 8755 IORecursiveLockUnlock(sKextLock); 8756 8757 return err; 8758 } 8759 8760 void 8761 OSKextResetPgoCountersLock() 8762 { 8763 IORecursiveLockLock(sKextLock); 8764 } 8765 8766 void 8767 OSKextResetPgoCountersUnlock() 8768 { 8769 IORecursiveLockUnlock(sKextLock); 8770 } 8771 8772 8773 extern unsigned int not_in_kdp; 8774 8775 void 8776 OSKextResetPgoCounters() 8777 { 8778 assert(!not_in_kdp); 8779 uint32_t count = sLoadedKexts->getCount(); 8780 for (uint32_t i = 0; i < count; i++) { 8781 OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 8782 kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 8783 if (!sect_prf_cnts) { 8784 continue; 8785 } 8786 memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size); 8787 } 8788 } 8789 8790 OSDictionary * 8791 OSKext::copyLoadedKextInfoByUUID( 8792 OSArray * kextIdentifiers, 8793 OSArray * infoKeys) 8794 { 8795 OSDictionary * result = NULL; 8796 OSDictionary * kextInfo = NULL; // must release 8797 uint32_t max_count, i, j; 8798 uint32_t idCount = 0; 8799 uint32_t idIndex = 0; 8800 IORecursiveLockLock(sKextLock); 8801 OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts}; 8802 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 8803 8804 #if CONFIG_MACF 8805 /* Is the calling process allowed to query kext info? */ 8806 if (current_task() != kernel_task) { 8807 int macCheckResult = 0; 8808 kauth_cred_t cred = NULL; 8809 8810 cred = kauth_cred_get_with_ref(); 8811 macCheckResult = mac_kext_check_query(cred); 8812 kauth_cred_unref(&cred); 8813 8814 if (macCheckResult != 0) { 8815 OSKextLog(/* kext */ NULL, 8816 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 8817 "Failed to query kext info (MAC policy error 0x%x).", 8818 macCheckResult); 8819 goto finish; 8820 } 8821 } 8822 #endif 8823 8824 /* Empty list of UUIDs is equivalent to no list (get all). 8825 */ 8826 if (kextIdentifiers && !kextIdentifiers->getCount()) { 8827 kextIdentifiers = NULL; 8828 } else if (kextIdentifiers) { 8829 idCount = kextIdentifiers->getCount(); 8830 } 8831 8832 /* Same for keys. 8833 */ 8834 if (infoKeys && !infoKeys->getCount()) { 8835 infoKeys = NULL; 8836 } 8837 8838 max_count = count[0] + count[1]; 8839 result = OSDictionary::withCapacity(max_count); 8840 if (!result) { 8841 goto finish; 8842 } 8843 8844 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 8845 for (i = 0; i < count[j]; i++) { 8846 OSKext *thisKext = NULL;// do not release 8847 Boolean includeThis = true; 8848 uuid_t thisKextUUID; 8849 uuid_t thisKextTextUUID; 8850 OSData *uuid_data; 8851 uuid_string_t uuid_key; 8852 8853 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 8854 if (!thisKext) { 8855 continue; 8856 } 8857 8858 uuid_data = thisKext->copyUUID(); 8859 if (!uuid_data) { 8860 continue; 8861 } 8862 8863 memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID)); 8864 OSSafeReleaseNULL(uuid_data); 8865 8866 uuid_unparse(thisKextUUID, uuid_key); 8867 8868 uuid_data = thisKext->copyTextUUID(); 8869 if (!uuid_data) { 8870 continue; 8871 } 8872 memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID)); 8873 OSSafeReleaseNULL(uuid_data); 8874 8875 /* Skip current kext if we have a list of UUIDs and 8876 * it isn't in the list. 8877 */ 8878 if (kextIdentifiers) { 8879 includeThis = false; 8880 8881 for (idIndex = 0; idIndex < idCount; idIndex++) { 8882 const OSString* wantedUUID = OSDynamicCast(OSString, 8883 kextIdentifiers->getObject(idIndex)); 8884 8885 uuid_t uuid; 8886 uuid_parse(wantedUUID->getCStringNoCopy(), uuid); 8887 8888 if ((0 == uuid_compare(uuid, thisKextUUID)) 8889 || (0 == uuid_compare(uuid, thisKextTextUUID))) { 8890 includeThis = true; 8891 /* Only need to find the first kext if multiple match, 8892 * ie. asking for the kernel uuid does not need to find 8893 * interface kexts or builtin static kexts. 8894 */ 8895 kextIdentifiers->removeObject(idIndex); 8896 uuid_unparse(uuid, uuid_key); 8897 break; 8898 } 8899 } 8900 } 8901 8902 if (!includeThis) { 8903 continue; 8904 } 8905 8906 kextInfo = thisKext->copyInfo(infoKeys); 8907 if (kextInfo) { 8908 result->setObject(uuid_key, kextInfo); 8909 kextInfo->release(); 8910 } 8911 8912 if (kextIdentifiers && !kextIdentifiers->getCount()) { 8913 goto finish; 8914 } 8915 } 8916 } 8917 8918 finish: 8919 IORecursiveLockUnlock(sKextLock); 8920 8921 return result; 8922 } 8923 8924 /********************************************************************* 8925 *********************************************************************/ 8926 /* static */ 8927 OSDictionary * 8928 OSKext::copyLoadedKextInfo( 8929 OSArray * kextIdentifiers, 8930 OSArray * infoKeys) 8931 { 8932 OSDictionary * result = NULL; 8933 uint32_t idCount = 0; 8934 bool onlyLoaded; 8935 8936 IORecursiveLockLock(sKextLock); 8937 8938 #if CONFIG_MACF 8939 /* Is the calling process allowed to query kext info? */ 8940 if (current_task() != kernel_task) { 8941 int macCheckResult = 0; 8942 kauth_cred_t cred = NULL; 8943 8944 cred = kauth_cred_get_with_ref(); 8945 macCheckResult = mac_kext_check_query(cred); 8946 kauth_cred_unref(&cred); 8947 8948 if (macCheckResult != 0) { 8949 OSKextLog(/* kext */ NULL, 8950 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 8951 "Failed to query kext info (MAC policy error 0x%x).", 8952 macCheckResult); 8953 goto finish; 8954 } 8955 } 8956 #endif 8957 8958 /* Empty list of bundle ids is equivalent to no list (get all). 8959 */ 8960 if (kextIdentifiers && !kextIdentifiers->getCount()) { 8961 kextIdentifiers = NULL; 8962 } else if (kextIdentifiers) { 8963 idCount = kextIdentifiers->getCount(); 8964 } 8965 8966 /* Same for keys. 8967 */ 8968 if (infoKeys && !infoKeys->getCount()) { 8969 infoKeys = NULL; 8970 } 8971 8972 onlyLoaded = (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey)); 8973 8974 result = OSDictionary::withCapacity(128); 8975 if (!result) { 8976 goto finish; 8977 } 8978 8979 #if 0 8980 OSKextLog(/* kext */ NULL, 8981 kOSKextLogErrorLevel | 8982 kOSKextLogGeneralFlag, 8983 "kaslr: vm_kernel_slide 0x%lx \n", 8984 vm_kernel_slide); 8985 OSKextLog(/* kext */ NULL, 8986 kOSKextLogErrorLevel | 8987 kOSKextLogGeneralFlag, 8988 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n", 8989 vm_kernel_stext, vm_kernel_etext); 8990 OSKextLog(/* kext */ NULL, 8991 kOSKextLogErrorLevel | 8992 kOSKextLogGeneralFlag, 8993 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n", 8994 vm_kernel_base, vm_kernel_top); 8995 OSKextLog(/* kext */ NULL, 8996 kOSKextLogErrorLevel | 8997 kOSKextLogGeneralFlag, 8998 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n", 8999 vm_kext_base, vm_kext_top); 9000 OSKextLog(/* kext */ NULL, 9001 kOSKextLogErrorLevel | 9002 kOSKextLogGeneralFlag, 9003 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n", 9004 vm_prelink_stext, vm_prelink_etext); 9005 OSKextLog(/* kext */ NULL, 9006 kOSKextLogErrorLevel | 9007 kOSKextLogGeneralFlag, 9008 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n", 9009 vm_prelink_sinfo, vm_prelink_einfo); 9010 OSKextLog(/* kext */ NULL, 9011 kOSKextLogErrorLevel | 9012 kOSKextLogGeneralFlag, 9013 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n", 9014 vm_slinkedit, vm_elinkedit); 9015 #endif 9016 9017 sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj) 9018 { 9019 OSKext * thisKext = NULL;// do not release 9020 Boolean includeThis = true; 9021 OSDictionary * kextInfo = NULL;// must release 9022 9023 thisKext = OSDynamicCast(OSKext, obj); 9024 if (!thisKext) { 9025 return false;; 9026 } 9027 9028 /* Skip current kext if not yet started and caller didn't request all. 9029 */ 9030 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 9031 return false;; 9032 } 9033 9034 /* Skip current kext if we have a list of bundle IDs and 9035 * it isn't in the list. 9036 */ 9037 if (kextIdentifiers) { 9038 includeThis = false; 9039 9040 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) { 9041 const OSString * thisRequestID = OSDynamicCast(OSString, 9042 kextIdentifiers->getObject(idIndex)); 9043 if (thisKextID->isEqualTo(thisRequestID)) { 9044 includeThis = true; 9045 break; 9046 } 9047 } 9048 } 9049 9050 if (!includeThis) { 9051 return false; 9052 } 9053 9054 kextInfo = thisKext->copyInfo(infoKeys); 9055 if (kextInfo) { 9056 result->setObject(thisKext->getIdentifier(), kextInfo); 9057 kextInfo->release(); 9058 } 9059 return false; 9060 }); 9061 9062 finish: 9063 IORecursiveLockUnlock(sKextLock); 9064 9065 return result; 9066 } 9067 9068 /********************************************************************* 9069 * Any info that needs to do allocations must goto finish on alloc 9070 * failure. Info that is just a lookup should just not set the object 9071 * if the info does not exist. 9072 *********************************************************************/ 9073 #define _OSKextLoadInfoDictCapacity (12) 9074 9075 OSDictionary * 9076 OSKext::copyInfo(OSArray * infoKeys) 9077 { 9078 OSDictionary * result = NULL; 9079 bool success = false; 9080 OSData * headerData = NULL;// must release 9081 OSData * logData = NULL;// must release 9082 OSNumber * cpuTypeNumber = NULL;// must release 9083 OSNumber * cpuSubtypeNumber = NULL;// must release 9084 OSString * versionString = NULL;// do not release 9085 uint32_t executablePathCStringSize = 0; 9086 char * executablePathCString = NULL;// must release 9087 OSString * executablePathString = NULL;// must release 9088 OSData * uuid = NULL;// must release 9089 OSNumber * scratchNumber = NULL;// must release 9090 OSArray * dependencyLoadTags = NULL;// must release 9091 OSCollectionIterator * metaClassIterator = NULL;// must release 9092 OSArray * metaClassInfo = NULL;// must release 9093 OSDictionary * metaClassDict = NULL;// must release 9094 OSMetaClass * thisMetaClass = NULL;// do not release 9095 OSString * metaClassName = NULL;// must release 9096 OSString * superclassName = NULL;// must release 9097 uint32_t count, i; 9098 9099 result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity); 9100 if (!result) { 9101 goto finish; 9102 } 9103 9104 9105 /* Empty keys means no keys, but NULL is quicker to check. 9106 */ 9107 if (infoKeys && !infoKeys->getCount()) { 9108 infoKeys = NULL; 9109 } 9110 9111 /* Headers, CPU type, and CPU subtype. 9112 */ 9113 if (!infoKeys || 9114 _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) || 9115 _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) || 9116 _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) || 9117 _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 9118 if (linkedExecutable && !isInterface()) { 9119 kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *) 9120 linkedExecutable->getBytesNoCopy(); 9121 9122 #if !SECURE_KERNEL 9123 // do not return macho header info on shipping iOS - 19095897 9124 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) { 9125 kernel_mach_header_t * temp_kext_mach_hdr; 9126 struct load_command * lcp; 9127 9128 headerData = OSData::withBytes(kext_mach_hdr, 9129 (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds)); 9130 if (!headerData) { 9131 goto finish; 9132 } 9133 9134 // unslide any vmaddrs we return to userspace - 10726716 9135 temp_kext_mach_hdr = (kernel_mach_header_t *) 9136 headerData->getBytesNoCopy(); 9137 if (temp_kext_mach_hdr == NULL) { 9138 goto finish; 9139 } 9140 9141 lcp = (struct load_command *) (temp_kext_mach_hdr + 1); 9142 for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) { 9143 if (lcp->cmd == LC_SEGMENT_KERNEL) { 9144 kernel_segment_command_t * segp; 9145 kernel_section_t * secp; 9146 9147 segp = (kernel_segment_command_t *) lcp; 9148 // 10543468 - if we jettisoned __LINKEDIT clear size info 9149 if (flags.jettisonLinkeditSeg) { 9150 if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) { 9151 segp->vmsize = 0; 9152 segp->fileoff = 0; 9153 segp->filesize = 0; 9154 } 9155 } 9156 9157 #if 0 9158 OSKextLog(/* kext */ NULL, 9159 kOSKextLogErrorLevel | 9160 kOSKextLogGeneralFlag, 9161 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u", 9162 __FUNCTION__, segp->segname, segp->vmaddr, 9163 VM_KERNEL_UNSLIDE(segp->vmaddr), 9164 segp->vmsize, segp->nsects); 9165 if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) && 9166 (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) && 9167 (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) && 9168 (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) && 9169 (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) { 9170 OSKextLog(/* kext */ NULL, 9171 kOSKextLogErrorLevel | 9172 kOSKextLogGeneralFlag, 9173 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX", 9174 __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top); 9175 } 9176 #endif 9177 segp->vmaddr = ml_static_unslide(segp->vmaddr); 9178 9179 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { 9180 secp->addr = ml_static_unslide(secp->addr); 9181 } 9182 } 9183 lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize); 9184 } 9185 result->setObject(kOSBundleMachOHeadersKey, headerData); 9186 } 9187 #endif // SECURE_KERNEL 9188 9189 if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) { 9190 osLogDataHeaderRef *header; 9191 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])]; 9192 9193 void *os_log_data = NULL; 9194 void *cstring_data = NULL; 9195 unsigned long os_log_size = 0; 9196 unsigned long cstring_size = 0; 9197 uint32_t os_log_offset = 0; 9198 uint32_t cstring_offset = 0; 9199 bool res; 9200 9201 os_log_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size); 9202 os_log_offset = getsectoffsetfromheader(kext_mach_hdr, "__TEXT", "__os_log"); 9203 cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size); 9204 cstring_offset = getsectoffsetfromheader(kext_mach_hdr, "__TEXT", "__cstring"); 9205 9206 header = (osLogDataHeaderRef *) headerBytes; 9207 header->version = OS_LOG_HDR_VERSION; 9208 header->sect_count = NUM_OS_LOG_SECTIONS; 9209 header->sections[OS_LOG_SECT_IDX].sect_offset = os_log_offset; 9210 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) os_log_size; 9211 header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset; 9212 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) cstring_size; 9213 9214 9215 logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef))); 9216 if (!logData) { 9217 goto finish; 9218 } 9219 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0]))); 9220 if (!res) { 9221 goto finish; 9222 } 9223 if (os_log_data) { 9224 res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size); 9225 if (!res) { 9226 goto finish; 9227 } 9228 } 9229 if (cstring_data) { 9230 res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size); 9231 if (!res) { 9232 goto finish; 9233 } 9234 } 9235 result->setObject(kOSBundleLogStringsKey, logData); 9236 } 9237 9238 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) { 9239 cpuTypeNumber = OSNumber::withNumber( 9240 (uint64_t) kext_mach_hdr->cputype, 9241 8 * sizeof(kext_mach_hdr->cputype)); 9242 if (!cpuTypeNumber) { 9243 goto finish; 9244 } 9245 result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber); 9246 } 9247 9248 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 9249 cpuSubtypeNumber = OSNumber::withNumber( 9250 (uint64_t) kext_mach_hdr->cpusubtype, 9251 8 * sizeof(kext_mach_hdr->cpusubtype)); 9252 if (!cpuSubtypeNumber) { 9253 goto finish; 9254 } 9255 result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber); 9256 } 9257 } else { 9258 if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) { 9259 osLogDataHeaderRef *header; 9260 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])]; 9261 bool res; 9262 9263 header = (osLogDataHeaderRef *) headerBytes; 9264 header->version = OS_LOG_HDR_VERSION; 9265 header->sect_count = NUM_OS_LOG_SECTIONS; 9266 header->sections[OS_LOG_SECT_IDX].sect_offset = 0; 9267 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) 0; 9268 header->sections[CSTRING_SECT_IDX].sect_offset = 0; 9269 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) 0; 9270 9271 logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef))); 9272 if (!logData) { 9273 goto finish; 9274 } 9275 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0]))); 9276 if (!res) { 9277 goto finish; 9278 } 9279 result->setObject(kOSBundleLogStringsKey, logData); 9280 } 9281 } 9282 } 9283 9284 /* CFBundleIdentifier. We set this regardless because it's just stupid not to. 9285 */ 9286 result->setObject(kCFBundleIdentifierKey, bundleID); 9287 9288 /* CFBundleVersion. 9289 */ 9290 if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) { 9291 versionString = OSDynamicCast(OSString, 9292 getPropertyForHostArch(kCFBundleVersionKey)); 9293 if (versionString) { 9294 result->setObject(kCFBundleVersionKey, versionString); 9295 } 9296 } 9297 9298 /* OSBundleCompatibleVersion. 9299 */ 9300 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) { 9301 versionString = OSDynamicCast(OSString, 9302 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 9303 if (versionString) { 9304 result->setObject(kOSBundleCompatibleVersionKey, versionString); 9305 } 9306 } 9307 9308 /* Path. 9309 */ 9310 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) { 9311 if (path) { 9312 result->setObject(kOSBundlePathKey, path); 9313 } 9314 } 9315 9316 9317 /* OSBundleExecutablePath. 9318 */ 9319 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) { 9320 if (path && executableRelPath) { 9321 uint32_t pathLength = path->getLength(); // gets incremented below 9322 9323 // +1 for slash, +1 for \0 9324 executablePathCStringSize = pathLength + executableRelPath->getLength() + 2; 9325 9326 executablePathCString = (char *)kalloc_tag((executablePathCStringSize) * 9327 sizeof(char), VM_KERN_MEMORY_OSKEXT); // +1 for \0 9328 if (!executablePathCString) { 9329 goto finish; 9330 } 9331 strlcpy(executablePathCString, path->getCStringNoCopy(), 9332 executablePathCStringSize); 9333 executablePathCString[pathLength++] = '/'; 9334 executablePathCString[pathLength++] = '\0'; 9335 strlcat(executablePathCString, executableRelPath->getCStringNoCopy(), 9336 executablePathCStringSize); 9337 9338 executablePathString = OSString::withCString(executablePathCString); 9339 9340 if (!executablePathString) { 9341 goto finish; 9342 } 9343 9344 result->setObject(kOSBundleExecutablePathKey, executablePathString); 9345 } else if (flags.builtin) { 9346 result->setObject(kOSBundleExecutablePathKey, bundleID); 9347 } else if (isDriverKit()) { 9348 if (path) { 9349 // +1 for slash, +1 for \0 9350 uint32_t pathLength = path->getLength(); 9351 executablePathCStringSize = pathLength + 2; 9352 9353 executablePathCString = (char *)kalloc_tag((executablePathCStringSize) * 9354 sizeof(char), VM_KERN_MEMORY_OSKEXT); 9355 if (!executablePathCString) { 9356 goto finish; 9357 } 9358 strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize); 9359 executablePathCString[pathLength++] = '/'; 9360 executablePathCString[pathLength++] = '\0'; 9361 9362 executablePathString = OSString::withCString(executablePathCString); 9363 9364 if (!executablePathString) { 9365 goto finish; 9366 } 9367 9368 result->setObject(kOSBundleExecutablePathKey, executablePathString); 9369 } 9370 } 9371 } 9372 9373 /* UUID, if the kext has one. 9374 */ 9375 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) { 9376 uuid = copyUUID(); 9377 if (uuid) { 9378 result->setObject(kOSBundleUUIDKey, uuid); 9379 uuid->release(); 9380 } 9381 } 9382 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) { 9383 uuid = copyTextUUID(); 9384 if (uuid) { 9385 result->setObject(kOSBundleTextUUIDKey, uuid); uuid->release(); 9386 } 9387 } 9388 9389 /***** 9390 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted. 9391 */ 9392 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) { 9393 result->setObject(kOSKernelResourceKey, 9394 isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse); 9395 } 9396 9397 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) { 9398 result->setObject(kOSBundleIsInterfaceKey, 9399 isInterface() ? kOSBooleanTrue : kOSBooleanFalse); 9400 } 9401 9402 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) { 9403 result->setObject(kOSBundlePrelinkedKey, 9404 isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse); 9405 } 9406 9407 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) { 9408 result->setObject(kOSBundleStartedKey, 9409 isStarted() ? kOSBooleanTrue : kOSBooleanFalse); 9410 } 9411 9412 /* LoadTag (Index). 9413 */ 9414 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) { 9415 scratchNumber = OSNumber::withNumber((unsigned long long)loadTag, 9416 /* numBits */ 8 * sizeof(loadTag)); 9417 if (!scratchNumber) { 9418 goto finish; 9419 } 9420 result->setObject(kOSBundleLoadTagKey, scratchNumber); 9421 OSSafeReleaseNULL(scratchNumber); 9422 } 9423 9424 /* LoadAddress, LoadSize. 9425 */ 9426 if (!infoKeys || 9427 _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) || 9428 _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) || 9429 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) || 9430 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) || 9431 _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 9432 bool is_dext = isDriverKit(); 9433 if (isInterface() || flags.builtin || linkedExecutable || is_dext) { 9434 /* These go to userspace via serialization, so we don't want any doubts 9435 * about their size. 9436 */ 9437 uint64_t loadAddress = 0; 9438 uint32_t loadSize = 0; 9439 uint32_t wiredSize = 0; 9440 uint64_t execLoadAddress = 0; 9441 uint32_t execLoadSize = 0; 9442 9443 /* Interfaces always report 0 load address & size. 9444 * Just the way they roll. 9445 * 9446 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp 9447 * xxx - shouldn't have one! 9448 */ 9449 9450 if (flags.builtin || linkedExecutable) { 9451 kernel_mach_header_t *mh = NULL; 9452 kernel_segment_command_t *seg = NULL; 9453 9454 if (flags.builtin) { 9455 loadAddress = kmod_info->address; 9456 loadSize = kmod_info->size; 9457 } else { 9458 loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy(); 9459 loadSize = linkedExecutable->getLength(); 9460 } 9461 mh = (kernel_mach_header_t *)loadAddress; 9462 loadAddress = ml_static_unslide(loadAddress); 9463 9464 /* Walk through the kext, looking for the first executable 9465 * segment in case we were asked for its size/address. 9466 */ 9467 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 9468 if (seg->initprot & VM_PROT_EXECUTE) { 9469 execLoadAddress = ml_static_unslide(seg->vmaddr); 9470 execLoadSize = seg->vmsize; 9471 break; 9472 } 9473 } 9474 9475 /* If we have a kmod_info struct, calculated the wired size 9476 * from that. Otherwise it's the full load size. 9477 */ 9478 if (kmod_info) { 9479 wiredSize = loadSize - kmod_info->hdr_size; 9480 } else { 9481 wiredSize = loadSize; 9482 } 9483 } else if (is_dext) { 9484 /* 9485 * DriverKit userspace executables do not have a kernel linkedExecutable, 9486 * so we "fake" their address range with the LoadTag. 9487 */ 9488 if (loadTag) { 9489 loadAddress = execLoadAddress = loadTag; 9490 loadSize = execLoadSize = 1; 9491 } 9492 } 9493 9494 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) { 9495 scratchNumber = OSNumber::withNumber( 9496 (unsigned long long)(loadAddress), 9497 /* numBits */ 8 * sizeof(loadAddress)); 9498 if (!scratchNumber) { 9499 goto finish; 9500 } 9501 result->setObject(kOSBundleLoadAddressKey, scratchNumber); 9502 OSSafeReleaseNULL(scratchNumber); 9503 } 9504 #if CONFIG_EMBEDDED 9505 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey)) 9506 && loadAddress && loadSize) { 9507 scratchNumber = OSNumber::withNumber( 9508 (unsigned long long)ml_static_unslide((uintptr_t)segLOWESTTEXT), 9509 /* numBits */ 8 * sizeof(loadAddress)); 9510 if (!scratchNumber) { 9511 goto finish; 9512 } 9513 result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber); 9514 OSSafeReleaseNULL(scratchNumber); 9515 } 9516 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey)) 9517 && (this == sKernelKext) && gBuiltinKmodsCount) { 9518 result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue); 9519 } 9520 #endif /* CONFIG_EMBEDDED */ 9521 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) { 9522 scratchNumber = OSNumber::withNumber( 9523 (unsigned long long)(execLoadAddress), 9524 /* numBits */ 8 * sizeof(execLoadAddress)); 9525 if (!scratchNumber) { 9526 goto finish; 9527 } 9528 result->setObject(kOSBundleExecLoadAddressKey, scratchNumber); 9529 OSSafeReleaseNULL(scratchNumber); 9530 } 9531 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) { 9532 scratchNumber = OSNumber::withNumber( 9533 (unsigned long long)(loadSize), 9534 /* numBits */ 8 * sizeof(loadSize)); 9535 if (!scratchNumber) { 9536 goto finish; 9537 } 9538 result->setObject(kOSBundleLoadSizeKey, scratchNumber); 9539 OSSafeReleaseNULL(scratchNumber); 9540 } 9541 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) { 9542 scratchNumber = OSNumber::withNumber( 9543 (unsigned long long)(execLoadSize), 9544 /* numBits */ 8 * sizeof(execLoadSize)); 9545 if (!scratchNumber) { 9546 goto finish; 9547 } 9548 result->setObject(kOSBundleExecLoadSizeKey, scratchNumber); 9549 OSSafeReleaseNULL(scratchNumber); 9550 } 9551 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 9552 scratchNumber = OSNumber::withNumber( 9553 (unsigned long long)(wiredSize), 9554 /* numBits */ 8 * sizeof(wiredSize)); 9555 if (!scratchNumber) { 9556 goto finish; 9557 } 9558 result->setObject(kOSBundleWiredSizeKey, scratchNumber); 9559 OSSafeReleaseNULL(scratchNumber); 9560 } 9561 } 9562 } 9563 9564 /* OSBundleDependencies. In descending order for 9565 * easy compatibility with kextstat(8). 9566 */ 9567 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) { 9568 if ((count = getNumDependencies())) { 9569 dependencyLoadTags = OSArray::withCapacity(count); 9570 result->setObject(kOSBundleDependenciesKey, dependencyLoadTags); 9571 9572 i = count - 1; 9573 do { 9574 OSKext * dependency = OSDynamicCast(OSKext, 9575 dependencies->getObject(i)); 9576 9577 OSSafeReleaseNULL(scratchNumber); 9578 9579 if (!dependency) { 9580 continue; 9581 } 9582 scratchNumber = OSNumber::withNumber( 9583 (unsigned long long)dependency->getLoadTag(), 9584 /* numBits*/ 8 * sizeof(loadTag)); 9585 if (!scratchNumber) { 9586 goto finish; 9587 } 9588 dependencyLoadTags->setObject(scratchNumber); 9589 } while (i--); 9590 } 9591 } 9592 9593 OSSafeReleaseNULL(scratchNumber); 9594 9595 /* OSBundleMetaClasses. 9596 */ 9597 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) { 9598 if (metaClasses && metaClasses->getCount()) { 9599 metaClassIterator = OSCollectionIterator::withCollection(metaClasses); 9600 metaClassInfo = OSArray::withCapacity(metaClasses->getCount()); 9601 if (!metaClassIterator || !metaClassInfo) { 9602 goto finish; 9603 } 9604 result->setObject(kOSBundleClassesKey, metaClassInfo); 9605 9606 while ((thisMetaClass = OSDynamicCast(OSMetaClass, 9607 metaClassIterator->getNextObject()))) { 9608 OSSafeReleaseNULL(metaClassDict); 9609 OSSafeReleaseNULL(scratchNumber); 9610 OSSafeReleaseNULL(metaClassName); 9611 OSSafeReleaseNULL(superclassName); 9612 9613 metaClassDict = OSDictionary::withCapacity(3); 9614 if (!metaClassDict) { 9615 goto finish; 9616 } 9617 9618 metaClassName = OSString::withCString(thisMetaClass->getClassName()); 9619 if (thisMetaClass->getSuperClass()) { 9620 superclassName = OSString::withCString( 9621 thisMetaClass->getSuperClass()->getClassName()); 9622 } 9623 scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(), 9624 8 * sizeof(unsigned int)); 9625 9626 /* Bail if any of the essentials is missing. The root class lacks a superclass, 9627 * of course. 9628 */ 9629 if (!metaClassDict || !metaClassName || !scratchNumber) { 9630 goto finish; 9631 } 9632 9633 metaClassInfo->setObject(metaClassDict); 9634 metaClassDict->setObject(kOSMetaClassNameKey, metaClassName); 9635 if (superclassName) { 9636 metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName); 9637 } 9638 metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber); 9639 } 9640 } 9641 } 9642 9643 /* OSBundleRetainCount. 9644 */ 9645 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) { 9646 OSSafeReleaseNULL(scratchNumber); 9647 { 9648 int kextRetainCount = getRetainCount() - 1; 9649 if (isLoaded()) { 9650 kextRetainCount--; 9651 } 9652 scratchNumber = OSNumber::withNumber( 9653 (int)kextRetainCount, 9654 /* numBits*/ 8 * sizeof(int)); 9655 if (scratchNumber) { 9656 result->setObject(kOSBundleRetainCountKey, scratchNumber); 9657 } 9658 } 9659 } 9660 9661 success = true; 9662 9663 finish: 9664 OSSafeReleaseNULL(headerData); 9665 OSSafeReleaseNULL(logData); 9666 OSSafeReleaseNULL(cpuTypeNumber); 9667 OSSafeReleaseNULL(cpuSubtypeNumber); 9668 OSSafeReleaseNULL(executablePathString); 9669 if (executablePathCString) { 9670 kfree(executablePathCString, executablePathCStringSize); 9671 } 9672 OSSafeReleaseNULL(scratchNumber); 9673 OSSafeReleaseNULL(dependencyLoadTags); 9674 OSSafeReleaseNULL(metaClassIterator); 9675 OSSafeReleaseNULL(metaClassInfo); 9676 OSSafeReleaseNULL(metaClassDict); 9677 OSSafeReleaseNULL(metaClassName); 9678 OSSafeReleaseNULL(superclassName); 9679 if (!success) { 9680 OSSafeReleaseNULL(result); 9681 } 9682 return result; 9683 } 9684 9685 /********************************************************************* 9686 *********************************************************************/ 9687 /* static */ 9688 bool 9689 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize) 9690 { 9691 bool ok; 9692 OSKext * kext; 9693 9694 IORecursiveLockLock(sKextLock); 9695 kext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)); 9696 if (kext) { 9697 kext->retain(); 9698 } 9699 IORecursiveLockUnlock(sKextLock); 9700 9701 if (!kext || !kext->path || !kext->userExecutableRelPath) { 9702 OSSafeReleaseNULL(kext); 9703 return false; 9704 } 9705 snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s", 9706 kext->path->getCStringNoCopy(), 9707 kext->userExecutableRelPath->getCStringNoCopy()); 9708 ok = true; 9709 kext->release(); 9710 9711 return ok; 9712 } 9713 9714 /********************************************************************* 9715 *********************************************************************/ 9716 /* static */ 9717 OSReturn 9718 OSKext::requestResource( 9719 const char * kextIdentifierCString, 9720 const char * resourceNameCString, 9721 OSKextRequestResourceCallback callback, 9722 void * context, 9723 OSKextRequestTag * requestTagOut) 9724 { 9725 OSReturn result = kOSReturnError; 9726 OSKext * callbackKext = NULL;// must release (looked up) 9727 9728 OSKextRequestTag requestTag = -1; 9729 OSNumber * requestTagNum = NULL;// must release 9730 9731 OSDictionary * requestDict = NULL;// must release 9732 OSString * kextIdentifier = NULL;// must release 9733 OSString * resourceName = NULL;// must release 9734 9735 OSDictionary * callbackRecord = NULL;// must release 9736 OSData * callbackWrapper = NULL;// must release 9737 9738 OSData * contextWrapper = NULL;// must release 9739 9740 IORecursiveLockLock(sKextLock); 9741 9742 if (requestTagOut) { 9743 *requestTagOut = kOSKextRequestTagInvalid; 9744 } 9745 9746 /* If requests to user space are disabled, don't go any further */ 9747 if (!sKernelRequestsEnabled) { 9748 OSKextLog(/* kext */ NULL, 9749 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 9750 "Can't request resource %s for %s - requests to user space are disabled.", 9751 resourceNameCString, 9752 kextIdentifierCString); 9753 result = kOSKextReturnDisabled; 9754 goto finish; 9755 } 9756 9757 if (!kextIdentifierCString || !resourceNameCString || !callback) { 9758 result = kOSKextReturnInvalidArgument; 9759 goto finish; 9760 } 9761 9762 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 9763 if (!callbackKext) { 9764 OSKextLog(/* kext */ NULL, 9765 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 9766 "Resource request has bad callback address."); 9767 result = kOSKextReturnInvalidArgument; 9768 goto finish; 9769 } 9770 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 9771 OSKextLog(/* kext */ NULL, 9772 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 9773 "Resource request callback is in a kext that is not started."); 9774 result = kOSKextReturnInvalidArgument; 9775 goto finish; 9776 } 9777 9778 /* Do not allow any new requests to be made on a kext that is unloading. 9779 */ 9780 if (callbackKext->flags.stopping) { 9781 result = kOSKextReturnStopping; 9782 goto finish; 9783 } 9784 9785 /* If we're wrapped the next available request tag around to the negative 9786 * numbers, we can't service any more requests. 9787 */ 9788 if (sNextRequestTag == kOSKextRequestTagInvalid) { 9789 OSKextLog(/* kext */ NULL, 9790 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 9791 "No more request tags available; restart required."); 9792 result = kOSKextReturnNoResources; 9793 goto finish; 9794 } 9795 requestTag = sNextRequestTag++; 9796 9797 result = _OSKextCreateRequest(kKextRequestPredicateRequestResource, 9798 &requestDict); 9799 if (result != kOSReturnSuccess) { 9800 goto finish; 9801 } 9802 9803 kextIdentifier = OSString::withCString(kextIdentifierCString); 9804 resourceName = OSString::withCString(resourceNameCString); 9805 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 9806 8 * sizeof(requestTag)); 9807 if (!kextIdentifier || 9808 !resourceName || 9809 !requestTagNum || 9810 !_OSKextSetRequestArgument(requestDict, 9811 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) || 9812 !_OSKextSetRequestArgument(requestDict, 9813 kKextRequestArgumentNameKey, resourceName) || 9814 !_OSKextSetRequestArgument(requestDict, 9815 kKextRequestArgumentRequestTagKey, requestTagNum)) { 9816 result = kOSKextReturnNoMemory; 9817 goto finish; 9818 } 9819 9820 callbackRecord = OSDynamicCast(OSDictionary, requestDict->copyCollection()); 9821 if (!callbackRecord) { 9822 result = kOSKextReturnNoMemory; 9823 goto finish; 9824 } 9825 // we validate callback address at call time 9826 callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *)); 9827 if (context) { 9828 contextWrapper = OSData::withBytes((void *)&context, sizeof(void *)); 9829 } 9830 if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord, 9831 kKextRequestArgumentCallbackKey, callbackWrapper)) { 9832 result = kOSKextReturnNoMemory; 9833 goto finish; 9834 } 9835 9836 if (context) { 9837 if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord, 9838 kKextRequestArgumentContextKey, contextWrapper)) { 9839 result = kOSKextReturnNoMemory; 9840 goto finish; 9841 } 9842 } 9843 9844 /* Only post the requests after all the other potential failure points 9845 * have been passed. 9846 */ 9847 if (!sKernelRequests->setObject(requestDict) || 9848 !sRequestCallbackRecords->setObject(callbackRecord)) { 9849 result = kOSKextReturnNoMemory; 9850 goto finish; 9851 } 9852 9853 OSKext::pingKextd(); 9854 9855 result = kOSReturnSuccess; 9856 if (requestTagOut) { 9857 *requestTagOut = requestTag; 9858 } 9859 9860 finish: 9861 9862 /* If we didn't succeed, yank the request & callback 9863 * from their holding arrays. 9864 */ 9865 if (result != kOSReturnSuccess) { 9866 unsigned int index; 9867 9868 index = sKernelRequests->getNextIndexOfObject(requestDict, 0); 9869 if (index != (unsigned int)-1) { 9870 sKernelRequests->removeObject(index); 9871 } 9872 index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord, 0); 9873 if (index != (unsigned int)-1) { 9874 sRequestCallbackRecords->removeObject(index); 9875 } 9876 } 9877 9878 OSKext::considerUnloads(/* rescheduleOnly? */ true); 9879 9880 IORecursiveLockUnlock(sKextLock); 9881 9882 if (callbackKext) { 9883 callbackKext->release(); 9884 } 9885 if (requestTagNum) { 9886 requestTagNum->release(); 9887 } 9888 9889 if (requestDict) { 9890 requestDict->release(); 9891 } 9892 if (kextIdentifier) { 9893 kextIdentifier->release(); 9894 } 9895 if (resourceName) { 9896 resourceName->release(); 9897 } 9898 9899 if (callbackRecord) { 9900 callbackRecord->release(); 9901 } 9902 if (callbackWrapper) { 9903 callbackWrapper->release(); 9904 } 9905 if (contextWrapper) { 9906 contextWrapper->release(); 9907 } 9908 9909 return result; 9910 } 9911 9912 OSReturn 9913 OSKext::requestDaemonLaunch( 9914 OSString *kextIdentifier, 9915 OSString *serverName, 9916 OSNumber *serverTag) 9917 { 9918 OSReturn result = kOSReturnError; 9919 OSDictionary * requestDict = NULL; // must release 9920 9921 if (!kextIdentifier || !serverName || !serverTag) { 9922 result = kOSKextReturnInvalidArgument; 9923 goto finish; 9924 } 9925 9926 IORecursiveLockLock(sKextLock); 9927 9928 OSKextLog(/* kext */ NULL, 9929 kOSKextLogDebugLevel | 9930 kOSKextLogGeneralFlag, 9931 "Requesting daemon launch for %s with serverName %s and tag %llu", 9932 kextIdentifier->getCStringNoCopy(), 9933 serverName->getCStringNoCopy(), 9934 serverTag->unsigned64BitValue() 9935 ); 9936 9937 result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, &requestDict); 9938 if (result != kOSReturnSuccess) { 9939 goto finish; 9940 } 9941 9942 if (!_OSKextSetRequestArgument(requestDict, 9943 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) || 9944 !_OSKextSetRequestArgument(requestDict, 9945 kKextRequestArgumentDriverExtensionServerName, serverName) || 9946 !_OSKextSetRequestArgument(requestDict, 9947 kKextRequestArgumentDriverExtensionServerTag, serverTag)) { 9948 result = kOSKextReturnNoMemory; 9949 goto finish; 9950 } 9951 9952 /* Only post the requests after all the other potential failure points 9953 * have been passed. 9954 */ 9955 if (!sKernelRequests->setObject(requestDict)) { 9956 result = kOSKextReturnNoMemory; 9957 goto finish; 9958 } 9959 OSKext::pingKextd(); 9960 9961 result = kOSReturnSuccess; 9962 finish: 9963 IORecursiveLockUnlock(sKextLock); 9964 if (requestDict) { 9965 requestDict->release(); 9966 } 9967 return result; 9968 } 9969 9970 /********************************************************************* 9971 * Assumes sKextLock is held. 9972 *********************************************************************/ 9973 /* static */ 9974 OSReturn 9975 OSKext::dequeueCallbackForRequestTag( 9976 OSKextRequestTag requestTag, 9977 OSDictionary ** callbackRecordOut) 9978 { 9979 OSReturn result = kOSReturnError; 9980 OSNumber * requestTagNum = NULL;// must release 9981 9982 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 9983 8 * sizeof(requestTag)); 9984 if (!requestTagNum) { 9985 goto finish; 9986 } 9987 9988 result = OSKext::dequeueCallbackForRequestTag(requestTagNum, 9989 callbackRecordOut); 9990 9991 finish: 9992 OSSafeReleaseNULL(requestTagNum); 9993 9994 return result; 9995 } 9996 9997 /********************************************************************* 9998 * Assumes sKextLock is held. 9999 *********************************************************************/ 10000 /* static */ 10001 OSReturn 10002 OSKext::dequeueCallbackForRequestTag( 10003 OSNumber * requestTagNum, 10004 OSDictionary ** callbackRecordOut) 10005 { 10006 OSReturn result = kOSKextReturnInvalidArgument; 10007 OSDictionary * callbackRecord = NULL;// retain if matched! 10008 OSNumber * callbackTagNum = NULL;// do not release 10009 unsigned int count, i; 10010 10011 result = kOSReturnError; 10012 count = sRequestCallbackRecords->getCount(); 10013 for (i = 0; i < count; i++) { 10014 callbackRecord = OSDynamicCast(OSDictionary, 10015 sRequestCallbackRecords->getObject(i)); 10016 if (!callbackRecord) { 10017 goto finish; 10018 } 10019 10020 /* If we don't find a tag, we basically have a leak here. Maybe 10021 * we should just remove it. 10022 */ 10023 callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument( 10024 callbackRecord, kKextRequestArgumentRequestTagKey)); 10025 if (!callbackTagNum) { 10026 goto finish; 10027 } 10028 10029 /* We could be even more paranoid and check that all the incoming 10030 * args match what's in the callback record. 10031 */ 10032 if (callbackTagNum->isEqualTo(requestTagNum)) { 10033 if (callbackRecordOut) { 10034 *callbackRecordOut = callbackRecord; 10035 callbackRecord->retain(); 10036 } 10037 sRequestCallbackRecords->removeObject(i); 10038 result = kOSReturnSuccess; 10039 goto finish; 10040 } 10041 } 10042 result = kOSKextReturnNotFound; 10043 10044 finish: 10045 return result; 10046 } 10047 10048 10049 /********************************************************************* 10050 * Busy timeout triage 10051 *********************************************************************/ 10052 /* static */ 10053 bool 10054 OSKext::isWaitingKextd(void) 10055 { 10056 return sRequestCallbackRecords && sRequestCallbackRecords->getCount(); 10057 } 10058 10059 /********************************************************************* 10060 * Assumes sKextLock is held. 10061 *********************************************************************/ 10062 /* static */ 10063 OSReturn 10064 OSKext::dispatchResource(OSDictionary * requestDict) 10065 { 10066 OSReturn result = kOSReturnError; 10067 OSDictionary * callbackRecord = NULL;// must release 10068 OSNumber * requestTag = NULL;// do not release 10069 OSNumber * requestResult = NULL;// do not release 10070 OSData * dataObj = NULL;// do not release 10071 uint32_t dataLength = 0; 10072 const void * dataPtr = NULL;// do not free 10073 OSData * callbackWrapper = NULL;// do not release 10074 OSKextRequestResourceCallback callback = NULL; 10075 OSData * contextWrapper = NULL;// do not release 10076 void * context = NULL;// do not free 10077 OSKext * callbackKext = NULL;// must release (looked up) 10078 10079 /* Get the args from the request. Right now we need the tag 10080 * to look up the callback record, and the result for invoking the callback. 10081 */ 10082 requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 10083 kKextRequestArgumentRequestTagKey)); 10084 requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 10085 kKextRequestArgumentResultKey)); 10086 if (!requestTag || !requestResult) { 10087 result = kOSKextReturnInvalidArgument; 10088 goto finish; 10089 } 10090 10091 /* Look for a callback record matching this request's tag. 10092 */ 10093 result = dequeueCallbackForRequestTag(requestTag, &callbackRecord); 10094 if (result != kOSReturnSuccess) { 10095 goto finish; 10096 } 10097 10098 /***** 10099 * Get the context pointer of the callback record (if there is one). 10100 */ 10101 contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord, 10102 kKextRequestArgumentContextKey)); 10103 context = _OSKextExtractPointer(contextWrapper); 10104 if (contextWrapper && !context) { 10105 goto finish; 10106 } 10107 10108 callbackWrapper = OSDynamicCast(OSData, 10109 _OSKextGetRequestArgument(callbackRecord, 10110 kKextRequestArgumentCallbackKey)); 10111 callback = (OSKextRequestResourceCallback) 10112 _OSKextExtractPointer(callbackWrapper); 10113 if (!callback) { 10114 goto finish; 10115 } 10116 10117 /* Check for a data obj. We might not have one and that's ok, that means 10118 * we didn't find the requested resource, and we still have to tell the 10119 * caller that via the callback. 10120 */ 10121 dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict, 10122 kKextRequestArgumentValueKey)); 10123 if (dataObj) { 10124 dataPtr = dataObj->getBytesNoCopy(); 10125 dataLength = dataObj->getLength(); 10126 } 10127 10128 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 10129 if (!callbackKext) { 10130 OSKextLog(/* kext */ NULL, 10131 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 10132 "Can't invoke callback for resource request; "); 10133 goto finish; 10134 } 10135 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 10136 OSKextLog(/* kext */ NULL, 10137 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 10138 "Can't invoke kext resource callback; "); 10139 goto finish; 10140 } 10141 10142 (void)callback(requestTag->unsigned32BitValue(), 10143 (OSReturn)requestResult->unsigned32BitValue(), 10144 dataPtr, dataLength, context); 10145 10146 result = kOSReturnSuccess; 10147 10148 finish: 10149 if (callbackKext) { 10150 callbackKext->release(); 10151 } 10152 if (callbackRecord) { 10153 callbackRecord->release(); 10154 } 10155 10156 return result; 10157 } 10158 10159 /********************************************************************* 10160 *********************************************************************/ 10161 /* static */ 10162 void 10163 OSKext::invokeRequestCallback( 10164 OSDictionary * callbackRecord, 10165 OSReturn callbackResult) 10166 { 10167 OSString * predicate = _OSKextGetRequestPredicate(callbackRecord); 10168 OSNumber * resultNum = NULL;// must release 10169 10170 if (!predicate) { 10171 goto finish; 10172 } 10173 10174 resultNum = OSNumber::withNumber((long long unsigned int)callbackResult, 10175 8 * sizeof(callbackResult)); 10176 if (!resultNum) { 10177 goto finish; 10178 } 10179 10180 /* Insert the result into the callback record and dispatch it as if it 10181 * were the reply coming down from user space. 10182 */ 10183 _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey, 10184 resultNum); 10185 10186 if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) { 10187 /* This removes the pending callback record. 10188 */ 10189 OSKext::dispatchResource(callbackRecord); 10190 } 10191 10192 finish: 10193 if (resultNum) { 10194 resultNum->release(); 10195 } 10196 return; 10197 } 10198 10199 /********************************************************************* 10200 * Assumes sKextLock is held. 10201 *********************************************************************/ 10202 /* static */ 10203 OSReturn 10204 OSKext::cancelRequest( 10205 OSKextRequestTag requestTag, 10206 void ** contextOut) 10207 { 10208 OSReturn result = kOSKextReturnNoMemory; 10209 OSDictionary * callbackRecord = NULL; // must release 10210 OSData * contextWrapper = NULL;// do not release 10211 10212 IORecursiveLockLock(sKextLock); 10213 result = OSKext::dequeueCallbackForRequestTag(requestTag, 10214 &callbackRecord); 10215 IORecursiveLockUnlock(sKextLock); 10216 10217 if (result == kOSReturnSuccess && contextOut) { 10218 contextWrapper = OSDynamicCast(OSData, 10219 _OSKextGetRequestArgument(callbackRecord, 10220 kKextRequestArgumentContextKey)); 10221 *contextOut = _OSKextExtractPointer(contextWrapper); 10222 } 10223 10224 if (callbackRecord) { 10225 callbackRecord->release(); 10226 } 10227 10228 return result; 10229 } 10230 10231 /********************************************************************* 10232 * Assumes sKextLock is held. 10233 *********************************************************************/ 10234 void 10235 OSKext::invokeOrCancelRequestCallbacks( 10236 OSReturn callbackResult, 10237 bool invokeFlag) 10238 { 10239 unsigned int count, i; 10240 10241 count = sRequestCallbackRecords->getCount(); 10242 if (!count) { 10243 goto finish; 10244 } 10245 10246 i = count - 1; 10247 do { 10248 OSDictionary * request = OSDynamicCast(OSDictionary, 10249 sRequestCallbackRecords->getObject(i)); 10250 10251 if (!request) { 10252 continue; 10253 } 10254 OSData * callbackWrapper = OSDynamicCast(OSData, 10255 _OSKextGetRequestArgument(request, 10256 kKextRequestArgumentCallbackKey)); 10257 10258 if (!callbackWrapper) { 10259 sRequestCallbackRecords->removeObject(i); 10260 continue; 10261 } 10262 10263 vm_address_t callbackAddress = (vm_address_t) 10264 _OSKextExtractPointer(callbackWrapper); 10265 10266 if ((kmod_info->address <= callbackAddress) && 10267 (callbackAddress < (kmod_info->address + kmod_info->size))) { 10268 if (invokeFlag) { 10269 /* This removes the callback record. 10270 */ 10271 invokeRequestCallback(request, callbackResult); 10272 } else { 10273 sRequestCallbackRecords->removeObject(i); 10274 } 10275 } 10276 } while (i--); 10277 10278 finish: 10279 return; 10280 } 10281 10282 /********************************************************************* 10283 * Assumes sKextLock is held. 10284 *********************************************************************/ 10285 uint32_t 10286 OSKext::countRequestCallbacks(void) 10287 { 10288 uint32_t result = 0; 10289 unsigned int count, i; 10290 10291 count = sRequestCallbackRecords->getCount(); 10292 if (!count) { 10293 goto finish; 10294 } 10295 10296 i = count - 1; 10297 do { 10298 OSDictionary * request = OSDynamicCast(OSDictionary, 10299 sRequestCallbackRecords->getObject(i)); 10300 10301 if (!request) { 10302 continue; 10303 } 10304 OSData * callbackWrapper = OSDynamicCast(OSData, 10305 _OSKextGetRequestArgument(request, 10306 kKextRequestArgumentCallbackKey)); 10307 10308 if (!callbackWrapper) { 10309 continue; 10310 } 10311 10312 vm_address_t callbackAddress = (vm_address_t) 10313 _OSKextExtractPointer(callbackWrapper); 10314 10315 if ((kmod_info->address <= callbackAddress) && 10316 (callbackAddress < (kmod_info->address + kmod_info->size))) { 10317 result++; 10318 } 10319 } while (i--); 10320 10321 finish: 10322 return result; 10323 } 10324 10325 /********************************************************************* 10326 *********************************************************************/ 10327 static OSReturn 10328 _OSKextCreateRequest( 10329 const char * predicate, 10330 OSDictionary ** requestP) 10331 { 10332 OSReturn result = kOSKextReturnNoMemory; 10333 OSDictionary * request = NULL; // must release on error 10334 10335 request = OSDictionary::withCapacity(2); 10336 if (!request) { 10337 goto finish; 10338 } 10339 result = _OSDictionarySetCStringValue(request, 10340 kKextRequestPredicateKey, predicate); 10341 if (result != kOSReturnSuccess) { 10342 goto finish; 10343 } 10344 result = kOSReturnSuccess; 10345 10346 finish: 10347 if (result != kOSReturnSuccess) { 10348 if (request) { 10349 request->release(); 10350 } 10351 } else { 10352 *requestP = request; 10353 } 10354 10355 return result; 10356 } 10357 10358 /********************************************************************* 10359 *********************************************************************/ 10360 static OSString * 10361 _OSKextGetRequestPredicate(OSDictionary * requestDict) 10362 { 10363 return OSDynamicCast(OSString, 10364 requestDict->getObject(kKextRequestPredicateKey)); 10365 } 10366 10367 /********************************************************************* 10368 *********************************************************************/ 10369 static OSObject * 10370 _OSKextGetRequestArgument( 10371 OSDictionary * requestDict, 10372 const char * argName) 10373 { 10374 OSDictionary * args = OSDynamicCast(OSDictionary, 10375 requestDict->getObject(kKextRequestArgumentsKey)); 10376 if (args) { 10377 return args->getObject(argName); 10378 } 10379 return NULL; 10380 } 10381 10382 /********************************************************************* 10383 *********************************************************************/ 10384 static bool 10385 _OSKextSetRequestArgument( 10386 OSDictionary * requestDict, 10387 const char * argName, 10388 OSObject * value) 10389 { 10390 OSDictionary * args = OSDynamicCast(OSDictionary, 10391 requestDict->getObject(kKextRequestArgumentsKey)); 10392 if (!args) { 10393 args = OSDictionary::withCapacity(2); 10394 if (!args) { 10395 goto finish; 10396 } 10397 requestDict->setObject(kKextRequestArgumentsKey, args); 10398 args->release(); 10399 } 10400 if (args) { 10401 return args->setObject(argName, value); 10402 } 10403 finish: 10404 return false; 10405 } 10406 10407 /********************************************************************* 10408 *********************************************************************/ 10409 static void * 10410 _OSKextExtractPointer(OSData * wrapper) 10411 { 10412 void * result = NULL; 10413 const void * resultPtr = NULL; 10414 10415 if (!wrapper) { 10416 goto finish; 10417 } 10418 resultPtr = wrapper->getBytesNoCopy(); 10419 result = *(void **)resultPtr; 10420 finish: 10421 return result; 10422 } 10423 10424 /********************************************************************* 10425 *********************************************************************/ 10426 static OSReturn 10427 _OSDictionarySetCStringValue( 10428 OSDictionary * dict, 10429 const char * cKey, 10430 const char * cValue) 10431 { 10432 OSReturn result = kOSKextReturnNoMemory; 10433 const OSSymbol * key = NULL; // must release 10434 OSString * value = NULL; // must release 10435 10436 key = OSSymbol::withCString(cKey); 10437 value = OSString::withCString(cValue); 10438 if (!key || !value) { 10439 goto finish; 10440 } 10441 if (dict->setObject(key, value)) { 10442 result = kOSReturnSuccess; 10443 } 10444 10445 finish: 10446 if (key) { 10447 key->release(); 10448 } 10449 if (value) { 10450 value->release(); 10451 } 10452 10453 return result; 10454 } 10455 10456 /********************************************************************* 10457 *********************************************************************/ 10458 static bool 10459 _OSArrayContainsCString( 10460 OSArray * array, 10461 const char * cString) 10462 { 10463 bool result = false; 10464 const OSSymbol * symbol = NULL; 10465 uint32_t count, i; 10466 10467 if (!array || !cString) { 10468 goto finish; 10469 } 10470 10471 symbol = OSSymbol::withCStringNoCopy(cString); 10472 if (!symbol) { 10473 goto finish; 10474 } 10475 10476 count = array->getCount(); 10477 for (i = 0; i < count; i++) { 10478 OSObject * thisObject = array->getObject(i); 10479 if (symbol->isEqualTo(thisObject)) { 10480 result = true; 10481 goto finish; 10482 } 10483 } 10484 10485 finish: 10486 if (symbol) { 10487 symbol->release(); 10488 } 10489 return result; 10490 } 10491 10492 /********************************************************************* 10493 * We really only care about boot / system start up related kexts. 10494 * We return true if we're less than REBUILD_MAX_TIME since start up, 10495 * otherwise return false. 10496 *********************************************************************/ 10497 bool 10498 _OSKextInPrelinkRebuildWindow(void) 10499 { 10500 static bool outside_the_window = false; 10501 AbsoluteTime my_abstime; 10502 UInt64 my_ns; 10503 SInt32 my_secs; 10504 10505 if (outside_the_window) { 10506 return false; 10507 } 10508 clock_get_uptime(&my_abstime); 10509 absolutetime_to_nanoseconds(my_abstime, &my_ns); 10510 my_secs = (SInt32)(my_ns / NSEC_PER_SEC); 10511 if (my_secs > REBUILD_MAX_TIME) { 10512 outside_the_window = true; 10513 return false; 10514 } 10515 return true; 10516 } 10517 10518 /********************************************************************* 10519 *********************************************************************/ 10520 bool 10521 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID ) 10522 { 10523 int unLoadedCount, i; 10524 bool result = false; 10525 10526 IORecursiveLockLock(sKextLock); 10527 10528 if (sUnloadedPrelinkedKexts == NULL) { 10529 goto finish; 10530 } 10531 unLoadedCount = sUnloadedPrelinkedKexts->getCount(); 10532 if (unLoadedCount == 0) { 10533 goto finish; 10534 } 10535 10536 for (i = 0; i < unLoadedCount; i++) { 10537 const OSSymbol * myBundleID;// do not release 10538 10539 myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i)); 10540 if (!myBundleID) { 10541 continue; 10542 } 10543 if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) { 10544 result = true; 10545 break; 10546 } 10547 } 10548 finish: 10549 IORecursiveLockUnlock(sKextLock); 10550 return result; 10551 } 10552 10553 #if PRAGMA_MARK 10554 #pragma mark Personalities (IOKit Drivers) 10555 #endif 10556 /********************************************************************* 10557 *********************************************************************/ 10558 /* static */ 10559 OSArray * 10560 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag) 10561 { 10562 OSArray * result = NULL;// returned 10563 OSCollectionIterator * kextIterator = NULL;// must release 10564 OSArray * personalities = NULL;// must release 10565 OSCollectionIterator * personalitiesIterator = NULL; // must release 10566 10567 OSString * kextID = NULL;// do not release 10568 OSKext * theKext = NULL;// do not release 10569 10570 IORecursiveLockLock(sKextLock); 10571 10572 /* Let's conservatively guess that any given kext has around 3 10573 * personalities for now. 10574 */ 10575 result = OSArray::withCapacity(sKextsByID->getCount() * 3); 10576 if (!result) { 10577 goto finish; 10578 } 10579 10580 kextIterator = OSCollectionIterator::withCollection(sKextsByID); 10581 if (!kextIterator) { 10582 goto finish; 10583 } 10584 10585 while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) { 10586 if (personalitiesIterator) { 10587 personalitiesIterator->release(); 10588 personalitiesIterator = NULL; 10589 } 10590 if (personalities) { 10591 personalities->release(); 10592 personalities = NULL; 10593 } 10594 10595 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID)); 10596 if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) { 10597 personalities = theKext->copyPersonalitiesArray(); 10598 if (!personalities) { 10599 continue; 10600 } 10601 result->merge(personalities); 10602 } else { 10603 // xxx - check for better place to put this log msg 10604 OSKextLog(theKext, 10605 kOSKextLogWarningLevel | 10606 kOSKextLogLoadFlag, 10607 "Kext %s is not loadable during safe boot; " 10608 "omitting its personalities.", 10609 theKext->getIdentifierCString()); 10610 } 10611 } 10612 10613 finish: 10614 IORecursiveLockUnlock(sKextLock); 10615 10616 if (kextIterator) { 10617 kextIterator->release(); 10618 } 10619 if (personalitiesIterator) { 10620 personalitiesIterator->release(); 10621 } 10622 if (personalities) { 10623 personalities->release(); 10624 } 10625 10626 return result; 10627 } 10628 10629 /********************************************************************* 10630 *********************************************************************/ 10631 /* static */ 10632 void 10633 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching) 10634 { 10635 int numPersonalities = 0; 10636 10637 OSKextLog(/* kext */ NULL, 10638 kOSKextLogStepLevel | 10639 kOSKextLogLoadFlag, 10640 "Sending all eligible registered kexts' personalities " 10641 "to the IOCatalogue %s.", 10642 startMatching ? "and starting matching" : "but not starting matching"); 10643 10644 OSArray * personalities = OSKext::copyAllKextPersonalities( 10645 /* filterSafeBootFlag */ true); 10646 10647 if (personalities) { 10648 gIOCatalogue->addDrivers(personalities, startMatching); 10649 numPersonalities = personalities->getCount(); 10650 personalities->release(); 10651 } 10652 10653 OSKextLog(/* kext */ NULL, 10654 kOSKextLogStepLevel | 10655 kOSKextLogLoadFlag, 10656 "%d kext personalit%s sent to the IOCatalogue; %s.", 10657 numPersonalities, numPersonalities > 0 ? "ies" : "y", 10658 startMatching ? "matching started" : "matching not started"); 10659 return; 10660 } 10661 10662 /********************************************************************* 10663 * Do not make a deep copy, just convert the IOKitPersonalities dict 10664 * to an array for sending to the IOCatalogue. 10665 *********************************************************************/ 10666 OSArray * 10667 OSKext::copyPersonalitiesArray(void) 10668 { 10669 OSArray * result = NULL; 10670 OSDictionary * personalities = NULL;// do not release 10671 OSCollectionIterator * personalitiesIterator = NULL;// must release 10672 10673 OSString * personalityName = NULL;// do not release 10674 OSString * personalityBundleIdentifier = NULL;// do not release 10675 10676 personalities = OSDynamicCast(OSDictionary, 10677 getPropertyForHostArch(kIOKitPersonalitiesKey)); 10678 if (!personalities) { 10679 goto finish; 10680 } 10681 10682 result = OSArray::withCapacity(personalities->getCount()); 10683 if (!result) { 10684 goto finish; 10685 } 10686 10687 personalitiesIterator = 10688 OSCollectionIterator::withCollection(personalities); 10689 if (!personalitiesIterator) { 10690 goto finish; 10691 } 10692 while ((personalityName = OSDynamicCast(OSString, 10693 personalitiesIterator->getNextObject()))) { 10694 OSDictionary * personality = OSDynamicCast(OSDictionary, 10695 personalities->getObject(personalityName)); 10696 10697 /****** 10698 * If the personality doesn't have a CFBundleIdentifier, or if it 10699 * differs from the kext's, insert the kext's ID so we can find it. 10700 * The publisher ID is used to remove personalities from bundles 10701 * correctly. 10702 */ 10703 personalityBundleIdentifier = OSDynamicCast(OSString, 10704 personality->getObject(kCFBundleIdentifierKey)); 10705 10706 if (!personalityBundleIdentifier) { 10707 personality->setObject(kCFBundleIdentifierKey, bundleID); 10708 } else if (!personalityBundleIdentifier->isEqualTo(bundleID)) { 10709 personality->setObject(kIOPersonalityPublisherKey, bundleID); 10710 } 10711 10712 result->setObject(personality); 10713 } 10714 10715 finish: 10716 if (personalitiesIterator) { 10717 personalitiesIterator->release(); 10718 } 10719 10720 return result; 10721 } 10722 10723 /********************************************************************* 10724 * Might want to change this to a bool return? 10725 *********************************************************************/ 10726 OSReturn 10727 OSKext::sendPersonalitiesToCatalog( 10728 bool startMatching, 10729 OSArray * personalityNames) 10730 { 10731 OSReturn result = kOSReturnSuccess; 10732 OSArray * personalitiesToSend = NULL;// must release 10733 OSDictionary * kextPersonalities = NULL;// do not release 10734 int count, i; 10735 10736 if (!sLoadEnabled) { 10737 OSKextLog(this, 10738 kOSKextLogErrorLevel | 10739 kOSKextLogLoadFlag, 10740 "Kext loading is disabled (attempt to start matching for kext %s).", 10741 getIdentifierCString()); 10742 result = kOSKextReturnDisabled; 10743 goto finish; 10744 } 10745 10746 if (sSafeBoot && !isLoadableInSafeBoot()) { 10747 OSKextLog(this, 10748 kOSKextLogErrorLevel | 10749 kOSKextLogLoadFlag, 10750 "Kext %s is not loadable during safe boot; " 10751 "not sending personalities to the IOCatalogue.", 10752 getIdentifierCString()); 10753 result = kOSKextReturnNotLoadable; 10754 goto finish; 10755 } 10756 10757 if (!personalityNames || !personalityNames->getCount()) { 10758 personalitiesToSend = copyPersonalitiesArray(); 10759 } else { 10760 kextPersonalities = OSDynamicCast(OSDictionary, 10761 getPropertyForHostArch(kIOKitPersonalitiesKey)); 10762 if (!kextPersonalities || !kextPersonalities->getCount()) { 10763 // not an error 10764 goto finish; 10765 } 10766 personalitiesToSend = OSArray::withCapacity(0); 10767 if (!personalitiesToSend) { 10768 result = kOSKextReturnNoMemory; 10769 goto finish; 10770 } 10771 count = personalityNames->getCount(); 10772 for (i = 0; i < count; i++) { 10773 OSString * name = OSDynamicCast(OSString, 10774 personalityNames->getObject(i)); 10775 if (!name) { 10776 continue; 10777 } 10778 OSDictionary * personality = OSDynamicCast(OSDictionary, 10779 kextPersonalities->getObject(name)); 10780 if (personality) { 10781 personalitiesToSend->setObject(personality); 10782 } 10783 } 10784 } 10785 if (personalitiesToSend) { 10786 unsigned numPersonalities = personalitiesToSend->getCount(); 10787 OSKextLog(this, 10788 kOSKextLogStepLevel | 10789 kOSKextLogLoadFlag, 10790 "Kext %s sending %d personalit%s to the IOCatalogue%s.", 10791 getIdentifierCString(), 10792 numPersonalities, 10793 numPersonalities > 1 ? "ies" : "y", 10794 startMatching ? " and starting matching" : " but not starting matching"); 10795 gIOCatalogue->addDrivers(personalitiesToSend, startMatching); 10796 } 10797 finish: 10798 if (personalitiesToSend) { 10799 personalitiesToSend->release(); 10800 } 10801 return result; 10802 } 10803 10804 /********************************************************************* 10805 * xxx - We should allow removing the kext's declared personalities, 10806 * xxx - even with other bundle identifiers. 10807 *********************************************************************/ 10808 void 10809 OSKext::removePersonalitiesFromCatalog(void) 10810 { 10811 OSDictionary * personality = NULL; // do not release 10812 10813 personality = OSDictionary::withCapacity(1); 10814 if (!personality) { 10815 goto finish; 10816 } 10817 personality->setObject(kCFBundleIdentifierKey, getIdentifier()); 10818 10819 OSKextLog(this, 10820 kOSKextLogStepLevel | 10821 kOSKextLogLoadFlag, 10822 "Kext %s removing all personalities naming it from the IOCatalogue.", 10823 getIdentifierCString()); 10824 10825 /* Have the IOCatalog remove all personalities matching this kext's 10826 * bundle ID and trigger matching anew. 10827 */ 10828 gIOCatalogue->removeDrivers(personality, /* startMatching */ true); 10829 10830 finish: 10831 if (personality) { 10832 personality->release(); 10833 } 10834 10835 return; 10836 } 10837 10838 10839 #if PRAGMA_MARK 10840 #pragma mark Logging 10841 #endif 10842 /********************************************************************* 10843 * Do not call any function that takes sKextLock here! 10844 *********************************************************************/ 10845 /* static */ 10846 OSKextLogSpec 10847 OSKext::setUserSpaceLogFilter( 10848 OSKextLogSpec newUserLogFilter, 10849 bool captureFlag) 10850 { 10851 OSKextLogSpec result; 10852 bool allocError = false; 10853 10854 /* Do not call any function that takes sKextLoggingLock during 10855 * this critical block. That means do logging after. 10856 */ 10857 IOLockLock(sKextLoggingLock); 10858 10859 result = sUserSpaceKextLogFilter; 10860 sUserSpaceKextLogFilter = newUserLogFilter; 10861 10862 if (newUserLogFilter && captureFlag && 10863 !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) { 10864 // xxx - do some measurements for a good initial capacity? 10865 sUserSpaceLogSpecArray = OSArray::withCapacity(0); 10866 sUserSpaceLogMessageArray = OSArray::withCapacity(0); 10867 10868 if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) { 10869 OSSafeReleaseNULL(sUserSpaceLogSpecArray); 10870 OSSafeReleaseNULL(sUserSpaceLogMessageArray); 10871 allocError = true; 10872 } 10873 } 10874 10875 IOLockUnlock(sKextLoggingLock); 10876 10877 /* If the config flag itself is changing, log the state change 10878 * going both ways, before setting up the user-space log arrays, 10879 * so that this is only logged in the kernel. 10880 */ 10881 if (result != newUserLogFilter) { 10882 OSKextLog(/* kext */ NULL, 10883 kOSKextLogDebugLevel | 10884 kOSKextLogGeneralFlag, 10885 "User-space log flags changed from 0x%x to 0x%x.", 10886 result, newUserLogFilter); 10887 } 10888 if (allocError) { 10889 OSKextLog(/* kext */ NULL, 10890 kOSKextLogErrorLevel | 10891 kOSKextLogGeneralFlag, 10892 "Failed to allocate user-space log message arrays."); 10893 } 10894 10895 return result; 10896 } 10897 10898 /********************************************************************* 10899 * Do not call any function that takes sKextLock here! 10900 *********************************************************************/ 10901 /* static */ 10902 OSArray * 10903 OSKext::clearUserSpaceLogFilter(void) 10904 { 10905 OSArray * result = NULL; 10906 OSKextLogSpec oldLogFilter; 10907 OSKextLogSpec newLogFilter = kOSKextLogSilentFilter; 10908 10909 /* Do not call any function that takes sKextLoggingLock during 10910 * this critical block. That means do logging after. 10911 */ 10912 IOLockLock(sKextLoggingLock); 10913 10914 result = OSArray::withCapacity(2); 10915 if (result) { 10916 result->setObject(sUserSpaceLogSpecArray); 10917 result->setObject(sUserSpaceLogMessageArray); 10918 } 10919 OSSafeReleaseNULL(sUserSpaceLogSpecArray); 10920 OSSafeReleaseNULL(sUserSpaceLogMessageArray); 10921 10922 oldLogFilter = sUserSpaceKextLogFilter; 10923 sUserSpaceKextLogFilter = newLogFilter; 10924 10925 IOLockUnlock(sKextLoggingLock); 10926 10927 /* If the config flag itself is changing, log the state change 10928 * going both ways, after tearing down the user-space log 10929 * arrays, so this is only logged within the kernel. 10930 */ 10931 if (oldLogFilter != newLogFilter) { 10932 OSKextLog(/* kext */ NULL, 10933 kOSKextLogDebugLevel | 10934 kOSKextLogGeneralFlag, 10935 "User-space log flags changed from 0x%x to 0x%x.", 10936 oldLogFilter, newLogFilter); 10937 } 10938 10939 return result; 10940 } 10941 10942 10943 /********************************************************************* 10944 * Do not call any function that takes sKextLock here! 10945 *********************************************************************/ 10946 /* static */ 10947 OSKextLogSpec 10948 OSKext::getUserSpaceLogFilter(void) 10949 { 10950 OSKextLogSpec result; 10951 10952 IOLockLock(sKextLoggingLock); 10953 result = sUserSpaceKextLogFilter; 10954 IOLockUnlock(sKextLoggingLock); 10955 10956 return result; 10957 } 10958 10959 /********************************************************************* 10960 * This function is called by OSMetaClass during kernel C++ setup. 10961 * Be careful what you access here; assume only OSKext::initialize() 10962 * has been called. 10963 * 10964 * Do not call any function that takes sKextLock here! 10965 *********************************************************************/ 10966 #define VTRESET "\033[0m" 10967 10968 #define VTBOLD "\033[1m" 10969 #define VTUNDER "\033[4m" 10970 10971 #define VTRED "\033[31m" 10972 #define VTGREEN "\033[32m" 10973 #define VTYELLOW "\033[33m" 10974 #define VTBLUE "\033[34m" 10975 #define VTMAGENTA "\033[35m" 10976 #define VTCYAN "\033[36m" 10977 10978 inline const char * 10979 colorForFlags(OSKextLogSpec flags) 10980 { 10981 OSKextLogSpec logLevel = flags & kOSKextLogLevelMask; 10982 10983 switch (logLevel) { 10984 case kOSKextLogErrorLevel: 10985 return VTRED VTBOLD; 10986 case kOSKextLogWarningLevel: 10987 return VTRED; 10988 case kOSKextLogBasicLevel: 10989 return VTYELLOW VTUNDER; 10990 case kOSKextLogProgressLevel: 10991 return VTYELLOW; 10992 case kOSKextLogStepLevel: 10993 return VTGREEN; 10994 case kOSKextLogDetailLevel: 10995 return VTCYAN; 10996 case kOSKextLogDebugLevel: 10997 return VTMAGENTA; 10998 default: 10999 return ""; // white 11000 } 11001 } 11002 11003 inline bool 11004 logSpecMatch( 11005 OSKextLogSpec msgLogSpec, 11006 OSKextLogSpec logFilter) 11007 { 11008 OSKextLogSpec filterKextGlobal = logFilter & kOSKextLogKextOrGlobalMask; 11009 OSKextLogSpec filterLevel = logFilter & kOSKextLogLevelMask; 11010 OSKextLogSpec filterFlags = logFilter & kOSKextLogFlagsMask; 11011 11012 OSKextLogSpec msgKextGlobal = msgLogSpec & kOSKextLogKextOrGlobalMask; 11013 OSKextLogSpec msgLevel = msgLogSpec & kOSKextLogLevelMask; 11014 OSKextLogSpec msgFlags = msgLogSpec & kOSKextLogFlagsMask; 11015 11016 /* Explicit messages always get logged. 11017 */ 11018 if (msgLevel == kOSKextLogExplicitLevel) { 11019 return true; 11020 } 11021 11022 /* Warnings and errors are logged regardless of the flags. 11023 */ 11024 if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) { 11025 return true; 11026 } 11027 11028 /* A verbose message that isn't for a logging-enabled kext and isn't global 11029 * does *not* get logged. 11030 */ 11031 if (!msgKextGlobal && !filterKextGlobal) { 11032 return false; 11033 } 11034 11035 /* Warnings and errors are logged regardless of the flags. 11036 * All other messages must fit the flags and 11037 * have a level at or below the filter. 11038 * 11039 */ 11040 if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) { 11041 return true; 11042 } 11043 return false; 11044 } 11045 11046 extern "C" { 11047 void 11048 OSKextLog( 11049 OSKext * aKext, 11050 OSKextLogSpec msgLogSpec, 11051 const char * format, ...) 11052 { 11053 va_list argList; 11054 11055 va_start(argList, format); 11056 OSKextVLog(aKext, msgLogSpec, format, argList); 11057 va_end(argList); 11058 } 11059 11060 void 11061 OSKextVLog( 11062 OSKext * aKext, 11063 OSKextLogSpec msgLogSpec, 11064 const char * format, 11065 va_list srcArgList) 11066 { 11067 extern int disableConsoleOutput; 11068 11069 bool logForKernel = false; 11070 bool logForUser = false; 11071 va_list argList; 11072 char stackBuffer[120]; 11073 uint32_t length = 0; 11074 char * allocBuffer = NULL; // must kfree 11075 OSNumber * logSpecNum = NULL; // must release 11076 OSString * logString = NULL; // must release 11077 char * buffer = stackBuffer;// do not free 11078 11079 IOLockLock(sKextLoggingLock); 11080 11081 /* Set the kext/global bit in the message spec if we have no 11082 * kext or if the kext requests logging. 11083 */ 11084 if (!aKext || aKext->flags.loggingEnabled) { 11085 msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask; 11086 } 11087 11088 logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter); 11089 if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 11090 logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter); 11091 } 11092 11093 if (!(logForKernel || logForUser)) { 11094 goto finish; 11095 } 11096 11097 /* No goto from here until past va_end()! 11098 */ 11099 va_copy(argList, srcArgList); 11100 length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList); 11101 va_end(argList); 11102 11103 if (length + 1 >= sizeof(stackBuffer)) { 11104 allocBuffer = (char *)kalloc_tag((length + 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT); 11105 if (!allocBuffer) { 11106 goto finish; 11107 } 11108 11109 /* No goto from here until past va_end()! 11110 */ 11111 va_copy(argList, srcArgList); 11112 vsnprintf(allocBuffer, length + 1, format, argList); 11113 va_end(argList); 11114 11115 buffer = allocBuffer; 11116 } 11117 11118 /* If user space wants the log message, queue it up. 11119 */ 11120 if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 11121 logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec)); 11122 logString = OSString::withCString(buffer); 11123 if (logSpecNum && logString) { 11124 sUserSpaceLogSpecArray->setObject(logSpecNum); 11125 sUserSpaceLogMessageArray->setObject(logString); 11126 } 11127 } 11128 11129 /* Always log messages from the kernel according to the kernel's 11130 * log flags. 11131 */ 11132 if (logForKernel) { 11133 /* If we are in console mode and have a custom log filter, 11134 * colorize the log message. 11135 */ 11136 if (!disableConsoleOutput && sBootArgLogFilterFound) { 11137 const char * color = ""; // do not free 11138 color = colorForFlags(msgLogSpec); 11139 printf("%s%s%s\n", colorForFlags(msgLogSpec), 11140 buffer, color[0] ? VTRESET : ""); 11141 } else { 11142 printf("%s\n", buffer); 11143 } 11144 } 11145 11146 finish: 11147 IOLockUnlock(sKextLoggingLock); 11148 11149 if (allocBuffer) { 11150 kfree(allocBuffer, (length + 1) * sizeof(char)); 11151 } 11152 OSSafeReleaseNULL(logString); 11153 OSSafeReleaseNULL(logSpecNum); 11154 return; 11155 } 11156 11157 #if KASLR_IOREG_DEBUG 11158 11159 #define IOLOG_INDENT( the_indention ) \ 11160 { \ 11161 int i; \ 11162 for ( i = 0; i < (the_indention); i++ ) { \ 11163 IOLog(" "); \ 11164 } \ 11165 } 11166 11167 extern vm_offset_t vm_kernel_stext; 11168 extern vm_offset_t vm_kernel_etext; 11169 extern mach_vm_offset_t kext_alloc_base; 11170 extern mach_vm_offset_t kext_alloc_max; 11171 11172 bool ScanForAddrInObject(OSObject * theObject, 11173 int indent ); 11174 11175 bool 11176 ScanForAddrInObject(OSObject * theObject, 11177 int indent) 11178 { 11179 const OSMetaClass * myTypeID; 11180 OSCollectionIterator * myIter; 11181 OSSymbol * myKey; 11182 OSObject * myValue; 11183 bool myResult = false; 11184 11185 if (theObject == NULL) { 11186 IOLog("%s: theObject is NULL \n", 11187 __FUNCTION__); 11188 return myResult; 11189 } 11190 11191 myTypeID = OSTypeIDInst(theObject); 11192 11193 if (myTypeID == OSTypeID(OSDictionary)) { 11194 OSDictionary * myDictionary; 11195 11196 myDictionary = OSDynamicCast(OSDictionary, theObject); 11197 myIter = OSCollectionIterator::withCollection( myDictionary ); 11198 if (myIter == NULL) { 11199 return myResult; 11200 } 11201 myIter->reset(); 11202 11203 while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) { 11204 bool myTempResult; 11205 11206 myValue = myDictionary->getObject(myKey); 11207 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 11208 if (myTempResult) { 11209 // if we ever get a true result return true 11210 myResult = true; 11211 IOLOG_INDENT(indent); 11212 IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy()); 11213 } 11214 } 11215 myIter->release(); 11216 } else if (myTypeID == OSTypeID(OSArray)) { 11217 OSArray * myArray; 11218 11219 myArray = OSDynamicCast(OSArray, theObject); 11220 myIter = OSCollectionIterator::withCollection(myArray); 11221 if (myIter == NULL) { 11222 return myResult; 11223 } 11224 myIter->reset(); 11225 11226 while ((myValue = myIter->getNextObject())) { 11227 bool myTempResult; 11228 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 11229 if (myTempResult) { 11230 // if we ever get a true result return true 11231 myResult = true; 11232 IOLOG_INDENT(indent); 11233 IOLog("OSArray: \n"); 11234 } 11235 } 11236 myIter->release(); 11237 } else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) { 11238 // should we look for addresses in strings? 11239 } else if (myTypeID == OSTypeID(OSData)) { 11240 void * * myPtrPtr; 11241 unsigned int myLen; 11242 OSData * myDataObj; 11243 11244 myDataObj = OSDynamicCast(OSData, theObject); 11245 myPtrPtr = (void * *) myDataObj->getBytesNoCopy(); 11246 myLen = myDataObj->getLength(); 11247 11248 if (myPtrPtr && myLen && myLen > 7) { 11249 int i; 11250 int myPtrCount = (myLen / sizeof(void *)); 11251 11252 for (i = 0; i < myPtrCount; i++) { 11253 UInt64 numberValue = (UInt64) * (myPtrPtr); 11254 11255 if (kext_alloc_max != 0 && 11256 numberValue >= kext_alloc_base && 11257 numberValue < kext_alloc_max) { 11258 OSKext * myKext = NULL;// must release (looked up) 11259 // IOLog("found OSData %p in kext map %p to %p \n", 11260 // *(myPtrPtr), 11261 // (void *) kext_alloc_base, 11262 // (void *) kext_alloc_max); 11263 11264 myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr)); 11265 if (myKext) { 11266 IOLog("found addr %p from an OSData obj within kext \"%s\" \n", 11267 *(myPtrPtr), 11268 myKext->getIdentifierCString()); 11269 myKext->release(); 11270 } 11271 myResult = true; 11272 } 11273 if (vm_kernel_etext != 0 && 11274 numberValue >= vm_kernel_stext && 11275 numberValue < vm_kernel_etext) { 11276 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n", 11277 *(myPtrPtr), 11278 (void *) vm_kernel_stext, 11279 (void *) vm_kernel_etext); 11280 myResult = true; 11281 } 11282 myPtrPtr++; 11283 } 11284 } 11285 } else if (myTypeID == OSTypeID(OSBoolean)) { 11286 // do nothing here... 11287 } else if (myTypeID == OSTypeID(OSNumber)) { 11288 OSNumber * number = OSDynamicCast(OSNumber, theObject); 11289 11290 UInt64 numberValue = number->unsigned64BitValue(); 11291 11292 if (kext_alloc_max != 0 && 11293 numberValue >= kext_alloc_base && 11294 numberValue < kext_alloc_max) { 11295 OSKext * myKext = NULL;// must release (looked up) 11296 IOLog("found OSNumber in kext map %p to %p \n", 11297 (void *) kext_alloc_base, 11298 (void *) kext_alloc_max); 11299 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 11300 11301 myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue ); 11302 if (myKext) { 11303 IOLog("found in kext \"%s\" \n", 11304 myKext->getIdentifierCString()); 11305 myKext->release(); 11306 } 11307 11308 myResult = true; 11309 } 11310 if (vm_kernel_etext != 0 && 11311 numberValue >= vm_kernel_stext && 11312 numberValue < vm_kernel_etext) { 11313 IOLog("found OSNumber in kernel text segment %p to %p \n", 11314 (void *) vm_kernel_stext, 11315 (void *) vm_kernel_etext); 11316 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 11317 myResult = true; 11318 } 11319 } 11320 #if 0 11321 else { 11322 const OSMetaClass* myMetaClass = NULL; 11323 11324 myMetaClass = theObject->getMetaClass(); 11325 if (myMetaClass) { 11326 IOLog("class %s \n", myMetaClass->getClassName()); 11327 } else { 11328 IOLog("Unknown object \n" ); 11329 } 11330 } 11331 #endif 11332 11333 return myResult; 11334 } 11335 #endif // KASLR_KEXT_DEBUG 11336 }; /* extern "C" */ 11337 11338 #if PRAGMA_MARK 11339 #pragma mark Backtrace Dump & kmod_get_info() support 11340 #endif 11341 /********************************************************************* 11342 * This function must be safe to call in panic context. 11343 *********************************************************************/ 11344 /* static */ 11345 void 11346 OSKext::printKextsInBacktrace( 11347 vm_offset_t * addr __unused, 11348 unsigned int cnt __unused, 11349 int (* printf_func)(const char *fmt, ...) __unused, 11350 uint32_t flags __unused) 11351 { 11352 addr64_t summary_page = 0; 11353 addr64_t last_summary_page = 0; 11354 bool found_kmod = false; 11355 u_int i = 0; 11356 11357 if (kPrintKextsLock & flags) { 11358 if (!sKextSummariesLock) { 11359 return; 11360 } 11361 IOLockLock(sKextSummariesLock); 11362 } 11363 11364 if (!gLoadedKextSummaries) { 11365 (*printf_func)(" can't perform kext scan: no kext summary"); 11366 goto finish; 11367 } 11368 11369 summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries); 11370 last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize); 11371 for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) { 11372 if (pmap_find_phys(kernel_pmap, summary_page) == 0) { 11373 (*printf_func)(" can't perform kext scan: " 11374 "missing kext summary page %p", summary_page); 11375 goto finish; 11376 } 11377 } 11378 11379 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 11380 OSKextLoadedKextSummary * summary; 11381 11382 summary = gLoadedKextSummaries->summaries + i; 11383 if (!summary->address) { 11384 continue; 11385 } 11386 11387 if (!summaryIsInBacktrace(summary, addr, cnt)) { 11388 continue; 11389 } 11390 11391 if (!found_kmod) { 11392 if (!(kPrintKextsTerse & flags)) { 11393 (*printf_func)(" Kernel Extensions in backtrace:\n"); 11394 } 11395 found_kmod = true; 11396 } 11397 11398 printSummary(summary, printf_func, flags); 11399 } 11400 11401 finish: 11402 if (kPrintKextsLock & flags) { 11403 IOLockUnlock(sKextSummariesLock); 11404 } 11405 11406 return; 11407 } 11408 11409 /********************************************************************* 11410 * This function must be safe to call in panic context. 11411 *********************************************************************/ 11412 /* static */ 11413 boolean_t 11414 OSKext::summaryIsInBacktrace( 11415 OSKextLoadedKextSummary * summary, 11416 vm_offset_t * addr, 11417 unsigned int cnt) 11418 { 11419 u_int i = 0; 11420 11421 for (i = 0; i < cnt; i++) { 11422 vm_offset_t kscan_addr = addr[i]; 11423 if ((kscan_addr >= summary->address) && 11424 (kscan_addr < (summary->address + summary->size))) { 11425 return TRUE; 11426 } 11427 } 11428 11429 return FALSE; 11430 } 11431 11432 /* 11433 * Get the kext summary object for the kext where 'addr' lies. Must be called with 11434 * sKextSummariesLock held. 11435 */ 11436 OSKextLoadedKextSummary * 11437 OSKext::summaryForAddress(const uintptr_t addr) 11438 { 11439 for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 11440 OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i]; 11441 if (!summary->address) { 11442 continue; 11443 } 11444 11445 #if VM_MAPPED_KEXTS 11446 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not 11447 * support split kexts, but we also may unmap the kexts, which can 11448 * race with the above codepath (see OSKext::unload). As such, 11449 * use a simple range lookup if we are using VM_MAPPED_KEXTS. 11450 */ 11451 if ((addr >= summary->address) && (addr < (summary->address + summary->size))) { 11452 return summary; 11453 } 11454 #else 11455 kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address; 11456 kernel_segment_command_t *seg; 11457 11458 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 11459 if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) { 11460 return summary; 11461 } 11462 } 11463 #endif 11464 } 11465 11466 /* addr did not map to any kext */ 11467 return NULL; 11468 } 11469 11470 /* static */ 11471 void * 11472 OSKext::kextForAddress(const void *address) 11473 { 11474 void * image = NULL; 11475 OSKextActiveAccount * active; 11476 OSKext * kext = NULL; 11477 uint32_t baseIdx; 11478 uint32_t lim; 11479 uintptr_t addr = (uintptr_t) address; 11480 11481 if (!addr) { 11482 return NULL; 11483 } 11484 11485 if (sKextAccountsCount) { 11486 IOSimpleLockLock(sKextAccountsLock); 11487 // bsearch sKextAccounts list 11488 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 11489 active = &sKextAccounts[baseIdx + (lim >> 1)]; 11490 if ((addr >= active->address) && (addr < active->address_end)) { 11491 kext = active->account->kext; 11492 if (kext && kext->kmod_info) { 11493 image = (void *) kext->kmod_info->address; 11494 } 11495 break; 11496 } else if (addr > active->address) { 11497 // move right 11498 baseIdx += (lim >> 1) + 1; 11499 lim--; 11500 } 11501 // else move left 11502 } 11503 IOSimpleLockUnlock(sKextAccountsLock); 11504 } 11505 if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) { 11506 image = (void *) &_mh_execute_header; 11507 } 11508 11509 return image; 11510 } 11511 11512 /********************************************************************* 11513 * scan list of loaded kext summaries looking for a load address match and if 11514 * found return the UUID C string. If not found then set empty string. 11515 *********************************************************************/ 11516 static void findSummaryUUID( 11517 uint32_t tag_ID, 11518 uuid_string_t uuid); 11519 11520 static void 11521 findSummaryUUID( 11522 uint32_t tag_ID, 11523 uuid_string_t uuid) 11524 { 11525 u_int i; 11526 11527 uuid[0] = 0x00; // default to no UUID 11528 11529 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 11530 OSKextLoadedKextSummary * summary; 11531 11532 summary = gLoadedKextSummaries->summaries + i; 11533 11534 if (summary->loadTag == tag_ID) { 11535 (void) uuid_unparse(summary->uuid, uuid); 11536 break; 11537 } 11538 } 11539 return; 11540 } 11541 11542 /********************************************************************* 11543 * This function must be safe to call in panic context. 11544 *********************************************************************/ 11545 void 11546 OSKext::printSummary( 11547 OSKextLoadedKextSummary * summary, 11548 int (* printf_func)(const char *fmt, ...), 11549 uint32_t flags) 11550 { 11551 kmod_reference_t * kmod_ref = NULL; 11552 uuid_string_t uuid; 11553 char version[kOSKextVersionMaxLength]; 11554 uint64_t tmpAddr; 11555 11556 if (!OSKextVersionGetString(summary->version, version, sizeof(version))) { 11557 strlcpy(version, "unknown version", sizeof(version)); 11558 } 11559 (void) uuid_unparse(summary->uuid, uuid); 11560 11561 if (kPrintKextsUnslide & flags) { 11562 tmpAddr = ml_static_unslide(summary->address); 11563 } else { 11564 tmpAddr = summary->address; 11565 } 11566 (*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n", 11567 (kPrintKextsTerse & flags) ? "" : " ", 11568 summary->name, version, uuid, 11569 tmpAddr, tmpAddr + summary->size - 1); 11570 11571 if (kPrintKextsTerse & flags) { 11572 return; 11573 } 11574 11575 /* print dependency info */ 11576 for (kmod_ref = (kmod_reference_t *) summary->reference_list; 11577 kmod_ref; 11578 kmod_ref = kmod_ref->next) { 11579 kmod_info_t * rinfo; 11580 11581 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) { 11582 (*printf_func)(" kmod dependency scan stopped " 11583 "due to missing dependency page: %p\n", 11584 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref); 11585 break; 11586 } 11587 rinfo = kmod_ref->info; 11588 11589 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) { 11590 (*printf_func)(" kmod dependency scan stopped " 11591 "due to missing kmod page: %p\n", 11592 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo); 11593 break; 11594 } 11595 11596 if (!rinfo->address) { 11597 continue; // skip fake entries for built-ins 11598 } 11599 11600 /* locate UUID in gLoadedKextSummaries */ 11601 findSummaryUUID(rinfo->id, uuid); 11602 11603 if (kPrintKextsUnslide & flags) { 11604 tmpAddr = ml_static_unslide(rinfo->address); 11605 } else { 11606 tmpAddr = rinfo->address; 11607 } 11608 (*printf_func)(" dependency: %s(%s)[%s]@%p\n", 11609 rinfo->name, rinfo->version, uuid, tmpAddr); 11610 } 11611 return; 11612 } 11613 11614 11615 /******************************************************************************* 11616 * substitute() looks at an input string (a pointer within a larger buffer) 11617 * for a match to a substring, and on match it writes the marker & substitution 11618 * character to an output string, updating the scan (from) and 11619 * output (to) indexes as appropriate. 11620 *******************************************************************************/ 11621 static int substitute( 11622 const char * scan_string, 11623 char * string_out, 11624 uint32_t * to_index, 11625 uint32_t * from_index, 11626 const char * substring, 11627 char marker, 11628 char substitution); 11629 11630 /* string_out must be at least KMOD_MAX_NAME bytes. 11631 */ 11632 static int 11633 substitute( 11634 const char * scan_string, 11635 char * string_out, 11636 uint32_t * to_index, 11637 uint32_t * from_index, 11638 const char * substring, 11639 char marker, 11640 char substitution) 11641 { 11642 uint32_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1); 11643 11644 /* On a substring match, append the marker (if there is one) and then 11645 * the substitution character, updating the output (to) index accordingly. 11646 * Then update the input (from) length by the length of the substring 11647 * that got replaced. 11648 */ 11649 if (!strncmp(scan_string, substring, substring_length)) { 11650 if (marker) { 11651 string_out[(*to_index)++] = marker; 11652 } 11653 string_out[(*to_index)++] = substitution; 11654 (*from_index) += substring_length; 11655 return 1; 11656 } 11657 return 0; 11658 } 11659 11660 /******************************************************************************* 11661 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least 11662 * KMOD_MAX_NAME characters and performs various substitutions of common 11663 * prefixes & substrings as defined by tables in kext_panic_report.h. 11664 *******************************************************************************/ 11665 static void compactIdentifier( 11666 const char * identifier, 11667 char * identifier_out, 11668 char ** identifier_out_end); 11669 11670 static void 11671 compactIdentifier( 11672 const char * identifier, 11673 char * identifier_out, 11674 char ** identifier_out_end) 11675 { 11676 uint32_t from_index, to_index; 11677 uint32_t scan_from_index = 0; 11678 uint32_t scan_to_index = 0; 11679 subs_entry_t * subs_entry = NULL; 11680 int did_sub = 0; 11681 11682 from_index = to_index = 0; 11683 identifier_out[0] = '\0'; 11684 11685 /* Replace certain identifier prefixes with shorter @+character sequences. 11686 * Check the return value of substitute() so we only replace the prefix. 11687 */ 11688 for (subs_entry = &kext_identifier_prefix_subs[0]; 11689 subs_entry->substring && !did_sub; 11690 subs_entry++) { 11691 did_sub = substitute(identifier, identifier_out, 11692 &scan_to_index, &scan_from_index, 11693 subs_entry->substring, /* marker */ '\0', subs_entry->substitute); 11694 } 11695 did_sub = 0; 11696 11697 /* Now scan through the identifier looking for the common substrings 11698 * and replacing them with shorter !+character sequences via substitute(). 11699 */ 11700 for (/* see above */; 11701 scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index]; 11702 /* see loop */) { 11703 const char * scan_string = &identifier[scan_from_index]; 11704 11705 did_sub = 0; 11706 11707 if (scan_from_index) { 11708 for (subs_entry = &kext_identifier_substring_subs[0]; 11709 subs_entry->substring && !did_sub; 11710 subs_entry++) { 11711 did_sub = substitute(scan_string, identifier_out, 11712 &scan_to_index, &scan_from_index, 11713 subs_entry->substring, '!', subs_entry->substitute); 11714 } 11715 } 11716 11717 /* If we didn't substitute, copy the input character to the output. 11718 */ 11719 if (!did_sub) { 11720 identifier_out[scan_to_index++] = identifier[scan_from_index++]; 11721 } 11722 } 11723 11724 identifier_out[scan_to_index] = '\0'; 11725 if (identifier_out_end) { 11726 *identifier_out_end = &identifier_out[scan_to_index]; 11727 } 11728 11729 return; 11730 } 11731 11732 /******************************************************************************* 11733 * assemble_identifier_and_version() adds to a string buffer a compacted 11734 * bundle identifier followed by a version string. 11735 *******************************************************************************/ 11736 11737 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length. 11738 */ 11739 static int assemble_identifier_and_version( 11740 kmod_info_t * kmod_info, 11741 char * identPlusVers, 11742 int bufSize); 11743 11744 static int 11745 assemble_identifier_and_version( 11746 kmod_info_t * kmod_info, 11747 char * identPlusVers, 11748 int bufSize) 11749 { 11750 int result = 0; 11751 11752 compactIdentifier(kmod_info->name, identPlusVers, NULL); 11753 result = strnlen(identPlusVers, KMOD_MAX_NAME - 1); 11754 identPlusVers[result++] = '\t'; // increment for real char 11755 identPlusVers[result] = '\0'; // don't increment for nul char 11756 result = strlcat(identPlusVers, kmod_info->version, bufSize); 11757 if (result >= bufSize) { 11758 identPlusVers[bufSize - 1] = '\0'; 11759 result = bufSize - 1; 11760 } 11761 11762 return result; 11763 } 11764 11765 /******************************************************************************* 11766 * Assumes sKextLock is held. 11767 *******************************************************************************/ 11768 /* static */ 11769 int 11770 OSKext::saveLoadedKextPanicListTyped( 11771 const char * prefix, 11772 int invertFlag, 11773 int libsFlag, 11774 char * paniclist, 11775 uint32_t list_size) 11776 { 11777 int result = -1; 11778 unsigned int count, i; 11779 11780 count = sLoadedKexts->getCount(); 11781 if (!count) { 11782 goto finish; 11783 } 11784 11785 i = count - 1; 11786 do { 11787 OSObject * rawKext = sLoadedKexts->getObject(i); 11788 OSKext * theKext = OSDynamicCast(OSKext, rawKext); 11789 int match; 11790 uint32_t identPlusVersLength; 11791 uint32_t tempLen; 11792 char identPlusVers[2 * KMOD_MAX_NAME]; 11793 11794 if (!rawKext) { 11795 printf("OSKext::saveLoadedKextPanicListTyped - " 11796 "NULL kext in loaded kext list; continuing\n"); 11797 continue; 11798 } 11799 11800 if (!theKext) { 11801 printf("OSKext::saveLoadedKextPanicListTyped - " 11802 "Kext type cast failed in loaded kext list; continuing\n"); 11803 continue; 11804 } 11805 11806 /* Skip all built-in kexts. 11807 */ 11808 if (theKext->isKernelComponent()) { 11809 continue; 11810 } 11811 11812 kmod_info_t * kmod_info = theKext->kmod_info; 11813 11814 /* Filter for kmod name (bundle identifier). 11815 */ 11816 match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME)); 11817 if ((match && invertFlag) || (!match && !invertFlag)) { 11818 continue; 11819 } 11820 11821 /* Filter for libraries (kexts that have a compatible version). 11822 */ 11823 if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) || 11824 (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) { 11825 continue; 11826 } 11827 11828 if (!kmod_info || 11829 !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) { 11830 printf("kext scan stopped due to missing kmod_info page: %p\n", 11831 kmod_info); 11832 goto finish; 11833 } 11834 11835 identPlusVersLength = assemble_identifier_and_version(kmod_info, 11836 identPlusVers, 11837 sizeof(identPlusVers)); 11838 if (!identPlusVersLength) { 11839 printf("error saving loaded kext info\n"); 11840 goto finish; 11841 } 11842 11843 /* make sure everything fits and we null terminate. 11844 */ 11845 tempLen = strlcat(paniclist, identPlusVers, list_size); 11846 if (tempLen >= list_size) { 11847 // panic list is full, keep it and null terminate 11848 paniclist[list_size - 1] = 0x00; 11849 result = 0; 11850 goto finish; 11851 } 11852 tempLen = strlcat(paniclist, "\n", list_size); 11853 if (tempLen >= list_size) { 11854 // panic list is full, keep it and null terminate 11855 paniclist[list_size - 1] = 0x00; 11856 result = 0; 11857 goto finish; 11858 } 11859 } while (i--); 11860 11861 result = 0; 11862 finish: 11863 11864 return result; 11865 } 11866 11867 /********************************************************************* 11868 *********************************************************************/ 11869 /* static */ 11870 void 11871 OSKext::saveLoadedKextPanicList(void) 11872 { 11873 char * newlist = NULL; 11874 uint32_t newlist_size = 0; 11875 11876 newlist_size = KEXT_PANICLIST_SIZE; 11877 newlist = (char *)kalloc_tag(newlist_size, VM_KERN_MEMORY_OSKEXT); 11878 11879 if (!newlist) { 11880 OSKextLog(/* kext */ NULL, 11881 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 11882 "Couldn't allocate kext panic log buffer."); 11883 goto finish; 11884 } 11885 11886 newlist[0] = '\0'; 11887 11888 // non-"com.apple." kexts 11889 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1, 11890 /* libs? */ -1, newlist, newlist_size) != 0) { 11891 goto finish; 11892 } 11893 // "com.apple." nonlibrary kexts 11894 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 11895 /* libs? */ 0, newlist, newlist_size) != 0) { 11896 goto finish; 11897 } 11898 // "com.apple." library kexts 11899 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 11900 /* libs? */ 1, newlist, newlist_size) != 0) { 11901 goto finish; 11902 } 11903 11904 if (loaded_kext_paniclist) { 11905 kfree(loaded_kext_paniclist, loaded_kext_paniclist_size); 11906 } 11907 loaded_kext_paniclist = newlist; 11908 newlist = NULL; 11909 loaded_kext_paniclist_size = newlist_size; 11910 11911 finish: 11912 if (newlist) { 11913 kfree(newlist, newlist_size); 11914 } 11915 return; 11916 } 11917 11918 /********************************************************************* 11919 * Assumes sKextLock is held. 11920 *********************************************************************/ 11921 void 11922 OSKext::savePanicString(bool isLoading) 11923 { 11924 u_long len; 11925 11926 if (!kmod_info) { 11927 return; // do not goto finish here b/c of lock 11928 } 11929 11930 len = assemble_identifier_and_version( kmod_info, 11931 (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf, 11932 (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf)); 11933 if (!len) { 11934 printf("error saving unloaded kext info\n"); 11935 goto finish; 11936 } 11937 11938 if (isLoading) { 11939 last_loaded_strlen = len; 11940 last_loaded_address = (void *)kmod_info->address; 11941 last_loaded_size = kmod_info->size; 11942 clock_get_uptime(&last_loaded_timestamp); 11943 } else { 11944 last_unloaded_strlen = len; 11945 last_unloaded_address = (void *)kmod_info->address; 11946 last_unloaded_size = kmod_info->size; 11947 clock_get_uptime(&last_unloaded_timestamp); 11948 } 11949 11950 finish: 11951 return; 11952 } 11953 11954 /********************************************************************* 11955 *********************************************************************/ 11956 /* static */ 11957 void 11958 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...)) 11959 { 11960 if (last_loaded_strlen) { 11961 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n", 11962 AbsoluteTime_to_scalar(&last_loaded_timestamp), 11963 last_loaded_strlen, last_loaded_str_buf, 11964 last_loaded_address, last_loaded_size); 11965 } 11966 11967 if (last_unloaded_strlen) { 11968 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n", 11969 AbsoluteTime_to_scalar(&last_unloaded_timestamp), 11970 last_unloaded_strlen, last_unloaded_str_buf, 11971 last_unloaded_address, last_unloaded_size); 11972 } 11973 11974 printf_func("loaded kexts:\n"); 11975 if (loaded_kext_paniclist && 11976 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) && 11977 loaded_kext_paniclist[0]) { 11978 printf_func("%.*s", 11979 strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size), 11980 loaded_kext_paniclist); 11981 } else { 11982 printf_func("(none)\n"); 11983 } 11984 return; 11985 } 11986 11987 /********************************************************************* 11988 * Assumes sKextLock is held. 11989 *********************************************************************/ 11990 /* static */ 11991 void 11992 OSKext::updateLoadedKextSummaries(void) 11993 { 11994 kern_return_t result = KERN_FAILURE; 11995 OSKextLoadedKextSummaryHeader *summaryHeader = NULL; 11996 OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL; 11997 OSKext *aKext; 11998 vm_map_offset_t start, end; 11999 size_t summarySize = 0; 12000 size_t size; 12001 u_int count; 12002 u_int maxKexts; 12003 u_int i, j; 12004 OSKextActiveAccount * accountingList; 12005 OSKextActiveAccount * prevAccountingList; 12006 uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount; 12007 12008 prevAccountingList = NULL; 12009 prevAccountingListCount = 0; 12010 12011 #if DEVELOPMENT || DEBUG 12012 if (IORecursiveLockHaveLock(sKextLock) == false) { 12013 panic("sKextLock must be held"); 12014 } 12015 #endif 12016 12017 IOLockLock(sKextSummariesLock); 12018 12019 count = sLoadedKexts->getCount(); 12020 for (i = 0, maxKexts = 0; i < count; ++i) { 12021 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 12022 maxKexts += (aKext && aKext->isExecutable()); 12023 } 12024 12025 if (!maxKexts) { 12026 goto finish; 12027 } 12028 if (maxKexts < kOSKextTypicalLoadCount) { 12029 maxKexts = kOSKextTypicalLoadCount; 12030 } 12031 12032 /* Calculate the size needed for the new summary headers. 12033 */ 12034 12035 size = sizeof(*gLoadedKextSummaries); 12036 size += maxKexts * sizeof(*gLoadedKextSummaries->summaries); 12037 size = round_page(size); 12038 12039 if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) { 12040 if (gLoadedKextSummaries) { 12041 kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize); 12042 gLoadedKextSummaries = NULL; 12043 gLoadedKextSummariesTimestamp = mach_absolute_time(); 12044 sLoadedKextSummariesAllocSize = 0; 12045 } 12046 result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, VM_KERN_MEMORY_OSKEXT); 12047 if (result != KERN_SUCCESS) { 12048 goto finish; 12049 } 12050 summaryHeader = summaryHeaderAlloc; 12051 summarySize = size; 12052 } else { 12053 summaryHeader = gLoadedKextSummaries; 12054 summarySize = sLoadedKextSummariesAllocSize; 12055 12056 start = (vm_map_offset_t) summaryHeader; 12057 end = start + summarySize; 12058 result = vm_map_protect(kernel_map, 12059 start, 12060 end, 12061 VM_PROT_DEFAULT, 12062 FALSE); 12063 if (result != KERN_SUCCESS) { 12064 goto finish; 12065 } 12066 } 12067 12068 /* Populate the summary header. 12069 */ 12070 12071 bzero(summaryHeader, summarySize); 12072 summaryHeader->version = kOSKextLoadedKextSummaryVersion; 12073 summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary); 12074 12075 /* Populate each kext summary. 12076 */ 12077 12078 count = sLoadedKexts->getCount(); 12079 accountingListAlloc = 0; 12080 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 12081 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 12082 if (!aKext || !aKext->isExecutable()) { 12083 continue; 12084 } 12085 12086 aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]); 12087 summaryHeader->numSummaries++; 12088 accountingListAlloc++; 12089 } 12090 12091 accountingList = IONew(typeof(accountingList[0]), accountingListAlloc); 12092 accountingListCount = 0; 12093 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 12094 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 12095 if (!aKext || !aKext->isExecutable()) { 12096 continue; 12097 } 12098 12099 OSKextActiveAccount activeAccount; 12100 aKext->updateActiveAccount(&activeAccount); 12101 // order by address 12102 for (idx = 0; idx < accountingListCount; idx++) { 12103 if (activeAccount.address < accountingList[idx].address) { 12104 break; 12105 } 12106 } 12107 bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0])); 12108 accountingList[idx] = activeAccount; 12109 accountingListCount++; 12110 } 12111 assert(accountingListCount == accountingListAlloc); 12112 /* Write protect the buffer and move it into place. 12113 */ 12114 12115 start = (vm_map_offset_t) summaryHeader; 12116 end = start + summarySize; 12117 12118 result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE); 12119 if (result != KERN_SUCCESS) { 12120 goto finish; 12121 } 12122 12123 gLoadedKextSummaries = summaryHeader; 12124 gLoadedKextSummariesTimestamp = mach_absolute_time(); 12125 sLoadedKextSummariesAllocSize = summarySize; 12126 summaryHeaderAlloc = NULL; 12127 12128 /* Call the magic breakpoint function through a static function pointer so 12129 * the compiler can't optimize the function away. 12130 */ 12131 if (sLoadedKextSummariesUpdated) { 12132 (*sLoadedKextSummariesUpdated)(); 12133 } 12134 12135 IOSimpleLockLock(sKextAccountsLock); 12136 prevAccountingList = sKextAccounts; 12137 prevAccountingListCount = sKextAccountsCount; 12138 sKextAccounts = accountingList; 12139 sKextAccountsCount = accountingListCount; 12140 IOSimpleLockUnlock(sKextAccountsLock); 12141 12142 finish: 12143 IOLockUnlock(sKextSummariesLock); 12144 12145 /* If we had to allocate a new buffer but failed to generate the summaries, 12146 * free that now. 12147 */ 12148 if (summaryHeaderAlloc) { 12149 kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize); 12150 } 12151 if (prevAccountingList) { 12152 IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount); 12153 } 12154 12155 return; 12156 } 12157 12158 /********************************************************************* 12159 *********************************************************************/ 12160 void 12161 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary) 12162 { 12163 OSData *uuid; 12164 12165 strlcpy(summary->name, getIdentifierCString(), 12166 sizeof(summary->name)); 12167 12168 uuid = copyUUID(); 12169 if (uuid) { 12170 memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid)); 12171 OSSafeReleaseNULL(uuid); 12172 } 12173 12174 if (flags.builtin) { 12175 // this value will stop lldb from parsing the mach-o header 12176 // summary->address = UINT64_MAX; 12177 // summary->size = 0; 12178 summary->address = kmod_info->address; 12179 summary->size = kmod_info->size; 12180 } else { 12181 summary->address = kmod_info->address; 12182 summary->size = kmod_info->size; 12183 } 12184 summary->version = getVersion(); 12185 summary->loadTag = kmod_info->id; 12186 summary->flags = 0; 12187 summary->reference_list = (uint64_t) kmod_info->reference_list; 12188 12189 return; 12190 } 12191 12192 /********************************************************************* 12193 *********************************************************************/ 12194 12195 void 12196 OSKext::updateActiveAccount(OSKextActiveAccount *accountp) 12197 { 12198 kernel_mach_header_t *hdr = NULL; 12199 kernel_segment_command_t *seg = NULL; 12200 12201 bzero(accountp, sizeof(*accountp)); 12202 12203 hdr = (kernel_mach_header_t *)kmod_info->address; 12204 if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO)) { 12205 /* If this kext supports split segments, use the first 12206 * executable segment as the range for instructions 12207 * (and thus for backtracing. 12208 */ 12209 for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) { 12210 if (seg->initprot & VM_PROT_EXECUTE) { 12211 break; 12212 } 12213 } 12214 } 12215 if (seg) { 12216 accountp->address = seg->vmaddr; 12217 if (accountp->address) { 12218 accountp->address_end = seg->vmaddr + seg->vmsize; 12219 } 12220 } else { 12221 /* For non-split kexts and for kexts without executable 12222 * segments, just use the kmod_info range (as the kext 12223 * is either all in one range or should not show up in 12224 * instruction backtraces). 12225 */ 12226 accountp->address = kmod_info->address; 12227 if (accountp->address) { 12228 accountp->address_end = kmod_info->address + kmod_info->size; 12229 } 12230 } 12231 12232 accountp->account = this->account; 12233 } 12234 12235 bool 12236 OSKext::isDriverKit(void) 12237 { 12238 OSString *bundleType; 12239 12240 if (infoDict) { 12241 bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)); 12242 if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) { 12243 return TRUE; 12244 } 12245 } 12246 return FALSE; 12247 } 12248 12249 extern "C" const vm_allocation_site_t * 12250 OSKextGetAllocationSiteForCaller(uintptr_t address) 12251 { 12252 OSKextActiveAccount * active; 12253 vm_allocation_site_t * site; 12254 vm_allocation_site_t * releasesite; 12255 12256 uint32_t baseIdx; 12257 uint32_t lim; 12258 12259 IOSimpleLockLock(sKextAccountsLock); 12260 site = releasesite = NULL; 12261 12262 // bsearch sKextAccounts list 12263 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 12264 active = &sKextAccounts[baseIdx + (lim >> 1)]; 12265 if ((address >= active->address) && (address < active->address_end)) { 12266 site = &active->account->site; 12267 if (!site->tag) { 12268 vm_tag_alloc_locked(site, &releasesite); 12269 } 12270 break; 12271 } else if (address > active->address) { 12272 // move right 12273 baseIdx += (lim >> 1) + 1; 12274 lim--; 12275 } 12276 // else move left 12277 } 12278 IOSimpleLockUnlock(sKextAccountsLock); 12279 if (releasesite) { 12280 kern_allocation_name_release(releasesite); 12281 } 12282 12283 return site; 12284 } 12285 12286 extern "C" uint32_t 12287 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen) 12288 { 12289 OSKextAccount * account = (typeof(account))site; 12290 const char * kname; 12291 12292 if (name) { 12293 if (account->kext) { 12294 kname = account->kext->getIdentifierCString(); 12295 } else { 12296 kname = "<>"; 12297 } 12298 strlcpy(name, kname, namelen); 12299 } 12300 12301 return account->loadTag; 12302 } 12303 12304 extern "C" void 12305 OSKextFreeSite(vm_allocation_site_t * site) 12306 { 12307 OSKextAccount * freeAccount = (typeof(freeAccount))site; 12308 IODelete(freeAccount, OSKextAccount, 1); 12309 } 12310 12311 /********************************************************************* 12312 *********************************************************************/ 12313 12314 #if CONFIG_IMAGEBOOT 12315 int 12316 OSKextGetUUIDForName(const char *name, uuid_t uuid) 12317 { 12318 OSKext *kext = OSKext::lookupKextWithIdentifier(name); 12319 if (!kext) { 12320 return 1; 12321 } 12322 12323 OSData *uuid_data = kext->copyUUID(); 12324 if (uuid_data) { 12325 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t)); 12326 OSSafeReleaseNULL(uuid_data); 12327 return 0; 12328 } 12329 12330 return 1; 12331 } 12332 #endif 12333