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