1 /* 2 * Copyright (c) 2008-2021 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 #define IOKIT_ENABLE_SHARED_PTR 30 31 extern "C" { 32 #include <string.h> 33 #include <kern/clock.h> 34 #include <kern/host.h> 35 #include <kern/kext_alloc.h> 36 #include <firehose/tracepoint_private.h> 37 #include <firehose/chunk_private.h> 38 #include <os/firehose_buffer_private.h> 39 #include <vm/vm_map_xnu.h> 40 #include <kextd/kextd_mach.h> 41 #include <libkern/kernel_mach_header.h> 42 #include <libkern/kext_panic_report.h> 43 #include <libkern/kext_request_keys.h> 44 #include <libkern/mkext.h> 45 #include <libkern/prelink.h> 46 #include <libkern/version.h> 47 #include <libkern/zlib.h> 48 #include <mach/host_special_ports.h> 49 #include <mach/mach_vm.h> 50 #include <mach/mach_time.h> 51 #include <uuid/uuid.h> 52 #include <sys/random.h> 53 #include <pexpert/pexpert.h> 54 55 #include <sys/pgo.h> 56 57 #if CONFIG_CSR 58 #include <sys/csr.h> 59 #include <sys/stat.h> 60 #include <sys/vnode.h> 61 #endif /* CONFIG_CSR */ 62 }; 63 64 #if CONFIG_MACF 65 #include <sys/kauth.h> 66 #include <security/mac_framework.h> 67 #endif 68 69 #include <vm/vm_kern_xnu.h> 70 #include <sys/sysctl.h> 71 #include <kern/task.h> 72 #include <os/cpp_util.h> 73 74 #include <libkern/OSKextLibPrivate.h> 75 #include <libkern/c++/OSKext.h> 76 #include <libkern/c++/OSLib.h> 77 78 #include <IOKit/IOLib.h> 79 #include <IOKit/IOCatalogue.h> 80 #include <IOKit/IORegistryEntry.h> 81 #include <IOKit/IOService.h> 82 #include <IOKit/IOUserServer.h> 83 84 #include <IOKit/IOStatisticsPrivate.h> 85 #include <IOKit/IOBSD.h> 86 #include <IOKit/IOPlatformExpert.h> 87 88 #include <san/kasan.h> 89 90 #if CONFIG_SPTM 91 #include <arm64/sptm/sptm.h> 92 #endif 93 94 #if PRAGMA_MARK 95 #pragma mark External & Internal Function Protos 96 #endif 97 /********************************************************************* 98 *********************************************************************/ 99 extern "C" { 100 extern int IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize); 101 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize); 102 103 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */ 104 extern int dtrace_keep_kernel_symbols(void); 105 106 #if defined(__x86_64__) || defined(__i386__) 107 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide); 108 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers); 109 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size); 110 static void *allocate_kcfileset_map_entry_list(void); 111 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size); 112 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable); 113 int vnode_put(struct vnode *vp); 114 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size, 115 void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot); 116 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size); 117 void * ubc_getobject(struct vnode *vp, __unused int flags); 118 #endif //(__x86_64__) || defined(__i386__) 119 } 120 121 extern unsigned long gVirtBase; 122 extern unsigned long gPhysBase; 123 124 bool pageableKCloaded = false; 125 bool auxKCloaded = false; 126 bool resetAuxKCSegmentOnUnload = false; 127 128 extern boolean_t pageablekc_uuid_valid; 129 extern uuid_t pageablekc_uuid; 130 extern uuid_string_t pageablekc_uuid_string; 131 132 extern boolean_t auxkc_uuid_valid; 133 extern uuid_t auxkc_uuid; 134 extern uuid_string_t auxkc_uuid_string; 135 136 static OSReturn _OSKextCreateRequest( 137 const char * predicate, 138 OSSharedPtr<OSDictionary> & requestP); 139 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict); 140 static OSObject * _OSKextGetRequestArgument( 141 OSDictionary * requestDict, 142 const char * argName); 143 static bool _OSKextSetRequestArgument( 144 OSDictionary * requestDict, 145 const char * argName, 146 OSMetaClassBase * value); 147 template <typename T> 148 static T * _OSKextExtractPointer(OSValueObject<T *> * wrapper); 149 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper); 150 static OSReturn _OSDictionarySetCStringValue( 151 OSDictionary * dict, 152 const char * key, 153 const char * value); 154 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID); 155 #if CONFIG_KXLD 156 static bool _OSKextInPrelinkRebuildWindow(void); 157 #endif 158 159 // We really should add containsObject() & containsCString to OSCollection & subclasses. 160 // So few pad slots, though.... 161 static bool _OSArrayContainsCString(OSArray * array, const char * cString); 162 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code); 163 164 static const char *getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size); 165 166 /* Prelinked arm kexts do not have VM entries because the method we use to 167 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does 168 * not work on ARM. To get around that, we must free prelinked kext 169 * executables with ml_static_mfree() instead of kext_free(). 170 */ 171 #if __i386__ || __x86_64__ 172 #define VM_MAPPED_KEXTS 1 173 #define KASLR_KEXT_DEBUG 0 174 #define KASLR_IOREG_DEBUG 0 175 #elif __arm__ || __arm64__ 176 #define VM_MAPPED_KEXTS 0 177 #define KASLR_KEXT_DEBUG 0 178 #else 179 #error Unsupported architecture 180 #endif 181 182 #if PRAGMA_MARK 183 #pragma mark Constants & Macros 184 #endif 185 /********************************************************************* 186 * Constants & Macros 187 *********************************************************************/ 188 189 /* Use this number to create containers. 190 */ 191 #define kOSKextTypicalLoadCount (150) 192 #define kOSKextTypicalUpgradeCount (5) 193 194 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict. 195 * A loaded kext will no dependents or external retains will have 2 retains. 196 */ 197 #define kOSKextMinRetainCount (1) 198 #define kOSKextMinLoadedRetainCount (2) 199 200 #define kOSKextMaxDextLaunchedCount (~((uint32_t)0)) 201 #define KOSBundleDextUniqueIdentifierMaxStringLength (KOSBundleDextUniqueIdentifierMaxLength * 2 +1) 202 203 /********** 204 * Strings and substrings used in dependency resolution. 205 */ 206 #define APPLE_KEXT_PREFIX "com.apple." 207 #define KERNEL_LIB "com.apple.kernel" 208 209 #define PRIVATE_KPI "com.apple.kpi.private" 210 211 /* Version for compatbility pseudokexts (com.apple.kernel.*), 212 * compatible back to v6.0. 213 */ 214 #define KERNEL6_LIB "com.apple.kernel.6.0" 215 #define KERNEL6_VERSION "7.9.9" 216 217 #define KERNEL_LIB_PREFIX "com.apple.kernel." 218 #define KPI_LIB_PREFIX "com.apple.kpi." 219 220 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0) 221 222 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes 223 #define MINIMUM_WAKEUP_SECONDS (30) 224 225 /********************************************************************* 226 * infoDict keys for internally-stored data. Saves on ivar slots for 227 * objects we don't keep around past boot time or during active load. 228 *********************************************************************/ 229 230 /* A usable, uncompressed file is stored under this key. 231 */ 232 #define _kOSKextExecutableKey "_OSKextExecutable" 233 234 /* An indirect reference to the executable file from an mkext 235 * is stored under this key. 236 */ 237 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference" 238 239 /* If the file is contained in a larger buffer laid down by the booter or 240 * sent from user space, the OSKext stores that OSData under this key so that 241 * references are properly tracked. This is always an mkext, right now. 242 */ 243 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData" 244 245 #define OS_LOG_HDR_VERSION 1 246 #define NUM_OS_LOG_SECTIONS 3 247 248 #define OS_LOG_SECT_IDX 0 249 #define CSTRING_SECT_IDX 1 250 #define ASAN_CSTRING_SECT_IDX 2 251 252 #if PRAGMA_MARK 253 #pragma mark Typedefs 254 #endif 255 /********************************************************************* 256 * Typedefs 257 *********************************************************************/ 258 259 /********************************************************************* 260 * osLogDataHeaderRef describes the header information of an OSData 261 * object that is returned when querying for kOSBundleLogStringsKey. 262 * We currently return information regarding 2 sections - os_log and 263 * cstring. In the case that the os_log section doesn't exist, we just 264 * return an offset and length of 0 for that section. 265 *********************************************************************/ 266 typedef struct osLogDataHeader { 267 uint32_t version; 268 uint32_t sect_count; 269 struct { 270 uint32_t sect_offset; 271 uint32_t sect_size; 272 } sections[0]; 273 } osLogDataHeaderRef; 274 275 /********************************************************************* 276 * MkextEntryRef describes the contents of an OSData object 277 * referencing a file entry from an mkext so that we can uncompress 278 * (if necessary) and extract it on demand. 279 * 280 * It contains the mkextVersion in case we ever wind up supporting 281 * multiple mkext formats. Mkext format 1 is officially retired as of 282 * Snow Leopard. 283 *********************************************************************/ 284 typedef struct MkextEntryRef { 285 mkext_basic_header * mkext; // beginning of whole mkext file 286 void * fileinfo;// mkext2_file_entry or equiv; see mkext.h 287 } MkextEntryRef; 288 289 #if PRAGMA_MARK 290 #pragma mark Global and static Module Variables 291 #endif 292 /********************************************************************* 293 * Global & static variables, used to keep track of kexts. 294 *********************************************************************/ 295 296 static bool sPrelinkBoot = false; 297 static bool sSafeBoot = false; 298 static bool sKeepSymbols = false; 299 static bool sPanicOnKCMismatch = false; 300 static bool sOSKextWasResetAfterUserspaceReboot = false; 301 302 /********************************************************************* 303 * sKextLock is the principal lock for OSKext, and guards all static 304 * and global variables not owned by other locks (declared further 305 * below). It must be taken by any entry-point method or function, 306 * including internal functions called on scheduled threads. 307 * 308 * sKextLock and sKextInnerLock are recursive due to multiple functions 309 * that are called both externally and internally. The other locks are 310 * nonrecursive. 311 * 312 * Which locks are taken depends on what they protect, but if more than 313 * one must be taken, they must always be locked in this order 314 * (and unlocked in reverse order) to prevent deadlocks: 315 * 316 * 1. sKextLock 317 * 2. sKextInnerLock 318 * 3. sKextSummariesLock 319 * 4. sKextLoggingLock 320 */ 321 static IORecursiveLock * sKextLock = NULL; 322 323 static OSSharedPtr<OSDictionary> sKextsByID; 324 static OSSharedPtr<OSDictionary> sExcludeListByID; 325 static OSKextVersion sExcludeListVersion = 0; 326 static OSSharedPtr<OSArray> sLoadedKexts; 327 static OSSharedPtr<OSDictionary> sNonLoadableKextsByID; 328 static OSSharedPtr<OSArray> sUnloadedPrelinkedKexts; 329 static OSSharedPtr<OSArray> sLoadedDriverKitKexts; 330 static OSSharedPtr<OSDictionary> sDriverKitToUpgradeByID; 331 332 // Requests to the IOKit daemon waiting to be picked up. 333 static OSSharedPtr<OSArray> sKernelRequests; 334 // Identifier of kext load requests in sKernelRequests 335 static OSSharedPtr<OSSet> sPostedKextLoadIdentifiers; 336 static OSSharedPtr<OSArray> sRequestCallbackRecords; 337 338 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel 339 static OSSharedPtr<OSSet> sAllKextLoadIdentifiers; 340 #if CONFIG_KXLD 341 static KXLDContext * sKxldContext = NULL; 342 #endif 343 static uint32_t sNextLoadTag = 0; 344 static uint32_t sNextRequestTag = 0; 345 346 static bool sUserLoadsActive = false; 347 static bool sIOKitDaemonActive = false; 348 static bool sDeferredLoadSucceeded = false; 349 static bool sConsiderUnloadsExecuted = false; 350 351 #if NO_KEXTD 352 static bool sKernelRequestsEnabled = false; 353 #else 354 static bool sKernelRequestsEnabled = true; 355 #endif 356 static bool sLoadEnabled = true; 357 static bool sUnloadEnabled = true; 358 359 /********************************************************************* 360 * Stuff for the OSKext representing the kernel itself. 361 **********/ 362 static OSKext * sKernelKext = NULL; 363 364 /* Load Tag IDs used by statically loaded binaries (e.g, the kernel itself). */ 365 enum : uint32_t { 366 kOSKextKernelLoadTag = 0, 367 #if CONFIG_SPTM 368 kOSKextSPTMLoadTag = 1, 369 kOSKextTXMLoadTag = 2, 370 #endif /* CONFIG_SPTM */ 371 kOSKextLoadTagCount 372 }; 373 374 /* Set up a fake kmod_info struct for the kernel. 375 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP() 376 * before OSKext is initialized; that call only needs the name 377 * and address to be set correctly. 378 * 379 * We don't do much else with the kerne's kmod_info; we never 380 * put it into the kmod list, never adjust the reference count, 381 * and never have kernel components reference it. 382 * For that matter, we don't do much with kmod_info structs 383 * at all anymore! We just keep them filled in for gdb and 384 * binary compability. 385 */ 386 kmod_info_t g_kernel_kmod_info = { 387 .next = NULL, 388 .info_version = KMOD_INFO_VERSION, 389 .id = kOSKextKernelLoadTag, // loadTag: kernel is always 0 390 .name = kOSKextKernelIdentifier,// bundle identifier 391 .version = "0", // filled in in OSKext::initialize() 392 .reference_count = -1, // never adjusted; kernel never unloads 393 .reference_list = NULL, 394 .address = 0, 395 .size = 0, // filled in in OSKext::initialize() 396 .hdr_size = 0, 397 .start = NULL, 398 .stop = NULL 399 }; 400 401 #if CONFIG_SPTM 402 /* The SPTM and TXM need fake kmod structures just like the kernel. */ 403 kmod_info_t g_sptm_kmod_info = { 404 .next = NULL, 405 .info_version = KMOD_INFO_VERSION, 406 .id = kOSKextSPTMLoadTag, // Always one after the kernel 407 .name = kOSKextSPTMIdentifier,// bundle identifier 408 .version = "0", // filled in by OSKext::initialize() 409 .reference_count = -1, // never adjusted; SPTM never unloads 410 .reference_list = NULL, 411 .address = 0, 412 .size = 0, // filled in by OSKext::initialize() 413 .hdr_size = 0, 414 .start = NULL, 415 .stop = NULL 416 }; 417 418 kmod_info_t g_txm_kmod_info = { 419 .next = NULL, 420 .info_version = KMOD_INFO_VERSION, 421 .id = kOSKextTXMLoadTag, // Always one after the SPTM 422 .name = kOSKextTXMIdentifier,// bundle identifier 423 .version = "0", // filled in by OSKext::initialize() 424 .reference_count = -1, // never adjusted; TXM never unloads 425 .reference_list = NULL, 426 .address = 0, 427 .size = 0, // filled in by OSKext::initialize() 428 .hdr_size = 0, 429 .start = NULL, 430 .stop = NULL 431 }; 432 #endif /* CONFIG_SPTM */ 433 434 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */ 435 436 kmod_info_t invalid_kmod_info = { 437 .next = NULL, 438 .info_version = KMOD_INFO_VERSION, 439 .id = UINT32_MAX, 440 .name = "invalid", 441 .version = "0", 442 .reference_count = -1, 443 .reference_list = NULL, 444 .address = 0, 445 .size = 0, 446 .hdr_size = 0, 447 .start = NULL, 448 .stop = NULL 449 }; 450 451 extern "C" { 452 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c, 453 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s, 454 // misc_protos.h, db_low_trace.c, kgmacros 455 // 'kmod' is a holdover from the old kmod system, we can't rename it. 456 kmod_info_t * kmod = NULL; 457 458 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE) 459 460 461 static char * loaded_kext_paniclist = NULL; 462 static uint32_t loaded_kext_paniclist_size = 0; 463 464 AbsoluteTime last_loaded_timestamp; 465 static char last_loaded_str_buf[2 * KMOD_MAX_NAME]; 466 static u_long last_loaded_strlen = 0; 467 static void * last_loaded_address = NULL; 468 static u_long last_loaded_size = 0; 469 470 AbsoluteTime last_unloaded_timestamp; 471 static char last_unloaded_str_buf[2 * KMOD_MAX_NAME]; 472 static u_long last_unloaded_strlen = 0; 473 static void * last_unloaded_address = NULL; 474 static u_long last_unloaded_size = 0; 475 476 // Statically linked kmods described by several mach-o sections: 477 // 478 // kPrelinkInfoSegment:kBuiltinInfoSection 479 // Array of pointers to kmod_info_t structs. 480 // 481 // kPrelinkInfoSegment:kBuiltinInfoSection 482 // Array of pointers to an embedded mach-o header. 483 // 484 // __DATA:kBuiltinInitSection, kBuiltinTermSection 485 // Structors for all kmods. Has to be filtered by proc address. 486 // 487 488 static uint32_t gBuiltinKmodsCount; 489 static kernel_section_t * gBuiltinKmodsSectionInfo; 490 static kernel_section_t * gBuiltinKmodsSectionStart; 491 492 const OSSymbol * gIOSurfaceIdentifier; 493 vm_tag_t gIOSurfaceTag; 494 495 /********************************************************************* 496 * sKextInnerLock protects against cross-calls with IOService and 497 * IOCatalogue, and owns the variables declared immediately below. 498 * 499 * Note that sConsiderUnloadsExecuted above belongs to sKextLock! 500 * 501 * When both sKextLock and sKextInnerLock need to be taken, 502 * always lock sKextLock first and unlock it second. Never take both 503 * locks in an entry point to OSKext; if you need to do so, you must 504 * spawn an independent thread to avoid potential deadlocks for threads 505 * calling into OSKext. 506 **********/ 507 static IORecursiveLock * sKextInnerLock = NULL; 508 509 #if XNU_TARGET_OS_OSX 510 static bool sAutounloadEnabled = true; 511 #endif 512 static bool sConsiderUnloadsCalled = false; 513 static bool sConsiderUnloadsPending = false; 514 515 static unsigned int sConsiderUnloadDelay = 60; // seconds 516 static thread_call_t sUnloadCallout = NULL; 517 #if CONFIG_KXLD 518 static thread_call_t sDestroyLinkContextThread = NULL; // one-shot, one-at-a-time thread 519 #endif // CONFIG_KXLD 520 static bool sSystemSleep = false; // true when system going to sleep 521 static AbsoluteTime sLastWakeTime; // last time we woke up 522 523 /********************************************************************* 524 * Backtraces can be printed at various times so we need a tight lock 525 * on data used for that. sKextSummariesLock protects the variables 526 * declared immediately below. 527 * 528 * gLoadedKextSummaries is accessed by other modules, but only during 529 * a panic so the lock isn't needed then. 530 * 531 * gLoadedKextSummaries has the "used" attribute in order to ensure 532 * that it remains visible even when we are performing extremely 533 * aggressive optimizations, as it is needed to allow the debugger 534 * to automatically parse the list of loaded kexts. 535 **********/ 536 static IOLock * sKextSummariesLock = NULL; 537 extern "C" lck_grp_t vm_page_lck_grp_bucket; 538 static lck_grp_t * sKextAccountsLockGrp = &vm_page_lck_grp_bucket; 539 #define sKextAccountsLock (&vm_allocation_sites_lock) 540 541 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated; 542 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL; 543 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0; 544 static size_t sLoadedKextSummariesAllocSize = 0; 545 546 static OSKextActiveAccount * sKextAccounts; 547 static uint32_t sKextAccountsCount; 548 }; 549 550 /********************************************************************* 551 * sKextLoggingLock protects the logging variables declared immediately below. 552 **********/ 553 static IOLock * sKextLoggingLock = NULL; 554 555 static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel | 556 kOSKextLogVerboseFlagsMask; 557 static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter; 558 static bool sBootArgLogFilterFound = false; 559 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter, 560 0, "kernel kext logging"); 561 562 static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter; 563 static OSSharedPtr<OSArray> sUserSpaceLogSpecArray; 564 static OSSharedPtr<OSArray> sUserSpaceLogMessageArray; 565 566 /********* 567 * End scope for sKextInnerLock-protected variables. 568 *********************************************************************/ 569 570 /********************************************************************* 571 * OSValueObject concrete type instantiations 572 **********/ 573 OSDefineValueObjectForDependentType(void*) 574 OSDefineValueObjectForDependentType(OSKextRequestResourceCallback) 575 576 577 /**********************************************************************/ 578 579 TUNABLE(uint32_t, kMaxDextCrashesInOneDay, "daily_max_dext_crashes", kMaxDextCrashesInOneDayDefault); 580 581 /********************************************************************* 582 * helper function used for collecting PGO data upon unload of a kext 583 */ 584 585 static int OSKextGrabPgoDataLocked(OSKext *kext, 586 bool metadata, 587 uuid_t instance_uuid, 588 uint64_t *pSize, 589 char *pBuffer, 590 uint64_t bufferSize); 591 592 /**********************************************************************/ 593 594 595 596 #if PRAGMA_MARK 597 #pragma mark OSData callbacks (need to move to OSData) 598 #endif 599 /********************************************************************* 600 * C functions used for callbacks. 601 *********************************************************************/ 602 extern "C" { 603 void 604 osdata_kmem_free(void * ptr, unsigned int length) 605 { 606 kmem_free(kernel_map, (vm_address_t)ptr, length); 607 return; 608 } 609 610 void 611 osdata_phys_free(void * ptr, unsigned int length) 612 { 613 ml_static_mfree((vm_offset_t)ptr, length); 614 return; 615 } 616 617 void 618 osdata_vm_deallocate(void * ptr, unsigned int length) 619 { 620 (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length); 621 return; 622 } 623 624 void 625 osdata_kext_free(void * ptr, unsigned int length) 626 { 627 (void)kext_free((vm_offset_t)ptr, length); 628 } 629 }; 630 631 #if PRAGMA_MARK 632 #pragma mark KXLD Allocation Callback 633 #endif 634 #if CONFIG_KXLD 635 /********************************************************************* 636 * KXLD Allocation Callback 637 *********************************************************************/ 638 kxld_addr_t 639 kern_allocate( 640 u_long size, 641 KXLDAllocateFlags * flags, 642 void * user_data) 643 { 644 vm_address_t result = 0; // returned 645 kern_return_t mach_result = KERN_FAILURE; 646 bool success = false; 647 OSKext * theKext = (OSKext *)user_data; 648 unsigned int roundSize = 0; 649 OSSharedPtr<OSData> linkBuffer; 650 651 if (round_page(size) > UINT_MAX) { 652 OSKextLog(theKext, 653 kOSKextLogErrorLevel | 654 kOSKextLogGeneralFlag, 655 "%s: Requested memory size is greater than UINT_MAX.", 656 theKext->getIdentifierCString()); 657 goto finish; 658 } 659 660 roundSize = (unsigned int)round_page(size); 661 662 mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE); 663 if (mach_result != KERN_SUCCESS) { 664 OSKextLog(theKext, 665 kOSKextLogErrorLevel | 666 kOSKextLogGeneralFlag, 667 "Can't allocate kernel memory to link %s.", 668 theKext->getIdentifierCString()); 669 goto finish; 670 } 671 672 /* Create an OSData wrapper for the allocated buffer. 673 */ 674 linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize); 675 if (!linkBuffer) { 676 OSKextLog(theKext, 677 kOSKextLogErrorLevel | 678 kOSKextLogGeneralFlag, 679 "Can't allocate linked executable wrapper for %s.", 680 theKext->getIdentifierCString()); 681 goto finish; 682 } 683 linkBuffer->setDeallocFunction(osdata_kext_free); 684 OSKextLog(theKext, 685 kOSKextLogProgressLevel | 686 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 687 "Allocated link buffer for kext %s at %p (%lu bytes).", 688 theKext->getIdentifierCString(), 689 (void *)result, (unsigned long)roundSize); 690 691 theKext->setLinkedExecutable(linkBuffer.get()); 692 693 *flags = kKxldAllocateWritable; 694 success = true; 695 696 finish: 697 if (!success && result) { 698 kext_free(result, roundSize); 699 result = 0; 700 } 701 702 return (kxld_addr_t)result; 703 } 704 705 /********************************************************************* 706 *********************************************************************/ 707 void 708 kxld_log_callback( 709 KXLDLogSubsystem subsystem, 710 KXLDLogLevel level, 711 const char * format, 712 va_list argList, 713 void * user_data) 714 { 715 OSKext *theKext = (OSKext *) user_data; 716 OSKextLogSpec logSpec = 0; 717 718 switch (subsystem) { 719 case kKxldLogLinking: 720 logSpec |= kOSKextLogLinkFlag; 721 break; 722 case kKxldLogPatching: 723 logSpec |= kOSKextLogPatchFlag; 724 break; 725 } 726 727 switch (level) { 728 case kKxldLogExplicit: 729 logSpec |= kOSKextLogExplicitLevel; 730 break; 731 case kKxldLogErr: 732 logSpec |= kOSKextLogErrorLevel; 733 break; 734 case kKxldLogWarn: 735 logSpec |= kOSKextLogWarningLevel; 736 break; 737 case kKxldLogBasic: 738 logSpec |= kOSKextLogProgressLevel; 739 break; 740 case kKxldLogDetail: 741 logSpec |= kOSKextLogDetailLevel; 742 break; 743 case kKxldLogDebug: 744 logSpec |= kOSKextLogDebugLevel; 745 break; 746 } 747 748 OSKextVLog(theKext, logSpec, format, argList); 749 } 750 #endif // CONFIG_KXLD 751 752 #if PRAGMA_MARK 753 #pragma mark IOStatistics defines 754 #endif 755 756 #if IOKITSTATS 757 758 #define notifyKextLoadObservers(kext, kmod_info) \ 759 do { \ 760 IOStatistics::onKextLoad(kext, kmod_info); \ 761 } while (0) 762 763 #define notifyKextUnloadObservers(kext) \ 764 do { \ 765 IOStatistics::onKextUnload(kext); \ 766 } while (0) 767 768 #define notifyAddClassObservers(kext, addedClass, flags) \ 769 do { \ 770 IOStatistics::onClassAdded(kext, addedClass); \ 771 } while (0) 772 773 #define notifyRemoveClassObservers(kext, removedClass, flags) \ 774 do { \ 775 IOStatistics::onClassRemoved(kext, removedClass); \ 776 } while (0) 777 778 #else 779 780 #define notifyKextLoadObservers(kext, kmod_info) 781 #define notifyKextUnloadObservers(kext) 782 #define notifyAddClassObservers(kext, addedClass, flags) 783 #define notifyRemoveClassObservers(kext, removedClass, flags) 784 785 #endif /* IOKITSTATS */ 786 787 #if PRAGMA_MARK 788 #pragma mark Module Config (Startup & Shutdown) 789 #endif 790 /********************************************************************* 791 * Module Config (Class Definition & Class Methods) 792 *********************************************************************/ 793 #define super OSObject 794 OSDefineMetaClassAndStructors(OSKext, OSObject) 795 796 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject); 797 798 OSDefineMetaClassAndStructors(OSDextStatistics, OSObject); 799 800 /********************************************************************* 801 *********************************************************************/ 802 /** 803 * Allocate and intialize a fake/representative OSKext object for a statically 804 * loaded (by iBoot) binary (e.g., the XNU kernel itself). 805 * 806 * @param kmod_info Pointer to the kmod_info structure for the binary being 807 * setup. At least the "name" and "id" fields needs to already 808 * be set correctly. 809 * 810 * @return The allocated and initialized OSKext object. 811 */ 812 /* static */ 813 OSKext * 814 OSKext::allocAndInitFakeKext(kmod_info_t *kmod_info) 815 { 816 vm_offset_t load_address = 0; 817 const char *bundle_name = NULL; 818 bool macho_is_unslid = false; 819 bool set_custom_path = false; 820 const char *executable_fallback_name = NULL; 821 822 if (kmod_info->id == kOSKextKernelLoadTag) { 823 load_address = (vm_offset_t)&_mh_execute_header; 824 bundle_name = "mach_kernel"; 825 826 /* The kernel Mach-O header is fixed up to slide all of its addresses. */ 827 macho_is_unslid = false; 828 829 /** 830 * No path to the binary is set for the kernel in its OSKext object. The 831 * kernel binary is located in fixed directories depending on the OS. 832 */ 833 set_custom_path = false; 834 executable_fallback_name = NULL; 835 #if CONFIG_SPTM 836 } else if (kmod_info->id == kOSKextSPTMLoadTag) { 837 load_address = (vm_offset_t)SPTMArgs->debug_header->image[DEBUG_HEADER_ENTRY_SPTM]; 838 bundle_name = "sptm"; 839 840 /* The addresses in the SPTM Mach-O header are all unslid. */ 841 macho_is_unslid = true; 842 843 set_custom_path = true; 844 executable_fallback_name = "sptm.no.binname.in.macho"; 845 } else if (kmod_info->id == kOSKextTXMLoadTag) { 846 load_address = (vm_offset_t)SPTMArgs->debug_header->image[DEBUG_HEADER_ENTRY_TXM]; 847 bundle_name = "txm"; 848 849 /* The addresses in the TXM Mach-O header are all unslid. */ 850 macho_is_unslid = true; 851 852 set_custom_path = true; 853 executable_fallback_name = "txm.no.binname.in.macho"; 854 #endif /* CONFIG_SPTM */ 855 } else { 856 panic("%s: Unsupported kmod_info->id (%d)", __func__, kmod_info->id); 857 } 858 859 /* Set up an OSKext instance to represent the statically loaded binary. */ 860 OSKext *fakeKext = new OSKext; 861 assert(fakeKext); 862 assert(load_address != 0); 863 864 /* 865 * The start address is always a slid address whereas the last VA returned 866 * by getlastaddr() might be unslid depending on the Mach-O. If the address 867 * coming from the Mach-O is unslid, then unslide the start address before 868 * computing the length of the executable. 869 */ 870 size_t binaryLength = getlastaddr((kernel_mach_header_t*)load_address); 871 binaryLength -= (macho_is_unslid) ? ml_static_unslide(load_address) : load_address; 872 assert(binaryLength <= UINT_MAX); 873 874 /** 875 * The load address is always slid. That value will be unslid before being 876 * exposed to userspace. 877 */ 878 OSSharedPtr<OSData> executable = OSData::withBytesNoCopy( 879 (void*)load_address, (unsigned int)binaryLength); 880 assert(executable); 881 882 fakeKext->loadTag = sNextLoadTag++; 883 fakeKext->bundleID = OSSymbol::withCString(kmod_info->name); 884 885 fakeKext->version = OSKextParseVersionString(osrelease); 886 fakeKext->compatibleVersion = fakeKext->version; 887 fakeKext->linkedExecutable = os::move(executable); 888 fakeKext->interfaceUUID = fakeKext->copyUUID(); 889 890 fakeKext->flags.hasAllDependencies = 1; 891 fakeKext->flags.kernelComponent = 1; 892 fakeKext->flags.prelinked = 0; 893 fakeKext->flags.loaded = 1; 894 fakeKext->flags.started = 1; 895 fakeKext->flags.CPPInitialized = 0; 896 fakeKext->flags.jettisonLinkeditSeg = 0; 897 fakeKext->flags.unslidMachO = macho_is_unslid; 898 899 #if CONFIG_SPTM 900 if (set_custom_path) { 901 /* Only SPTM/TXM should have custom paths to their executables set. */ 902 assert((kmod_info->id == kOSKextSPTMLoadTag) || 903 (kmod_info->id == kOSKextTXMLoadTag)); 904 905 /* All SPTM/TXM binaries are placed into the same path on internal systems. */ 906 fakeKext->path = OSString::withCStringNoCopy("/usr/appleinternal/standalone/platform"); 907 908 /** 909 * Each SPTM/TXM Mach-O should contain a __TEXT,__binname section which contains 910 * a character array representing the name of the Mach-O executable. 911 */ 912 kernel_section_t *binname_sect = 913 getsectbynamefromheader((kernel_mach_header_t*)load_address, "__TEXT", "__binname"); 914 915 if (binname_sect != NULL) { 916 const char *binname = (const char *)ml_static_slide(binname_sect->addr); 917 fakeKext->executableRelPath = OSString::withCStringNoCopy(binname); 918 } else { 919 fakeKext->executableRelPath = OSString::withCStringNoCopy(executable_fallback_name); 920 } 921 } 922 #endif /* CONFIG_SPTM */ 923 924 fakeKext->kmod_info = kmod_info; 925 strlcpy(kmod_info->version, osrelease, 926 sizeof(kmod_info->version)); 927 kmod_info->size = binaryLength; 928 assert(kmod_info->id == fakeKext->loadTag); 929 930 /* 931 * Con up an info dict, so we don't have to have special-case checking all 932 * over. 933 */ 934 fakeKext->infoDict = OSDictionary::withCapacity(5); 935 assert(fakeKext->infoDict); 936 bool setResult = fakeKext->infoDict->setObject(kCFBundleIdentifierKey, 937 fakeKext->bundleID.get()); 938 assert(setResult); 939 setResult = fakeKext->infoDict->setObject(kOSKernelResourceKey, 940 kOSBooleanTrue); 941 assert(setResult); 942 943 { 944 OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease)); 945 assert(scratchString); 946 setResult = fakeKext->infoDict->setObject(kCFBundleVersionKey, 947 scratchString.get()); 948 assert(setResult); 949 } 950 951 { 952 OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(bundle_name)); 953 assert(scratchString); 954 setResult = fakeKext->infoDict->setObject(kCFBundleNameKey, 955 scratchString.get()); 956 assert(setResult); 957 } 958 959 return fakeKext; 960 } 961 962 /* static */ 963 void 964 OSKext::initialize(void) 965 { 966 OSSharedPtr<OSData> kernelExecutable = NULL;// do not release 967 IORegistryEntry * registryRoot = NULL;// do not release 968 OSSharedPtr<OSNumber> kernelCPUType; 969 OSSharedPtr<OSNumber> kernelCPUSubtype; 970 OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter; 971 bool setResult = false; 972 uint64_t * timestamp = NULL; 973 __unused char bootArgBuffer[16];// for PE_parse_boot_argn w/strings 974 975 /* This must be the first thing allocated. Everything else grabs this lock. 976 */ 977 sKextLock = IORecursiveLockAlloc(); 978 sKextInnerLock = IORecursiveLockAlloc(); 979 sKextSummariesLock = IOLockAlloc(); 980 sKextLoggingLock = IOLockAlloc(); 981 assert(sKextLock); 982 assert(sKextInnerLock); 983 assert(sKextSummariesLock); 984 assert(sKextLoggingLock); 985 986 sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount); 987 sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 988 sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 989 sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10); 990 sKernelRequests = OSArray::withCapacity(0); 991 sPostedKextLoadIdentifiers = OSSet::withCapacity(0); 992 sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount); 993 sRequestCallbackRecords = OSArray::withCapacity(0); 994 sDriverKitToUpgradeByID = OSDictionary::withCapacity(kOSKextTypicalUpgradeCount); 995 996 assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests && 997 sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers && 998 sRequestCallbackRecords && sUnloadedPrelinkedKexts && sDriverKitToUpgradeByID); 999 1000 /* Read the log flag boot-args and set the log flags. 1001 */ 1002 if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) { 1003 sBootArgLogFilterFound = true; 1004 sKernelLogFilter = bootLogFilter; 1005 // log this if any flags are set 1006 OSKextLog(/* kext */ NULL, 1007 kOSKextLogBasicLevel | 1008 kOSKextLogFlagsMask, 1009 "Kernel kext log filter 0x%x per kextlog boot arg.", 1010 (unsigned)sKernelLogFilter); 1011 } 1012 1013 #if !defined(__arm__) && !defined(__arm64__) 1014 /* 1015 * On our ARM targets, the kernelcache/boot kernel collection contains 1016 * the set of kexts required to boot, as specified by KCB. Safeboot is 1017 * either unsupported, or is supported by the bootloader only loading 1018 * the boot kernel collection; as a result OSKext has no role to play 1019 * in safeboot policy on ARM. 1020 */ 1021 sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer, 1022 sizeof(bootArgBuffer)) ? true : false; 1023 #endif /* defined(__arm__) && defined(__arm64__) */ 1024 1025 if (sSafeBoot) { 1026 OSKextLog(/* kext */ NULL, 1027 kOSKextLogWarningLevel | 1028 kOSKextLogGeneralFlag, 1029 "SAFE BOOT DETECTED - " 1030 "only valid OSBundleRequired kexts will be loaded."); 1031 } 1032 1033 PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols)); 1034 #if CONFIG_DTRACE 1035 if (dtrace_keep_kernel_symbols()) { 1036 sKeepSymbols = true; 1037 } 1038 #endif /* CONFIG_DTRACE */ 1039 #if KASAN_DYNAMIC_BLACKLIST 1040 /* needed for function lookup */ 1041 sKeepSymbols = true; 1042 #endif 1043 1044 /* 1045 * Should we panic when the SystemKC is not linked against the 1046 * BootKC that was loaded by the booter? By default: yes, if the 1047 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic 1048 * on mis-match and instead just print an error and continue. 1049 */ 1050 sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer, 1051 sizeof(bootArgBuffer)) ? false : true; 1052 1053 /* Set up an OSKext instance to represent the kernel itself. */ 1054 sKernelKext = allocAndInitFakeKext(&g_kernel_kmod_info); 1055 assert(sKernelKext); 1056 1057 #if CONFIG_SPTM 1058 /* Set up OSKext instances to represent the SPTM/TXM. */ 1059 OSKext *SPTMKext = allocAndInitFakeKext(&g_sptm_kmod_info); 1060 OSKext *TXMKext = allocAndInitFakeKext(&g_txm_kmod_info); 1061 #endif 1062 1063 /* Add the kernel kext to the bookkeeping dictionaries. Note that 1064 * the kernel kext doesn't have a kmod_info struct. copyInfo() 1065 * gathers info from other places anyhow. 1066 */ 1067 setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext); 1068 assert(setResult); 1069 setResult = sLoadedKexts->setObject(sKernelKext); 1070 assert(setResult); 1071 1072 #if CONFIG_SPTM 1073 setResult = sKextsByID->setObject(SPTMKext->bundleID.get(), SPTMKext); 1074 assert(setResult); 1075 setResult = sLoadedKexts->setObject(SPTMKext); 1076 assert(setResult); 1077 1078 setResult = sKextsByID->setObject(TXMKext->bundleID.get(), TXMKext); 1079 assert(setResult); 1080 setResult = sLoadedKexts->setObject(TXMKext); 1081 assert(setResult); 1082 #endif /* CONFIG_SPTM */ 1083 1084 // XXX: better way with OSSharedPtr? 1085 // sKernelKext remains a valid pointer even after the decref 1086 sKernelKext->release(); 1087 #if CONFIG_SPTM 1088 SPTMKext->release(); 1089 TXMKext->release(); 1090 #endif /* CONFIG_SPTM */ 1091 1092 registryRoot = IORegistryEntry::getRegistryRoot(); 1093 kernelCPUType = OSNumber::withNumber( 1094 (long long unsigned int)_mh_execute_header.cputype, 1095 8 * sizeof(_mh_execute_header.cputype)); 1096 kernelCPUSubtype = OSNumber::withNumber( 1097 (long long unsigned int)_mh_execute_header.cpusubtype, 1098 8 * sizeof(_mh_execute_header.cpusubtype)); 1099 assert(registryRoot && kernelCPUSubtype && kernelCPUType); 1100 1101 registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get()); 1102 registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get()); 1103 1104 gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection); 1105 if (gBuiltinKmodsSectionInfo) { 1106 uint32_t count; 1107 1108 assert(gBuiltinKmodsSectionInfo->addr); 1109 assert(gBuiltinKmodsSectionInfo->size); 1110 assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX); 1111 gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *)); 1112 1113 gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection); 1114 assert(gBuiltinKmodsSectionStart); 1115 assert(gBuiltinKmodsSectionStart->addr); 1116 assert(gBuiltinKmodsSectionStart->size); 1117 assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX); 1118 count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t)); 1119 // one extra pointer for the end of last kmod 1120 assert(count == (gBuiltinKmodsCount + 1)); 1121 1122 vm_kernel_builtinkmod_text = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0]; 1123 vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1]; 1124 } 1125 1126 // Don't track this object -- it's never released 1127 gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach(); 1128 1129 timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp); 1130 *timestamp = 0; 1131 timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp); 1132 *timestamp = 0; 1133 timestamp = __OSAbsoluteTimePtr(&sLastWakeTime); 1134 *timestamp = 0; 1135 1136 OSKextLog(/* kext */ NULL, 1137 kOSKextLogProgressLevel | 1138 kOSKextLogGeneralFlag, 1139 "Kext system initialized."); 1140 1141 notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info); 1142 #if CONFIG_SPTM 1143 notifyKextLoadObservers(SPTMKext, SPTMKext->kmod_info); 1144 notifyKextLoadObservers(TXMKext, TXMKext->kmod_info); 1145 #endif 1146 1147 return; 1148 } 1149 1150 /********************************************************************* 1151 * This is expected to be called exactly once, from exactly one thread 1152 * context, during kernel bootstrap. 1153 *********************************************************************/ 1154 /* static */ 1155 OSReturn 1156 OSKext::removeKextBootstrap(void) 1157 { 1158 OSReturn result = kOSReturnError; 1159 1160 const char * dt_kernel_header_name = "Kernel-__HEADER"; 1161 const char * dt_kernel_symtab_name = "Kernel-__SYMTAB"; 1162 kernel_mach_header_t * dt_mach_header = NULL; 1163 int dt_mach_header_size = 0; 1164 struct symtab_command * dt_symtab = NULL; 1165 int dt_symtab_size = 0; 1166 int dt_result = 0; 1167 1168 kernel_segment_command_t * seg_kld = NULL; 1169 kernel_segment_command_t * seg_klddata = NULL; 1170 kernel_segment_command_t * seg_linkedit = NULL; 1171 1172 const char __unused * dt_segment_name = NULL; 1173 void __unused * segment_paddress = NULL; 1174 int __unused segment_size = 0; 1175 1176 OSKextLog(/* kext */ NULL, 1177 kOSKextLogProgressLevel | 1178 kOSKextLogGeneralFlag, 1179 "Jettisoning kext bootstrap segments."); 1180 1181 /* 1182 * keep the linkedit segment around when booted from a new MH_FILESET 1183 * KC because all the kexts shared a linkedit segment. 1184 */ 1185 kc_format_t kc_format; 1186 if (!PE_get_primary_kc_format(&kc_format)) { 1187 OSKextLog(/* kext */ NULL, 1188 kOSKextLogErrorLevel | 1189 kOSKextLogGeneralFlag, 1190 "Unable to determine primary KC format"); 1191 } 1192 1193 /***** 1194 * Dispose of unnecessary stuff that the booter didn't need to load. 1195 */ 1196 dt_result = IODTGetLoaderInfo(dt_kernel_header_name, 1197 (void **)&dt_mach_header, &dt_mach_header_size); 1198 if (dt_result == 0 && dt_mach_header) { 1199 IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header, 1200 round_page_32(dt_mach_header_size)); 1201 } 1202 dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name, 1203 (void **)&dt_symtab, &dt_symtab_size); 1204 if (dt_result == 0 && dt_symtab) { 1205 IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab, 1206 round_page_32(dt_symtab_size)); 1207 } 1208 1209 /***** 1210 * KLD & KLDDATA bootstrap segments. 1211 */ 1212 // xxx - should rename KLD segment 1213 seg_kld = getsegbyname("__KLD"); 1214 seg_klddata = getsegbyname("__KLDDATA"); 1215 if (seg_klddata) { 1216 // __mod_term_func is part of __KLDDATA 1217 OSRuntimeUnloadCPPForSegment(seg_klddata); 1218 } 1219 1220 #if __arm__ || __arm64__ 1221 /* Free the memory that was set up by iBoot. 1222 */ 1223 #if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR) 1224 /* We cannot free the KLD segment with CTRR enabled as it contains text and 1225 * is covered by the contiguous rorgn. 1226 */ 1227 dt_segment_name = "Kernel-__KLD"; 1228 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) { 1229 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1230 (int)segment_size); // calls ml_static_mfree 1231 } else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) { 1232 /* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */ 1233 #if !CONFIG_SPTM 1234 ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase), 1235 seg_kld->vmsize); 1236 #else 1237 ml_static_mfree((seg_kld->vmaddr), seg_kld->vmsize); 1238 #endif 1239 } 1240 #endif 1241 dt_segment_name = "Kernel-__KLDDATA"; 1242 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) { 1243 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1244 (int)segment_size); // calls ml_static_mfree 1245 } else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) { 1246 /* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */ 1247 #if !CONFIG_SPTM 1248 ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase), 1249 seg_klddata->vmsize); 1250 #else 1251 ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize); 1252 #endif 1253 } 1254 #elif __i386__ || __x86_64__ 1255 /* On x86, use the mapping data from the segment load command to 1256 * unload KLD & KLDDATA directly. 1257 * This may invalidate any assumptions about "avail_start" 1258 * defining the lower bound for valid physical addresses. 1259 */ 1260 if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) { 1261 bzero((void *)seg_kld->vmaddr, seg_kld->vmsize); 1262 ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize); 1263 } 1264 if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) { 1265 bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize); 1266 ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize); 1267 } 1268 #else 1269 #error arch 1270 #endif 1271 1272 /***** 1273 * Prelinked kernel's symtab (if there is one). 1274 */ 1275 if (kc_format != KCFormatFileset) { 1276 kernel_section_t * sect; 1277 sect = getsectbyname("__PRELINK", "__symtab"); 1278 if (sect && sect->addr && sect->size) { 1279 ml_static_mfree(sect->addr, sect->size); 1280 } 1281 } 1282 1283 seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT"); 1284 1285 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it 1286 * pageable, unless keepsyms is set. To do that, we have to copy it from 1287 * its booter-allocated memory, free the booter memory, reallocate proper 1288 * managed memory, then copy the segment back in. 1289 * 1290 * NOTE: This optimization is not valid for fileset KCs because each 1291 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment 1292 * that points to one fileset-global LINKEDIT segment. This 1293 * optimization is also only valid for platforms that support vm 1294 * mapped kexts or mapped kext collections (pageable KCs) 1295 */ 1296 #if VM_MAPPED_KEXTS 1297 if (!sKeepSymbols && kc_format != KCFormatFileset) { 1298 kern_return_t mem_result; 1299 void *seg_copy = NULL; 1300 void *seg_data = NULL; 1301 vm_map_offset_t seg_offset = 0; 1302 vm_map_offset_t seg_copy_offset = 0; 1303 vm_map_size_t seg_length = 0; 1304 1305 seg_data = (void *) seg_linkedit->vmaddr; 1306 seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr; 1307 seg_length = (vm_map_size_t) seg_linkedit->vmsize; 1308 1309 /* Allocate space for the LINKEDIT copy. 1310 */ 1311 mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy, 1312 seg_length, KMA_ZERO, VM_KERN_MEMORY_KEXT); 1313 if (mem_result != KERN_SUCCESS) { 1314 OSKextLog(/* kext */ NULL, 1315 kOSKextLogErrorLevel | 1316 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1317 "Can't copy __LINKEDIT segment for VM reassign."); 1318 return result; 1319 } 1320 seg_copy_offset = (vm_map_offset_t) seg_copy; 1321 1322 /* Copy it out. 1323 */ 1324 memcpy(seg_copy, seg_data, seg_length); 1325 1326 /* Dump the booter memory. 1327 */ 1328 ml_static_mfree(seg_offset, seg_length); 1329 1330 /* Set up the VM region. 1331 */ 1332 mem_result = mach_vm_map_kernel( 1333 kernel_map, 1334 &seg_offset, 1335 seg_length, /* mask */ 0, 1336 VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true), 1337 (ipc_port_t)NULL, 1338 (vm_object_offset_t) 0, 1339 /* copy */ FALSE, 1340 /* cur_protection */ VM_PROT_READ | VM_PROT_WRITE, 1341 /* max_protection */ VM_PROT_ALL, 1342 /* inheritance */ VM_INHERIT_DEFAULT); 1343 if ((mem_result != KERN_SUCCESS) || 1344 (seg_offset != (vm_map_offset_t) seg_data)) { 1345 OSKextLog(/* kext */ NULL, 1346 kOSKextLogErrorLevel | 1347 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1348 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).", 1349 seg_data, seg_length, mem_result); 1350 return result; 1351 } 1352 1353 /* And copy it back. 1354 */ 1355 memcpy(seg_data, seg_copy, seg_length); 1356 1357 /* Free the copy. 1358 */ 1359 kmem_free(kernel_map, seg_copy_offset, seg_length); 1360 } else if (!sKeepSymbols && kc_format == KCFormatFileset) { 1361 /* Remove the linkedit segment of the Boot KC */ 1362 kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary); 1363 OSKext::jettisonFileSetLinkeditSegment(mh); 1364 } 1365 #else // !VM_MAPPED_KEXTS 1366 /***** 1367 * Dump the LINKEDIT segment, unless keepsyms is set. 1368 */ 1369 if (!sKeepSymbols && kc_format != KCFormatFileset) { 1370 dt_segment_name = "Kernel-__LINKEDIT"; 1371 if (0 == IODTGetLoaderInfo(dt_segment_name, 1372 &segment_paddress, &segment_size)) { 1373 #ifdef SECURE_KERNEL 1374 vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress); 1375 bzero((void*)vmaddr, segment_size); 1376 #endif 1377 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1378 (int)segment_size); 1379 } 1380 } else if (!sKeepSymbols && kc_format == KCFormatFileset) { 1381 /* Remove the linkedit segment of the Boot KC */ 1382 kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary); 1383 OSKext::jettisonFileSetLinkeditSegment(mh); 1384 } else { 1385 OSKextLog(/* kext */ NULL, 1386 kOSKextLogBasicLevel | 1387 kOSKextLogGeneralFlag, 1388 "keepsyms boot arg specified; keeping linkedit segment for symbols."); 1389 } 1390 #endif // VM_MAPPED_KEXTS 1391 1392 result = kOSReturnSuccess; 1393 1394 return result; 1395 } 1396 1397 #if CONFIG_KXLD 1398 /********************************************************************* 1399 *********************************************************************/ 1400 void 1401 OSKext::flushNonloadedKexts( 1402 Boolean flushPrelinkedKexts) 1403 { 1404 OSSharedPtr<OSSet> keepKexts; 1405 1406 /* TODO: make this more efficient with MH_FILESET kexts */ 1407 1408 // Do not unload prelinked kexts on arm because the kernelcache is not 1409 // structured in a way that allows them to be unmapped 1410 #if !defined(__x86_64__) 1411 flushPrelinkedKexts = false; 1412 #endif /* defined(__x86_64__) */ 1413 1414 IORecursiveLockLock(sKextLock); 1415 1416 OSKextLog(/* kext */ NULL, 1417 kOSKextLogProgressLevel | 1418 kOSKextLogKextBookkeepingFlag, 1419 "Flushing nonloaded kexts and other unused data."); 1420 1421 OSKext::considerDestroyingLinkContext(); 1422 1423 /* If we aren't flushing unused prelinked kexts, we have to put them 1424 * aside while we flush everything else so make a container for them. 1425 */ 1426 keepKexts = OSSet::withCapacity(16); 1427 if (!keepKexts) { 1428 goto finish; 1429 } 1430 1431 /* Set aside prelinked kexts (in-use or not) and break 1432 * any lingering inter-kext references for nonloaded kexts 1433 * so they have min. retain counts. 1434 */ 1435 { 1436 sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) { 1437 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1438 if (!thisKext) { 1439 return false; 1440 } 1441 if (!flushPrelinkedKexts && thisKext->isPrelinked()) { 1442 keepKexts->setObject(thisKext); 1443 } else if (!thisKext->declaresExecutable()) { 1444 /* 1445 * Don't unload codeless kexts, because they never appear in the loadedKexts array. 1446 * Requesting one from the IOKit daemon will load it and then immediately remove it by calling 1447 * flushNonloadedKexts(). 1448 * And adding one to loadedKexts breaks code assuming they have kmod_info etc. 1449 */ 1450 keepKexts->setObject(thisKext); 1451 } else if (thisKext->isInFileset()) { 1452 /* keep all kexts in the new MH_FILESET KC */ 1453 keepKexts->setObject(thisKext); 1454 } 1455 1456 thisKext->flushDependencies(/* forceIfLoaded */ false); 1457 return false; 1458 }); 1459 } 1460 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly. 1461 */ 1462 sKextsByID->flushCollection(); 1463 1464 /* Now put the loaded kexts back into the ID dictionary. 1465 */ 1466 sLoadedKexts->iterateObjects(^bool (OSObject * obj) { 1467 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1468 if (!thisKext) { 1469 return false; 1470 } 1471 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1472 return false; 1473 }); 1474 1475 /* Finally, put back the kept kexts if we saved any. 1476 */ 1477 keepKexts->iterateObjects(^bool (OSObject * obj) { 1478 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1479 if (!thisKext) { 1480 return false; 1481 } 1482 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1483 return false; 1484 }); 1485 1486 finish: 1487 IORecursiveLockUnlock(sKextLock); 1488 return; 1489 } 1490 #else /* !CONFIG_KXLD */ 1491 1492 void 1493 OSKext::flushNonloadedKexts( 1494 Boolean flushPrelinkedKexts __unused) 1495 { 1496 IORecursiveLockLock(sKextLock); 1497 1498 OSKextLog(/* kext */ NULL, 1499 kOSKextLogProgressLevel | 1500 kOSKextLogKextBookkeepingFlag, 1501 "Flushing dependency info for non-loaded kexts."); 1502 1503 /* 1504 * In a world where we don't dynamically link kexts, they all come 1505 * from a kext collection that's either in wired memory, or 1506 * wire-on-demand. We don't need to mess around with moving kexts in 1507 * and out of the sKextsByID array - they can all just stay there. 1508 * Here we just flush the dependency list for kexts that are not 1509 * loaded. 1510 */ 1511 sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) { 1512 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1513 if (!thisKext) { 1514 return false; 1515 } 1516 thisKext->flushDependencies(/* forceIfLoaded */ false); 1517 return false; 1518 }); 1519 1520 IORecursiveLockUnlock(sKextLock); 1521 return; 1522 } 1523 1524 #endif /* CONFIG_KXLD */ 1525 1526 /********************************************************************* 1527 *********************************************************************/ 1528 /* static */ 1529 void 1530 OSKext::setIOKitDaemonActive(bool active) 1531 { 1532 IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0); 1533 IORecursiveLockLock(sKextLock); 1534 sIOKitDaemonActive = active; 1535 if (sKernelRequests->getCount()) { 1536 OSKext::pingIOKitDaemon(); 1537 } 1538 IORecursiveLockUnlock(sKextLock); 1539 1540 return; 1541 } 1542 1543 /********************************************************************* 1544 * OSKextLib.cpp might need access to this someday but for now it's 1545 * private. 1546 *********************************************************************/ 1547 extern "C" { 1548 extern void ipc_port_release_send(ipc_port_t); 1549 }; 1550 1551 /* static */ 1552 OSReturn 1553 OSKext::pingIOKitDaemon(void) 1554 { 1555 OSReturn result = kOSReturnError; 1556 #if !NO_KEXTD 1557 mach_port_t kextd_port = IPC_PORT_NULL; 1558 1559 if (!sIOKitDaemonActive) { 1560 result = kOSKextReturnDisabled; // basically unavailable 1561 goto finish; 1562 } 1563 1564 result = host_get_kextd_port(host_priv_self(), &kextd_port); 1565 if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) { 1566 OSKextLog(/* kext */ NULL, 1567 kOSKextLogErrorLevel | 1568 kOSKextLogIPCFlag, 1569 "Can't get " kIOKitDaemonName " port."); 1570 goto finish; 1571 } 1572 1573 result = kextd_ping(kextd_port); 1574 if (result != KERN_SUCCESS) { 1575 OSKextLog(/* kext */ NULL, 1576 kOSKextLogErrorLevel | 1577 kOSKextLogIPCFlag, 1578 kIOKitDaemonName " ping failed (0x%x).", (int)result); 1579 goto finish; 1580 } 1581 1582 finish: 1583 if (IPC_PORT_VALID(kextd_port)) { 1584 ipc_port_release_send(kextd_port); 1585 } 1586 #endif 1587 1588 return result; 1589 } 1590 1591 /********************************************************************* 1592 *********************************************************************/ 1593 /* static */ 1594 bool 1595 OSKext::driverkitEnabled(void) 1596 { 1597 #if XNU_TARGET_OS_WATCH 1598 return false; 1599 #else //!XNU_TARGET_OS_WATCH 1600 return true; 1601 #endif //XNU_TARGET_OS_WATCH 1602 } 1603 1604 /********************************************************************* 1605 *********************************************************************/ 1606 /* static */ 1607 bool 1608 OSKext::iokitDaemonAvailable(void) 1609 { 1610 #if !XNU_TARGET_OS_IOS && !XNU_TARGET_OS_OSX 1611 int notused; 1612 if (PE_parse_boot_argn("-restore", ¬used, sizeof(notused))) { 1613 return false; 1614 } 1615 #endif //!XNU_TARGET_OS_IOS && !XNU_TARGET_OS_OSX 1616 return driverkitEnabled(); 1617 } 1618 1619 /********************************************************************* 1620 *********************************************************************/ 1621 /* static */ 1622 void 1623 OSKext::setDeferredLoadSucceeded(Boolean succeeded) 1624 { 1625 IORecursiveLockLock(sKextLock); 1626 sDeferredLoadSucceeded = succeeded; 1627 IORecursiveLockUnlock(sKextLock); 1628 1629 return; 1630 } 1631 1632 /********************************************************************* 1633 * Called from IOSystemShutdownNotification. 1634 *********************************************************************/ 1635 /* static */ 1636 void 1637 OSKext::willShutdown(void) 1638 { 1639 #if !NO_KEXTD 1640 OSReturn checkResult = kOSReturnError; 1641 #endif 1642 OSSharedPtr<OSDictionary> exitRequest; 1643 1644 IORecursiveLockLock(sKextLock); 1645 1646 OSKext::setLoadEnabled(false); 1647 OSKext::setUnloadEnabled(false); 1648 OSKext::setAutounloadsEnabled(false); 1649 OSKext::setKernelRequestsEnabled(false); 1650 1651 #if defined(__x86_64__) || defined(__i386__) 1652 if (IOPMRootDomainGetWillShutdown()) { 1653 OSKext::freeKCFileSetcontrol(); 1654 } 1655 #endif // (__x86_64__) || defined(__i386__) 1656 1657 #if !NO_KEXTD 1658 OSKextLog(/* kext */ NULL, 1659 kOSKextLogProgressLevel | 1660 kOSKextLogGeneralFlag, 1661 "System shutdown; requesting immediate " kIOKitDaemonName " exit."); 1662 1663 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit, 1664 exitRequest); 1665 if (checkResult != kOSReturnSuccess) { 1666 goto finish; 1667 } 1668 if (!sKernelRequests->setObject(exitRequest.get())) { 1669 goto finish; 1670 } 1671 1672 OSKext::pingIOKitDaemon(); 1673 1674 finish: 1675 #endif 1676 1677 IORecursiveLockUnlock(sKextLock); 1678 return; 1679 } 1680 1681 void 1682 OSKext::willUserspaceReboot(void) 1683 { 1684 OSKext::willShutdown(); 1685 IOService::userSpaceWillReboot(); 1686 gIOCatalogue->terminateDriversForUserspaceReboot(); 1687 } 1688 1689 void 1690 OSKext::resetAfterUserspaceReboot(void) 1691 { 1692 OSSharedPtr<OSArray> arr = OSArray::withCapacity(1); 1693 IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */); 1694 1695 IORecursiveLockLock(sKextLock); 1696 gIOCatalogue->resetAfterUserspaceReboot(); 1697 IOService::userSpaceDidReboot(); 1698 OSKext::removeDaemonExitRequests(); 1699 OSKext::setLoadEnabled(true); 1700 OSKext::setUnloadEnabled(true); 1701 OSKext::setAutounloadsEnabled(true); 1702 OSKext::setKernelRequestsEnabled(true); 1703 sOSKextWasResetAfterUserspaceReboot = true; 1704 IORecursiveLockUnlock(sKextLock); 1705 } 1706 1707 extern "C" void 1708 OSKextResetAfterUserspaceReboot(void) 1709 { 1710 OSKext::resetAfterUserspaceReboot(); 1711 } 1712 1713 /* 1714 * Remove daemon exit requests from sKernelRequests 1715 * 1716 * If we sent a daemon exit request during a userspace reboot and launchd 1717 * killed the IOKit daemon before it was able to dequeue the exit request, the 1718 * next time the daemon starts up it will immediately exit as it gets the old exit request. 1719 * 1720 * This removes exit requests so that this does not happen. 1721 */ 1722 void 1723 OSKext::removeDaemonExitRequests(void) 1724 { 1725 OSDictionary * current = NULL; 1726 OSString * predicate = NULL; 1727 size_t index = 0; 1728 OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey); 1729 1730 while (index < sKernelRequests->getCount()) { 1731 current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index)); 1732 if (current) { 1733 predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get())); 1734 if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) { 1735 sKernelRequests->removeObject(index); 1736 continue; 1737 } 1738 } 1739 index++; 1740 } 1741 } 1742 1743 /********************************************************************* 1744 *********************************************************************/ 1745 /* static */ 1746 bool 1747 OSKext::getLoadEnabled(void) 1748 { 1749 bool result; 1750 1751 IORecursiveLockLock(sKextLock); 1752 result = sLoadEnabled; 1753 IORecursiveLockUnlock(sKextLock); 1754 return result; 1755 } 1756 1757 /********************************************************************* 1758 *********************************************************************/ 1759 /* static */ 1760 bool 1761 OSKext::setLoadEnabled(bool flag) 1762 { 1763 bool result; 1764 1765 IORecursiveLockLock(sKextLock); 1766 result = sLoadEnabled; 1767 sLoadEnabled = (flag ? true : false); 1768 1769 if (sLoadEnabled != result) { 1770 OSKextLog(/* kext */ NULL, 1771 kOSKextLogBasicLevel | 1772 kOSKextLogLoadFlag, 1773 "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis"); 1774 } 1775 1776 IORecursiveLockUnlock(sKextLock); 1777 1778 return result; 1779 } 1780 1781 /********************************************************************* 1782 *********************************************************************/ 1783 /* static */ 1784 bool 1785 OSKext::getUnloadEnabled(void) 1786 { 1787 bool result; 1788 1789 IORecursiveLockLock(sKextLock); 1790 result = sUnloadEnabled; 1791 IORecursiveLockUnlock(sKextLock); 1792 return result; 1793 } 1794 1795 /********************************************************************* 1796 *********************************************************************/ 1797 /* static */ 1798 bool 1799 OSKext::setUnloadEnabled(bool flag) 1800 { 1801 bool result; 1802 1803 IORecursiveLockLock(sKextLock); 1804 result = sUnloadEnabled; 1805 sUnloadEnabled = (flag ? true : false); 1806 IORecursiveLockUnlock(sKextLock); 1807 1808 if (sUnloadEnabled != result) { 1809 OSKextLog(/* kext */ NULL, 1810 kOSKextLogBasicLevel | 1811 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1812 "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis"); 1813 } 1814 1815 return result; 1816 } 1817 1818 /********************************************************************* 1819 * Do not call any function that takes sKextLock here! 1820 *********************************************************************/ 1821 /* static */ 1822 bool 1823 OSKext::getAutounloadEnabled(void) 1824 { 1825 #if XNU_TARGET_OS_OSX 1826 bool result; 1827 1828 IORecursiveLockLock(sKextInnerLock); 1829 result = sAutounloadEnabled ? true : false; 1830 IORecursiveLockUnlock(sKextInnerLock); 1831 return result; 1832 #else 1833 return false; 1834 #endif /* XNU_TARGET_OS_OSX */ 1835 } 1836 1837 /********************************************************************* 1838 * Do not call any function that takes sKextLock here! 1839 *********************************************************************/ 1840 /* static */ 1841 bool 1842 OSKext::setAutounloadsEnabled(bool flag) 1843 { 1844 #if XNU_TARGET_OS_OSX 1845 bool result; 1846 1847 IORecursiveLockLock(sKextInnerLock); 1848 1849 result = sAutounloadEnabled; 1850 sAutounloadEnabled = (flag ? true : false); 1851 if (!sAutounloadEnabled && sUnloadCallout) { 1852 thread_call_cancel(sUnloadCallout); 1853 } 1854 1855 if (sAutounloadEnabled != result) { 1856 OSKextLog(/* kext */ NULL, 1857 kOSKextLogBasicLevel | 1858 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1859 "Kext autounloading now %sabled.", 1860 sAutounloadEnabled ? "en" : "dis"); 1861 } 1862 1863 IORecursiveLockUnlock(sKextInnerLock); 1864 1865 return result; 1866 #else 1867 (void)flag; 1868 return false; 1869 #endif /* XNU_TARGET_OS_OSX */ 1870 } 1871 1872 /********************************************************************* 1873 *********************************************************************/ 1874 /* instance method operating on OSKext field */ 1875 bool 1876 OSKext::setAutounloadEnabled(bool flag) 1877 { 1878 bool result = flags.autounloadEnabled ? true : false; 1879 flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0; 1880 1881 if (result != (flag ? true : false)) { 1882 OSKextLog(this, 1883 kOSKextLogProgressLevel | 1884 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 1885 "Autounloading for kext %s now %sabled.", 1886 getIdentifierCString(), 1887 flags.autounloadEnabled ? "en" : "dis"); 1888 } 1889 return result; 1890 } 1891 1892 /********************************************************************* 1893 *********************************************************************/ 1894 /* static */ 1895 bool 1896 OSKext::setKernelRequestsEnabled(bool flag) 1897 { 1898 bool result; 1899 1900 IORecursiveLockLock(sKextLock); 1901 result = sKernelRequestsEnabled; 1902 sKernelRequestsEnabled = flag ? true : false; 1903 1904 if (sKernelRequestsEnabled != result) { 1905 OSKextLog(/* kext */ NULL, 1906 kOSKextLogBasicLevel | 1907 kOSKextLogGeneralFlag, 1908 "Kernel requests now %sabled.", 1909 sKernelRequestsEnabled ? "en" : "dis"); 1910 } 1911 IORecursiveLockUnlock(sKextLock); 1912 return result; 1913 } 1914 1915 /********************************************************************* 1916 *********************************************************************/ 1917 /* static */ 1918 bool 1919 OSKext::getKernelRequestsEnabled(void) 1920 { 1921 bool result; 1922 1923 IORecursiveLockLock(sKextLock); 1924 result = sKernelRequestsEnabled; 1925 IORecursiveLockUnlock(sKextLock); 1926 return result; 1927 } 1928 1929 static bool 1930 segmentIsMutable(kernel_segment_command_t *seg) 1931 { 1932 /* Mutable segments have to have VM_PROT_WRITE */ 1933 if ((seg->maxprot & VM_PROT_WRITE) == 0) { 1934 return false; 1935 } 1936 /* Exclude the __DATA_CONST segment */ 1937 if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) { 1938 return false; 1939 } 1940 /* Exclude __LINKEDIT */ 1941 if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) { 1942 return false; 1943 } 1944 return true; 1945 } 1946 1947 #if PRAGMA_MARK 1948 #pragma mark Kext Life Cycle 1949 #endif 1950 /********************************************************************* 1951 *********************************************************************/ 1952 OSSharedPtr<OSKext> 1953 OSKext::withPrelinkedInfoDict( 1954 OSDictionary * anInfoDict, 1955 bool doCoalescedSlides, 1956 kc_kind_t type) 1957 { 1958 OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>()); 1959 1960 if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) { 1961 return NULL; 1962 } 1963 1964 return newKext; 1965 } 1966 1967 OSData * 1968 OSKext::parseDextUniqueID( 1969 OSDictionary * anInfoDict, 1970 const char *dextIDCS) 1971 { 1972 OSData *ret = NULL; 1973 OSData *data_duid = OSDynamicCast(OSData, anInfoDict->getObject(kOSBundleDextUniqueIdentifierKey)); 1974 if (data_duid != NULL) { 1975 if (data_duid->getLength() > KOSBundleDextUniqueIdentifierMaxLength) { 1976 OSKextLog(NULL, 1977 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 1978 "Dext %s DextUniqueIdentifier too long.", 1979 dextIDCS); 1980 } else { 1981 /* 1982 * If the DextUniqueID exists it should be 1983 * present also into the personalities. 1984 */ 1985 setDextUniqueIDInPersonalities(anInfoDict, data_duid); 1986 ret = data_duid; 1987 } 1988 } else { 1989 OSKextLog(NULL, 1990 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 1991 "Dext %s does not have a DextUniqueIdentifier", 1992 dextIDCS); 1993 } 1994 return ret; 1995 } 1996 1997 void 1998 OSKext::setDextUniqueIDInPersonalities( 1999 OSDictionary * anInfoDict, 2000 OSData * dextUniqueID) 2001 { 2002 OSDictionary * dextPersonalities = NULL; 2003 OSSharedPtr<OSCollectionIterator> personalitiesIterator; 2004 OSString * personalityName = NULL; 2005 2006 dextPersonalities = OSDynamicCast(OSDictionary, 2007 anInfoDict->getObject(kIOKitPersonalitiesKey)); 2008 if (!dextPersonalities || !dextPersonalities->getCount()) { 2009 return; 2010 } 2011 2012 personalitiesIterator = 2013 OSCollectionIterator::withCollection(dextPersonalities); 2014 if (!personalitiesIterator) { 2015 return; 2016 } 2017 while ((personalityName = OSDynamicCast(OSString, 2018 personalitiesIterator->getNextObject()))) { 2019 OSDictionary * personality = OSDynamicCast(OSDictionary, 2020 dextPersonalities->getObject(personalityName)); 2021 if (personality) { 2022 OSObject *duid = personality->getObject(kOSBundleDextUniqueIdentifierKey); 2023 if (duid == NULL) { 2024 personality->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID); 2025 } 2026 } 2027 } 2028 } 2029 /********************************************************************* 2030 *********************************************************************/ 2031 bool 2032 OSKext::initWithPrelinkedInfoDict( 2033 OSDictionary * anInfoDict, 2034 bool doCoalescedSlides, 2035 kc_kind_t type) 2036 { 2037 bool result = false; 2038 OSString * kextPath = NULL; // do not release 2039 OSNumber * addressNum = NULL; // reused; do not release 2040 OSNumber * lengthNum = NULL; // reused; do not release 2041 OSBoolean * scratchBool = NULL; // do not release 2042 void * data = NULL; // do not free 2043 void * srcData = NULL; // do not free 2044 OSSharedPtr<OSData> prelinkedExecutable; 2045 uint32_t length = 0; // reused 2046 uintptr_t kext_slide = PE_get_kc_slide(type); 2047 bool shouldSaveSegments = false; 2048 kc_format format = KCFormatUnknown; 2049 2050 if (!super::init()) { 2051 goto finish; 2052 } 2053 2054 /* Get the path. Don't look for an arch-specific path property. 2055 */ 2056 kextPath = OSDynamicCast(OSString, 2057 anInfoDict->getObject(kPrelinkBundlePathKey)); 2058 2059 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 2060 goto finish; 2061 } 2062 2063 #if KASLR_KEXT_DEBUG 2064 IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString()); 2065 #endif 2066 2067 /* Also get the executable's bundle-relative path if present. 2068 * Don't look for an arch-specific path property. 2069 */ 2070 executableRelPath.reset(OSDynamicCast(OSString, 2071 anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain); 2072 userExecutableRelPath.reset(OSDynamicCast(OSString, 2073 anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain); 2074 2075 /* Don't need the paths to be in the info dictionary any more. 2076 */ 2077 anInfoDict->removeObject(kPrelinkBundlePathKey); 2078 anInfoDict->removeObject(kPrelinkExecutableRelativePathKey); 2079 2080 scratchBool = OSDynamicCast(OSBoolean, 2081 getPropertyForHostArch(kOSBundleRequireExplicitLoadKey)); 2082 if (scratchBool == kOSBooleanTrue) { 2083 flags.requireExplicitLoad = 1; 2084 } 2085 2086 /* Create an OSData wrapper around the linked executable. 2087 */ 2088 addressNum = OSDynamicCast(OSNumber, 2089 anInfoDict->getObject(kPrelinkExecutableLoadKey)); 2090 if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) { 2091 lengthNum = OSDynamicCast(OSNumber, 2092 anInfoDict->getObject(kPrelinkExecutableSizeKey)); 2093 if (!lengthNum) { 2094 OSKextLog(this, 2095 kOSKextLogErrorLevel | 2096 kOSKextLogArchiveFlag, 2097 "Kext %s can't find prelinked kext executable size.", 2098 getIdentifierCString()); 2099 return result; 2100 } 2101 2102 data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 2103 length = (uint32_t) (lengthNum->unsigned32BitValue()); 2104 2105 #if KASLR_KEXT_DEBUG 2106 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n", 2107 (unsigned long)ml_static_unslide((vm_offset_t)data), 2108 (unsigned long)data, 2109 length); 2110 #endif 2111 2112 anInfoDict->removeObject(kPrelinkExecutableLoadKey); 2113 anInfoDict->removeObject(kPrelinkExecutableSizeKey); 2114 2115 /* If the kext's load address differs from its source address, allocate 2116 * space in the kext map at the load address and copy the kext over. 2117 */ 2118 addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey)); 2119 if (addressNum) { 2120 srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 2121 2122 #if KASLR_KEXT_DEBUG 2123 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n", 2124 (unsigned long)ml_static_unslide((vm_offset_t)srcData), 2125 (unsigned long)srcData); 2126 #endif 2127 2128 if (data != srcData) { 2129 #if __LP64__ 2130 kern_return_t alloc_result; 2131 2132 alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE); 2133 if (alloc_result != KERN_SUCCESS) { 2134 OSKextLog(this, 2135 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 2136 "Failed to allocate space for prelinked kext %s.", 2137 getIdentifierCString()); 2138 goto finish; 2139 } 2140 memcpy(data, srcData, length); 2141 #else 2142 OSKextLog(this, 2143 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 2144 "Error: prelinked kext %s - source and load addresses " 2145 "differ on ILP32 architecture.", 2146 getIdentifierCString()); 2147 goto finish; 2148 #endif /* __LP64__ */ 2149 } 2150 2151 anInfoDict->removeObject(kPrelinkExecutableSourceKey); 2152 } 2153 2154 prelinkedExecutable = OSData::withBytesNoCopy(data, length); 2155 if (!prelinkedExecutable) { 2156 OSKextLog(this, 2157 kOSKextLogErrorLevel | 2158 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 2159 "Kext %s failed to create executable wrapper.", 2160 getIdentifierCString()); 2161 goto finish; 2162 } 2163 2164 /* 2165 * Fileset KCs are mapped as a whole by iBoot. 2166 * Individual kext executables should not be unmapped 2167 * by xnu. 2168 * Doing so may result in panics like rdar://85419651 2169 */ 2170 if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) { 2171 prelinkedExecutable->setDeallocFunction(NULL); 2172 } else { // Not from a Fileset KC 2173 #if VM_MAPPED_KEXTS 2174 prelinkedExecutable->setDeallocFunction(osdata_kext_free); 2175 #else 2176 prelinkedExecutable->setDeallocFunction(osdata_phys_free); 2177 #endif 2178 } 2179 setLinkedExecutable(prelinkedExecutable.get()); 2180 addressNum = OSDynamicCast(OSNumber, 2181 anInfoDict->getObject(kPrelinkKmodInfoKey)); 2182 if (!addressNum) { 2183 OSKextLog(this, 2184 kOSKextLogErrorLevel | 2185 kOSKextLogArchiveFlag, 2186 "Kext %s can't find prelinked kext kmod_info address.", 2187 getIdentifierCString()); 2188 goto finish; 2189 } 2190 2191 if (addressNum->unsigned64BitValue() != 0) { 2192 kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 2193 if (kmod_info->address) { 2194 kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide); 2195 } else { 2196 kmod_info->address = (uintptr_t)data; 2197 kmod_info->size = length; 2198 } 2199 #if KASLR_KEXT_DEBUG 2200 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n", 2201 (unsigned long)((vm_offset_t)kmod_info) - kext_slide, 2202 (unsigned long)kmod_info); 2203 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n", 2204 (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide, 2205 (unsigned long)kmod_info->address); 2206 #endif 2207 } 2208 2209 anInfoDict->removeObject(kPrelinkKmodInfoKey); 2210 } 2211 2212 if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) { 2213 uintptr_t builtinTextStart; 2214 uintptr_t builtinTextEnd; 2215 2216 flags.builtin = true; 2217 builtinKmodIdx = addressNum->unsigned32BitValue(); 2218 assert(builtinKmodIdx < gBuiltinKmodsCount); 2219 2220 builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx]; 2221 builtinTextEnd = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1]; 2222 2223 kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx]; 2224 kmod_info->address = builtinTextStart; 2225 kmod_info->size = builtinTextEnd - builtinTextStart; 2226 } 2227 2228 /* If the plist has a UUID for an interface, save that off. 2229 */ 2230 if (isInterface()) { 2231 interfaceUUID.reset(OSDynamicCast(OSData, 2232 anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain); 2233 if (interfaceUUID) { 2234 anInfoDict->removeObject(kPrelinkInterfaceUUIDKey); 2235 } 2236 } 2237 2238 result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides)); 2239 if (!result) { 2240 goto finish; 2241 } 2242 2243 kc_type = type; 2244 /* Exclude builtin and codeless kexts */ 2245 if (prelinkedExecutable && kmod_info) { 2246 switch (kc_type) { 2247 case KCKindPrimary: 2248 shouldSaveSegments = ( 2249 getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue || 2250 getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue); 2251 if (shouldSaveSegments) { 2252 flags.resetSegmentsFromImmutableCopy = 1; 2253 } else { 2254 flags.unloadUnsupported = 1; 2255 } 2256 break; 2257 case KCKindPageable: 2258 flags.resetSegmentsFromVnode = 1; 2259 break; 2260 case KCKindAuxiliary: 2261 if (!pageableKCloaded) { 2262 flags.resetSegmentsFromImmutableCopy = 1; 2263 } else if (resetAuxKCSegmentOnUnload) { 2264 flags.resetSegmentsFromVnode = 1; 2265 } else { 2266 flags.unloadUnsupported = 1; 2267 } 2268 break; 2269 default: 2270 break; 2271 } 2272 } 2273 2274 if (flags.resetSegmentsFromImmutableCopy) { 2275 /* Save a pristine copy of the mutable segments */ 2276 kernel_segment_command_t *seg = NULL; 2277 kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address; 2278 2279 savedMutableSegments = OSArray::withCapacity(0); 2280 2281 for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) { 2282 if (!segmentIsMutable(seg)) { 2283 continue; 2284 } 2285 uint64_t unslid_vmaddr = seg->vmaddr - kext_slide; 2286 uint64_t vmsize = seg->vmsize; 2287 OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2288 "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1); 2289 OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg); 2290 if (!savedSegment) { 2291 OSKextLog(this, 2292 kOSKextLogErrorLevel | 2293 kOSKextLogGeneralFlag, 2294 "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 2295 result = false; 2296 goto finish; 2297 } 2298 savedMutableSegments->setObject(savedSegment); 2299 } 2300 } 2301 2302 if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) { 2303 /* 2304 * set VM protections now, wire pages for the old style Aux KC now, 2305 * wire pages for the rest of the KC types at load time. 2306 */ 2307 result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false)); 2308 if (!result) { 2309 goto finish; 2310 } 2311 } 2312 2313 flags.prelinked = true; 2314 2315 if (isDriverKit()) { 2316 dextStatistics = OSDextStatistics::create(); 2317 dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain); 2318 dextLaunchedCount = 0; 2319 } 2320 2321 /* If we created a kext from prelink info, 2322 * we must be booting from a prelinked kernel. 2323 */ 2324 sPrelinkBoot = true; 2325 2326 result = (registerIdentifier() == kOSKextInitialized); 2327 finish: 2328 return result; 2329 } 2330 2331 /********************************************************************* 2332 *********************************************************************/ 2333 /* static */ 2334 OSSharedPtr<OSKext> 2335 OSKext::withCodelessInfo(OSDictionary * anInfoDict, OSKextInitResult *result) 2336 { 2337 OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>(); 2338 if (!newKext) { 2339 return NULL; 2340 } 2341 2342 OSKextInitResult ret = newKext->initWithCodelessInfo(anInfoDict); 2343 if (result != NULL) { 2344 *result = ret; 2345 } 2346 if (ret != kOSKextInitialized) { 2347 return NULL; 2348 } 2349 2350 return newKext; 2351 } 2352 2353 /********************************************************************* 2354 *********************************************************************/ 2355 OSKextInitResult 2356 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict) 2357 { 2358 OSKextInitResult result = kOSKextInitFailure; 2359 OSString * kextPath = NULL; // do not release 2360 OSBoolean * scratchBool = NULL; // do not release 2361 2362 if (anInfoDict == NULL || !super::init()) { 2363 goto finish; 2364 } 2365 2366 /* 2367 * Get the path. Don't look for an arch-specific path property. 2368 */ 2369 kextPath = OSDynamicCast(OSString, 2370 anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey)); 2371 if (!kextPath) { 2372 OSKextLog(NULL, 2373 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 2374 "Requested codeless kext dictionary does not contain the '%s' key", 2375 kKextRequestArgumentCodelessInfoBundlePathKey); 2376 goto finish; 2377 } 2378 2379 uniquePersonalityProperties(anInfoDict); 2380 2381 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 2382 goto finish; 2383 } 2384 2385 /* 2386 * This path is meant to initialize codeless kexts only. Refuse 2387 * anything that looks like it has an executable and/or declares 2388 * itself as a kernel component. 2389 */ 2390 if (declaresExecutable() || isKernelComponent()) { 2391 OSKextLog(NULL, 2392 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 2393 "Refusing to register codeless kext that declares an executable/kernel component: %s", 2394 getIdentifierCString()); 2395 goto finish; 2396 } 2397 2398 if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) { 2399 boolean_t updated = updateExcludeList(infoDict.get()); 2400 if (updated) { 2401 OSKextLog(this, 2402 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2403 "KextExcludeList was updated to version: %lld", sExcludeListVersion); 2404 } 2405 } 2406 2407 kc_type = KCKindNone; 2408 2409 scratchBool = OSDynamicCast(OSBoolean, 2410 getPropertyForHostArch(kOSBundleRequireExplicitLoadKey)); 2411 if (scratchBool == kOSBooleanTrue) { 2412 flags.requireExplicitLoad = 1; 2413 } 2414 2415 /* Also get the executable's bundle-relative path if present. 2416 * Don't look for an arch-specific path property. 2417 */ 2418 userExecutableRelPath.reset(OSDynamicCast(OSString, 2419 anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain); 2420 2421 /* remove unnecessary paths from the info dict */ 2422 anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey); 2423 2424 if (isDriverKit()) { 2425 dextStatistics = OSDextStatistics::create(); 2426 dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain); 2427 dextLaunchedCount = 0; 2428 } 2429 2430 result = registerIdentifier(); 2431 2432 finish: 2433 return result; 2434 } 2435 2436 /********************************************************************* 2437 *********************************************************************/ 2438 /* static */ 2439 void 2440 OSKext::setAllVMAttributes(void) 2441 { 2442 OSSharedPtr<OSCollectionIterator> kextIterator; 2443 const OSSymbol * thisID = NULL; // do not release 2444 2445 IORecursiveLockLock(sKextLock); 2446 2447 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 2448 if (!kextIterator) { 2449 goto finish; 2450 } 2451 2452 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 2453 OSKext * thisKext; // do not release 2454 2455 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 2456 if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) { 2457 continue; 2458 } 2459 2460 if (!thisKext->flags.resetSegmentsFromVnode) { 2461 /* 2462 * set VM protections now, wire pages for the old style Aux KC now, 2463 * wire pages for the rest of the KC types at load time. 2464 */ 2465 thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false); 2466 } 2467 } 2468 2469 finish: 2470 IORecursiveLockUnlock(sKextLock); 2471 2472 return; 2473 } 2474 2475 /********************************************************************* 2476 *********************************************************************/ 2477 OSSharedPtr<OSKext> 2478 OSKext::withBooterData( 2479 OSString * deviceTreeName, 2480 OSData * booterData) 2481 { 2482 OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>()); 2483 2484 if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) { 2485 return NULL; 2486 } 2487 2488 return newKext; 2489 } 2490 2491 /********************************************************************* 2492 *********************************************************************/ 2493 typedef struct _BooterKextFileInfo { 2494 uint32_t infoDictPhysAddr; 2495 uint32_t infoDictLength; 2496 uint32_t executablePhysAddr; 2497 uint32_t executableLength; 2498 uint32_t bundlePathPhysAddr; 2499 uint32_t bundlePathLength; 2500 } _BooterKextFileInfo; 2501 2502 bool 2503 OSKext::initWithBooterData( 2504 OSString * deviceTreeName, 2505 OSData * booterData) 2506 { 2507 bool result = false; 2508 _BooterKextFileInfo * kextFileInfo = NULL; // do not free 2509 char * infoDictAddr = NULL; // do not free 2510 void * executableAddr = NULL; // do not free 2511 char * bundlePathAddr = NULL; // do not free 2512 2513 OSDictionary * theInfoDict = NULL; // do not release 2514 OSSharedPtr<OSObject> parsedXML; 2515 OSSharedPtr<OSString> kextPath; 2516 2517 OSSharedPtr<OSString> errorString; 2518 OSSharedPtr<OSData> executable; 2519 2520 if (!super::init()) { 2521 goto finish; 2522 } 2523 2524 kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy(); 2525 if (!kextFileInfo) { 2526 OSKextLog(this, 2527 kOSKextLogErrorLevel | 2528 kOSKextLogGeneralFlag, 2529 "No booter-provided data for kext device tree entry %s.", 2530 deviceTreeName->getCStringNoCopy()); 2531 goto finish; 2532 } 2533 2534 /* The info plist must exist or we can't read the kext. 2535 */ 2536 if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) { 2537 OSKextLog(this, 2538 kOSKextLogErrorLevel | 2539 kOSKextLogGeneralFlag, 2540 "No kext info dictionary for booter device tree entry %s.", 2541 deviceTreeName->getCStringNoCopy()); 2542 goto finish; 2543 } 2544 2545 infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 2546 if (!infoDictAddr) { 2547 OSKextLog(this, 2548 kOSKextLogErrorLevel | 2549 kOSKextLogGeneralFlag, 2550 "Can't translate physical address 0x%x of kext info dictionary " 2551 "for device tree entry %s.", 2552 (int)kextFileInfo->infoDictPhysAddr, 2553 deviceTreeName->getCStringNoCopy()); 2554 goto finish; 2555 } 2556 2557 parsedXML = OSUnserializeXML(infoDictAddr, errorString); 2558 if (parsedXML) { 2559 theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 2560 } 2561 if (!theInfoDict) { 2562 const char * errorCString = "(unknown error)"; 2563 2564 if (errorString && errorString->getCStringNoCopy()) { 2565 errorCString = errorString->getCStringNoCopy(); 2566 } else if (parsedXML) { 2567 errorCString = "not a dictionary"; 2568 } 2569 OSKextLog(this, 2570 kOSKextLogErrorLevel | 2571 kOSKextLogGeneralFlag, 2572 "Error unserializing info dictionary for device tree entry %s: %s.", 2573 deviceTreeName->getCStringNoCopy(), errorCString); 2574 goto finish; 2575 } 2576 2577 /* A bundle path is not mandatory. 2578 */ 2579 if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) { 2580 bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr); 2581 if (!bundlePathAddr) { 2582 OSKextLog(this, 2583 kOSKextLogErrorLevel | 2584 kOSKextLogGeneralFlag, 2585 "Can't translate physical address 0x%x of kext bundle path " 2586 "for device tree entry %s.", 2587 (int)kextFileInfo->bundlePathPhysAddr, 2588 deviceTreeName->getCStringNoCopy()); 2589 goto finish; 2590 } 2591 bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0'; // just in case! 2592 2593 kextPath = OSString::withCString(bundlePathAddr); 2594 if (!kextPath) { 2595 OSKextLog(this, 2596 kOSKextLogErrorLevel | 2597 kOSKextLogGeneralFlag, 2598 "Failed to create wrapper for device tree entry %s kext path %s.", 2599 deviceTreeName->getCStringNoCopy(), bundlePathAddr); 2600 goto finish; 2601 } 2602 } 2603 2604 if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) { 2605 goto finish; 2606 } 2607 2608 /* An executable is not mandatory. 2609 */ 2610 if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) { 2611 executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr); 2612 if (!executableAddr) { 2613 OSKextLog(this, 2614 kOSKextLogErrorLevel | 2615 kOSKextLogGeneralFlag, 2616 "Can't translate physical address 0x%x of kext executable " 2617 "for device tree entry %s.", 2618 (int)kextFileInfo->executablePhysAddr, 2619 deviceTreeName->getCStringNoCopy()); 2620 goto finish; 2621 } 2622 2623 executable = OSData::withBytesNoCopy(executableAddr, 2624 kextFileInfo->executableLength); 2625 if (!executable) { 2626 OSKextLog(this, 2627 kOSKextLogErrorLevel | 2628 kOSKextLogGeneralFlag, 2629 "Failed to create executable wrapper for device tree entry %s.", 2630 deviceTreeName->getCStringNoCopy()); 2631 goto finish; 2632 } 2633 2634 /* A kext with an executable needs to retain the whole booterData 2635 * object to keep the executable in memory. 2636 */ 2637 if (!setExecutable(executable.get(), booterData)) { 2638 OSKextLog(this, 2639 kOSKextLogErrorLevel | 2640 kOSKextLogGeneralFlag, 2641 "Failed to set kext executable for device tree entry %s.", 2642 deviceTreeName->getCStringNoCopy()); 2643 goto finish; 2644 } 2645 } 2646 2647 if (isDriverKit()) { 2648 dextStatistics = OSDextStatistics::create(); 2649 dextUniqueID.reset(parseDextUniqueID(theInfoDict, getIdentifierCString()), OSRetain); 2650 dextLaunchedCount = 0; 2651 } 2652 2653 result = (registerIdentifier() == kOSKextInitialized); 2654 2655 finish: 2656 return result; 2657 } 2658 2659 /********************************************************************* 2660 *********************************************************************/ 2661 OSKextInitResult 2662 OSKext::registerIdentifier(void) 2663 { 2664 OSKextInitResult result = kOSKextInitFailure; 2665 OSKext * existingKext = NULL; // do not release 2666 bool existingIsLoaded = false; 2667 bool existingIsPrelinked = false; 2668 bool existingIsCodeless = false; 2669 bool existingIsDext = false; 2670 OSKextVersion newVersion = -1; 2671 OSKextVersion existingVersion = -1; 2672 char newVersionCString[kOSKextVersionMaxLength]; 2673 char existingVersionCString[kOSKextVersionMaxLength]; 2674 OSSharedPtr<OSData> newUUID; 2675 OSSharedPtr<OSData> existingUUID; 2676 const char *newDextUniqueIDCString = NULL; 2677 const char *existingDextUniqueIDCString = NULL; 2678 unsigned int newDextUniqueIDCStringSize = 0; 2679 unsigned int existingDextUniqueIDCStringSize = 0; 2680 2681 IORecursiveLockLock(sKextLock); 2682 2683 /* Get the new kext's version for checks & log messages. 2684 */ 2685 newVersion = getVersion(); 2686 OSKextVersionGetString(newVersion, newVersionCString, 2687 kOSKextVersionMaxLength); 2688 2689 /* If we don't have an existing kext with this identifier, 2690 * just record the new kext and we're done! 2691 */ 2692 existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get())); 2693 if (!existingKext) { 2694 sKextsByID->setObject(bundleID.get(), this); 2695 result = kOSKextInitialized; 2696 goto finish; 2697 } 2698 2699 /* Get the existing kext's version for checks & log messages. 2700 */ 2701 existingVersion = existingKext->getVersion(); 2702 OSKextVersionGetString(existingVersion, 2703 existingVersionCString, kOSKextVersionMaxLength); 2704 2705 existingIsLoaded = existingKext->isLoaded(); 2706 existingIsPrelinked = existingKext->isPrelinked(); 2707 existingIsDext = existingKext->isDriverKit(); 2708 existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext; 2709 2710 /* 2711 * Check if we are trying to upgrade a dext 2712 * with another dext. 2713 */ 2714 if (isDriverKit() && existingIsDext) { 2715 OSData *newDextUID = getDextUniqueID(); 2716 if (!newDextUID) { 2717 OSKextLog(this, 2718 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2719 "New dext %s, v%s requested does not have a unique dext identifier\n", 2720 getIdentifierCString(), newVersionCString); 2721 goto finish; 2722 } 2723 newDextUniqueIDCString = getDextUniqueIDCString(newDextUID, &newDextUniqueIDCStringSize); 2724 assert(newDextUniqueIDCString != NULL); 2725 2726 OSData *existingDextUID = existingKext->getDextUniqueID(); 2727 if (!existingDextUID) { 2728 OSKextLog(this, 2729 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2730 "Found a dext %s, v%s: with no unique dext identifier\n", 2731 existingKext->getIdentifierCString(), existingVersionCString); 2732 goto finish; 2733 } 2734 existingDextUniqueIDCString = getDextUniqueIDCString(existingDextUID, &existingDextUniqueIDCStringSize); 2735 assert(existingDextUniqueIDCString != NULL); 2736 2737 /* 2738 * We might get multiple requests to save the same dext. 2739 * Check if we already have saved it or if this is an upgrade 2740 * for a dext with the same BundleID. 2741 * Dexts are uniquely identified by DextUniqueID, if a new DextUniqueID 2742 * is requested for a BundleID we are going to upgrade to the newest 2743 * received irrespective from the dext version. 2744 */ 2745 if (newDextUID->isEqualTo(existingDextUID) && existingKext->flags.dextToReplace == 0) { 2746 OSKextLog(this, 2747 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2748 "Refusing new dext %s, v%s:" 2749 "a dext v %s with the same unique dext identifier (%s) already exists\n", 2750 getIdentifierCString(), newVersionCString, 2751 existingVersionCString, newDextUniqueIDCString); 2752 result = kOSKextAlreadyExist; 2753 goto finish; 2754 } 2755 2756 bool upgraded = upgradeDext(existingKext, this); 2757 if (upgraded) { 2758 /* If the dext was upgraded existingKext might have been deallocated */ 2759 existingKext = NULL; 2760 OSKextLog(this, 2761 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2762 "Dext %s, v%s , unique dext identifier %s " 2763 "Upgraded to v%s, unique dext identifier %s \n", 2764 getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString, 2765 newVersionCString, newDextUniqueIDCString); 2766 result = kOSKextInitialized; 2767 } else { 2768 OSKextLog(this, 2769 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2770 "Upgrade delayed for %s v%s, unique dext identifier %s " 2771 "with v%s, unique dext identifier %s.\n", 2772 getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString, 2773 newVersionCString, newDextUniqueIDCString); 2774 result = kOSKextAlreadyExist; 2775 } 2776 2777 goto finish; 2778 } 2779 2780 /* If we have a non-codeless kext with this identifier that's already 2781 * loaded/prelinked, we can't use the new one, but let's be really 2782 * thorough and check how the two are related for a precise diagnostic 2783 * log message. 2784 * 2785 * This check is valid for kexts that declare an executable and for 2786 * dexts, but not for codeless kexts - we can just replace those. 2787 */ 2788 if ((!existingIsCodeless || existingIsDext) && 2789 (existingIsLoaded || existingIsPrelinked)) { 2790 bool sameVersion = (newVersion == existingVersion); 2791 bool sameExecutable = true; // assume true unless we have UUIDs 2792 2793 /* Only get the UUID if the existing kext is loaded. Doing so 2794 * might have to uncompress an mkext executable and we shouldn't 2795 * take that hit when neither kext is loaded. 2796 * 2797 * Note: there is no decompression that happens when all kexts 2798 * are loaded from kext collecitons. 2799 */ 2800 newUUID = copyUUID(); 2801 existingUUID = existingKext->copyUUID(); 2802 2803 if (existingIsDext && !isDriverKit()) { 2804 OSKextLog(this, 2805 kOSKextLogWarningLevel | 2806 kOSKextLogKextBookkeepingFlag, 2807 "Notice - new kext %s, v%s matches a %s dext" 2808 "with the same bundle ID, v%s.", 2809 getIdentifierCString(), newVersionCString, 2810 (existingIsLoaded ? "loaded" : "prelinked"), 2811 existingVersionCString); 2812 goto finish; 2813 } 2814 2815 /* I'm entirely too paranoid about checking equivalence of executables, 2816 * but I remember nasty problems with it in the past. 2817 * 2818 * - If we have UUIDs for both kexts, compare them. 2819 * - If only one kext has a UUID, they're definitely different. 2820 */ 2821 if (newUUID && existingUUID) { 2822 sameExecutable = newUUID->isEqualTo(existingUUID.get()); 2823 } else if (newUUID || existingUUID) { 2824 sameExecutable = false; 2825 } 2826 2827 if (!newUUID && !existingUUID) { 2828 /* If there are no UUIDs, we can't really tell that the executables 2829 * are *different* without a lot of work; the loaded kext's 2830 * unrelocated executable is no longer around (and we never had it 2831 * in-kernel for a prelinked kext). We certainly don't want to do 2832 * a whole fake link for the new kext just to compare, either. 2833 */ 2834 OSKextLog(this, 2835 kOSKextLogWarningLevel | 2836 kOSKextLogKextBookkeepingFlag, 2837 "Notice - new kext %s, v%s matches %s kext " 2838 "but can't determine if executables are the same (no UUIDs).", 2839 getIdentifierCString(), 2840 newVersionCString, 2841 (existingIsLoaded ? "loaded" : "prelinked")); 2842 } 2843 2844 if (sameVersion && sameExecutable) { 2845 OSKextLog(this, 2846 (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) | 2847 kOSKextLogKextBookkeepingFlag, 2848 "Refusing new kext %s, v%s: a %s copy is already present " 2849 "(same version and executable).", 2850 getIdentifierCString(), newVersionCString, 2851 (existingIsLoaded ? "loaded" : "prelinked")); 2852 } else { 2853 if (!sameVersion) { 2854 /* This condition is significant so log it under warnings. 2855 */ 2856 OSKextLog(this, 2857 kOSKextLogWarningLevel | 2858 kOSKextLogKextBookkeepingFlag, 2859 "Refusing new kext %s, v%s: already have %s v%s.", 2860 getIdentifierCString(), 2861 newVersionCString, 2862 (existingIsLoaded ? "loaded" : "prelinked"), 2863 existingVersionCString); 2864 } else { 2865 /* This condition is significant so log it under warnings. 2866 */ 2867 OSKextLog(this, 2868 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 2869 "Refusing new kext %s, v%s: a %s copy with a different " 2870 "executable UUID is already present.", 2871 getIdentifierCString(), newVersionCString, 2872 (existingIsLoaded ? "loaded" : "prelinked")); 2873 } 2874 } 2875 goto finish; 2876 } /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */ 2877 2878 /* Refuse to allow an existing loaded codeless kext be replaced by a 2879 * normal kext with the same bundle ID. 2880 */ 2881 if (existingIsCodeless && declaresExecutable()) { 2882 OSKextLog(this, 2883 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 2884 "Refusing new kext %s, v%s: a codeless copy is already %s", 2885 getIdentifierCString(), newVersionCString, 2886 (existingIsLoaded ? "loaded" : "prelinked")); 2887 goto finish; 2888 } 2889 2890 /* Dexts packaged in the BootKC will be protected against replacement 2891 * by non-dexts by the logic above which checks if they are prelinked. 2892 * Dexts which are prelinked into the System KC will be registered 2893 * before any other kexts in the AuxKC are registered, and we never 2894 * put dexts in the AuxKC. Therefore, there is no need to check if an 2895 * existing object is a dext and is being replaced by a non-dext. 2896 * The scenario cannot happen by construction. 2897 * 2898 * See: OSKext::loadFileSetKexts() 2899 */ 2900 2901 2902 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether 2903 * user loads are happening or if we're still in early boot. User agents are 2904 * supposed to resolve dependencies topside and include only the exact 2905 * kexts needed; so we always accept the new kext (in fact we should never 2906 * see an older unloaded copy hanging around). 2907 */ 2908 if (sUserLoadsActive) { 2909 sKextsByID->setObject(bundleID.get(), this); 2910 result = kOSKextInitialized; 2911 2912 OSKextLog(this, 2913 kOSKextLogStepLevel | 2914 kOSKextLogKextBookkeepingFlag, 2915 "Dropping old copy of kext %s (v%s) for newly-added (v%s).", 2916 getIdentifierCString(), 2917 existingVersionCString, 2918 newVersionCString); 2919 2920 goto finish; 2921 } 2922 2923 /* During early boot, the kext with the highest version always wins out. 2924 * Prelinked kernels will never hit this, but mkexts and booter-read 2925 * kexts might have duplicates. 2926 */ 2927 if (newVersion > existingVersion) { 2928 sKextsByID->setObject(bundleID.get(), this); 2929 result = kOSKextInitialized; 2930 2931 OSKextLog(this, 2932 kOSKextLogStepLevel | 2933 kOSKextLogKextBookkeepingFlag, 2934 "Dropping lower version (v%s) of registered kext %s for higher (v%s).", 2935 existingVersionCString, 2936 getIdentifierCString(), 2937 newVersionCString); 2938 } else { 2939 OSKextLog(this, 2940 kOSKextLogStepLevel | 2941 kOSKextLogKextBookkeepingFlag, 2942 "Kext %s is already registered with a higher/same version (v%s); " 2943 "dropping newly-added (v%s).", 2944 getIdentifierCString(), 2945 existingVersionCString, 2946 newVersionCString); 2947 } 2948 2949 /* result has been set appropriately by now. */ 2950 2951 finish: 2952 2953 IORecursiveLockUnlock(sKextLock); 2954 2955 if (newDextUniqueIDCString != NULL) { 2956 kfree_data(newDextUniqueIDCString, newDextUniqueIDCStringSize); 2957 } 2958 if (existingDextUniqueIDCString != NULL) { 2959 kfree_data(existingDextUniqueIDCString, existingDextUniqueIDCStringSize); 2960 } 2961 2962 if (result == kOSKextInitialized) { 2963 OSKextLog(this, 2964 kOSKextLogStepLevel | 2965 kOSKextLogKextBookkeepingFlag, 2966 "Kext %s, v%s registered and available for loading.", 2967 getIdentifierCString(), newVersionCString); 2968 } 2969 2970 return result; 2971 } 2972 2973 /********************************************************************* 2974 * Does the bare minimum validation to look up a kext. 2975 * All other validation is done on the spot as needed. 2976 **********************************************************************/ 2977 bool 2978 OSKext::setInfoDictionaryAndPath( 2979 OSDictionary * aDictionary, 2980 OSString * aPath) 2981 { 2982 bool result = false; 2983 OSString * bundleIDString = NULL; // do not release 2984 OSString * versionString = NULL; // do not release 2985 OSString * compatibleVersionString = NULL; // do not release 2986 const char * versionCString = NULL; // do not free 2987 const char * compatibleVersionCString = NULL; // do not free 2988 OSBoolean * scratchBool = NULL; // do not release 2989 OSDictionary * scratchDict = NULL; // do not release 2990 2991 if (infoDict) { 2992 panic("Attempt to set info dictionary on a kext " 2993 "that already has one (%s).", 2994 getIdentifierCString()); 2995 } 2996 2997 if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) { 2998 goto finish; 2999 } 3000 3001 infoDict.reset(aDictionary, OSRetain); 3002 3003 /* Check right away if the info dictionary has any log flags. 3004 */ 3005 scratchBool = OSDynamicCast(OSBoolean, 3006 getPropertyForHostArch(kOSBundleEnableKextLoggingKey)); 3007 if (scratchBool == kOSBooleanTrue) { 3008 flags.loggingEnabled = 1; 3009 } 3010 3011 /* The very next thing to get is the bundle identifier. Unlike 3012 * in user space, a kext with no bundle identifier gets axed 3013 * immediately. 3014 */ 3015 bundleIDString = OSDynamicCast(OSString, 3016 getPropertyForHostArch(kCFBundleIdentifierKey)); 3017 if (!bundleIDString) { 3018 OSKextLog(this, 3019 kOSKextLogErrorLevel | 3020 kOSKextLogValidationFlag, 3021 "CFBundleIdentifier missing/invalid type in kext %s.", 3022 aPath ? aPath->getCStringNoCopy() : "(unknown)"); 3023 goto finish; 3024 } 3025 bundleID = OSSymbol::withString(bundleIDString); 3026 if (!bundleID) { 3027 OSKextLog(this, 3028 kOSKextLogErrorLevel | 3029 kOSKextLogValidationFlag, 3030 "Can't copy bundle identifier as symbol for kext %s.", 3031 bundleIDString->getCStringNoCopy()); 3032 goto finish; 3033 } 3034 3035 /* Save the path if we got one (it should always be available but it's 3036 * just something nice to have for bookkeeping). 3037 */ 3038 if (aPath) { 3039 path.reset(aPath, OSRetain); 3040 } 3041 3042 /***** 3043 * Minimal validation to initialize. We'll do other validation on the spot. 3044 */ 3045 if (bundleID->getLength() >= KMOD_MAX_NAME) { 3046 OSKextLog(this, 3047 kOSKextLogErrorLevel | 3048 kOSKextLogValidationFlag, 3049 "Kext %s error - CFBundleIdentifier over max length %d.", 3050 getIdentifierCString(), KMOD_MAX_NAME - 1); 3051 goto finish; 3052 } 3053 3054 version = compatibleVersion = -1; 3055 3056 versionString = OSDynamicCast(OSString, 3057 getPropertyForHostArch(kCFBundleVersionKey)); 3058 if (!versionString) { 3059 OSKextLog(this, 3060 kOSKextLogErrorLevel | 3061 kOSKextLogValidationFlag, 3062 "Kext %s error - CFBundleVersion missing/invalid type.", 3063 getIdentifierCString()); 3064 goto finish; 3065 } 3066 versionCString = versionString->getCStringNoCopy(); 3067 version = OSKextParseVersionString(versionCString); 3068 if (version < 0) { 3069 OSKextLog(this, 3070 kOSKextLogErrorLevel | 3071 kOSKextLogValidationFlag, 3072 "Kext %s error - CFBundleVersion bad value '%s'.", 3073 getIdentifierCString(), versionCString); 3074 goto finish; 3075 } 3076 3077 compatibleVersion = -1; // set to illegal value for kexts that don't have 3078 3079 compatibleVersionString = OSDynamicCast(OSString, 3080 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 3081 if (compatibleVersionString) { 3082 compatibleVersionCString = compatibleVersionString->getCStringNoCopy(); 3083 compatibleVersion = OSKextParseVersionString(compatibleVersionCString); 3084 if (compatibleVersion < 0) { 3085 OSKextLog(this, 3086 kOSKextLogErrorLevel | 3087 kOSKextLogValidationFlag, 3088 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.", 3089 getIdentifierCString(), compatibleVersionCString); 3090 goto finish; 3091 } 3092 3093 if (compatibleVersion > version) { 3094 OSKextLog(this, 3095 kOSKextLogErrorLevel | 3096 kOSKextLogValidationFlag, 3097 "Kext %s error - %s %s > %s %s (must be <=).", 3098 getIdentifierCString(), 3099 kOSBundleCompatibleVersionKey, compatibleVersionCString, 3100 kCFBundleVersionKey, versionCString); 3101 goto finish; 3102 } 3103 } 3104 3105 /* Check to see if this kext is in exclude list */ 3106 if (isInExcludeList()) { 3107 OSKextLog(this, 3108 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 3109 "Kext %s is in exclude list, not loadable", 3110 getIdentifierCString()); 3111 goto finish; 3112 } 3113 3114 /* Set flags for later use if the infoDict gets flushed. We only 3115 * check for true values, not false ones(!) 3116 */ 3117 scratchBool = OSDynamicCast(OSBoolean, 3118 getPropertyForHostArch(kOSBundleIsInterfaceKey)); 3119 if (scratchBool == kOSBooleanTrue) { 3120 flags.interface = 1; 3121 } 3122 3123 scratchBool = OSDynamicCast(OSBoolean, 3124 getPropertyForHostArch(kOSKernelResourceKey)); 3125 if (scratchBool == kOSBooleanTrue) { 3126 flags.kernelComponent = 1; 3127 flags.interface = 1; // xxx - hm. the kernel itself isn't an interface... 3128 flags.started = 1; 3129 3130 /* A kernel component has one implicit dependency on the kernel. 3131 */ 3132 flags.hasAllDependencies = 1; 3133 } 3134 3135 /* Make sure common string values in personalities are uniqued to OSSymbols. 3136 */ 3137 scratchDict = OSDynamicCast(OSDictionary, 3138 getPropertyForHostArch(kIOKitPersonalitiesKey)); 3139 if (scratchDict) { 3140 uniquePersonalityProperties(scratchDict); 3141 } 3142 3143 result = true; 3144 3145 finish: 3146 3147 return result; 3148 } 3149 3150 /********************************************************************* 3151 * Not used for prelinked kernel boot as there is no unrelocated 3152 * executable. 3153 *********************************************************************/ 3154 bool 3155 OSKext::setExecutable( 3156 OSData * anExecutable, 3157 OSData * externalData, 3158 bool externalDataIsMkext) 3159 { 3160 bool result = false; 3161 const char * executableKey = NULL; // do not free 3162 3163 if (!anExecutable) { 3164 infoDict->removeObject(_kOSKextExecutableKey); 3165 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 3166 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 3167 result = true; 3168 goto finish; 3169 } 3170 3171 if (infoDict->getObject(_kOSKextExecutableKey) || 3172 infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) { 3173 panic("Attempt to set an executable on a kext " 3174 "that already has one (%s).", 3175 getIdentifierCString()); 3176 goto finish; 3177 } 3178 3179 if (externalDataIsMkext) { 3180 executableKey = _kOSKextMkextExecutableReferenceKey; 3181 } else { 3182 executableKey = _kOSKextExecutableKey; 3183 } 3184 3185 if (anExecutable) { 3186 infoDict->setObject(executableKey, anExecutable); 3187 if (externalData) { 3188 infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData); 3189 } 3190 } 3191 3192 result = true; 3193 3194 finish: 3195 return result; 3196 } 3197 3198 /********************************************************************* 3199 *********************************************************************/ 3200 static void 3201 uniqueStringPlistProperty(OSDictionary * dict, const char * key) 3202 { 3203 OSObject * value = NULL; // do not release 3204 OSString * stringValue = NULL; // do not release 3205 OSSharedPtr<const OSSymbol> symbolValue; 3206 3207 value = dict->getObject(key); 3208 if (!value) { 3209 goto finish; 3210 } 3211 if (OSDynamicCast(OSSymbol, value)) { 3212 /* this is already an OSSymbol: we're good */ 3213 goto finish; 3214 } 3215 3216 stringValue = OSDynamicCast(OSString, value); 3217 if (!stringValue) { 3218 goto finish; 3219 } 3220 3221 symbolValue = OSSymbol::withString(stringValue); 3222 if (!symbolValue) { 3223 goto finish; 3224 } 3225 3226 dict->setObject(key, symbolValue.get()); 3227 3228 finish: 3229 return; 3230 } 3231 3232 /********************************************************************* 3233 *********************************************************************/ 3234 static void 3235 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key) 3236 { 3237 OSObject * value = NULL; // do not release 3238 OSString * stringValue = NULL; // do not release 3239 OSSharedPtr<const OSSymbol> symbolValue; 3240 3241 value = dict->getObject(key); 3242 if (!value) { 3243 goto finish; 3244 } 3245 if (OSDynamicCast(OSSymbol, value)) { 3246 /* this is already an OSSymbol: we're good */ 3247 goto finish; 3248 } 3249 3250 stringValue = OSDynamicCast(OSString, value); 3251 if (!stringValue) { 3252 goto finish; 3253 } 3254 3255 symbolValue = OSSymbol::withString(stringValue); 3256 if (!symbolValue) { 3257 goto finish; 3258 } 3259 3260 dict->setObject(key, symbolValue.get()); 3261 3262 finish: 3263 return; 3264 } 3265 3266 void 3267 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict) 3268 { 3269 OSKext::uniquePersonalityProperties(personalityDict, true); 3270 } 3271 3272 /********************************************************************* 3273 * Replace common personality property values with uniqued instances 3274 * to save on wired memory. 3275 *********************************************************************/ 3276 /* static */ 3277 void 3278 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier) 3279 { 3280 /* Properties every personality has. 3281 */ 3282 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey); 3283 uniqueStringPlistProperty(personalityDict, kIOProviderClassKey); 3284 uniqueStringPlistProperty(personalityDict, gIOClassKey.get()); 3285 if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) { 3286 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey); 3287 } else if (defaultAddKernelBundleIdentifier) { 3288 personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey)); 3289 } 3290 3291 /* Other commonly used properties. 3292 */ 3293 uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey); 3294 uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey); 3295 uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey); 3296 3297 uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior"); 3298 uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType"); 3299 uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType"); 3300 uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType"); 3301 uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher"); 3302 uniqueStringPlistProperty(personalityDict, "Physical Interconnect"); 3303 uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location"); 3304 uniqueStringPlistProperty(personalityDict, "Vendor"); 3305 uniqueStringPlistProperty(personalityDict, "Vendor Identification"); 3306 uniqueStringPlistProperty(personalityDict, "Vendor Name"); 3307 uniqueStringPlistProperty(personalityDict, "bConfigurationValue"); 3308 uniqueStringPlistProperty(personalityDict, "bInterfaceNumber"); 3309 uniqueStringPlistProperty(personalityDict, "idProduct"); 3310 3311 return; 3312 } 3313 3314 /********************************************************************* 3315 *********************************************************************/ 3316 void 3317 OSKext::free(void) 3318 { 3319 if (isLoaded()) { 3320 panic("Attempt to free loaded kext %s.", getIdentifierCString()); 3321 } 3322 3323 if (isDriverKit()) { 3324 if (dextLaunchedCount > 0) { 3325 panic("Freeing dext %s but dextLaunchedCount is %d\n", getIdentifierCString(), dextLaunchedCount); 3326 } 3327 } 3328 3329 infoDict.reset(); 3330 bundleID.reset(); 3331 path.reset(); 3332 executableRelPath.reset(); 3333 userExecutableRelPath.reset(); 3334 dependencies.reset(); 3335 linkedExecutable.reset(); 3336 metaClasses.reset(); 3337 interfaceUUID.reset(); 3338 driverKitUUID.reset(); 3339 dextStatistics.reset(); 3340 dextUniqueID.reset(); 3341 3342 if (isInterface() && kmod_info) { 3343 kfree_type(kmod_info_t, kmod_info); 3344 } 3345 3346 super::free(); 3347 return; 3348 } 3349 3350 #if PRAGMA_MARK 3351 #pragma mark Mkext files 3352 #endif 3353 3354 #if CONFIG_KXLD 3355 /* 3356 * mkext archives are really only relevant on kxld-enabled kernels. 3357 * Without a dynamic kernel linker, we don't need to support any mkexts. 3358 */ 3359 3360 /********************************************************************* 3361 *********************************************************************/ 3362 OSReturn 3363 OSKext::readMkextArchive(OSData * mkextData, 3364 uint32_t * checksumPtr) 3365 { 3366 OSReturn result = kOSKextReturnBadData; 3367 uint32_t mkextLength = 0; 3368 mkext_header * mkextHeader = NULL; // do not free 3369 uint32_t mkextVersion = 0; 3370 3371 /* Note default return of kOSKextReturnBadData above. 3372 */ 3373 mkextLength = mkextData->getLength(); 3374 if (mkextLength < sizeof(mkext_basic_header)) { 3375 OSKextLog(/* kext */ NULL, 3376 kOSKextLogErrorLevel | 3377 kOSKextLogArchiveFlag, 3378 "Mkext archive too small to be valid."); 3379 goto finish; 3380 } 3381 3382 mkextHeader = (mkext_header *)mkextData->getBytesNoCopy(); 3383 3384 if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC || 3385 MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) { 3386 OSKextLog(/* kext */ NULL, 3387 kOSKextLogErrorLevel | 3388 kOSKextLogArchiveFlag, 3389 "Mkext archive has invalid magic or signature."); 3390 goto finish; 3391 } 3392 3393 if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) { 3394 OSKextLog(/* kext */ NULL, 3395 kOSKextLogErrorLevel | 3396 kOSKextLogArchiveFlag, 3397 "Mkext archive recorded length doesn't match actual file length."); 3398 goto finish; 3399 } 3400 3401 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 3402 3403 if (mkextVersion == MKEXT_VERS_2) { 3404 result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr); 3405 } else { 3406 OSKextLog(/* kext */ NULL, 3407 kOSKextLogErrorLevel | 3408 kOSKextLogArchiveFlag, 3409 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion); 3410 result = kOSKextReturnUnsupported; 3411 } 3412 3413 finish: 3414 return result; 3415 } 3416 3417 /********************************************************************* 3418 * Assumes magic, signature, version, length have been checked. 3419 * xxx - need to add further bounds checking for each file entry 3420 * 3421 * Should keep track of all kexts created so far, and if we hit a 3422 * fatal error halfway through, remove those kexts. If we've dropped 3423 * an older version that had already been read, whoops! Might want to 3424 * add a level of buffering? 3425 *********************************************************************/ 3426 /* static */ 3427 OSReturn 3428 OSKext::readMkext2Archive( 3429 OSData * mkextData, 3430 OSDictionary ** mkextPlistOut, 3431 uint32_t * checksumPtr) 3432 { 3433 OSReturn result = kOSReturnError; 3434 uint32_t mkextLength; 3435 mkext2_header * mkextHeader = NULL; // do not free 3436 void * mkextEnd = NULL; // do not free 3437 uint32_t mkextVersion; 3438 uint8_t * crc_address = NULL; 3439 size_t crc_buffer_size = 0; 3440 uint32_t checksum; 3441 uint32_t mkextPlistOffset; 3442 uint32_t mkextPlistCompressedSize; 3443 char * mkextPlistEnd = NULL; // do not free 3444 uint32_t mkextPlistFullSize; 3445 OSSharedPtr<OSString> errorString; 3446 OSSharedPtr<OSData> mkextPlistUncompressedData; 3447 const char * mkextPlistDataBuffer = NULL; // do not free 3448 OSSharedPtr<OSObject> parsedXML; 3449 OSDictionary * mkextPlist = NULL; // do not release 3450 OSArray * mkextInfoDictArray = NULL; // do not release 3451 uint32_t count, i; 3452 kc_format_t kc_format; 3453 3454 if (!PE_get_primary_kc_format(&kc_format)) { 3455 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 3456 "Unable to determine primary KC format"); 3457 goto finish; 3458 } 3459 3460 mkextLength = mkextData->getLength(); 3461 mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy(); 3462 mkextEnd = (char *)mkextHeader + mkextLength; 3463 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 3464 3465 crc_address = (u_int8_t *)&mkextHeader->version; 3466 crc_buffer_size = (uintptr_t)mkextHeader + 3467 MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address; 3468 if (crc_buffer_size > INT32_MAX) { 3469 OSKextLog(/* kext */ NULL, 3470 kOSKextLogErrorLevel | 3471 kOSKextLogArchiveFlag, 3472 "Mkext archive size is too large (%lu > INT32_MAX).", 3473 crc_buffer_size); 3474 result = kOSKextReturnBadData; 3475 goto finish; 3476 } 3477 checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size); 3478 3479 if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) { 3480 OSKextLog(/* kext */ NULL, 3481 kOSKextLogErrorLevel | 3482 kOSKextLogArchiveFlag, 3483 "Mkext archive has bad checksum."); 3484 result = kOSKextReturnBadData; 3485 goto finish; 3486 } 3487 3488 if (checksumPtr) { 3489 *checksumPtr = checksum; 3490 } 3491 3492 /* Check that the CPU type & subtype match that of the running kernel. */ 3493 if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) { 3494 OSKextLog(/* kext */ NULL, 3495 kOSKextLogErrorLevel | 3496 kOSKextLogArchiveFlag, 3497 "Mkext archive must have a specific CPU type."); 3498 result = kOSKextReturnBadData; 3499 goto finish; 3500 } else { 3501 if ((UInt32)_mh_execute_header.cputype != 3502 MKEXT_GET_CPUTYPE(mkextHeader)) { 3503 OSKextLog(/* kext */ NULL, 3504 kOSKextLogErrorLevel | 3505 kOSKextLogArchiveFlag, 3506 "Mkext archive does not match the running kernel's CPU type."); 3507 result = kOSKextReturnArchNotFound; 3508 goto finish; 3509 } 3510 } 3511 3512 mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader); 3513 mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader); 3514 mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset + 3515 mkextPlistCompressedSize; 3516 if (mkextPlistEnd > mkextEnd) { 3517 OSKextLog(/* kext */ NULL, 3518 kOSKextLogErrorLevel | 3519 kOSKextLogArchiveFlag, 3520 "Mkext archive file overrun."); 3521 result = kOSKextReturnBadData; 3522 } 3523 3524 mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader); 3525 if (mkextPlistCompressedSize) { 3526 mkextPlistUncompressedData = sKernelKext->extractMkext2FileData( 3527 (UInt8 *)mkextHeader + mkextPlistOffset, 3528 "plist", 3529 mkextPlistCompressedSize, mkextPlistFullSize); 3530 if (!mkextPlistUncompressedData) { 3531 goto finish; 3532 } 3533 mkextPlistDataBuffer = (const char *) 3534 mkextPlistUncompressedData->getBytesNoCopy(); 3535 } else { 3536 mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset; 3537 } 3538 3539 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it. 3540 */ 3541 parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString); 3542 if (parsedXML) { 3543 mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get()); 3544 } 3545 if (!mkextPlist) { 3546 const char * errorCString = "(unknown error)"; 3547 3548 if (errorString && errorString->getCStringNoCopy()) { 3549 errorCString = errorString->getCStringNoCopy(); 3550 } else if (parsedXML) { 3551 errorCString = "not a dictionary"; 3552 } 3553 OSKextLog(/* kext */ NULL, 3554 kOSKextLogErrorLevel | 3555 kOSKextLogArchiveFlag, 3556 "Error unserializing mkext plist: %s.", errorCString); 3557 goto finish; 3558 } 3559 3560 mkextInfoDictArray = OSDynamicCast(OSArray, 3561 mkextPlist->getObject(kMKEXTInfoDictionariesKey)); 3562 if (!mkextInfoDictArray) { 3563 OSKextLog(/* kext */ NULL, 3564 kOSKextLogErrorLevel | 3565 kOSKextLogArchiveFlag, 3566 "Mkext archive contains no kext info dictionaries."); 3567 goto finish; 3568 } 3569 3570 count = mkextInfoDictArray->getCount(); 3571 for (i = 0; i < count; i++) { 3572 OSDictionary * infoDict; 3573 3574 3575 infoDict = OSDynamicCast(OSDictionary, 3576 mkextInfoDictArray->getObject(i)); 3577 3578 /* Create the kext for the entry, then release it, because the 3579 * kext system keeps them around until explicitly removed. 3580 * Any creation/registration failures are already logged for us. 3581 */ 3582 if (infoDict) { 3583 OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData); 3584 3585 /* Fail dynamic loading of a kext when booted from MH_FILESET */ 3586 if (kc_format == KCFormatFileset && 3587 newKext && 3588 !(newKext->isPrelinked()) && 3589 newKext->declaresExecutable()) { 3590 result = kOSReturnError; 3591 printf("Kext LOG: Dynamic loading of kext denied for kext %s\n", 3592 newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext"); 3593 3594 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 3595 "Dynamic loading of kext denied for kext %s\n", 3596 newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext"); 3597 goto finish; 3598 } 3599 } 3600 } 3601 3602 /* If the caller needs the plist, hand them back our copy 3603 */ 3604 if (mkextPlistOut) { 3605 *mkextPlistOut = mkextPlist; 3606 parsedXML.detach(); 3607 } 3608 3609 /* Even if we didn't keep any kexts from the mkext, we may have a load 3610 * request to process, so we are successful (no errors occurred). 3611 */ 3612 result = kOSReturnSuccess; 3613 3614 finish: 3615 return result; 3616 } 3617 3618 /* static */ 3619 OSReturn 3620 OSKext::readMkext2Archive( 3621 OSData * mkextData, 3622 OSSharedPtr<OSDictionary> &mkextPlistOut, 3623 uint32_t * checksumPtr) 3624 { 3625 OSDictionary * mkextPlist = NULL; 3626 OSReturn ret; 3627 3628 if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData, 3629 &mkextPlist, 3630 checksumPtr))) { 3631 mkextPlistOut.reset(mkextPlist, OSNoRetain); 3632 } 3633 return ret; 3634 } 3635 3636 /********************************************************************* 3637 *********************************************************************/ 3638 /* static */ 3639 OSSharedPtr<OSKext> 3640 OSKext::withMkext2Info( 3641 OSDictionary * anInfoDict, 3642 OSData * mkextData) 3643 { 3644 OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>(); 3645 3646 if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) { 3647 return NULL; 3648 } 3649 3650 return newKext; 3651 } 3652 3653 /********************************************************************* 3654 *********************************************************************/ 3655 bool 3656 OSKext::initWithMkext2Info( 3657 OSDictionary * anInfoDict, 3658 OSData * mkextData) 3659 { 3660 bool result = false; 3661 OSString * kextPath = NULL; // do not release 3662 OSNumber * executableOffsetNum = NULL; // do not release 3663 OSSharedPtr<OSData> executable; 3664 3665 if (anInfoDict == NULL || !super::init()) { 3666 goto finish; 3667 } 3668 3669 /* Get the path. Don't look for an arch-specific path property. 3670 */ 3671 kextPath = OSDynamicCast(OSString, 3672 anInfoDict->getObject(kMKEXTBundlePathKey)); 3673 3674 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 3675 goto finish; 3676 } 3677 3678 /* If we have a path to the executable, save it. 3679 */ 3680 executableRelPath.reset(OSDynamicCast(OSString, 3681 anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain); 3682 3683 /* Don't need the paths to be in the info dictionary any more. 3684 */ 3685 anInfoDict->removeObject(kMKEXTBundlePathKey); 3686 anInfoDict->removeObject(kMKEXTExecutableRelativePathKey); 3687 3688 executableOffsetNum = OSDynamicCast(OSNumber, 3689 infoDict->getObject(kMKEXTExecutableKey)); 3690 if (executableOffsetNum) { 3691 executable = createMkext2FileEntry(mkextData, 3692 executableOffsetNum, "executable"); 3693 infoDict->removeObject(kMKEXTExecutableKey); 3694 if (!executable) { 3695 goto finish; 3696 } 3697 if (!setExecutable(executable.get(), mkextData, true)) { 3698 goto finish; 3699 } 3700 } 3701 3702 result = (registerIdentifier() == kOSKextInitialized); 3703 finish: 3704 return result; 3705 } 3706 3707 /********************************************************************* 3708 *********************************************************************/ 3709 OSSharedPtr<OSData> 3710 OSKext::createMkext2FileEntry( 3711 OSData * mkextData, 3712 OSNumber * offsetNum, 3713 const char * name) 3714 { 3715 OSSharedPtr<OSData> result; 3716 MkextEntryRef entryRef; 3717 uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy(); 3718 uint32_t entryOffset = offsetNum->unsigned32BitValue(); 3719 3720 result = OSData::withCapacity(sizeof(entryRef)); 3721 if (!result) { 3722 goto finish; 3723 } 3724 3725 entryRef.mkext = (mkext_basic_header *)mkextBuffer; 3726 entryRef.fileinfo = mkextBuffer + entryOffset; 3727 if (!result->appendValue(entryRef)) { 3728 result.reset(); 3729 goto finish; 3730 } 3731 3732 finish: 3733 if (!result) { 3734 OSKextLog(this, 3735 kOSKextLogErrorLevel | 3736 kOSKextLogArchiveFlag, 3737 "Can't create wrapper for mkext file entry '%s' of kext %s.", 3738 name, getIdentifierCString()); 3739 } 3740 return result; 3741 } 3742 3743 /********************************************************************* 3744 *********************************************************************/ 3745 extern "C" { 3746 static void * z_alloc(void *, u_int items, u_int size); 3747 static void z_free(void *, void *ptr); 3748 3749 typedef struct z_mem { 3750 uint32_t alloc_size; 3751 uint8_t data[0]; 3752 } z_mem; 3753 3754 /* 3755 * Space allocation and freeing routines for use by zlib routines. 3756 */ 3757 void * 3758 z_alloc(void * notused __unused, u_int num_items, u_int size) 3759 { 3760 void * result = NULL; 3761 z_mem * zmem = NULL; 3762 3763 uint64_t total = ((uint64_t)num_items) * ((uint64_t)size); 3764 //Check for overflow due to multiplication 3765 if (total > UINT32_MAX) { 3766 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x", 3767 notused, num_items, size, num_items, size); 3768 } 3769 3770 uint64_t allocSize64 = total + ((uint64_t)sizeof(zmem)); 3771 //Check for overflow due to addition 3772 if (allocSize64 > UINT32_MAX) { 3773 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx", 3774 notused, num_items, size, (uint32_t)total, sizeof(zmem)); 3775 } 3776 uint32_t allocSize = (uint32_t)allocSize64; 3777 3778 zmem = (z_mem *)kalloc_data_tag(allocSize, Z_WAITOK, 3779 VM_KERN_MEMORY_OSKEXT); 3780 if (!zmem) { 3781 goto finish; 3782 } 3783 zmem->alloc_size = allocSize; 3784 result = (void *)&(zmem->data); 3785 finish: 3786 return result; 3787 } 3788 3789 void 3790 z_free(void * notused __unused, void * ptr) 3791 { 3792 uint32_t * skipper = (uint32_t *)ptr - 1; 3793 z_mem * zmem = (z_mem *)skipper; 3794 kfree_data(zmem, zmem->alloc_size); 3795 } 3796 }; 3797 3798 OSSharedPtr<OSData> 3799 OSKext::extractMkext2FileData( 3800 UInt8 * data, 3801 const char * name, 3802 uint32_t compressedSize, 3803 uint32_t fullSize) 3804 { 3805 OSSharedPtr<OSData> result; 3806 OSSharedPtr<OSData> uncompressedData; // release on error 3807 3808 uint8_t * uncompressedDataBuffer = NULL; // do not free 3809 unsigned long uncompressedSize; 3810 z_stream zstream; 3811 bool zstream_inited = false; 3812 int zlib_result; 3813 3814 /* If the file isn't compressed, we want to make a copy 3815 * so that we don't have the tie to the larger mkext file buffer any more. 3816 */ 3817 if (!compressedSize) { 3818 uncompressedData = OSData::withBytes(data, fullSize); 3819 // xxx - no check for failure? 3820 result = uncompressedData; 3821 goto finish; 3822 } 3823 3824 if (KERN_SUCCESS != kmem_alloc(kernel_map, 3825 (vm_offset_t*)&uncompressedDataBuffer, fullSize, 3826 KMA_DATA, VM_KERN_MEMORY_OSKEXT)) { 3827 /* How's this for cheesy? The kernel is only asked to extract 3828 * kext plists so we tailor the log messages. 3829 */ 3830 if (isKernel()) { 3831 OSKextLog(this, 3832 kOSKextLogErrorLevel | 3833 kOSKextLogArchiveFlag, 3834 "Allocation failure extracting %s from mkext.", name); 3835 } else { 3836 OSKextLog(this, 3837 kOSKextLogErrorLevel | 3838 kOSKextLogArchiveFlag, 3839 "Allocation failure extracting %s from mkext for kext %s.", 3840 name, getIdentifierCString()); 3841 } 3842 3843 goto finish; 3844 } 3845 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize); 3846 if (!uncompressedData) { 3847 if (isKernel()) { 3848 OSKextLog(this, 3849 kOSKextLogErrorLevel | 3850 kOSKextLogArchiveFlag, 3851 "Allocation failure extracting %s from mkext.", name); 3852 } else { 3853 OSKextLog(this, 3854 kOSKextLogErrorLevel | 3855 kOSKextLogArchiveFlag, 3856 "Allocation failure extracting %s from mkext for kext %s.", 3857 name, getIdentifierCString()); 3858 } 3859 goto finish; 3860 } 3861 uncompressedData->setDeallocFunction(&osdata_kmem_free); 3862 3863 if (isKernel()) { 3864 OSKextLog(this, 3865 kOSKextLogDetailLevel | 3866 kOSKextLogArchiveFlag, 3867 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.", 3868 name, compressedSize, fullSize); 3869 } else { 3870 OSKextLog(this, 3871 kOSKextLogDetailLevel | 3872 kOSKextLogArchiveFlag, 3873 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.", 3874 getIdentifierCString(), name, compressedSize, fullSize); 3875 } 3876 3877 bzero(&zstream, sizeof(zstream)); 3878 zstream.next_in = (UInt8 *)data; 3879 zstream.avail_in = compressedSize; 3880 3881 zstream.next_out = uncompressedDataBuffer; 3882 zstream.avail_out = fullSize; 3883 3884 zstream.zalloc = z_alloc; 3885 zstream.zfree = z_free; 3886 3887 zlib_result = inflateInit(&zstream); 3888 if (Z_OK != zlib_result) { 3889 if (isKernel()) { 3890 OSKextLog(this, 3891 kOSKextLogErrorLevel | 3892 kOSKextLogArchiveFlag, 3893 "Mkext error; zlib inflateInit failed (%d) for %s.", 3894 zlib_result, name); 3895 } else { 3896 OSKextLog(this, 3897 kOSKextLogErrorLevel | 3898 kOSKextLogArchiveFlag, 3899 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .", 3900 getIdentifierCString(), zlib_result, name); 3901 } 3902 goto finish; 3903 } else { 3904 zstream_inited = true; 3905 } 3906 3907 zlib_result = inflate(&zstream, Z_FINISH); 3908 3909 if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) { 3910 uncompressedSize = zstream.total_out; 3911 } else { 3912 if (isKernel()) { 3913 OSKextLog(this, 3914 kOSKextLogErrorLevel | 3915 kOSKextLogArchiveFlag, 3916 "Mkext error; zlib inflate failed (%d) for %s.", 3917 zlib_result, name); 3918 } else { 3919 OSKextLog(this, 3920 kOSKextLogErrorLevel | 3921 kOSKextLogArchiveFlag, 3922 "Kext %s - mkext error; zlib inflate failed (%d) for %s .", 3923 getIdentifierCString(), zlib_result, name); 3924 } 3925 if (zstream.msg) { 3926 OSKextLog(this, 3927 kOSKextLogErrorLevel | 3928 kOSKextLogArchiveFlag, 3929 "zlib error: %s.", zstream.msg); 3930 } 3931 goto finish; 3932 } 3933 3934 if (uncompressedSize != fullSize) { 3935 if (isKernel()) { 3936 OSKextLog(this, 3937 kOSKextLogErrorLevel | 3938 kOSKextLogArchiveFlag, 3939 "Mkext error; zlib inflate discrepancy for %s, " 3940 "uncompressed size != original size.", name); 3941 } else { 3942 OSKextLog(this, 3943 kOSKextLogErrorLevel | 3944 kOSKextLogArchiveFlag, 3945 "Kext %s - mkext error; zlib inflate discrepancy for %s, " 3946 "uncompressed size != original size.", 3947 getIdentifierCString(), name); 3948 } 3949 goto finish; 3950 } 3951 3952 result = os::move(uncompressedData); 3953 3954 finish: 3955 /* Don't bother checking return, nothing we can do on fail. 3956 */ 3957 if (zstream_inited) { 3958 inflateEnd(&zstream); 3959 } 3960 3961 return result; 3962 } 3963 3964 /********************************************************************* 3965 *********************************************************************/ 3966 /* static */ 3967 OSReturn 3968 OSKext::loadFromMkext( 3969 OSKextLogSpec clientLogFilter, 3970 char * mkextBuffer, 3971 uint32_t mkextBufferLength, 3972 char ** logInfoOut, 3973 uint32_t * logInfoLengthOut) 3974 { 3975 OSReturn result = kOSReturnError; 3976 OSReturn tempResult = kOSReturnError; 3977 3978 OSSharedPtr<OSData> mkextData; 3979 OSSharedPtr<OSDictionary> mkextPlist; 3980 3981 OSSharedPtr<OSArray> logInfoArray; 3982 OSSharedPtr<OSSerialize> serializer; 3983 3984 OSString * predicate = NULL; // do not release 3985 OSDictionary * requestArgs = NULL; // do not release 3986 3987 OSString * kextIdentifier = NULL; // do not release 3988 OSNumber * startKextExcludeNum = NULL; // do not release 3989 OSNumber * startMatchingExcludeNum = NULL; // do not release 3990 OSBoolean * delayAutounloadBool = NULL; // do not release 3991 OSArray * personalityNames = NULL; // do not release 3992 3993 /* Default values for these two options: regular autounload behavior, 3994 * load all kexts, send no personalities. 3995 */ 3996 Boolean delayAutounload = false; 3997 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 3998 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll; 3999 4000 IORecursiveLockLock(sKextLock); 4001 4002 if (logInfoOut) { 4003 *logInfoOut = NULL; 4004 *logInfoLengthOut = 0; 4005 } 4006 4007 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 4008 4009 OSKextLog(/* kext */ NULL, 4010 kOSKextLogDebugLevel | 4011 kOSKextLogIPCFlag, 4012 "Received kext load request from user space."); 4013 4014 /* Regardless of processing, the fact that we have gotten here means some 4015 * user-space program is up and talking to us, so we'll switch our kext 4016 * registration to reflect that. 4017 */ 4018 if (!sUserLoadsActive) { 4019 OSKextLog(/* kext */ NULL, 4020 kOSKextLogProgressLevel | 4021 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 4022 "Switching to late startup (user-space) kext loading policy."); 4023 4024 sUserLoadsActive = true; 4025 } 4026 4027 if (!sLoadEnabled) { 4028 OSKextLog(/* kext */ NULL, 4029 kOSKextLogErrorLevel | 4030 kOSKextLogLoadFlag, 4031 "Kext loading is disabled."); 4032 result = kOSKextReturnDisabled; 4033 goto finish; 4034 } 4035 4036 /* Note that we do not set a dealloc function on this OSData 4037 * object! No references to it can remain after the loadFromMkext() 4038 * call since we are in a MIG function, and will vm_deallocate() 4039 * the buffer. 4040 */ 4041 mkextData = OSData::withBytesNoCopy(mkextBuffer, 4042 mkextBufferLength); 4043 if (!mkextData) { 4044 OSKextLog(/* kext */ NULL, 4045 kOSKextLogErrorLevel | 4046 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 4047 "Failed to create wrapper for kext load request."); 4048 result = kOSKextReturnNoMemory; 4049 goto finish; 4050 } 4051 4052 result = readMkext2Archive(mkextData.get(), mkextPlist, NULL); 4053 if (result != kOSReturnSuccess) { 4054 OSKextLog(/* kext */ NULL, 4055 kOSKextLogErrorLevel | 4056 kOSKextLogLoadFlag, 4057 "Failed to read kext load request."); 4058 goto finish; 4059 } 4060 4061 predicate = _OSKextGetRequestPredicate(mkextPlist.get()); 4062 if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) { 4063 OSKextLog(/* kext */ NULL, 4064 kOSKextLogErrorLevel | 4065 kOSKextLogLoadFlag, 4066 "Received kext load request with no predicate; skipping."); 4067 result = kOSKextReturnInvalidArgument; 4068 goto finish; 4069 } 4070 4071 requestArgs = OSDynamicCast(OSDictionary, 4072 mkextPlist->getObject(kKextRequestArgumentsKey)); 4073 if (!requestArgs || !requestArgs->getCount()) { 4074 OSKextLog(/* kext */ NULL, 4075 kOSKextLogErrorLevel | 4076 kOSKextLogLoadFlag, 4077 "Received kext load request with no arguments."); 4078 result = kOSKextReturnInvalidArgument; 4079 goto finish; 4080 } 4081 4082 kextIdentifier = OSDynamicCast(OSString, 4083 requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey)); 4084 4085 if (!kextIdentifier) { 4086 OSKextLog(/* kext */ NULL, 4087 kOSKextLogErrorLevel | 4088 kOSKextLogLoadFlag, 4089 "Received kext load request with no kext identifier."); 4090 result = kOSKextReturnInvalidArgument; 4091 goto finish; 4092 } 4093 4094 startKextExcludeNum = OSDynamicCast(OSNumber, 4095 requestArgs->getObject(kKextRequestArgumentStartExcludeKey)); 4096 startMatchingExcludeNum = OSDynamicCast(OSNumber, 4097 requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey)); 4098 delayAutounloadBool = OSDynamicCast(OSBoolean, 4099 requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey)); 4100 personalityNames = OSDynamicCast(OSArray, 4101 requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey)); 4102 4103 if (delayAutounloadBool) { 4104 delayAutounload = delayAutounloadBool->getValue(); 4105 } 4106 if (startKextExcludeNum) { 4107 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 4108 } 4109 if (startMatchingExcludeNum) { 4110 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 4111 } 4112 4113 OSKextLog(/* kext */ NULL, 4114 kOSKextLogProgressLevel | 4115 kOSKextLogIPCFlag, 4116 "Received request from user space to load kext %s.", 4117 kextIdentifier->getCStringNoCopy()); 4118 4119 /* Load the kext, with no deferral, since this is a load from outside 4120 * the kernel. 4121 * xxx - Would like a better way to handle the default values for the 4122 * xxx - start/match opt args. 4123 */ 4124 result = OSKext::loadKextWithIdentifier( 4125 kextIdentifier, 4126 /* kextRef */ NULL, 4127 /* allowDefer */ false, 4128 delayAutounload, 4129 startKextExcludeLevel, 4130 startMatchingExcludeLevel, 4131 personalityNames); 4132 if (result != kOSReturnSuccess) { 4133 goto finish; 4134 } 4135 /* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue 4136 * for matching via a separate IOKit calldown. 4137 */ 4138 4139 finish: 4140 4141 /* Gather up the collected log messages for user space. Any 4142 * error messages past this call will not make it up as log messages 4143 * but will be in the system log. 4144 */ 4145 logInfoArray = OSKext::clearUserSpaceLogFilter(); 4146 4147 if (logInfoArray && logInfoOut && logInfoLengthOut) { 4148 tempResult = OSKext::serializeLogInfo(logInfoArray.get(), 4149 logInfoOut, logInfoLengthOut); 4150 if (tempResult != kOSReturnSuccess) { 4151 result = tempResult; 4152 } 4153 } 4154 4155 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false); 4156 4157 IORecursiveLockUnlock(sKextLock); 4158 4159 /* Note: mkextDataObject will have been retained by every kext w/an 4160 * executable in it. That should all have been flushed out at the 4161 * and of the load operation, but you never know.... 4162 */ 4163 if (mkextData && mkextData->getRetainCount() > 1) { 4164 OSKextLog(/* kext */ NULL, 4165 kOSKextLogErrorLevel | 4166 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 4167 "Kext load request buffer from user space still retained by a kext; " 4168 "probable memory leak."); 4169 } 4170 4171 return result; 4172 } 4173 4174 #endif // CONFIG_KXLD 4175 4176 /********************************************************************* 4177 *********************************************************************/ 4178 /* static */ 4179 OSReturn 4180 OSKext::serializeLogInfo( 4181 OSArray * logInfoArray, 4182 char ** logInfoOut, 4183 uint32_t * logInfoLengthOut) 4184 { 4185 OSReturn result = kOSReturnError; 4186 char * buffer = NULL; 4187 kern_return_t kmem_result = KERN_FAILURE; 4188 OSSharedPtr<OSSerialize> serializer; 4189 char * logInfo = NULL; // returned by reference 4190 uint32_t logInfoLength = 0; 4191 4192 if (!logInfoArray || !logInfoOut || !logInfoLengthOut) { 4193 OSKextLog(/* kext */ NULL, 4194 kOSKextLogErrorLevel | 4195 kOSKextLogIPCFlag, 4196 "Internal error; invalid arguments to OSKext::serializeLogInfo()."); 4197 /* Bad programmer. */ 4198 result = kOSKextReturnInvalidArgument; 4199 goto finish; 4200 } 4201 4202 serializer = OSSerialize::withCapacity(0); 4203 if (!serializer) { 4204 OSKextLog(/* kext */ NULL, 4205 kOSKextLogErrorLevel | 4206 kOSKextLogIPCFlag, 4207 "Failed to create serializer on log info for request from user space."); 4208 /* Incidental error; we're going to (try to) allow the request 4209 * itself to succeed. */ 4210 } else { 4211 if (!logInfoArray->serialize(serializer.get())) { 4212 OSKextLog(/* kext */ NULL, 4213 kOSKextLogErrorLevel | 4214 kOSKextLogIPCFlag, 4215 "Failed to serialize log info for request from user space."); 4216 /* Incidental error; we're going to (try to) allow the request 4217 * itself to succeed. */ 4218 } else { 4219 logInfo = serializer->text(); 4220 logInfoLength = serializer->getLength(); 4221 4222 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), 4223 KMA_DATA, VM_KERN_MEMORY_OSKEXT); 4224 if (kmem_result != KERN_SUCCESS) { 4225 OSKextLog(/* kext */ NULL, 4226 kOSKextLogErrorLevel | 4227 kOSKextLogIPCFlag, 4228 "Failed to copy log info for request from user space."); 4229 /* Incidental error; we're going to (try to) allow the request 4230 * to succeed. */ 4231 } else { 4232 /* 11981737 - clear uninitialized data in last page */ 4233 bzero((void *)(buffer + logInfoLength), 4234 (round_page(logInfoLength) - logInfoLength)); 4235 memcpy(buffer, logInfo, logInfoLength); 4236 *logInfoOut = buffer; 4237 *logInfoLengthOut = logInfoLength; 4238 } 4239 } 4240 } 4241 4242 result = kOSReturnSuccess; 4243 finish: 4244 return result; 4245 } 4246 4247 #if PRAGMA_MARK 4248 #pragma mark Instance Management Methods 4249 #endif 4250 /********************************************************************* 4251 *********************************************************************/ 4252 OSSharedPtr<OSKext> 4253 OSKext::lookupKextWithIdentifier(const char * kextIdentifier) 4254 { 4255 OSSharedPtr<OSKext> foundKext; 4256 4257 IORecursiveLockLock(sKextLock); 4258 foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain); 4259 IORecursiveLockUnlock(sKextLock); 4260 4261 return foundKext; 4262 } 4263 4264 /********************************************************************* 4265 *********************************************************************/ 4266 OSSharedPtr<OSKext> 4267 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier) 4268 { 4269 return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy()); 4270 } 4271 4272 /********************************************************************* 4273 *********************************************************************/ 4274 OSSharedPtr<OSKext> 4275 OSKext::lookupDextWithIdentifier(OSString * dextIdentifier, OSData *dextUniqueIdentifier) 4276 { 4277 OSSharedPtr<OSKext> foundDext; 4278 foundDext.reset(); 4279 4280 IORecursiveLockLock(sKextLock); 4281 OSKext *dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIdentifier->getCStringNoCopy())); 4282 if (dext != NULL && dext->isDriverKit()) { 4283 if (dext->dextUniqueID == NULL || dext->dextUniqueID->isEqualTo(dextUniqueIdentifier)) { 4284 foundDext.reset(dext, OSRetain); 4285 } 4286 } 4287 IORecursiveLockUnlock(sKextLock); 4288 4289 return foundDext; 4290 } 4291 4292 /********************************************************************* 4293 *********************************************************************/ 4294 OSSharedPtr<OSKext> 4295 OSKext::lookupKextWithLoadTag(uint32_t aTag) 4296 { 4297 OSSharedPtr<OSKext> foundKext; // returned 4298 uint32_t i, j; 4299 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 4300 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 4301 4302 IORecursiveLockLock(sKextLock); 4303 4304 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 4305 for (i = 0; i < count[j]; i++) { 4306 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 4307 if (thisKext->getLoadTag() == aTag) { 4308 foundKext.reset(thisKext, OSRetain); 4309 goto finish; 4310 } 4311 } 4312 } 4313 4314 finish: 4315 IORecursiveLockUnlock(sKextLock); 4316 4317 return foundKext; 4318 } 4319 4320 /********************************************************************* 4321 *********************************************************************/ 4322 OSSharedPtr<OSKext> 4323 OSKext::lookupKextWithAddress(vm_address_t address) 4324 { 4325 OSSharedPtr<OSKext> foundKext; // returned 4326 uint32_t count, i; 4327 kmod_info_t *kmod_info; 4328 vm_address_t originalAddress; 4329 #if defined(__arm64__) 4330 uint64_t textExecBase; 4331 size_t textExecSize; 4332 #endif /* defined(__arm64__) */ 4333 4334 originalAddress = address; 4335 #if __has_feature(ptrauth_calls) 4336 address = (vm_address_t)VM_KERNEL_STRIP_PTR(address); 4337 #endif /* __has_feature(ptrauth_calls) */ 4338 4339 IORecursiveLockLock(sKextLock); 4340 4341 count = sLoadedKexts->getCount(); 4342 for (i = 0; i < count; i++) { 4343 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 4344 if (thisKext == sKernelKext) { 4345 continue; 4346 } 4347 if (thisKext->kmod_info && thisKext->kmod_info->address) { 4348 kmod_info = thisKext->kmod_info; 4349 vm_address_t kext_start = kmod_info->address; 4350 vm_address_t kext_end = kext_start + kmod_info->size; 4351 if ((kext_start <= address) && (address < kext_end)) { 4352 foundKext.reset(thisKext, OSRetain); 4353 goto finish; 4354 } 4355 #if defined(__arm64__) 4356 textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize); 4357 4358 /** 4359 * If the addresses within the Mach-O are unslid, then manually 4360 * slide any addresses coming from the Mach-O before usage. 4361 */ 4362 if (thisKext->flags.unslidMachO) { 4363 textExecBase = (uintptr_t) ml_static_slide((vm_offset_t) textExecBase); 4364 } 4365 4366 if ((textExecBase <= address) && (address < textExecBase + textExecSize)) { 4367 foundKext.reset(thisKext, OSRetain); 4368 goto finish; 4369 } 4370 #endif /* defined (__arm64__) */ 4371 } 4372 } 4373 if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) { 4374 foundKext.reset(sKernelKext, OSRetain); 4375 goto finish; 4376 } 4377 /* 4378 * DriverKit userspace executables do not have a kernel linkedExecutable, 4379 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address 4380 * here, so use the original address passed to this method. 4381 * 4382 * This is supposed to be used for logging reasons only. When logd 4383 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we 4384 * remove it here before checking it against the LoadTag. 4385 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line. 4386 */ 4387 4388 address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT); 4389 count = sLoadedDriverKitKexts->getCount(); 4390 for (i = 0; i < count; i++) { 4391 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i)); 4392 if (thisKext->getLoadTag() == address) { 4393 foundKext.reset(thisKext, OSRetain); 4394 } 4395 } 4396 4397 finish: 4398 IORecursiveLockUnlock(sKextLock); 4399 4400 return foundKext; 4401 } 4402 4403 OSSharedPtr<OSData> 4404 OSKext::copyKextUUIDForAddress(OSNumber *address) 4405 { 4406 OSSharedPtr<OSData> uuid; 4407 OSSharedPtr<OSKext> kext; 4408 4409 if (!address) { 4410 return NULL; 4411 } 4412 4413 #if CONFIG_MACF 4414 /* Is the calling process allowed to query kext info? */ 4415 if (current_task() != kernel_task) { 4416 int macCheckResult = 0; 4417 kauth_cred_t cred = NULL; 4418 4419 cred = kauth_cred_get_with_ref(); 4420 macCheckResult = mac_kext_check_query(cred); 4421 kauth_cred_unref(&cred); 4422 4423 if (macCheckResult != 0) { 4424 OSKextLog(/* kext */ NULL, 4425 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 4426 "Failed to query kext UUID (MAC policy error 0x%x).", 4427 macCheckResult); 4428 return NULL; 4429 } 4430 } 4431 #endif 4432 4433 uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue()); 4434 if (slidAddress != 0) { 4435 kext = lookupKextWithAddress(slidAddress); 4436 if (kext) { 4437 uuid = kext->copyTextUUID(); 4438 } 4439 } 4440 4441 if (!uuid) { 4442 /* 4443 * If we still don't have a UUID, then we failed to match the slid + stripped address with 4444 * a kext. This might have happened because the log message came from a dext. 4445 * 4446 * Try again with the original address. 4447 */ 4448 kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue()); 4449 if (kext && kext->isDriverKit()) { 4450 uuid = kext->copyTextUUID(); 4451 } 4452 } 4453 4454 return uuid; 4455 } 4456 4457 /********************************************************************* 4458 *********************************************************************/ 4459 OSSharedPtr<OSKext> 4460 OSKext::lookupKextWithUUID(uuid_t wanted) 4461 { 4462 OSSharedPtr<OSKext> foundKext; // returned 4463 uint32_t j, i; 4464 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 4465 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 4466 4467 4468 IORecursiveLockLock(sKextLock); 4469 4470 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 4471 for (i = 0; i < count[j]; i++) { 4472 OSKext * thisKext = NULL; 4473 4474 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 4475 if (!thisKext) { 4476 continue; 4477 } 4478 4479 OSSharedPtr<OSData> uuid_data = thisKext->copyUUID(); 4480 if (!uuid_data) { 4481 continue; 4482 } 4483 4484 uuid_t uuid; 4485 memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 4486 4487 if (0 == uuid_compare(wanted, uuid)) { 4488 foundKext.reset(thisKext, OSRetain); 4489 goto finish; 4490 } 4491 } 4492 } 4493 finish: 4494 IORecursiveLockUnlock(sKextLock); 4495 4496 return foundKext; 4497 } 4498 4499 4500 4501 4502 /********************************************************************* 4503 *********************************************************************/ 4504 /* static */ 4505 bool 4506 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier) 4507 { 4508 bool result = false; 4509 OSKext * foundKext = NULL; // returned 4510 4511 IORecursiveLockLock(sKextLock); 4512 4513 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 4514 if (foundKext && foundKext->isLoaded()) { 4515 result = true; 4516 } 4517 4518 IORecursiveLockUnlock(sKextLock); 4519 4520 return result; 4521 } 4522 4523 /********************************************************************* 4524 * xxx - should spawn a separate thread so a kext can safely have 4525 * xxx - itself unloaded. 4526 *********************************************************************/ 4527 /* static */ 4528 OSReturn 4529 OSKext::removeKext( 4530 OSKext * aKext, 4531 #if CONFIG_EMBEDDED 4532 __unused 4533 #endif 4534 bool terminateServicesAndRemovePersonalitiesFlag) 4535 { 4536 #if CONFIG_EMBEDDED 4537 if (!aKext->isDriverKit()) { 4538 OSKextLog(aKext, 4539 kOSKextLogErrorLevel | 4540 kOSKextLogKextBookkeepingFlag, 4541 "removeKext() called for %s, only supported on embedded for DriverKit dexts", 4542 aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext"); 4543 4544 return kOSReturnSuccess; 4545 } 4546 #endif /* CONFIG_EMBEDDED */ 4547 OSReturn result = kOSKextReturnInUse; 4548 OSKext * checkKext = NULL; // do not release 4549 #if CONFIG_MACF 4550 int macCheckResult = 0; 4551 kauth_cred_t cred = NULL; 4552 #endif 4553 4554 IORecursiveLockLock(sKextLock); 4555 4556 /* If the kext has no identifier, it failed to init 4557 * so isn't in sKextsByID and it isn't loaded. 4558 */ 4559 if (!aKext->getIdentifier()) { 4560 result = kOSReturnSuccess; 4561 goto finish; 4562 } 4563 4564 checkKext = OSDynamicCast(OSKext, 4565 sKextsByID->getObject(aKext->getIdentifier())); 4566 if (checkKext != aKext) { 4567 result = kOSKextReturnNotFound; 4568 goto finish; 4569 } 4570 4571 if (aKext->isLoaded() || aKext->isDriverKit()) { 4572 #if CONFIG_MACF 4573 if (current_task() != kernel_task) { 4574 cred = kauth_cred_get_with_ref(); 4575 macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString()); 4576 kauth_cred_unref(&cred); 4577 } 4578 4579 if (macCheckResult != 0) { 4580 result = kOSReturnError; 4581 OSKextLog(aKext, 4582 kOSKextLogErrorLevel | 4583 kOSKextLogKextBookkeepingFlag, 4584 "Failed to remove kext %s (MAC policy error 0x%x).", 4585 aKext->getIdentifierCString(), macCheckResult); 4586 goto finish; 4587 } 4588 #endif 4589 4590 /* make sure there are no resource requests in flight - 17187548 */ 4591 if (aKext->declaresExecutable() && aKext->countRequestCallbacks()) { 4592 goto finish; 4593 } 4594 if (aKext->flags.unloadUnsupported) { 4595 result = kOSKextReturnInUse; 4596 OSKextLog(aKext, 4597 kOSKextLogErrorLevel | 4598 kOSKextLogKextBookkeepingFlag, 4599 "Can't remove kext %s; unsupported by cache.", 4600 aKext->getIdentifierCString()); 4601 goto finish; 4602 } 4603 4604 /* If we are terminating, send the request to the IOCatalogue 4605 * (which will actually call us right back but that's ok we have 4606 * a recursive lock don't you know) but do not ask the IOCatalogue 4607 * to call back with an unload, we'll do that right here. 4608 */ 4609 if (terminateServicesAndRemovePersonalitiesFlag) { 4610 result = gIOCatalogue->terminateDriversForModule( 4611 aKext->getIdentifierCString(), /* unload */ false); 4612 if (result != kOSReturnSuccess) { 4613 OSKextLog(aKext, 4614 kOSKextLogErrorLevel | 4615 kOSKextLogKextBookkeepingFlag, 4616 "Can't remove kext %s; services failed to terminate - 0x%x.", 4617 aKext->getIdentifierCString(), result); 4618 goto finish; 4619 } 4620 } 4621 4622 result = aKext->unload(); 4623 if (result != kOSReturnSuccess) { 4624 OSKextLog(aKext, 4625 kOSKextLogErrorLevel | 4626 kOSKextLogKextBookkeepingFlag, 4627 "Can't remove kext %s; kext failed to unload - 0x%x.", 4628 aKext->getIdentifierCString(), result); 4629 goto finish; 4630 } 4631 } 4632 4633 /* Remove personalities as requested. This is a bit redundant for a loaded 4634 * kext as IOCatalogue::terminateDriversForModule() removes driver 4635 * personalities, but it doesn't restart matching, which we always want 4636 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures 4637 * that happens. 4638 */ 4639 if (terminateServicesAndRemovePersonalitiesFlag) { 4640 aKext->removePersonalitiesFromCatalog(); 4641 } 4642 4643 if (aKext->isInFileset()) { 4644 OSKextLog(aKext, 4645 kOSKextLogProgressLevel | 4646 kOSKextLogKextBookkeepingFlag, 4647 "Fileset kext %s unloaded.", 4648 aKext->getIdentifierCString()); 4649 } else { 4650 OSKextLog(aKext, 4651 kOSKextLogProgressLevel | 4652 kOSKextLogKextBookkeepingFlag, 4653 "Removing kext %s.", 4654 aKext->getIdentifierCString()); 4655 4656 sKextsByID->removeObject(aKext->getIdentifier()); 4657 } 4658 result = kOSReturnSuccess; 4659 4660 finish: 4661 IORecursiveLockUnlock(sKextLock); 4662 return result; 4663 } 4664 4665 /********************************************************************* 4666 *********************************************************************/ 4667 /* static */ 4668 OSReturn 4669 OSKext::removeKextWithIdentifier( 4670 const char * kextIdentifier, 4671 bool terminateServicesAndRemovePersonalitiesFlag) 4672 { 4673 OSReturn result = kOSReturnError; 4674 4675 IORecursiveLockLock(sKextLock); 4676 4677 OSKext * aKext = OSDynamicCast(OSKext, 4678 sKextsByID->getObject(kextIdentifier)); 4679 if (!aKext) { 4680 result = kOSKextReturnNotFound; 4681 OSKextLog(/* kext */ NULL, 4682 kOSKextLogErrorLevel | 4683 kOSKextLogKextBookkeepingFlag, 4684 "Can't remove kext %s - not found.", 4685 kextIdentifier); 4686 goto finish; 4687 } 4688 4689 result = OSKext::removeKext(aKext, 4690 terminateServicesAndRemovePersonalitiesFlag); 4691 4692 finish: 4693 IORecursiveLockUnlock(sKextLock); 4694 4695 return result; 4696 } 4697 4698 /********************************************************************* 4699 *********************************************************************/ 4700 /* static */ 4701 OSReturn 4702 OSKext::removeKextWithLoadTag( 4703 OSKextLoadTag loadTag, 4704 bool terminateServicesAndRemovePersonalitiesFlag) 4705 { 4706 OSReturn result = kOSReturnError; 4707 OSKext * foundKext = NULL; 4708 uint32_t i, j; 4709 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 4710 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 4711 4712 4713 IORecursiveLockLock(sKextLock); 4714 4715 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 4716 for (i = 0; i < count[j]; i++) { 4717 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 4718 if (thisKext->loadTag == loadTag) { 4719 foundKext = thisKext; 4720 break; 4721 } 4722 } 4723 } 4724 4725 if (!foundKext) { 4726 result = kOSKextReturnNotFound; 4727 OSKextLog(/* kext */ NULL, 4728 kOSKextLogErrorLevel | 4729 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 4730 "Can't remove kext with load tag %d - not found.", 4731 loadTag); 4732 goto finish; 4733 } 4734 4735 result = OSKext::removeKext(foundKext, 4736 terminateServicesAndRemovePersonalitiesFlag); 4737 4738 finish: 4739 IORecursiveLockUnlock(sKextLock); 4740 4741 return result; 4742 } 4743 4744 /********************************************************************* 4745 *********************************************************************/ 4746 OSSharedPtr<OSDictionary> 4747 OSKext::copyKexts(void) 4748 { 4749 OSSharedPtr<OSDictionary> result; 4750 4751 IORecursiveLockLock(sKextLock); 4752 result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection()); 4753 IORecursiveLockUnlock(sKextLock); 4754 4755 return result; 4756 } 4757 4758 /********************************************************************* 4759 *********************************************************************/ 4760 #define BOOTER_KEXT_PREFIX "Driver-" 4761 4762 typedef struct _DeviceTreeBuffer { 4763 uint32_t paddr; 4764 uint32_t length; 4765 } _DeviceTreeBuffer; 4766 4767 /********************************************************************* 4768 * Create a dictionary of excluded kexts from the given booter data. 4769 *********************************************************************/ 4770 /* static */ 4771 void 4772 OSKext::createExcludeListFromBooterData( 4773 OSDictionary * theDictionary, 4774 OSCollectionIterator * theIterator ) 4775 { 4776 OSString * deviceTreeName = NULL; // do not release 4777 const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not release 4778 char * booterDataPtr = NULL; // do not release 4779 _BooterKextFileInfo * kextFileInfo = NULL; // do not release 4780 char * infoDictAddr = NULL; // do not release 4781 OSSharedPtr<OSObject> parsedXML; 4782 OSDictionary * theInfoDict = NULL; // do not release 4783 4784 theIterator->reset(); 4785 4786 /* look for AppleKextExcludeList.kext */ 4787 while ((deviceTreeName = 4788 OSDynamicCast(OSString, theIterator->getNextObject()))) { 4789 const char * devTreeNameCString; 4790 OSData * deviceTreeEntry; // do not release 4791 OSString * myBundleID; // do not release 4792 4793 deviceTreeEntry = 4794 OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName)); 4795 if (!deviceTreeEntry) { 4796 continue; 4797 } 4798 4799 /* Make sure it is a kext */ 4800 devTreeNameCString = deviceTreeName->getCStringNoCopy(); 4801 if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX, 4802 (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) { 4803 OSKextLog(NULL, 4804 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4805 "\"%s\" not a kext", 4806 devTreeNameCString); 4807 continue; 4808 } 4809 4810 deviceTreeBuffer = (const _DeviceTreeBuffer *) 4811 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer)); 4812 if (!deviceTreeBuffer) { 4813 continue; 4814 } 4815 4816 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr); 4817 if (!booterDataPtr) { 4818 continue; 4819 } 4820 4821 kextFileInfo = (_BooterKextFileInfo *) booterDataPtr; 4822 if (!kextFileInfo->infoDictPhysAddr || 4823 !kextFileInfo->infoDictLength) { 4824 continue; 4825 } 4826 4827 infoDictAddr = (char *) 4828 ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 4829 if (!infoDictAddr) { 4830 continue; 4831 } 4832 4833 parsedXML = OSUnserializeXML(infoDictAddr); 4834 if (!parsedXML) { 4835 continue; 4836 } 4837 4838 theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 4839 if (!theInfoDict) { 4840 continue; 4841 } 4842 4843 myBundleID = 4844 OSDynamicCast(OSString, 4845 theInfoDict->getObject(kCFBundleIdentifierKey)); 4846 if (myBundleID && 4847 strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) { 4848 boolean_t updated = updateExcludeList(theInfoDict); 4849 if (!updated) { 4850 /* 25322874 */ 4851 panic("Missing OSKextExcludeList dictionary"); 4852 } 4853 break; 4854 } 4855 } // while ( (deviceTreeName = ...) ) 4856 4857 return; 4858 } 4859 4860 /********************************************************************* 4861 * Create a dictionary of excluded kexts from the given prelink 4862 * info (kernelcache). 4863 *********************************************************************/ 4864 /* static */ 4865 void 4866 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray ) 4867 { 4868 OSDictionary * myInfoDict = NULL; // do not release 4869 OSString * myBundleID; // do not release 4870 u_int i; 4871 4872 /* Find the Apple Kext Exclude List. */ 4873 for (i = 0; i < theInfoArray->getCount(); i++) { 4874 myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i)); 4875 if (!myInfoDict) { 4876 continue; 4877 } 4878 myBundleID = 4879 OSDynamicCast(OSString, 4880 myInfoDict->getObject(kCFBundleIdentifierKey)); 4881 if (myBundleID && 4882 strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) { 4883 boolean_t updated = updateExcludeList(myInfoDict); 4884 if (!updated) { 4885 /* 25322874 */ 4886 panic("Missing OSKextExcludeList dictionary"); 4887 } 4888 break; 4889 } 4890 } // for (i = 0; i < theInfoArray->getCount()... 4891 4892 return; 4893 } 4894 4895 /* static */ 4896 boolean_t 4897 OSKext::updateExcludeList(OSDictionary *infoDict) 4898 { 4899 OSDictionary *myTempDict = NULL; // do not free 4900 OSString *myTempString = NULL; // do not free 4901 OSKextVersion newVersion = 0; 4902 boolean_t updated = false; 4903 4904 if (!infoDict) { 4905 return false; 4906 } 4907 4908 myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList")); 4909 if (!myTempDict) { 4910 return false; 4911 } 4912 4913 myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey)); 4914 if (!myTempString) { 4915 return false; 4916 } 4917 4918 newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy()); 4919 if (newVersion == 0) { 4920 return false; 4921 } 4922 4923 IORecursiveLockLock(sKextLock); 4924 4925 if (newVersion > sExcludeListVersion) { 4926 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0); 4927 sExcludeListVersion = newVersion; 4928 updated = true; 4929 } 4930 4931 IORecursiveLockUnlock(sKextLock); 4932 return updated; 4933 } 4934 4935 #if PRAGMA_MARK 4936 #pragma mark Accessors 4937 #endif 4938 4939 /********************************************************************* 4940 *********************************************************************/ 4941 const OSObject * 4942 OSKext::getBundleExecutable(void) 4943 { 4944 return infoDict->getObject(kCFBundleExecutableKey); 4945 } 4946 4947 /********************************************************************* 4948 *********************************************************************/ 4949 const OSSymbol * 4950 OSKext::getIdentifier(void) 4951 { 4952 return bundleID.get(); 4953 } 4954 4955 /********************************************************************* 4956 * A kext must have a bundle identifier to even survive initialization; 4957 * this is guaranteed to exist past then. 4958 *********************************************************************/ 4959 const char * 4960 OSKext::getIdentifierCString(void) 4961 { 4962 return bundleID->getCStringNoCopy(); 4963 } 4964 4965 /********************************************************************* 4966 *********************************************************************/ 4967 OSKextVersion 4968 OSKext::getVersion(void) 4969 { 4970 return version; 4971 } 4972 4973 /********************************************************************* 4974 *********************************************************************/ 4975 OSKextVersion 4976 OSKext::getCompatibleVersion(void) 4977 { 4978 return compatibleVersion; 4979 } 4980 4981 /********************************************************************* 4982 *********************************************************************/ 4983 bool 4984 OSKext::isLibrary(void) 4985 { 4986 return getCompatibleVersion() > 0; 4987 } 4988 4989 /********************************************************************* 4990 *********************************************************************/ 4991 bool 4992 OSKext::isCompatibleWithVersion(OSKextVersion aVersion) 4993 { 4994 if ((compatibleVersion > -1 && version > -1) && 4995 (compatibleVersion <= version && aVersion <= version)) { 4996 return true; 4997 } 4998 return false; 4999 } 5000 5001 /********************************************************************* 5002 *********************************************************************/ 5003 bool 5004 OSKext::declaresExecutable(void) 5005 { 5006 if (isDriverKit()) { 5007 return false; 5008 } 5009 return getPropertyForHostArch(kCFBundleExecutableKey) != NULL; 5010 } 5011 5012 /********************************************************************* 5013 *********************************************************************/ 5014 OSData * 5015 OSKext::getExecutable(void) 5016 { 5017 OSData * result = NULL; 5018 OSSharedPtr<OSData> extractedExecutable; 5019 5020 if (flags.builtin) { 5021 return sKernelKext->linkedExecutable.get(); 5022 } 5023 5024 result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey)); 5025 if (result) { 5026 return result; 5027 } 5028 5029 #if CONFIG_KXLD 5030 OSData * mkextExecutableRef = NULL; // do not release 5031 mkextExecutableRef = OSDynamicCast(OSData, 5032 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey)); 5033 5034 if (mkextExecutableRef) { 5035 MkextEntryRef * mkextEntryRef = (MkextEntryRef *) 5036 mkextExecutableRef->getBytesNoCopy(); 5037 uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext); 5038 if (mkextVersion == MKEXT_VERS_2) { 5039 mkext2_file_entry * fileinfo = 5040 (mkext2_file_entry *)mkextEntryRef->fileinfo; 5041 uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo); 5042 uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo); 5043 extractedExecutable = extractMkext2FileData( 5044 MKEXT2_GET_ENTRY_DATA(fileinfo), "executable", 5045 compressedSize, fullSize); 5046 } else { 5047 OSKextLog(this, kOSKextLogErrorLevel | 5048 kOSKextLogArchiveFlag, 5049 "Kext %s - unknown mkext version 0x%x for executable.", 5050 getIdentifierCString(), mkextVersion); 5051 } 5052 5053 /* Regardless of success, remove the mkext executable, 5054 * and drop one reference on the mkext. (setExecutable() does not 5055 * replace, it removes, or panics if asked to replace.) 5056 */ 5057 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 5058 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 5059 5060 if (extractedExecutable && extractedExecutable->getLength()) { 5061 if (!setExecutable(extractedExecutable.get())) { 5062 goto finish; 5063 } 5064 result = extractedExecutable.get(); 5065 } else { 5066 goto finish; 5067 } 5068 } 5069 5070 finish: 5071 #endif // CONFIG_KXLD 5072 return result; 5073 } 5074 5075 /********************************************************************* 5076 *********************************************************************/ 5077 bool 5078 OSKext::isInterface(void) 5079 { 5080 return flags.interface; 5081 } 5082 5083 /********************************************************************* 5084 *********************************************************************/ 5085 bool 5086 OSKext::isKernel(void) 5087 { 5088 return this == sKernelKext; 5089 } 5090 5091 /********************************************************************* 5092 *********************************************************************/ 5093 bool 5094 OSKext::isKernelComponent(void) 5095 { 5096 return flags.kernelComponent ? true : false; 5097 } 5098 5099 /********************************************************************* 5100 *********************************************************************/ 5101 bool 5102 OSKext::isExecutable(void) 5103 { 5104 return !isKernel() && !isInterface() && declaresExecutable(); 5105 } 5106 5107 /********************************************************************* 5108 *********************************************************************/ 5109 bool 5110 OSKext::isSpecialKernelBinary(void) 5111 { 5112 #if CONFIG_SPTM 5113 return (this->kmod_info) && 5114 ((this->kmod_info->id == kOSKextSPTMLoadTag) || 5115 (this->kmod_info->id == kOSKextTXMLoadTag)); 5116 #else 5117 return false; 5118 #endif 5119 } 5120 5121 /********************************************************************* 5122 * We might want to check this recursively for all dependencies, 5123 * since a subtree of dependencies could get loaded before we hit 5124 * a dependency that isn't safe-boot-loadable. 5125 * 5126 * xxx - Might want to return false if OSBundleEnableKextLogging or 5127 * OSBundleDebugLevel 5128 * or IOKitDebug is nonzero too (we used to do that, but I don't see 5129 * the point except it's usually development drivers, which might 5130 * cause panics on startup, that have those properties). Heh; could 5131 * use a "kx" boot-arg! 5132 *********************************************************************/ 5133 bool 5134 OSKext::isLoadableInSafeBoot(void) 5135 { 5136 bool result = false; 5137 OSString * required = NULL; // do not release 5138 5139 if (isKernel()) { 5140 result = true; 5141 goto finish; 5142 } 5143 5144 if (isDriverKit()) { 5145 result = true; 5146 goto finish; 5147 } 5148 5149 required = OSDynamicCast(OSString, 5150 getPropertyForHostArch(kOSBundleRequiredKey)); 5151 if (!required) { 5152 goto finish; 5153 } 5154 if (required->isEqualTo(kOSBundleRequiredRoot) || 5155 required->isEqualTo(kOSBundleRequiredLocalRoot) || 5156 required->isEqualTo(kOSBundleRequiredNetworkRoot) || 5157 required->isEqualTo(kOSBundleRequiredSafeBoot) || 5158 required->isEqualTo(kOSBundleRequiredConsole)) { 5159 result = true; 5160 } 5161 5162 finish: 5163 return result; 5164 } 5165 5166 /********************************************************************* 5167 *********************************************************************/ 5168 bool 5169 OSKext::isPrelinked(void) 5170 { 5171 return flags.prelinked ? true : false; 5172 } 5173 5174 /********************************************************************* 5175 *********************************************************************/ 5176 bool 5177 OSKext::isLoaded(void) 5178 { 5179 return flags.loaded ? true : false; 5180 } 5181 5182 /********************************************************************* 5183 *********************************************************************/ 5184 bool 5185 OSKext::isStarted(void) 5186 { 5187 return flags.started ? true : false; 5188 } 5189 5190 /********************************************************************* 5191 *********************************************************************/ 5192 bool 5193 OSKext::isCPPInitialized(void) 5194 { 5195 return flags.CPPInitialized; 5196 } 5197 5198 /********************************************************************* 5199 *********************************************************************/ 5200 void 5201 OSKext::setCPPInitialized(bool initialized) 5202 { 5203 flags.CPPInitialized = initialized; 5204 } 5205 5206 /********************************************************************* 5207 *********************************************************************/ 5208 uint32_t 5209 OSKext::getLoadTag(void) 5210 { 5211 return loadTag; 5212 } 5213 5214 /********************************************************************* 5215 *********************************************************************/ 5216 void 5217 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize) 5218 { 5219 if (linkedExecutable) { 5220 *loadSize = linkedExecutable->getLength(); 5221 5222 /* If we have a kmod_info struct, calculated the wired size 5223 * from that. Otherwise it's the full load size. 5224 */ 5225 if (kmod_info) { 5226 *wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size; 5227 } else { 5228 *wiredSize = *loadSize; 5229 } 5230 } else { 5231 *wiredSize = 0; 5232 *loadSize = 0; 5233 } 5234 } 5235 5236 /********************************************************************* 5237 *********************************************************************/ 5238 OSSharedPtr<OSData> 5239 OSKext::copyUUID(void) 5240 { 5241 OSSharedPtr<OSData> result; 5242 OSData * theExecutable = NULL; // do not release 5243 const kernel_mach_header_t * header; 5244 5245 /* An interface kext doesn't have a linked executable with an LC_UUID, 5246 * we create one when it's linked. 5247 */ 5248 if (interfaceUUID) { 5249 result = interfaceUUID; 5250 goto finish; 5251 } 5252 5253 if (flags.builtin || isInterface()) { 5254 return sKernelKext->copyUUID(); 5255 } 5256 5257 if (isDriverKit() && infoDict) { 5258 return driverKitUUID; 5259 } 5260 5261 /* For real kexts, try to get the UUID from the linked executable, 5262 * or if is hasn't been linked yet, the unrelocated executable. 5263 */ 5264 theExecutable = linkedExecutable.get(); 5265 if (!theExecutable) { 5266 theExecutable = getExecutable(); 5267 } 5268 5269 if (!theExecutable) { 5270 goto finish; 5271 } 5272 5273 header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy(); 5274 result = copyMachoUUID(header); 5275 5276 finish: 5277 return result; 5278 } 5279 5280 /********************************************************************* 5281 *********************************************************************/ 5282 OSSharedPtr<OSData> 5283 OSKext::copyTextUUID(void) 5284 { 5285 if (flags.builtin) { 5286 return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address); 5287 } 5288 return copyUUID(); 5289 } 5290 5291 /********************************************************************* 5292 *********************************************************************/ 5293 OSSharedPtr<OSData> 5294 OSKext::copyMachoUUID(const kernel_mach_header_t * header) 5295 { 5296 OSSharedPtr<OSData> result; 5297 const struct load_command * load_cmd = NULL; 5298 const struct uuid_command * uuid_cmd = NULL; 5299 uint32_t i; 5300 5301 load_cmd = (const struct load_command *)&header[1]; 5302 5303 if (header->magic != MH_MAGIC_KERNEL) { 5304 OSKextLog(NULL, 5305 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 5306 "%s: bad header %p", 5307 __func__, 5308 header); 5309 goto finish; 5310 } 5311 5312 for (i = 0; i < header->ncmds; i++) { 5313 if (load_cmd->cmd == LC_UUID) { 5314 uuid_cmd = (struct uuid_command *)load_cmd; 5315 result = OSData::withValue(uuid_cmd->uuid); 5316 goto finish; 5317 } 5318 load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize); 5319 } 5320 5321 finish: 5322 return result; 5323 } 5324 5325 void 5326 OSKext::setDriverKitUUID(OSData *uuid) 5327 { 5328 if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) { 5329 OSSafeReleaseNULL(uuid); 5330 } 5331 } 5332 5333 OSData * 5334 OSKext::getDextUniqueID(void) 5335 { 5336 if (isDriverKit() && dextUniqueID != NULL) { 5337 return dextUniqueID.get(); 5338 } 5339 5340 return NULL; 5341 } 5342 5343 /* 5344 * In case a DextUniqueID exists this function returns 5345 * an allocated char* with the hexadecimal represantition of 5346 * DextUniqueID. 5347 * The returned pinter needs to be freed with kfree_data, the 5348 * size of the allocated buffer is returned in size. 5349 */ 5350 static const char * 5351 getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size) 5352 { 5353 if (dextUniqueID != NULL) { 5354 char *s_buffer = NULL; 5355 unsigned int d_length = dextUniqueID->getLength(); 5356 /* 5357 * We are converting in hex, so for every byte we will have 5358 * 2 hex chars and one last \0. 5359 */ 5360 unsigned int s_length = d_length * 2 + 1; 5361 s_buffer = (char *) kalloc_data(s_length, Z_WAITOK_ZERO); 5362 5363 char *uid = (char*) dextUniqueID->getBytesNoCopy(); 5364 int cpos = 0; 5365 for (unsigned int i = 0; i < d_length && cpos < (s_length - 1); i++) { 5366 int ret = snprintf(s_buffer + cpos, s_length - cpos - 1, "%02X", uid[i]); 5367 if (ret <= 0) { 5368 break; 5369 } 5370 cpos += ret; 5371 } 5372 *size = s_length; 5373 5374 return s_buffer; 5375 } 5376 5377 return NULL; 5378 } 5379 5380 /* 5381 * Atomically swaps the olddext with newdext. 5382 * olddext will be unloaded, so it might be freed 5383 * after this call unless it was previously retained. 5384 * 5385 * If newdext is NULL, this unloads olddext and does not perform an upgrade 5386 */ 5387 void 5388 OSKext::replaceDextInternal(OSKext *olddext, OSKext *newdext) 5389 { 5390 OSReturn result; 5391 const OSSymbol * dextID = olddext->getIdentifier(); 5392 OSData * oldDextUniqueIdentifier = olddext->getDextUniqueID(); 5393 OSSharedPtr<OSArray> new_personalities; 5394 OSSharedPtr<OSString> kextIdentifier; 5395 __assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock); 5396 assert(lock_held); 5397 5398 // The old dext will be unloaded and release dextID, so we need to retain dextID here 5399 dextID->retain(); 5400 5401 if (newdext != NULL) { 5402 __assert_only bool eq = dextID->isEqualTo(newdext->getIdentifier()); 5403 assert(eq); 5404 } 5405 5406 if (newdext != NULL) { 5407 /* 5408 * Swap the catalog personalities. 5409 */ 5410 new_personalities = newdext->copyPersonalitiesArray(); 5411 olddext->updatePersonalitiesInCatalog(new_personalities.get()); 5412 } 5413 5414 if (NULL != oldDextUniqueIdentifier) { 5415 oldDextUniqueIdentifier->retain(); 5416 } 5417 5418 /* 5419 * Unload the dext. 5420 */ 5421 result = olddext->unload(); 5422 if (result != kOSReturnSuccess) { 5423 OSKextLog(NULL, 5424 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5425 "Cannot unload dext for upgrade %s: %d\n", 5426 dextID->getCStringNoCopy(), result); 5427 } 5428 5429 if (newdext != NULL) { 5430 /* 5431 * Swap the dexts on the OSKext dictionary. 5432 * This might free the dext. 5433 */ 5434 sKextsByID->setObject(dextID, newdext); 5435 } else { 5436 /* 5437 * Remove the old dext 5438 */ 5439 removeKext(olddext, true); 5440 } 5441 5442 /* 5443 * Inform userspace. 5444 */ 5445 if (newdext != NULL) { 5446 result = notifyDextUpgrade(OSDynamicCast(OSString, dextID), newdext->getDextUniqueID()); 5447 if (result != kOSReturnSuccess) { 5448 OSKextLog(NULL, 5449 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5450 "Cannot send upgrade notification for %s\n", 5451 dextID->getCStringNoCopy()); 5452 } 5453 } else { 5454 // notify dext removal 5455 queueKextNotification(kKextRequestPredicateUnloadNotification, 5456 OSDynamicCast(OSString, dextID), oldDextUniqueIdentifier); 5457 } 5458 5459 OSSafeReleaseNULL(dextID); 5460 OSSafeReleaseNULL(oldDextUniqueIdentifier); 5461 } 5462 5463 /* 5464 * To be called with sKextLock held. 5465 * NOTE: this could unload the olddext. 5466 */ 5467 bool 5468 OSKext::upgradeDext(OSKext *olddext, OSKext *newdext) 5469 { 5470 const char * dextIDCS = newdext->getIdentifierCString(); 5471 __assert_only bool old_isDext = olddext->isDriverKit(); 5472 __assert_only bool new_isDext = newdext->isDriverKit(); 5473 __assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock); 5474 5475 assert(old_isDext && new_isDext); 5476 assert(lock_held); 5477 5478 /* 5479 * New dext and old dext have the same ID. 5480 * We use this ID as key on the OSKext 5481 * dictionarys/arrays. 5482 */ 5483 const OSSymbol * dextID = newdext->getIdentifier(); 5484 __assert_only bool eq = dextID->isEqualTo(olddext->getIdentifier()); 5485 assert(eq); 5486 5487 /* 5488 * Set this OSKect as to update. 5489 * Note that this flags will never be removed once set. 5490 * When a OSKext is marked, it will be substitued by a new 5491 * OSKext, and every subsystem having a reference on this 5492 * OSKext need to know they have check if they can use 5493 * this OSKext or look for a new one. 5494 */ 5495 olddext->flags.dextToReplace = 1; 5496 5497 /* 5498 * Check if the current OSKext has any 5499 * userspace processes launched. 5500 * In this case we cannot upgrade and we have to 5501 * delay the upgrade until all processes 5502 * are done. 5503 */ 5504 if (olddext->dextLaunchedCount == 0) { 5505 /* 5506 * Be sure that if there are no launched dexts, no 5507 * pending upgrades exist. 5508 * This is an error if it happens, as the decrement 5509 * should have removed the dext from sDriverKitToUpgradeByID 5510 * in case it reached 0. 5511 */ 5512 OSObject *pending_upgdare = sDriverKitToUpgradeByID->getObject(dextID); 5513 if (pending_upgdare != NULL) { 5514 OSKextLog(NULL, 5515 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5516 "Pending upgrade found for %s but dextLaunchedCount is 0!\n", 5517 dextIDCS); 5518 goto out; 5519 } 5520 5521 replaceDextInternal(olddext, newdext); 5522 return true; 5523 } 5524 5525 out: 5526 5527 /* 5528 * Delay the upgrade. 5529 * Make the new dext available in sDriverKitToUpgradeByID. 5530 * In case there was already a pending upgrade, this will 5531 * overwrite it. 5532 */ 5533 sDriverKitToUpgradeByID->setObject(dextID, newdext); 5534 return false; 5535 } 5536 5537 /* 5538 * To be called with sKextLock held. 5539 * NOTE: this could unload the dext. 5540 */ 5541 bool 5542 OSKext::removeDext(OSKext *dext) 5543 { 5544 __assert_only bool dext_isDext = dext->isDriverKit(); 5545 __assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock); 5546 IOReturn result; 5547 5548 assert(dext_isDext); 5549 assert(lock_held); 5550 5551 /* 5552 * Set this OSKext to be unloaded when all running instances exit. 5553 */ 5554 dext->flags.dextToReplace = 1; 5555 5556 result = gIOCatalogue->terminateDriversForModule( 5557 dext->getIdentifierCString(), /* unload */ false, /* asynchronous */ true); 5558 if (result != kOSReturnSuccess) { 5559 OSKextLog(dext, 5560 kOSKextLogErrorLevel | 5561 kOSKextLogKextBookkeepingFlag, 5562 "%s services failed to terminate - 0x%x.", 5563 dext->getIdentifierCString(), result); 5564 } 5565 5566 dext->removePersonalitiesFromCatalog(); 5567 sDriverKitToUpgradeByID->removeObject(dext->getIdentifier()); 5568 5569 /* 5570 * Check if the current OSKext has any 5571 * userspace processes launched. 5572 * In this case we cannot unload and we have to 5573 * delay the unload until all processes 5574 * are done. 5575 */ 5576 if (dext->dextLaunchedCount == 0) { 5577 replaceDextInternal(dext, NULL); 5578 return true; 5579 } 5580 5581 return false; 5582 } 5583 5584 bool 5585 OSKext::incrementDextLaunchCount(OSKext *dext, OSData *dextUniqueIDToMatch) 5586 { 5587 bool ret = false; 5588 __assert_only bool isDext = dext->isDriverKit(); 5589 assert(isDext); 5590 5591 const char * dextIDCS = dext->getIdentifierCString(); 5592 OSData *myDextUniqueID = dext->getDextUniqueID(); 5593 5594 if (!myDextUniqueID || !dextUniqueIDToMatch) { 5595 OSKextLog(dext, 5596 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5597 "Cannot find dext UniqueID for %s, cannot increment dext launches\n", 5598 dextIDCS); 5599 return ret; 5600 } 5601 5602 unsigned int dextUniqueIDCStringSize = 0, dextUniqueIDToMatchCStringSize = 0; 5603 const char *dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize); 5604 const char *dextUniqueIDToMatchCString = getDextUniqueIDCString(dextUniqueIDToMatch, &dextUniqueIDToMatchCStringSize); 5605 assert(dextUniqueIDCString != NULL); 5606 assert(dextUniqueIDToMatchCString != NULL); 5607 5608 IORecursiveLockLock(sKextLock); 5609 5610 /* 5611 * Check that the dext we are referencing is the same 5612 * looked for the match. 5613 */ 5614 if (myDextUniqueID->isEqualTo(dextUniqueIDToMatch)) { 5615 if (dext->flags.dextToReplace == 0 || dext->dextLaunchedCount > 0) { 5616 if (dext->dextLaunchedCount == kOSKextMaxDextLaunchedCount) { 5617 OSKextLog(dext, 5618 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5619 "Too many dexts launched for %s UniqueID %s\n", 5620 dextIDCS, dextUniqueIDCString); 5621 } else { 5622 dext->dextLaunchedCount++; 5623 ret = true; 5624 5625 OSKextLog(dext, 5626 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5627 "New dext launched for %s UniqueID %s", 5628 dextIDCS, dextUniqueIDCString); 5629 } 5630 } else { 5631 OSKextLog(dext, 5632 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5633 "Dext %s UniqueID %s requires update, cannot launch a new dext\n", 5634 dextIDCS, dextUniqueIDCString); 5635 } 5636 } else { 5637 OSKextLog(dext, 5638 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5639 "Dext %s: UniqueID %s does not match UniqueID looked for %s, cannot launch a new dext\n", 5640 dextIDCS, dextUniqueIDCString, dextUniqueIDToMatchCString); 5641 } 5642 5643 IORecursiveLockUnlock(sKextLock); 5644 5645 if (dextUniqueIDCString != NULL) { 5646 kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize); 5647 } 5648 if (dextUniqueIDToMatchCString != NULL) { 5649 kfree_data(dextUniqueIDToMatchCString, dextUniqueIDToMatchCStringSize); 5650 } 5651 return ret; 5652 } 5653 5654 bool 5655 OSKext::decrementDextLaunchCount(OSString *bundleID) 5656 { 5657 bool ret = false; 5658 const char * dextIDCS; 5659 OSData *myDextUniqueID; 5660 unsigned int dextUniqueIDCStringSize = 0; 5661 const char * dextUniqueIDCString = NULL; 5662 OSKext* dext = NULL; 5663 5664 if (!bundleID) { 5665 return ret; 5666 } 5667 dextIDCS = bundleID->getCStringNoCopy(); 5668 5669 IORecursiveLockLock(sKextLock); 5670 5671 /* 5672 * Look for the dext with the bundle it. This 5673 * call is triggered only if a previous increment was 5674 * performed. It means that the dext could have not 5675 * been upgraded as its dextLaunchedCount was at least 1. 5676 * Because of this it still needs to be available 5677 * in sKextsByID. 5678 */ 5679 dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIDCS)); 5680 if (!dext || !dext->isDriverKit()) { 5681 OSKextLog(NULL, 5682 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5683 "Cannot find dext for %s, cannot decrement dext launches\n", 5684 dextIDCS); 5685 5686 goto out_locked; 5687 } 5688 5689 myDextUniqueID = dext->getDextUniqueID(); 5690 if (!myDextUniqueID) { 5691 OSKextLog(dext, 5692 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5693 "Cannot find dext UniqueID for %s, cannot decrement dext launches\n", 5694 dextIDCS); 5695 5696 goto out_locked; 5697 } 5698 dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize); 5699 assert(dextUniqueIDCString != NULL); 5700 5701 if (dext->dextLaunchedCount == 0) { 5702 OSKextLog(dext, 5703 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5704 "Over decrementing dext launch for %s UniqueID %s\n", 5705 dextIDCS, dextUniqueIDCString); 5706 5707 goto out_locked; 5708 } 5709 5710 dext->dextLaunchedCount--; 5711 5712 OSKextLog(dext, 5713 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5714 "Dext terminated for %s UniqueID %s", 5715 dextIDCS, dextUniqueIDCString); 5716 5717 if (dext->dextLaunchedCount == 0 && dext->flags.dextToReplace == 1) { 5718 /* 5719 * Find the upgraded dext. 5720 */ 5721 OSKext *newdext = OSDynamicCast(OSKext, sDriverKitToUpgradeByID->getObject(dextIDCS)); 5722 if (newdext) { 5723 OSKextLog(dext, 5724 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5725 "Dext upgrade for %s UniqueID %s", 5726 dextIDCS, dextUniqueIDCString); 5727 replaceDextInternal(dext, newdext); 5728 /* NOTE dext could have been freed past this point */ 5729 5730 sDriverKitToUpgradeByID->removeObject(dextIDCS); 5731 } else { 5732 OSKextLog(dext, 5733 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5734 "Dext unload for %s UniqueID %s", 5735 dextIDCS, dextUniqueIDCString); 5736 replaceDextInternal(dext, NULL); 5737 } 5738 5739 ret = true; 5740 } 5741 out_locked: 5742 IORecursiveLockUnlock(sKextLock); 5743 5744 if (dextUniqueIDCString != NULL) { 5745 kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize); 5746 } 5747 5748 return ret; 5749 } 5750 5751 /********************************************************************* 5752 *********************************************************************/ 5753 #if defined (__arm__) 5754 #include <arm/arch.h> 5755 #endif 5756 5757 #if defined (__x86_64__) 5758 #define ARCHNAME "x86_64" 5759 #elif defined (__arm64__) 5760 #define ARCHNAME "arm64" 5761 #elif defined (__arm__) 5762 5763 #if defined (__ARM_ARCH_7S__) 5764 #define ARCHNAME "armv7s" 5765 #elif defined (__ARM_ARCH_7F__) 5766 #define ARCHNAME "armv7f" 5767 #elif defined (__ARM_ARCH_7K__) 5768 #define ARCHNAME "armv7k" 5769 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */ 5770 #define ARCHNAME "armv7" 5771 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */ 5772 #define ARCHNAME "armv6" 5773 #endif 5774 5775 #elif defined (__arm64__) 5776 #define ARCHNAME "arm64" 5777 #else 5778 #error architecture not supported 5779 #endif 5780 5781 #define ARCH_SEPARATOR_CHAR '_' 5782 5783 static char * 5784 makeHostArchKey(const char * key, size_t * keySizeOut) 5785 { 5786 char * result = NULL; 5787 size_t keyLength = strlen(key); 5788 size_t keySize; 5789 5790 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'. 5791 */ 5792 keySize = 1 + 1 + keyLength + strlen(ARCHNAME); 5793 result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 5794 5795 if (!result) { 5796 goto finish; 5797 } 5798 strlcpy(result, key, keySize); 5799 result[keyLength++] = ARCH_SEPARATOR_CHAR; 5800 result[keyLength] = '\0'; 5801 strlcat(result, ARCHNAME, keySize); 5802 *keySizeOut = keySize; 5803 5804 finish: 5805 return result; 5806 } 5807 5808 /********************************************************************* 5809 *********************************************************************/ 5810 OSObject * 5811 OSKext::getPropertyForHostArch(const char * key) 5812 { 5813 OSObject * result = NULL;// do not release 5814 size_t hostArchKeySize = 0; 5815 char * hostArchKey = NULL;// must kfree 5816 5817 if (!key || !infoDict) { 5818 goto finish; 5819 } 5820 5821 /* Some properties are not allowed to be arch-variant: 5822 * - Any CFBundle... property. 5823 * - OSBundleIsInterface. 5824 * - OSKernelResource. 5825 */ 5826 if (STRING_HAS_PREFIX(key, "OS") || 5827 STRING_HAS_PREFIX(key, "IO")) { 5828 hostArchKey = makeHostArchKey(key, &hostArchKeySize); 5829 if (!hostArchKey) { 5830 OSKextLog(/* kext (this isn't about a kext) */ NULL, 5831 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 5832 "Allocation failure."); 5833 goto finish; 5834 } 5835 result = infoDict->getObject(hostArchKey); 5836 } 5837 5838 if (!result) { 5839 result = infoDict->getObject(key); 5840 } 5841 5842 finish: 5843 if (hostArchKey) { 5844 kfree_data(hostArchKey, hostArchKeySize); 5845 } 5846 return result; 5847 } 5848 5849 #if PRAGMA_MARK 5850 #pragma mark Load/Start/Stop/Unload 5851 #endif 5852 5853 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n') 5854 5855 /********************************************************************* 5856 * sExcludeListByID is a dictionary with keys / values of: 5857 * key = bundleID string of kext we will not allow to load 5858 * value = version string(s) of the kext that is to be denied loading. 5859 * The version strings can be comma delimited. For example if kext 5860 * com.foocompany.fookext has two versions that we want to deny 5861 * loading then the version strings might look like: 5862 * 1.0.0, 1.0.1 5863 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will 5864 * not load the kext. 5865 * 5866 * Value may also be in the form of "LE 2.0.0" (version numbers 5867 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version 5868 * number less than 2.0.0 will not load) 5869 * 5870 * NOTE - we cannot use the characters "<=" or "<" because we have code 5871 * that serializes plists and treats '<' as a special character. 5872 *********************************************************************/ 5873 bool 5874 OSKext::isInExcludeList(void) 5875 { 5876 OSString * versionString = NULL; // do not release 5877 char * versionCString = NULL; // do not free 5878 size_t i; 5879 boolean_t wantLessThan = false; 5880 boolean_t wantLessThanEqualTo = false; 5881 boolean_t isInExcludeList = true; 5882 char myBuffer[32]; 5883 5884 IORecursiveLockLock(sKextLock); 5885 5886 if (!sExcludeListByID) { 5887 isInExcludeList = false; 5888 } else { 5889 /* look up by bundleID in our exclude list and if found get version 5890 * string (or strings) that we will not allow to load 5891 */ 5892 versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get())); 5893 if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) { 5894 isInExcludeList = false; 5895 } 5896 } 5897 5898 IORecursiveLockUnlock(sKextLock); 5899 5900 if (!isInExcludeList) { 5901 return false; 5902 } 5903 5904 /* parse version strings */ 5905 versionCString = (char *) versionString->getCStringNoCopy(); 5906 5907 /* look for "LT" or "LE" form of version string, must be in first two 5908 * positions. 5909 */ 5910 if (*versionCString == 'L' && *(versionCString + 1) == 'T') { 5911 wantLessThan = true; 5912 versionCString += 2; 5913 } else if (*versionCString == 'L' && *(versionCString + 1) == 'E') { 5914 wantLessThanEqualTo = true; 5915 versionCString += 2; 5916 } 5917 5918 for (i = 0; *versionCString != 0x00; versionCString++) { 5919 /* skip whitespace */ 5920 if (isWhiteSpace(*versionCString)) { 5921 continue; 5922 } 5923 5924 /* peek ahead for version string separator or null terminator */ 5925 if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) { 5926 /* OK, we have a version string */ 5927 myBuffer[i++] = *versionCString; 5928 myBuffer[i] = 0x00; 5929 5930 OSKextVersion excludeVers; 5931 excludeVers = OSKextParseVersionString(myBuffer); 5932 5933 if (wantLessThanEqualTo) { 5934 if (version <= excludeVers) { 5935 return true; 5936 } 5937 } else if (wantLessThan) { 5938 if (version < excludeVers) { 5939 return true; 5940 } 5941 } else if (version == excludeVers) { 5942 return true; 5943 } 5944 5945 /* reset for the next (if any) version string */ 5946 i = 0; 5947 wantLessThan = false; 5948 wantLessThanEqualTo = false; 5949 } else { 5950 /* save valid version character */ 5951 myBuffer[i++] = *versionCString; 5952 5953 /* make sure bogus version string doesn't overrun local buffer */ 5954 if (i >= sizeof(myBuffer)) { 5955 break; 5956 } 5957 } 5958 } 5959 5960 return false; 5961 } 5962 5963 /********************************************************************* 5964 * sNonLoadableKextsByID is a dictionary with keys / values of: 5965 * key = bundleID string of kext we will not allow to load 5966 * value = boolean (true == loadable, false == not loadable) 5967 * 5968 * Only kexts which are in the AuxKC will be marked as "not loadble," 5969 * i.e., the value for the kext's bundleID will be false. All kexts in 5970 * the primary and system KCs will always be marked as "loadable." 5971 * 5972 * This list ultimately comes from kexts which have been uninstalled 5973 * in user space by deleting the kext from disk, but which have not 5974 * yet been removed from the AuxKC. Because the user could choose to 5975 * re-install the exact same version of the kext, we need to keep 5976 * a dictionary of boolean values so that user space only needs to 5977 * keep a simple list of "uninstalled" or "missing" bundles. When 5978 * a bundle is re-installed, the iokit daemon can use the 5979 * AucKCBundleAvailable predicate to set the individual kext's 5980 * availability to true. 5981 *********************************************************************/ 5982 bool 5983 OSKext::isLoadable(void) 5984 { 5985 bool isLoadable = true; 5986 5987 if (kc_type != KCKindAuxiliary) { 5988 /* this filtering only applies to kexts in the auxkc */ 5989 return true; 5990 } 5991 5992 IORecursiveLockLock(sKextLock); 5993 5994 if (sNonLoadableKextsByID) { 5995 /* look up by bundleID in our exclude list and if found get version 5996 * string (or strings) that we will not allow to load 5997 */ 5998 OSBoolean *loadableVal; 5999 loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get())); 6000 if (loadableVal && !loadableVal->getValue()) { 6001 isLoadable = false; 6002 } 6003 } 6004 IORecursiveLockUnlock(sKextLock); 6005 6006 return isLoadable; 6007 } 6008 6009 /********************************************************************* 6010 *********************************************************************/ 6011 /* static */ 6012 OSReturn 6013 OSKext::loadKextWithIdentifier( 6014 const char * kextIdentifierCString, 6015 Boolean allowDeferFlag, 6016 Boolean delayAutounloadFlag, 6017 OSKextExcludeLevel startOpt, 6018 OSKextExcludeLevel startMatchingOpt, 6019 OSArray * personalityNames) 6020 { 6021 OSReturn result = kOSReturnError; 6022 OSSharedPtr<OSString> kextIdentifier; 6023 6024 kextIdentifier = OSString::withCString(kextIdentifierCString); 6025 if (!kextIdentifier) { 6026 result = kOSKextReturnNoMemory; 6027 goto finish; 6028 } 6029 result = OSKext::loadKextWithIdentifier(kextIdentifier.get(), 6030 NULL /* kextRef */, 6031 allowDeferFlag, delayAutounloadFlag, 6032 startOpt, startMatchingOpt, personalityNames); 6033 6034 finish: 6035 return result; 6036 } 6037 6038 OSReturn 6039 OSKext::loadKextWithIdentifier( 6040 OSString * kextIdentifier, 6041 OSSharedPtr<OSObject> &kextRef, 6042 Boolean allowDeferFlag, 6043 Boolean delayAutounloadFlag, 6044 OSKextExcludeLevel startOpt, 6045 OSKextExcludeLevel startMatchingOpt, 6046 OSArray * personalityNames) 6047 { 6048 OSObject * kextRefRaw = NULL; 6049 OSReturn result; 6050 6051 result = loadKextWithIdentifier(kextIdentifier, 6052 &kextRefRaw, 6053 allowDeferFlag, 6054 delayAutounloadFlag, 6055 startOpt, 6056 startMatchingOpt, 6057 personalityNames); 6058 if ((kOSReturnSuccess == result) && kextRefRaw) { 6059 kextRef.reset(kextRefRaw, OSNoRetain); 6060 } 6061 return result; 6062 } 6063 6064 /********************************************************************* 6065 *********************************************************************/ 6066 OSReturn 6067 OSKext::loadKextWithIdentifier( 6068 OSString * kextIdentifier, 6069 OSObject ** kextRef, 6070 Boolean allowDeferFlag, 6071 Boolean delayAutounloadFlag, 6072 OSKextExcludeLevel startOpt, 6073 OSKextExcludeLevel startMatchingOpt, 6074 OSArray * personalityNames) 6075 { 6076 OSReturn result = kOSReturnError; 6077 OSReturn pingResult = kOSReturnError; 6078 OSKext * theKext = NULL; // do not release 6079 OSSharedPtr<OSDictionary> loadRequest; 6080 OSSharedPtr<const OSSymbol> kextIdentifierSymbol; 6081 6082 if (kextRef) { 6083 *kextRef = NULL; 6084 } 6085 6086 IORecursiveLockLock(sKextLock); 6087 6088 if (!kextIdentifier) { 6089 result = kOSKextReturnInvalidArgument; 6090 goto finish; 6091 } 6092 6093 OSKext::recordIdentifierRequest(kextIdentifier); 6094 6095 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 6096 if (!theKext) { 6097 if (!allowDeferFlag) { 6098 OSKextLog(/* kext */ NULL, 6099 kOSKextLogErrorLevel | 6100 kOSKextLogLoadFlag, 6101 "Can't load kext %s - not found.", 6102 kextIdentifier->getCStringNoCopy()); 6103 goto finish; 6104 } 6105 6106 if (!sKernelRequestsEnabled) { 6107 OSKextLog(theKext, 6108 kOSKextLogErrorLevel | 6109 kOSKextLogLoadFlag, 6110 "Can't load kext %s - requests to user space are disabled.", 6111 kextIdentifier->getCStringNoCopy()); 6112 result = kOSKextReturnDisabled; 6113 goto finish; 6114 } 6115 6116 /* Create a new request unless one is already sitting 6117 * in sKernelRequests for this bundle identifier 6118 */ 6119 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 6120 if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) { 6121 result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad, 6122 loadRequest); 6123 if (result != kOSReturnSuccess) { 6124 goto finish; 6125 } 6126 if (!_OSKextSetRequestArgument(loadRequest.get(), 6127 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 6128 result = kOSKextReturnNoMemory; 6129 goto finish; 6130 } 6131 if (!sKernelRequests->setObject(loadRequest.get())) { 6132 result = kOSKextReturnNoMemory; 6133 goto finish; 6134 } 6135 6136 if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) { 6137 result = kOSKextReturnNoMemory; 6138 goto finish; 6139 } 6140 6141 OSKextLog(theKext, 6142 kOSKextLogDebugLevel | 6143 kOSKextLogLoadFlag, 6144 "Kext %s not found; queued load request to user space.", 6145 kextIdentifier->getCStringNoCopy()); 6146 } 6147 6148 pingResult = OSKext::pingIOKitDaemon(); 6149 if (pingResult == kOSKextReturnDisabled) { 6150 OSKextLog(/* kext */ NULL, 6151 ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) | 6152 kOSKextLogLoadFlag, 6153 "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.", 6154 kextIdentifier->getCStringNoCopy()); 6155 } 6156 6157 result = kOSKextReturnDeferred; 6158 goto finish; 6159 } 6160 6161 result = theKext->load(startOpt, startMatchingOpt, personalityNames); 6162 6163 if (result != kOSReturnSuccess) { 6164 OSKextLog(theKext, 6165 kOSKextLogErrorLevel | 6166 kOSKextLogLoadFlag, 6167 "Failed to load kext %s (error 0x%x).", 6168 kextIdentifier->getCStringNoCopy(), (int)result); 6169 6170 if (theKext->kc_type == KCKindUnknown) { 6171 OSKext::removeKext(theKext, 6172 /* terminateService/removePersonalities */ true); 6173 } 6174 goto finish; 6175 } 6176 6177 if (delayAutounloadFlag) { 6178 OSKextLog(theKext, 6179 kOSKextLogProgressLevel | 6180 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 6181 "Setting delayed autounload for %s.", 6182 kextIdentifier->getCStringNoCopy()); 6183 theKext->flags.delayAutounload = 1; 6184 } 6185 6186 finish: 6187 if ((kOSReturnSuccess == result) && kextRef) { 6188 *kextRef = theKext; 6189 theKext->matchingRefCount++; 6190 theKext->retain(); 6191 } 6192 6193 IORecursiveLockUnlock(sKextLock); 6194 6195 return result; 6196 } 6197 6198 /********************************************************************* 6199 *********************************************************************/ 6200 /* static */ 6201 OSReturn 6202 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict) 6203 { 6204 OSReturn result = kOSReturnError; 6205 6206 OSBoolean *delayAutounloadBool = NULL; // do not release 6207 OSNumber *startKextExcludeNum = NULL; // do not release 6208 OSNumber *startMatchingExcludeNum = NULL; // do not release 6209 OSArray *personalityNames = NULL; // do not release 6210 6211 /* 6212 * Default values for these options: 6213 * regular autounload behavior 6214 * start the kext 6215 * send all personalities to the catalog 6216 */ 6217 Boolean delayAutounload = false; 6218 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 6219 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone; 6220 6221 IORecursiveLockLock(sKextLock); 6222 6223 OSKextLog(/* kext */ NULL, 6224 kOSKextLogDebugLevel | 6225 kOSKextLogIPCFlag, 6226 "Received kext KC load request from user space."); 6227 6228 /* Regardless of processing, the fact that we have gotten here means some 6229 * user-space program is up and talking to us, so we'll switch our kext 6230 * registration to reflect that. 6231 */ 6232 if (!sUserLoadsActive) { 6233 OSKextLog(/* kext */ NULL, 6234 kOSKextLogProgressLevel | 6235 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 6236 "Switching to late startup (user-space) kext loading policy."); 6237 sUserLoadsActive = true; 6238 } 6239 6240 delayAutounloadBool = OSDynamicCast(OSBoolean, 6241 _OSKextGetRequestArgument(requestDict, 6242 kKextRequestArgumentDelayAutounloadKey)); 6243 startKextExcludeNum = OSDynamicCast(OSNumber, 6244 _OSKextGetRequestArgument(requestDict, 6245 kKextRequestArgumentStartExcludeKey)); 6246 startMatchingExcludeNum = OSDynamicCast(OSNumber, 6247 _OSKextGetRequestArgument(requestDict, 6248 kKextRequestArgumentStartMatchingExcludeKey)); 6249 personalityNames = OSDynamicCast(OSArray, 6250 _OSKextGetRequestArgument(requestDict, 6251 kKextRequestArgumentPersonalityNamesKey)); 6252 6253 if (delayAutounloadBool) { 6254 delayAutounload = delayAutounloadBool->getValue(); 6255 } 6256 if (startKextExcludeNum) { 6257 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 6258 } 6259 if (startMatchingExcludeNum) { 6260 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 6261 } 6262 6263 OSKextLog(/* kext */ NULL, 6264 kOSKextLogProgressLevel | 6265 kOSKextLogIPCFlag, 6266 "Received request from user space to load KC kext %s.", 6267 theKext->getIdentifierCString()); 6268 6269 /* this could be in the Auxiliary KC, so record the load request */ 6270 OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier())); 6271 6272 /* 6273 * Load the kext 6274 */ 6275 result = theKext->load(startKextExcludeLevel, 6276 startMatchingExcludeLevel, personalityNames); 6277 6278 if (result != kOSReturnSuccess) { 6279 OSKextLog(theKext, 6280 kOSKextLogErrorLevel | 6281 kOSKextLogLoadFlag, 6282 "Failed to load kext %s (error 0x%x).", 6283 theKext->getIdentifierCString(), (int)result); 6284 6285 OSKext::removeKext(theKext, 6286 /* terminateService/removePersonalities */ true); 6287 goto finish; 6288 } else { 6289 OSKextLog(theKext, 6290 kOSKextLogProgressLevel | 6291 kOSKextLogLoadFlag, 6292 "Kext %s Loaded successfully from %s KC", 6293 theKext->getIdentifierCString(), theKext->getKCTypeString()); 6294 } 6295 6296 if (delayAutounload) { 6297 OSKextLog(theKext, 6298 kOSKextLogProgressLevel | 6299 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 6300 "Setting delayed autounload for %s.", 6301 theKext->getIdentifierCString()); 6302 theKext->flags.delayAutounload = 1; 6303 } 6304 6305 finish: 6306 IORecursiveLockUnlock(sKextLock); 6307 6308 return result; 6309 } 6310 6311 /********************************************************************* 6312 *********************************************************************/ 6313 /* static */ 6314 OSReturn 6315 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict) 6316 { 6317 OSReturn result = kOSReturnError; 6318 OSDictionary *anInfoDict = NULL; // do not release 6319 6320 anInfoDict = OSDynamicCast(OSDictionary, 6321 _OSKextGetRequestArgument(requestDict, 6322 kKextRequestArgumentCodelessInfoKey)); 6323 if (anInfoDict == NULL) { 6324 OSKextLog(/* kext */ NULL, 6325 kOSKextLogErrorLevel | 6326 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 6327 "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.", 6328 kextIdentifier->getCStringNoCopy()); 6329 return kOSKextReturnInvalidArgument; 6330 } 6331 6332 IORecursiveLockLock(sKextLock); 6333 6334 OSKextLog(/* kext */ NULL, 6335 kOSKextLogProgressLevel | 6336 kOSKextLogIPCFlag, 6337 "Received request from user space to load codeless kext %s.", 6338 kextIdentifier->getCStringNoCopy()); 6339 6340 { 6341 // instantiate a new kext, and don't hold a reference 6342 // (the kext subsystem will hold one implicitly) 6343 OSKextInitResult ret; 6344 OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict, &ret); 6345 if (!newKext) { 6346 /* 6347 * We might have failed to create a new OSKext 6348 * because the old one should still be used. 6349 * Check if that is the case. 6350 */ 6351 if (ret != kOSKextInitFailure) { 6352 result = kOSReturnSuccess; 6353 goto finish; 6354 } 6355 OSKextLog(/* kext */ NULL, 6356 kOSKextLogErrorLevel | 6357 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 6358 "Could not instantiate codeless kext."); 6359 result = kOSKextReturnNotLoadable; 6360 goto finish; 6361 } 6362 if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) { 6363 OSKextLog(/* kext */ NULL, 6364 kOSKextLogErrorLevel | 6365 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 6366 "Codeless kext identifiers don't match '%s' != '%s'", 6367 kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString()); 6368 6369 OSKext::removeKext(newKext.get(), false); 6370 result = kOSKextReturnInvalidArgument; 6371 goto finish; 6372 } 6373 6374 /* Record the request for the codeless kext */ 6375 OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier())); 6376 6377 result = kOSReturnSuccess; 6378 /* Send the kext's personalities to the IOCatalog. This is an explicit load. */ 6379 result = newKext->sendPersonalitiesToCatalog(true, NULL); 6380 } 6381 6382 finish: 6383 IORecursiveLockUnlock(sKextLock); 6384 6385 return result; 6386 } 6387 6388 /********************************************************************* 6389 *********************************************************************/ 6390 /* static */ 6391 void 6392 OSKext::dropMatchingReferences( 6393 OSSet * kexts) 6394 { 6395 IORecursiveLockLock(sKextLock); 6396 kexts->iterateObjects(^bool (OSObject * obj) { 6397 OSKext * thisKext = OSDynamicCast(OSKext, obj); 6398 if (!thisKext) { 6399 return false; 6400 } 6401 thisKext->matchingRefCount--; 6402 return false; 6403 }); 6404 IORecursiveLockUnlock(sKextLock); 6405 } 6406 6407 /********************************************************************* 6408 *********************************************************************/ 6409 /* static */ 6410 void 6411 OSKext::recordIdentifierRequest( 6412 OSString * kextIdentifier) 6413 { 6414 OSSharedPtr<const OSSymbol> kextIdentifierSymbol; 6415 bool fail = false; 6416 6417 if (!sAllKextLoadIdentifiers || !kextIdentifier) { 6418 goto finish; 6419 } 6420 6421 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 6422 if (!kextIdentifierSymbol) { 6423 // xxx - this is really a basic alloc failure 6424 fail = true; 6425 goto finish; 6426 } 6427 6428 IORecursiveLockLock(sKextLock); 6429 if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) { 6430 if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) { 6431 fail = true; 6432 } else { 6433 // xxx - need to find a way to associate this whole func w/the kext 6434 OSKextLog(/* kext */ NULL, 6435 // xxx - check level 6436 kOSKextLogStepLevel | 6437 kOSKextLogArchiveFlag, 6438 "Recorded kext %s as a candidate for inclusion in prelinked kernel.", 6439 kextIdentifier->getCStringNoCopy()); 6440 } 6441 } 6442 IORecursiveLockUnlock(sKextLock); 6443 6444 finish: 6445 6446 if (fail) { 6447 OSKextLog(/* kext */ NULL, 6448 kOSKextLogErrorLevel | 6449 kOSKextLogArchiveFlag, 6450 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.", 6451 kextIdentifier->getCStringNoCopy()); 6452 } 6453 return; 6454 } 6455 6456 /********************************************************************* 6457 *********************************************************************/ 6458 OSReturn 6459 OSKext::load( 6460 OSKextExcludeLevel startOpt, 6461 OSKextExcludeLevel startMatchingOpt, 6462 OSArray * personalityNames) 6463 { 6464 OSReturn result = kOSReturnError; 6465 OSKextExcludeLevel dependenciesStartOpt = startOpt; 6466 OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt; 6467 unsigned int i, count; 6468 Boolean alreadyLoaded = false; 6469 OSKext * lastLoadedKext = NULL; // do not release 6470 6471 if (isInExcludeList()) { 6472 OSKextLog(this, 6473 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | 6474 kOSKextLogLoadFlag, 6475 "Kext %s is in exclude list, not loadable", 6476 getIdentifierCString()); 6477 6478 result = kOSKextReturnNotLoadable; 6479 goto finish; 6480 } 6481 if (!isLoadable()) { 6482 OSKextLog(this, 6483 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | 6484 kOSKextLogLoadFlag, 6485 "Kext %s is not loadable", 6486 getIdentifierCString()); 6487 6488 result = kOSKextReturnNotLoadable; 6489 goto finish; 6490 } 6491 6492 if (isLoaded()) { 6493 alreadyLoaded = true; 6494 result = kOSReturnSuccess; 6495 6496 OSKextLog(this, 6497 kOSKextLogDebugLevel | 6498 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 6499 "Kext %s is already loaded.", 6500 getIdentifierCString()); 6501 goto loaded; 6502 } 6503 6504 #if CONFIG_MACF 6505 /* 6506 * On kxld and on embedded, only call into the MAC hook when on a 6507 * user thread, for access control over userspace kextloads. 6508 * 6509 * On non-kxld systems, additionally check the MAC hook for kexts in 6510 * the Pageable and Aux KCs, regardless of whether we are on a user 6511 * thread or not. This means on Apple silicon devices that the MAC 6512 * hook will only be useful to block 3rd party kexts loaded via 6513 * matching, and any kexts loaded from userspace kextloads. 6514 * 6515 * Note that this should _not_ be called on kexts loaded from the 6516 * kernel bootstrap thread as the kernel proc's cred struct is not 6517 * yet initialized! This won't happen on macOS because all the kexts 6518 * in the BootKC are self-contained and their kc_type = KCKindPrimary. 6519 */ 6520 if (current_task() != kernel_task 6521 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD 6522 || (kc_type != KCKindPrimary && kc_type != KCKindUnknown) 6523 #endif 6524 ) { 6525 int macCheckResult = 0; 6526 kauth_cred_t cred = NULL; 6527 6528 cred = kauth_cred_get_with_ref(); 6529 macCheckResult = mac_kext_check_load(cred, getIdentifierCString()); 6530 kauth_cred_unref(&cred); 6531 6532 if (macCheckResult != 0) { 6533 result = kOSReturnError; 6534 OSKextLog(this, 6535 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 6536 "Failed to load kext %s (MAC policy error 0x%x).", 6537 getIdentifierCString(), macCheckResult); 6538 goto finish; 6539 } 6540 } 6541 #endif /* CONFIG_MACF */ 6542 6543 if (!sLoadEnabled) { 6544 OSKextLog(this, 6545 kOSKextLogErrorLevel | 6546 kOSKextLogLoadFlag, 6547 "Kext loading is disabled (attempt to load kext %s).", 6548 getIdentifierCString()); 6549 result = kOSKextReturnDisabled; 6550 goto finish; 6551 } 6552 6553 /* If we've pushed the next available load tag to the invalid value, 6554 * we can't load any more kexts. 6555 */ 6556 if (sNextLoadTag == kOSKextInvalidLoadTag) { 6557 OSKextLog(this, 6558 kOSKextLogErrorLevel | 6559 kOSKextLogLoadFlag, 6560 "Can't load kext %s - no more load tags to assign.", 6561 getIdentifierCString()); 6562 result = kOSKextReturnNoResources; 6563 goto finish; 6564 } 6565 6566 /* This is a bit of a hack, because we shouldn't be handling 6567 * personalities within the load function. 6568 */ 6569 if (!declaresExecutable()) { 6570 /* There is a special case where a non-executable kext can be loaded: the 6571 * AppleKextExcludeList. Detect that special kext by bundle identifier and 6572 * load its metadata into the global data structures, if appropriate 6573 */ 6574 if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) { 6575 boolean_t updated = updateExcludeList(infoDict.get()); 6576 if (updated) { 6577 OSKextLog(this, 6578 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 6579 "KextExcludeList was updated to version: %lld", sExcludeListVersion); 6580 } 6581 } 6582 6583 if (isDriverKit()) { 6584 if (loadTag == 0) { 6585 sLoadedDriverKitKexts->setObject(this); 6586 loadTag = sNextLoadTag++; 6587 } 6588 } 6589 result = kOSReturnSuccess; 6590 goto loaded; 6591 } 6592 6593 /* Are we in safe boot? 6594 */ 6595 if (sSafeBoot && !isLoadableInSafeBoot()) { 6596 OSKextLog(this, 6597 kOSKextLogErrorLevel | 6598 kOSKextLogLoadFlag, 6599 "Can't load kext %s - not loadable during safe boot.", 6600 getIdentifierCString()); 6601 result = kOSKextReturnBootLevel; 6602 goto finish; 6603 } 6604 6605 OSKextLog(this, 6606 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 6607 "Loading kext %s.", 6608 getIdentifierCString()); 6609 6610 #if !VM_MAPPED_KEXTS 6611 if (isPrelinked() == false) { 6612 OSKextLog(this, 6613 kOSKextLogErrorLevel | 6614 kOSKextLogLoadFlag, 6615 "Can't load kext %s - not in a kext collection.", 6616 getIdentifierCString()); 6617 result = kOSKextReturnDisabled; 6618 goto finish; 6619 } 6620 #endif /* defined(__x86_64__) */ 6621 6622 #if CONFIG_KXLD 6623 if (!sKxldContext) { 6624 kern_return_t kxldResult; 6625 kxldResult = kxld_create_context(&sKxldContext, &kern_allocate, 6626 &kxld_log_callback, /* Flags */ (KXLDFlags) 0, 6627 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0); 6628 if (kxldResult) { 6629 OSKextLog(this, 6630 kOSKextLogErrorLevel | 6631 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 6632 "Can't load kext %s - failed to create link context.", 6633 getIdentifierCString()); 6634 result = kOSKextReturnNoMemory; 6635 goto finish; 6636 } 6637 } 6638 #endif // CONFIG_KXLD 6639 6640 /* We only need to resolve dependencies once for the whole graph, but 6641 * resolveDependencies will just return if there's no work to do, so it's 6642 * safe to call it more than once. 6643 */ 6644 if (!resolveDependencies()) { 6645 // xxx - check resolveDependencies() for log msg 6646 OSKextLog(this, 6647 kOSKextLogErrorLevel | 6648 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 6649 "Can't load kext %s - failed to resolve library dependencies.", 6650 getIdentifierCString()); 6651 result = kOSKextReturnDependencies; 6652 goto finish; 6653 } 6654 6655 /* If we are excluding just the kext being loaded now (and not its 6656 * dependencies), drop the exclusion level to none so dependencies 6657 * start and/or add their personalities. 6658 */ 6659 if (dependenciesStartOpt == kOSKextExcludeKext) { 6660 dependenciesStartOpt = kOSKextExcludeNone; 6661 } 6662 6663 if (dependenciesStartMatchingOpt == kOSKextExcludeKext) { 6664 dependenciesStartMatchingOpt = kOSKextExcludeNone; 6665 } 6666 6667 /* Load the dependencies, recursively. 6668 */ 6669 count = getNumDependencies(); 6670 for (i = 0; i < count; i++) { 6671 OSKext * dependency = OSDynamicCast(OSKext, 6672 dependencies->getObject(i)); 6673 if (dependency == NULL) { 6674 OSKextLog(this, 6675 kOSKextLogErrorLevel | 6676 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 6677 "Internal error loading kext %s; dependency disappeared.", 6678 getIdentifierCString()); 6679 result = kOSKextReturnInternalError; 6680 goto finish; 6681 } 6682 6683 /* Dependencies must be started accorting to the opt, 6684 * but not given the personality names of the main kext. 6685 */ 6686 result = dependency->load(dependenciesStartOpt, 6687 dependenciesStartMatchingOpt, 6688 /* personalityNames */ NULL); 6689 if (result != KERN_SUCCESS) { 6690 OSKextLog(this, 6691 kOSKextLogErrorLevel | 6692 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 6693 "Dependency %s of kext %s failed to load.", 6694 dependency->getIdentifierCString(), 6695 getIdentifierCString()); 6696 6697 OSKext::removeKext(dependency, 6698 /* terminateService/removePersonalities */ true); 6699 result = kOSKextReturnDependencyLoadError; 6700 6701 goto finish; 6702 } 6703 } 6704 6705 result = loadExecutable(); 6706 if (result != KERN_SUCCESS) { 6707 goto finish; 6708 } 6709 6710 pendingPgoHead.next = &pendingPgoHead; 6711 pendingPgoHead.prev = &pendingPgoHead; 6712 6713 // The kernel PRNG is not initialized when the first kext is 6714 // loaded, so use early random 6715 uuid_generate_early_random(instance_uuid); 6716 account = IOMallocType(OSKextAccount); 6717 6718 account->loadTag = kmod_info->id; 6719 account->site.refcount = 0; 6720 account->site.flags = VM_TAG_KMOD; 6721 6722 #if DEVELOPMENT || DEBUG 6723 /* Setup the task reference group. */ 6724 (void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name), 6725 "task_%s", getIdentifierCString()); 6726 account->task_refgrp.grp_name = account->task_refgrp_name; 6727 account->task_refgrp.grp_parent = &task_external_refgrp; 6728 account->task_refgrp.grp_flags = OS_REFGRP_F_ALWAYS_ENABLED; 6729 os_ref_log_init(&account->task_refgrp); 6730 #endif /* DEVELOPMENT || DEBUG */ 6731 6732 account->kext = this; 6733 if (gIOSurfaceIdentifier == bundleID) { 6734 vm_tag_alloc(&account->site); 6735 gIOSurfaceTag = account->site.tag; 6736 } 6737 6738 flags.loaded = true; 6739 6740 /* Add the kext to the list of loaded kexts and update the kmod_info 6741 * struct to point to that of the last loaded kext (which is the way 6742 * it's always been done, though I'd rather do them in order now). 6743 */ 6744 lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 6745 sLoadedKexts->setObject(this); 6746 6747 /* Keep the kernel itself out of the kmod list. 6748 */ 6749 if (lastLoadedKext->isKernel()) { 6750 lastLoadedKext = NULL; 6751 } 6752 6753 if (lastLoadedKext) { 6754 kmod_info->next = lastLoadedKext->kmod_info; 6755 } 6756 6757 notifyKextLoadObservers(this, kmod_info); 6758 6759 /* Make the global kmod list point at the just-loaded kext. Note that the 6760 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard, 6761 * although we do report it in kextstat these days by using the newer 6762 * OSArray of loaded kexts, which does contain it. 6763 * 6764 * (The OSKext object representing the kernel doesn't even have a kmod_info 6765 * struct, though I suppose we could stick a pointer to it from the 6766 * static struct in OSRuntime.cpp.) 6767 */ 6768 kmod = kmod_info; 6769 6770 /* Save the list of loaded kexts in case we panic. 6771 */ 6772 OSKext::saveLoadedKextPanicList(); 6773 6774 if (isExecutable()) { 6775 OSKext::updateLoadedKextSummaries(); 6776 savePanicString(/* isLoading */ true); 6777 6778 #if CONFIG_DTRACE 6779 registerWithDTrace(); 6780 #else 6781 jettisonLinkeditSegment(); 6782 #endif /* CONFIG_DTRACE */ 6783 6784 #if !VM_MAPPED_KEXTS 6785 /* If there is a page (or more) worth of padding after the end 6786 * of the last data section but before the end of the data segment 6787 * then free it in the same manner the LinkeditSegment is freed 6788 */ 6789 jettisonDATASegmentPadding(); 6790 #endif 6791 } 6792 6793 loaded: 6794 if (isExecutable() && !flags.started) { 6795 if (startOpt == kOSKextExcludeNone) { 6796 result = start(); 6797 if (result != kOSReturnSuccess) { 6798 OSKextLog(this, 6799 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 6800 "Kext %s start failed (result 0x%x).", 6801 getIdentifierCString(), result); 6802 result = kOSKextReturnStartStopError; 6803 } 6804 } 6805 } 6806 6807 /* If not excluding matching, send the personalities to the kernel. 6808 * This never affects the result of the load operation. 6809 * This is a bit of a hack, because we shouldn't be handling 6810 * personalities within the load function. 6811 */ 6812 if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) { 6813 result = sendPersonalitiesToCatalog(true, personalityNames); 6814 } 6815 6816 finish: 6817 6818 if (result != kOSReturnSuccess) { 6819 OSKextLog(this, 6820 kOSKextLogErrorLevel | 6821 kOSKextLogLoadFlag, 6822 "Kext %s failed to load (0x%x).", 6823 getIdentifierCString(), (int)result); 6824 } else if (!alreadyLoaded) { 6825 OSKextLog(this, 6826 kOSKextLogProgressLevel | 6827 kOSKextLogLoadFlag, 6828 "Kext %s loaded.", 6829 getIdentifierCString()); 6830 6831 queueKextNotification(kKextRequestPredicateLoadNotification, 6832 OSDynamicCast(OSString, bundleID.get()), getDextUniqueID()); 6833 } 6834 return result; 6835 } 6836 6837 #if CONFIG_KXLD 6838 /********************************************************************* 6839 * 6840 *********************************************************************/ 6841 static char * 6842 strdup(const char * string) 6843 { 6844 char * result = NULL; 6845 size_t size; 6846 6847 if (!string) { 6848 goto finish; 6849 } 6850 6851 size = 1 + strlen(string); 6852 result = (char *)kalloc_data_tag(size, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 6853 if (!result) { 6854 goto finish; 6855 } 6856 6857 memcpy(result, string, size); 6858 6859 finish: 6860 return result; 6861 } 6862 #endif // CONFIG_KXLD 6863 6864 /********************************************************************* 6865 * 6866 *********************************************************************/ 6867 6868 kernel_section_t * 6869 OSKext::lookupSection(const char *segname, const char *secname) 6870 { 6871 kernel_section_t * found_section = NULL; 6872 kernel_mach_header_t * mh = NULL; 6873 kernel_segment_command_t * seg = NULL; 6874 kernel_section_t * sec = NULL; 6875 6876 if (!linkedExecutable) { 6877 return NULL; 6878 } 6879 6880 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 6881 6882 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 6883 if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) { 6884 continue; 6885 } 6886 6887 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 6888 if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) { 6889 found_section = sec; 6890 goto out; 6891 } 6892 } 6893 } 6894 6895 out: 6896 return found_section; 6897 } 6898 6899 /********************************************************************* 6900 * 6901 *********************************************************************/ 6902 6903 OSReturn 6904 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides) 6905 { 6906 OSReturn result = kOSKextReturnBadData; 6907 kernel_mach_header_t * mh = NULL; 6908 kernel_segment_command_t * seg = NULL; 6909 kernel_segment_command_t * linkeditSeg = NULL; 6910 kernel_section_t * sec = NULL; 6911 char * linkeditBase = NULL; 6912 bool haveLinkeditBase = false; 6913 char * relocBase = NULL; 6914 bool haveRelocBase = false; 6915 struct dysymtab_command * dysymtab = NULL; 6916 struct linkedit_data_command * segmentSplitInfo = NULL; 6917 struct symtab_command * symtab = NULL; 6918 kernel_nlist_t * sym = NULL; 6919 struct relocation_info * reloc = NULL; 6920 uint32_t i = 0; 6921 int reloc_size; 6922 vm_offset_t new_kextsize; 6923 kc_format format = KCFormatUnknown; 6924 6925 if (linkedExecutable == NULL || flags.builtin) { 6926 result = kOSReturnSuccess; 6927 goto finish; 6928 } 6929 6930 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 6931 if (kernel_mach_header_is_in_fileset(mh)) { 6932 // kexts in filesets are slid as part of collection sliding 6933 result = kOSReturnSuccess; 6934 goto finish; 6935 } 6936 6937 segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO); 6938 6939 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 6940 if (!seg->vmaddr) { 6941 continue; 6942 } 6943 6944 seg->vmaddr = ml_static_slide(seg->vmaddr); 6945 6946 #if KASLR_KEXT_DEBUG 6947 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n", 6948 seg->segname, 6949 (unsigned long)ml_static_unslide(seg->vmaddr), 6950 (unsigned long)seg->vmaddr); 6951 #endif 6952 6953 if (!haveRelocBase) { 6954 relocBase = (char *) seg->vmaddr; 6955 haveRelocBase = true; 6956 } 6957 if (!strcmp(seg->segname, "__LINKEDIT")) { 6958 linkeditBase = (char *) seg->vmaddr - seg->fileoff; 6959 haveLinkeditBase = true; 6960 linkeditSeg = seg; 6961 } 6962 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 6963 sec->addr = ml_static_slide(sec->addr); 6964 6965 #if KASLR_KEXT_DEBUG 6966 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n", 6967 sec->sectname, 6968 (unsigned long)ml_static_unslide(sec->addr), 6969 (unsigned long)sec->addr); 6970 #endif 6971 } 6972 } 6973 6974 dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB); 6975 6976 symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB); 6977 6978 if (symtab != NULL && doCoalescedSlides == false) { 6979 /* Some pseudo-kexts have symbol tables without segments. 6980 * Ignore them. */ 6981 if (symtab->nsyms > 0 && haveLinkeditBase) { 6982 sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff); 6983 for (i = 0; i < symtab->nsyms; i++) { 6984 if (sym[i].n_type & N_STAB) { 6985 continue; 6986 } 6987 sym[i].n_value = ml_static_slide(sym[i].n_value); 6988 6989 #if KASLR_KEXT_DEBUG 6990 #define MAX_SYMS_TO_LOG 5 6991 if (i < MAX_SYMS_TO_LOG) { 6992 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n", 6993 (unsigned long)ml_static_unslide(sym[i].n_value), 6994 (unsigned long)sym[i].n_value); 6995 } 6996 #endif 6997 } 6998 } 6999 } 7000 7001 if (dysymtab != NULL && doCoalescedSlides == false) { 7002 if (dysymtab->nextrel > 0) { 7003 OSKextLog(this, 7004 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 7005 kOSKextLogLinkFlag, 7006 "Sliding kext %s: External relocations found.", 7007 getIdentifierCString()); 7008 goto finish; 7009 } 7010 7011 if (dysymtab->nlocrel > 0) { 7012 if (!haveLinkeditBase) { 7013 OSKextLog(this, 7014 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 7015 kOSKextLogLinkFlag, 7016 "Sliding kext %s: No linkedit segment.", 7017 getIdentifierCString()); 7018 goto finish; 7019 } 7020 7021 if (!haveRelocBase) { 7022 OSKextLog(this, 7023 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 7024 kOSKextLogLinkFlag, 7025 #if __x86_64__ 7026 "Sliding kext %s: No writable segments.", 7027 #else 7028 "Sliding kext %s: No segments.", 7029 #endif 7030 getIdentifierCString()); 7031 goto finish; 7032 } 7033 7034 reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff); 7035 reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info); 7036 7037 for (i = 0; i < dysymtab->nlocrel; i++) { 7038 if (reloc[i].r_extern != 0 7039 || reloc[i].r_type != 0 7040 || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2) 7041 ) { 7042 OSKextLog(this, 7043 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 7044 kOSKextLogLinkFlag, 7045 "Sliding kext %s: Unexpected relocation found.", 7046 getIdentifierCString()); 7047 goto finish; 7048 } 7049 if (reloc[i].r_pcrel != 0) { 7050 continue; 7051 } 7052 uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address); 7053 *relocAddr = ml_static_slide(*relocAddr); 7054 7055 #if KASLR_KEXT_DEBUG 7056 #define MAX_DYSYMS_TO_LOG 5 7057 if (i < MAX_DYSYMS_TO_LOG) { 7058 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n", 7059 (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))), 7060 (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address))); 7061 } 7062 #endif 7063 } 7064 7065 /* We should free these relocations, not just delete the reference to them. 7066 * <rdar://problem/10535549> Free relocations from PIE kexts. 7067 * 7068 * For now, we do not free LINKEDIT for kexts with split segments. 7069 */ 7070 new_kextsize = round_page(kmod_info->size - reloc_size); 7071 if (new_kextsize > UINT_MAX) { 7072 OSKextLog(this, 7073 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 7074 kOSKextLogLinkFlag, 7075 "Kext %s: new kext size is too large.", 7076 getIdentifierCString()); 7077 goto finish; 7078 } 7079 if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) { 7080 vm_offset_t endofkext = kmod_info->address + kmod_info->size; 7081 vm_offset_t new_endofkext = kmod_info->address + new_kextsize; 7082 vm_offset_t endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size); 7083 size_t bytes_remaining = endofkext - endofrelocInfo; 7084 OSSharedPtr<OSData> new_osdata; 7085 7086 /* fix up symbol offsets if they are after the dsymtab local relocs */ 7087 if (symtab) { 7088 if (dysymtab->locreloff < symtab->symoff) { 7089 symtab->symoff -= reloc_size; 7090 } 7091 if (dysymtab->locreloff < symtab->stroff) { 7092 symtab->stroff -= reloc_size; 7093 } 7094 } 7095 if (dysymtab->locreloff < dysymtab->extreloff) { 7096 dysymtab->extreloff -= reloc_size; 7097 } 7098 7099 /* move data behind reloc info down to new offset */ 7100 if (endofrelocInfo < endofkext) { 7101 memcpy(reloc, (void *)endofrelocInfo, bytes_remaining); 7102 } 7103 7104 /* Create a new OSData for the smaller kext object and reflect 7105 * new linkedit segment size. 7106 */ 7107 linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size); 7108 linkeditSeg->filesize = linkeditSeg->vmsize; 7109 7110 new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize); 7111 if (new_osdata) { 7112 /* Fix up kmod info and linkedExecutable. 7113 */ 7114 kmod_info->size = new_kextsize; 7115 /* 7116 * Fileset KCs are mapped as a whole by iBoot. 7117 * Individual kext executables should not be unmapped 7118 * by xnu. 7119 * Doing so may result in panics like rdar://85419651 7120 */ 7121 if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) { 7122 new_osdata->setDeallocFunction(NULL); 7123 } else { // Not from a Fileset KC 7124 #if VM_MAPPED_KEXTS 7125 new_osdata->setDeallocFunction(osdata_kext_free); 7126 #else 7127 new_osdata->setDeallocFunction(osdata_phys_free); 7128 #endif 7129 } 7130 linkedExecutable->setDeallocFunction(NULL); 7131 linkedExecutable = os::move(new_osdata); 7132 7133 #if VM_MAPPED_KEXTS 7134 kext_free(new_endofkext, (endofkext - new_endofkext)); 7135 #else 7136 ml_static_mfree(new_endofkext, (endofkext - new_endofkext)); 7137 #endif 7138 } 7139 } 7140 dysymtab->nlocrel = 0; 7141 dysymtab->locreloff = 0; 7142 } 7143 } 7144 7145 result = kOSReturnSuccess; 7146 finish: 7147 return result; 7148 } 7149 7150 /********************************************************************* 7151 * called only by load() 7152 *********************************************************************/ 7153 OSReturn 7154 OSKext::loadExecutable() 7155 { 7156 OSReturn result = kOSReturnError; 7157 OSSharedPtr<OSArray> linkDependencies; 7158 uint32_t num_kmod_refs = 0; 7159 OSData * theExecutable = NULL; // do not release 7160 OSString * versString = NULL; // do not release 7161 const char * versCString = NULL; // do not free 7162 const char * string = NULL; // do not free 7163 7164 #if CONFIG_KXLD 7165 unsigned int i; 7166 uint32_t numDirectDependencies = 0; 7167 kern_return_t kxldResult; 7168 KXLDDependency * kxlddeps = NULL; // must kfree 7169 uint32_t num_kxlddeps = 0; 7170 struct mach_header ** kxldHeaderPtr = NULL; // do not free 7171 struct mach_header * kxld_header = NULL; // xxx - need to free here? 7172 #endif // CONFIG_KXLD 7173 7174 /* We need the version string for a variety of bits below. 7175 */ 7176 versString = OSDynamicCast(OSString, 7177 getPropertyForHostArch(kCFBundleVersionKey)); 7178 if (!versString) { 7179 goto finish; 7180 } 7181 versCString = versString->getCStringNoCopy(); 7182 7183 if (isKernelComponent()) { 7184 if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) { 7185 if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) { 7186 OSKextLog(this, 7187 kOSKextLogErrorLevel | 7188 kOSKextLogLoadFlag, 7189 "Kernel component %s has incorrect version %s; " 7190 "expected %s.", 7191 getIdentifierCString(), 7192 versCString, KERNEL6_VERSION); 7193 result = kOSKextReturnInternalError; 7194 goto finish; 7195 } else if (strcmp(versCString, osrelease)) { 7196 OSKextLog(this, 7197 kOSKextLogErrorLevel | 7198 kOSKextLogLoadFlag, 7199 "Kernel component %s has incorrect version %s; " 7200 "expected %s.", 7201 getIdentifierCString(), 7202 versCString, osrelease); 7203 result = kOSKextReturnInternalError; 7204 goto finish; 7205 } 7206 } 7207 } 7208 7209 #if defined(__x86_64__) || defined(__i386__) 7210 if (flags.resetSegmentsFromVnode) { 7211 /* Fixup the chains and slide the mach headers */ 7212 kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address; 7213 7214 if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) { 7215 result = kOSKextReturnValidation; 7216 goto finish; 7217 } 7218 } 7219 #endif //(__x86_64__) || defined(__i386__) 7220 7221 if (isPrelinked()) { 7222 goto register_kmod; 7223 } 7224 7225 /* <rdar://problem/21444003> all callers must be entitled */ 7226 if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) { 7227 OSKextLog(this, 7228 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 7229 "Not entitled to link kext '%s'", 7230 getIdentifierCString()); 7231 result = kOSKextReturnNotPrivileged; 7232 goto finish; 7233 } 7234 7235 theExecutable = getExecutable(); 7236 if (!theExecutable) { 7237 if (declaresExecutable()) { 7238 OSKextLog(this, 7239 kOSKextLogErrorLevel | 7240 kOSKextLogLoadFlag, 7241 "Can't load kext %s - executable is missing.", 7242 getIdentifierCString()); 7243 result = kOSKextReturnValidation; 7244 goto finish; 7245 } 7246 goto register_kmod; 7247 } 7248 7249 if (isInterface()) { 7250 OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable); 7251 if (executableCopy) { 7252 setLinkedExecutable(executableCopy.get()); 7253 } 7254 goto register_kmod; 7255 } 7256 7257 #if CONFIG_KXLD 7258 numDirectDependencies = getNumDependencies(); 7259 7260 if (flags.hasBleedthrough) { 7261 linkDependencies = dependencies; 7262 } else { 7263 linkDependencies = OSArray::withArray(dependencies.get()); 7264 if (!linkDependencies) { 7265 OSKextLog(this, 7266 kOSKextLogErrorLevel | 7267 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 7268 "Can't allocate link dependencies to load kext %s.", 7269 getIdentifierCString()); 7270 goto finish; 7271 } 7272 7273 for (i = 0; i < numDirectDependencies; ++i) { 7274 OSKext * dependencyKext = OSDynamicCast(OSKext, 7275 dependencies->getObject(i)); 7276 dependencyKext->addBleedthroughDependencies(linkDependencies.get()); 7277 } 7278 } 7279 7280 num_kxlddeps = linkDependencies->getCount(); 7281 if (!num_kxlddeps) { 7282 OSKextLog(this, 7283 kOSKextLogErrorLevel | 7284 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 7285 "Can't load kext %s - it has no library dependencies.", 7286 getIdentifierCString()); 7287 goto finish; 7288 } 7289 7290 kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 7291 if (!kxlddeps) { 7292 OSKextLog(this, 7293 kOSKextLogErrorLevel | 7294 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 7295 "Can't allocate link context to load kext %s.", 7296 getIdentifierCString()); 7297 goto finish; 7298 } 7299 bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps)); 7300 7301 for (i = 0; i < num_kxlddeps; ++i) { 7302 OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i)); 7303 7304 if (dependency->isInterface()) { 7305 OSKext *interfaceTargetKext = NULL; //do not release 7306 OSData * interfaceTarget = NULL; //do not release 7307 7308 if (dependency->isKernelComponent()) { 7309 interfaceTargetKext = sKernelKext; 7310 interfaceTarget = sKernelKext->linkedExecutable.get(); 7311 } else { 7312 interfaceTargetKext = OSDynamicCast(OSKext, 7313 dependency->dependencies->getObject(0)); 7314 7315 interfaceTarget = interfaceTargetKext->linkedExecutable.get(); 7316 } 7317 7318 if (!interfaceTarget) { 7319 // panic? 7320 goto finish; 7321 } 7322 7323 /* The names set here aren't actually logged yet <rdar://problem/7941514>, 7324 * it will be useful to have them in the debugger. 7325 * strdup() failing isn't critical right here so we don't check that. 7326 */ 7327 kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy(); 7328 kxlddeps[i].kext_size = interfaceTarget->getLength(); 7329 kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString()); 7330 7331 if (dependency->linkedExecutable != NULL) { 7332 kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 7333 kxlddeps[i].interface_size = dependency->linkedExecutable->getLength(); 7334 } else { 7335 kxlddeps[i].interface = (u_char *) NULL; 7336 kxlddeps[i].interface_size = 0; 7337 } 7338 kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString()); 7339 } else { 7340 kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 7341 kxlddeps[i].kext_size = dependency->linkedExecutable->getLength(); 7342 kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString()); 7343 } 7344 7345 kxlddeps[i].is_direct_dependency = (i < numDirectDependencies); 7346 } 7347 7348 kxldHeaderPtr = &kxld_header; 7349 7350 #if DEBUG 7351 OSKextLog(this, 7352 kOSKextLogExplicitLevel | 7353 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 7354 "Kext %s - calling kxld_link_file:\n" 7355 " kxld_context: %p\n" 7356 " executable: %p executable_length: %d\n" 7357 " user_data: %p\n" 7358 " kxld_dependencies: %p num_dependencies: %d\n" 7359 " kxld_header_ptr: %p kmod_info_ptr: %p\n", 7360 getIdentifierCString(), sKxldContext, 7361 theExecutable->getBytesNoCopy(), theExecutable->getLength(), 7362 this, kxlddeps, num_kxlddeps, 7363 kxldHeaderPtr, &kmod_info); 7364 #endif 7365 7366 /* After this call, the linkedExecutable instance variable 7367 * should exist. 7368 */ 7369 kxldResult = kxld_link_file(sKxldContext, 7370 (u_char *)theExecutable->getBytesNoCopy(), 7371 theExecutable->getLength(), 7372 getIdentifierCString(), this, kxlddeps, num_kxlddeps, 7373 (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info); 7374 7375 if (kxldResult != KERN_SUCCESS) { 7376 // xxx - add kxldResult here? 7377 OSKextLog(this, 7378 kOSKextLogErrorLevel | 7379 kOSKextLogLoadFlag, 7380 "Can't load kext %s - link failed.", 7381 getIdentifierCString()); 7382 result = kOSKextReturnLinkError; 7383 goto finish; 7384 } 7385 7386 /* We've written data & instructions into kernel memory, so flush the data 7387 * cache and invalidate the instruction cache. 7388 * I/D caches are coherent on x86 7389 */ 7390 #if !defined(__i386__) && !defined(__x86_64__) 7391 flush_dcache(kmod_info->address, kmod_info->size, false); 7392 invalidate_icache(kmod_info->address, kmod_info->size, false); 7393 #endif 7394 7395 #else // !CONFIG_KXLD 7396 OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag, 7397 "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString()); 7398 result = kOSKextReturnLinkError; 7399 goto finish; 7400 #endif // CONFIG_KXLD 7401 7402 register_kmod: 7403 7404 if (isInterface()) { 7405 /* Whip up a fake kmod_info entry for the interface kext. 7406 */ 7407 kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO)); 7408 if (!kmod_info) { 7409 result = KERN_MEMORY_ERROR; 7410 goto finish; 7411 } 7412 7413 /* A pseudokext has almost nothing in its kmod_info struct. 7414 */ 7415 kmod_info->info_version = KMOD_INFO_VERSION; 7416 7417 /* An interface kext doesn't have a linkedExecutable, so save a 7418 * copy of the UUID out of the original executable via copyUUID() 7419 * while we still have the original executable. 7420 */ 7421 interfaceUUID = copyUUID(); 7422 } 7423 7424 kmod_info->id = loadTag = sNextLoadTag++; 7425 kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid). 7426 7427 /* Stamp the bundle ID and version from the OSKext over anything 7428 * resident inside the kmod_info. 7429 */ 7430 string = getIdentifierCString(); 7431 strlcpy(kmod_info->name, string, sizeof(kmod_info->name)); 7432 7433 string = versCString; 7434 strlcpy(kmod_info->version, string, sizeof(kmod_info->version)); 7435 7436 /* Add the dependencies' kmod_info structs as kmod_references. 7437 */ 7438 num_kmod_refs = getNumDependencies(); 7439 if (num_kmod_refs) { 7440 kmod_info->reference_list = kalloc_type_tag(kmod_reference_t, 7441 num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT); 7442 if (!kmod_info->reference_list) { 7443 result = KERN_MEMORY_ERROR; 7444 goto finish; 7445 } 7446 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 7447 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 7448 OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex)); 7449 ref->info = refKext->kmod_info; 7450 ref->info->reference_count++; 7451 7452 if (refIndex + 1 < num_kmod_refs) { 7453 ref->next = kmod_info->reference_list + refIndex + 1; 7454 } 7455 } 7456 } 7457 7458 if (kmod_info->hdr_size > UINT32_MAX) { 7459 OSKextLog(this, 7460 kOSKextLogErrorLevel | 7461 kOSKextLogLoadFlag, 7462 #if __LP64__ 7463 "Kext %s header size is too large (%lu > UINT32_MAX).", 7464 #else 7465 "Kext %s header size is too large (%u > UINT32_MAX).", 7466 #endif 7467 kmod_info->name, 7468 kmod_info->hdr_size); 7469 result = KERN_FAILURE; 7470 goto finish; 7471 } 7472 7473 if (kmod_info->size > UINT32_MAX) { 7474 OSKextLog(this, 7475 kOSKextLogErrorLevel | 7476 kOSKextLogLoadFlag, 7477 #if __LP64__ 7478 "Kext %s size is too large (%lu > UINT32_MAX).", 7479 #else 7480 "Kext %s size is too large (%u > UINT32_MAX).", 7481 #endif 7482 kmod_info->name, 7483 kmod_info->size); 7484 result = KERN_FAILURE; 7485 goto finish; 7486 } 7487 7488 if (!isInterface() && linkedExecutable) { 7489 OSKextLog(this, 7490 kOSKextLogProgressLevel | 7491 kOSKextLogLoadFlag, 7492 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).", 7493 kmod_info->name, 7494 (unsigned)kmod_info->size / PAGE_SIZE, 7495 (unsigned long)ml_static_unslide(kmod_info->address), 7496 (unsigned)kmod_info->id); 7497 } 7498 7499 /* VM protections and wiring for the Aux KC are done at collection loading time */ 7500 if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) { 7501 /* if prelinked and primary KC, VM protections are already set */ 7502 result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true); 7503 if (result != KERN_SUCCESS) { 7504 goto finish; 7505 } 7506 } 7507 7508 #if KASAN 7509 if (linkedExecutable) { 7510 kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), 7511 linkedExecutable->getLength(), getIdentifierCString()); 7512 } 7513 #else 7514 if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) { 7515 OSKextLog(this, 7516 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 7517 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n", 7518 getIdentifierCString() 7519 ); 7520 result = KERN_FAILURE; 7521 goto finish; 7522 } 7523 #endif 7524 7525 result = kOSReturnSuccess; 7526 7527 finish: 7528 7529 #if CONFIG_KXLD 7530 /* Clear up locally allocated dependency info. 7531 */ 7532 for (i = 0; i < num_kxlddeps; ++i) { 7533 size_t size; 7534 7535 if (kxlddeps[i].kext_name) { 7536 size = 1 + strlen(kxlddeps[i].kext_name); 7537 kfree_data(kxlddeps[i].kext_name, size); 7538 } 7539 if (kxlddeps[i].interface_name) { 7540 size = 1 + strlen(kxlddeps[i].interface_name); 7541 kfree_data(kxlddeps[i].interface_name, size); 7542 } 7543 } 7544 if (kxlddeps) { 7545 kfree_type(KXLDDependency, num_kxlddeps, kxlddeps); 7546 } 7547 #endif // CONFIG_KXLD 7548 7549 /* We no longer need the unrelocated executable (which the linker 7550 * has altered anyhow). 7551 */ 7552 setExecutable(NULL); 7553 7554 if (result != kOSReturnSuccess) { 7555 OSKextLog(this, 7556 kOSKextLogErrorLevel | 7557 kOSKextLogLoadFlag, 7558 "Failed to load executable for kext %s.", 7559 getIdentifierCString()); 7560 7561 if (kmod_info && kmod_info->reference_list) { 7562 kfree_type(kmod_reference_t, num_kmod_refs, 7563 kmod_info->reference_list); 7564 } 7565 if (isInterface()) { 7566 kfree_type(kmod_info_t, kmod_info); 7567 kmod_info = NULL; 7568 } 7569 if (kc_type == KCKindUnknown) { 7570 kmod_info = NULL; 7571 if (linkedExecutable) { 7572 linkedExecutable.reset(); 7573 } 7574 } 7575 } 7576 7577 return result; 7578 } 7579 7580 /* static */ 7581 void 7582 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh) 7583 { 7584 kernel_segment_command_t *linkeditseg = NULL; 7585 7586 linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT); 7587 if (linkeditseg == NULL) { 7588 panic("FileSet booted with no Linkedit segment"); 7589 } 7590 7591 #if VM_MAPPED_KEXTS 7592 /* BootKC on x86_64 is not vm mapped */ 7593 ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize); 7594 7595 OSKextLog(/* kext */ NULL, 7596 kOSKextLogProgressLevel | 7597 kOSKextLogGeneralFlag, 7598 "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu", 7599 linkeditseg->vmaddr, linkeditseg->vmsize); 7600 #else 7601 /* BootKC on arm64 is not vm mapped, but is slid */ 7602 #if !CONFIG_SPTM 7603 vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase)); 7604 #else 7605 vm_offset_t linkedit_vmaddr = linkeditseg->vmaddr; 7606 #endif 7607 7608 ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize); 7609 7610 OSKextLog(/* kext */ NULL, 7611 kOSKextLogProgressLevel | 7612 kOSKextLogGeneralFlag, 7613 "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu", 7614 (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize); 7615 #endif /* VM_MAPPED_KEXTS */ 7616 } 7617 7618 /********************************************************************* 7619 * The linkedit segment is used by the kext linker for dependency 7620 * resolution, and by dtrace for probe initialization. We can free it 7621 * for non-library kexts, since no kexts depend on non-library kexts 7622 * by definition, once dtrace has been initialized. 7623 *********************************************************************/ 7624 void 7625 OSKext::jettisonLinkeditSegment(void) 7626 { 7627 kernel_mach_header_t * machhdr = (kernel_mach_header_t *)kmod_info->address; 7628 kernel_segment_command_t * linkedit = NULL; 7629 vm_offset_t start; 7630 vm_size_t linkeditsize, kextsize; 7631 OSSharedPtr<OSData> data; 7632 kc_format format = KCFormatUnknown; 7633 7634 if (isInFileset()) { 7635 return; 7636 } 7637 7638 #if NO_KEXTD 7639 /* We can free symbol tables for all embedded kexts because we don't 7640 * support runtime kext linking. 7641 */ 7642 if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 7643 #else 7644 if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 7645 #endif 7646 goto finish; 7647 } 7648 7649 /* Find the linkedit segment. If it's not the last segment, then freeing 7650 * it will fragment the kext into multiple VM regions, which OSKext is not 7651 * designed to handle, so we'll have to skip it. 7652 */ 7653 linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT); 7654 if (!linkedit) { 7655 goto finish; 7656 } 7657 7658 if (round_page(kmod_info->address + kmod_info->size) != 7659 round_page(linkedit->vmaddr + linkedit->vmsize)) { 7660 goto finish; 7661 } 7662 7663 /* Create a new OSData for the smaller kext object. 7664 */ 7665 linkeditsize = round_page(linkedit->vmsize); 7666 kextsize = kmod_info->size - linkeditsize; 7667 start = linkedit->vmaddr; 7668 7669 if (kextsize > UINT_MAX) { 7670 goto finish; 7671 } 7672 data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize); 7673 if (!data) { 7674 goto finish; 7675 } 7676 7677 /* Fix the kmod info and linkedExecutable. 7678 */ 7679 kmod_info->size = kextsize; 7680 7681 /* 7682 * Fileset KCs are mapped as a whole by iBoot. 7683 * Individual kext executables should not be unmapped by xnu 7684 * Doing so may result in panics like rdar://85419651 7685 */ 7686 if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) { 7687 data->setDeallocFunction(NULL); 7688 } else { // Not from a Fileset KC 7689 #if VM_MAPPED_KEXTS 7690 data->setDeallocFunction(osdata_kext_free); 7691 #else 7692 data->setDeallocFunction(osdata_phys_free); 7693 #endif 7694 } 7695 linkedExecutable->setDeallocFunction(NULL); 7696 linkedExecutable = os::move(data); 7697 flags.jettisonLinkeditSeg = 1; 7698 7699 /* Free the linkedit segment. 7700 */ 7701 #if VM_MAPPED_KEXTS 7702 kext_free(start, linkeditsize); 7703 #else 7704 ml_static_mfree(start, linkeditsize); 7705 #endif 7706 7707 finish: 7708 return; 7709 } 7710 7711 /********************************************************************* 7712 * If there are whole pages that are unused betweem the last section 7713 * of the DATA segment and the end of the DATA segment then we can free 7714 * them 7715 *********************************************************************/ 7716 void 7717 OSKext::jettisonDATASegmentPadding(void) 7718 { 7719 kernel_mach_header_t * mh; 7720 kernel_segment_command_t * dataSeg; 7721 kernel_section_t * sec, * lastSec; 7722 vm_offset_t dataSegEnd, lastSecEnd; 7723 vm_size_t padSize; 7724 7725 if (flags.builtin) { 7726 return; 7727 } 7728 mh = (kernel_mach_header_t *)kmod_info->address; 7729 7730 if (isInFileset()) { 7731 return; 7732 } 7733 7734 dataSeg = getsegbynamefromheader(mh, SEG_DATA); 7735 if (dataSeg == NULL) { 7736 return; 7737 } 7738 7739 lastSec = NULL; 7740 sec = firstsect(dataSeg); 7741 while (sec != NULL) { 7742 lastSec = sec; 7743 sec = nextsect(dataSeg, sec); 7744 } 7745 7746 if (lastSec == NULL) { 7747 return; 7748 } 7749 7750 if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) || 7751 (dataSeg->vmsize != round_page(dataSeg->vmsize))) { 7752 return; 7753 } 7754 7755 dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize; 7756 lastSecEnd = round_page(lastSec->addr + lastSec->size); 7757 7758 if (dataSegEnd <= lastSecEnd) { 7759 return; 7760 } 7761 7762 padSize = dataSegEnd - lastSecEnd; 7763 7764 if (padSize >= PAGE_SIZE) { 7765 #if VM_MAPPED_KEXTS 7766 kext_free(lastSecEnd, padSize); 7767 #else 7768 ml_static_mfree(lastSecEnd, padSize); 7769 #endif 7770 } 7771 } 7772 7773 /********************************************************************* 7774 *********************************************************************/ 7775 void 7776 OSKext::setLinkedExecutable(OSData * anExecutable) 7777 { 7778 if (linkedExecutable) { 7779 panic("Attempt to set linked executable on kext " 7780 "that already has one (%s).\n", 7781 getIdentifierCString()); 7782 } 7783 linkedExecutable.reset(anExecutable, OSRetain); 7784 return; 7785 } 7786 7787 #if CONFIG_DTRACE 7788 /********************************************************************* 7789 * Go through all loaded kexts and tell them to register with dtrace. 7790 * The instance method only registers if necessary. 7791 *********************************************************************/ 7792 /* static */ 7793 void 7794 OSKext::registerKextsWithDTrace(void) 7795 { 7796 uint32_t count = sLoadedKexts->getCount(); 7797 uint32_t i; 7798 7799 IORecursiveLockLock(sKextLock); 7800 7801 for (i = 0; i < count; i++) { 7802 OSKext * thisKext = NULL; // do not release 7803 7804 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 7805 if (!thisKext || !thisKext->isExecutable()) { 7806 continue; 7807 } 7808 7809 thisKext->registerWithDTrace(); 7810 } 7811 7812 IORecursiveLockUnlock(sKextLock); 7813 7814 return; 7815 } 7816 7817 extern "C" { 7818 extern int (*dtrace_modload)(struct kmod_info *, uint32_t); 7819 extern int (*dtrace_modunload)(struct kmod_info *); 7820 }; 7821 7822 /********************************************************************* 7823 *********************************************************************/ 7824 void 7825 OSKext::registerWithDTrace(void) 7826 { 7827 /* Register kext with dtrace. A dtrace_modload failure should not 7828 * prevent a kext from loading, so we ignore the return code. 7829 */ 7830 if (!flags.dtraceInitialized && (dtrace_modload != NULL)) { 7831 uint32_t modflag = 0; 7832 OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit"); 7833 7834 if (!sKeepSymbols && kc_type == KCKindPrimary) { 7835 if (forceInit == kOSBooleanTrue) { 7836 OSKextLog(this, 7837 kOSKextLogBasicLevel | 7838 kOSKextLogGeneralFlag, 7839 "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s", 7840 getIdentifierCString()); 7841 forceInit = kOSBooleanFalse; 7842 } 7843 /* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */ 7844 modflag |= KMOD_DTRACE_NO_KERNEL_SYMS; 7845 } 7846 7847 if (forceInit == kOSBooleanTrue) { 7848 modflag |= KMOD_DTRACE_FORCE_INIT; 7849 } 7850 if (flags.builtin) { 7851 modflag |= KMOD_DTRACE_STATIC_KEXT; 7852 } 7853 7854 (void)(*dtrace_modload)(kmod_info, modflag); 7855 flags.dtraceInitialized = true; 7856 jettisonLinkeditSegment(); 7857 } 7858 return; 7859 } 7860 /********************************************************************* 7861 *********************************************************************/ 7862 void 7863 OSKext::unregisterWithDTrace(void) 7864 { 7865 /* Unregister kext with dtrace. A dtrace_modunload failure should not 7866 * prevent a kext from loading, so we ignore the return code. 7867 */ 7868 if (flags.dtraceInitialized && (dtrace_modunload != NULL)) { 7869 (void)(*dtrace_modunload)(kmod_info); 7870 flags.dtraceInitialized = false; 7871 } 7872 return; 7873 } 7874 #endif /* CONFIG_DTRACE */ 7875 7876 7877 /********************************************************************* 7878 * called only by loadExecutable() 7879 *********************************************************************/ 7880 #if !VM_MAPPED_KEXTS 7881 #if defined(__arm__) || defined(__arm64__) 7882 static inline kern_return_t 7883 OSKext_protect( 7884 kernel_mach_header_t *kext_mh, 7885 vm_map_t map, 7886 vm_map_offset_t start, 7887 vm_map_offset_t end, 7888 vm_prot_t new_prot, 7889 boolean_t set_max, 7890 kc_kind_t kc_type) 7891 { 7892 #pragma unused(kext_mh,map,kc_type) 7893 assert(map == kernel_map); // we can handle KEXTs arising from the PRELINK segment and no others 7894 assert(start <= end); 7895 if (start >= end) { 7896 return KERN_SUCCESS; // Punt segments of length zero (e.g., headers) or less (i.e., blunders) 7897 } else if (set_max) { 7898 return KERN_SUCCESS; // Punt set_max, as there's no mechanism to record that state 7899 } else { 7900 return ml_static_protect(start, end - start, new_prot); 7901 } 7902 } 7903 7904 static inline kern_return_t 7905 OSKext_wire( 7906 kernel_mach_header_t *kext_mh, 7907 vm_map_t map, 7908 vm_map_offset_t start, 7909 vm_map_offset_t end, 7910 vm_prot_t access_type, 7911 boolean_t user_wire, 7912 kc_kind_t kc_type) 7913 { 7914 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type) 7915 return KERN_SUCCESS; // No-op as PRELINK kexts are cemented into physical memory at boot 7916 } 7917 #else 7918 #error Unrecognized architecture 7919 #endif 7920 #else 7921 static inline kern_return_t 7922 OSKext_protect( 7923 kernel_mach_header_t *kext_mh, 7924 vm_map_t map, 7925 vm_map_offset_t start, 7926 vm_map_offset_t end, 7927 vm_prot_t new_prot, 7928 boolean_t set_max, 7929 kc_kind_t kc_type) 7930 { 7931 if (start == end) { // 10538581 7932 return KERN_SUCCESS; 7933 } 7934 if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) { 7935 /* 7936 * XXX: This will probably need to be different for AuxKC and 7937 * pageableKC! 7938 */ 7939 return ml_static_protect(start, end - start, new_prot); 7940 } 7941 return vm_map_protect(map, start, end, new_prot, set_max); 7942 } 7943 7944 static inline kern_return_t 7945 OSKext_wire( 7946 kernel_mach_header_t *kext_mh, 7947 vm_map_t map, 7948 vm_map_offset_t start, 7949 vm_map_offset_t end, 7950 vm_prot_t access_type, 7951 boolean_t user_wire, 7952 kc_kind_t kc_type) 7953 { 7954 if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) { 7955 /* TODO: we may need to hook this for the pageableKC */ 7956 return KERN_SUCCESS; 7957 } 7958 return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire); 7959 } 7960 #endif 7961 7962 OSReturn 7963 OSKext::setVMAttributes(bool protect, bool wire) 7964 { 7965 vm_map_t kext_map = NULL; 7966 kernel_segment_command_t * seg = NULL; 7967 vm_map_offset_t start_protect = 0; 7968 vm_map_offset_t start_wire = 0; 7969 vm_map_offset_t end_protect = 0; 7970 vm_map_offset_t end_wire = 0; 7971 OSReturn result = kOSReturnError; 7972 7973 if (isInterface() || !declaresExecutable() || flags.builtin) { 7974 result = kOSReturnSuccess; 7975 goto finish; 7976 } 7977 7978 /* Get the kext's vm map */ 7979 kext_map = kext_get_vm_map(kmod_info); 7980 if (!kext_map) { 7981 result = KERN_MEMORY_ERROR; 7982 goto finish; 7983 } 7984 7985 #if !VM_MAPPED_KEXTS 7986 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) { 7987 /* This is a split kext in a prelinked kernelcache; we'll let the 7988 * platform code take care of protecting it. It is already wired. 7989 */ 7990 /* TODO: Should this still allow protections for the first segment 7991 * to go through, in the event that we have a mix of split and 7992 * unsplit kexts? 7993 */ 7994 result = KERN_SUCCESS; 7995 goto finish; 7996 } 7997 7998 if (isInFileset() && kc_type != KCKindPageable) { 7999 // kexts in filesets have protections setup as part of collection loading 8000 result = KERN_SUCCESS; 8001 goto finish; 8002 } 8003 #endif 8004 8005 /* Protect the headers as read-only; they do not need to be wired */ 8006 result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address, 8007 kext_map, kmod_info->address, 8008 kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type) 8009 : KERN_SUCCESS; 8010 if (result != KERN_SUCCESS) { 8011 goto finish; 8012 } 8013 8014 /* Set the VM protections and wire down each of the segments */ 8015 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 8016 while (seg) { 8017 #if __arm__ 8018 /* We build all ARM kexts, so we can ensure they are aligned */ 8019 assert((seg->vmaddr & PAGE_MASK) == 0); 8020 assert((seg->vmsize & PAGE_MASK) == 0); 8021 #endif 8022 8023 /* 8024 * For the non page aligned segments, the range calculation for protection 8025 * and wiring differ as follows: 8026 * 8027 * Protection: The non page aligned data at the start or at the end of the 8028 * segment is excluded from the protection. This exclusion is needed to make 8029 * sure OSKext_protect is not called twice on same page, if the page is shared 8030 * between two segments. 8031 * 8032 * Wiring: The non page aligned data at the start or at the end of the 8033 * segment is included in the wiring range, this inclusion is needed to make sure 8034 * all the data of the segment is wired. 8035 */ 8036 start_protect = round_page(seg->vmaddr); 8037 end_protect = trunc_page(seg->vmaddr + seg->vmsize); 8038 8039 start_wire = trunc_page(seg->vmaddr); 8040 end_wire = round_page(seg->vmaddr + seg->vmsize); 8041 8042 /* 8043 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared 8044 * across kexts and data from kexts is not page aligned 8045 */ 8046 if (protect && (end_protect > start_protect) && 8047 ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 && 8048 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) || 8049 (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) { 8050 result = OSKext_protect((kernel_mach_header_t *)kmod_info->address, 8051 kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type); 8052 if (result != KERN_SUCCESS) { 8053 OSKextLog(this, 8054 kOSKextLogErrorLevel | 8055 kOSKextLogLoadFlag, 8056 "Kext %s failed to set maximum VM protections " 8057 "for segment %s - 0x%x.", 8058 getIdentifierCString(), seg->segname, (int)result); 8059 goto finish; 8060 } 8061 8062 result = OSKext_protect((kernel_mach_header_t *)kmod_info->address, 8063 kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type); 8064 if (result != KERN_SUCCESS) { 8065 OSKextLog(this, 8066 kOSKextLogErrorLevel | 8067 kOSKextLogLoadFlag, 8068 "Kext %s failed to set initial VM protections " 8069 "for segment %s - 0x%x.", 8070 getIdentifierCString(), seg->segname, (int)result); 8071 goto finish; 8072 } 8073 } 8074 8075 if (segmentShouldBeWired(seg) && wire) { 8076 result = OSKext_wire((kernel_mach_header_t *)kmod_info->address, 8077 kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type); 8078 if (result != KERN_SUCCESS) { 8079 goto finish; 8080 } 8081 } 8082 8083 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 8084 } 8085 8086 finish: 8087 return result; 8088 } 8089 8090 /********************************************************************* 8091 *********************************************************************/ 8092 boolean_t 8093 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg) 8094 { 8095 return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) && 8096 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname))); 8097 } 8098 8099 /********************************************************************* 8100 *********************************************************************/ 8101 OSReturn 8102 OSKext::validateKextMapping(bool startFlag) 8103 { 8104 OSReturn result = kOSReturnError; 8105 const char * whichOp = startFlag ? "start" : "stop"; 8106 kern_return_t kern_result = 0; 8107 vm_map_t kext_map = NULL; 8108 kernel_segment_command_t * seg = NULL; 8109 mach_vm_address_t address = 0; 8110 mach_vm_size_t size = 0; 8111 uint32_t depth = 0; 8112 uint64_t kext_segbase = 0; 8113 uint64_t kext_segsize = 0; 8114 mach_msg_type_number_t count; 8115 vm_region_submap_short_info_data_64_t info; 8116 uintptr_t kext_slide = PE_get_kc_slide(kc_type); 8117 8118 if (flags.builtin) { 8119 return kOSReturnSuccess; 8120 } 8121 8122 count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 8123 bzero(&info, sizeof(info)); 8124 8125 // xxx - do we need a distinct OSReturn value for these or is "bad data" 8126 // xxx - sufficient? 8127 8128 /* Verify that the kmod_info and start/stop pointers are non-NULL. 8129 */ 8130 if (!kmod_info) { 8131 OSKextLog(this, 8132 kOSKextLogErrorLevel | 8133 kOSKextLogLoadFlag, 8134 "Kext %s - NULL kmod_info pointer.", 8135 getIdentifierCString()); 8136 result = kOSKextReturnBadData; 8137 goto finish; 8138 } 8139 8140 if (startFlag) { 8141 address = (mach_vm_address_t)kmod_info->start; 8142 } else { 8143 address = (mach_vm_address_t)kmod_info->stop; 8144 } 8145 8146 if (!address) { 8147 OSKextLog(this, 8148 kOSKextLogErrorLevel | 8149 kOSKextLogLoadFlag, 8150 "Kext %s - NULL module %s pointer.", 8151 getIdentifierCString(), whichOp); 8152 result = kOSKextReturnBadData; 8153 goto finish; 8154 } 8155 8156 kext_map = kext_get_vm_map(kmod_info); 8157 depth = (kernel_map == kext_map) ? 1 : 2; 8158 if (isInFileset()) { 8159 #if defined(HAS_APPLE_PAC) 8160 address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0); 8161 #endif /* defined(HAS_APPLE_PAC) */ 8162 } 8163 8164 /* Verify that the start/stop function lies within the kext's address range. 8165 */ 8166 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) || 8167 isInFileset()) { 8168 /* This will likely be how we deal with split kexts; walk the segments to 8169 * check that the function lies inside one of the segments of this kext. 8170 */ 8171 for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 8172 seg != NULL; 8173 seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) { 8174 if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) { 8175 kext_segbase = seg->vmaddr; 8176 kext_segsize = seg->vmsize; 8177 break; 8178 } 8179 } 8180 8181 if (!seg) { 8182 OSKextLog(this, 8183 kOSKextLogErrorLevel | 8184 kOSKextLogLoadFlag, 8185 "Kext %s module %s pointer is outside of kext range " 8186 "(%s %p - kext starts at %p).", 8187 getIdentifierCString(), 8188 whichOp, 8189 whichOp, 8190 (void *)(((uintptr_t)address) - kext_slide), 8191 (void *)(((uintptr_t)kmod_info->address) - kext_slide)); 8192 result = kOSKextReturnBadData; 8193 goto finish; 8194 } 8195 8196 seg = NULL; 8197 } else { 8198 if (address < kmod_info->address + kmod_info->hdr_size || 8199 kmod_info->address + kmod_info->size <= address) { 8200 OSKextLog(this, 8201 kOSKextLogErrorLevel | 8202 kOSKextLogLoadFlag, 8203 "Kext %s module %s pointer is outside of kext range " 8204 "(%s %p - kext at %p-%p).", 8205 getIdentifierCString(), 8206 whichOp, 8207 whichOp, 8208 (void *)(((uintptr_t)address) - kext_slide), 8209 (void *)(((uintptr_t)kmod_info->address) - kext_slide), 8210 (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size)); 8211 result = kOSKextReturnBadData; 8212 goto finish; 8213 } 8214 } 8215 8216 /* Only do these checks before calling the start function; 8217 * If anything goes wrong with the mapping while the kext is running, 8218 * we'll likely have panicked well before any attempt to stop the kext. 8219 */ 8220 if (startFlag) { 8221 if (!isInFileset() || kc_type != KCKindPrimary) { 8222 /* 8223 * Verify that the start/stop function is executable. 8224 */ 8225 kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth, 8226 (vm_region_recurse_info_t)&info, &count); 8227 if (kern_result != KERN_SUCCESS) { 8228 OSKextLog(this, 8229 kOSKextLogErrorLevel | 8230 kOSKextLogLoadFlag, 8231 "Kext %s - bad %s pointer %p.", 8232 getIdentifierCString(), 8233 whichOp, (void *)ml_static_unslide(address)); 8234 result = kOSKextReturnBadData; 8235 goto finish; 8236 } 8237 } else { 8238 /* 8239 * Since kexts loaded from the primary KC are held in memory 8240 * allocated by efiboot, we cannot use mach_vm_region_recurse() to 8241 * discover that memory's protection flags. Instead, we need to 8242 * get that information from the kernel pmap itself. Above, we 8243 * (potentially) saved the size of the segment in which the address 8244 * in question was located. If we have a non-zero size, verify 8245 * that all pages in the (address, address + kext_segsize) range 8246 * are marked executable. If we somehow did not record the size 8247 * (or the base) just verify the single page that includes the address. 8248 */ 8249 if (kext_segbase == 0 || kext_segsize == 0) { 8250 kext_segbase = address & ~(uint64_t)PAGE_MASK; 8251 kext_segsize = PAGE_SIZE; 8252 } 8253 } 8254 8255 #if VM_MAPPED_KEXTS 8256 if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) || 8257 ((isInFileset() && kc_type == KCKindPrimary) && 8258 ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) { 8259 OSKextLog(this, 8260 kOSKextLogErrorLevel | 8261 kOSKextLogLoadFlag, 8262 "Kext %s - memory region containing module %s function " 8263 "is not executable.", 8264 getIdentifierCString(), whichOp); 8265 result = kOSKextReturnBadData; 8266 goto finish; 8267 } 8268 #endif 8269 8270 /* Verify that the kext's segments are backed by physical memory. 8271 */ 8272 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 8273 while (seg) { 8274 if (!verifySegmentMapping(seg)) { 8275 result = kOSKextReturnBadData; 8276 goto finish; 8277 } 8278 8279 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 8280 } 8281 } 8282 8283 result = kOSReturnSuccess; 8284 finish: 8285 return result; 8286 } 8287 8288 /********************************************************************* 8289 *********************************************************************/ 8290 boolean_t 8291 OSKext::verifySegmentMapping(kernel_segment_command_t *seg) 8292 { 8293 mach_vm_address_t address = 0; 8294 8295 if (seg->vmsize > UINT32_MAX) { 8296 return false; 8297 } 8298 8299 if (!segmentShouldBeWired(seg)) { 8300 return true; 8301 } 8302 8303 for (address = seg->vmaddr; 8304 address < round_page(seg->vmaddr + seg->vmsize); 8305 address += PAGE_SIZE) { 8306 if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) { 8307 OSKextLog(this, 8308 kOSKextLogErrorLevel | 8309 kOSKextLogLoadFlag, 8310 "Kext %s - page %p is not backed by physical memory.", 8311 getIdentifierCString(), 8312 (void *)address); 8313 return false; 8314 } 8315 } 8316 8317 return true; 8318 } 8319 8320 /********************************************************************* 8321 *********************************************************************/ 8322 static void 8323 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code) 8324 { 8325 uint64_t stamp = 0; 8326 firehose_tracepoint_id_u trace_id; 8327 struct firehose_trace_uuid_info_s uuid_info_s; 8328 firehose_trace_uuid_info_t uuid_info = &uuid_info_s; 8329 size_t uuid_info_len = sizeof(struct firehose_trace_uuid_info_s); 8330 OSSharedPtr<OSData> uuid_data; 8331 8332 stamp = firehose_tracepoint_time(firehose_activity_flags_default); 8333 trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code); 8334 8335 uuid_data = aKext->copyTextUUID(); 8336 if (uuid_data) { 8337 memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid)); 8338 } 8339 8340 uuid_info->ftui_size = size; 8341 if (aKext->isDriverKit()) { 8342 uuid_info->ftui_address = address; 8343 } else { 8344 uuid_info->ftui_address = ml_static_unslide(address); 8345 } 8346 os_log_encoded_metadata(trace_id, stamp, uuid_info, uuid_info_len); 8347 return; 8348 } 8349 8350 void 8351 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext) 8352 { 8353 OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load); 8354 } 8355 8356 /********************************************************************* 8357 *********************************************************************/ 8358 OSReturn 8359 OSKext::start(bool startDependenciesFlag) 8360 { 8361 OSReturn result = kOSReturnError; 8362 kern_return_t (* startfunc)(kmod_info_t *, void *); 8363 unsigned int i, count; 8364 void * kmodStartData = NULL; 8365 8366 if (isStarted() || isInterface() || isKernelComponent()) { 8367 result = kOSReturnSuccess; 8368 goto finish; 8369 } 8370 8371 if (!isLoaded()) { 8372 OSKextLog(this, 8373 kOSKextLogErrorLevel | 8374 kOSKextLogLoadFlag, 8375 "Attempt to start nonloaded kext %s.", 8376 getIdentifierCString()); 8377 result = kOSKextReturnInvalidArgument; 8378 goto finish; 8379 } 8380 8381 if (!sLoadEnabled) { 8382 OSKextLog(this, 8383 kOSKextLogErrorLevel | 8384 kOSKextLogLoadFlag, 8385 "Kext loading is disabled (attempt to start kext %s).", 8386 getIdentifierCString()); 8387 result = kOSKextReturnDisabled; 8388 goto finish; 8389 } 8390 8391 result = validateKextMapping(/* start? */ true); 8392 if (result != kOSReturnSuccess) { 8393 goto finish; 8394 } 8395 8396 startfunc = kmod_info->start; 8397 8398 count = getNumDependencies(); 8399 for (i = 0; i < count; i++) { 8400 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i)); 8401 if (dependency == NULL) { 8402 OSKextLog(this, 8403 kOSKextLogErrorLevel | 8404 kOSKextLogLoadFlag, 8405 "Kext %s start - internal error, dependency disappeared.", 8406 getIdentifierCString()); 8407 goto finish; 8408 } 8409 if (!dependency->isStarted()) { 8410 if (startDependenciesFlag) { 8411 OSReturn dependencyResult = 8412 dependency->start(startDependenciesFlag); 8413 if (dependencyResult != KERN_SUCCESS) { 8414 OSKextLog(this, 8415 kOSKextLogErrorLevel | 8416 kOSKextLogLoadFlag, 8417 "Kext %s start - dependency %s failed to start (error 0x%x).", 8418 getIdentifierCString(), 8419 dependency->getIdentifierCString(), 8420 dependencyResult); 8421 goto finish; 8422 } 8423 } else { 8424 OSKextLog(this, 8425 kOSKextLogErrorLevel | 8426 kOSKextLogLoadFlag, 8427 "Not starting %s - dependency %s not started yet.", 8428 getIdentifierCString(), 8429 dependency->getIdentifierCString()); 8430 result = kOSKextReturnStartStopError; // xxx - make new return? 8431 goto finish; 8432 } 8433 } 8434 } 8435 8436 OSKextLog(this, 8437 kOSKextLogDetailLevel | 8438 kOSKextLogLoadFlag, 8439 "Kext %s calling module start function.", 8440 getIdentifierCString()); 8441 8442 flags.starting = 1; 8443 8444 // Drop a log message so logd can grab the needed information to decode this kext 8445 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load); 8446 result = OSRuntimeInitializeCPP(this); 8447 if (result == KERN_SUCCESS) { 8448 result = startfunc(kmod_info, kmodStartData); 8449 } 8450 8451 flags.starting = 0; 8452 8453 /* On success overlap the setting of started/starting. On failure just 8454 * clear starting. 8455 */ 8456 if (result == KERN_SUCCESS) { 8457 flags.started = 1; 8458 8459 // xxx - log start error from kernel? 8460 OSKextLog(this, 8461 kOSKextLogProgressLevel | 8462 kOSKextLogLoadFlag, 8463 "Kext %s is now started.", 8464 getIdentifierCString()); 8465 } else { 8466 invokeOrCancelRequestCallbacks( 8467 /* result not actually used */ kOSKextReturnStartStopError, 8468 /* invokeFlag */ false); 8469 OSKextLog(this, 8470 kOSKextLogWarningLevel | 8471 kOSKextLogLoadFlag, 8472 "Kext %s did not start (return code 0x%x).", 8473 getIdentifierCString(), result); 8474 } 8475 8476 finish: 8477 return result; 8478 } 8479 8480 /********************************************************************* 8481 *********************************************************************/ 8482 /* static */ 8483 bool 8484 OSKext::canUnloadKextWithIdentifier( 8485 OSString * kextIdentifier, 8486 bool checkClassesFlag) 8487 { 8488 bool result = false; 8489 OSKext * aKext = NULL; // do not release 8490 8491 IORecursiveLockLock(sKextLock); 8492 8493 aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 8494 8495 if (!aKext) { 8496 goto finish; // can't unload what's not loaded 8497 } 8498 8499 if (aKext->isLoaded()) { 8500 if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) { 8501 goto finish; 8502 } 8503 if (checkClassesFlag && aKext->hasOSMetaClassInstances()) { 8504 goto finish; 8505 } 8506 } 8507 8508 result = true; 8509 8510 finish: 8511 IORecursiveLockUnlock(sKextLock); 8512 return result; 8513 } 8514 8515 /********************************************************************* 8516 *********************************************************************/ 8517 OSReturn 8518 OSKext::stop(void) 8519 { 8520 OSReturn result = kOSReturnError; 8521 kern_return_t (*stopfunc)(kmod_info_t *, void *); 8522 8523 if (!isStarted() || isInterface()) { 8524 result = kOSReturnSuccess; 8525 goto finish; 8526 } 8527 8528 if (!isLoaded()) { 8529 OSKextLog(this, 8530 kOSKextLogErrorLevel | 8531 kOSKextLogLoadFlag, 8532 "Attempt to stop nonloaded kext %s.", 8533 getIdentifierCString()); 8534 result = kOSKextReturnInvalidArgument; 8535 goto finish; 8536 } 8537 8538 /* Refuse to stop if we have clients or instances. It is up to 8539 * the caller to make sure those aren't true. 8540 */ 8541 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 8542 OSKextLog(this, 8543 kOSKextLogErrorLevel | 8544 kOSKextLogLoadFlag, 8545 "Kext %s - C++ instances; can't stop.", 8546 getIdentifierCString()); 8547 result = kOSKextReturnInUse; 8548 goto finish; 8549 } 8550 8551 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 8552 OSKextLog(this, 8553 kOSKextLogErrorLevel | 8554 kOSKextLogLoadFlag, 8555 "Kext %s - has references (linkage or tracking object); " 8556 "can't stop.", 8557 getIdentifierCString()); 8558 result = kOSKextReturnInUse; 8559 goto finish; 8560 } 8561 8562 /* Note: If validateKextMapping fails on the stop & unload path, 8563 * we are in serious trouble and a kernel panic is likely whether 8564 * we stop & unload the kext or not. 8565 */ 8566 result = validateKextMapping(/* start? */ false); 8567 if (result != kOSReturnSuccess) { 8568 goto finish; 8569 } 8570 8571 stopfunc = kmod_info->stop; 8572 if (stopfunc) { 8573 OSKextLog(this, 8574 kOSKextLogDetailLevel | 8575 kOSKextLogLoadFlag, 8576 "Kext %s calling module stop function.", 8577 getIdentifierCString()); 8578 8579 flags.stopping = 1; 8580 8581 result = stopfunc(kmod_info, /* userData */ NULL); 8582 if (result == KERN_SUCCESS) { 8583 result = OSRuntimeFinalizeCPP(this); 8584 } 8585 8586 flags.stopping = 0; 8587 8588 if (result == KERN_SUCCESS) { 8589 flags.started = 0; 8590 8591 OSKextLog(this, 8592 kOSKextLogDetailLevel | 8593 kOSKextLogLoadFlag, 8594 "Kext %s is now stopped and ready to unload.", 8595 getIdentifierCString()); 8596 } else { 8597 OSKextLog(this, 8598 kOSKextLogErrorLevel | 8599 kOSKextLogLoadFlag, 8600 "Kext %s did not stop (return code 0x%x).", 8601 getIdentifierCString(), result); 8602 result = kOSKextReturnStartStopError; 8603 } 8604 } 8605 8606 finish: 8607 // Drop a log message so logd can update this kext's metadata 8608 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload); 8609 return result; 8610 } 8611 8612 /********************************************************************* 8613 *********************************************************************/ 8614 OSReturn 8615 OSKext::unload(void) 8616 { 8617 OSReturn result = kOSReturnError; 8618 unsigned int index; 8619 uint32_t num_kmod_refs = 0; 8620 OSKextAccount * freeAccount; 8621 bool in_fileset = false; 8622 8623 if (!sUnloadEnabled) { 8624 OSKextLog(this, 8625 kOSKextLogErrorLevel | 8626 kOSKextLogLoadFlag, 8627 "Kext unloading is disabled (%s).", 8628 this->getIdentifierCString()); 8629 8630 result = kOSKextReturnDisabled; 8631 goto finish; 8632 } 8633 8634 // cache this result so we don't need to access the kmod_info after 8635 // it's been potentially free'd 8636 in_fileset = isInFileset(); 8637 8638 /* Refuse to unload if we have clients or instances. It is up to 8639 * the caller to make sure those aren't true. 8640 */ 8641 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 8642 // xxx - Don't log under errors? this is more of an info thing 8643 OSKextLog(this, 8644 kOSKextLogErrorLevel | 8645 kOSKextLogKextBookkeepingFlag, 8646 "Can't unload kext %s; outstanding references %d (linkage or tracking object).", 8647 getIdentifierCString(), getRetainCount()); 8648 result = kOSKextReturnInUse; 8649 goto finish; 8650 } 8651 8652 if (isDriverKit()) { 8653 index = sLoadedDriverKitKexts->getNextIndexOfObject(this, 0); 8654 if (index != (unsigned int)-1) { 8655 sLoadedDriverKitKexts->removeObject(index); 8656 OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload); 8657 loadTag = 0; 8658 } 8659 } 8660 8661 if (!isLoaded()) { 8662 result = kOSReturnSuccess; 8663 goto finish; 8664 } 8665 8666 if (isKernelComponent()) { 8667 result = kOSKextReturnInvalidArgument; 8668 goto finish; 8669 } 8670 8671 if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) { 8672 OSKextLog(this, 8673 kOSKextLogErrorLevel | 8674 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 8675 "Can't unload kext %s; classes have instances:", 8676 getIdentifierCString()); 8677 reportOSMetaClassInstances(kOSKextLogErrorLevel | 8678 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag); 8679 result = kOSKextReturnInUse; 8680 goto finish; 8681 } 8682 8683 /* Note that the kext is unloading before running any code that 8684 * might be in the kext (request callbacks, module stop function). 8685 * We will deny certain requests made against a kext in the process 8686 * of unloading. 8687 */ 8688 flags.unloading = 1; 8689 8690 /* Update the string describing the last kext to unload in case we panic. 8691 */ 8692 savePanicString(/* isLoading */ false); 8693 8694 if (isStarted()) { 8695 result = stop(); 8696 if (result != KERN_SUCCESS) { 8697 OSKextLog(this, 8698 kOSKextLogErrorLevel | 8699 kOSKextLogLoadFlag, 8700 "Kext %s can't unload - module stop returned 0x%x.", 8701 getIdentifierCString(), (unsigned)result); 8702 result = kOSKextReturnStartStopError; 8703 goto finish; 8704 } 8705 } 8706 8707 OSKextLog(this, 8708 kOSKextLogProgressLevel | 8709 kOSKextLogLoadFlag, 8710 "Kext %s unloading.", 8711 getIdentifierCString()); 8712 8713 { 8714 struct list_head *p; 8715 struct list_head *prev; 8716 struct list_head *next; 8717 for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) { 8718 OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head); 8719 s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize); 8720 prev = p->prev; 8721 next = p->next; 8722 prev->next = next; 8723 next->prev = prev; 8724 p->prev = p; 8725 p->next = p; 8726 IORecursiveLockWakeup(sKextLock, s, false); 8727 } 8728 } 8729 8730 8731 /* Even if we don't call the stop function, we want to be sure we 8732 * have no OSMetaClass references before unloading the kext executable 8733 * from memory. OSMetaClasses may have pointers into the kext executable 8734 * and that would cause a panic on OSKext::free() when metaClasses is freed. 8735 */ 8736 if (metaClasses) { 8737 metaClasses->flushCollection(); 8738 } 8739 (void) OSRuntimeFinalizeCPP(this); 8740 8741 /* Remove the kext from the list of loaded kexts, patch the gap 8742 * in the kmod_info_t linked list, and reset "kmod" to point to the 8743 * last loaded kext that isn't the fake kernel kext (sKernelKext). 8744 */ 8745 index = sLoadedKexts->getNextIndexOfObject(this, 0); 8746 if (index != (unsigned int)-1) { 8747 sLoadedKexts->removeObject(index); 8748 8749 OSKext * nextKext = OSDynamicCast(OSKext, 8750 sLoadedKexts->getObject(index)); 8751 8752 if (nextKext) { 8753 if (index > 0) { 8754 OSKext * gapKext = OSDynamicCast(OSKext, 8755 sLoadedKexts->getObject(index - 1)); 8756 8757 nextKext->kmod_info->next = gapKext->kmod_info; 8758 } else { /* index == 0 */ 8759 nextKext->kmod_info->next = NULL; 8760 } 8761 } 8762 8763 OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 8764 if (lastKext && !lastKext->isKernel()) { 8765 kmod = lastKext->kmod_info; 8766 } else { 8767 kmod = NULL; // clear the global kmod variable 8768 } 8769 } 8770 8771 /* Clear out the kmod references that we're keeping for compatibility 8772 * with current panic backtrace code & kgmacros. 8773 * xxx - will want to update those bits sometime and remove this. 8774 */ 8775 num_kmod_refs = getNumDependencies(); 8776 if (num_kmod_refs && kmod_info && kmod_info->reference_list) { 8777 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 8778 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 8779 ref->info->reference_count--; 8780 } 8781 kfree_type(kmod_reference_t, num_kmod_refs, 8782 kmod_info->reference_list); 8783 } 8784 8785 #if CONFIG_DTRACE 8786 unregisterWithDTrace(); 8787 #endif /* CONFIG_DTRACE */ 8788 8789 notifyKextUnloadObservers(this); 8790 8791 freeAccount = NULL; 8792 lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp); 8793 account->kext = NULL; 8794 if (account->site.tag) { 8795 account->site.flags |= VM_TAG_UNLOAD; 8796 } else { 8797 freeAccount = account; 8798 } 8799 8800 #if DEVELOPMENT || DEBUG 8801 assertf(account->task_refgrp.grp_count == 0, 8802 "unloading a kext with active task references"); 8803 #endif /* DEVELOPMENT || DEBUG */ 8804 8805 lck_ticket_unlock(sKextAccountsLock); 8806 if (freeAccount) { 8807 IOFreeType(freeAccount, OSKextAccount); 8808 } 8809 8810 /* Unwire and free the linked executable. 8811 */ 8812 if (linkedExecutable) { 8813 #if KASAN 8814 kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength()); 8815 #endif 8816 8817 #if VM_MAPPED_KEXTS 8818 if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) { 8819 kernel_segment_command_t *seg = NULL; 8820 vm_map_t kext_map = kext_get_vm_map(kmod_info); 8821 8822 if (!kext_map) { 8823 OSKextLog(this, 8824 kOSKextLogErrorLevel | 8825 kOSKextLogLoadFlag, 8826 "Failed to free kext %s; couldn't find the kext map.", 8827 getIdentifierCString()); 8828 result = kOSKextReturnInternalError; 8829 goto finish; 8830 } 8831 8832 OSKextLog(this, 8833 kOSKextLogProgressLevel | 8834 kOSKextLogLoadFlag, 8835 "Kext %s unwiring and unmapping linked executable.", 8836 getIdentifierCString()); 8837 8838 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 8839 while (seg) { 8840 if (segmentShouldBeWired(seg)) { 8841 vm_map_offset_t start_wire = trunc_page(seg->vmaddr); 8842 vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize); 8843 8844 result = vm_map_unwire(kext_map, start_wire, 8845 end_wire, FALSE); 8846 if (result != KERN_SUCCESS) { 8847 OSKextLog(this, 8848 kOSKextLogErrorLevel | 8849 kOSKextLogLoadFlag, 8850 "Failed to unwire kext %s.", 8851 getIdentifierCString()); 8852 result = kOSKextReturnInternalError; 8853 goto finish; 8854 } 8855 } 8856 8857 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 8858 } 8859 #if defined(__x86_64__) || defined(__i386__) 8860 if (in_fileset && flags.resetSegmentsFromVnode) { 8861 IORecursiveLockLock(sKextLock); 8862 resetKCFileSetSegments(); 8863 IORecursiveLockUnlock(sKextLock); 8864 } 8865 #endif // (__x86_64__) || defined(__i386__) 8866 } 8867 #endif /* VM_MAPPED_KEXTS */ 8868 if (flags.resetSegmentsFromImmutableCopy) { 8869 result = resetMutableSegments(); 8870 if (result != kOSReturnSuccess) { 8871 OSKextLog(this, 8872 kOSKextLogErrorLevel | 8873 kOSKextLogLoadFlag, 8874 "Failed to reset kext %s.", 8875 getIdentifierCString()); 8876 result = kOSKextReturnInternalError; 8877 goto finish; 8878 } 8879 } 8880 if (kc_type == KCKindUnknown) { 8881 linkedExecutable.reset(); 8882 } 8883 } 8884 8885 /* An interface kext has a fake kmod_info that was allocated, 8886 * so we have to free it. 8887 */ 8888 if (isInterface()) { 8889 kfree_type(kmod_info_t, kmod_info); 8890 kmod_info = NULL; 8891 } 8892 8893 if (!in_fileset) { 8894 kmod_info = NULL; 8895 } 8896 8897 flags.loaded = false; 8898 flushDependencies(); 8899 8900 /* save a copy of the bundle ID for us to check when deciding to 8901 * rebuild the kernel cache file. If a kext was already in the kernel 8902 * cache and unloaded then later loaded we do not need to rebuild the 8903 * kernel cache. 9055303 8904 */ 8905 if (isPrelinked()) { 8906 if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) { 8907 IORecursiveLockLock(sKextLock); 8908 if (sUnloadedPrelinkedKexts) { 8909 sUnloadedPrelinkedKexts->setObject(bundleID.get()); 8910 } 8911 IORecursiveLockUnlock(sKextLock); 8912 } 8913 } 8914 8915 OSKextLog(this, 8916 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 8917 "Kext %s unloaded.", getIdentifierCString()); 8918 8919 queueKextNotification(kKextRequestPredicateUnloadNotification, 8920 OSDynamicCast(OSString, bundleID.get()), getDextUniqueID()); 8921 8922 finish: 8923 OSKext::saveLoadedKextPanicList(); 8924 OSKext::updateLoadedKextSummaries(); 8925 8926 flags.unloading = 0; 8927 return result; 8928 } 8929 8930 /********************************************************************* 8931 * Assumes sKextLock is held. 8932 *********************************************************************/ 8933 /* static */ 8934 OSReturn 8935 OSKext::queueKextNotification( 8936 const char * notificationName, 8937 OSString * kextIdentifier, 8938 OSData * dextUniqueIdentifier) 8939 { 8940 OSReturn result = kOSReturnError; 8941 OSSharedPtr<OSDictionary> loadRequest; 8942 8943 if (!kextIdentifier) { 8944 result = kOSKextReturnInvalidArgument; 8945 goto finish; 8946 } 8947 8948 /* Create a new request unless one is already sitting 8949 * in sKernelRequests for this bundle identifier 8950 */ 8951 result = _OSKextCreateRequest(notificationName, loadRequest); 8952 if (result != kOSReturnSuccess) { 8953 goto finish; 8954 } 8955 if (!_OSKextSetRequestArgument(loadRequest.get(), 8956 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 8957 result = kOSKextReturnNoMemory; 8958 goto finish; 8959 } 8960 if (NULL != dextUniqueIdentifier) { 8961 if (!_OSKextSetRequestArgument(loadRequest.get(), 8962 kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) { 8963 result = kOSKextReturnNoMemory; 8964 goto finish; 8965 } 8966 } 8967 if (!sKernelRequests->setObject(loadRequest.get())) { 8968 result = kOSKextReturnNoMemory; 8969 goto finish; 8970 } 8971 8972 /* We might want to only queue the notification if the IOKit daemon is active, 8973 * but that wouldn't work for embedded. Note that we don't care if 8974 * the ping immediately succeeds here so don't do anything with the 8975 * result of this call. 8976 */ 8977 OSKext::pingIOKitDaemon(); 8978 8979 result = kOSReturnSuccess; 8980 8981 finish: 8982 return result; 8983 } 8984 8985 8986 #if CONFIG_KXLD 8987 /********************************************************************* 8988 *********************************************************************/ 8989 static void 8990 _OSKextConsiderDestroyingLinkContext( 8991 __unused thread_call_param_t p0, 8992 __unused thread_call_param_t p1) 8993 { 8994 /* Take multiple locks in the correct order. 8995 */ 8996 IORecursiveLockLock(sKextLock); 8997 IORecursiveLockLock(sKextInnerLock); 8998 8999 /* The first time we destroy the kxldContext is in the first 9000 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled 9001 * before calling this function. Thereafter any call to this function 9002 * will actually destroy the context. 9003 */ 9004 if (sConsiderUnloadsCalled && sKxldContext) { 9005 kxld_destroy_context(sKxldContext); 9006 sKxldContext = NULL; 9007 } 9008 9009 /* Free the thread_call that was allocated to execute this function. 9010 */ 9011 if (sDestroyLinkContextThread) { 9012 if (!thread_call_free(sDestroyLinkContextThread)) { 9013 OSKextLog(/* kext */ NULL, 9014 kOSKextLogErrorLevel | 9015 kOSKextLogGeneralFlag, 9016 "thread_call_free() failed for kext link context."); 9017 } 9018 sDestroyLinkContextThread = NULL; 9019 } 9020 9021 IORecursiveLockUnlock(sKextInnerLock); 9022 IORecursiveLockUnlock(sKextLock); 9023 9024 return; 9025 } 9026 9027 /********************************************************************* 9028 * Destroying the kxldContext requires checking variables under both 9029 * sKextInnerLock and sKextLock, so we do it on a separate thread 9030 * to avoid deadlocks with IOService, with which OSKext has a reciprocal 9031 * call relationship. 9032 * 9033 * This function must be invoked with sKextInnerLock held. 9034 * Do not call any function that takes sKextLock here! 9035 *********************************************************************/ 9036 /* static */ 9037 void 9038 OSKext::considerDestroyingLinkContext(void) 9039 { 9040 IORecursiveLockLock(sKextInnerLock); 9041 9042 /* If we have already queued a thread to destroy the link context, 9043 * don't bother resetting; that thread will take care of it. 9044 */ 9045 if (sDestroyLinkContextThread) { 9046 goto finish; 9047 } 9048 9049 /* The function to be invoked in the thread will deallocate 9050 * this thread_call, so don't share it around. 9051 */ 9052 sDestroyLinkContextThread = thread_call_allocate( 9053 &_OSKextConsiderDestroyingLinkContext, NULL); 9054 if (!sDestroyLinkContextThread) { 9055 OSKextLog(/* kext */ NULL, 9056 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag, 9057 "Can't create thread to destroy kext link context."); 9058 goto finish; 9059 } 9060 9061 thread_call_enter(sDestroyLinkContextThread); 9062 9063 finish: 9064 IORecursiveLockUnlock(sKextInnerLock); 9065 return; 9066 } 9067 9068 #else // !CONFIG_KXLD 9069 9070 /* static */ 9071 void 9072 OSKext::considerDestroyingLinkContext(void) 9073 { 9074 return; 9075 } 9076 9077 #endif // CONFIG_KXLD 9078 9079 #if PRAGMA_MARK 9080 #pragma mark Autounload 9081 #endif 9082 /********************************************************************* 9083 * This is a static method because the kext will be deallocated if it 9084 * does unload! 9085 *********************************************************************/ 9086 /* static */ 9087 OSReturn 9088 OSKext::autounloadKext(OSKext * aKext) 9089 { 9090 OSReturn result = kOSKextReturnInUse; 9091 9092 #if NO_KEXTD 9093 /* 9094 * Do not unload prelinked kexts on platforms that do not have an 9095 * IOKit daemon as there is no way to reload the kext or restart 9096 * matching. 9097 */ 9098 if (aKext->isPrelinked()) { 9099 goto finish; 9100 } 9101 #endif /* defined(__x86_64__) */ 9102 9103 /* Check for external references to this kext (usu. dependents), 9104 * instances of defined classes (or classes derived from them), 9105 * outstanding requests. 9106 */ 9107 if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) || 9108 !aKext->flags.autounloadEnabled || 9109 aKext->isKernelComponent()) { 9110 goto finish; 9111 } 9112 9113 /* Skip a delay-autounload kext, once. 9114 */ 9115 if (aKext->flags.delayAutounload) { 9116 OSKextLog(aKext, 9117 kOSKextLogProgressLevel | 9118 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 9119 "Kext %s has delayed autounload set; skipping and clearing flag.", 9120 aKext->getIdentifierCString()); 9121 aKext->flags.delayAutounload = 0; 9122 goto finish; 9123 } 9124 9125 if (aKext->hasOSMetaClassInstances() || 9126 aKext->countRequestCallbacks()) { 9127 goto finish; 9128 } 9129 9130 result = OSKext::removeKext(aKext); 9131 9132 finish: 9133 return result; 9134 } 9135 9136 /********************************************************************* 9137 *********************************************************************/ 9138 void 9139 _OSKextConsiderUnloads( 9140 __unused thread_call_param_t p0, 9141 __unused thread_call_param_t p1) 9142 { 9143 bool didUnload = false; 9144 unsigned int count, i; 9145 9146 /* Take multiple locks in the correct order 9147 * (note also sKextSummaries lock further down). 9148 */ 9149 IORecursiveLockLock(sKextLock); 9150 IORecursiveLockLock(sKextInnerLock); 9151 9152 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true); 9153 9154 /* If the system is powering down, don't try to unload anything. 9155 */ 9156 if (sSystemSleep) { 9157 goto finish; 9158 } 9159 9160 OSKextLog(/* kext */ NULL, 9161 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 9162 "Checking for unused kexts to autounload."); 9163 9164 /***** 9165 * Remove any request callbacks marked as stale, 9166 * and mark as stale any currently in flight. 9167 */ 9168 count = sRequestCallbackRecords->getCount(); 9169 if (count) { 9170 i = count - 1; 9171 do { 9172 OSDictionary * callbackRecord = OSDynamicCast(OSDictionary, 9173 sRequestCallbackRecords->getObject(i)); 9174 if (callbackRecord) { 9175 OSBoolean * stale = OSDynamicCast(OSBoolean, 9176 callbackRecord->getObject(kKextRequestStaleKey)); 9177 9178 if (stale == kOSBooleanTrue) { 9179 OSKext::invokeRequestCallback(callbackRecord, 9180 kOSKextReturnTimeout); 9181 } else { 9182 callbackRecord->setObject(kKextRequestStaleKey, 9183 kOSBooleanTrue); 9184 } 9185 } 9186 } while (i--); 9187 } 9188 9189 /***** 9190 * Make multiple passes through the array of loaded kexts until 9191 * we don't unload any. This handles unwinding of dependency 9192 * chains. We have to go *backwards* through the array because 9193 * kexts are removed from it when unloaded, and we cannot make 9194 * a copy or we'll mess up the retain counts we rely on to 9195 * check whether a kext will unload. If only we could have 9196 * nonretaining collections like CF has.... 9197 */ 9198 do { 9199 didUnload = false; 9200 9201 count = sLoadedKexts->getCount(); 9202 if (count) { 9203 i = count - 1; 9204 do { 9205 OSKext * thisKext = OSDynamicCast(OSKext, 9206 sLoadedKexts->getObject(i)); 9207 didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext)); 9208 } while (i--); 9209 } 9210 } while (didUnload); 9211 9212 finish: 9213 sConsiderUnloadsPending = false; 9214 sConsiderUnloadsExecuted = true; 9215 9216 (void) OSKext::considerRebuildOfPrelinkedKernel(); 9217 9218 IORecursiveLockUnlock(sKextInnerLock); 9219 IORecursiveLockUnlock(sKextLock); 9220 9221 return; 9222 } 9223 9224 /********************************************************************* 9225 * Do not call any function that takes sKextLock here! 9226 *********************************************************************/ 9227 void 9228 OSKext::considerUnloads(Boolean rescheduleOnlyFlag) 9229 { 9230 AbsoluteTime when; 9231 9232 IORecursiveLockLock(sKextInnerLock); 9233 9234 if (!sUnloadCallout) { 9235 sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL); 9236 } 9237 9238 /* we only reset delay value for unloading if we already have something 9239 * pending. rescheduleOnlyFlag should not start the count down. 9240 */ 9241 if (rescheduleOnlyFlag && !sConsiderUnloadsPending) { 9242 goto finish; 9243 } 9244 9245 thread_call_cancel(sUnloadCallout); 9246 if (OSKext::getAutounloadEnabled() && !sSystemSleep 9247 #if !NO_KEXTD 9248 && sIOKitDaemonActive 9249 #endif 9250 ) { 9251 clock_interval_to_deadline(sConsiderUnloadDelay, 9252 1000 * 1000 * 1000, &when); 9253 9254 OSKextLog(/* kext */ NULL, 9255 kOSKextLogProgressLevel | 9256 kOSKextLogLoadFlag, 9257 "%scheduling %sscan for unused kexts in %lu seconds.", 9258 sConsiderUnloadsPending ? "Res" : "S", 9259 sConsiderUnloadsCalled ? "" : "initial ", 9260 (unsigned long)sConsiderUnloadDelay); 9261 9262 sConsiderUnloadsPending = true; 9263 thread_call_enter_delayed(sUnloadCallout, when); 9264 } 9265 9266 finish: 9267 /* The kxld context should be reused throughout boot. We mark the end of 9268 * period as the first time considerUnloads() is called, and we destroy 9269 * the first kxld context in that function. Afterwards, it will be 9270 * destroyed in flushNonloadedKexts. 9271 */ 9272 if (!sConsiderUnloadsCalled) { 9273 sConsiderUnloadsCalled = true; 9274 OSKext::considerDestroyingLinkContext(); 9275 } 9276 9277 IORecursiveLockUnlock(sKextInnerLock); 9278 return; 9279 } 9280 9281 /********************************************************************* 9282 * Do not call any function that takes sKextLock here! 9283 *********************************************************************/ 9284 extern "C" { 9285 IOReturn OSKextSystemSleepOrWake(UInt32 messageType); 9286 IOReturn 9287 OSKextSystemSleepOrWake(UInt32 messageType) 9288 { 9289 IORecursiveLockLock(sKextInnerLock); 9290 9291 /* If the system is going to sleep, cancel the reaper thread timer, 9292 * and note that we're in a sleep state in case it just fired but hasn't 9293 * taken the lock yet. If we are coming back from sleep, just 9294 * clear the sleep flag; IOService's normal operation will cause 9295 * unloads to be considered soon enough. 9296 */ 9297 if (messageType == kIOMessageSystemWillSleep) { 9298 if (sUnloadCallout) { 9299 thread_call_cancel(sUnloadCallout); 9300 } 9301 sSystemSleep = true; 9302 AbsoluteTime_to_scalar(&sLastWakeTime) = 0; 9303 } else if (messageType == kIOMessageSystemHasPoweredOn) { 9304 sSystemSleep = false; 9305 clock_get_uptime(&sLastWakeTime); 9306 } 9307 IORecursiveLockUnlock(sKextInnerLock); 9308 9309 return kIOReturnSuccess; 9310 } 9311 }; 9312 9313 9314 #if PRAGMA_MARK 9315 #pragma mark Prelinked Kernel 9316 #endif 9317 9318 #ifdef CONFIG_KXLD 9319 /********************************************************************* 9320 * Do not access sConsiderUnloads... variables other than 9321 * sConsiderUnloadsExecuted in this function. They are guarded by a 9322 * different lock. 9323 *********************************************************************/ 9324 /* static */ 9325 void 9326 OSKext::considerRebuildOfPrelinkedKernel(void) 9327 { 9328 static bool requestedPrelink = false; 9329 OSReturn checkResult = kOSReturnError; 9330 OSSharedPtr<OSDictionary> prelinkRequest; 9331 OSSharedPtr<OSCollectionIterator> kextIterator; 9332 const OSSymbol * thisID = NULL; // do not release 9333 bool doRebuild = false; 9334 AbsoluteTime my_abstime; 9335 UInt64 my_ns; 9336 SInt32 delta_secs; 9337 9338 /* Only one auto rebuild per boot and only on boot from prelinked kernel */ 9339 if (requestedPrelink || !sPrelinkBoot) { 9340 return; 9341 } 9342 9343 /* no direct return from this point */ 9344 IORecursiveLockLock(sKextLock); 9345 9346 /* We need to wait for the IOKit daemon to get up and running with unloads already done 9347 * and any new startup kexts loaded. 9348 */ 9349 if (!sConsiderUnloadsExecuted || 9350 !sDeferredLoadSucceeded) { 9351 goto finish; 9352 } 9353 9354 /* we really only care about boot / system start up related kexts so bail 9355 * if we're here after REBUILD_MAX_TIME. 9356 */ 9357 if (!_OSKextInPrelinkRebuildWindow()) { 9358 OSKextLog(/* kext */ NULL, 9359 kOSKextLogArchiveFlag, 9360 "%s prebuild rebuild has expired", 9361 __FUNCTION__); 9362 requestedPrelink = true; 9363 goto finish; 9364 } 9365 9366 /* we do not want to trigger a rebuild if we get here too close to waking 9367 * up. (see radar 10233768) 9368 */ 9369 IORecursiveLockLock(sKextInnerLock); 9370 9371 clock_get_uptime(&my_abstime); 9372 delta_secs = MINIMUM_WAKEUP_SECONDS + 1; 9373 if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) { 9374 SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime); 9375 absolutetime_to_nanoseconds(my_abstime, &my_ns); 9376 delta_secs = (SInt32)(my_ns / NSEC_PER_SEC); 9377 } 9378 IORecursiveLockUnlock(sKextInnerLock); 9379 9380 if (delta_secs < MINIMUM_WAKEUP_SECONDS) { 9381 /* too close to time of last wake from sleep */ 9382 goto finish; 9383 } 9384 requestedPrelink = true; 9385 9386 /* Now it's time to see if we have a reason to rebuild. We may have done 9387 * some loads and unloads but the kernel cache didn't actually change. 9388 * We will rebuild if any kext is not marked prelinked AND is not in our 9389 * list of prelinked kexts that got unloaded. (see radar 9055303) 9390 */ 9391 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 9392 if (!kextIterator) { 9393 goto finish; 9394 } 9395 9396 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 9397 OSKext * thisKext; // do not release 9398 9399 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 9400 if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) { 9401 continue; 9402 } 9403 9404 if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) { 9405 continue; 9406 } 9407 /* kext is loaded and was not in current kernel cache so let's rebuild 9408 */ 9409 doRebuild = true; 9410 OSKextLog(/* kext */ NULL, 9411 kOSKextLogArchiveFlag, 9412 "considerRebuildOfPrelinkedKernel %s triggered rebuild", 9413 thisKext->bundleID->getCStringNoCopy()); 9414 break; 9415 } 9416 sUnloadedPrelinkedKexts->flushCollection(); 9417 9418 if (!doRebuild) { 9419 goto finish; 9420 } 9421 9422 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink, 9423 prelinkRequest); 9424 if (checkResult != kOSReturnSuccess) { 9425 goto finish; 9426 } 9427 9428 if (!sKernelRequests->setObject(prelinkRequest.get())) { 9429 goto finish; 9430 } 9431 9432 OSKext::pingIOKitDaemon(); 9433 9434 finish: 9435 IORecursiveLockUnlock(sKextLock); 9436 9437 return; 9438 } 9439 9440 #else /* !CONFIG_KXLD */ 9441 9442 void 9443 OSKext::considerRebuildOfPrelinkedKernel(void) 9444 { 9445 /* in a non-dynamic kext loading world, there is never a reason to rebuild */ 9446 return; 9447 } 9448 9449 #endif /* CONFIG_KXLD */ 9450 9451 #if PRAGMA_MARK 9452 #pragma mark Dependencies 9453 #endif 9454 /********************************************************************* 9455 *********************************************************************/ 9456 bool 9457 OSKext::resolveDependencies( 9458 OSArray * loopStack) 9459 { 9460 bool result = false; 9461 OSSharedPtr<OSArray> localLoopStack; 9462 bool addedToLoopStack = false; 9463 OSDictionary * libraries = NULL; // do not release 9464 OSSharedPtr<OSCollectionIterator> libraryIterator; 9465 OSString * libraryID = NULL; // do not release 9466 OSKext * libraryKext = NULL; // do not release 9467 bool hasRawKernelDependency = false; 9468 bool hasKernelDependency = false; 9469 bool hasKPIDependency = false; 9470 bool hasPrivateKPIDependency = false; 9471 unsigned int count; 9472 9473 #if CONFIG_KXLD 9474 OSString * infoString = NULL; // do not release 9475 OSString * readableString = NULL; // do not release 9476 #endif // CONFIG_KXLD 9477 9478 /* A kernel component will automatically have this flag set, 9479 * and a loaded kext should also have it set (as should all its 9480 * loaded dependencies). 9481 */ 9482 if (flags.hasAllDependencies) { 9483 result = true; 9484 goto finish; 9485 } 9486 9487 /* Check for loops in the dependency graph. 9488 */ 9489 if (loopStack) { 9490 if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) { 9491 OSKextLog(this, 9492 kOSKextLogErrorLevel | 9493 kOSKextLogDependenciesFlag, 9494 "Kext %s has a dependency loop; can't resolve dependencies.", 9495 getIdentifierCString()); 9496 goto finish; 9497 } 9498 } else { 9499 OSKextLog(this, 9500 kOSKextLogStepLevel | 9501 kOSKextLogDependenciesFlag, 9502 "Kext %s resolving dependencies.", 9503 getIdentifierCString()); 9504 9505 localLoopStack = OSArray::withCapacity(6); // any small capacity will do 9506 if (!localLoopStack) { 9507 OSKextLog(this, 9508 kOSKextLogErrorLevel | 9509 kOSKextLogDependenciesFlag, 9510 "Kext %s can't create bookkeeping stack to resolve dependencies.", 9511 getIdentifierCString()); 9512 goto finish; 9513 } 9514 loopStack = localLoopStack.get(); 9515 } 9516 if (!loopStack->setObject(this)) { 9517 OSKextLog(this, 9518 kOSKextLogErrorLevel | 9519 kOSKextLogDependenciesFlag, 9520 "Kext %s - internal error resolving dependencies.", 9521 getIdentifierCString()); 9522 goto finish; 9523 } 9524 addedToLoopStack = true; 9525 9526 /* Purge any existing kexts in the dependency list and start over. 9527 */ 9528 flushDependencies(); 9529 if (dependencies) { 9530 OSKextLog(this, 9531 kOSKextLogErrorLevel | 9532 kOSKextLogDependenciesFlag, 9533 "Kext %s - internal error resolving dependencies.", 9534 getIdentifierCString()); 9535 } 9536 9537 libraries = OSDynamicCast(OSDictionary, 9538 getPropertyForHostArch(kOSBundleLibrariesKey)); 9539 if (libraries == NULL || libraries->getCount() == 0) { 9540 OSKextLog(this, 9541 kOSKextLogErrorLevel | 9542 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 9543 "Kext %s - can't resolve dependencies; %s missing/invalid type.", 9544 getIdentifierCString(), kOSBundleLibrariesKey); 9545 goto finish; 9546 } 9547 9548 /* Make a new array to hold the dependencies (flush freed the old one). 9549 */ 9550 dependencies = OSArray::withCapacity(libraries->getCount()); 9551 if (!dependencies) { 9552 OSKextLog(this, 9553 kOSKextLogErrorLevel | 9554 kOSKextLogDependenciesFlag, 9555 "Kext %s - can't allocate dependencies array.", 9556 getIdentifierCString()); 9557 goto finish; 9558 } 9559 9560 // xxx - compat: We used to add an implicit dependency on kernel 6.0 9561 // xxx - compat: if none were declared. 9562 9563 libraryIterator = OSCollectionIterator::withCollection(libraries); 9564 if (!libraryIterator) { 9565 OSKextLog(this, 9566 kOSKextLogErrorLevel | 9567 kOSKextLogDependenciesFlag, 9568 "Kext %s - can't allocate dependencies iterator.", 9569 getIdentifierCString()); 9570 goto finish; 9571 } 9572 9573 while ((libraryID = OSDynamicCast(OSString, 9574 libraryIterator->getNextObject()))) { 9575 const char * library_id = libraryID->getCStringNoCopy(); 9576 9577 OSString * libraryVersion = OSDynamicCast(OSString, 9578 libraries->getObject(libraryID)); 9579 if (libraryVersion == NULL) { 9580 OSKextLog(this, 9581 kOSKextLogErrorLevel | 9582 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 9583 "Kext %s - illegal type in OSBundleLibraries.", 9584 getIdentifierCString()); 9585 goto finish; 9586 } 9587 9588 OSKextVersion libraryVers = 9589 OSKextParseVersionString(libraryVersion->getCStringNoCopy()); 9590 if (libraryVers == -1) { 9591 OSKextLog(this, 9592 kOSKextLogErrorLevel | 9593 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 9594 "Kext %s - invalid library version %s.", 9595 getIdentifierCString(), 9596 libraryVersion->getCStringNoCopy()); 9597 goto finish; 9598 } 9599 9600 libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID)); 9601 if (libraryKext == NULL) { 9602 OSKextLog(this, 9603 kOSKextLogErrorLevel | 9604 kOSKextLogDependenciesFlag, 9605 "Kext %s - library kext %s not found.", 9606 getIdentifierCString(), library_id); 9607 goto finish; 9608 } 9609 9610 if (!libraryKext->isCompatibleWithVersion(libraryVers)) { 9611 OSKextLog(this, 9612 kOSKextLogErrorLevel | 9613 kOSKextLogDependenciesFlag, 9614 "Kext %s - library kext %s not compatible " 9615 "with requested version %s.", 9616 getIdentifierCString(), library_id, 9617 libraryVersion->getCStringNoCopy()); 9618 goto finish; 9619 } 9620 9621 /* If a nonprelinked library somehow got into the mix for a 9622 * prelinked kext, at any point in the chain, we must fail 9623 * because the prelinked relocs for the library will be all wrong. 9624 */ 9625 if (this->isPrelinked() && 9626 libraryKext->declaresExecutable() && 9627 !libraryKext->isPrelinked()) { 9628 OSKextLog(this, 9629 kOSKextLogErrorLevel | 9630 kOSKextLogDependenciesFlag, 9631 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.", 9632 getIdentifierCString(), library_id, 9633 libraryVersion->getCStringNoCopy()); 9634 goto finish; 9635 } 9636 9637 if (!libraryKext->resolveDependencies(loopStack)) { 9638 goto finish; 9639 } 9640 9641 /* Add the library directly only if it has an executable to link. 9642 * Otherwise it's just used to collect other dependencies, so put 9643 * *its* dependencies on the list for this kext. 9644 */ 9645 // xxx - We are losing info here; would like to make fake entries or 9646 // xxx - keep these in the dependency graph for loaded kexts. 9647 // xxx - I really want to make kernel components not a special case! 9648 if (libraryKext->declaresExecutable() || 9649 libraryKext->isInterface()) { 9650 if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) { 9651 dependencies->setObject(libraryKext); 9652 9653 OSKextLog(this, 9654 kOSKextLogDetailLevel | 9655 kOSKextLogDependenciesFlag, 9656 "Kext %s added dependency %s.", 9657 getIdentifierCString(), 9658 libraryKext->getIdentifierCString()); 9659 } 9660 } else { 9661 int numLibDependencies = libraryKext->getNumDependencies(); 9662 OSArray * libraryDependencies = libraryKext->getDependencies(); 9663 int index; 9664 9665 if (numLibDependencies) { 9666 // xxx - this msg level should be 1 lower than the per-kext one 9667 OSKextLog(this, 9668 kOSKextLogDetailLevel | 9669 kOSKextLogDependenciesFlag, 9670 "Kext %s pulling %d dependencies from codeless library %s.", 9671 getIdentifierCString(), 9672 numLibDependencies, 9673 libraryKext->getIdentifierCString()); 9674 } 9675 for (index = 0; index < numLibDependencies; index++) { 9676 OSKext * thisLibDependency = OSDynamicCast(OSKext, 9677 libraryDependencies->getObject(index)); 9678 if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) { 9679 dependencies->setObject(thisLibDependency); 9680 OSKextLog(this, 9681 kOSKextLogDetailLevel | 9682 kOSKextLogDependenciesFlag, 9683 "Kext %s added dependency %s from codeless library %s.", 9684 getIdentifierCString(), 9685 thisLibDependency->getIdentifierCString(), 9686 libraryKext->getIdentifierCString()); 9687 } 9688 } 9689 } 9690 9691 if ((strlen(library_id) == strlen(KERNEL_LIB)) && 9692 0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) { 9693 hasRawKernelDependency = true; 9694 } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) { 9695 hasKernelDependency = true; 9696 } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) { 9697 hasKPIDependency = true; 9698 if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) { 9699 hasPrivateKPIDependency = true; 9700 } 9701 } 9702 } 9703 9704 if (hasRawKernelDependency) { 9705 OSKextLog(this, 9706 kOSKextLogErrorLevel | 9707 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 9708 "Error - kext %s declares a dependency on %s, which is not permitted.", 9709 getIdentifierCString(), KERNEL_LIB); 9710 goto finish; 9711 } 9712 #if __LP64__ 9713 if (hasKernelDependency) { 9714 OSKextLog(this, 9715 kOSKextLogErrorLevel | 9716 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 9717 "Error - kext %s declares %s dependencies. " 9718 "Only %s* dependencies are supported for 64-bit kexts.", 9719 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 9720 goto finish; 9721 } 9722 if (!hasKPIDependency) { 9723 OSKextLog(this, 9724 kOSKextLogWarningLevel | 9725 kOSKextLogDependenciesFlag, 9726 "Warning - kext %s declares no %s* dependencies. " 9727 "If it uses any KPIs, the link may fail with undefined symbols.", 9728 getIdentifierCString(), KPI_LIB_PREFIX); 9729 } 9730 #else /* __LP64__ */ 9731 // xxx - will change to flatly disallow "kernel" dependencies at some point 9732 // xxx - is it invalid to do both "com.apple.kernel" and any 9733 // xxx - "com.apple.kernel.*"? 9734 9735 if (hasKernelDependency && hasKPIDependency) { 9736 OSKextLog(this, 9737 kOSKextLogWarningLevel | 9738 kOSKextLogDependenciesFlag, 9739 "Warning - kext %s has immediate dependencies on both " 9740 "%s* and %s* components; use only one style.", 9741 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 9742 } 9743 9744 if (!hasKernelDependency && !hasKPIDependency) { 9745 // xxx - do we want to use validation flag for these too? 9746 OSKextLog(this, 9747 kOSKextLogWarningLevel | 9748 kOSKextLogDependenciesFlag, 9749 "Warning - %s declares no kernel dependencies; using %s.", 9750 getIdentifierCString(), KERNEL6_LIB); 9751 OSKext * kernelKext = OSDynamicCast(OSKext, 9752 sKextsByID->getObject(KERNEL6_LIB)); 9753 if (kernelKext) { 9754 dependencies->setObject(kernelKext); 9755 } else { 9756 OSKextLog(this, 9757 kOSKextLogErrorLevel | 9758 kOSKextLogDependenciesFlag, 9759 "Error - Library %s not found for %s.", 9760 KERNEL6_LIB, getIdentifierCString()); 9761 } 9762 } 9763 9764 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of 9765 * its indirect dependencies to simulate old-style linking. XXX - Should 9766 * check for duplicates. 9767 */ 9768 if (!hasKPIDependency) { 9769 unsigned int i; 9770 9771 flags.hasBleedthrough = true; 9772 9773 count = getNumDependencies(); 9774 9775 /* We add to the dependencies array in this loop, but do not iterate 9776 * past its original count. 9777 */ 9778 for (i = 0; i < count; i++) { 9779 OSKext * dependencyKext = OSDynamicCast(OSKext, 9780 dependencies->getObject(i)); 9781 dependencyKext->addBleedthroughDependencies(dependencies.get()); 9782 } 9783 } 9784 #endif /* __LP64__ */ 9785 9786 #if CONFIG_KXLD 9787 /* 9788 * If we're not dynamically linking kexts, then we don't need to check 9789 * copyright strings. The linker in user space has already done this. 9790 */ 9791 if (hasPrivateKPIDependency) { 9792 bool hasApplePrefix = false; 9793 bool infoCopyrightIsValid = false; 9794 bool readableCopyrightIsValid = false; 9795 9796 hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(), 9797 APPLE_KEXT_PREFIX); 9798 9799 infoString = OSDynamicCast(OSString, 9800 getPropertyForHostArch("CFBundleGetInfoString")); 9801 if (infoString) { 9802 infoCopyrightIsValid = 9803 kxld_validate_copyright_string(infoString->getCStringNoCopy()); 9804 } 9805 9806 readableString = OSDynamicCast(OSString, 9807 getPropertyForHostArch("NSHumanReadableCopyright")); 9808 if (readableString) { 9809 readableCopyrightIsValid = 9810 kxld_validate_copyright_string(readableString->getCStringNoCopy()); 9811 } 9812 9813 if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) { 9814 OSKextLog(this, 9815 kOSKextLogErrorLevel | 9816 kOSKextLogDependenciesFlag, 9817 "Error - kext %s declares a dependency on %s. " 9818 "Only Apple kexts may declare a dependency on %s.", 9819 getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI); 9820 goto finish; 9821 } 9822 } 9823 #endif // CONFIG_KXLD 9824 9825 result = true; 9826 flags.hasAllDependencies = 1; 9827 9828 finish: 9829 9830 if (addedToLoopStack) { 9831 count = loopStack->getCount(); 9832 if (count > 0 && (this == loopStack->getObject(count - 1))) { 9833 loopStack->removeObject(count - 1); 9834 } else { 9835 OSKextLog(this, 9836 kOSKextLogErrorLevel | 9837 kOSKextLogDependenciesFlag, 9838 "Kext %s - internal error resolving dependencies.", 9839 getIdentifierCString()); 9840 } 9841 } 9842 9843 if (result && localLoopStack) { 9844 OSKextLog(this, 9845 kOSKextLogStepLevel | 9846 kOSKextLogDependenciesFlag, 9847 "Kext %s successfully resolved dependencies.", 9848 getIdentifierCString()); 9849 } 9850 9851 return result; 9852 } 9853 9854 /********************************************************************* 9855 *********************************************************************/ 9856 bool 9857 OSKext::addBleedthroughDependencies(OSArray * anArray) 9858 { 9859 bool result = false; 9860 unsigned int dependencyIndex, dependencyCount; 9861 9862 dependencyCount = getNumDependencies(); 9863 9864 for (dependencyIndex = 0; 9865 dependencyIndex < dependencyCount; 9866 dependencyIndex++) { 9867 OSKext * dependency = OSDynamicCast(OSKext, 9868 dependencies->getObject(dependencyIndex)); 9869 if (!dependency) { 9870 OSKextLog(this, 9871 kOSKextLogErrorLevel | 9872 kOSKextLogDependenciesFlag, 9873 "Kext %s - internal error propagating compatibility dependencies.", 9874 getIdentifierCString()); 9875 goto finish; 9876 } 9877 if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) { 9878 anArray->setObject(dependency); 9879 } 9880 dependency->addBleedthroughDependencies(anArray); 9881 } 9882 9883 result = true; 9884 9885 finish: 9886 return result; 9887 } 9888 9889 /********************************************************************* 9890 *********************************************************************/ 9891 bool 9892 OSKext::flushDependencies(bool forceFlag) 9893 { 9894 bool result = false; 9895 9896 /* Only clear the dependencies if the kext isn't loaded; 9897 * we need the info for loaded kexts to track references. 9898 */ 9899 if (!isLoaded() || forceFlag) { 9900 if (dependencies) { 9901 // xxx - check level 9902 OSKextLog(this, 9903 kOSKextLogProgressLevel | 9904 kOSKextLogDependenciesFlag, 9905 "Kext %s flushing dependencies.", 9906 getIdentifierCString()); 9907 dependencies.reset(); 9908 } 9909 if (!isKernelComponent()) { 9910 flags.hasAllDependencies = 0; 9911 } 9912 result = true; 9913 } 9914 9915 return result; 9916 } 9917 9918 /********************************************************************* 9919 *********************************************************************/ 9920 uint32_t 9921 OSKext::getNumDependencies(void) 9922 { 9923 if (!dependencies) { 9924 return 0; 9925 } 9926 return dependencies->getCount(); 9927 } 9928 9929 /********************************************************************* 9930 *********************************************************************/ 9931 OSArray * 9932 OSKext::getDependencies(void) 9933 { 9934 return dependencies.get(); 9935 } 9936 9937 bool 9938 OSKext::hasDependency(const OSSymbol * depID) 9939 { 9940 bool result __block; 9941 9942 if (depID == getIdentifier()) { 9943 return true; 9944 } 9945 if (!dependencies) { 9946 return false; 9947 } 9948 result = false; 9949 dependencies->iterateObjects(^bool (OSObject * obj) { 9950 OSKext * kext; 9951 kext = OSDynamicCast(OSKext, obj); 9952 if (!kext) { 9953 return false; 9954 } 9955 result = (depID == kext->getIdentifier()); 9956 return result; 9957 }); 9958 return result; 9959 } 9960 9961 #if PRAGMA_MARK 9962 #pragma mark OSMetaClass Support 9963 #endif 9964 /********************************************************************* 9965 *********************************************************************/ 9966 OSReturn 9967 OSKext::addClass( 9968 OSMetaClass * aClass, 9969 uint32_t numClasses) 9970 { 9971 OSReturn result = kOSMetaClassNoInsKModSet; 9972 9973 if (!metaClasses) { 9974 metaClasses = OSSet::withCapacity(numClasses); 9975 if (!metaClasses) { 9976 goto finish; 9977 } 9978 } 9979 9980 if (metaClasses->containsObject(aClass)) { 9981 OSKextLog(this, 9982 kOSKextLogWarningLevel | 9983 kOSKextLogLoadFlag, 9984 "Notice - kext %s has already registered class %s.", 9985 getIdentifierCString(), 9986 aClass->getClassName()); 9987 result = kOSReturnSuccess; 9988 goto finish; 9989 } 9990 9991 if (!metaClasses->setObject(aClass)) { 9992 goto finish; 9993 } else { 9994 OSKextLog(this, 9995 kOSKextLogDetailLevel | 9996 kOSKextLogLoadFlag, 9997 "Kext %s registered class %s.", 9998 getIdentifierCString(), 9999 aClass->getClassName()); 10000 } 10001 10002 if (!flags.autounloadEnabled) { 10003 const OSMetaClass * metaScan = NULL; // do not release 10004 10005 for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) { 10006 if (metaScan == OSTypeID(IOService)) { 10007 OSKextLog(this, 10008 kOSKextLogProgressLevel | 10009 kOSKextLogLoadFlag, 10010 "Kext %s has IOService subclass %s; enabling autounload.", 10011 getIdentifierCString(), 10012 aClass->getClassName()); 10013 10014 flags.autounloadEnabled = (0 == flags.unloadUnsupported); 10015 break; 10016 } 10017 } 10018 } 10019 10020 notifyAddClassObservers(this, aClass, flags); 10021 10022 result = kOSReturnSuccess; 10023 10024 finish: 10025 if (result != kOSReturnSuccess) { 10026 OSKextLog(this, 10027 kOSKextLogErrorLevel | 10028 kOSKextLogLoadFlag, 10029 "Kext %s failed to register class %s.", 10030 getIdentifierCString(), 10031 aClass->getClassName()); 10032 } 10033 10034 return result; 10035 } 10036 10037 /********************************************************************* 10038 *********************************************************************/ 10039 OSReturn 10040 OSKext::removeClass( 10041 OSMetaClass * aClass) 10042 { 10043 OSReturn result = kOSMetaClassNoKModSet; 10044 10045 if (!metaClasses) { 10046 goto finish; 10047 } 10048 10049 if (!metaClasses->containsObject(aClass)) { 10050 OSKextLog(this, 10051 kOSKextLogWarningLevel | 10052 kOSKextLogLoadFlag, 10053 "Notice - kext %s asked to unregister unknown class %s.", 10054 getIdentifierCString(), 10055 aClass->getClassName()); 10056 result = kOSReturnSuccess; 10057 goto finish; 10058 } 10059 10060 OSKextLog(this, 10061 kOSKextLogDetailLevel | 10062 kOSKextLogLoadFlag, 10063 "Kext %s unregistering class %s.", 10064 getIdentifierCString(), 10065 aClass->getClassName()); 10066 10067 metaClasses->removeObject(aClass); 10068 10069 notifyRemoveClassObservers(this, aClass, flags); 10070 10071 result = kOSReturnSuccess; 10072 10073 finish: 10074 if (result != kOSReturnSuccess) { 10075 OSKextLog(this, 10076 kOSKextLogErrorLevel | 10077 kOSKextLogLoadFlag, 10078 "Failed to unregister kext %s class %s.", 10079 getIdentifierCString(), 10080 aClass->getClassName()); 10081 } 10082 return result; 10083 } 10084 10085 /********************************************************************* 10086 *********************************************************************/ 10087 OSSet * 10088 OSKext::getMetaClasses(void) 10089 { 10090 return metaClasses.get(); 10091 } 10092 10093 /********************************************************************* 10094 *********************************************************************/ 10095 bool 10096 OSKext::hasOSMetaClassInstances(void) 10097 { 10098 bool result = false; 10099 OSSharedPtr<OSCollectionIterator> classIterator; 10100 OSMetaClass * checkClass = NULL; // do not release 10101 10102 if (!metaClasses) { 10103 goto finish; 10104 } 10105 10106 classIterator = OSCollectionIterator::withCollection(metaClasses.get()); 10107 if (!classIterator) { 10108 // xxx - log alloc failure? 10109 goto finish; 10110 } 10111 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 10112 if (checkClass->getInstanceCount()) { 10113 result = true; 10114 goto finish; 10115 } 10116 } 10117 10118 finish: 10119 return result; 10120 } 10121 10122 /********************************************************************* 10123 *********************************************************************/ 10124 /* static */ 10125 void 10126 OSKext::reportOSMetaClassInstances( 10127 const char * kextIdentifier, 10128 OSKextLogSpec msgLogSpec) 10129 { 10130 OSSharedPtr<OSKext> theKext; 10131 10132 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 10133 if (!theKext) { 10134 goto finish; 10135 } 10136 10137 theKext->reportOSMetaClassInstances(msgLogSpec); 10138 finish: 10139 return; 10140 } 10141 10142 /********************************************************************* 10143 *********************************************************************/ 10144 void 10145 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec) 10146 { 10147 OSSharedPtr<OSCollectionIterator> classIterator; 10148 OSMetaClass * checkClass = NULL; // do not release 10149 10150 if (!metaClasses) { 10151 goto finish; 10152 } 10153 10154 classIterator = OSCollectionIterator::withCollection(metaClasses.get()); 10155 if (!classIterator) { 10156 goto finish; 10157 } 10158 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 10159 if (checkClass->getInstanceCount()) { 10160 OSKextLog(this, 10161 msgLogSpec, 10162 " Kext %s class %s has %d instance%s.", 10163 getIdentifierCString(), 10164 checkClass->getClassName(), 10165 checkClass->getInstanceCount(), 10166 checkClass->getInstanceCount() == 1 ? "" : "s"); 10167 } 10168 } 10169 10170 finish: 10171 return; 10172 } 10173 10174 #if PRAGMA_MARK 10175 #pragma mark User-Space Requests 10176 #endif 10177 10178 static kern_return_t 10179 patchDextLaunchRequests(task_t calling_task, OSArray *requests) 10180 { 10181 OSReturn result = kOSReturnSuccess; 10182 for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) { 10183 OSDictionary * request = NULL; //do not release 10184 IOUserServerCheckInToken * token = NULL; //do not release 10185 OSString * requestPredicate = NULL; //do not release 10186 OSSharedPtr<OSNumber> portNameNumber; 10187 mach_port_name_t portName = 0; 10188 request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex)); 10189 if (!request) { 10190 OSKextLog(/* kext */ NULL, 10191 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10192 "Elements of request should be of type OSDictionary"); 10193 result = kOSKextReturnInternalError; 10194 goto finish; 10195 } 10196 requestPredicate = _OSKextGetRequestPredicate(request); 10197 if (!requestPredicate) { 10198 OSKextLog(/* kext */ NULL, 10199 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10200 "Failed to get request predicate"); 10201 result = kOSKextReturnInternalError; 10202 goto finish; 10203 } 10204 // is this a dext launch? 10205 if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) { 10206 token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken)); 10207 if (!token) { 10208 OSKextLog(/* kext */ NULL, 10209 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10210 "Could not find a IOUserServerCheckInToken in daemon launch request."); 10211 result = kOSKextReturnInternalError; 10212 goto finish; 10213 } 10214 portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT); 10215 if (portName == 0 || portName == MACH_PORT_DEAD) { 10216 OSKextLog(/* kext */ NULL, 10217 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10218 "Could not create send right for object."); 10219 result = kOSKextReturnInternalError; 10220 goto finish; 10221 } 10222 // Store the mach port name as a OSNumber 10223 portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName)); 10224 if (!portNameNumber) { 10225 OSKextLog(/* kext */ NULL, 10226 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10227 "Could not create OSNumber object."); 10228 result = kOSKextReturnNoMemory; 10229 goto finish; 10230 } 10231 if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) { 10232 OSKextLog(/* kext */ NULL, 10233 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10234 "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken); 10235 result = kOSKextReturnNoMemory; 10236 goto finish; 10237 } 10238 } 10239 finish: 10240 if (result != kOSReturnSuccess) { 10241 break; 10242 } 10243 } 10244 return result; 10245 } 10246 10247 bool 10248 OSKext::iokitDaemonActive() 10249 { 10250 bool result; 10251 IORecursiveLockLock(sKextLock); 10252 result = sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot; 10253 IORecursiveLockUnlock(sKextLock); 10254 return result; 10255 } 10256 10257 /********************************************************************* 10258 * XXX - this function is a big ugly mess 10259 *********************************************************************/ 10260 /* static */ 10261 OSReturn 10262 OSKext::handleRequest( 10263 host_priv_t hostPriv, 10264 OSKextLogSpec clientLogFilter, 10265 char * requestBuffer, 10266 uint32_t requestLength, 10267 char ** responseOut, 10268 uint32_t * responseLengthOut, 10269 char ** logInfoOut, 10270 uint32_t * logInfoLengthOut) 10271 { 10272 OSReturn result = kOSReturnError; 10273 kern_return_t kmem_result = KERN_FAILURE; 10274 10275 char * response = NULL; // returned by reference 10276 uint32_t responseLength = 0; 10277 10278 bool taskCanManageAllKCs = false; 10279 bool taskOnlyManagesBootKC = false; 10280 10281 OSSharedPtr<OSObject> parsedXML; 10282 OSDictionary * requestDict = NULL; // do not release 10283 OSSharedPtr<OSString> errorString; 10284 10285 OSSharedPtr<OSObject> responseObject; 10286 10287 OSSharedPtr<OSSerialize> serializer; 10288 10289 OSSharedPtr<OSArray> logInfoArray; 10290 10291 OSString * predicate = NULL; // do not release 10292 OSString * kextIdentifier = NULL; // do not release 10293 OSArray * kextIdentifiers = NULL; // do not release 10294 OSKext * theKext = NULL; // do not release 10295 OSBoolean * boolArg = NULL; // do not release 10296 10297 10298 IORecursiveLockLock(sKextLock); 10299 10300 if (responseOut) { 10301 *responseOut = NULL; 10302 *responseLengthOut = 0; 10303 } 10304 if (logInfoOut) { 10305 *logInfoOut = NULL; 10306 *logInfoLengthOut = 0; 10307 } 10308 10309 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 10310 10311 /* XML must be nul-terminated. 10312 */ 10313 if (requestBuffer[requestLength - 1] != '\0') { 10314 OSKextLog(/* kext */ NULL, 10315 kOSKextLogErrorLevel | 10316 kOSKextLogIPCFlag, 10317 "Invalid request from user space (not nul-terminated)."); 10318 result = kOSKextReturnBadData; 10319 goto finish; 10320 } 10321 parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString); 10322 if (parsedXML) { 10323 requestDict = OSDynamicCast(OSDictionary, parsedXML.get()); 10324 } 10325 if (!requestDict) { 10326 const char * errorCString = "(unknown error)"; 10327 10328 if (errorString && errorString->getCStringNoCopy()) { 10329 errorCString = errorString->getCStringNoCopy(); 10330 } else if (parsedXML) { 10331 errorCString = "not a dictionary"; 10332 } 10333 OSKextLog(/* kext */ NULL, 10334 kOSKextLogErrorLevel | 10335 kOSKextLogIPCFlag, 10336 "Error unserializing request from user space: %s.", 10337 errorCString); 10338 result = kOSKextReturnSerialization; 10339 goto finish; 10340 } 10341 10342 predicate = _OSKextGetRequestPredicate(requestDict); 10343 if (!predicate) { 10344 OSKextLog(/* kext */ NULL, 10345 kOSKextLogErrorLevel | 10346 kOSKextLogIPCFlag, 10347 "Recieved kext request from user space with no predicate."); 10348 result = kOSKextReturnInvalidArgument; 10349 goto finish; 10350 } 10351 OSKextLog(/* kext */ NULL, 10352 kOSKextLogDebugLevel | 10353 kOSKextLogIPCFlag, 10354 "Received '%s' request from user space.", 10355 predicate->getCStringNoCopy()); 10356 10357 /* 10358 * All management of file sets requires an entitlement 10359 */ 10360 result = kOSKextReturnNotPrivileged; 10361 if (predicate->isEqualTo(kKextRequestPredicateUnload) || 10362 predicate->isEqualTo(kKextRequestPredicateStart) || 10363 predicate->isEqualTo(kKextRequestPredicateStop) || 10364 predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) || 10365 predicate->isEqualTo(kKextRequestPredicateSendResource) || 10366 predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) || 10367 predicate->isEqualTo(kKextRequestPredicateLoadCodeless) || 10368 predicate->isEqualTo(kKextRequestPredicateLoadFromKC) || 10369 predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) || 10370 predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) || 10371 predicate->isEqualTo(kKextRequestPredicateDaemonReady)) { 10372 if (!iokitDaemonAvailable()) { 10373 panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable"); 10374 } 10375 if (hostPriv == HOST_PRIV_NULL) { 10376 OSKextLog(/* kext */ NULL, 10377 kOSKextLogErrorLevel | 10378 kOSKextLogIPCFlag, 10379 "Access Failure - must be root user."); 10380 goto finish; 10381 } 10382 taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE; 10383 taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE; 10384 10385 if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) { 10386 OSKextLog(/* kext */ NULL, 10387 kOSKextLogErrorLevel | 10388 kOSKextLogIPCFlag, 10389 "Access Failure - client not entitled to manage file sets."); 10390 goto finish; 10391 } 10392 10393 /* 10394 * The OnlyBootKC entitlement restricts the 10395 * collection-management entitlement to only managing kexts in 10396 * the BootKC. All other predicates that alter global state or 10397 * add new KCs are disallowed. 10398 */ 10399 if (taskOnlyManagesBootKC && 10400 (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) || 10401 predicate->isEqualTo(kKextRequestPredicateSendResource) || 10402 predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) || 10403 predicate->isEqualTo(kKextRequestPredicateLoadCodeless) || 10404 predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) || 10405 predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) || 10406 predicate->isEqualTo(kKextRequestPredicateDaemonReady))) { 10407 OSKextLog(/* kext */ NULL, 10408 kOSKextLogErrorLevel | 10409 kOSKextLogIPCFlag, 10410 "Access Failure - client not entitled to manage non-primary KCs"); 10411 goto finish; 10412 } 10413 10414 /* 10415 * If we get here, then the process either has the full KC 10416 * management entitlement, or it has the BootKC-only 10417 * entitlement and the request is about the BootKC. 10418 */ 10419 } 10420 10421 /* Get common args in anticipation of use. 10422 */ 10423 kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument( 10424 requestDict, kKextRequestArgumentBundleIdentifierKey)); 10425 kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 10426 requestDict, kKextRequestArgumentBundleIdentifierKey)); 10427 if (kextIdentifier) { 10428 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 10429 } 10430 boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 10431 requestDict, kKextRequestArgumentValueKey)); 10432 10433 if (taskOnlyManagesBootKC && 10434 theKext && 10435 theKext->isInFileset() && 10436 theKext->kc_type != KCKindPrimary) { 10437 OSKextLog(/* kext */ NULL, 10438 kOSKextLogErrorLevel | 10439 kOSKextLogIPCFlag, 10440 "Access Failure - client not entitled to manage kext in non-primary KC"); 10441 result = kOSKextReturnNotPrivileged; 10442 goto finish; 10443 } 10444 result = kOSKextReturnInvalidArgument; 10445 10446 if (predicate->isEqualTo(kKextRequestPredicateStart)) { 10447 if (!kextIdentifier) { 10448 OSKextLog(/* kext */ NULL, 10449 kOSKextLogErrorLevel | 10450 kOSKextLogIPCFlag, 10451 "Invalid arguments to kext start request."); 10452 } else if (!theKext) { 10453 OSKextLog(/* kext */ NULL, 10454 kOSKextLogErrorLevel | 10455 kOSKextLogIPCFlag, 10456 "Kext %s not found for start request.", 10457 kextIdentifier->getCStringNoCopy()); 10458 result = kOSKextReturnNotFound; 10459 } else { 10460 result = theKext->start(); 10461 } 10462 } else if (predicate->isEqualTo(kKextRequestPredicateStop)) { 10463 if (!kextIdentifier) { 10464 OSKextLog(/* kext */ NULL, 10465 kOSKextLogErrorLevel | 10466 kOSKextLogIPCFlag, 10467 "Invalid arguments to kext stop request."); 10468 } else if (!theKext) { 10469 OSKextLog(/* kext */ NULL, 10470 kOSKextLogErrorLevel | 10471 kOSKextLogIPCFlag, 10472 "Kext %s not found for stop request.", 10473 kextIdentifier->getCStringNoCopy()); 10474 result = kOSKextReturnNotFound; 10475 } else { 10476 result = theKext->stop(); 10477 } 10478 } else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) { 10479 result = OSKext::setMissingAuxKCBundles(requestDict); 10480 } else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) { 10481 if (!kextIdentifier) { 10482 OSKextLog(/* kext */ NULL, 10483 kOSKextLogErrorLevel | 10484 kOSKextLogIPCFlag, 10485 "Invalid arguments to AuxKC Bundle Available request."); 10486 } else { 10487 result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict); 10488 } 10489 } else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) { 10490 if (!kextIdentifier) { 10491 OSKextLog(/* kext */ NULL, 10492 kOSKextLogErrorLevel | 10493 kOSKextLogIPCFlag, 10494 "Invalid arguments to kext load from KC request."); 10495 } else if (!theKext) { 10496 OSKextLog(/* kext */ NULL, 10497 kOSKextLogErrorLevel | 10498 kOSKextLogIPCFlag, 10499 "Kext %s not found for load from KC request.", 10500 kextIdentifier->getCStringNoCopy()); 10501 result = kOSKextReturnNotFound; 10502 } else if (!theKext->isInFileset()) { 10503 OSKextLog(/* kext */ NULL, 10504 kOSKextLogErrorLevel | 10505 kOSKextLogIPCFlag, 10506 "Kext %s does not exist in a KC: refusing to load.", 10507 kextIdentifier->getCStringNoCopy()); 10508 result = kOSKextReturnNotLoadable; 10509 } else { 10510 result = OSKext::loadKextFromKC(theKext, requestDict); 10511 } 10512 } else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) { 10513 if (!kextIdentifier) { 10514 OSKextLog(/* kext */ NULL, 10515 kOSKextLogErrorLevel | 10516 kOSKextLogIPCFlag, 10517 "Invalid arguments to codeless kext load interface (missing identifier)."); 10518 } else { 10519 result = OSKext::loadCodelessKext(kextIdentifier, requestDict); 10520 } 10521 } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) { 10522 if (!kextIdentifier) { 10523 OSKextLog(/* kext */ NULL, 10524 kOSKextLogErrorLevel | 10525 kOSKextLogIPCFlag, 10526 "Invalid arguments to kext unload request."); 10527 } else if (!theKext) { 10528 OSKextLog(/* kext */ NULL, 10529 kOSKextLogErrorLevel | 10530 kOSKextLogIPCFlag, 10531 "Kext %s not found for unload request.", 10532 kextIdentifier->getCStringNoCopy()); 10533 result = kOSKextReturnNotFound; 10534 } else { 10535 if (theKext->isDriverKit()) { 10536 result = OSKext::removeDext(theKext); 10537 } else { 10538 OSBoolean * terminateFlag = OSDynamicCast(OSBoolean, 10539 _OSKextGetRequestArgument(requestDict, 10540 kKextRequestArgumentTerminateIOServicesKey)); 10541 result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue); 10542 } 10543 } 10544 } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) { 10545 result = OSKext::dispatchResource(requestDict); 10546 } else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) { 10547 OSNumber *lookupNum = NULL; 10548 lookupNum = OSDynamicCast(OSNumber, 10549 _OSKextGetRequestArgument(requestDict, 10550 kKextRequestArgumentLookupAddressKey)); 10551 10552 responseObject = OSKext::copyKextUUIDForAddress(lookupNum); 10553 if (responseObject) { 10554 result = kOSReturnSuccess; 10555 } else { 10556 goto finish; 10557 } 10558 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) || 10559 predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) || 10560 predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection) || 10561 predicate->isEqualTo(kKextRequestPredicateGetDexts)) { 10562 OSBoolean * delayAutounloadBool = NULL; 10563 OSObject * infoKeysRaw = NULL; 10564 OSArray * infoKeys = NULL; 10565 uint32_t infoKeysCount = 0; 10566 10567 delayAutounloadBool = OSDynamicCast(OSBoolean, 10568 _OSKextGetRequestArgument(requestDict, 10569 kKextRequestArgumentDelayAutounloadKey)); 10570 10571 /* If asked to delay autounload, reset the timer if it's currently set. 10572 * (That is, don't schedule an unload if one isn't already pending. 10573 */ 10574 if (delayAutounloadBool == kOSBooleanTrue) { 10575 OSKext::considerUnloads(/* rescheduleOnly? */ true); 10576 } 10577 10578 infoKeysRaw = _OSKextGetRequestArgument(requestDict, 10579 kKextRequestArgumentInfoKeysKey); 10580 infoKeys = OSDynamicCast(OSArray, infoKeysRaw); 10581 if (infoKeysRaw && !infoKeys) { 10582 OSKextLog(/* kext */ NULL, 10583 kOSKextLogErrorLevel | 10584 kOSKextLogIPCFlag, 10585 "Invalid arguments to kext info request."); 10586 goto finish; 10587 } 10588 10589 if (infoKeys) { 10590 infoKeysCount = infoKeys->getCount(); 10591 for (uint32_t i = 0; i < infoKeysCount; i++) { 10592 if (!OSDynamicCast(OSString, infoKeys->getObject(i))) { 10593 OSKextLog(/* kext */ NULL, 10594 kOSKextLogErrorLevel | 10595 kOSKextLogIPCFlag, 10596 "Invalid arguments to kext info request."); 10597 goto finish; 10598 } 10599 } 10600 } 10601 10602 if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) { 10603 responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys); 10604 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) { 10605 responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys); 10606 } else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) { 10607 responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys); 10608 } else if (predicate->isEqualTo(kKextRequestPredicateGetDexts)) { 10609 responseObject = OSKext::copyDextsInfo(kextIdentifiers, infoKeys); 10610 } 10611 10612 if (!responseObject) { 10613 result = kOSKextReturnInternalError; 10614 } else { 10615 OSKextLog(/* kext */ NULL, 10616 kOSKextLogDebugLevel | 10617 kOSKextLogIPCFlag, 10618 "Returning loaded kext info."); 10619 result = kOSReturnSuccess; 10620 } 10621 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 10622 /* Hand the current sKernelRequests array to the caller 10623 * (who must release it), and make a new one. 10624 */ 10625 responseObject = os::move(sKernelRequests); 10626 sKernelRequests = OSArray::withCapacity(0); 10627 sPostedKextLoadIdentifiers->flushCollection(); 10628 OSKextLog(/* kext */ NULL, 10629 kOSKextLogDebugLevel | 10630 kOSKextLogIPCFlag, 10631 "Returning kernel requests."); 10632 result = kOSReturnSuccess; 10633 } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) { 10634 /* Return the set of all requested bundle identifiers */ 10635 responseObject = sAllKextLoadIdentifiers; 10636 OSKextLog(/* kext */ NULL, 10637 kOSKextLogDebugLevel | 10638 kOSKextLogIPCFlag, 10639 "Returning load requests."); 10640 result = kOSReturnSuccess; 10641 } else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) { 10642 printf("KextLog: Loading FileSet KC(s)\n"); 10643 result = OSKext::loadFileSetKexts(requestDict); 10644 } else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) { 10645 bool active = iokitDaemonActive(); 10646 printf("KextLog: " kIOKitDaemonName " is %s\n", active ? "active" : "not active"); 10647 if (sOSKextWasResetAfterUserspaceReboot) { 10648 printf("KextLog: was reset after userspace reboot\n"); 10649 } 10650 result = active ? kOSReturnSuccess : kIOReturnNotReady; 10651 } else { 10652 OSKextLog(/* kext */ NULL, 10653 kOSKextLogDebugLevel | 10654 kOSKextLogIPCFlag, 10655 "Received '%s' invalid request from user space.", 10656 predicate->getCStringNoCopy()); 10657 goto finish; 10658 } 10659 10660 /********** 10661 * Now we have handle the request, or not. Gather up the response & logging 10662 * info to ship to user space. 10663 *********/ 10664 10665 /* Note: Nothing in OSKext is supposed to retain requestDict, 10666 * but you never know.... 10667 */ 10668 if (requestDict->getRetainCount() > 1) { 10669 OSKextLog(/* kext */ NULL, 10670 kOSKextLogWarningLevel | 10671 kOSKextLogIPCFlag, 10672 "Request from user space still retained by a kext; " 10673 "probable memory leak."); 10674 } 10675 10676 if (responseOut && responseObject) { 10677 serializer = OSSerialize::withCapacity(0); 10678 if (!serializer) { 10679 result = kOSKextReturnNoMemory; 10680 goto finish; 10681 } 10682 /* 10683 * Before serializing the kernel requests, patch the dext launch requests so 10684 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the 10685 * IOUserServerCheckInToken kernel object. 10686 */ 10687 if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 10688 OSArray * requests = OSDynamicCast(OSArray, responseObject.get()); 10689 task_t calling_task = current_task(); 10690 if (!requests) { 10691 OSKextLog(/* kext */ NULL, 10692 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10693 "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests); 10694 result = kOSKextReturnInternalError; 10695 goto finish; 10696 } 10697 result = patchDextLaunchRequests(calling_task, requests); 10698 if (result != kOSReturnSuccess) { 10699 OSKextLog(/* kext */ NULL, 10700 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10701 "Failed to patch dext launch requests."); 10702 goto finish; 10703 } 10704 } 10705 10706 if (!responseObject->serialize(serializer.get())) { 10707 OSKextLog(/* kext */ NULL, 10708 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10709 "Failed to serialize response to request from user space."); 10710 result = kOSKextReturnSerialization; 10711 goto finish; 10712 } 10713 10714 response = (char *)serializer->text(); 10715 responseLength = serializer->getLength(); 10716 } 10717 10718 if (responseOut && response) { 10719 char * buffer; 10720 10721 /* This kmem_alloc sets the return value of the function. 10722 */ 10723 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, 10724 round_page(responseLength), KMA_DATA, VM_KERN_MEMORY_OSKEXT); 10725 if (kmem_result != KERN_SUCCESS) { 10726 OSKextLog(/* kext */ NULL, 10727 kOSKextLogErrorLevel | 10728 kOSKextLogIPCFlag, 10729 "Failed to copy response to request from user space."); 10730 result = kmem_result; 10731 goto finish; 10732 } else { 10733 /* 11981737 - clear uninitialized data in last page */ 10734 bzero((void *)(buffer + responseLength), 10735 (round_page(responseLength) - responseLength)); 10736 memcpy(buffer, response, responseLength); 10737 *responseOut = buffer; 10738 *responseLengthOut = responseLength; 10739 } 10740 } 10741 10742 finish: 10743 10744 /* Gather up the collected log messages for user space. Any messages 10745 * messages past this call will not make it up as log messages but 10746 * will be in the system log. Note that we ignore the return of the 10747 * serialize; it has no bearing on the operation at hand even if we 10748 * fail to get the log messages. 10749 */ 10750 logInfoArray = OSKext::clearUserSpaceLogFilter(); 10751 10752 if (logInfoArray && logInfoOut && logInfoLengthOut) { 10753 (void)OSKext::serializeLogInfo(logInfoArray.get(), 10754 logInfoOut, logInfoLengthOut); 10755 } 10756 10757 IORecursiveLockUnlock(sKextLock); 10758 10759 return result; 10760 } 10761 10762 #if PRAGMA_MARK 10763 #pragma mark Linked Kext Collection Support 10764 #endif 10765 10766 static int 10767 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount) 10768 { 10769 for (int i = 0; i < segCount; i++) { 10770 vm_offset_t segStart = segAddrs[i]; 10771 vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i]; 10772 10773 if (theAddr >= segStart && theAddr < segEnd) { 10774 return i; 10775 } 10776 } 10777 return -1; 10778 } 10779 10780 static void 10781 __slideOldKaslrOffsets(kernel_mach_header_t *mh, 10782 kernel_segment_command_t *kextTextSeg, 10783 OSData *kaslrOffsets) 10784 { 10785 static const char *plk_segNames[] = { 10786 "__TEXT", 10787 "__TEXT_EXEC", 10788 "__DATA", 10789 "__DATA_CONST", 10790 "__LINKEDIT", 10791 "__PRELINK_TEXT", 10792 "__PLK_TEXT_EXEC", 10793 "__PRELINK_DATA", 10794 "__PLK_DATA_CONST", 10795 "__PLK_LLVM_COV", 10796 "__PLK_LINKEDIT", 10797 "__PRELINK_INFO" 10798 }; 10799 static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0])); 10800 10801 unsigned long plk_segSizes[num_plk_seg]; 10802 vm_offset_t plk_segAddrs[num_plk_seg]; 10803 10804 for (size_t i = 0; i < num_plk_seg; i++) { 10805 plk_segSizes[i] = 0; 10806 plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]); 10807 } 10808 10809 uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr; 10810 10811 int slidKextAddrCount = 0; 10812 int badSlideAddr = 0; 10813 int badSlideTarget = 0; 10814 10815 struct kaslrPackedOffsets { 10816 uint32_t count; /* number of offsets */ 10817 uint32_t offsetsArray[]; /* offsets to slide */ 10818 }; 10819 const struct kaslrPackedOffsets *myOffsets = NULL; 10820 myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy(); 10821 10822 for (uint32_t j = 0; j < myOffsets->count; j++) { 10823 uint64_t slideOffset = (uint64_t)myOffsets->offsetsArray[j]; 10824 vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset); 10825 int slideAddrSegIndex = -1; 10826 int addrToSlideSegIndex = -1; 10827 10828 slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg); 10829 if (slideAddrSegIndex >= 0) { 10830 addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg); 10831 if (addrToSlideSegIndex < 0) { 10832 badSlideTarget++; 10833 continue; 10834 } 10835 } else { 10836 badSlideAddr++; 10837 continue; 10838 } 10839 10840 slidKextAddrCount++; 10841 *slideAddr = ml_static_slide(*slideAddr); 10842 } // for ... 10843 } 10844 10845 10846 10847 /******************************************************************** 10848 * addKextsFromKextCollection 10849 * 10850 * Input: MachO header of kext collection. The MachO is assumed to 10851 * have a section named 'info_seg_name,info_sect_name' that 10852 * contains a serialized XML info dictionary. This dictionary 10853 * contains a UUID, possibly a set of relocations (for older 10854 * kxld-built binaries), and an array of kext personalities. 10855 * 10856 ********************************************************************/ 10857 bool 10858 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh, 10859 OSDictionary *infoDict, const char *text_seg_name, 10860 OSData **kcUUID, kc_kind_t type) 10861 { 10862 bool result = false; 10863 10864 OSArray *kextArray = NULL; // do not release 10865 OSData *infoDictKCUUID = NULL; // do not release 10866 OSData *kaslrOffsets = NULL; // do not release 10867 10868 IORegistryEntry *registryRoot = NULL; // do not release 10869 OSSharedPtr<OSNumber> kcKextCount; 10870 10871 /* extract the KC UUID from the dictionary */ 10872 infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 10873 if (infoDictKCUUID) { 10874 if (infoDictKCUUID->getLength() != sizeof(uuid_t)) { 10875 panic("kcUUID length is %d, expected %lu", 10876 infoDictKCUUID->getLength(), sizeof(uuid_t)); 10877 } 10878 } 10879 10880 /* locate the array of kext dictionaries */ 10881 kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey)); 10882 if (!kextArray) { 10883 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 10884 "The given KC has no kext info dictionaries"); 10885 goto finish; 10886 } 10887 10888 /* 10889 * old-style KASLR offsets may be present in the info dictionary. If 10890 * we find them, use them and eventually slide them. 10891 */ 10892 kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey)); 10893 10894 /* 10895 * Before processing any kexts, locate the special kext bundle which 10896 * contains a list of kexts that we are to prevent from loading. 10897 */ 10898 createExcludeListFromPrelinkInfo(kextArray); 10899 10900 /* 10901 * Create OSKext objects for each kext we find in the array of kext 10902 * info plist dictionaries. 10903 */ 10904 for (int i = 0; i < (int)kextArray->getCount(); ++i) { 10905 OSDictionary *kextDict = NULL; 10906 kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i)); 10907 if (!kextDict) { 10908 OSKextLog(/* kext */ NULL, 10909 kOSKextLogErrorLevel | 10910 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 10911 "Kext info dictionary for kext #%d isn't a dictionary?", i); 10912 continue; 10913 } 10914 10915 /* 10916 * Create the kext for the entry, then release it, because the 10917 * kext system keeps a reference around until the kext is 10918 * explicitly removed. Any creation/registration failures are 10919 * already logged for us. 10920 */ 10921 withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type); 10922 } 10923 10924 /* 10925 * slide old-style kxld relocations 10926 * NOTE: this is still used on embedded KCs built with kcgen 10927 * TODO: Remove this once we use the new kext linker everywhere! 10928 */ 10929 if (kaslrOffsets && vm_kernel_slide > 0) { 10930 kernel_segment_command_t *text_segment = NULL; 10931 text_segment = getsegbynamefromheader(mh, text_seg_name); 10932 if (!text_segment) { 10933 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 10934 "Can't find a TEXT segment named '%s' in macho header", text_seg_name); 10935 goto finish; 10936 } 10937 10938 __slideOldKaslrOffsets(mh, text_segment, kaslrOffsets); 10939 /* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */ 10940 setAllVMAttributes(); 10941 } 10942 10943 /* Store the number of prelinked kexts in the registry so we can tell 10944 * when the system has been started from a prelinked kernel. 10945 */ 10946 registryRoot = IORegistryEntry::getRegistryRoot(); 10947 assert(registryRoot); 10948 10949 kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t)); 10950 assert(kcKextCount); 10951 if (kcKextCount) { 10952 OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey); 10953 OSNumber *num; 10954 num = OSDynamicCast(OSNumber, prop.get()); 10955 if (num) { 10956 kcKextCount->addValue(num->unsigned64BitValue()); 10957 } 10958 registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get()); 10959 } 10960 10961 OSKextLog(/* kext */ NULL, 10962 kOSKextLogProgressLevel | 10963 kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag | 10964 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 10965 "%u prelinked kexts", infoDict->getCount()); 10966 10967 10968 if (kcUUID && infoDictKCUUID) { 10969 *kcUUID = OSData::withData(infoDictKCUUID).detach(); 10970 } 10971 10972 result = true; 10973 10974 finish: 10975 return result; 10976 } 10977 10978 bool 10979 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh, 10980 OSDictionary *infoDict, const char *text_seg_name, 10981 OSSharedPtr<OSData> &kcUUID, kc_kind_t type) 10982 { 10983 OSData *result = NULL; 10984 bool success = addKextsFromKextCollection(mh, 10985 infoDict, 10986 text_seg_name, 10987 &result, 10988 type); 10989 if (success) { 10990 kcUUID.reset(result, OSNoRetain); 10991 } 10992 return success; 10993 } 10994 10995 static OSSharedPtr<OSObject> deferredAuxKCXML; 10996 bool 10997 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh, 10998 OSSharedPtr<OSObject> &parsedXML, kc_kind_t type) 10999 { 11000 if (type != KCKindAuxiliary) { 11001 return false; 11002 } 11003 11004 kernel_mach_header_t *_mh; 11005 _mh = (kernel_mach_header_t*)PE_get_kc_header(type); 11006 if (!_mh || _mh != mh) { 11007 return false; 11008 } 11009 11010 if (deferredAuxKCXML) { 11011 /* only allow this to be called once */ 11012 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 11013 "An Aux KC has already been registered for deferred processing."); 11014 return false; 11015 } 11016 11017 OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 11018 if (!infoDict) { 11019 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 11020 "The Aux KC has info dictionary"); 11021 return false; 11022 } 11023 11024 OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 11025 if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) { 11026 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 11027 "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey); 11028 return false; 11029 } 11030 11031 /* 11032 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid 11033 * sysctl can return the UUID to user space which will check this 11034 * value for errors. 11035 */ 11036 memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(), 11037 kcUUID->getLength()); 11038 uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string); 11039 auxkc_uuid_valid = TRUE; 11040 11041 deferredAuxKCXML = parsedXML; 11042 11043 return true; 11044 } 11045 11046 OSSharedPtr<OSObject> 11047 OSKext::consumeDeferredKextCollection(kc_kind_t type) 11048 { 11049 if (type != KCKindAuxiliary || !deferredAuxKCXML) { 11050 return NULL; 11051 } 11052 11053 return os::move(deferredAuxKCXML); 11054 } 11055 11056 #if PRAGMA_MARK 11057 #pragma mark Profile-Guided-Optimization Support 11058 #endif 11059 11060 // #include <InstrProfiling.h> 11061 extern "C" { 11062 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin, 11063 const char *DataEnd, 11064 const char *CountersBegin, 11065 const char *CountersEnd, 11066 const char *NamesBegin, 11067 const char *NamesEnd); 11068 int __llvm_profile_write_buffer_internal(char *Buffer, 11069 const char *DataBegin, 11070 const char *DataEnd, 11071 const char *CountersBegin, 11072 const char *CountersEnd, 11073 const char *NamesBegin, 11074 const char *NamesEnd); 11075 } 11076 11077 11078 static 11079 void 11080 OSKextPgoMetadataPut(char *pBuffer, 11081 size_t *position, 11082 size_t bufferSize, 11083 uint32_t *num_pairs, 11084 const char *key, 11085 const char *value) 11086 { 11087 size_t strlen_key = strlen(key); 11088 size_t strlen_value = strlen(value); 11089 size_t len = strlen(key) + 1 + strlen(value) + 1; 11090 char *pos = pBuffer + *position; 11091 *position += len; 11092 if (pBuffer && bufferSize && *position <= bufferSize) { 11093 memcpy(pos, key, strlen_key); pos += strlen_key; 11094 *(pos++) = '='; 11095 memcpy(pos, value, strlen_value); pos += strlen_value; 11096 *(pos++) = 0; 11097 if (num_pairs) { 11098 (*num_pairs)++; 11099 } 11100 } 11101 } 11102 11103 11104 static 11105 void 11106 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max) 11107 { 11108 *position += strlen(key) + 1 + value_max + 1; 11109 } 11110 11111 11112 static 11113 void 11114 OSKextPgoMetadataPutAll(OSKext *kext, 11115 uuid_t instance_uuid, 11116 char *pBuffer, 11117 size_t *position, 11118 size_t bufferSize, 11119 uint32_t *num_pairs) 11120 { 11121 _static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0); 11122 //log_10 2^16 ≈ 4.82 11123 const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2; 11124 const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6; 11125 11126 if (!pBuffer) { 11127 OSKextPgoMetadataPutMax(position, "INSTANCE", 36); 11128 OSKextPgoMetadataPutMax(position, "UUID", 36); 11129 OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size); 11130 } else { 11131 uuid_string_t instance_uuid_string; 11132 uuid_unparse(instance_uuid, instance_uuid_string); 11133 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 11134 "INSTANCE", instance_uuid_string); 11135 11136 OSSharedPtr<OSData> uuid_data; 11137 uuid_t uuid; 11138 uuid_string_t uuid_string; 11139 uuid_data = kext->copyUUID(); 11140 if (uuid_data) { 11141 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 11142 uuid_unparse(uuid, uuid_string); 11143 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 11144 "UUID", uuid_string); 11145 } 11146 11147 clock_sec_t secs; 11148 clock_usec_t usecs; 11149 clock_get_calendar_microtime(&secs, &usecs); 11150 assert(usecs < 1000000); 11151 char timestamp[max_timestamp_string_size + 1]; 11152 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t)); 11153 snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs); 11154 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 11155 "TIMESTAMP", timestamp); 11156 } 11157 11158 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 11159 "NAME", kext->getIdentifierCString()); 11160 11161 char versionCString[kOSKextVersionMaxLength]; 11162 OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength); 11163 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 11164 "VERSION", versionCString); 11165 } 11166 11167 static 11168 size_t 11169 OSKextPgoMetadataSize(OSKext *kext) 11170 { 11171 size_t position = 0; 11172 uuid_t fakeuuid = {}; 11173 OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL); 11174 return position; 11175 } 11176 11177 int 11178 OSKextGrabPgoDataLocked(OSKext *kext, 11179 bool metadata, 11180 uuid_t instance_uuid, 11181 uint64_t *pSize, 11182 char *pBuffer, 11183 uint64_t bufferSize) 11184 { 11185 int err = 0; 11186 11187 kernel_section_t *sect_prf_data = NULL; 11188 kernel_section_t *sect_prf_name = NULL; 11189 kernel_section_t *sect_prf_cnts = NULL; 11190 uint64_t size; 11191 size_t metadata_size = 0; 11192 size_t offset_to_pairs = 0; 11193 11194 sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data"); 11195 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names"); 11196 if (!sect_prf_name) { 11197 // kextcache sometimes truncates the section name to 15 chars 11198 // <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache 11199 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name"); 11200 } 11201 sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 11202 11203 if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) { 11204 err = ENOTSUP; 11205 goto out; 11206 } 11207 11208 size = __llvm_profile_get_size_for_buffer_internal( 11209 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 11210 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 11211 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 11212 11213 if (metadata) { 11214 metadata_size = OSKextPgoMetadataSize(kext); 11215 size += metadata_size; 11216 size += sizeof(pgo_metadata_footer); 11217 } 11218 11219 11220 if (pSize) { 11221 *pSize = size; 11222 } 11223 11224 if (pBuffer && bufferSize) { 11225 if (bufferSize < size) { 11226 err = ERANGE; 11227 goto out; 11228 } 11229 11230 err = __llvm_profile_write_buffer_internal( 11231 pBuffer, 11232 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 11233 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 11234 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 11235 11236 if (err) { 11237 err = EIO; 11238 goto out; 11239 } 11240 11241 if (metadata) { 11242 offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size; 11243 if (offset_to_pairs > UINT32_MAX) { 11244 err = E2BIG; 11245 goto out; 11246 } 11247 11248 char *end_of_buffer = pBuffer + size; 11249 struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer)); 11250 char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size); 11251 11252 size_t metadata_position = 0; 11253 uint32_t num_pairs = 0; 11254 OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs); 11255 while (metadata_position < metadata_size) { 11256 metadata_buffer[metadata_position++] = 0; 11257 } 11258 11259 struct pgo_metadata_footer footer; 11260 footer.magic = htonl(0x6d657461); 11261 footer.number_of_pairs = htonl( num_pairs ); 11262 footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs ); 11263 memcpy(footerp, &footer, sizeof(footer)); 11264 } 11265 } 11266 11267 out: 11268 return err; 11269 } 11270 11271 11272 int 11273 OSKextGrabPgoData(uuid_t uuid, 11274 uint64_t *pSize, 11275 char *pBuffer, 11276 uint64_t bufferSize, 11277 int wait_for_unload, 11278 int metadata) 11279 { 11280 int err = 0; 11281 OSSharedPtr<OSKext> kext; 11282 11283 11284 IORecursiveLockLock(sKextLock); 11285 11286 kext = OSKext::lookupKextWithUUID(uuid); 11287 if (!kext) { 11288 err = ENOENT; 11289 goto out; 11290 } 11291 11292 if (wait_for_unload) { 11293 OSKextGrabPgoStruct s; 11294 11295 s.metadata = metadata; 11296 s.pSize = pSize; 11297 s.pBuffer = pBuffer; 11298 s.bufferSize = bufferSize; 11299 s.err = EINTR; 11300 11301 struct list_head *prev = &kext->pendingPgoHead; 11302 struct list_head *next = kext->pendingPgoHead.next; 11303 11304 s.list_head.prev = prev; 11305 s.list_head.next = next; 11306 11307 prev->next = &s.list_head; 11308 next->prev = &s.list_head; 11309 11310 kext.reset(); 11311 11312 IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE); 11313 11314 prev = s.list_head.prev; 11315 next = s.list_head.next; 11316 11317 prev->next = next; 11318 next->prev = prev; 11319 11320 err = s.err; 11321 } else { 11322 err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize); 11323 } 11324 11325 out: 11326 11327 IORecursiveLockUnlock(sKextLock); 11328 11329 return err; 11330 } 11331 11332 void 11333 OSKextResetPgoCountersLock() 11334 { 11335 IORecursiveLockLock(sKextLock); 11336 } 11337 11338 void 11339 OSKextResetPgoCountersUnlock() 11340 { 11341 IORecursiveLockUnlock(sKextLock); 11342 } 11343 11344 11345 extern unsigned int not_in_kdp; 11346 11347 void 11348 OSKextResetPgoCounters() 11349 { 11350 assert(!not_in_kdp); 11351 uint32_t count = sLoadedKexts->getCount(); 11352 for (uint32_t i = 0; i < count; i++) { 11353 OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 11354 kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 11355 if (!sect_prf_cnts) { 11356 continue; 11357 } 11358 memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size); 11359 } 11360 } 11361 11362 OSSharedPtr<OSDictionary> 11363 OSKext::copyLoadedKextInfoByUUID( 11364 OSArray * kextIdentifiers, 11365 OSArray * infoKeys) 11366 { 11367 OSSharedPtr<OSDictionary> result; 11368 OSSharedPtr<OSDictionary> kextInfo; 11369 uint32_t max_count, i, j; 11370 uint32_t idCount = 0; 11371 uint32_t idIndex = 0; 11372 IORecursiveLockLock(sKextLock); 11373 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 11374 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 11375 11376 #if CONFIG_MACF 11377 /* Is the calling process allowed to query kext info? */ 11378 if (current_task() != kernel_task) { 11379 int macCheckResult = 0; 11380 kauth_cred_t cred = NULL; 11381 11382 cred = kauth_cred_get_with_ref(); 11383 macCheckResult = mac_kext_check_query(cred); 11384 kauth_cred_unref(&cred); 11385 11386 if (macCheckResult != 0) { 11387 OSKextLog(/* kext */ NULL, 11388 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 11389 "Failed to query kext info (MAC policy error 0x%x).", 11390 macCheckResult); 11391 goto finish; 11392 } 11393 } 11394 #endif 11395 11396 /* Empty list of UUIDs is equivalent to no list (get all). 11397 */ 11398 if (kextIdentifiers && !kextIdentifiers->getCount()) { 11399 kextIdentifiers = NULL; 11400 } else if (kextIdentifiers) { 11401 idCount = kextIdentifiers->getCount(); 11402 } 11403 11404 /* Same for keys. 11405 */ 11406 if (infoKeys && !infoKeys->getCount()) { 11407 infoKeys = NULL; 11408 } 11409 11410 max_count = count[0] + count[1]; 11411 result = OSDictionary::withCapacity(max_count); 11412 if (!result) { 11413 goto finish; 11414 } 11415 11416 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 11417 for (i = 0; i < count[j]; i++) { 11418 OSKext *thisKext = NULL; // do not release 11419 Boolean includeThis = true; 11420 uuid_t thisKextUUID; 11421 uuid_t thisKextTextUUID; 11422 OSSharedPtr<OSData> uuid_data; 11423 uuid_string_t uuid_key; 11424 11425 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 11426 if (!thisKext) { 11427 continue; 11428 } 11429 11430 uuid_data = thisKext->copyUUID(); 11431 if (!uuid_data) { 11432 continue; 11433 } 11434 11435 memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID)); 11436 11437 uuid_unparse(thisKextUUID, uuid_key); 11438 11439 uuid_data = thisKext->copyTextUUID(); 11440 if (!uuid_data) { 11441 continue; 11442 } 11443 memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID)); 11444 11445 /* Skip current kext if we have a list of UUIDs and 11446 * it isn't in the list. 11447 */ 11448 if (kextIdentifiers) { 11449 includeThis = false; 11450 11451 for (idIndex = 0; idIndex < idCount; idIndex++) { 11452 const OSString* wantedUUID = OSDynamicCast(OSString, 11453 kextIdentifiers->getObject(idIndex)); 11454 11455 uuid_t uuid; 11456 uuid_parse(wantedUUID->getCStringNoCopy(), uuid); 11457 11458 if ((0 == uuid_compare(uuid, thisKextUUID)) 11459 || (0 == uuid_compare(uuid, thisKextTextUUID))) { 11460 includeThis = true; 11461 /* Only need to find the first kext if multiple match, 11462 * ie. asking for the kernel uuid does not need to find 11463 * interface kexts or builtin static kexts. 11464 */ 11465 kextIdentifiers->removeObject(idIndex); 11466 uuid_unparse(uuid, uuid_key); 11467 break; 11468 } 11469 } 11470 } 11471 11472 if (!includeThis) { 11473 continue; 11474 } 11475 11476 kextInfo = thisKext->copyInfo(infoKeys); 11477 if (kextInfo) { 11478 result->setObject(uuid_key, kextInfo.get()); 11479 } 11480 11481 if (kextIdentifiers && !kextIdentifiers->getCount()) { 11482 goto finish; 11483 } 11484 } 11485 } 11486 11487 finish: 11488 IORecursiveLockUnlock(sKextLock); 11489 11490 return result; 11491 } 11492 11493 /********************************************************************* 11494 *********************************************************************/ 11495 /* static */ 11496 OSSharedPtr<OSDictionary> 11497 OSKext::copyKextCollectionInfo( 11498 OSDictionary *requestDict, 11499 OSArray *infoKeys) 11500 { 11501 OSSharedPtr<OSDictionary> result; 11502 OSString *collectionType = NULL; 11503 OSObject *rawLoadedState = NULL; 11504 OSString *loadedState = NULL; 11505 11506 kc_kind_t kc_request_kind = KCKindUnknown; 11507 bool onlyLoaded = false; 11508 bool onlyUnloaded = false; 11509 11510 #if CONFIG_MACF 11511 /* Is the calling process allowed to query kext info? */ 11512 if (current_task() != kernel_task) { 11513 int macCheckResult = 0; 11514 kauth_cred_t cred = NULL; 11515 11516 cred = kauth_cred_get_with_ref(); 11517 macCheckResult = mac_kext_check_query(cred); 11518 kauth_cred_unref(&cred); 11519 11520 if (macCheckResult != 0) { 11521 OSKextLog(/* kext */ NULL, 11522 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 11523 "Failed to query kext info (MAC policy error 0x%x).", 11524 macCheckResult); 11525 goto finish; 11526 } 11527 } 11528 #endif 11529 11530 if (infoKeys && !infoKeys->getCount()) { 11531 infoKeys = NULL; 11532 } 11533 11534 collectionType = OSDynamicCast(OSString, 11535 _OSKextGetRequestArgument(requestDict, 11536 kKextRequestArgumentCollectionTypeKey)); 11537 if (!collectionType) { 11538 OSKextLog(/* kext */ NULL, 11539 kOSKextLogErrorLevel | 11540 kOSKextLogIPCFlag, 11541 "Invalid '%s' argument to kext collection info request.", 11542 kKextRequestArgumentCollectionTypeKey); 11543 goto finish; 11544 } 11545 if (collectionType->isEqualTo(kKCTypePrimary)) { 11546 kc_request_kind = KCKindPrimary; 11547 } else if (collectionType->isEqualTo(kKCTypeSystem)) { 11548 kc_request_kind = KCKindPageable; 11549 } else if (collectionType->isEqualTo(kKCTypeAuxiliary)) { 11550 kc_request_kind = KCKindAuxiliary; 11551 } else if (collectionType->isEqualTo(kKCTypeCodeless)) { 11552 kc_request_kind = KCKindNone; 11553 } else if (!collectionType->isEqualTo(kKCTypeAny)) { 11554 OSKextLog(/* kext */ NULL, 11555 kOSKextLogErrorLevel | 11556 kOSKextLogIPCFlag, 11557 "Invalid '%s' argument value '%s' to kext collection info request.", 11558 kKextRequestArgumentCollectionTypeKey, 11559 collectionType->getCStringNoCopy()); 11560 goto finish; 11561 } 11562 11563 rawLoadedState = _OSKextGetRequestArgument(requestDict, 11564 kKextRequestArgumentLoadedStateKey); 11565 if (rawLoadedState) { 11566 loadedState = OSDynamicCast(OSString, rawLoadedState); 11567 if (!loadedState) { 11568 OSKextLog(/* kext */ NULL, 11569 kOSKextLogErrorLevel | 11570 kOSKextLogIPCFlag, 11571 "Invalid '%s' argument to kext collection info request.", 11572 kKextRequestArgumentLoadedStateKey); 11573 goto finish; 11574 } 11575 } 11576 if (loadedState) { 11577 if (loadedState->isEqualTo("Loaded")) { 11578 onlyLoaded = true; 11579 } else if (loadedState->isEqualTo("Unloaded")) { 11580 onlyUnloaded = true; 11581 } else if (!loadedState->isEqualTo("Any")) { 11582 OSKextLog(/* kext */ NULL, 11583 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 11584 "Invalid '%s' argument value '%s' for '%s' collection info", 11585 kKextRequestArgumentLoadedStateKey, 11586 loadedState->getCStringNoCopy(), 11587 collectionType->getCStringNoCopy()); 11588 goto finish; 11589 } 11590 } 11591 11592 result = OSDictionary::withCapacity(sKextsByID->getCount()); 11593 if (!result) { 11594 goto finish; 11595 } 11596 11597 IORecursiveLockLock(sKextLock); 11598 { // start block scope 11599 sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj) 11600 { 11601 OSKext *thisKext = NULL; // do not release 11602 OSSharedPtr<OSDictionary> kextInfo; 11603 11604 (void)thisKextID; 11605 11606 thisKext = OSDynamicCast(OSKext, obj); 11607 if (!thisKext) { 11608 return false; 11609 } 11610 11611 /* 11612 * skip the kext if it came from the wrong collection type 11613 * (and the caller requested a specific type) 11614 */ 11615 if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) { 11616 return false; 11617 } 11618 11619 /* 11620 * respect the caller's desire to find only loaded or 11621 * unloaded kexts 11622 */ 11623 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 11624 return false; 11625 } 11626 if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 11627 return false; 11628 } 11629 11630 kextInfo = thisKext->copyInfo(infoKeys); 11631 if (kextInfo) { 11632 result->setObject(thisKext->getIdentifier(), kextInfo.get()); 11633 } 11634 return false; 11635 }); 11636 } // end block scope 11637 IORecursiveLockUnlock(sKextLock); 11638 11639 finish: 11640 return result; 11641 } 11642 11643 /* static */ 11644 OSSharedPtr<OSArray> 11645 OSKext::copyDextsInfo( 11646 OSArray *kextIdentifiers, 11647 OSArray *infoKeys) 11648 { 11649 OSSharedPtr<OSArray> result = NULL; 11650 uint32_t idCount = 0; 11651 bool getActive = false; 11652 bool getLoaded = false; 11653 bool getUnloaded = false; 11654 bool getPendingUpgrade = false; 11655 unsigned int avgDextCount = 0; 11656 11657 #if CONFIG_MACF 11658 /* Is the calling process allowed to query dext info? */ 11659 if (current_task() != kernel_task) { 11660 int macCheckResult = 0; 11661 kauth_cred_t cred = NULL; 11662 11663 cred = kauth_cred_get_with_ref(); 11664 macCheckResult = mac_kext_check_query(cred); 11665 kauth_cred_unref(&cred); 11666 11667 if (macCheckResult != 0) { 11668 OSKextLog(/* kext */ NULL, 11669 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 11670 "Failed to query kext info (MAC policy error 0x%x).", 11671 macCheckResult); 11672 goto finish; 11673 } 11674 } 11675 #endif 11676 /* 11677 * No infoKeys means return everything we 11678 * know about the dexts. 11679 */ 11680 if (infoKeys && !infoKeys->getCount()) { 11681 infoKeys = NULL; 11682 } 11683 11684 /* 11685 * Empty list of bundle ids is equivalent to 11686 * no list (get all). 11687 */ 11688 if (kextIdentifiers && !kextIdentifiers->getCount()) { 11689 kextIdentifiers = NULL; 11690 } else if (kextIdentifiers) { 11691 idCount = kextIdentifiers->getCount(); 11692 } 11693 11694 /* 11695 * Caller can specify which state of dexts to query. 11696 */ 11697 if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveKey)) { 11698 getActive = true; 11699 } 11700 if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveLoadedKey)) { 11701 getLoaded = true; 11702 } 11703 if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveUnloadedKey)) { 11704 getUnloaded = true; 11705 } 11706 if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStatePendingUpgradeKey)) { 11707 getPendingUpgrade = true; 11708 } 11709 11710 /* 11711 * By default we are going to return all active and pendingUpgrade dexts 11712 * only. 11713 */ 11714 if (!(getActive || getLoaded || getUnloaded || getPendingUpgrade)) { 11715 getActive = true; 11716 getPendingUpgrade = true; 11717 } 11718 11719 /* 11720 * We return a dictionary of dexts 11721 * for every group requested. 11722 */ 11723 avgDextCount = sLoadedDriverKitKexts->getCount() + sDriverKitToUpgradeByID->getCount(); 11724 result = OSArray::withCapacity(avgDextCount); 11725 if (!result) { 11726 goto finish; 11727 } 11728 11729 IORecursiveLockLock(sKextLock); 11730 { // start block scope 11731 if (getActive || getLoaded || getUnloaded) { 11732 sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj) 11733 { 11734 OSKext *thisKext = NULL; // do not release 11735 OSSharedPtr<OSDictionary> kextInfo; 11736 Boolean includeThis = true; 11737 (void)thisKextID; 11738 11739 thisKext = OSDynamicCast(OSKext, obj); 11740 if (!thisKext || !thisKext->isDriverKit()) { 11741 return false; 11742 } 11743 11744 /* 11745 * Skip current dext if we have a list of bundle IDs and 11746 * it isn't in the list. 11747 */ 11748 if (kextIdentifiers) { 11749 includeThis = false; 11750 11751 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) { 11752 const OSString * thisRequestID = OSDynamicCast(OSString, 11753 kextIdentifiers->getObject(idIndex)); 11754 if (thisKextID->isEqualTo(thisRequestID)) { 11755 includeThis = true; 11756 break; 11757 } 11758 } 11759 } 11760 11761 if (!includeThis) { 11762 return false; 11763 } 11764 11765 OSSharedPtr<OSString> state; 11766 if (sLoadedDriverKitKexts->getNextIndexOfObject(thisKext, 0) == -1U) { 11767 if (!(getActive || getUnloaded)) { 11768 return false; 11769 } 11770 state = OSString::withCString(kOSBundleDextStateActiveUnloadedKey); 11771 } else { 11772 if (!(getActive || getLoaded)) { 11773 return false; 11774 } 11775 state = OSString::withCString(kOSBundleDextStateActiveLoadedKey); 11776 } 11777 11778 kextInfo = thisKext->copyInfo(infoKeys); 11779 if (kextInfo) { 11780 kextInfo->setObject(kOSBundleDextStateKey, state.get()); 11781 result->setObject(kextInfo.get()); 11782 } 11783 11784 return false; 11785 }); 11786 } 11787 11788 if (getPendingUpgrade) { 11789 sDriverKitToUpgradeByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj) 11790 { 11791 OSKext *thisKext = NULL; // do not release 11792 OSSharedPtr<OSDictionary> kextInfo; 11793 Boolean includeThis = true; 11794 (void)thisKextID; 11795 11796 thisKext = OSDynamicCast(OSKext, obj); 11797 if (!thisKext) { 11798 return false; 11799 } 11800 __assert_only bool isDext = thisKext->isDriverKit(); 11801 assert(isDext == true); 11802 11803 /* 11804 * Skip current dext if we have a list of bundle IDs and 11805 * it isn't in the list. 11806 */ 11807 if (kextIdentifiers) { 11808 includeThis = false; 11809 11810 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) { 11811 const OSString * thisRequestID = OSDynamicCast(OSString, 11812 kextIdentifiers->getObject(idIndex)); 11813 if (thisKextID->isEqualTo(thisRequestID)) { 11814 includeThis = true; 11815 break; 11816 } 11817 } 11818 } 11819 11820 if (!includeThis) { 11821 return false; 11822 } 11823 11824 kextInfo = thisKext->copyInfo(infoKeys); 11825 if (kextInfo) { 11826 OSSharedPtr<OSString> state = OSString::withCString(kOSBundleDextStatePendingUpgradeKey); 11827 kextInfo->setObject(kOSBundleDextStateKey, state.get()); 11828 result->setObject(kextInfo.get()); 11829 } 11830 return false; 11831 }); 11832 } 11833 } // end block scope 11834 IORecursiveLockUnlock(sKextLock); 11835 finish: 11836 return result; 11837 } 11838 11839 /********************************************************************* 11840 *********************************************************************/ 11841 /* static */ 11842 OSSharedPtr<OSDictionary> 11843 OSKext::copyLoadedKextInfo( 11844 OSArray * kextIdentifiers, 11845 OSArray * infoKeys) 11846 { 11847 OSSharedPtr<OSDictionary> result; 11848 uint32_t idCount = 0; 11849 bool onlyLoaded; 11850 11851 IORecursiveLockLock(sKextLock); 11852 11853 #if CONFIG_MACF 11854 /* Is the calling process allowed to query kext info? */ 11855 if (current_task() != kernel_task) { 11856 int macCheckResult = 0; 11857 kauth_cred_t cred = NULL; 11858 11859 cred = kauth_cred_get_with_ref(); 11860 macCheckResult = mac_kext_check_query(cred); 11861 kauth_cred_unref(&cred); 11862 11863 if (macCheckResult != 0) { 11864 OSKextLog(/* kext */ NULL, 11865 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 11866 "Failed to query kext info (MAC policy error 0x%x).", 11867 macCheckResult); 11868 goto finish; 11869 } 11870 } 11871 #endif 11872 11873 /* Empty list of bundle ids is equivalent to no list (get all). 11874 */ 11875 if (kextIdentifiers && !kextIdentifiers->getCount()) { 11876 kextIdentifiers = NULL; 11877 } else if (kextIdentifiers) { 11878 idCount = kextIdentifiers->getCount(); 11879 } 11880 11881 /* Same for keys. 11882 */ 11883 if (infoKeys && !infoKeys->getCount()) { 11884 infoKeys = NULL; 11885 } 11886 11887 onlyLoaded = (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey)); 11888 11889 result = OSDictionary::withCapacity(128); 11890 if (!result) { 11891 goto finish; 11892 } 11893 11894 #if 0 11895 OSKextLog(/* kext */ NULL, 11896 kOSKextLogErrorLevel | 11897 kOSKextLogGeneralFlag, 11898 "kaslr: vm_kernel_slide 0x%lx \n", 11899 vm_kernel_slide); 11900 OSKextLog(/* kext */ NULL, 11901 kOSKextLogErrorLevel | 11902 kOSKextLogGeneralFlag, 11903 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n", 11904 vm_kernel_stext, vm_kernel_etext); 11905 OSKextLog(/* kext */ NULL, 11906 kOSKextLogErrorLevel | 11907 kOSKextLogGeneralFlag, 11908 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n", 11909 vm_kernel_base, vm_kernel_top); 11910 OSKextLog(/* kext */ NULL, 11911 kOSKextLogErrorLevel | 11912 kOSKextLogGeneralFlag, 11913 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n", 11914 vm_kext_base, vm_kext_top); 11915 OSKextLog(/* kext */ NULL, 11916 kOSKextLogErrorLevel | 11917 kOSKextLogGeneralFlag, 11918 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n", 11919 vm_prelink_stext, vm_prelink_etext); 11920 OSKextLog(/* kext */ NULL, 11921 kOSKextLogErrorLevel | 11922 kOSKextLogGeneralFlag, 11923 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n", 11924 vm_prelink_sinfo, vm_prelink_einfo); 11925 OSKextLog(/* kext */ NULL, 11926 kOSKextLogErrorLevel | 11927 kOSKextLogGeneralFlag, 11928 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n", 11929 vm_slinkedit, vm_elinkedit); 11930 #endif 11931 { // start block scope 11932 sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj) 11933 { 11934 OSKext * thisKext = NULL; // do not release 11935 Boolean includeThis = true; 11936 OSSharedPtr<OSDictionary> kextInfo; 11937 11938 thisKext = OSDynamicCast(OSKext, obj); 11939 if (!thisKext) { 11940 return false; 11941 } 11942 11943 /* Skip current kext if not yet started and caller didn't request all. 11944 */ 11945 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 11946 return false; 11947 } 11948 11949 /* Skip current kext if we have a list of bundle IDs and 11950 * it isn't in the list. 11951 */ 11952 if (kextIdentifiers) { 11953 includeThis = false; 11954 11955 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) { 11956 const OSString * thisRequestID = OSDynamicCast(OSString, 11957 kextIdentifiers->getObject(idIndex)); 11958 if (thisKextID->isEqualTo(thisRequestID)) { 11959 includeThis = true; 11960 break; 11961 } 11962 } 11963 } 11964 11965 if (!includeThis) { 11966 return false; 11967 } 11968 11969 kextInfo = thisKext->copyInfo(infoKeys); 11970 if (kextInfo) { 11971 result->setObject(thisKext->getIdentifier(), kextInfo.get()); 11972 } 11973 return false; 11974 }); 11975 } // end block scope 11976 11977 finish: 11978 IORecursiveLockUnlock(sKextLock); 11979 11980 return result; 11981 } 11982 11983 /********************************************************************* 11984 * Any info that needs to do allocations must goto finish on alloc 11985 * failure. Info that is just a lookup should just not set the object 11986 * if the info does not exist. 11987 *********************************************************************/ 11988 #define _OSKextLoadInfoDictCapacity (12) 11989 11990 OSSharedPtr<OSDictionary> 11991 OSKext::copyInfo(OSArray * infoKeys) 11992 { 11993 OSSharedPtr<OSDictionary> result; 11994 bool success = false; 11995 OSSharedPtr<OSData> headerData; 11996 OSSharedPtr<OSData> logData; 11997 OSSharedPtr<OSNumber> cpuTypeNumber; 11998 OSSharedPtr<OSNumber> cpuSubtypeNumber; 11999 OSString * versionString = NULL; // do not release 12000 OSString * bundleType = NULL; // do not release 12001 uint32_t executablePathCStringSize = 0; 12002 char * executablePathCString = NULL; // must kfree 12003 OSSharedPtr<OSString> executablePathString; 12004 OSSharedPtr<OSData> uuid; 12005 OSSharedPtr<OSArray> dependencyLoadTags; 12006 OSSharedPtr<OSCollectionIterator> metaClassIterator; 12007 OSSharedPtr<OSArray> metaClassInfo; 12008 OSSharedPtr<OSDictionary> metaClassDict; 12009 OSMetaClass * thisMetaClass = NULL; // do not release 12010 OSSharedPtr<OSString> metaClassName; 12011 OSSharedPtr<OSString> superclassName; 12012 kc_format_t kcformat; 12013 uint32_t count, i; 12014 12015 result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity); 12016 if (!result) { 12017 goto finish; 12018 } 12019 12020 12021 /* Empty keys means no keys, but NULL is quicker to check. 12022 */ 12023 if (infoKeys && !infoKeys->getCount()) { 12024 infoKeys = NULL; 12025 } 12026 12027 if (!PE_get_primary_kc_format(&kcformat)) { 12028 goto finish; 12029 } 12030 12031 /* Headers, CPU type, and CPU subtype. 12032 */ 12033 if (!infoKeys || 12034 _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) || 12035 _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) || 12036 _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) || 12037 _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 12038 if (linkedExecutable && !isInterface()) { 12039 kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *) 12040 linkedExecutable->getBytesNoCopy(); 12041 12042 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX 12043 // do not return macho header info on shipping embedded - 19095897 12044 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) { 12045 kernel_mach_header_t * temp_kext_mach_hdr; 12046 struct load_command * lcp; 12047 12048 headerData = OSData::withBytes(kext_mach_hdr, 12049 (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds)); 12050 if (!headerData) { 12051 goto finish; 12052 } 12053 12054 // unslide any vmaddrs we return to userspace - 10726716 12055 temp_kext_mach_hdr = (kernel_mach_header_t *) 12056 headerData->getBytesNoCopy(); 12057 if (temp_kext_mach_hdr == NULL) { 12058 goto finish; 12059 } 12060 12061 lcp = (struct load_command *) (temp_kext_mach_hdr + 1); 12062 for (i = 0; (i < temp_kext_mach_hdr->ncmds) && !flags.unslidMachO; i++) { 12063 if (lcp->cmd == LC_SEGMENT_KERNEL) { 12064 kernel_segment_command_t * segp; 12065 kernel_section_t * secp; 12066 12067 segp = (kernel_segment_command_t *) lcp; 12068 // 10543468 - if we jettisoned __LINKEDIT clear size info 12069 if (flags.jettisonLinkeditSeg) { 12070 if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) { 12071 segp->vmsize = 0; 12072 segp->fileoff = 0; 12073 segp->filesize = 0; 12074 } 12075 } 12076 12077 #if __arm__ || __arm64__ 12078 // iBoot disregards zero-size segments, just set their addresses to gVirtBase 12079 // and unslide them to avoid vm assertion failures / kernel logging breakage. 12080 if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) { 12081 segp->vmaddr = gVirtBase; 12082 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { 12083 secp->size = 0; // paranoia :) 12084 secp->addr = gVirtBase; 12085 } 12086 } 12087 #endif 12088 12089 #if 0 12090 OSKextLog(/* kext */ NULL, 12091 kOSKextLogErrorLevel | 12092 kOSKextLogGeneralFlag, 12093 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u", 12094 __FUNCTION__, segp->segname, segp->vmaddr, 12095 VM_KERNEL_UNSLIDE(segp->vmaddr), 12096 segp->vmsize, segp->nsects); 12097 if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) && 12098 (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) && 12099 (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) && 12100 (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) && 12101 (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) { 12102 OSKextLog(/* kext */ NULL, 12103 kOSKextLogErrorLevel | 12104 kOSKextLogGeneralFlag, 12105 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX", 12106 __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top); 12107 } 12108 #endif 12109 segp->vmaddr = ml_static_unslide(segp->vmaddr); 12110 12111 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { 12112 secp->addr = ml_static_unslide(secp->addr); 12113 } 12114 } 12115 lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize); 12116 } 12117 result->setObject(kOSBundleMachOHeadersKey, headerData.get()); 12118 } 12119 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX 12120 12121 if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) { 12122 osLogDataHeaderRef *header; 12123 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])]; 12124 12125 void *os_log_data = NULL; 12126 void *cstring_data = NULL; 12127 void *asan_cstring_data = NULL; 12128 unsigned long os_log_size = 0; 12129 unsigned long cstring_size = 0; 12130 unsigned long asan_cstring_size = 0; 12131 uint32_t os_log_offset = 0; 12132 uint32_t cstring_offset = 0; 12133 uint32_t asan_cstring_offset = 0; 12134 bool res; 12135 12136 os_log_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size); 12137 cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size); 12138 asan_cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size); 12139 12140 /* 12141 * If the addresses in the Mach-O header are unslid, manually 12142 * slide them to allow for dereferencing. 12143 */ 12144 if (flags.unslidMachO) { 12145 os_log_data = (os_log_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)os_log_data) : nullptr; 12146 cstring_data = (cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)cstring_data) : nullptr; 12147 asan_cstring_data = (asan_cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)asan_cstring_data) : nullptr; 12148 } 12149 12150 os_log_offset = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr; 12151 cstring_offset = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr; 12152 asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr; 12153 12154 header = (osLogDataHeaderRef *) headerBytes; 12155 header->version = OS_LOG_HDR_VERSION; 12156 header->sect_count = NUM_OS_LOG_SECTIONS; 12157 header->sections[OS_LOG_SECT_IDX].sect_offset = os_log_offset; 12158 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) os_log_size; 12159 header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset; 12160 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) cstring_size; 12161 header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset; 12162 header->sections[ASAN_CSTRING_SECT_IDX].sect_size = (uint32_t) asan_cstring_size; 12163 12164 12165 logData = OSData::withValue(*header); 12166 if (!logData) { 12167 goto finish; 12168 } 12169 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0]))); 12170 if (!res) { 12171 goto finish; 12172 } 12173 if (os_log_data) { 12174 res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size); 12175 if (!res) { 12176 goto finish; 12177 } 12178 } 12179 if (cstring_data) { 12180 res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size); 12181 if (!res) { 12182 goto finish; 12183 } 12184 } 12185 if (asan_cstring_data) { 12186 res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size); 12187 if (!res) { 12188 goto finish; 12189 } 12190 } 12191 result->setObject(kOSBundleLogStringsKey, logData.get()); 12192 } 12193 12194 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) { 12195 cpuTypeNumber = OSNumber::withNumber( 12196 (uint64_t) kext_mach_hdr->cputype, 12197 8 * sizeof(kext_mach_hdr->cputype)); 12198 if (!cpuTypeNumber) { 12199 goto finish; 12200 } 12201 result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get()); 12202 } 12203 12204 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 12205 cpuSubtypeNumber = OSNumber::withNumber( 12206 (uint64_t) kext_mach_hdr->cpusubtype, 12207 8 * sizeof(kext_mach_hdr->cpusubtype)); 12208 if (!cpuSubtypeNumber) { 12209 goto finish; 12210 } 12211 result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get()); 12212 } 12213 } else { 12214 if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) { 12215 osLogDataHeaderRef *header; 12216 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])]; 12217 bool res; 12218 12219 header = (osLogDataHeaderRef *) headerBytes; 12220 header->version = OS_LOG_HDR_VERSION; 12221 header->sect_count = NUM_OS_LOG_SECTIONS; 12222 header->sections[OS_LOG_SECT_IDX].sect_offset = 0; 12223 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) 0; 12224 header->sections[CSTRING_SECT_IDX].sect_offset = 0; 12225 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) 0; 12226 header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0; 12227 header->sections[ASAN_CSTRING_SECT_IDX].sect_size = (uint32_t) 0; 12228 12229 logData = OSData::withValue(*header); 12230 if (!logData) { 12231 goto finish; 12232 } 12233 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0]))); 12234 if (!res) { 12235 goto finish; 12236 } 12237 result->setObject(kOSBundleLogStringsKey, logData.get()); 12238 } 12239 } 12240 } 12241 12242 /* CFBundleIdentifier. We set this regardless because it's just stupid not to. 12243 */ 12244 result->setObject(kCFBundleIdentifierKey, bundleID.get()); 12245 12246 /* kOSBundleDextUniqueIdentifierKey if present. 12247 */ 12248 if (isDriverKit() && dextUniqueID != NULL) { 12249 result->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID.get()); 12250 } 12251 12252 /* CFBundlePackageType 12253 */ 12254 bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL; 12255 if (bundleType) { 12256 result->setObject(kCFBundlePackageTypeKey, bundleType); 12257 } 12258 12259 /* CFBundleVersion. 12260 */ 12261 if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) { 12262 versionString = OSDynamicCast(OSString, 12263 getPropertyForHostArch(kCFBundleVersionKey)); 12264 if (versionString) { 12265 result->setObject(kCFBundleVersionKey, versionString); 12266 } 12267 } 12268 12269 /* OSBundleCompatibleVersion. 12270 */ 12271 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) { 12272 versionString = OSDynamicCast(OSString, 12273 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 12274 if (versionString) { 12275 result->setObject(kOSBundleCompatibleVersionKey, versionString); 12276 } 12277 } 12278 12279 /* Path. 12280 */ 12281 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) { 12282 if (path) { 12283 result->setObject(kOSBundlePathKey, path.get()); 12284 } 12285 } 12286 12287 12288 /* OSBundleExecutablePath. 12289 */ 12290 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) { 12291 if (path && executableRelPath) { 12292 uint32_t pathLength = path->getLength(); // gets incremented below 12293 12294 // +1 for slash, +1 for \0 12295 executablePathCStringSize = pathLength + executableRelPath->getLength() + 2; 12296 12297 executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize, 12298 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); // +1 for \0 12299 if (!executablePathCString) { 12300 goto finish; 12301 } 12302 strlcpy(executablePathCString, path->getCStringNoCopy(), 12303 executablePathCStringSize); 12304 executablePathCString[pathLength++] = '/'; 12305 executablePathCString[pathLength++] = '\0'; 12306 strlcat(executablePathCString, executableRelPath->getCStringNoCopy(), 12307 executablePathCStringSize); 12308 12309 executablePathString = OSString::withCString(executablePathCString); 12310 12311 if (!executablePathString) { 12312 goto finish; 12313 } 12314 12315 result->setObject(kOSBundleExecutablePathKey, executablePathString.get()); 12316 } else if (flags.builtin) { 12317 result->setObject(kOSBundleExecutablePathKey, bundleID.get()); 12318 } else if (isDriverKit()) { 12319 if (path) { 12320 // +1 for slash, +1 for \0 12321 uint32_t pathLength = path->getLength(); 12322 executablePathCStringSize = pathLength + 2; 12323 12324 executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize, 12325 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 12326 if (!executablePathCString) { 12327 goto finish; 12328 } 12329 strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize); 12330 executablePathCString[pathLength++] = '/'; 12331 executablePathCString[pathLength++] = '\0'; 12332 12333 executablePathString = OSString::withCString(executablePathCString); 12334 12335 if (!executablePathString) { 12336 goto finish; 12337 } 12338 12339 result->setObject(kOSBundleExecutablePathKey, executablePathString.get()); 12340 } 12341 } 12342 } 12343 12344 /* UUID, if the kext has one. 12345 */ 12346 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) { 12347 uuid = copyUUID(); 12348 if (uuid) { 12349 result->setObject(kOSBundleUUIDKey, uuid.get()); 12350 } 12351 } 12352 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) { 12353 uuid = copyTextUUID(); 12354 if (uuid) { 12355 result->setObject(kOSBundleTextUUIDKey, uuid.get()); 12356 } 12357 } 12358 12359 /* 12360 * Info.plist digest 12361 */ 12362 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) { 12363 OSData *digest; 12364 digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL; 12365 if (digest) { 12366 result->setObject(kOSKextInfoPlistDigestKey, digest); 12367 } 12368 } 12369 12370 /* 12371 * Collection type 12372 */ 12373 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) { 12374 result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString())); 12375 } 12376 12377 /* 12378 * Collection availability 12379 */ 12380 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) { 12381 result->setObject(kOSKextAuxKCAvailabilityKey, 12382 isLoadable() ? kOSBooleanTrue : kOSBooleanFalse); 12383 } 12384 12385 /* 12386 * Allows user load 12387 */ 12388 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) { 12389 OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey)); 12390 if (allowUserLoad) { 12391 result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad); 12392 } 12393 } 12394 12395 /* 12396 * Bundle Dependencies (OSBundleLibraries) 12397 */ 12398 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) { 12399 OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey)); 12400 if (libraries) { 12401 result->setObject(kOSBundleLibrariesKey, libraries); 12402 } 12403 } 12404 12405 /***** 12406 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted. 12407 */ 12408 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) { 12409 result->setObject(kOSKernelResourceKey, 12410 isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse); 12411 } 12412 12413 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) { 12414 result->setObject(kOSBundleIsInterfaceKey, 12415 isInterface() ? kOSBooleanTrue : kOSBooleanFalse); 12416 } 12417 12418 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) { 12419 result->setObject(kOSBundlePrelinkedKey, 12420 isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse); 12421 } 12422 12423 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) { 12424 result->setObject(kOSBundleStartedKey, 12425 isStarted() ? kOSBooleanTrue : kOSBooleanFalse); 12426 } 12427 12428 /* LoadTag (Index). 12429 */ 12430 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) { 12431 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag, 12432 /* numBits */ 8 * sizeof(loadTag)); 12433 if (!scratchNumber) { 12434 goto finish; 12435 } 12436 result->setObject(kOSBundleLoadTagKey, scratchNumber.get()); 12437 } 12438 12439 /* LoadAddress, LoadSize. 12440 */ 12441 if (!infoKeys || 12442 _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) || 12443 _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) || 12444 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) || 12445 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) || 12446 _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 12447 bool is_dext = isDriverKit(); 12448 if (isInterface() || flags.builtin || linkedExecutable || is_dext) { 12449 /* These go to userspace via serialization, so we don't want any doubts 12450 * about their size. 12451 */ 12452 uint64_t loadAddress = 0; 12453 uint32_t loadSize = 0; 12454 uint32_t wiredSize = 0; 12455 uint64_t execLoadAddress = 0; 12456 uint32_t execLoadSize = 0; 12457 12458 /* Interfaces always report 0 load address & size. 12459 * Just the way they roll. 12460 * 12461 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp 12462 * xxx - shouldn't have one! 12463 */ 12464 12465 if (flags.builtin || linkedExecutable) { 12466 kernel_mach_header_t *mh = NULL; 12467 kernel_segment_command_t *seg = NULL; 12468 12469 if (flags.builtin) { 12470 loadAddress = kmod_info->address; 12471 loadSize = (uint32_t)kmod_info->size; 12472 } else { 12473 loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy(); 12474 loadSize = linkedExecutable->getLength(); 12475 } 12476 mh = (kernel_mach_header_t *)loadAddress; 12477 loadAddress = ml_static_unslide(loadAddress); 12478 12479 /* Walk through the kext, looking for the first executable 12480 * segment in case we were asked for its size/address. 12481 */ 12482 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 12483 if (seg->initprot & VM_PROT_EXECUTE) { 12484 execLoadAddress = (flags.unslidMachO) ? seg->vmaddr : ml_static_unslide(seg->vmaddr); 12485 execLoadSize = (uint32_t)seg->vmsize; 12486 break; 12487 } 12488 } 12489 12490 /* If we have a kmod_info struct, calculated the wired size 12491 * from that. Otherwise it's the full load size. 12492 */ 12493 if (kmod_info) { 12494 wiredSize = loadSize - (uint32_t)kmod_info->hdr_size; 12495 } else { 12496 wiredSize = loadSize; 12497 } 12498 } else if (is_dext) { 12499 /* 12500 * DriverKit userspace executables do not have a kernel linkedExecutable, 12501 * so we "fake" their address range with the LoadTag. 12502 */ 12503 if (loadTag) { 12504 loadAddress = execLoadAddress = loadTag; 12505 loadSize = execLoadSize = 1; 12506 } 12507 } 12508 12509 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) { 12510 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12511 (unsigned long long)(loadAddress), 12512 /* numBits */ 8 * sizeof(loadAddress)); 12513 if (!scratchNumber) { 12514 goto finish; 12515 } 12516 result->setObject(kOSBundleLoadAddressKey, scratchNumber.get()); 12517 } 12518 if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) { 12519 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey)) 12520 && loadAddress && loadSize) { 12521 void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary); 12522 if (!baseAddress) { 12523 goto finish; 12524 } 12525 12526 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12527 (unsigned long long)ml_static_unslide((vm_offset_t)baseAddress), 12528 /* numBits */ 8 * sizeof(loadAddress)); 12529 if (!scratchNumber) { 12530 goto finish; 12531 } 12532 result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get()); 12533 } 12534 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey)) 12535 && (this == sKernelKext) && gBuiltinKmodsCount) { 12536 result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue); 12537 } 12538 } 12539 12540 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) { 12541 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12542 (unsigned long long)(execLoadAddress), 12543 /* numBits */ 8 * sizeof(execLoadAddress)); 12544 if (!scratchNumber) { 12545 goto finish; 12546 } 12547 result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get()); 12548 } 12549 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) { 12550 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12551 (unsigned long long)(loadSize), 12552 /* numBits */ 8 * sizeof(loadSize)); 12553 if (!scratchNumber) { 12554 goto finish; 12555 } 12556 result->setObject(kOSBundleLoadSizeKey, scratchNumber.get()); 12557 } 12558 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) { 12559 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12560 (unsigned long long)(execLoadSize), 12561 /* numBits */ 8 * sizeof(execLoadSize)); 12562 if (!scratchNumber) { 12563 goto finish; 12564 } 12565 result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get()); 12566 } 12567 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 12568 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12569 (unsigned long long)(wiredSize), 12570 /* numBits */ 8 * sizeof(wiredSize)); 12571 if (!scratchNumber) { 12572 goto finish; 12573 } 12574 result->setObject(kOSBundleWiredSizeKey, scratchNumber.get()); 12575 } 12576 } 12577 } 12578 12579 /* OSBundleDependencies. In descending order for 12580 * easy compatibility with kextstat(8). 12581 */ 12582 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) { 12583 if ((count = getNumDependencies())) { 12584 dependencyLoadTags = OSArray::withCapacity(count); 12585 result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get()); 12586 12587 i = count - 1; 12588 do { 12589 OSKext * dependency = OSDynamicCast(OSKext, 12590 dependencies->getObject(i)); 12591 12592 if (!dependency) { 12593 continue; 12594 } 12595 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12596 (unsigned long long)dependency->getLoadTag(), 12597 /* numBits*/ 8 * sizeof(loadTag)); 12598 if (!scratchNumber) { 12599 goto finish; 12600 } 12601 dependencyLoadTags->setObject(scratchNumber.get()); 12602 } while (i--); 12603 } 12604 } 12605 12606 /* OSBundleMetaClasses. 12607 */ 12608 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) { 12609 if (metaClasses && metaClasses->getCount()) { 12610 metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get()); 12611 metaClassInfo = OSArray::withCapacity(metaClasses->getCount()); 12612 if (!metaClassIterator || !metaClassInfo) { 12613 goto finish; 12614 } 12615 result->setObject(kOSBundleClassesKey, metaClassInfo.get()); 12616 12617 while ((thisMetaClass = OSDynamicCast(OSMetaClass, 12618 metaClassIterator->getNextObject()))) { 12619 metaClassDict = OSDictionary::withCapacity(3); 12620 if (!metaClassDict) { 12621 goto finish; 12622 } 12623 12624 metaClassName = OSString::withCString(thisMetaClass->getClassName()); 12625 if (thisMetaClass->getSuperClass()) { 12626 superclassName = OSString::withCString( 12627 thisMetaClass->getSuperClass()->getClassName()); 12628 } 12629 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(), 12630 8 * sizeof(unsigned int)); 12631 12632 /* Bail if any of the essentials is missing. The root class lacks a superclass, 12633 * of course. 12634 */ 12635 if (!metaClassDict || !metaClassName || !scratchNumber) { 12636 goto finish; 12637 } 12638 12639 metaClassInfo->setObject(metaClassDict.get()); 12640 metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get()); 12641 if (superclassName) { 12642 metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get()); 12643 } 12644 metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get()); 12645 } 12646 } 12647 } 12648 12649 /* OSBundleRetainCount. 12650 */ 12651 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) { 12652 { 12653 int kextRetainCount = getRetainCount() - 1; 12654 if (isLoaded()) { 12655 kextRetainCount--; 12656 } 12657 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12658 (int)kextRetainCount, 12659 /* numBits*/ 8 * sizeof(int)); 12660 if (scratchNumber) { 12661 result->setObject(kOSBundleRetainCountKey, scratchNumber.get()); 12662 } 12663 } 12664 } 12665 12666 success = true; 12667 12668 finish: 12669 if (executablePathCString) { 12670 kfree_data(executablePathCString, executablePathCStringSize); 12671 } 12672 if (!success) { 12673 result.reset(); 12674 } 12675 return result; 12676 } 12677 12678 /********************************************************************* 12679 *********************************************************************/ 12680 /* static */ 12681 bool 12682 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize) 12683 { 12684 bool ok; 12685 OSSharedPtr<OSKext> kext; 12686 12687 IORecursiveLockLock(sKextLock); 12688 kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain); 12689 IORecursiveLockUnlock(sKextLock); 12690 12691 if (!kext || !kext->path || !kext->userExecutableRelPath) { 12692 return false; 12693 } 12694 snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s", 12695 kext->path->getCStringNoCopy(), 12696 kext->userExecutableRelPath->getCStringNoCopy()); 12697 ok = true; 12698 12699 return ok; 12700 } 12701 12702 /********************************************************************* 12703 *********************************************************************/ 12704 /* static */ 12705 OSReturn 12706 OSKext::requestResource( 12707 const char * kextIdentifierCString, 12708 const char * resourceNameCString, 12709 OSKextRequestResourceCallback callback, 12710 void * context, 12711 OSKextRequestTag * requestTagOut) 12712 { 12713 OSReturn result = kOSReturnError; 12714 OSSharedPtr<OSKext> callbackKext; // looked up 12715 12716 OSKextRequestTag requestTag = -1; 12717 OSSharedPtr<OSNumber> requestTagNum; 12718 OSSharedPtr<OSDictionary> requestDict; 12719 OSSharedPtr<OSString> kextIdentifier; 12720 OSSharedPtr<OSString> resourceName; 12721 12722 OSSharedPtr<OSDictionary> callbackRecord; 12723 OSSharedPtr<OSValueObject<OSKextRequestResourceCallback> > callbackWrapper; 12724 12725 OSSharedPtr<OSValueObject<void *> > contextWrapper; 12726 12727 IORecursiveLockLock(sKextLock); 12728 12729 if (requestTagOut) { 12730 *requestTagOut = kOSKextRequestTagInvalid; 12731 } 12732 12733 /* If requests to user space are disabled, don't go any further */ 12734 if (!sKernelRequestsEnabled) { 12735 OSKextLog(/* kext */ NULL, 12736 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12737 "Can't request resource %s for %s - requests to user space are disabled.", 12738 resourceNameCString, 12739 kextIdentifierCString); 12740 result = kOSKextReturnDisabled; 12741 goto finish; 12742 } 12743 12744 if (!kextIdentifierCString || !resourceNameCString || !callback) { 12745 result = kOSKextReturnInvalidArgument; 12746 goto finish; 12747 } 12748 12749 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 12750 if (!callbackKext) { 12751 OSKextLog(/* kext */ NULL, 12752 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12753 "Resource request has bad callback address."); 12754 result = kOSKextReturnInvalidArgument; 12755 goto finish; 12756 } 12757 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 12758 OSKextLog(/* kext */ NULL, 12759 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12760 "Resource request callback is in a kext that is not started."); 12761 result = kOSKextReturnInvalidArgument; 12762 goto finish; 12763 } 12764 12765 /* Do not allow any new requests to be made on a kext that is unloading. 12766 */ 12767 if (callbackKext->flags.stopping) { 12768 result = kOSKextReturnStopping; 12769 goto finish; 12770 } 12771 12772 /* If we're wrapped the next available request tag around to the negative 12773 * numbers, we can't service any more requests. 12774 */ 12775 if (sNextRequestTag == kOSKextRequestTagInvalid) { 12776 OSKextLog(/* kext */ NULL, 12777 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12778 "No more request tags available; restart required."); 12779 result = kOSKextReturnNoResources; 12780 goto finish; 12781 } 12782 requestTag = sNextRequestTag++; 12783 12784 result = _OSKextCreateRequest(kKextRequestPredicateRequestResource, 12785 requestDict); 12786 if (result != kOSReturnSuccess) { 12787 goto finish; 12788 } 12789 12790 kextIdentifier = OSString::withCString(kextIdentifierCString); 12791 resourceName = OSString::withCString(resourceNameCString); 12792 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 12793 8 * sizeof(requestTag)); 12794 if (!kextIdentifier || 12795 !resourceName || 12796 !requestTagNum || 12797 !_OSKextSetRequestArgument(requestDict.get(), 12798 kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) || 12799 !_OSKextSetRequestArgument(requestDict.get(), 12800 kKextRequestArgumentNameKey, resourceName.get()) || 12801 !_OSKextSetRequestArgument(requestDict.get(), 12802 kKextRequestArgumentRequestTagKey, requestTagNum.get())) { 12803 result = kOSKextReturnNoMemory; 12804 goto finish; 12805 } 12806 12807 callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection()); 12808 if (!callbackRecord) { 12809 result = kOSKextReturnNoMemory; 12810 goto finish; 12811 } 12812 // we validate callback address at call time 12813 callbackWrapper = OSValueObjectWithValue(callback); 12814 if (context) { 12815 contextWrapper = OSValueObjectWithValue(context); 12816 } 12817 if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(), 12818 kKextRequestArgumentCallbackKey, callbackWrapper.get())) { 12819 result = kOSKextReturnNoMemory; 12820 goto finish; 12821 } 12822 12823 if (context) { 12824 if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(), 12825 kKextRequestArgumentContextKey, contextWrapper.get())) { 12826 result = kOSKextReturnNoMemory; 12827 goto finish; 12828 } 12829 } 12830 12831 /* Only post the requests after all the other potential failure points 12832 * have been passed. 12833 */ 12834 if (!sKernelRequests->setObject(requestDict.get()) || 12835 !sRequestCallbackRecords->setObject(callbackRecord.get())) { 12836 result = kOSKextReturnNoMemory; 12837 goto finish; 12838 } 12839 12840 OSKext::pingIOKitDaemon(); 12841 12842 result = kOSReturnSuccess; 12843 if (requestTagOut) { 12844 *requestTagOut = requestTag; 12845 } 12846 12847 finish: 12848 12849 /* If we didn't succeed, yank the request & callback 12850 * from their holding arrays. 12851 */ 12852 if (result != kOSReturnSuccess) { 12853 unsigned int index; 12854 12855 index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0); 12856 if (index != (unsigned int)-1) { 12857 sKernelRequests->removeObject(index); 12858 } 12859 index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0); 12860 if (index != (unsigned int)-1) { 12861 sRequestCallbackRecords->removeObject(index); 12862 } 12863 } 12864 12865 OSKext::considerUnloads(/* rescheduleOnly? */ true); 12866 12867 IORecursiveLockUnlock(sKextLock); 12868 12869 return result; 12870 } 12871 12872 OSReturn 12873 OSKext::requestDaemonLaunch( 12874 OSString *kextIdentifier, 12875 OSString *serverName, 12876 OSNumber *serverTag, 12877 OSBoolean *reslide, 12878 IOUserServerCheckInToken * checkInToken, 12879 OSData *serverDUI) 12880 { 12881 OSReturn result = kOSReturnError; 12882 OSSharedPtr<OSDictionary> requestDict; 12883 unsigned int size = 0; 12884 const char *dextUniqueIDCString = NULL; 12885 12886 if (!kextIdentifier || !serverName || !serverTag || !checkInToken) { 12887 return kOSKextReturnInvalidArgument; 12888 } 12889 if (!iokitDaemonAvailable()) { 12890 panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable"); 12891 } 12892 12893 if (serverDUI != NULL) { 12894 dextUniqueIDCString = getDextUniqueIDCString(serverDUI, &size); 12895 } 12896 12897 IORecursiveLockLock(sKextLock); 12898 12899 OSKextLog(/* kext */ NULL, 12900 kOSKextLogDebugLevel | 12901 kOSKextLogGeneralFlag, 12902 "Requesting daemon launch for %s %s with serverName %s and tag %llu%s", 12903 kextIdentifier->getCStringNoCopy(), 12904 (dextUniqueIDCString != NULL)?dextUniqueIDCString:"", 12905 serverName->getCStringNoCopy(), 12906 serverTag->unsigned64BitValue(), 12907 reslide == kOSBooleanTrue ? " with reslid shared cache" : "" 12908 ); 12909 12910 result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict); 12911 if (result != kOSReturnSuccess) { 12912 goto finish; 12913 } 12914 12915 if (!_OSKextSetRequestArgument(requestDict.get(), 12916 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) || 12917 !_OSKextSetRequestArgument(requestDict.get(), 12918 kKextRequestArgumentDriverExtensionServerName, serverName) || 12919 !_OSKextSetRequestArgument(requestDict.get(), 12920 kKextRequestArgumentDriverExtensionServerTag, serverTag) || 12921 !_OSKextSetRequestArgument(requestDict.get(), 12922 kKextRequestArgumentDriverExtensionReslideSharedCache, reslide) || 12923 !_OSKextSetRequestArgument(requestDict.get(), 12924 kKextRequestArgumentCheckInToken, checkInToken)) { 12925 result = kOSKextReturnNoMemory; 12926 goto finish; 12927 } 12928 12929 if (serverDUI) { 12930 if (!_OSKextSetRequestArgument(requestDict.get(), 12931 kOSBundleDextUniqueIdentifierKey, serverDUI)) { 12932 result = kOSKextReturnNoMemory; 12933 goto finish; 12934 } 12935 } 12936 12937 /* Only post the requests after all the other potential failure points 12938 * have been passed. 12939 */ 12940 if (!sKernelRequests->setObject(requestDict.get())) { 12941 result = kOSKextReturnNoMemory; 12942 goto finish; 12943 } 12944 result = OSKext::pingIOKitDaemon(); 12945 if (result != kOSReturnSuccess) { 12946 goto finish; 12947 } 12948 12949 result = kOSReturnSuccess; 12950 finish: 12951 IORecursiveLockUnlock(sKextLock); 12952 if (dextUniqueIDCString) { 12953 kfree_data(dextUniqueIDCString, size); 12954 } 12955 return result; 12956 } 12957 12958 OSReturn 12959 OSKext::notifyDextUpgrade( 12960 OSString *kextIdentifier, 12961 OSData *dextUniqueIdentifier) 12962 { 12963 OSReturn result = kOSReturnError; 12964 OSSharedPtr<OSDictionary> requestDict; 12965 unsigned int size = 0; 12966 const char *dextUniqueIDCString = getDextUniqueIDCString(dextUniqueIdentifier, &size); 12967 assert(dextUniqueIDCString != NULL); 12968 12969 IORecursiveLockLock(sKextLock); 12970 12971 OSKextLog(NULL, 12972 kOSKextLogDebugLevel | 12973 kOSKextLogGeneralFlag, 12974 "Notifying of dext upgrade for %s with UniqueID %s", 12975 kextIdentifier->getCStringNoCopy(), dextUniqueIDCString); 12976 12977 result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonUpgradeNotification, requestDict); 12978 if (result != kOSReturnSuccess) { 12979 goto finish; 12980 } 12981 12982 if (!_OSKextSetRequestArgument(requestDict.get(), 12983 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) || 12984 !_OSKextSetRequestArgument(requestDict.get(), 12985 kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) { 12986 result = kOSKextReturnNoMemory; 12987 goto finish; 12988 } 12989 12990 /* Only post the requests after all the other potential failure points 12991 * have been passed. 12992 */ 12993 if (!sKernelRequests->setObject(requestDict.get())) { 12994 result = kOSKextReturnNoMemory; 12995 goto finish; 12996 } 12997 OSKext::pingIOKitDaemon(); 12998 12999 result = kOSReturnSuccess; 13000 finish: 13001 IORecursiveLockUnlock(sKextLock); 13002 13003 if (dextUniqueIDCString != NULL) { 13004 kfree_data(dextUniqueIDCString, size); 13005 } 13006 return result; 13007 } 13008 13009 /********************************************************************* 13010 * Assumes sKextLock is held. 13011 *********************************************************************/ 13012 /* static */ 13013 OSReturn 13014 OSKext::dequeueCallbackForRequestTag( 13015 OSKextRequestTag requestTag, 13016 OSSharedPtr<OSDictionary> &callbackRecordOut) 13017 { 13018 OSDictionary * callbackRecordOutRaw = NULL; 13019 OSReturn result; 13020 13021 result = dequeueCallbackForRequestTag(requestTag, 13022 &callbackRecordOutRaw); 13023 13024 if (kOSReturnSuccess == result) { 13025 callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain); 13026 } 13027 13028 return result; 13029 } 13030 OSReturn 13031 OSKext::dequeueCallbackForRequestTag( 13032 OSKextRequestTag requestTag, 13033 OSDictionary ** callbackRecordOut) 13034 { 13035 OSReturn result = kOSReturnError; 13036 OSSharedPtr<OSNumber> requestTagNum; 13037 13038 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 13039 8 * sizeof(requestTag)); 13040 if (!requestTagNum) { 13041 goto finish; 13042 } 13043 13044 result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(), 13045 callbackRecordOut); 13046 13047 finish: 13048 return result; 13049 } 13050 13051 /********************************************************************* 13052 * Assumes sKextLock is held. 13053 *********************************************************************/ 13054 /* static */ 13055 OSReturn 13056 OSKext::dequeueCallbackForRequestTag( 13057 OSNumber * requestTagNum, 13058 OSSharedPtr<OSDictionary> &callbackRecordOut) 13059 { 13060 OSDictionary * callbackRecordOutRaw = NULL; 13061 OSReturn result; 13062 13063 result = dequeueCallbackForRequestTag(requestTagNum, 13064 &callbackRecordOutRaw); 13065 13066 if (kOSReturnSuccess == result) { 13067 callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain); 13068 } 13069 13070 return result; 13071 } 13072 OSReturn 13073 OSKext::dequeueCallbackForRequestTag( 13074 OSNumber * requestTagNum, 13075 OSDictionary ** callbackRecordOut) 13076 { 13077 OSReturn result = kOSKextReturnInvalidArgument; 13078 OSDictionary * callbackRecord = NULL; // retain if matched! 13079 OSNumber * callbackTagNum = NULL; // do not release 13080 unsigned int count, i; 13081 13082 result = kOSReturnError; 13083 count = sRequestCallbackRecords->getCount(); 13084 for (i = 0; i < count; i++) { 13085 callbackRecord = OSDynamicCast(OSDictionary, 13086 sRequestCallbackRecords->getObject(i)); 13087 if (!callbackRecord) { 13088 goto finish; 13089 } 13090 13091 /* If we don't find a tag, we basically have a leak here. Maybe 13092 * we should just remove it. 13093 */ 13094 callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument( 13095 callbackRecord, kKextRequestArgumentRequestTagKey)); 13096 if (!callbackTagNum) { 13097 goto finish; 13098 } 13099 13100 /* We could be even more paranoid and check that all the incoming 13101 * args match what's in the callback record. 13102 */ 13103 if (callbackTagNum->isEqualTo(requestTagNum)) { 13104 if (callbackRecordOut) { 13105 *callbackRecordOut = callbackRecord; 13106 callbackRecord->retain(); 13107 } 13108 sRequestCallbackRecords->removeObject(i); 13109 result = kOSReturnSuccess; 13110 goto finish; 13111 } 13112 } 13113 result = kOSKextReturnNotFound; 13114 13115 finish: 13116 return result; 13117 } 13118 13119 13120 /********************************************************************* 13121 * Busy timeout triage 13122 *********************************************************************/ 13123 /* static */ 13124 bool 13125 OSKext::pendingIOKitDaemonRequests(void) 13126 { 13127 return sRequestCallbackRecords && sRequestCallbackRecords->getCount(); 13128 } 13129 13130 /********************************************************************* 13131 * Acquires and releases sKextLock 13132 * 13133 * This function is designed to be called by kernelmanagerd and driverkitd 13134 * and it gathers all codeless kext and dext personalities, and then attempts 13135 * to map a System (pageable) KC and an Auxiliary (aux) KC. 13136 * 13137 * The pageable and aux KC can be loaded only once at boot time. 13138 * Even if the pageable or aux KC fail to load - this function will 13139 * not allow a new pageable or aux KC to be installed by subsequent calls. 13140 * This is done to avoid security issues where userspace has been compromised 13141 * or the pageable kc has been tampered with and the attacker 13142 * attempts to re-load a malicious variant. 13143 * However dexts can be dynamically loaded, so this function can be used 13144 * to request the installation of a new set of dexts even after boot time. 13145 * 13146 * 13147 * 13148 * Return: if a KC fails to load the return value will contain: 13149 * kOSKextReturnKCLoadFailure. If the pageable KC fails, 13150 * the return value will contain kOSKextReturnKCLoadFailureSystemKC. 13151 * Similarly, if the aux kc load fails, the return value will 13152 * contain kOSKextReturnKCLoadFailureAuxKC. The two values 13153 * compose with each other and with kOSKextReturnKCLoadFailure. 13154 *********************************************************************/ 13155 /* static */ 13156 OSReturn 13157 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused) 13158 { 13159 static bool daemon_ready = false; 13160 13161 OSReturn ret = kOSKextReturnInvalidArgument; 13162 OSReturn kcerr = 0; 13163 bool start_matching = false; 13164 13165 bool allow_fileset_load = !daemon_ready; 13166 #if !(defined(__x86_64__) || defined(__i386__)) 13167 /* never allow KCs full of kexts on non-x86 machines */ 13168 allow_fileset_load = false; 13169 #endif 13170 13171 /* 13172 * Change with 70582300 13173 */ 13174 #if 0 || !defined(VM_MAPPED_KEXTS) 13175 /* 13176 * On platforms that don't support the SystemKC or a file-backed 13177 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter 13178 * needs to be queried before we load any codeless kexts or release 13179 * any 3rd party kexts to run. On platforms that support a file-backed 13180 * AuxKC, this process is done via the kext audit mechanism. 13181 */ 13182 13183 printf("KextLog: waiting for kext receipt to be queried.\n"); 13184 while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) { 13185 IOSleep(30); 13186 } 13187 #endif /* !VM_MAPPED_KEXTS */ 13188 13189 /* 13190 * Get the args from the request. Right now we need the file 13191 * name for the pageable and the aux kext collection file sets. 13192 */ 13193 OSDictionary * requestArgs = NULL; // do not release 13194 OSString * pageable_filepath = NULL; // do not release 13195 OSString * aux_filepath = NULL; // do not release 13196 OSArray * codeless_kexts = NULL; // do not release 13197 13198 kernel_mach_header_t *akc_mh = NULL; 13199 13200 requestArgs = OSDynamicCast(OSDictionary, 13201 requestDict->getObject(kKextRequestArgumentsKey)); 13202 13203 if (requestArgs == NULL) { 13204 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13205 "KextLog: No arguments in plist for loading fileset kext\n"); 13206 printf("KextLog: No arguments in plist for loading fileset kext\n"); 13207 return ret; 13208 } 13209 13210 ret = kOSKextReturnDisabled; 13211 13212 IORecursiveLockLock(sKextLock); 13213 13214 if (!sLoadEnabled) { 13215 OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag, 13216 "KextLog: Kext loading is disabled (attempt to load KCs)."); 13217 IORecursiveLockUnlock(sKextLock); 13218 return ret; 13219 } 13220 13221 pageable_filepath = OSDynamicCast(OSString, 13222 requestArgs->getObject(kKextRequestArgumentPageableKCFilename)); 13223 13224 if (allow_fileset_load && pageable_filepath != NULL) { 13225 printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy()); 13226 13227 ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable); 13228 if (ret) { 13229 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13230 "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret); 13231 13232 printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret); 13233 ret = kOSKextReturnKCLoadFailure; 13234 kcerr |= kOSKextReturnKCLoadFailureSystemKC; 13235 goto try_auxkc; 13236 } 13237 /* 13238 * Even if the AuxKC fails to load, we still want to send 13239 * the System KC personalities to the catalog for matching 13240 */ 13241 start_matching = true; 13242 } else if (pageable_filepath != NULL) { 13243 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 13244 "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy()); 13245 ret = kOSKextReturnUnsupported; 13246 } 13247 13248 try_auxkc: 13249 akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary); 13250 if (akc_mh) { 13251 /* 13252 * If we try to load a deferred AuxKC, then don't ever attempt 13253 * a filesystem map of a file 13254 */ 13255 allow_fileset_load = false; 13256 13257 /* 13258 * This function is only called once per boot, so we haven't 13259 * yet loaded an AuxKC. If we have registered the AuxKC mach 13260 * header, that means that the kext collection has been placed 13261 * in memory for us by the booter, and is waiting for us to 13262 * process it. Grab the deferred XML plist of info 13263 * dictionaries and add all the kexts. 13264 */ 13265 OSSharedPtr<OSObject> parsedXML; 13266 OSSharedPtr<OSData> loaded_kcUUID; 13267 OSDictionary *infoDict; 13268 parsedXML = consumeDeferredKextCollection(KCKindAuxiliary); 13269 infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 13270 #if !defined(VM_MAPPED_KEXTS) 13271 /* 13272 * On platforms where we don't dynamically wire-down / page-in 13273 * kext memory, we need to maintain the invariant that if the 13274 * AuxKC in memory does not contain a kext receipt, then we 13275 * should not load any of the kexts. 13276 */ 13277 size_t receipt_sz = 0; 13278 if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) { 13279 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13280 "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt"); 13281 ret = kOSKextReturnKCLoadFailure; 13282 goto try_codeless; 13283 } 13284 #endif 13285 if (infoDict) { 13286 bool added; 13287 printf("KextLog: Adding kexts from in-memory AuxKC\n"); 13288 added = OSKext::addKextsFromKextCollection(akc_mh, infoDict, 13289 kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary); 13290 if (!loaded_kcUUID) { 13291 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13292 "KextLog: WARNING: did not find UUID in deferred Aux KC!"); 13293 } else if (!added) { 13294 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13295 "KextLog: WARNING: Failed to load AuxKC from memory."); 13296 } 13297 /* only return success if the pageable load (above) was successful */ 13298 if (ret != kOSKextReturnKCLoadFailure) { 13299 ret = kOSReturnSuccess; 13300 } 13301 /* the registration of the AuxKC parsed out the KC's UUID already */ 13302 } else { 13303 if (daemon_ready) { 13304 /* 13305 * Complain, but don't return an error if this isn't the first time the 13306 * IOKit daemon is checking in. If the daemon ever restarts, we will 13307 * hit this case because we've already consumed the deferred personalities. 13308 * We return success here so that a call to this function from a restarted 13309 * daemon with no codeless kexts will succeed. 13310 */ 13311 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 13312 "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart"); 13313 if (ret != kOSKextReturnKCLoadFailure) { 13314 ret = kOSReturnSuccess; 13315 } 13316 } else { 13317 /* this is a real error case */ 13318 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag, 13319 "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary"); 13320 printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n"); 13321 ret = kOSKextReturnKCLoadFailure; 13322 kcerr |= kOSKextReturnKCLoadFailureAuxKC; 13323 } 13324 } 13325 } 13326 13327 aux_filepath = OSDynamicCast(OSString, 13328 requestArgs->getObject(kKextRequestArgumentAuxKCFilename)); 13329 if (allow_fileset_load && aux_filepath != NULL) { 13330 printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy()); 13331 13332 ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary); 13333 if (ret) { 13334 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13335 "KextLog: loadKCFileSet for Aux KC returned %d\n", ret); 13336 13337 printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret); 13338 ret = kOSKextReturnKCLoadFailure; 13339 kcerr |= kOSKextReturnKCLoadFailureAuxKC; 13340 goto try_codeless; 13341 } 13342 start_matching = true; 13343 } else if (aux_filepath != NULL) { 13344 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 13345 "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy()); 13346 if (ret != kOSKextReturnKCLoadFailure) { 13347 ret = kOSKextReturnUnsupported; 13348 } 13349 } 13350 13351 try_codeless: 13352 /* 13353 * Load codeless kexts last so that there is no possibilty of a 13354 * codeless kext bundle ID preventing a kext in the system KC from 13355 * loading 13356 */ 13357 codeless_kexts = OSDynamicCast(OSArray, 13358 requestArgs->getObject(kKextRequestArgumentCodelessPersonalities)); 13359 if (codeless_kexts != NULL) { 13360 uint32_t count = codeless_kexts->getCount(); 13361 OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13362 "KextLog: loading %d codeless kexts/dexts", count); 13363 for (uint32_t i = 0; i < count; i++) { 13364 OSDictionary *infoDict; 13365 infoDict = OSDynamicCast(OSDictionary, 13366 codeless_kexts->getObject(i)); 13367 if (!infoDict) { 13368 continue; 13369 } 13370 // instantiate a new kext, and don't hold a reference 13371 // (the kext subsystem will hold one implicitly) 13372 OSKext::withCodelessInfo(infoDict, NULL); 13373 } 13374 /* ignore errors that are not KC load failures */ 13375 if (ret != kOSKextReturnKCLoadFailure) { 13376 ret = kOSReturnSuccess; 13377 } 13378 start_matching = true; 13379 } 13380 13381 /* send personalities to the IOCatalog once */ 13382 if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) { 13383 OSKext::sendAllKextPersonalitiesToCatalog(true); 13384 /* 13385 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark 13386 * things as active and start all the delayed matching: the 13387 * dext and codeless kext personalities should have all been 13388 * delivered via this one call. 13389 */ 13390 if (!daemon_ready) { 13391 OSKext::setIOKitDaemonActive(); 13392 OSKext::setDeferredLoadSucceeded(TRUE); 13393 IOService::iokitDaemonLaunched(); 13394 } 13395 if (sOSKextWasResetAfterUserspaceReboot) { 13396 sOSKextWasResetAfterUserspaceReboot = false; 13397 OSKext::setIOKitDaemonActive(); 13398 IOService::startDeferredMatches(); 13399 } 13400 } 13401 13402 if (ret == kOSKextReturnKCLoadFailure) { 13403 ret |= kcerr; 13404 } 13405 13406 /* 13407 * Only allow this function to attempt to load the pageable and 13408 * aux KCs once per boot. 13409 */ 13410 daemon_ready = true; 13411 13412 IORecursiveLockUnlock(sKextLock); 13413 13414 return ret; 13415 } 13416 13417 OSReturn 13418 OSKext::resetMutableSegments(void) 13419 { 13420 kernel_segment_command_t *seg = NULL; 13421 kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address; 13422 u_int index = 0; 13423 OSKextSavedMutableSegment *savedSegment = NULL; 13424 uintptr_t kext_slide = PE_get_kc_slide(kc_type); 13425 OSReturn err; 13426 13427 if (!savedMutableSegments) { 13428 OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag, 13429 "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString()); 13430 err = kOSKextReturnInternalError; 13431 goto finish; 13432 } 13433 13434 for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) { 13435 if (!segmentIsMutable(seg)) { 13436 continue; 13437 } 13438 uint64_t unslid_vmaddr = seg->vmaddr - kext_slide; 13439 uint64_t vmsize = seg->vmsize; 13440 err = kOSKextReturnInternalError; 13441 for (index = 0; index < savedMutableSegments->getCount(); index++) { 13442 savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index)); 13443 assert(savedSegment); 13444 if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) { 13445 OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag, 13446 "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1); 13447 err = savedSegment->restoreContents(seg); 13448 if (err != kOSReturnSuccess) { 13449 panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 13450 } 13451 } 13452 } 13453 if (err != kOSReturnSuccess) { 13454 panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 13455 } 13456 } 13457 err = kOSReturnSuccess; 13458 finish: 13459 return err; 13460 } 13461 13462 13463 /********************************************************************* 13464 * Assumes sKextLock is held. 13465 *********************************************************************/ 13466 /* static */ 13467 OSReturn 13468 OSKext::loadKCFileSet( 13469 const char *filepath, 13470 kc_kind_t type) 13471 { 13472 #if VM_MAPPED_KEXTS 13473 /* we only need to load filesets on systems that support VM_MAPPED kexts */ 13474 OSReturn err; 13475 struct vnode *vp = NULL; 13476 void *fileset_control; 13477 off_t fsize; 13478 bool pageable = (type == KCKindPageable); 13479 13480 if ((pageable && pageableKCloaded) || 13481 (!pageable && auxKCloaded)) { 13482 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13483 "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux")); 13484 13485 return kOSKextReturnInvalidArgument; 13486 } 13487 13488 /* Do not allow AuxKC to load if Pageable KC is not loaded */ 13489 if (!pageable && !pageableKCloaded) { 13490 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13491 "Trying to load the Aux KC without loading the Pageable KC"); 13492 return kOSKextReturnInvalidArgument; 13493 } 13494 13495 fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize); 13496 13497 if (fileset_control == NULL) { 13498 printf("Could not get memory control object for file %s", filepath); 13499 13500 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13501 "Could not get memory control object for file %s", filepath); 13502 return kOSKextReturnInvalidArgument; 13503 } 13504 if (vp == NULL) { 13505 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13506 "Could not find vnode for file %s", filepath); 13507 return kOSKextReturnInvalidArgument; 13508 } 13509 13510 kernel_mach_header_t *mh = NULL; 13511 uintptr_t slide = 0; 13512 13513 #if CONFIG_CSR 13514 /* 13515 * When SIP is enabled, the KC we map must be SIP-protected 13516 */ 13517 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) { 13518 struct vnode_attr va; 13519 int error; 13520 VATTR_INIT(&va); 13521 VATTR_WANTED(&va, va_flags); 13522 error = vnode_getattr(vp, &va, vfs_context_current()); 13523 if (error) { 13524 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13525 "vnode_getattr(%s) failed (error=%d)", filepath, error); 13526 err = kOSKextReturnInternalError; 13527 goto finish; 13528 } 13529 if (!(va.va_flags & SF_RESTRICTED)) { 13530 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13531 "Path to KC '%s' is not SIP-protected", filepath); 13532 err = kOSKextReturnInvalidArgument; 13533 goto finish; 13534 } 13535 } 13536 #endif 13537 13538 err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL); 13539 if (err) { 13540 printf("KextLog: mapKCFileSet returned %d\n", err); 13541 13542 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13543 "mapKCFileSet returned %d\n", err); 13544 13545 err = kOSKextReturnInvalidArgument; 13546 } 13547 13548 #if CONFIG_CSR 13549 finish: 13550 #endif 13551 /* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */ 13552 assert(vp != NULL); 13553 if (err == kOSReturnSuccess) { 13554 PE_set_kc_vp(type, vp); 13555 if (pageable) { 13556 pageableKCloaded = true; 13557 } else { 13558 auxKCloaded = true; 13559 } 13560 } else { 13561 vnode_put(vp); 13562 } 13563 13564 return err; 13565 #else 13566 (void)filepath; 13567 (void)type; 13568 return kOSKextReturnUnsupported; 13569 #endif // VM_MAPPED_KEXTS 13570 } 13571 13572 #if defined(__x86_64__) || defined(__i386__) 13573 /********************************************************************* 13574 * Assumes sKextLock is held. 13575 *********************************************************************/ 13576 /* static */ 13577 OSReturn 13578 OSKext::mapKCFileSet( 13579 void *control, 13580 vm_size_t fsize, 13581 kernel_mach_header_t **mhp, 13582 off_t file_offset, 13583 uintptr_t *slidep, 13584 bool pageable, 13585 void *map_entry_list) 13586 { 13587 bool fileset_load = false; 13588 kern_return_t ret; 13589 OSReturn err; 13590 kernel_section_t *infoPlistSection = NULL; 13591 OSDictionary *infoDict = NULL; 13592 13593 OSSharedPtr<OSObject> parsedXML; 13594 OSSharedPtr<OSString> errorString; 13595 OSSharedPtr<OSData> loaded_kcUUID; 13596 13597 /* Check if initial load for file set */ 13598 if (*mhp == NULL) { 13599 fileset_load = true; 13600 13601 /* Get a page aligned address from kext map to map the file */ 13602 vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize); 13603 if (pagealigned_addr == 0) { 13604 return kOSKextReturnNoMemory; 13605 } 13606 13607 *mhp = (kernel_mach_header_t *)pagealigned_addr; 13608 13609 /* Allocate memory for bailout mechanism */ 13610 map_entry_list = allocate_kcfileset_map_entry_list(); 13611 if (map_entry_list == NULL) { 13612 return kOSKextReturnNoMemory; 13613 } 13614 } 13615 13616 uintptr_t *slideptr = fileset_load ? slidep : NULL; 13617 err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list); 13618 /* mhp and slideptr are updated by mapKCTextSegment */ 13619 if (err) { 13620 if (fileset_load) { 13621 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13622 } 13623 return err; 13624 } 13625 13626 /* Initialize the kc header globals */ 13627 if (fileset_load) { 13628 if (pageable) { 13629 PE_set_kc_header(KCKindPageable, *mhp, *slidep); 13630 } else { 13631 PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep); 13632 } 13633 } 13634 13635 /* Iterate through all the segments and map necessary segments */ 13636 struct load_command *lcp = (struct load_command *) (*mhp + 1); 13637 for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) { 13638 vm_map_offset_t start; 13639 kernel_mach_header_t *k_mh = NULL; 13640 kernel_segment_command_t * seg = NULL; 13641 struct fileset_entry_command *fse = NULL; 13642 13643 if (lcp->cmd == LC_SEGMENT_KERNEL) { 13644 seg = (kernel_segment_command_t *)lcp; 13645 start = ((uintptr_t)(seg->vmaddr)) + *slidep; 13646 } else if (lcp->cmd == LC_FILESET_ENTRY) { 13647 fse = (struct fileset_entry_command *)lcp; 13648 k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep); 13649 13650 /* Map the segments of the mach-o binary */ 13651 err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list); 13652 if (err) { 13653 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13654 return kOSKextReturnInvalidArgument; 13655 } 13656 continue; 13657 } else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) { 13658 /* Check if the Aux KC is built pageable style */ 13659 if (!pageable && !fileset_load && !auxKCloaded) { 13660 resetAuxKCSegmentOnUnload = true; 13661 } 13662 continue; 13663 } else { 13664 continue; 13665 } 13666 13667 if (fileset_load) { 13668 if (seg->vmsize == 0) { 13669 continue; 13670 } 13671 13672 /* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */ 13673 if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 && 13674 strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 && 13675 strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 && 13676 strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) { 13677 continue; 13678 } 13679 } else { 13680 if (seg->vmsize == 0) { 13681 continue; 13682 } 13683 13684 /* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */ 13685 if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 || 13686 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 || 13687 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) { 13688 continue; 13689 } 13690 } 13691 13692 ret = vm_map_kcfileset_segment( 13693 &start, seg->vmsize, 13694 (memory_object_control_t)control, seg->fileoff, seg->maxprot); 13695 13696 if (ret != KERN_SUCCESS) { 13697 if (fileset_load) { 13698 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13699 } 13700 return kOSKextReturnInvalidArgument; 13701 } 13702 add_kcfileset_map_entry(map_entry_list, start, seg->vmsize); 13703 } 13704 13705 /* Return if regular mach-o */ 13706 if (!fileset_load) { 13707 return 0; 13708 } 13709 13710 /* 13711 * Fixup for the Pageable KC and the Aux KC is done by 13712 * i386_slide_kext_collection_mh_addrs, but it differs in 13713 * following ways: 13714 * 13715 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands. 13716 * The fixup of kext segments and kext load commands are done at kext 13717 * load time by calling i386_slide_individual_kext. 13718 * 13719 * AuxKC old style: Fixup all the segments and all the load commands. 13720 * 13721 * AuxKC pageable style: Same as the Pageable KC. 13722 */ 13723 bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false)); 13724 ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header); 13725 if (ret != KERN_SUCCESS) { 13726 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13727 return kOSKextReturnInvalidArgument; 13728 } 13729 13730 /* Get the prelink info dictionary */ 13731 infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection); 13732 parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString); 13733 if (parsedXML) { 13734 infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 13735 } 13736 13737 if (!infoDict) { 13738 const char *errorCString = "(unknown error)"; 13739 13740 if (errorString && errorString->getCStringNoCopy()) { 13741 errorCString = errorString->getCStringNoCopy(); 13742 } else if (parsedXML) { 13743 errorCString = "not a dictionary"; 13744 } 13745 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13746 "Error unserializing kext info plist section: %s.", errorCString); 13747 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13748 return kOSKextReturnInvalidArgument; 13749 } 13750 13751 /* Validate that the Kext Collection is prelinked to the loaded KC */ 13752 err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary); 13753 if (err) { 13754 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13755 return kOSKextReturnInvalidArgument; 13756 } 13757 13758 /* Set Protection of Segments */ 13759 OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary); 13760 13761 OSKext::addKextsFromKextCollection(*mhp, 13762 infoDict, kPrelinkTextSegment, 13763 loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary); 13764 13765 /* Copy in the KC UUID */ 13766 if (!loaded_kcUUID) { 13767 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13768 "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux"); 13769 } else if (pageable) { 13770 pageablekc_uuid_valid = TRUE; 13771 memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength()); 13772 uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string); 13773 } else { 13774 auxkc_uuid_valid = TRUE; 13775 memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength()); 13776 uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string); 13777 } 13778 13779 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable); 13780 13781 return 0; 13782 } 13783 13784 /********************************************************************* 13785 * Assumes sKextLock is held. 13786 *********************************************************************/ 13787 /* static */ 13788 OSReturn 13789 OSKext::mapKCTextSegment( 13790 void *control, 13791 kernel_mach_header_t **mhp, 13792 off_t file_offset, 13793 uintptr_t *slidep, 13794 void *map_entry_list) 13795 { 13796 kern_return_t ret; 13797 vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t), 13798 PAGE_MASK); 13799 vm_map_offset_t load_command_map_size = 0; 13800 kernel_mach_header_t *base_mh = *mhp; 13801 13802 /* Map the mach header at start of fileset for now (vmaddr = 0) */ 13803 ret = vm_map_kcfileset_segment( 13804 (vm_map_offset_t *)&base_mh, mach_header_map_size, 13805 (memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE)); 13806 13807 if (ret != KERN_SUCCESS) { 13808 printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret); 13809 13810 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13811 "Failed to map mach header of kc fileset with error %d", ret); 13812 return kOSKextReturnInvalidArgument; 13813 } 13814 13815 if (slidep) { 13816 /* Verify that it's an MH_FILESET */ 13817 if (base_mh->filetype != MH_FILESET) { 13818 printf("Kext Log: mapKCTextSegment mach header filetype" 13819 " is not an MH_FILESET, it is %x", base_mh->filetype); 13820 13821 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13822 "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype); 13823 13824 /* Unmap the mach header */ 13825 vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 13826 return kOSKextReturnInvalidArgument; 13827 } 13828 } 13829 13830 /* Map the remaining pages of load commands */ 13831 if (base_mh->sizeofcmds > mach_header_map_size) { 13832 vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size; 13833 load_command_map_size = base_mh->sizeofcmds - mach_header_map_size; 13834 13835 /* Map the load commands */ 13836 ret = vm_map_kcfileset_segment( 13837 &load_command_addr, load_command_map_size, 13838 (memory_object_control_t)control, file_offset + mach_header_map_size, 13839 (VM_PROT_READ | VM_PROT_WRITE)); 13840 13841 if (ret != KERN_SUCCESS) { 13842 printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret); 13843 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13844 "Failed to map load commands of kc fileset with error %d", ret); 13845 13846 /* Unmap the mach header */ 13847 vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 13848 return kOSKextReturnInvalidArgument; 13849 } 13850 } 13851 13852 kernel_segment_command_t *text_seg; 13853 text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT); 13854 13855 /* Calculate the slide and vm addr of mach header */ 13856 if (slidep) { 13857 *mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr); 13858 *slidep = ((uintptr_t)*mhp) - text_seg->vmaddr; 13859 } 13860 13861 /* Cache the text segment size and file offset before unmapping */ 13862 vm_map_offset_t text_segment_size = text_seg->vmsize; 13863 vm_object_offset_t text_segment_fileoff = text_seg->fileoff; 13864 vm_prot_t text_maxprot = text_seg->maxprot; 13865 13866 /* Unmap the first page and loadcommands and map the text segment */ 13867 ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 13868 assert(ret == KERN_SUCCESS); 13869 13870 if (load_command_map_size) { 13871 vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size; 13872 ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size); 13873 assert(ret == KERN_SUCCESS); 13874 } 13875 13876 /* Map the text segment at actual vm addr specified in fileset */ 13877 ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size, 13878 (memory_object_control_t)control, text_segment_fileoff, text_maxprot); 13879 if (ret != KERN_SUCCESS) { 13880 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13881 "Failed to map Text segment of kc fileset with error %d", ret); 13882 return kOSKextReturnInvalidArgument; 13883 } 13884 13885 add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size); 13886 return 0; 13887 } 13888 13889 /********************************************************************* 13890 * Assumes sKextLock is held. 13891 *********************************************************************/ 13892 /* static */ 13893 OSReturn 13894 OSKext::protectKCFileSet( 13895 kernel_mach_header_t *mh, 13896 kc_kind_t type) 13897 { 13898 vm_map_t kext_map = g_kext_map; 13899 kernel_segment_command_t * seg = NULL; 13900 vm_map_offset_t start = 0; 13901 vm_map_offset_t end = 0; 13902 OSReturn ret = 0; 13903 13904 /* Set VM permissions */ 13905 seg = firstsegfromheader((kernel_mach_header_t *)mh); 13906 while (seg) { 13907 start = round_page(seg->vmaddr); 13908 end = trunc_page(seg->vmaddr + seg->vmsize); 13909 13910 /* 13911 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS 13912 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT 13913 * for the Aux KC as well. 13914 */ 13915 if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 || 13916 strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 || 13917 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 || 13918 (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload && 13919 strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) { 13920 ret = OSKext_protect((kernel_mach_header_t *)mh, 13921 kext_map, start, end, seg->maxprot, TRUE, type); 13922 if (ret != KERN_SUCCESS) { 13923 printf("OSKext protect failed with error %d", ret); 13924 return kOSKextReturnInvalidArgument; 13925 } 13926 13927 ret = OSKext_protect((kernel_mach_header_t *)mh, 13928 kext_map, start, end, seg->initprot, FALSE, type); 13929 if (ret != KERN_SUCCESS) { 13930 printf("OSKext protect failed with error %d", ret); 13931 return kOSKextReturnInvalidArgument; 13932 } 13933 13934 ret = OSKext_wire((kernel_mach_header_t *)mh, 13935 kext_map, start, end, seg->initprot, FALSE, type); 13936 if (ret != KERN_SUCCESS) { 13937 printf("OSKext wire failed with error %d", ret); 13938 return kOSKextReturnInvalidArgument; 13939 } 13940 } 13941 13942 seg = nextsegfromheader((kernel_mach_header_t *) mh, seg); 13943 } 13944 13945 return 0; 13946 } 13947 13948 /********************************************************************* 13949 * Assumes sKextLock is held. 13950 *********************************************************************/ 13951 /* static */ 13952 void 13953 OSKext::freeKCFileSetcontrol(void) 13954 { 13955 PE_reset_all_kc_vp(); 13956 } 13957 13958 /********************************************************************* 13959 * Assumes sKextLock is held. 13960 * 13961 * resetKCFileSetSegments: Kext start function expects data segment to 13962 * be pristine on every load, unmap the dirty segments on unload and 13963 * remap them from FileSet on disk. Remap all segments of kext since 13964 * fixups are done per kext and not per segment. 13965 *********************************************************************/ 13966 OSReturn 13967 OSKext::resetKCFileSetSegments(void) 13968 { 13969 kernel_segment_command_t *seg = NULL; 13970 kernel_segment_command_t *text_seg; 13971 uint32_t text_fileoff; 13972 kernel_mach_header_t *k_mh = NULL; 13973 uintptr_t slide; 13974 struct vnode *vp = NULL; 13975 void *fileset_control = NULL; 13976 bool pageable = (kc_type == KCKindPageable); 13977 OSReturn err; 13978 kern_return_t kr; 13979 13980 /* Check the vnode reference is still available */ 13981 vp = (struct vnode *)PE_get_kc_vp(kc_type); 13982 if (vp == NULL) { 13983 OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag, 13984 "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString()); 13985 return kOSKextReturnInternalError; 13986 } 13987 13988 fileset_control = ubc_getobject(vp, 0); 13989 assert(fileset_control != NULL); 13990 13991 OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag, 13992 "Kext %s resetting all segments", getIdentifierCString()); 13993 13994 k_mh = (kernel_mach_header_t *)kmod_info->address; 13995 text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT); 13996 text_fileoff = text_seg->fileoff; 13997 slide = PE_get_kc_slide(kc_type); 13998 13999 seg = firstsegfromheader((kernel_mach_header_t *)k_mh); 14000 while (seg) { 14001 if (seg->vmsize == 0) { 14002 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 14003 continue; 14004 } 14005 14006 /* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */ 14007 if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 || 14008 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 || 14009 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) { 14010 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 14011 continue; 14012 } 14013 14014 kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize); 14015 assert(kr == KERN_SUCCESS); 14016 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 14017 } 14018 14019 /* Unmap the text segment */ 14020 kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize); 14021 assert(kr == KERN_SUCCESS); 14022 14023 /* Map all the segments of the kext */ 14024 err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL); 14025 if (err) { 14026 panic("Could not reset segments of a mapped kext, error %x", err); 14027 } 14028 14029 /* Update address in kmod_info, since it has been reset */ 14030 if (kmod_info->address) { 14031 kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide); 14032 } 14033 14034 return 0; 14035 } 14036 14037 /********************************************************************* 14038 * Mechanism to track all segment mapping while mapping KC fileset. 14039 *********************************************************************/ 14040 14041 struct kcfileset_map_entry { 14042 vm_map_offset_t me_start; 14043 vm_map_offset_t me_size; 14044 }; 14045 14046 struct kcfileset_map_entry_list { 14047 int kme_list_count; 14048 int kme_list_index; 14049 struct kcfileset_map_entry kme_list[]; 14050 }; 14051 14052 #define KCFILESET_MAP_ENTRY_MAX (16380) 14053 14054 static void * 14055 allocate_kcfileset_map_entry_list(void) 14056 { 14057 struct kcfileset_map_entry_list *entry_list; 14058 14059 entry_list = kalloc_type(struct kcfileset_map_entry_list, 14060 struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO); 14061 14062 entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX; 14063 entry_list->kme_list_index = 0; 14064 return entry_list; 14065 } 14066 14067 static void 14068 add_kcfileset_map_entry( 14069 void *map_entry_list, 14070 vm_map_offset_t start, 14071 vm_map_offset_t size) 14072 { 14073 if (map_entry_list == NULL) { 14074 return; 14075 } 14076 14077 struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list; 14078 14079 if (entry_list->kme_list_index >= entry_list->kme_list_count) { 14080 panic("Ran out of map kc fileset list"); 14081 } 14082 14083 entry_list->kme_list[entry_list->kme_list_index].me_start = start; 14084 entry_list->kme_list[entry_list->kme_list_index].me_size = size; 14085 14086 entry_list->kme_list_index++; 14087 } 14088 14089 static void 14090 deallocate_kcfileset_map_entry_list_and_unmap_entries( 14091 void *map_entry_list, 14092 boolean_t unmap_entries, 14093 bool pageable) 14094 { 14095 struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list; 14096 14097 if (unmap_entries) { 14098 for (int i = 0; i < entry_list->kme_list_index; i++) { 14099 kern_return_t ret; 14100 ret = vm_unmap_kcfileset_segment( 14101 &(entry_list->kme_list[i].me_start), 14102 entry_list->kme_list[i].me_size); 14103 assert(ret == KERN_SUCCESS); 14104 } 14105 14106 PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary); 14107 } 14108 14109 kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry, 14110 KCFILESET_MAP_ENTRY_MAX, entry_list); 14111 } 14112 14113 /********************************************************************* 14114 * Mechanism to map kext segment. 14115 *********************************************************************/ 14116 14117 kern_return_t 14118 vm_map_kcfileset_segment( 14119 vm_map_offset_t *start, 14120 vm_map_offset_t size, 14121 void *control, 14122 vm_object_offset_t fileoffset, 14123 vm_prot_t max_prot) 14124 { 14125 vm_map_kernel_flags_t vmk_flags = { 14126 .vmf_fixed = true, 14127 .vmkf_no_copy_on_read = true, 14128 .vmkf_cs_enforcement_override = true, 14129 .vm_tag = VM_KERN_MEMORY_OSKEXT, 14130 }; 14131 kern_return_t ret; 14132 14133 /* Add Write to max prot to allow fixups */ 14134 max_prot = max_prot | VM_PROT_WRITE; 14135 14136 /* 14137 * Map the segments from file as COPY mappings to 14138 * make sure changes on disk to the file does not affect 14139 * mapped segments. 14140 */ 14141 ret = vm_map_enter_mem_object_control( 14142 g_kext_map, 14143 start, 14144 size, 14145 (mach_vm_offset_t)0, 14146 vmk_flags, 14147 (memory_object_control_t)control, 14148 fileoffset, 14149 TRUE, /* copy */ 14150 (VM_PROT_READ | VM_PROT_WRITE), max_prot, 14151 VM_INHERIT_NONE); 14152 14153 return ret; 14154 } 14155 14156 kern_return_t 14157 vm_unmap_kcfileset_segment( 14158 vm_map_offset_t *start, 14159 vm_map_offset_t size) 14160 { 14161 return mach_vm_deallocate(g_kext_map, *start, size); 14162 } 14163 14164 #endif //(__x86_64__) || defined(__i386__) 14165 14166 /********************************************************************* 14167 * Assumes sKextLock is held. 14168 *********************************************************************/ 14169 /* static */ 14170 OSReturn 14171 OSKext::validateKCFileSetUUID( 14172 OSDictionary *infoDict, 14173 kc_kind_t type) 14174 { 14175 OSReturn ret = kOSReturnSuccess; 14176 14177 if (!kernelcache_uuid_valid) { 14178 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 14179 "validateKCFileSetUUID Boot KC UUID was not set at boot."); 14180 ret = kOSKextReturnInvalidArgument; 14181 goto finish; 14182 } 14183 ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey); 14184 if (ret != 0) { 14185 goto finish; 14186 } 14187 14188 #if defined(__x86_64__) || defined(__i386__) 14189 /* Check if the Aux KC is prelinked to correct Pageable KC */ 14190 if (type == KCKindAuxiliary) { 14191 if (!pageablekc_uuid_valid) { 14192 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 14193 "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC."); 14194 ret = kOSKextReturnInvalidArgument; 14195 goto finish; 14196 } 14197 ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey); 14198 if (ret != 0) { 14199 goto finish; 14200 } 14201 } 14202 #endif //(__x86_64__) || defined(__i386__) 14203 14204 printf("KextLog: Collection UUID matches with loaded KCs.\n"); 14205 finish: 14206 return ret; 14207 } 14208 14209 /********************************************************************* 14210 * Assumes sKextLock is held. 14211 *********************************************************************/ 14212 /* static */ 14213 OSReturn 14214 OSKext::validateKCUUIDfromPrelinkInfo( 14215 uuid_t *loaded_kcuuid, 14216 kc_kind_t type, 14217 OSDictionary *infoDict, 14218 const char *uuid_key) 14219 { 14220 /* extract the UUID from the dictionary */ 14221 OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key)); 14222 if (!prelinkinfoKCUUID) { 14223 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 14224 "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key); 14225 return kOSKextReturnInvalidArgument; 14226 } 14227 14228 if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) { 14229 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 14230 "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength()); 14231 return kOSKextReturnInvalidArgument; 14232 } 14233 14234 if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), 14235 prelinkinfoKCUUID->getLength())) { 14236 OSData *info_dict_uuid; 14237 uuid_string_t info_dict_uuid_str = {}; 14238 uuid_string_t expected_uuid_str = {}; 14239 uuid_string_t given_uuid_str = {}; 14240 uuid_t given_uuid; 14241 14242 /* extract the KC UUID from the dictionary */ 14243 info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 14244 if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) { 14245 uuid_t tmp_uuid; 14246 memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid)); 14247 uuid_unparse(tmp_uuid, info_dict_uuid_str); 14248 } 14249 14250 uuid_unparse(*loaded_kcuuid, expected_uuid_str); 14251 memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid)); 14252 uuid_unparse(given_uuid, given_uuid_str); 14253 14254 printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key, 14255 given_uuid_str, expected_uuid_str, info_dict_uuid_str); 14256 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 14257 "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key, 14258 given_uuid_str, expected_uuid_str, info_dict_uuid_str); 14259 if (type == KCKindPageable && sPanicOnKCMismatch) { 14260 panic("System KC UUID %s linked against %s, but %s is loaded", 14261 info_dict_uuid_str, given_uuid_str, expected_uuid_str); 14262 } 14263 return kOSKextReturnInvalidArgument; 14264 } 14265 14266 return 0; 14267 } 14268 14269 /********************************************************************* 14270 * Assumes sKextLock is held. 14271 *********************************************************************/ 14272 /* static */ 14273 OSReturn 14274 OSKext::dispatchResource(OSDictionary * requestDict) 14275 { 14276 OSReturn result = kOSReturnError; 14277 OSSharedPtr<OSDictionary> callbackRecord; 14278 OSNumber * requestTag = NULL; // do not release 14279 OSNumber * requestResult = NULL; // do not release 14280 OSData * dataObj = NULL; // do not release 14281 uint32_t dataLength = 0; 14282 const void * dataPtr = NULL; // do not free 14283 OSValueObject<OSKextRequestResourceCallback> * callbackWrapper = nullptr; // do not release 14284 OSKextRequestResourceCallback callback = NULL; 14285 OSValueObject<void *> * contextWrapper = nullptr; // do not release 14286 void * context = NULL; // do not free 14287 OSSharedPtr<OSKext> callbackKext; 14288 14289 /* Get the args from the request. Right now we need the tag 14290 * to look up the callback record, and the result for invoking the callback. 14291 */ 14292 requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 14293 kKextRequestArgumentRequestTagKey)); 14294 requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 14295 kKextRequestArgumentResultKey)); 14296 if (!requestTag || !requestResult) { 14297 result = kOSKextReturnInvalidArgument; 14298 goto finish; 14299 } 14300 14301 /* Look for a callback record matching this request's tag. 14302 */ 14303 result = dequeueCallbackForRequestTag(requestTag, callbackRecord); 14304 if (result != kOSReturnSuccess) { 14305 goto finish; 14306 } 14307 14308 /***** 14309 * Get the context pointer of the callback record (if there is one). 14310 */ 14311 contextWrapper = OSDynamicCast(OSValueObject<void *>, _OSKextGetRequestArgument( 14312 callbackRecord.get(), kKextRequestArgumentContextKey)); 14313 context = _OSKextExtractPointer(contextWrapper); 14314 if (contextWrapper && !context) { 14315 goto finish; 14316 } 14317 14318 callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>, 14319 _OSKextGetRequestArgument(callbackRecord.get(), 14320 kKextRequestArgumentCallbackKey)); 14321 callback = _OSKextExtractCallbackPointer(callbackWrapper); 14322 if (!callback) { 14323 goto finish; 14324 } 14325 14326 /* Check for a data obj. We might not have one and that's ok, that means 14327 * we didn't find the requested resource, and we still have to tell the 14328 * caller that via the callback. 14329 */ 14330 dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict, 14331 kKextRequestArgumentValueKey)); 14332 if (dataObj) { 14333 dataPtr = dataObj->getBytesNoCopy(); 14334 dataLength = dataObj->getLength(); 14335 } 14336 14337 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 14338 if (!callbackKext) { 14339 OSKextLog(/* kext */ NULL, 14340 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 14341 "Can't invoke callback for resource request; "); 14342 goto finish; 14343 } 14344 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 14345 OSKextLog(/* kext */ NULL, 14346 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 14347 "Can't invoke kext resource callback; "); 14348 goto finish; 14349 } 14350 14351 (void)callback(requestTag->unsigned32BitValue(), 14352 (OSReturn)requestResult->unsigned32BitValue(), 14353 dataPtr, dataLength, context); 14354 14355 result = kOSReturnSuccess; 14356 14357 finish: 14358 return result; 14359 } 14360 14361 /********************************************************************* 14362 * Assumes sKextLock is held. 14363 *********************************************************************/ 14364 /* static */ 14365 OSReturn 14366 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict) 14367 { 14368 OSSharedPtr<OSDictionary> missingIDs; 14369 OSArray *bundleIDList = NULL; // do not release 14370 14371 bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 14372 requestDict, kKextRequestArgumentMissingBundleIDs)); 14373 if (!bundleIDList) { 14374 return kOSKextReturnInvalidArgument; 14375 } 14376 14377 missingIDs = OSDictionary::withCapacity(bundleIDList->getCount()); 14378 if (!missingIDs) { 14379 return kOSKextReturnNoMemory; 14380 } 14381 14382 uint32_t count, i; 14383 count = bundleIDList->getCount(); 14384 for (i = 0; i < count; i++) { 14385 OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i)); 14386 if (thisID) { 14387 missingIDs->setObject(thisID, kOSBooleanFalse); 14388 } 14389 } 14390 14391 sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain); 14392 14393 return kOSReturnSuccess; 14394 } 14395 14396 /********************************************************************* 14397 * Assumes sKextLock is held. 14398 *********************************************************************/ 14399 /* static */ 14400 OSReturn 14401 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict) 14402 { 14403 bool loadable = true; 14404 if (!kextIdentifier) { 14405 return kOSKextReturnInvalidArgument; 14406 } 14407 14408 if (requestDict) { 14409 OSBoolean *loadableArg; 14410 loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 14411 requestDict, kKextRequestArgumentBundleAvailability)); 14412 /* If we find the "Bundle Available" arg, and it's false, then 14413 * mark the bundle ID as _not_ loadable 14414 */ 14415 if (loadableArg && !loadableArg->getValue()) { 14416 loadable = false; 14417 } 14418 } 14419 14420 if (!sNonLoadableKextsByID) { 14421 sNonLoadableKextsByID = OSDictionary::withCapacity(1); 14422 } 14423 14424 sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable)); 14425 14426 OSKextLog(/* kext */ NULL, 14427 kOSKextLogBasicLevel | kOSKextLogIPCFlag, 14428 "KextLog: AuxKC bundle %s marked as %s", 14429 kextIdentifier->getCStringNoCopy(), 14430 (loadable ? "loadable" : "NOT loadable")); 14431 14432 return kOSReturnSuccess; 14433 } 14434 14435 /********************************************************************* 14436 *********************************************************************/ 14437 /* static */ 14438 void 14439 OSKext::invokeRequestCallback( 14440 OSDictionary * callbackRecord, 14441 OSReturn callbackResult) 14442 { 14443 OSString * predicate = _OSKextGetRequestPredicate(callbackRecord); 14444 OSSharedPtr<OSNumber> resultNum; 14445 14446 if (!predicate) { 14447 goto finish; 14448 } 14449 14450 resultNum = OSNumber::withNumber((long long unsigned int)callbackResult, 14451 8 * sizeof(callbackResult)); 14452 if (!resultNum) { 14453 goto finish; 14454 } 14455 14456 /* Insert the result into the callback record and dispatch it as if it 14457 * were the reply coming down from user space. 14458 */ 14459 _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey, 14460 resultNum.get()); 14461 14462 if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) { 14463 /* This removes the pending callback record. 14464 */ 14465 OSKext::dispatchResource(callbackRecord); 14466 } 14467 14468 finish: 14469 return; 14470 } 14471 14472 /********************************************************************* 14473 * Assumes sKextLock is held. 14474 *********************************************************************/ 14475 /* static */ 14476 OSReturn 14477 OSKext::cancelRequest( 14478 OSKextRequestTag requestTag, 14479 void ** contextOut) 14480 { 14481 OSReturn result = kOSKextReturnNoMemory; 14482 OSSharedPtr<OSDictionary> callbackRecord; 14483 OSValueObject<void *> * contextWrapper = nullptr; // do not release 14484 14485 IORecursiveLockLock(sKextLock); 14486 result = OSKext::dequeueCallbackForRequestTag(requestTag, 14487 callbackRecord); 14488 IORecursiveLockUnlock(sKextLock); 14489 14490 if (result == kOSReturnSuccess && contextOut) { 14491 contextWrapper = OSDynamicCast(OSValueObject<void *>, 14492 _OSKextGetRequestArgument(callbackRecord.get(), 14493 kKextRequestArgumentContextKey)); 14494 *contextOut = _OSKextExtractPointer(contextWrapper); 14495 } 14496 14497 return result; 14498 } 14499 14500 /********************************************************************* 14501 * Assumes sKextLock is held. 14502 *********************************************************************/ 14503 void 14504 OSKext::invokeOrCancelRequestCallbacks( 14505 OSReturn callbackResult, 14506 bool invokeFlag) 14507 { 14508 unsigned int count, i; 14509 14510 count = sRequestCallbackRecords->getCount(); 14511 if (!count) { 14512 goto finish; 14513 } 14514 14515 i = count - 1; 14516 do { 14517 OSDictionary * request = OSDynamicCast(OSDictionary, 14518 sRequestCallbackRecords->getObject(i)); 14519 14520 if (!request) { 14521 continue; 14522 } 14523 auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>, 14524 _OSKextGetRequestArgument(request, 14525 kKextRequestArgumentCallbackKey)); 14526 14527 if (!callbackWrapper) { 14528 sRequestCallbackRecords->removeObject(i); 14529 continue; 14530 } 14531 14532 vm_address_t callbackAddress = (vm_address_t) 14533 ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer); 14534 14535 if ((kmod_info->address <= callbackAddress) && 14536 (callbackAddress < (kmod_info->address + kmod_info->size))) { 14537 if (invokeFlag) { 14538 /* This removes the callback record. 14539 */ 14540 invokeRequestCallback(request, callbackResult); 14541 } else { 14542 sRequestCallbackRecords->removeObject(i); 14543 } 14544 } 14545 } while (i--); 14546 14547 finish: 14548 return; 14549 } 14550 14551 /********************************************************************* 14552 * Assumes sKextLock is held. 14553 *********************************************************************/ 14554 uint32_t 14555 OSKext::countRequestCallbacks(void) 14556 { 14557 uint32_t result = 0; 14558 unsigned int count, i; 14559 14560 count = sRequestCallbackRecords->getCount(); 14561 if (!count) { 14562 goto finish; 14563 } 14564 14565 i = count - 1; 14566 do { 14567 OSDictionary * request = OSDynamicCast(OSDictionary, 14568 sRequestCallbackRecords->getObject(i)); 14569 14570 if (!request) { 14571 continue; 14572 } 14573 auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>, 14574 _OSKextGetRequestArgument(request, 14575 kKextRequestArgumentCallbackKey)); 14576 14577 if (!callbackWrapper) { 14578 continue; 14579 } 14580 14581 vm_address_t callbackAddress = (vm_address_t) 14582 ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer); 14583 14584 if ((kmod_info->address <= callbackAddress) && 14585 (callbackAddress < (kmod_info->address + kmod_info->size))) { 14586 result++; 14587 } 14588 } while (i--); 14589 14590 finish: 14591 return result; 14592 } 14593 14594 /********************************************************************* 14595 *********************************************************************/ 14596 static OSReturn 14597 _OSKextCreateRequest( 14598 const char * predicate, 14599 OSSharedPtr<OSDictionary> & requestR) 14600 { 14601 OSReturn result = kOSKextReturnNoMemory; 14602 OSSharedPtr<OSDictionary> request; 14603 14604 request = OSDictionary::withCapacity(2); 14605 if (!request) { 14606 goto finish; 14607 } 14608 result = _OSDictionarySetCStringValue(request.get(), 14609 kKextRequestPredicateKey, predicate); 14610 if (result != kOSReturnSuccess) { 14611 goto finish; 14612 } 14613 result = kOSReturnSuccess; 14614 14615 finish: 14616 if (result == kOSReturnSuccess) { 14617 requestR = os::move(request); 14618 } 14619 14620 return result; 14621 } 14622 14623 /********************************************************************* 14624 *********************************************************************/ 14625 static OSString * 14626 _OSKextGetRequestPredicate(OSDictionary * requestDict) 14627 { 14628 return OSDynamicCast(OSString, 14629 requestDict->getObject(kKextRequestPredicateKey)); 14630 } 14631 14632 /********************************************************************* 14633 *********************************************************************/ 14634 static OSObject * 14635 _OSKextGetRequestArgument( 14636 OSDictionary * requestDict, 14637 const char * argName) 14638 { 14639 OSDictionary * args = OSDynamicCast(OSDictionary, 14640 requestDict->getObject(kKextRequestArgumentsKey)); 14641 if (args) { 14642 return args->getObject(argName); 14643 } 14644 return NULL; 14645 } 14646 14647 /********************************************************************* 14648 *********************************************************************/ 14649 static bool 14650 _OSKextSetRequestArgument( 14651 OSDictionary * requestDict, 14652 const char * argName, 14653 OSMetaClassBase * value) 14654 { 14655 OSDictionary * args = OSDynamicCast(OSDictionary, 14656 requestDict->getObject(kKextRequestArgumentsKey)); 14657 OSSharedPtr<OSDictionary> newArgs; 14658 if (!args) { 14659 newArgs = OSDictionary::withCapacity(2); 14660 args = newArgs.get(); 14661 if (!args) { 14662 goto finish; 14663 } 14664 requestDict->setObject(kKextRequestArgumentsKey, args); 14665 } 14666 if (args) { 14667 return args->setObject(argName, value); 14668 } 14669 finish: 14670 return false; 14671 } 14672 14673 /********************************************************************* 14674 *********************************************************************/ 14675 template <typename T> 14676 static T * 14677 _OSKextExtractPointer(OSValueObject<T *> * wrapper) 14678 { 14679 if (!wrapper) { 14680 return nullptr; 14681 } 14682 return wrapper->getRef(); 14683 } 14684 14685 /********************************************************************* 14686 *********************************************************************/ 14687 static OSKextRequestResourceCallback 14688 _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper) 14689 { 14690 if (!wrapper) { 14691 return nullptr; 14692 } 14693 return wrapper->getRef(); 14694 } 14695 14696 14697 /********************************************************************* 14698 *********************************************************************/ 14699 static OSReturn 14700 _OSDictionarySetCStringValue( 14701 OSDictionary * dict, 14702 const char * cKey, 14703 const char * cValue) 14704 { 14705 OSReturn result = kOSKextReturnNoMemory; 14706 OSSharedPtr<const OSSymbol> key; 14707 OSSharedPtr<OSString> value; 14708 14709 key = OSSymbol::withCString(cKey); 14710 value = OSString::withCString(cValue); 14711 if (!key || !value) { 14712 goto finish; 14713 } 14714 if (dict->setObject(key.get(), value.get())) { 14715 result = kOSReturnSuccess; 14716 } 14717 14718 finish: 14719 return result; 14720 } 14721 14722 /********************************************************************* 14723 *********************************************************************/ 14724 static bool 14725 _OSArrayContainsCString( 14726 OSArray * array, 14727 const char * cString) 14728 { 14729 bool result = false; 14730 OSSharedPtr<const OSSymbol> symbol; 14731 uint32_t count, i; 14732 14733 if (!array || !cString) { 14734 goto finish; 14735 } 14736 14737 symbol = OSSymbol::withCStringNoCopy(cString); 14738 if (!symbol) { 14739 goto finish; 14740 } 14741 14742 count = array->getCount(); 14743 for (i = 0; i < count; i++) { 14744 OSObject * thisObject = array->getObject(i); 14745 if (symbol->isEqualTo(thisObject)) { 14746 result = true; 14747 goto finish; 14748 } 14749 } 14750 14751 finish: 14752 return result; 14753 } 14754 14755 #if CONFIG_KXLD 14756 /********************************************************************* 14757 * We really only care about boot / system start up related kexts. 14758 * We return true if we're less than REBUILD_MAX_TIME since start up, 14759 * otherwise return false. 14760 *********************************************************************/ 14761 bool 14762 _OSKextInPrelinkRebuildWindow(void) 14763 { 14764 static bool outside_the_window = false; 14765 AbsoluteTime my_abstime; 14766 UInt64 my_ns; 14767 SInt32 my_secs; 14768 14769 if (outside_the_window) { 14770 return false; 14771 } 14772 clock_get_uptime(&my_abstime); 14773 absolutetime_to_nanoseconds(my_abstime, &my_ns); 14774 my_secs = (SInt32)(my_ns / NSEC_PER_SEC); 14775 if (my_secs > REBUILD_MAX_TIME) { 14776 outside_the_window = true; 14777 return false; 14778 } 14779 return true; 14780 } 14781 #endif /* CONFIG_KXLD */ 14782 14783 /********************************************************************* 14784 *********************************************************************/ 14785 bool 14786 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID ) 14787 { 14788 int unLoadedCount, i; 14789 bool result = false; 14790 14791 IORecursiveLockLock(sKextLock); 14792 14793 if (sUnloadedPrelinkedKexts == NULL) { 14794 goto finish; 14795 } 14796 unLoadedCount = sUnloadedPrelinkedKexts->getCount(); 14797 if (unLoadedCount == 0) { 14798 goto finish; 14799 } 14800 14801 for (i = 0; i < unLoadedCount; i++) { 14802 const OSSymbol * myBundleID; // do not release 14803 14804 myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i)); 14805 if (!myBundleID) { 14806 continue; 14807 } 14808 if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) { 14809 result = true; 14810 break; 14811 } 14812 } 14813 finish: 14814 IORecursiveLockUnlock(sKextLock); 14815 return result; 14816 } 14817 14818 #if PRAGMA_MARK 14819 #pragma mark Personalities (IOKit Drivers) 14820 #endif 14821 /********************************************************************* 14822 *********************************************************************/ 14823 /* static */ 14824 OSSharedPtr<OSArray> 14825 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag) 14826 { 14827 OSSharedPtr<OSArray> result; 14828 OSSharedPtr<OSCollectionIterator> kextIterator; 14829 OSSharedPtr<OSArray> personalities; 14830 14831 OSString * kextID = NULL; // do not release 14832 OSKext * theKext = NULL; // do not release 14833 14834 IORecursiveLockLock(sKextLock); 14835 14836 /* Let's conservatively guess that any given kext has around 3 14837 * personalities for now. 14838 */ 14839 result = OSArray::withCapacity(sKextsByID->getCount() * 3); 14840 if (!result) { 14841 goto finish; 14842 } 14843 14844 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 14845 if (!kextIterator) { 14846 goto finish; 14847 } 14848 14849 while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) { 14850 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID)); 14851 if (theKext->flags.requireExplicitLoad) { 14852 OSKextLog(theKext, 14853 kOSKextLogDebugLevel | 14854 kOSKextLogLoadFlag, 14855 "Kext %s requires an explicit kextload; " 14856 "omitting its personalities.", 14857 theKext->getIdentifierCString()); 14858 } else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) { 14859 personalities = theKext->copyPersonalitiesArray(); 14860 if (!personalities) { 14861 continue; 14862 } 14863 result->merge(personalities.get()); 14864 } else { 14865 // xxx - check for better place to put this log msg 14866 OSKextLog(theKext, 14867 kOSKextLogWarningLevel | 14868 kOSKextLogLoadFlag, 14869 "Kext %s is not loadable during safe boot; " 14870 "omitting its personalities.", 14871 theKext->getIdentifierCString()); 14872 } 14873 } 14874 14875 finish: 14876 IORecursiveLockUnlock(sKextLock); 14877 14878 return result; 14879 } 14880 14881 /********************************************************************* 14882 *********************************************************************/ 14883 /* static */ 14884 void 14885 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching) 14886 { 14887 int numPersonalities = 0; 14888 14889 OSKextLog(/* kext */ NULL, 14890 kOSKextLogStepLevel | 14891 kOSKextLogLoadFlag, 14892 "Sending all eligible registered kexts' personalities " 14893 "to the IOCatalogue %s.", 14894 startMatching ? "and starting matching" : "but not starting matching"); 14895 14896 OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities( 14897 /* filterSafeBootFlag */ true); 14898 14899 if (personalities) { 14900 gIOCatalogue->addDrivers(personalities.get(), startMatching); 14901 numPersonalities = personalities->getCount(); 14902 } 14903 14904 OSKextLog(/* kext */ NULL, 14905 kOSKextLogStepLevel | 14906 kOSKextLogLoadFlag, 14907 "%d kext personalit%s sent to the IOCatalogue; %s.", 14908 numPersonalities, numPersonalities > 0 ? "ies" : "y", 14909 startMatching ? "matching started" : "matching not started"); 14910 return; 14911 } 14912 14913 /********************************************************************* 14914 * Do not make a deep copy, just convert the IOKitPersonalities dict 14915 * to an array for sending to the IOCatalogue. 14916 *********************************************************************/ 14917 OSSharedPtr<OSArray> 14918 OSKext::copyPersonalitiesArray(void) 14919 { 14920 OSSharedPtr<OSArray> result; 14921 OSDictionary * personalities = NULL; // do not release 14922 OSSharedPtr<OSCollectionIterator> personalitiesIterator; 14923 14924 OSString * personalityName = NULL; // do not release 14925 OSString * personalityBundleIdentifier = NULL; // do not release 14926 14927 personalities = OSDynamicCast(OSDictionary, 14928 getPropertyForHostArch(kIOKitPersonalitiesKey)); 14929 if (!personalities) { 14930 goto finish; 14931 } 14932 14933 result = OSArray::withCapacity(personalities->getCount()); 14934 if (!result) { 14935 goto finish; 14936 } 14937 14938 personalitiesIterator = 14939 OSCollectionIterator::withCollection(personalities); 14940 if (!personalitiesIterator) { 14941 goto finish; 14942 } 14943 while ((personalityName = OSDynamicCast(OSString, 14944 personalitiesIterator->getNextObject()))) { 14945 OSDictionary * personality = OSDynamicCast(OSDictionary, 14946 personalities->getObject(personalityName)); 14947 14948 if (personality) { 14949 /****** 14950 * If the personality doesn't have a CFBundleIdentifier, or if it 14951 * differs from the kext's, insert the kext's ID so we can find it. 14952 * The publisher ID is used to remove personalities from bundles 14953 * correctly. 14954 */ 14955 personalityBundleIdentifier = OSDynamicCast(OSString, 14956 personality->getObject(kCFBundleIdentifierKey)); 14957 14958 if (!personalityBundleIdentifier) { 14959 personality->setObject(kCFBundleIdentifierKey, bundleID.get()); 14960 } else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) { 14961 personality->setObject(kIOPersonalityPublisherKey, bundleID.get()); 14962 } 14963 } 14964 14965 result->setObject(personality); 14966 } 14967 14968 finish: 14969 return result; 14970 } 14971 14972 /********************************************************************* 14973 * Might want to change this to a bool return? 14974 *********************************************************************/ 14975 OSReturn 14976 OSKext::sendPersonalitiesToCatalog( 14977 bool startMatching, 14978 OSArray * personalityNames) 14979 { 14980 OSReturn result = kOSReturnSuccess; 14981 OSSharedPtr<OSArray> personalitiesToSend; 14982 OSDictionary * kextPersonalities = NULL; // do not release 14983 int count, i; 14984 14985 if (!sLoadEnabled) { 14986 OSKextLog(this, 14987 kOSKextLogErrorLevel | 14988 kOSKextLogLoadFlag, 14989 "Kext loading is disabled (attempt to start matching for kext %s).", 14990 getIdentifierCString()); 14991 result = kOSKextReturnDisabled; 14992 goto finish; 14993 } 14994 14995 if (sSafeBoot && !isLoadableInSafeBoot()) { 14996 OSKextLog(this, 14997 kOSKextLogErrorLevel | 14998 kOSKextLogLoadFlag, 14999 "Kext %s is not loadable during safe boot; " 15000 "not sending personalities to the IOCatalogue.", 15001 getIdentifierCString()); 15002 result = kOSKextReturnNotLoadable; 15003 goto finish; 15004 } 15005 15006 if (!personalityNames || !personalityNames->getCount()) { 15007 personalitiesToSend = copyPersonalitiesArray(); 15008 } else { 15009 kextPersonalities = OSDynamicCast(OSDictionary, 15010 getPropertyForHostArch(kIOKitPersonalitiesKey)); 15011 if (!kextPersonalities || !kextPersonalities->getCount()) { 15012 // not an error 15013 goto finish; 15014 } 15015 personalitiesToSend = OSArray::withCapacity(0); 15016 if (!personalitiesToSend) { 15017 result = kOSKextReturnNoMemory; 15018 goto finish; 15019 } 15020 count = personalityNames->getCount(); 15021 for (i = 0; i < count; i++) { 15022 OSString * name = OSDynamicCast(OSString, 15023 personalityNames->getObject(i)); 15024 if (!name) { 15025 continue; 15026 } 15027 OSDictionary * personality = OSDynamicCast(OSDictionary, 15028 kextPersonalities->getObject(name)); 15029 if (personality) { 15030 personalitiesToSend->setObject(personality); 15031 } 15032 } 15033 } 15034 if (personalitiesToSend) { 15035 unsigned numPersonalities = personalitiesToSend->getCount(); 15036 OSKextLog(this, 15037 kOSKextLogStepLevel | 15038 kOSKextLogLoadFlag, 15039 "Kext %s sending %d personalit%s to the IOCatalogue%s.", 15040 getIdentifierCString(), 15041 numPersonalities, 15042 numPersonalities > 1 ? "ies" : "y", 15043 startMatching ? " and starting matching" : " but not starting matching"); 15044 gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching); 15045 } 15046 finish: 15047 return result; 15048 } 15049 15050 /********************************************************************* 15051 * xxx - We should allow removing the kext's declared personalities, 15052 * xxx - even with other bundle identifiers. 15053 *********************************************************************/ 15054 void 15055 OSKext::removePersonalitiesFromCatalog(void) 15056 { 15057 OSSharedPtr<OSDictionary> personality; 15058 15059 personality = OSDictionary::withCapacity(1); 15060 if (!personality) { 15061 goto finish; 15062 } 15063 personality->setObject(kCFBundleIdentifierKey, getIdentifier()); 15064 15065 OSKextLog(this, 15066 kOSKextLogStepLevel | 15067 kOSKextLogLoadFlag, 15068 "Kext %s removing all personalities naming it from the IOCatalogue.", 15069 getIdentifierCString()); 15070 15071 /* Have the IOCatalog remove all personalities matching this kext's 15072 * bundle ID and trigger matching anew. 15073 */ 15074 gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true); 15075 15076 finish: 15077 return; 15078 } 15079 15080 void 15081 OSKext::updatePersonalitiesInCatalog(OSArray *upgradedPersonalities) 15082 { 15083 if (!upgradedPersonalities || upgradedPersonalities->getCount() == 0) { 15084 return; 15085 } 15086 15087 OSSharedPtr<OSDictionary> personalityToRemove = OSDictionary::withCapacity(1); 15088 if (!personalityToRemove) { 15089 return; 15090 } 15091 15092 /* 15093 * Create a personality dictionary with just the bundleID. 15094 * We will remove any personality that has a matching bundleID, 15095 * irrespective of which other keys are present on the dictionary. 15096 */ 15097 personalityToRemove->setObject(kCFBundleIdentifierKey, getIdentifier()); 15098 gIOCatalogue->exchangeDrivers(personalityToRemove.get(), upgradedPersonalities, true); 15099 } 15100 15101 #if PRAGMA_MARK 15102 #pragma mark Logging 15103 #endif 15104 /********************************************************************* 15105 * Do not call any function that takes sKextLock here! 15106 *********************************************************************/ 15107 /* static */ 15108 OSKextLogSpec 15109 OSKext::setUserSpaceLogFilter( 15110 OSKextLogSpec newUserLogFilter, 15111 bool captureFlag) 15112 { 15113 OSKextLogSpec result; 15114 bool allocError = false; 15115 15116 /* Do not call any function that takes sKextLoggingLock during 15117 * this critical block. That means do logging after. 15118 */ 15119 IOLockLock(sKextLoggingLock); 15120 15121 result = sUserSpaceKextLogFilter; 15122 sUserSpaceKextLogFilter = newUserLogFilter; 15123 15124 if (newUserLogFilter && captureFlag && 15125 !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) { 15126 // xxx - do some measurements for a good initial capacity? 15127 sUserSpaceLogSpecArray = OSArray::withCapacity(0); 15128 sUserSpaceLogMessageArray = OSArray::withCapacity(0); 15129 15130 if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) { 15131 allocError = true; 15132 } 15133 } 15134 15135 IOLockUnlock(sKextLoggingLock); 15136 15137 /* If the config flag itself is changing, log the state change 15138 * going both ways, before setting up the user-space log arrays, 15139 * so that this is only logged in the kernel. 15140 */ 15141 if (result != newUserLogFilter) { 15142 OSKextLog(/* kext */ NULL, 15143 kOSKextLogDebugLevel | 15144 kOSKextLogGeneralFlag, 15145 "User-space log flags changed from 0x%x to 0x%x.", 15146 result, newUserLogFilter); 15147 } 15148 if (allocError) { 15149 OSKextLog(/* kext */ NULL, 15150 kOSKextLogErrorLevel | 15151 kOSKextLogGeneralFlag, 15152 "Failed to allocate user-space log message arrays."); 15153 } 15154 15155 return result; 15156 } 15157 15158 /********************************************************************* 15159 * Do not call any function that takes sKextLock here! 15160 *********************************************************************/ 15161 /* static */ 15162 OSSharedPtr<OSArray> 15163 OSKext::clearUserSpaceLogFilter(void) 15164 { 15165 OSSharedPtr<OSArray> result; 15166 OSKextLogSpec oldLogFilter; 15167 OSKextLogSpec newLogFilter = kOSKextLogSilentFilter; 15168 15169 /* Do not call any function that takes sKextLoggingLock during 15170 * this critical block. That means do logging after. 15171 */ 15172 IOLockLock(sKextLoggingLock); 15173 15174 result = OSArray::withCapacity(2); 15175 if (result) { 15176 result->setObject(sUserSpaceLogSpecArray.get()); 15177 result->setObject(sUserSpaceLogMessageArray.get()); 15178 } 15179 sUserSpaceLogSpecArray.reset(); 15180 sUserSpaceLogMessageArray.reset(); 15181 15182 oldLogFilter = sUserSpaceKextLogFilter; 15183 sUserSpaceKextLogFilter = newLogFilter; 15184 15185 IOLockUnlock(sKextLoggingLock); 15186 15187 /* If the config flag itself is changing, log the state change 15188 * going both ways, after tearing down the user-space log 15189 * arrays, so this is only logged within the kernel. 15190 */ 15191 if (oldLogFilter != newLogFilter) { 15192 OSKextLog(/* kext */ NULL, 15193 kOSKextLogDebugLevel | 15194 kOSKextLogGeneralFlag, 15195 "User-space log flags changed from 0x%x to 0x%x.", 15196 oldLogFilter, newLogFilter); 15197 } 15198 15199 return result; 15200 } 15201 15202 15203 /********************************************************************* 15204 * Do not call any function that takes sKextLock here! 15205 *********************************************************************/ 15206 /* static */ 15207 OSKextLogSpec 15208 OSKext::getUserSpaceLogFilter(void) 15209 { 15210 OSKextLogSpec result; 15211 15212 IOLockLock(sKextLoggingLock); 15213 result = sUserSpaceKextLogFilter; 15214 IOLockUnlock(sKextLoggingLock); 15215 15216 return result; 15217 } 15218 15219 /********************************************************************* 15220 * This function is called by OSMetaClass during kernel C++ setup. 15221 * Be careful what you access here; assume only OSKext::initialize() 15222 * has been called. 15223 * 15224 * Do not call any function that takes sKextLock here! 15225 *********************************************************************/ 15226 #define VTRESET "\033[0m" 15227 15228 #define VTBOLD "\033[1m" 15229 #define VTUNDER "\033[4m" 15230 15231 #define VTRED "\033[31m" 15232 #define VTGREEN "\033[32m" 15233 #define VTYELLOW "\033[33m" 15234 #define VTBLUE "\033[34m" 15235 #define VTMAGENTA "\033[35m" 15236 #define VTCYAN "\033[36m" 15237 15238 inline const char * 15239 colorForFlags(OSKextLogSpec flags) 15240 { 15241 OSKextLogSpec logLevel = flags & kOSKextLogLevelMask; 15242 15243 switch (logLevel) { 15244 case kOSKextLogErrorLevel: 15245 return VTRED VTBOLD; 15246 case kOSKextLogWarningLevel: 15247 return VTRED; 15248 case kOSKextLogBasicLevel: 15249 return VTYELLOW VTUNDER; 15250 case kOSKextLogProgressLevel: 15251 return VTYELLOW; 15252 case kOSKextLogStepLevel: 15253 return VTGREEN; 15254 case kOSKextLogDetailLevel: 15255 return VTCYAN; 15256 case kOSKextLogDebugLevel: 15257 return VTMAGENTA; 15258 default: 15259 return ""; // white 15260 } 15261 } 15262 15263 inline bool 15264 logSpecMatch( 15265 OSKextLogSpec msgLogSpec, 15266 OSKextLogSpec logFilter) 15267 { 15268 OSKextLogSpec filterKextGlobal = logFilter & kOSKextLogKextOrGlobalMask; 15269 OSKextLogSpec filterLevel = logFilter & kOSKextLogLevelMask; 15270 OSKextLogSpec filterFlags = logFilter & kOSKextLogFlagsMask; 15271 15272 OSKextLogSpec msgKextGlobal = msgLogSpec & kOSKextLogKextOrGlobalMask; 15273 OSKextLogSpec msgLevel = msgLogSpec & kOSKextLogLevelMask; 15274 OSKextLogSpec msgFlags = msgLogSpec & kOSKextLogFlagsMask; 15275 15276 /* Explicit messages always get logged. 15277 */ 15278 if (msgLevel == kOSKextLogExplicitLevel) { 15279 return true; 15280 } 15281 15282 /* Warnings and errors are logged regardless of the flags. 15283 */ 15284 if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) { 15285 return true; 15286 } 15287 15288 /* A verbose message that isn't for a logging-enabled kext and isn't global 15289 * does *not* get logged. 15290 */ 15291 if (!msgKextGlobal && !filterKextGlobal) { 15292 return false; 15293 } 15294 15295 /* Warnings and errors are logged regardless of the flags. 15296 * All other messages must fit the flags and 15297 * have a level at or below the filter. 15298 * 15299 */ 15300 if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) { 15301 return true; 15302 } 15303 return false; 15304 } 15305 15306 extern "C" { 15307 void 15308 OSKextLog( 15309 OSKext * aKext, 15310 OSKextLogSpec msgLogSpec, 15311 const char * format, ...) 15312 { 15313 va_list argList; 15314 15315 va_start(argList, format); 15316 OSKextVLog(aKext, msgLogSpec, format, argList); 15317 va_end(argList); 15318 } 15319 15320 void 15321 OSKextVLog( 15322 OSKext * aKext, 15323 OSKextLogSpec msgLogSpec, 15324 const char * format, 15325 va_list srcArgList) 15326 { 15327 bool logForKernel = false; 15328 bool logForUser = false; 15329 va_list argList; 15330 char stackBuffer[120]; 15331 uint32_t length = 0; 15332 char * allocBuffer = NULL; // must kfree 15333 OSSharedPtr<OSNumber> logSpecNum; 15334 OSSharedPtr<OSString> logString; 15335 char * buffer = stackBuffer; // do not free 15336 15337 IOLockLock(sKextLoggingLock); 15338 15339 /* Set the kext/global bit in the message spec if we have no 15340 * kext or if the kext requests logging. 15341 */ 15342 if (!aKext || aKext->flags.loggingEnabled) { 15343 msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask; 15344 } 15345 15346 logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter); 15347 if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 15348 logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter); 15349 } 15350 15351 if (!(logForKernel || logForUser)) { 15352 goto finish; 15353 } 15354 15355 /* No goto from here until past va_end()! 15356 */ 15357 va_copy(argList, srcArgList); 15358 length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList); 15359 va_end(argList); 15360 15361 if (length + 1 >= sizeof(stackBuffer)) { 15362 allocBuffer = (char *)kalloc_data_tag(length + 1, 15363 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 15364 if (!allocBuffer) { 15365 goto finish; 15366 } 15367 15368 /* No goto from here until past va_end()! 15369 */ 15370 va_copy(argList, srcArgList); 15371 vsnprintf(allocBuffer, length + 1, format, argList); 15372 va_end(argList); 15373 15374 buffer = allocBuffer; 15375 } 15376 15377 /* If user space wants the log message, queue it up. 15378 */ 15379 if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 15380 logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec)); 15381 logString = OSString::withCString(buffer); 15382 if (logSpecNum && logString) { 15383 sUserSpaceLogSpecArray->setObject(logSpecNum.get()); 15384 sUserSpaceLogMessageArray->setObject(logString.get()); 15385 } 15386 } 15387 15388 /* Always log messages from the kernel according to the kernel's 15389 * log flags. 15390 */ 15391 if (logForKernel) { 15392 /* If we are in console mode and have a custom log filter, 15393 * colorize the log message. 15394 */ 15395 if (sBootArgLogFilterFound) { 15396 const char * color = ""; // do not free 15397 color = colorForFlags(msgLogSpec); 15398 printf("%s%s%s\n", colorForFlags(msgLogSpec), 15399 buffer, color[0] ? VTRESET : ""); 15400 } else { 15401 printf("%s\n", buffer); 15402 } 15403 } 15404 15405 finish: 15406 IOLockUnlock(sKextLoggingLock); 15407 15408 if (allocBuffer) { 15409 kfree_data(allocBuffer, length + 1); 15410 } 15411 return; 15412 } 15413 15414 #if KASLR_IOREG_DEBUG 15415 15416 #define IOLOG_INDENT( the_indention ) \ 15417 { \ 15418 int i; \ 15419 for ( i = 0; i < (the_indention); i++ ) { \ 15420 IOLog(" "); \ 15421 } \ 15422 } 15423 15424 extern vm_offset_t vm_kernel_stext; 15425 extern vm_offset_t vm_kernel_etext; 15426 extern mach_vm_offset_t kext_alloc_base; 15427 extern mach_vm_offset_t kext_alloc_max; 15428 15429 bool ScanForAddrInObject(OSObject * theObject, 15430 int indent ); 15431 15432 bool 15433 ScanForAddrInObject(OSObject * theObject, 15434 int indent) 15435 { 15436 const OSMetaClass * myTypeID; 15437 OSSharedPtr<OSCollectionIterator> myIter; 15438 OSSymbol * myKey; 15439 OSObject * myValue; 15440 bool myResult = false; 15441 15442 if (theObject == NULL) { 15443 IOLog("%s: theObject is NULL \n", 15444 __FUNCTION__); 15445 return myResult; 15446 } 15447 15448 myTypeID = OSTypeIDInst(theObject); 15449 15450 if (myTypeID == OSTypeID(OSDictionary)) { 15451 OSDictionary * myDictionary; 15452 15453 myDictionary = OSDynamicCast(OSDictionary, theObject); 15454 myIter = OSCollectionIterator::withCollection( myDictionary ); 15455 if (myIter == NULL) { 15456 return myResult; 15457 } 15458 15459 // !! reset the iterator 15460 myIter->reset(); 15461 15462 while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) { 15463 bool myTempResult; 15464 15465 myValue = myDictionary->getObject(myKey); 15466 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 15467 if (myTempResult) { 15468 // if we ever get a true result return true 15469 myResult = true; 15470 IOLOG_INDENT(indent); 15471 IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy()); 15472 } 15473 } 15474 15475 // !! release the iterator 15476 myIter.reset(); 15477 } else if (myTypeID == OSTypeID(OSArray)) { 15478 OSArray * myArray; 15479 15480 myArray = OSDynamicCast(OSArray, theObject); 15481 myIter = OSCollectionIterator::withCollection(myArray); 15482 if (myIter == NULL) { 15483 return myResult; 15484 } 15485 // !! reset the iterator 15486 myIter->reset(); 15487 15488 while ((myValue = myIter->getNextObject())) { 15489 bool myTempResult; 15490 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 15491 if (myTempResult) { 15492 // if we ever get a true result return true 15493 myResult = true; 15494 IOLOG_INDENT(indent); 15495 IOLog("OSArray: \n"); 15496 } 15497 } 15498 // !! release the iterator 15499 myIter.reset(); 15500 } else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) { 15501 // should we look for addresses in strings? 15502 } else if (myTypeID == OSTypeID(OSData)) { 15503 void * * myPtrPtr; 15504 unsigned int myLen; 15505 OSData * myDataObj; 15506 15507 myDataObj = OSDynamicCast(OSData, theObject); 15508 myPtrPtr = (void * *) myDataObj->getBytesNoCopy(); 15509 myLen = myDataObj->getLength(); 15510 15511 if (myPtrPtr && myLen && myLen > 7) { 15512 int i; 15513 int myPtrCount = (myLen / sizeof(void *)); 15514 15515 for (i = 0; i < myPtrCount; i++) { 15516 UInt64 numberValue = (UInt64) * (myPtrPtr); 15517 15518 if (kext_alloc_max != 0 && 15519 numberValue >= kext_alloc_base && 15520 numberValue < kext_alloc_max) { 15521 OSSharedPtr<OSKext> myKext; 15522 // IOLog("found OSData %p in kext map %p to %p \n", 15523 // *(myPtrPtr), 15524 // (void *) kext_alloc_base, 15525 // (void *) kext_alloc_max); 15526 15527 myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr)); 15528 if (myKext) { 15529 IOLog("found addr %p from an OSData obj within kext \"%s\" \n", 15530 *(myPtrPtr), 15531 myKext->getIdentifierCString()); 15532 } 15533 myResult = true; 15534 } 15535 if (vm_kernel_etext != 0 && 15536 numberValue >= vm_kernel_stext && 15537 numberValue < vm_kernel_etext) { 15538 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n", 15539 *(myPtrPtr), 15540 (void *) vm_kernel_stext, 15541 (void *) vm_kernel_etext); 15542 myResult = true; 15543 } 15544 myPtrPtr++; 15545 } 15546 } 15547 } else if (myTypeID == OSTypeID(OSBoolean)) { 15548 // do nothing here... 15549 } else if (myTypeID == OSTypeID(OSNumber)) { 15550 OSNumber * number = OSDynamicCast(OSNumber, theObject); 15551 15552 UInt64 numberValue = number->unsigned64BitValue(); 15553 15554 if (kext_alloc_max != 0 && 15555 numberValue >= kext_alloc_base && 15556 numberValue < kext_alloc_max) { 15557 OSSharedPtr<OSKext> myKext; 15558 IOLog("found OSNumber in kext map %p to %p \n", 15559 (void *) kext_alloc_base, 15560 (void *) kext_alloc_max); 15561 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 15562 15563 myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue ); 15564 if (myKext) { 15565 IOLog("found in kext \"%s\" \n", 15566 myKext->getIdentifierCString()); 15567 } 15568 15569 myResult = true; 15570 } 15571 if (vm_kernel_etext != 0 && 15572 numberValue >= vm_kernel_stext && 15573 numberValue < vm_kernel_etext) { 15574 IOLog("found OSNumber in kernel text segment %p to %p \n", 15575 (void *) vm_kernel_stext, 15576 (void *) vm_kernel_etext); 15577 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 15578 myResult = true; 15579 } 15580 } 15581 #if 0 15582 else { 15583 const OSMetaClass* myMetaClass = NULL; 15584 15585 myMetaClass = theObject->getMetaClass(); 15586 if (myMetaClass) { 15587 IOLog("class %s \n", myMetaClass->getClassName()); 15588 } else { 15589 IOLog("Unknown object \n" ); 15590 } 15591 } 15592 #endif 15593 15594 return myResult; 15595 } 15596 #endif // KASLR_KEXT_DEBUG 15597 }; /* extern "C" */ 15598 15599 #if PRAGMA_MARK 15600 #pragma mark Backtrace Dump & kmod_get_info() support 15601 #endif 15602 /********************************************************************* 15603 * This function must be safe to call in panic context. 15604 *********************************************************************/ 15605 /* static */ 15606 void 15607 OSKext::printKextsInBacktrace( 15608 vm_offset_t * addr __unused, 15609 unsigned int cnt __unused, 15610 int (* printf_func)(const char *fmt, ...) __unused, 15611 uint32_t flags __unused) 15612 { 15613 addr64_t summary_page = 0; 15614 addr64_t last_summary_page = 0; 15615 15616 if (kPrintKextsLock & flags) { 15617 if (!sKextSummariesLock) { 15618 return; 15619 } 15620 IOLockLock(sKextSummariesLock); 15621 } 15622 15623 if (!gLoadedKextSummaries) { 15624 (*printf_func)(" can't perform kext scan: no kext summary"); 15625 goto finish; 15626 } 15627 15628 summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries); 15629 last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize); 15630 for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) { 15631 if (pmap_find_phys(kernel_pmap, summary_page) == 0) { 15632 (*printf_func)(" can't perform kext scan: " 15633 "missing kext summary page %p", summary_page); 15634 goto finish; 15635 } 15636 } 15637 15638 foreachKextInBacktrace(addr, cnt, 0, ^(OSKextLoadedKextSummary *summary, uint32_t index) { 15639 if (index == 0 && !(kPrintKextsTerse & flags)) { 15640 (*printf_func)(" Kernel Extensions in backtrace:\n"); 15641 } 15642 15643 printSummary(summary, printf_func, flags); 15644 }); 15645 15646 finish: 15647 if (kPrintKextsLock & flags) { 15648 IOLockUnlock(sKextSummariesLock); 15649 } 15650 15651 return; 15652 } 15653 15654 void 15655 OSKext::foreachKextInBacktrace( 15656 vm_offset_t * addr, 15657 uint32_t cnt, 15658 uint32_t flags, 15659 void (^ handler)(OSKextLoadedKextSummary *summary, uint32_t index)) 15660 { 15661 uint32_t n = 0; 15662 15663 if (kPrintKextsLock & flags) { 15664 if (!sKextSummariesLock) { 15665 return; 15666 } 15667 IOLockLock(sKextSummariesLock); 15668 } 15669 15670 for (uint32_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 15671 OSKextLoadedKextSummary * summary; 15672 15673 summary = gLoadedKextSummaries->summaries + i; 15674 if (!summary->address) { 15675 continue; 15676 } 15677 15678 if (!summaryIsInBacktrace(summary, addr, cnt)) { 15679 continue; 15680 } 15681 15682 handler(summary, n++); 15683 } 15684 15685 if (kPrintKextsLock & flags) { 15686 IOLockUnlock(sKextSummariesLock); 15687 } 15688 } 15689 15690 /********************************************************************* 15691 * This function must be safe to call in panic context. 15692 *********************************************************************/ 15693 /* static */ 15694 boolean_t 15695 OSKext::summaryIsInBacktrace( 15696 OSKextLoadedKextSummary * summary, 15697 vm_offset_t * addr, 15698 unsigned int cnt) 15699 { 15700 u_int i = 0; 15701 15702 for (i = 0; i < cnt; i++) { 15703 vm_offset_t kscan_addr = addr[i]; 15704 #if __has_feature(ptrauth_calls) 15705 kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr); 15706 #endif /* __has_feature(ptrauth_calls) */ 15707 if ((kscan_addr >= summary->text_exec_address) && 15708 (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) { 15709 return TRUE; 15710 } 15711 } 15712 15713 return FALSE; 15714 } 15715 15716 /* 15717 * Get the kext summary object for the kext where 'addr' lies. Must be called with 15718 * sKextSummariesLock held. 15719 */ 15720 OSKextLoadedKextSummary * 15721 OSKext::summaryForAddress(uintptr_t addr) 15722 { 15723 #if __has_feature(ptrauth_calls) 15724 addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr); 15725 #endif /* __has_feature(ptrauth_calls) */ 15726 for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 15727 OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i]; 15728 if (!summary->address) { 15729 continue; 15730 } 15731 15732 #if VM_MAPPED_KEXTS 15733 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not 15734 * support split kexts, but we also may unmap the kexts, which can 15735 * race with the above codepath (see OSKext::unload). As such, 15736 * use a simple range lookup if we are using VM_MAPPED_KEXTS. 15737 */ 15738 if ((addr >= summary->address) && (addr < (summary->address + summary->size))) { 15739 return summary; 15740 } 15741 #else 15742 kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address; 15743 kernel_segment_command_t *seg; 15744 15745 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 15746 if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) { 15747 return summary; 15748 } 15749 } 15750 #endif 15751 } 15752 15753 /* addr did not map to any kext */ 15754 return NULL; 15755 } 15756 15757 /* static */ 15758 void * 15759 OSKext::kextForAddress(const void *address) 15760 { 15761 OSKextActiveAccount * active; 15762 OSKext * kext = NULL; 15763 uint32_t baseIdx; 15764 uint32_t lim; 15765 uintptr_t addr = (uintptr_t) address; 15766 size_t i; 15767 15768 if (!addr) { 15769 return NULL; 15770 } 15771 #if __has_feature(ptrauth_calls) 15772 addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr); 15773 #endif /* __has_feature(ptrauth_calls) */ 15774 15775 if (sKextAccountsCount) { 15776 lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp); 15777 // bsearch sKextAccounts list 15778 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 15779 active = &sKextAccounts[baseIdx + (lim >> 1)]; 15780 if ((addr >= active->address) && (addr < active->address_end)) { 15781 kext = active->account->kext; 15782 if (kext && kext->kmod_info) { 15783 lck_ticket_unlock(sKextAccountsLock); 15784 return (void *)kext->kmod_info->address; 15785 } 15786 break; 15787 } else if (addr > active->address) { 15788 // move right 15789 baseIdx += (lim >> 1) + 1; 15790 lim--; 15791 } 15792 // else move left 15793 } 15794 lck_ticket_unlock(sKextAccountsLock); 15795 } 15796 if (kernel_text_contains(addr)) { 15797 return (void *)&_mh_execute_header; 15798 } 15799 if (gLoadedKextSummaries) { 15800 IOLockLock(sKextSummariesLock); 15801 for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) { 15802 OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i; 15803 if (addr >= summary->address && addr < summary->address + summary->size) { 15804 void *kextAddress = (void *)summary->address; 15805 IOLockUnlock(sKextSummariesLock); 15806 return kextAddress; 15807 } 15808 } 15809 IOLockUnlock(sKextSummariesLock); 15810 } 15811 15812 return NULL; 15813 } 15814 15815 /* static */ 15816 kern_return_t 15817 OSKext::summaryForAddressExt( 15818 const void * address, 15819 OSKextLoadedKextSummary * summary) 15820 { 15821 kern_return_t result = KERN_FAILURE; 15822 const OSKextLoadedKextSummary * foundSummary = NULL; 15823 15824 /* 15825 * This needs to be safe to call even before the lock has been initialized 15826 * in OSKext::initialize(), as we might get here from the ksancov runtime 15827 * when instrumenting XNU itself with sanitizer coverage. 15828 */ 15829 if (!sKextSummariesLock) { 15830 return result; 15831 } 15832 15833 IOLockLock(sKextSummariesLock); 15834 if (gLoadedKextSummaries) { 15835 foundSummary = summaryForAddress((uintptr_t)address); 15836 if (foundSummary) { 15837 memcpy(summary, foundSummary, sizeof(*summary)); 15838 result = KERN_SUCCESS; 15839 } else { 15840 result = KERN_NOT_FOUND; 15841 } 15842 } 15843 IOLockUnlock(sKextSummariesLock); 15844 15845 return result; 15846 } 15847 15848 /* 15849 * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t * 15850 * Safe to call in panic context. 15851 */ 15852 static OSKextLoadedKextSummary * 15853 findSummary(uint32_t tagID) 15854 { 15855 OSKextLoadedKextSummary * summary; 15856 for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 15857 summary = gLoadedKextSummaries->summaries + i; 15858 if (summary->loadTag == tagID) { 15859 return summary; 15860 } 15861 } 15862 return NULL; 15863 } 15864 15865 /********************************************************************* 15866 * This function must be safe to call in panic context. 15867 *********************************************************************/ 15868 void 15869 OSKext::printSummary( 15870 OSKextLoadedKextSummary * summary, 15871 int (* printf_func)(const char *fmt, ...), 15872 uint32_t flags) 15873 { 15874 kmod_reference_t * kmod_ref = NULL; 15875 uuid_string_t uuid; 15876 char version[kOSKextVersionMaxLength]; 15877 uint64_t tmpAddr; 15878 uint64_t tmpSize; 15879 OSKextLoadedKextSummary *dependencySummary; 15880 15881 if (!OSKextVersionGetString(summary->version, version, sizeof(version))) { 15882 strlcpy(version, "unknown version", sizeof(version)); 15883 } 15884 (void) uuid_unparse(summary->uuid, uuid); 15885 15886 #if defined(__arm__) || defined(__arm64__) 15887 tmpAddr = summary->text_exec_address; 15888 tmpSize = summary->text_exec_size; 15889 #else 15890 tmpAddr = summary->address; 15891 tmpSize = summary->size; 15892 #endif 15893 if (kPrintKextsUnslide & flags) { 15894 tmpAddr = ml_static_unslide(tmpAddr); 15895 } 15896 (*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n", 15897 (kPrintKextsTerse & flags) ? "" : " ", 15898 summary->name, version, uuid, 15899 tmpAddr, tmpAddr + tmpSize - 1); 15900 15901 if (kPrintKextsTerse & flags) { 15902 return; 15903 } 15904 15905 /* print dependency info */ 15906 for (kmod_ref = (kmod_reference_t *) summary->reference_list; 15907 kmod_ref; 15908 kmod_ref = kmod_ref->next) { 15909 kmod_info_t * rinfo; 15910 15911 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) { 15912 (*printf_func)(" kmod dependency scan stopped " 15913 "due to missing dependency page: %p\n", 15914 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref); 15915 break; 15916 } 15917 rinfo = kmod_ref->info; 15918 15919 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) { 15920 (*printf_func)(" kmod dependency scan stopped " 15921 "due to missing kmod page: %p\n", 15922 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo); 15923 break; 15924 } 15925 15926 if (!rinfo->address) { 15927 continue; // skip fake entries for built-ins 15928 } 15929 15930 dependencySummary = findSummary(rinfo->id); 15931 uuid[0] = 0x00; 15932 tmpAddr = rinfo->address; 15933 tmpSize = rinfo->size; 15934 if (dependencySummary) { 15935 (void) uuid_unparse(dependencySummary->uuid, uuid); 15936 #if defined(__arm__) || defined(__arm64__) 15937 tmpAddr = dependencySummary->text_exec_address; 15938 tmpSize = dependencySummary->text_exec_size; 15939 #endif 15940 } 15941 15942 if (kPrintKextsUnslide & flags) { 15943 tmpAddr = ml_static_unslide(tmpAddr); 15944 } 15945 (*printf_func)(" dependency: %s(%s)[%s]@%p->%p\n", 15946 rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1); 15947 } 15948 return; 15949 } 15950 15951 15952 #if !defined(__arm__) && !defined(__arm64__) 15953 /******************************************************************************* 15954 * substitute() looks at an input string (a pointer within a larger buffer) 15955 * for a match to a substring, and on match it writes the marker & substitution 15956 * character to an output string, updating the scan (from) and 15957 * output (to) indexes as appropriate. 15958 *******************************************************************************/ 15959 static int substitute( 15960 const char * scan_string, 15961 char * string_out, 15962 uint32_t * to_index, 15963 uint32_t * from_index, 15964 const char * substring, 15965 char marker, 15966 char substitution); 15967 15968 /* string_out must be at least KMOD_MAX_NAME bytes. 15969 */ 15970 static int 15971 substitute( 15972 const char * scan_string, 15973 char * string_out, 15974 uint32_t * to_index, 15975 uint32_t * from_index, 15976 const char * substring, 15977 char marker, 15978 char substitution) 15979 { 15980 size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1); 15981 15982 /* On a substring match, append the marker (if there is one) and then 15983 * the substitution character, updating the output (to) index accordingly. 15984 * Then update the input (from) length by the length of the substring 15985 * that got replaced. 15986 */ 15987 if (!strncmp(scan_string, substring, substring_length)) { 15988 if (marker) { 15989 string_out[(*to_index)++] = marker; 15990 } 15991 string_out[(*to_index)++] = substitution; 15992 (*from_index) += substring_length; 15993 return 1; 15994 } 15995 return 0; 15996 } 15997 15998 /******************************************************************************* 15999 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least 16000 * KMOD_MAX_NAME characters and performs various substitutions of common 16001 * prefixes & substrings as defined by tables in kext_panic_report.h. 16002 *******************************************************************************/ 16003 static void compactIdentifier( 16004 const char * identifier, 16005 char * identifier_out, 16006 char ** identifier_out_end); 16007 16008 static void 16009 compactIdentifier( 16010 const char * identifier, 16011 char * identifier_out, 16012 char ** identifier_out_end) 16013 { 16014 uint32_t from_index, to_index; 16015 uint32_t scan_from_index = 0; 16016 uint32_t scan_to_index = 0; 16017 subs_entry_t * subs_entry = NULL; 16018 int did_sub = 0; 16019 16020 from_index = to_index = 0; 16021 identifier_out[0] = '\0'; 16022 16023 /* Replace certain identifier prefixes with shorter @+character sequences. 16024 * Check the return value of substitute() so we only replace the prefix. 16025 */ 16026 for (subs_entry = &kext_identifier_prefix_subs[0]; 16027 subs_entry->substring && !did_sub; 16028 subs_entry++) { 16029 did_sub = substitute(identifier, identifier_out, 16030 &scan_to_index, &scan_from_index, 16031 subs_entry->substring, /* marker */ '\0', subs_entry->substitute); 16032 } 16033 did_sub = 0; 16034 16035 /* Now scan through the identifier looking for the common substrings 16036 * and replacing them with shorter !+character sequences via substitute(). 16037 */ 16038 for (/* see above */; 16039 scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index]; 16040 /* see loop */) { 16041 const char * scan_string = &identifier[scan_from_index]; 16042 16043 did_sub = 0; 16044 16045 if (scan_from_index) { 16046 for (subs_entry = &kext_identifier_substring_subs[0]; 16047 subs_entry->substring && !did_sub; 16048 subs_entry++) { 16049 did_sub = substitute(scan_string, identifier_out, 16050 &scan_to_index, &scan_from_index, 16051 subs_entry->substring, '!', subs_entry->substitute); 16052 } 16053 } 16054 16055 /* If we didn't substitute, copy the input character to the output. 16056 */ 16057 if (!did_sub) { 16058 identifier_out[scan_to_index++] = identifier[scan_from_index++]; 16059 } 16060 } 16061 16062 identifier_out[scan_to_index] = '\0'; 16063 if (identifier_out_end) { 16064 *identifier_out_end = &identifier_out[scan_to_index]; 16065 } 16066 16067 return; 16068 } 16069 #endif /* !defined(__arm__) && !defined(__arm64__) */ 16070 16071 /******************************************************************************* 16072 * assemble_identifier_and_version() adds to a string buffer a compacted 16073 * bundle identifier followed by a version string. 16074 *******************************************************************************/ 16075 16076 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length. 16077 */ 16078 static size_t assemble_identifier_and_version( 16079 kmod_info_t * kmod_info, 16080 char * identPlusVers, 16081 size_t bufSize); 16082 16083 static size_t 16084 assemble_identifier_and_version( 16085 kmod_info_t * kmod_info, 16086 char * identPlusVers, 16087 size_t bufSize) 16088 { 16089 size_t result = 0; 16090 16091 #if defined(__arm__) || defined(__arm64__) 16092 result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME); 16093 #else 16094 compactIdentifier(kmod_info->name, identPlusVers, NULL); 16095 result = strnlen(identPlusVers, KMOD_MAX_NAME - 1); 16096 #endif 16097 identPlusVers[result++] = '\t'; // increment for real char 16098 identPlusVers[result] = '\0'; // don't increment for nul char 16099 result = strlcat(identPlusVers, kmod_info->version, bufSize); 16100 if (result >= bufSize) { 16101 identPlusVers[bufSize - 1] = '\0'; 16102 result = bufSize - 1; 16103 } 16104 16105 return result; 16106 } 16107 16108 /******************************************************************************* 16109 * Assumes sKextLock is held. 16110 *******************************************************************************/ 16111 /* static */ 16112 int 16113 OSKext::saveLoadedKextPanicListTyped( 16114 const char * prefix, 16115 int invertFlag, 16116 int libsFlag, 16117 char * paniclist, 16118 uint32_t list_size) 16119 { 16120 int result = -1; 16121 unsigned int count, i; 16122 16123 count = sLoadedKexts->getCount(); 16124 if (!count) { 16125 goto finish; 16126 } 16127 16128 i = count - 1; 16129 do { 16130 OSObject * rawKext = sLoadedKexts->getObject(i); 16131 OSKext * theKext = OSDynamicCast(OSKext, rawKext); 16132 int match; 16133 size_t identPlusVersLength; 16134 size_t tempLen; 16135 char identPlusVers[2 * KMOD_MAX_NAME]; 16136 16137 if (!rawKext) { 16138 printf("OSKext::saveLoadedKextPanicListTyped - " 16139 "NULL kext in loaded kext list; continuing\n"); 16140 continue; 16141 } 16142 16143 if (!theKext) { 16144 printf("OSKext::saveLoadedKextPanicListTyped - " 16145 "Kext type cast failed in loaded kext list; continuing\n"); 16146 continue; 16147 } 16148 16149 /* Skip all built-in kexts. 16150 */ 16151 if (theKext->isKernelComponent()) { 16152 continue; 16153 } 16154 16155 kmod_info_t * kmod_info = theKext->kmod_info; 16156 16157 /* Filter for kmod name (bundle identifier). 16158 */ 16159 match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME)); 16160 if ((match && invertFlag) || (!match && !invertFlag)) { 16161 continue; 16162 } 16163 16164 /* Filter for libraries (kexts that have a compatible version). 16165 */ 16166 if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) || 16167 (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) { 16168 continue; 16169 } 16170 16171 if (!kmod_info || 16172 !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) { 16173 printf("kext scan stopped due to missing kmod_info page: %p\n", 16174 kmod_info); 16175 goto finish; 16176 } 16177 16178 identPlusVersLength = assemble_identifier_and_version(kmod_info, 16179 identPlusVers, 16180 sizeof(identPlusVers)); 16181 if (!identPlusVersLength) { 16182 printf("error saving loaded kext info\n"); 16183 goto finish; 16184 } 16185 16186 /* make sure everything fits and we null terminate. 16187 */ 16188 tempLen = strlcat(paniclist, identPlusVers, list_size); 16189 if (tempLen >= list_size) { 16190 // panic list is full, keep it and null terminate 16191 paniclist[list_size - 1] = 0x00; 16192 result = 0; 16193 goto finish; 16194 } 16195 tempLen = strlcat(paniclist, "\n", list_size); 16196 if (tempLen >= list_size) { 16197 // panic list is full, keep it and null terminate 16198 paniclist[list_size - 1] = 0x00; 16199 result = 0; 16200 goto finish; 16201 } 16202 } while (i--); 16203 16204 result = 0; 16205 finish: 16206 16207 return result; 16208 } 16209 16210 /********************************************************************* 16211 *********************************************************************/ 16212 /* static */ 16213 void 16214 OSKext::saveLoadedKextPanicList(void) 16215 { 16216 char * newlist = NULL; 16217 uint32_t newlist_size = 0; 16218 16219 newlist_size = KEXT_PANICLIST_SIZE; 16220 newlist = (char *)kalloc_data_tag(newlist_size, 16221 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 16222 16223 if (!newlist) { 16224 OSKextLog(/* kext */ NULL, 16225 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 16226 "Couldn't allocate kext panic log buffer."); 16227 goto finish; 16228 } 16229 16230 newlist[0] = '\0'; 16231 16232 // non-"com.apple." kexts 16233 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1, 16234 /* libs? */ -1, newlist, newlist_size) != 0) { 16235 goto finish; 16236 } 16237 // "com.apple." nonlibrary kexts 16238 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 16239 /* libs? */ 0, newlist, newlist_size) != 0) { 16240 goto finish; 16241 } 16242 // "com.apple." library kexts 16243 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 16244 /* libs? */ 1, newlist, newlist_size) != 0) { 16245 goto finish; 16246 } 16247 16248 if (loaded_kext_paniclist) { 16249 kfree_data(loaded_kext_paniclist, loaded_kext_paniclist_size); 16250 } 16251 loaded_kext_paniclist = newlist; 16252 newlist = NULL; 16253 loaded_kext_paniclist_size = newlist_size; 16254 16255 finish: 16256 if (newlist) { 16257 kfree_data(newlist, newlist_size); 16258 } 16259 return; 16260 } 16261 16262 /********************************************************************* 16263 * Assumes sKextLock is held. 16264 *********************************************************************/ 16265 void 16266 OSKext::savePanicString(bool isLoading) 16267 { 16268 u_long len; 16269 16270 if (!kmod_info) { 16271 return; // do not goto finish here b/c of lock 16272 } 16273 16274 len = assemble_identifier_and_version( kmod_info, 16275 (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf, 16276 (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf)); 16277 if (!len) { 16278 printf("error saving unloaded kext info\n"); 16279 goto finish; 16280 } 16281 16282 if (isLoading) { 16283 last_loaded_strlen = len; 16284 last_loaded_address = (void *)kmod_info->address; 16285 last_loaded_size = kmod_info->size; 16286 clock_get_uptime(&last_loaded_timestamp); 16287 } else { 16288 last_unloaded_strlen = len; 16289 last_unloaded_address = (void *)kmod_info->address; 16290 last_unloaded_size = kmod_info->size; 16291 clock_get_uptime(&last_unloaded_timestamp); 16292 } 16293 16294 finish: 16295 return; 16296 } 16297 16298 /********************************************************************* 16299 *********************************************************************/ 16300 /* static */ 16301 void 16302 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...)) 16303 { 16304 if (last_loaded_strlen) { 16305 printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n", 16306 AbsoluteTime_to_scalar(&last_loaded_timestamp), 16307 last_loaded_strlen, last_loaded_str_buf, 16308 last_loaded_address, last_loaded_size); 16309 } 16310 16311 if (last_unloaded_strlen) { 16312 printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n", 16313 AbsoluteTime_to_scalar(&last_unloaded_timestamp), 16314 last_unloaded_strlen, last_unloaded_str_buf, 16315 last_unloaded_address, last_unloaded_size); 16316 } 16317 16318 printf_func("loaded kexts:\n"); 16319 if (loaded_kext_paniclist && 16320 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) && 16321 loaded_kext_paniclist[0]) { 16322 printf_func("%.*s", 16323 strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size), 16324 loaded_kext_paniclist); 16325 } else { 16326 printf_func("(none)\n"); 16327 } 16328 return; 16329 } 16330 16331 /********************************************************************* 16332 * Assumes sKextLock is held. 16333 *********************************************************************/ 16334 /* static */ 16335 void 16336 OSKext::updateLoadedKextSummaries(void) 16337 { 16338 kern_return_t result = KERN_FAILURE; 16339 OSKextLoadedKextSummaryHeader *summaryHeader = NULL; 16340 OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL; 16341 OSKext *aKext; 16342 vm_map_offset_t start, end; 16343 size_t summarySize = 0; 16344 size_t size; 16345 u_int count; 16346 u_int maxKexts; 16347 u_int i, j; 16348 OSKextActiveAccount * accountingList; 16349 OSKextActiveAccount * prevAccountingList; 16350 uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount; 16351 16352 prevAccountingList = NULL; 16353 prevAccountingListCount = 0; 16354 16355 #if DEVELOPMENT || DEBUG 16356 if (IORecursiveLockHaveLock(sKextLock) == false) { 16357 panic("sKextLock must be held"); 16358 } 16359 #endif 16360 16361 IOLockLock(sKextSummariesLock); 16362 16363 count = sLoadedKexts->getCount(); 16364 for (i = 0, maxKexts = 0; i < count; ++i) { 16365 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 16366 maxKexts += (aKext && (aKext->isExecutable() || aKext->isSpecialKernelBinary())); 16367 } 16368 16369 if (!maxKexts) { 16370 goto finish; 16371 } 16372 if (maxKexts < kOSKextTypicalLoadCount) { 16373 maxKexts = kOSKextTypicalLoadCount; 16374 } 16375 16376 /* Calculate the size needed for the new summary headers. 16377 */ 16378 16379 size = sizeof(*gLoadedKextSummaries); 16380 size += maxKexts * sizeof(*gLoadedKextSummaries->summaries); 16381 size = round_page(size); 16382 16383 if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) { 16384 if (gLoadedKextSummaries) { 16385 kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize); 16386 gLoadedKextSummaries = NULL; 16387 gLoadedKextSummariesTimestamp = mach_absolute_time(); 16388 sLoadedKextSummariesAllocSize = 0; 16389 } 16390 result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, 16391 KMA_DATA, VM_KERN_MEMORY_OSKEXT); 16392 if (result != KERN_SUCCESS) { 16393 goto finish; 16394 } 16395 summaryHeader = summaryHeaderAlloc; 16396 summarySize = size; 16397 } else { 16398 summaryHeader = gLoadedKextSummaries; 16399 summarySize = sLoadedKextSummariesAllocSize; 16400 16401 start = (vm_map_offset_t) summaryHeader; 16402 end = start + summarySize; 16403 result = vm_map_protect(kernel_map, 16404 start, 16405 end, 16406 VM_PROT_DEFAULT, 16407 FALSE); 16408 if (result != KERN_SUCCESS) { 16409 goto finish; 16410 } 16411 } 16412 16413 /* Populate the summary header. 16414 */ 16415 16416 bzero(summaryHeader, summarySize); 16417 summaryHeader->version = kOSKextLoadedKextSummaryVersion; 16418 summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary); 16419 16420 /* Populate each kext summary. 16421 */ 16422 16423 count = sLoadedKexts->getCount(); 16424 accountingListAlloc = 0; 16425 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 16426 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 16427 if (!aKext || (!aKext->isExecutable() && !aKext->isSpecialKernelBinary())) { 16428 continue; 16429 } 16430 16431 aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]); 16432 summaryHeader->numSummaries++; 16433 accountingListAlloc++; 16434 } 16435 16436 accountingList = IONew(typeof(accountingList[0]), accountingListAlloc); 16437 accountingListCount = 0; 16438 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 16439 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 16440 if (!aKext || (!aKext->isExecutable() && !aKext->isSpecialKernelBinary())) { 16441 continue; 16442 } 16443 16444 OSKextActiveAccount activeAccount; 16445 aKext->updateActiveAccount(&activeAccount); 16446 // order by address 16447 for (idx = 0; idx < accountingListCount; idx++) { 16448 if (activeAccount.address < accountingList[idx].address) { 16449 break; 16450 } 16451 } 16452 bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0])); 16453 accountingList[idx] = activeAccount; 16454 accountingListCount++; 16455 } 16456 assert(accountingListCount == accountingListAlloc); 16457 /* Write protect the buffer and move it into place. 16458 */ 16459 16460 start = (vm_map_offset_t) summaryHeader; 16461 end = start + summarySize; 16462 16463 result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE); 16464 if (result != KERN_SUCCESS) { 16465 goto finish; 16466 } 16467 16468 gLoadedKextSummaries = summaryHeader; 16469 gLoadedKextSummariesTimestamp = mach_absolute_time(); 16470 sLoadedKextSummariesAllocSize = summarySize; 16471 summaryHeaderAlloc = NULL; 16472 16473 /* Call the magic breakpoint function through a static function pointer so 16474 * the compiler can't optimize the function away. 16475 */ 16476 if (sLoadedKextSummariesUpdated) { 16477 (*sLoadedKextSummariesUpdated)(); 16478 } 16479 16480 lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp); 16481 prevAccountingList = sKextAccounts; 16482 prevAccountingListCount = sKextAccountsCount; 16483 sKextAccounts = accountingList; 16484 sKextAccountsCount = accountingListCount; 16485 lck_ticket_unlock(sKextAccountsLock); 16486 16487 finish: 16488 IOLockUnlock(sKextSummariesLock); 16489 16490 /* If we had to allocate a new buffer but failed to generate the summaries, 16491 * free that now. 16492 */ 16493 if (summaryHeaderAlloc) { 16494 kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize); 16495 } 16496 if (prevAccountingList) { 16497 IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount); 16498 } 16499 16500 return; 16501 } 16502 16503 /********************************************************************* 16504 *********************************************************************/ 16505 void 16506 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary) 16507 { 16508 OSSharedPtr<OSData> uuid; 16509 16510 strlcpy(summary->name, getIdentifierCString(), 16511 sizeof(summary->name)); 16512 16513 uuid = copyUUID(); 16514 if (uuid) { 16515 memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid)); 16516 } 16517 16518 if (flags.builtin) { 16519 // this value will stop lldb from parsing the mach-o header 16520 // summary->address = UINT64_MAX; 16521 // summary->size = 0; 16522 summary->address = kmod_info->address; 16523 summary->size = kmod_info->size; 16524 } else { 16525 summary->address = kmod_info->address; 16526 summary->size = kmod_info->size; 16527 } 16528 summary->version = getVersion(); 16529 summary->loadTag = kmod_info->id; 16530 summary->flags = 0; 16531 summary->reference_list = (uint64_t) kmod_info->reference_list; 16532 16533 summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size); 16534 if (summary->text_exec_address == 0) { 16535 // Fallback to __TEXT 16536 summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size); 16537 } 16538 16539 /** 16540 * If the addresses within the Mach-O are unslid, then manually slide any 16541 * addresses coming from the Mach-O as higher layer software using these 16542 * summaries expects a slid address here. 16543 */ 16544 if (flags.unslidMachO) { 16545 summary->text_exec_address = (uint64_t) ml_static_slide((vm_offset_t) summary->text_exec_address); 16546 } 16547 16548 return; 16549 } 16550 16551 /********************************************************************* 16552 *********************************************************************/ 16553 16554 void 16555 OSKext::updateActiveAccount(OSKextActiveAccount *accountp) 16556 { 16557 kernel_mach_header_t *hdr = NULL; 16558 kernel_segment_command_t *seg = NULL; 16559 16560 bzero(accountp, sizeof(*accountp)); 16561 16562 hdr = (kernel_mach_header_t *)kmod_info->address; 16563 if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) { 16564 /* 16565 * If this kext supports split segments (or is in a new 16566 * MH_FILESET kext collection), use the first 16567 * executable segment as the range for instructions 16568 * (and thus for backtracing. 16569 */ 16570 for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) { 16571 if (seg->initprot & VM_PROT_EXECUTE) { 16572 break; 16573 } 16574 } 16575 } 16576 if (seg) { 16577 accountp->address = seg->vmaddr; 16578 if (accountp->address) { 16579 accountp->address_end = seg->vmaddr + seg->vmsize; 16580 } 16581 } else { 16582 /* For non-split kexts and for kexts without executable 16583 * segments, just use the kmod_info range (as the kext 16584 * is either all in one range or should not show up in 16585 * instruction backtraces). 16586 */ 16587 accountp->address = kmod_info->address; 16588 if (accountp->address) { 16589 accountp->address_end = kmod_info->address + kmod_info->size; 16590 } 16591 } 16592 16593 accountp->account = this->account; 16594 } 16595 16596 bool 16597 OSKext::isDriverKit(void) 16598 { 16599 OSString *bundleType; 16600 16601 if (infoDict) { 16602 bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)); 16603 if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) { 16604 return TRUE; 16605 } 16606 } 16607 return FALSE; 16608 } 16609 16610 bool 16611 OSKext::isInFileset(void) 16612 { 16613 if (!kmod_info) { 16614 goto check_prelinked; 16615 } 16616 16617 if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) { 16618 return true; 16619 } 16620 16621 check_prelinked: 16622 if (isPrelinked()) { 16623 /* 16624 * If we haven't setup kmod_info yet, but we know 16625 * we're loading a prelinked kext in an MH_FILESET KC, 16626 * then return true 16627 */ 16628 kc_format_t kc_format; 16629 if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) { 16630 return true; 16631 } 16632 } 16633 return false; 16634 } 16635 16636 OSSharedPtr<OSDextStatistics> 16637 OSKext::copyDextStatistics(void) 16638 { 16639 return dextStatistics; 16640 } 16641 16642 bool 16643 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg) 16644 { 16645 kern_return_t result; 16646 if (!super::init()) { 16647 return false; 16648 } 16649 if (seg == nullptr) { 16650 return false; 16651 } 16652 result = kmem_alloc(kernel_map, (vm_offset_t *)&data, seg->vmsize, 16653 KMA_PAGEABLE, VM_KERN_MEMORY_KEXT); 16654 if (result != KERN_SUCCESS) { 16655 return false; 16656 } 16657 memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize); 16658 savedSegment = seg; 16659 vmsize = seg->vmsize; 16660 vmaddr = seg->vmaddr; 16661 return true; 16662 } 16663 16664 OSSharedPtr<OSKextSavedMutableSegment> 16665 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg) 16666 { 16667 OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>(); 16668 if (me && !me->initWithSegment(seg)) { 16669 return nullptr; 16670 } 16671 return me; 16672 } 16673 16674 void 16675 OSKextSavedMutableSegment::free(void) 16676 { 16677 if (data) { 16678 kmem_free(kernel_map, (vm_offset_t)data, vmsize); 16679 } 16680 } 16681 16682 vm_offset_t 16683 OSKextSavedMutableSegment::getVMAddr() const 16684 { 16685 return vmaddr; 16686 } 16687 16688 vm_offset_t 16689 OSKextSavedMutableSegment::getVMSize() const 16690 { 16691 return vmsize; 16692 } 16693 16694 OSReturn 16695 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg) 16696 { 16697 if (seg != savedSegment) { 16698 return kOSKextReturnInvalidArgument; 16699 } 16700 if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) { 16701 return kOSKextReturnInvalidArgument; 16702 } 16703 memcpy((void *)seg->vmaddr, data, vmsize); 16704 return kOSReturnSuccess; 16705 } 16706 16707 extern "C" kern_return_t 16708 OSKextSetReceiptQueried(void) 16709 { 16710 OSKextLog(/* kext */ NULL, 16711 kOSKextLogStepLevel | kOSKextLogGeneralFlag, 16712 "Setting kext receipt as queried"); 16713 16714 IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue); 16715 return KERN_SUCCESS; 16716 } 16717 16718 extern "C" const vm_allocation_site_t * 16719 OSKextGetAllocationSiteForCaller(uintptr_t address) 16720 { 16721 OSKextActiveAccount * active; 16722 vm_allocation_site_t * site; 16723 vm_allocation_site_t * releasesite; 16724 16725 uint32_t baseIdx; 16726 uint32_t lim; 16727 #if __has_feature(ptrauth_calls) 16728 address = (uintptr_t)VM_KERNEL_STRIP_PTR(address); 16729 #endif /* __has_feature(ptrauth_calls) */ 16730 16731 lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp); 16732 site = releasesite = NULL; 16733 16734 // bsearch sKextAccounts list 16735 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 16736 active = &sKextAccounts[baseIdx + (lim >> 1)]; 16737 if ((address >= active->address) && (address < active->address_end)) { 16738 site = &active->account->site; 16739 if (!site->tag) { 16740 vm_tag_alloc_locked(site, &releasesite); 16741 } 16742 break; 16743 } else if (address > active->address) { 16744 // move right 16745 baseIdx += (lim >> 1) + 1; 16746 lim--; 16747 } 16748 // else move left 16749 } 16750 lck_ticket_unlock(sKextAccountsLock); 16751 if (releasesite) { 16752 kern_allocation_name_release(releasesite); 16753 } 16754 16755 return site; 16756 } 16757 16758 #if DEVELOPMENT || DEBUG 16759 extern "C" void 16760 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *)) 16761 { 16762 OSKextActiveAccount * active; 16763 16764 uint32_t baseIdx; 16765 uint32_t lim; 16766 #if __has_feature(ptrauth_calls) 16767 address = (uintptr_t)VM_KERNEL_STRIP_PTR(address); 16768 #endif /* __has_feature(ptrauth_calls) */ 16769 16770 lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp); 16771 16772 // bsearch sKextAccounts list 16773 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 16774 active = &sKextAccounts[baseIdx + (lim >> 1)]; 16775 if ((address >= active->address) && (address < active->address_end)) { 16776 cb(&active->account->task_refgrp); 16777 break; 16778 } else if (address > active->address) { 16779 // move right 16780 baseIdx += (lim >> 1) + 1; 16781 lim--; 16782 } 16783 // else move left 16784 } 16785 lck_ticket_unlock(sKextAccountsLock); 16786 } 16787 #endif /* DEVELOPMENT || DEBUG */ 16788 16789 extern "C" uint32_t 16790 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen) 16791 { 16792 OSKextAccount * account = (typeof(account))site; 16793 const char * kname; 16794 16795 if (name) { 16796 if (account->kext) { 16797 kname = account->kext->getIdentifierCString(); 16798 } else { 16799 kname = "<>"; 16800 } 16801 strlcpy(name, kname, namelen); 16802 } 16803 16804 return account->loadTag; 16805 } 16806 16807 extern "C" void 16808 OSKextFreeSite(vm_allocation_site_t * site) 16809 { 16810 OSKextAccount * freeAccount = (typeof(freeAccount))site; 16811 IOFreeType(freeAccount, OSKextAccount); 16812 } 16813 16814 /********************************************************************* 16815 *********************************************************************/ 16816 16817 #if CONFIG_IMAGEBOOT 16818 int 16819 OSKextGetUUIDForName(const char *name, uuid_t uuid) 16820 { 16821 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name); 16822 if (!kext) { 16823 return 1; 16824 } 16825 16826 OSSharedPtr<OSData> uuid_data = kext->copyUUID(); 16827 if (uuid_data) { 16828 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t)); 16829 return 0; 16830 } 16831 16832 return 1; 16833 } 16834 #endif 16835 16836 16837 16838 class OSDextCrash : public OSObject { 16839 OSDeclareDefaultStructors(OSDextCrash); 16840 public: 16841 static OSPtr<OSDextCrash> withTimestamp(uint64_t timestamp); 16842 uint64_t getTimestamp(); 16843 16844 private: 16845 virtual bool initWithTimestamp(uint64_t timestamp); 16846 uint64_t fTimestamp; 16847 }; 16848 16849 OSDefineMetaClassAndStructors(OSDextCrash, OSObject); 16850 16851 OSSharedPtr<OSDextCrash> 16852 OSDextCrash::withTimestamp(uint64_t timestamp) 16853 { 16854 OSSharedPtr<OSDextCrash> result = OSMakeShared<OSDextCrash>(); 16855 if (!result->initWithTimestamp(timestamp)) { 16856 return NULL; 16857 } 16858 return result; 16859 } 16860 16861 bool 16862 OSDextCrash::initWithTimestamp(uint64_t timestamp) 16863 { 16864 if (!OSObject::init()) { 16865 return false; 16866 } 16867 fTimestamp = timestamp; 16868 return true; 16869 } 16870 16871 uint64_t 16872 OSDextCrash::getTimestamp() 16873 { 16874 return fTimestamp; 16875 } 16876 16877 OSSharedPtr<OSDextStatistics> 16878 OSDextStatistics::create() 16879 { 16880 OSSharedPtr<OSDextStatistics> result = OSMakeShared<OSDextStatistics>(); 16881 if (!result->init()) { 16882 return NULL; 16883 } 16884 return result; 16885 } 16886 16887 bool 16888 OSDextStatistics::init() 16889 { 16890 if (!OSObject::init()) { 16891 return false; 16892 } 16893 16894 lock = IOLockAlloc(); 16895 crashes = OSArray::withCapacity(kMaxDextCrashesInOneDay); 16896 return true; 16897 } 16898 16899 void 16900 OSDextStatistics::free() 16901 { 16902 if (lock) { 16903 IOLockFree(lock); 16904 } 16905 crashes.reset(); 16906 OSObject::free(); 16907 } 16908 16909 OSDextCrashPolicy 16910 OSDextStatistics::recordCrash() 16911 { 16912 size_t i = 0; 16913 uint64_t timestamp = mach_continuous_time(); 16914 uint64_t interval; 16915 nanoseconds_to_absolutetime(86400 * NSEC_PER_SEC /* 1 day */, &interval); 16916 uint64_t lastTimestamp = timestamp > interval ? timestamp - interval : 0; 16917 OSDextCrashPolicy policy; 16918 16919 IOLockLock(lock); 16920 OSSharedPtr<OSDextCrash> crash = OSDextCrash::withTimestamp(timestamp); 16921 for (i = 0; i < crashes->getCount();) { 16922 OSDextCrash * current = OSDynamicCast(OSDextCrash, crashes->getObject(i)); 16923 assert(current != NULL); 16924 if (current->getTimestamp() < lastTimestamp) { 16925 crashes->removeObject(i); 16926 } else { 16927 i++; 16928 } 16929 } 16930 16931 crashes->setObject(crash); 16932 16933 if (crashes->getCount() > kMaxDextCrashesInOneDay) { 16934 policy = kOSDextCrashPolicyReboot; 16935 } else { 16936 policy = kOSDextCrashPolicyNone; 16937 } 16938 16939 IOLockUnlock(lock); 16940 16941 return policy; 16942 } 16943 16944 size_t 16945 OSDextStatistics::getCrashCount() 16946 { 16947 size_t result = 0; 16948 IOLockLock(lock); 16949 result = crashes->getCount(); 16950 IOLockUnlock(lock); 16951 return result; 16952 } 16953 16954 static int 16955 sysctl_willuserspacereboot 16956 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 16957 { 16958 int new_value = 0, old_value = 0, changed = 0; 16959 int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed); 16960 if (error) { 16961 return error; 16962 } 16963 if (changed) { 16964 OSKext::willUserspaceReboot(); 16965 } 16966 return 0; 16967 } 16968 16969 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot, 16970 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 16971 NULL, 0, sysctl_willuserspacereboot, "I", ""); 16972