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