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