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