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