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