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.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.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 PRAGMA_MARK 91 #pragma mark External & Internal Function Protos 92 #endif 93 /********************************************************************* 94 *********************************************************************/ 95 extern "C" { 96 extern int IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize); 97 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize); 98 99 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */ 100 extern int dtrace_keep_kernel_symbols(void); 101 102 #if defined(__x86_64__) || defined(__i386__) 103 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide); 104 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers); 105 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size); 106 static void *allocate_kcfileset_map_entry_list(void); 107 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size); 108 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable); 109 int vnode_put(struct vnode *vp); 110 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size, 111 void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot); 112 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size); 113 void * ubc_getobject(struct vnode *vp, __unused int flags); 114 #endif //(__x86_64__) || defined(__i386__) 115 } 116 117 extern unsigned long gVirtBase; 118 extern unsigned long gPhysBase; 119 extern vm_map_t g_kext_map; 120 121 bool pageableKCloaded = false; 122 bool auxKCloaded = false; 123 bool resetAuxKCSegmentOnUnload = false; 124 125 extern boolean_t pageablekc_uuid_valid; 126 extern uuid_t pageablekc_uuid; 127 extern uuid_string_t pageablekc_uuid_string; 128 129 extern boolean_t auxkc_uuid_valid; 130 extern uuid_t auxkc_uuid; 131 extern uuid_string_t auxkc_uuid_string; 132 133 static OSReturn _OSKextCreateRequest( 134 const char * predicate, 135 OSSharedPtr<OSDictionary> & requestP); 136 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict); 137 static OSObject * _OSKextGetRequestArgument( 138 OSDictionary * requestDict, 139 const char * argName); 140 static bool _OSKextSetRequestArgument( 141 OSDictionary * requestDict, 142 const char * argName, 143 OSObject * value); 144 static void * _OSKextExtractPointer(OSData * wrapper); 145 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSData * wrapper); 146 static OSReturn _OSDictionarySetCStringValue( 147 OSDictionary * dict, 148 const char * key, 149 const char * value); 150 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID); 151 #if CONFIG_KXLD 152 static bool _OSKextInPrelinkRebuildWindow(void); 153 #endif 154 155 // We really should add containsObject() & containsCString to OSCollection & subclasses. 156 // So few pad slots, though.... 157 static bool _OSArrayContainsCString(OSArray * array, const char * cString); 158 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code); 159 160 /* Prelinked arm kexts do not have VM entries because the method we use to 161 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does 162 * not work on ARM. To get around that, we must free prelinked kext 163 * executables with ml_static_mfree() instead of kext_free(). 164 */ 165 #if __i386__ || __x86_64__ 166 #define VM_MAPPED_KEXTS 1 167 #define KASLR_KEXT_DEBUG 0 168 #define KASLR_IOREG_DEBUG 0 169 #elif __arm__ || __arm64__ 170 #define VM_MAPPED_KEXTS 0 171 #define KASLR_KEXT_DEBUG 0 172 #else 173 #error Unsupported architecture 174 #endif 175 176 #if PRAGMA_MARK 177 #pragma mark Constants & Macros 178 #endif 179 /********************************************************************* 180 * Constants & Macros 181 *********************************************************************/ 182 183 /* Use this number to create containers. 184 */ 185 #define kOSKextTypicalLoadCount (150) 186 187 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict. 188 * A loaded kext will no dependents or external retains will have 2 retains. 189 */ 190 #define kOSKextMinRetainCount (1) 191 #define kOSKextMinLoadedRetainCount (2) 192 193 /********** 194 * Strings and substrings used in dependency resolution. 195 */ 196 #define APPLE_KEXT_PREFIX "com.apple." 197 #define KERNEL_LIB "com.apple.kernel" 198 199 #define PRIVATE_KPI "com.apple.kpi.private" 200 201 /* Version for compatbility pseudokexts (com.apple.kernel.*), 202 * compatible back to v6.0. 203 */ 204 #define KERNEL6_LIB "com.apple.kernel.6.0" 205 #define KERNEL6_VERSION "7.9.9" 206 207 #define KERNEL_LIB_PREFIX "com.apple.kernel." 208 #define KPI_LIB_PREFIX "com.apple.kpi." 209 210 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0) 211 212 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes 213 #define MINIMUM_WAKEUP_SECONDS (30) 214 215 /********************************************************************* 216 * infoDict keys for internally-stored data. Saves on ivar slots for 217 * objects we don't keep around past boot time or during active load. 218 *********************************************************************/ 219 220 /* A usable, uncompressed file is stored under this key. 221 */ 222 #define _kOSKextExecutableKey "_OSKextExecutable" 223 224 /* An indirect reference to the executable file from an mkext 225 * is stored under this key. 226 */ 227 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference" 228 229 /* If the file is contained in a larger buffer laid down by the booter or 230 * sent from user space, the OSKext stores that OSData under this key so that 231 * references are properly tracked. This is always an mkext, right now. 232 */ 233 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData" 234 235 #define OS_LOG_HDR_VERSION 1 236 #define NUM_OS_LOG_SECTIONS 3 237 238 #define OS_LOG_SECT_IDX 0 239 #define CSTRING_SECT_IDX 1 240 #define ASAN_CSTRING_SECT_IDX 2 241 242 #if PRAGMA_MARK 243 #pragma mark Typedefs 244 #endif 245 /********************************************************************* 246 * Typedefs 247 *********************************************************************/ 248 249 /********************************************************************* 250 * osLogDataHeaderRef describes the header information of an OSData 251 * object that is returned when querying for kOSBundleLogStringsKey. 252 * We currently return information regarding 2 sections - os_log and 253 * cstring. In the case that the os_log section doesn't exist, we just 254 * return an offset and length of 0 for that section. 255 *********************************************************************/ 256 typedef struct osLogDataHeader { 257 uint32_t version; 258 uint32_t sect_count; 259 struct { 260 uint32_t sect_offset; 261 uint32_t sect_size; 262 } sections[0]; 263 } osLogDataHeaderRef; 264 265 /********************************************************************* 266 * MkextEntryRef describes the contents of an OSData object 267 * referencing a file entry from an mkext so that we can uncompress 268 * (if necessary) and extract it on demand. 269 * 270 * It contains the mkextVersion in case we ever wind up supporting 271 * multiple mkext formats. Mkext format 1 is officially retired as of 272 * Snow Leopard. 273 *********************************************************************/ 274 typedef struct MkextEntryRef { 275 mkext_basic_header * mkext; // beginning of whole mkext file 276 void * fileinfo;// mkext2_file_entry or equiv; see mkext.h 277 } MkextEntryRef; 278 279 #if PRAGMA_MARK 280 #pragma mark Global and static Module Variables 281 #endif 282 /********************************************************************* 283 * Global & static variables, used to keep track of kexts. 284 *********************************************************************/ 285 286 static bool sPrelinkBoot = false; 287 static bool sSafeBoot = false; 288 static bool sKeepSymbols = false; 289 static bool sPanicOnKCMismatch = false; 290 static bool sOSKextWasResetAfterUserspaceReboot = false; 291 292 /********************************************************************* 293 * sKextLock is the principal lock for OSKext, and guards all static 294 * and global variables not owned by other locks (declared further 295 * below). It must be taken by any entry-point method or function, 296 * including internal functions called on scheduled threads. 297 * 298 * sKextLock and sKextInnerLock are recursive due to multiple functions 299 * that are called both externally and internally. The other locks are 300 * nonrecursive. 301 * 302 * Which locks are taken depends on what they protect, but if more than 303 * one must be taken, they must always be locked in this order 304 * (and unlocked in reverse order) to prevent deadlocks: 305 * 306 * 1. sKextLock 307 * 2. sKextInnerLock 308 * 3. sKextSummariesLock 309 * 4. sKextLoggingLock 310 */ 311 static IORecursiveLock * sKextLock = NULL; 312 313 static OSSharedPtr<OSDictionary> sKextsByID; 314 static OSSharedPtr<OSDictionary> sExcludeListByID; 315 static OSKextVersion sExcludeListVersion = 0; 316 static OSSharedPtr<OSArray> sLoadedKexts; 317 static OSSharedPtr<OSDictionary> sNonLoadableKextsByID; 318 static OSSharedPtr<OSArray> sUnloadedPrelinkedKexts; 319 static OSSharedPtr<OSArray> sLoadedDriverKitKexts; 320 321 // Requests to the IOKit daemon waiting to be picked up. 322 static OSSharedPtr<OSArray> sKernelRequests; 323 // Identifier of kext load requests in sKernelRequests 324 static OSSharedPtr<OSSet> sPostedKextLoadIdentifiers; 325 static OSSharedPtr<OSArray> sRequestCallbackRecords; 326 327 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel 328 static OSSharedPtr<OSSet> sAllKextLoadIdentifiers; 329 #if CONFIG_KXLD 330 static KXLDContext * sKxldContext = NULL; 331 #endif 332 static uint32_t sNextLoadTag = 0; 333 static uint32_t sNextRequestTag = 0; 334 335 static bool sUserLoadsActive = false; 336 static bool sIOKitDaemonActive = false; 337 static bool sDeferredLoadSucceeded = false; 338 static bool sConsiderUnloadsExecuted = false; 339 340 #if NO_KEXTD 341 static bool sKernelRequestsEnabled = false; 342 #else 343 static bool sKernelRequestsEnabled = true; 344 #endif 345 static bool sLoadEnabled = true; 346 static bool sUnloadEnabled = true; 347 348 /********************************************************************* 349 * Stuff for the OSKext representing the kernel itself. 350 **********/ 351 static OSKext * sKernelKext = NULL; 352 353 /* Set up a fake kmod_info struct for the kernel. 354 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP() 355 * before OSKext is initialized; that call only needs the name 356 * and address to be set correctly. 357 * 358 * We don't do much else with the kerne's kmod_info; we never 359 * put it into the kmod list, never adjust the reference count, 360 * and never have kernel components reference it. 361 * For that matter, we don't do much with kmod_info structs 362 * at all anymore! We just keep them filled in for gdb and 363 * binary compability. 364 */ 365 kmod_info_t g_kernel_kmod_info = { 366 .next = NULL, 367 .info_version = KMOD_INFO_VERSION, 368 .id = 0, // loadTag: kernel is always 0 369 .name = kOSKextKernelIdentifier,// bundle identifier 370 .version = "0", // filled in in OSKext::initialize() 371 .reference_count = -1, // never adjusted; kernel never unloads 372 .reference_list = NULL, 373 .address = 0, 374 .size = 0, // filled in in OSKext::initialize() 375 .hdr_size = 0, 376 .start = NULL, 377 .stop = NULL 378 }; 379 380 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */ 381 382 kmod_info_t invalid_kmod_info = { 383 .next = NULL, 384 .info_version = KMOD_INFO_VERSION, 385 .id = UINT32_MAX, 386 .name = "invalid", 387 .version = "0", 388 .reference_count = -1, 389 .reference_list = NULL, 390 .address = 0, 391 .size = 0, 392 .hdr_size = 0, 393 .start = NULL, 394 .stop = NULL 395 }; 396 397 extern "C" { 398 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c, 399 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s, 400 // misc_protos.h, db_low_trace.c, kgmacros 401 // 'kmod' is a holdover from the old kmod system, we can't rename it. 402 kmod_info_t * kmod = NULL; 403 404 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE) 405 406 407 static char * loaded_kext_paniclist = NULL; 408 static uint32_t loaded_kext_paniclist_size = 0; 409 410 AbsoluteTime last_loaded_timestamp; 411 static char last_loaded_str_buf[2 * KMOD_MAX_NAME]; 412 static u_long last_loaded_strlen = 0; 413 static void * last_loaded_address = NULL; 414 static u_long last_loaded_size = 0; 415 416 AbsoluteTime last_unloaded_timestamp; 417 static char last_unloaded_str_buf[2 * KMOD_MAX_NAME]; 418 static u_long last_unloaded_strlen = 0; 419 static void * last_unloaded_address = NULL; 420 static u_long last_unloaded_size = 0; 421 422 // Statically linked kmods described by several mach-o sections: 423 // 424 // kPrelinkInfoSegment:kBuiltinInfoSection 425 // Array of pointers to kmod_info_t structs. 426 // 427 // kPrelinkInfoSegment:kBuiltinInfoSection 428 // Array of pointers to an embedded mach-o header. 429 // 430 // __DATA:kBuiltinInitSection, kBuiltinTermSection 431 // Structors for all kmods. Has to be filtered by proc address. 432 // 433 434 static uint32_t gBuiltinKmodsCount; 435 static kernel_section_t * gBuiltinKmodsSectionInfo; 436 static kernel_section_t * gBuiltinKmodsSectionStart; 437 438 const OSSymbol * gIOSurfaceIdentifier; 439 vm_tag_t gIOSurfaceTag; 440 441 /********************************************************************* 442 * sKextInnerLock protects against cross-calls with IOService and 443 * IOCatalogue, and owns the variables declared immediately below. 444 * 445 * Note that sConsiderUnloadsExecuted above belongs to sKextLock! 446 * 447 * When both sKextLock and sKextInnerLock need to be taken, 448 * always lock sKextLock first and unlock it second. Never take both 449 * locks in an entry point to OSKext; if you need to do so, you must 450 * spawn an independent thread to avoid potential deadlocks for threads 451 * calling into OSKext. 452 **********/ 453 static IORecursiveLock * sKextInnerLock = NULL; 454 455 #if XNU_TARGET_OS_OSX 456 static bool sAutounloadEnabled = true; 457 #endif 458 static bool sConsiderUnloadsCalled = false; 459 static bool sConsiderUnloadsPending = false; 460 461 static unsigned int sConsiderUnloadDelay = 60; // seconds 462 static thread_call_t sUnloadCallout = NULL; 463 #if CONFIG_KXLD 464 static thread_call_t sDestroyLinkContextThread = NULL; // one-shot, one-at-a-time thread 465 #endif // CONFIG_KXLD 466 static bool sSystemSleep = false; // true when system going to sleep 467 static AbsoluteTime sLastWakeTime; // last time we woke up 468 469 /********************************************************************* 470 * Backtraces can be printed at various times so we need a tight lock 471 * on data used for that. sKextSummariesLock protects the variables 472 * declared immediately below. 473 * 474 * gLoadedKextSummaries is accessed by other modules, but only during 475 * a panic so the lock isn't needed then. 476 * 477 * gLoadedKextSummaries has the "used" attribute in order to ensure 478 * that it remains visible even when we are performing extremely 479 * aggressive optimizations, as it is needed to allow the debugger 480 * to automatically parse the list of loaded kexts. 481 **********/ 482 static IOLock * sKextSummariesLock = NULL; 483 extern "C" lck_spin_t vm_allocation_sites_lock; 484 static IOSimpleLock * sKextAccountsLock = &vm_allocation_sites_lock; 485 486 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated; 487 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL; 488 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0; 489 static size_t sLoadedKextSummariesAllocSize = 0; 490 491 static OSKextActiveAccount * sKextAccounts; 492 static uint32_t sKextAccountsCount; 493 }; 494 495 /********************************************************************* 496 * sKextLoggingLock protects the logging variables declared immediately below. 497 **********/ 498 static IOLock * sKextLoggingLock = NULL; 499 500 static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel | 501 kOSKextLogVerboseFlagsMask; 502 static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter; 503 static bool sBootArgLogFilterFound = false; 504 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter, 505 0, "kernel kext logging"); 506 507 static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter; 508 static OSSharedPtr<OSArray> sUserSpaceLogSpecArray; 509 static OSSharedPtr<OSArray> sUserSpaceLogMessageArray; 510 511 /********* 512 * End scope for sKextInnerLock-protected variables. 513 *********************************************************************/ 514 515 516 /********************************************************************* 517 * helper function used for collecting PGO data upon unload of a kext 518 */ 519 520 static int OSKextGrabPgoDataLocked(OSKext *kext, 521 bool metadata, 522 uuid_t instance_uuid, 523 uint64_t *pSize, 524 char *pBuffer, 525 uint64_t bufferSize); 526 527 /**********************************************************************/ 528 529 530 531 #if PRAGMA_MARK 532 #pragma mark OSData callbacks (need to move to OSData) 533 #endif 534 /********************************************************************* 535 * C functions used for callbacks. 536 *********************************************************************/ 537 extern "C" { 538 void 539 osdata_kmem_free(void * ptr, unsigned int length) 540 { 541 kmem_free(kernel_map, (vm_address_t)ptr, length); 542 return; 543 } 544 545 void 546 osdata_phys_free(void * ptr, unsigned int length) 547 { 548 ml_static_mfree((vm_offset_t)ptr, length); 549 return; 550 } 551 552 void 553 osdata_vm_deallocate(void * ptr, unsigned int length) 554 { 555 (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length); 556 return; 557 } 558 559 void 560 osdata_kext_free(void * ptr, unsigned int length) 561 { 562 (void)kext_free((vm_offset_t)ptr, length); 563 } 564 }; 565 566 #if PRAGMA_MARK 567 #pragma mark KXLD Allocation Callback 568 #endif 569 #if CONFIG_KXLD 570 /********************************************************************* 571 * KXLD Allocation Callback 572 *********************************************************************/ 573 kxld_addr_t 574 kern_allocate( 575 u_long size, 576 KXLDAllocateFlags * flags, 577 void * user_data) 578 { 579 vm_address_t result = 0; // returned 580 kern_return_t mach_result = KERN_FAILURE; 581 bool success = false; 582 OSKext * theKext = (OSKext *)user_data; 583 unsigned int roundSize = 0; 584 OSSharedPtr<OSData> linkBuffer; 585 586 if (round_page(size) > UINT_MAX) { 587 OSKextLog(theKext, 588 kOSKextLogErrorLevel | 589 kOSKextLogGeneralFlag, 590 "%s: Requested memory size is greater than UINT_MAX.", 591 theKext->getIdentifierCString()); 592 goto finish; 593 } 594 595 roundSize = (unsigned int)round_page(size); 596 597 mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE); 598 if (mach_result != KERN_SUCCESS) { 599 OSKextLog(theKext, 600 kOSKextLogErrorLevel | 601 kOSKextLogGeneralFlag, 602 "Can't allocate kernel memory to link %s.", 603 theKext->getIdentifierCString()); 604 goto finish; 605 } 606 607 /* Create an OSData wrapper for the allocated buffer. 608 */ 609 linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize); 610 if (!linkBuffer) { 611 OSKextLog(theKext, 612 kOSKextLogErrorLevel | 613 kOSKextLogGeneralFlag, 614 "Can't allocate linked executable wrapper for %s.", 615 theKext->getIdentifierCString()); 616 goto finish; 617 } 618 linkBuffer->setDeallocFunction(osdata_kext_free); 619 OSKextLog(theKext, 620 kOSKextLogProgressLevel | 621 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 622 "Allocated link buffer for kext %s at %p (%lu bytes).", 623 theKext->getIdentifierCString(), 624 (void *)result, (unsigned long)roundSize); 625 626 theKext->setLinkedExecutable(linkBuffer.get()); 627 628 *flags = kKxldAllocateWritable; 629 success = true; 630 631 finish: 632 if (!success && result) { 633 kext_free(result, roundSize); 634 result = 0; 635 } 636 637 return (kxld_addr_t)result; 638 } 639 640 /********************************************************************* 641 *********************************************************************/ 642 void 643 kxld_log_callback( 644 KXLDLogSubsystem subsystem, 645 KXLDLogLevel level, 646 const char * format, 647 va_list argList, 648 void * user_data) 649 { 650 OSKext *theKext = (OSKext *) user_data; 651 OSKextLogSpec logSpec = 0; 652 653 switch (subsystem) { 654 case kKxldLogLinking: 655 logSpec |= kOSKextLogLinkFlag; 656 break; 657 case kKxldLogPatching: 658 logSpec |= kOSKextLogPatchFlag; 659 break; 660 } 661 662 switch (level) { 663 case kKxldLogExplicit: 664 logSpec |= kOSKextLogExplicitLevel; 665 break; 666 case kKxldLogErr: 667 logSpec |= kOSKextLogErrorLevel; 668 break; 669 case kKxldLogWarn: 670 logSpec |= kOSKextLogWarningLevel; 671 break; 672 case kKxldLogBasic: 673 logSpec |= kOSKextLogProgressLevel; 674 break; 675 case kKxldLogDetail: 676 logSpec |= kOSKextLogDetailLevel; 677 break; 678 case kKxldLogDebug: 679 logSpec |= kOSKextLogDebugLevel; 680 break; 681 } 682 683 OSKextVLog(theKext, logSpec, format, argList); 684 } 685 #endif // CONFIG_KXLD 686 687 #if PRAGMA_MARK 688 #pragma mark IOStatistics defines 689 #endif 690 691 #if IOKITSTATS 692 693 #define notifyKextLoadObservers(kext, kmod_info) \ 694 do { \ 695 IOStatistics::onKextLoad(kext, kmod_info); \ 696 } while (0) 697 698 #define notifyKextUnloadObservers(kext) \ 699 do { \ 700 IOStatistics::onKextUnload(kext); \ 701 } while (0) 702 703 #define notifyAddClassObservers(kext, addedClass, flags) \ 704 do { \ 705 IOStatistics::onClassAdded(kext, addedClass); \ 706 } while (0) 707 708 #define notifyRemoveClassObservers(kext, removedClass, flags) \ 709 do { \ 710 IOStatistics::onClassRemoved(kext, removedClass); \ 711 } while (0) 712 713 #else 714 715 #define notifyKextLoadObservers(kext, kmod_info) 716 #define notifyKextUnloadObservers(kext) 717 #define notifyAddClassObservers(kext, addedClass, flags) 718 #define notifyRemoveClassObservers(kext, removedClass, flags) 719 720 #endif /* IOKITSTATS */ 721 722 #if PRAGMA_MARK 723 #pragma mark Module Config (Startup & Shutdown) 724 #endif 725 /********************************************************************* 726 * Module Config (Class Definition & Class Methods) 727 *********************************************************************/ 728 #define super OSObject 729 OSDefineMetaClassAndStructors(OSKext, OSObject) 730 731 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject); 732 733 /********************************************************************* 734 *********************************************************************/ 735 /* static */ 736 void 737 OSKext::initialize(void) 738 { 739 OSSharedPtr<OSData> kernelExecutable = NULL;// do not release 740 u_char * kernelStart = NULL;// do not free 741 size_t kernelLength = 0; 742 IORegistryEntry * registryRoot = NULL;// do not release 743 OSSharedPtr<OSNumber> kernelCPUType; 744 OSSharedPtr<OSNumber> kernelCPUSubtype; 745 OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter; 746 bool setResult = false; 747 uint64_t * timestamp = NULL; 748 __unused char bootArgBuffer[16];// for PE_parse_boot_argn w/strings 749 750 /* This must be the first thing allocated. Everything else grabs this lock. 751 */ 752 sKextLock = IORecursiveLockAlloc(); 753 sKextInnerLock = IORecursiveLockAlloc(); 754 sKextSummariesLock = IOLockAlloc(); 755 sKextLoggingLock = IOLockAlloc(); 756 assert(sKextLock); 757 assert(sKextInnerLock); 758 assert(sKextSummariesLock); 759 assert(sKextLoggingLock); 760 761 sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount); 762 sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 763 sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 764 sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10); 765 sKernelRequests = OSArray::withCapacity(0); 766 sPostedKextLoadIdentifiers = OSSet::withCapacity(0); 767 sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount); 768 sRequestCallbackRecords = OSArray::withCapacity(0); 769 assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests && 770 sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers && 771 sRequestCallbackRecords && sUnloadedPrelinkedKexts); 772 773 /* Read the log flag boot-args and set the log flags. 774 */ 775 if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) { 776 sBootArgLogFilterFound = true; 777 sKernelLogFilter = bootLogFilter; 778 // log this if any flags are set 779 OSKextLog(/* kext */ NULL, 780 kOSKextLogBasicLevel | 781 kOSKextLogFlagsMask, 782 "Kernel kext log filter 0x%x per kextlog boot arg.", 783 (unsigned)sKernelLogFilter); 784 } 785 786 #if !defined(__arm__) && !defined(__arm64__) 787 /* 788 * On our ARM targets, the kernelcache/boot kernel collection contains 789 * the set of kexts required to boot, as specified by KCB. Safeboot is 790 * either unsupported, or is supported by the bootloader only loading 791 * the boot kernel collection; as a result OSKext has no role to play 792 * in safeboot policy on ARM. 793 */ 794 sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer, 795 sizeof(bootArgBuffer)) ? true : false; 796 #endif /* defined(__arm__) && defined(__arm64__) */ 797 798 if (sSafeBoot) { 799 OSKextLog(/* kext */ NULL, 800 kOSKextLogWarningLevel | 801 kOSKextLogGeneralFlag, 802 "SAFE BOOT DETECTED - " 803 "only valid OSBundleRequired kexts will be loaded."); 804 } 805 806 PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols)); 807 #if CONFIG_DTRACE 808 if (dtrace_keep_kernel_symbols()) { 809 sKeepSymbols = true; 810 } 811 #endif /* CONFIG_DTRACE */ 812 #if KASAN_DYNAMIC_BLACKLIST 813 /* needed for function lookup */ 814 sKeepSymbols = true; 815 #endif 816 817 /* 818 * Should we panic when the SystemKC is not linked against the 819 * BootKC that was loaded by the booter? By default: yes, if the 820 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic 821 * on mis-match and instead just print an error and continue. 822 */ 823 sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer, 824 sizeof(bootArgBuffer)) ? false : true; 825 826 /* Set up an OSKext instance to represent the kernel itself. 827 */ 828 sKernelKext = new OSKext; 829 assert(sKernelKext); 830 831 kernelStart = (u_char *)&_mh_execute_header; 832 kernelLength = getlastaddr() - (vm_offset_t)kernelStart; 833 assert(kernelLength <= UINT_MAX); 834 kernelExecutable = OSData::withBytesNoCopy( 835 kernelStart, (unsigned int)kernelLength); 836 assert(kernelExecutable); 837 838 #if KASLR_KEXT_DEBUG 839 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %lu (0x%016lx) \n", 840 (unsigned long)kernelStart, 841 (unsigned long)getlastaddr(), 842 kernelLength, 843 (unsigned long)vm_kernel_slide, 844 (unsigned long)vm_kernel_slide); 845 #endif 846 847 sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0 848 sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier); 849 850 sKernelKext->version = OSKextParseVersionString(osrelease); 851 sKernelKext->compatibleVersion = sKernelKext->version; 852 sKernelKext->linkedExecutable = os::move(kernelExecutable); 853 sKernelKext->interfaceUUID = sKernelKext->copyUUID(); 854 855 sKernelKext->flags.hasAllDependencies = 1; 856 sKernelKext->flags.kernelComponent = 1; 857 sKernelKext->flags.prelinked = 0; 858 sKernelKext->flags.loaded = 1; 859 sKernelKext->flags.started = 1; 860 sKernelKext->flags.CPPInitialized = 0; 861 sKernelKext->flags.jettisonLinkeditSeg = 0; 862 863 sKernelKext->kmod_info = &g_kernel_kmod_info; 864 strlcpy(g_kernel_kmod_info.version, osrelease, 865 sizeof(g_kernel_kmod_info.version)); 866 g_kernel_kmod_info.size = kernelLength; 867 g_kernel_kmod_info.id = sKernelKext->loadTag; 868 869 /* Cons up an info dict, so we don't have to have special-case 870 * checking all over. 871 */ 872 sKernelKext->infoDict = OSDictionary::withCapacity(5); 873 assert(sKernelKext->infoDict); 874 setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey, 875 sKernelKext->bundleID.get()); 876 assert(setResult); 877 setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey, 878 kOSBooleanTrue); 879 assert(setResult); 880 881 { 882 OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease)); 883 assert(scratchString); 884 setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey, 885 scratchString.get()); 886 assert(setResult); 887 } 888 889 { 890 OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy("mach_kernel")); 891 assert(scratchString); 892 setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey, 893 scratchString.get()); 894 assert(setResult); 895 } 896 897 /* Add the kernel kext to the bookkeeping dictionaries. Note that 898 * the kernel kext doesn't have a kmod_info struct. copyInfo() 899 * gathers info from other places anyhow. 900 */ 901 setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext); 902 assert(setResult); 903 setResult = sLoadedKexts->setObject(sKernelKext); 904 assert(setResult); 905 906 // XXX: better way with OSSharedPtr? 907 // sKernelKext remains a valid pointer even after the decref 908 sKernelKext->release(); 909 910 registryRoot = IORegistryEntry::getRegistryRoot(); 911 kernelCPUType = OSNumber::withNumber( 912 (long long unsigned int)_mh_execute_header.cputype, 913 8 * sizeof(_mh_execute_header.cputype)); 914 kernelCPUSubtype = OSNumber::withNumber( 915 (long long unsigned int)_mh_execute_header.cpusubtype, 916 8 * sizeof(_mh_execute_header.cpusubtype)); 917 assert(registryRoot && kernelCPUSubtype && kernelCPUType); 918 919 registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get()); 920 registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get()); 921 922 gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection); 923 if (gBuiltinKmodsSectionInfo) { 924 uint32_t count; 925 926 assert(gBuiltinKmodsSectionInfo->addr); 927 assert(gBuiltinKmodsSectionInfo->size); 928 assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX); 929 gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *)); 930 931 gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection); 932 assert(gBuiltinKmodsSectionStart); 933 assert(gBuiltinKmodsSectionStart->addr); 934 assert(gBuiltinKmodsSectionStart->size); 935 assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX); 936 count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t)); 937 // one extra pointer for the end of last kmod 938 assert(count == (gBuiltinKmodsCount + 1)); 939 940 vm_kernel_builtinkmod_text = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0]; 941 vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1]; 942 } 943 944 // Don't track this object -- it's never released 945 gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach(); 946 947 timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp); 948 *timestamp = 0; 949 timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp); 950 *timestamp = 0; 951 timestamp = __OSAbsoluteTimePtr(&sLastWakeTime); 952 *timestamp = 0; 953 954 OSKextLog(/* kext */ NULL, 955 kOSKextLogProgressLevel | 956 kOSKextLogGeneralFlag, 957 "Kext system initialized."); 958 959 notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info); 960 961 return; 962 } 963 964 /********************************************************************* 965 * This is expected to be called exactly once, from exactly one thread 966 * context, during kernel bootstrap. 967 *********************************************************************/ 968 /* static */ 969 OSReturn 970 OSKext::removeKextBootstrap(void) 971 { 972 OSReturn result = kOSReturnError; 973 974 const char * dt_kernel_header_name = "Kernel-__HEADER"; 975 const char * dt_kernel_symtab_name = "Kernel-__SYMTAB"; 976 kernel_mach_header_t * dt_mach_header = NULL; 977 int dt_mach_header_size = 0; 978 struct symtab_command * dt_symtab = NULL; 979 int dt_symtab_size = 0; 980 int dt_result = 0; 981 982 kernel_segment_command_t * seg_kld = NULL; 983 kernel_segment_command_t * seg_klddata = NULL; 984 kernel_segment_command_t * seg_linkedit = NULL; 985 986 const char __unused * dt_segment_name = NULL; 987 void __unused * segment_paddress = NULL; 988 int __unused segment_size = 0; 989 990 OSKextLog(/* kext */ NULL, 991 kOSKextLogProgressLevel | 992 kOSKextLogGeneralFlag, 993 "Jettisoning kext bootstrap segments."); 994 995 /* 996 * keep the linkedit segment around when booted from a new MH_FILESET 997 * KC because all the kexts shared a linkedit segment. 998 */ 999 kc_format_t kc_format; 1000 if (!PE_get_primary_kc_format(&kc_format)) { 1001 OSKextLog(/* kext */ NULL, 1002 kOSKextLogErrorLevel | 1003 kOSKextLogGeneralFlag, 1004 "Unable to determine primary KC format"); 1005 } 1006 1007 /***** 1008 * Dispose of unnecessary stuff that the booter didn't need to load. 1009 */ 1010 dt_result = IODTGetLoaderInfo(dt_kernel_header_name, 1011 (void **)&dt_mach_header, &dt_mach_header_size); 1012 if (dt_result == 0 && dt_mach_header) { 1013 IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header, 1014 round_page_32(dt_mach_header_size)); 1015 } 1016 dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name, 1017 (void **)&dt_symtab, &dt_symtab_size); 1018 if (dt_result == 0 && dt_symtab) { 1019 IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab, 1020 round_page_32(dt_symtab_size)); 1021 } 1022 1023 /***** 1024 * KLD & KLDDATA bootstrap segments. 1025 */ 1026 // xxx - should rename KLD segment 1027 seg_kld = getsegbyname("__KLD"); 1028 seg_klddata = getsegbyname("__KLDDATA"); 1029 if (seg_klddata) { 1030 // __mod_term_func is part of __KLDDATA 1031 OSRuntimeUnloadCPPForSegment(seg_klddata); 1032 } 1033 1034 #if __arm__ || __arm64__ 1035 /* Free the memory that was set up by iBoot. 1036 */ 1037 #if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR) 1038 /* We cannot free the KLD segment with CTRR enabled as it contains text and 1039 * is covered by the contiguous rorgn. 1040 */ 1041 dt_segment_name = "Kernel-__KLD"; 1042 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) { 1043 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1044 (int)segment_size); // calls ml_static_mfree 1045 } else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) { 1046 /* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */ 1047 ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase), 1048 seg_kld->vmsize); 1049 } 1050 #endif 1051 dt_segment_name = "Kernel-__KLDDATA"; 1052 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) { 1053 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1054 (int)segment_size); // calls ml_static_mfree 1055 } else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) { 1056 /* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */ 1057 ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase), 1058 seg_klddata->vmsize); 1059 } 1060 #elif __i386__ || __x86_64__ 1061 /* On x86, use the mapping data from the segment load command to 1062 * unload KLD & KLDDATA directly. 1063 * This may invalidate any assumptions about "avail_start" 1064 * defining the lower bound for valid physical addresses. 1065 */ 1066 if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) { 1067 bzero((void *)seg_kld->vmaddr, seg_kld->vmsize); 1068 ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize); 1069 } 1070 if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) { 1071 bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize); 1072 ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize); 1073 } 1074 #else 1075 #error arch 1076 #endif 1077 1078 /***** 1079 * Prelinked kernel's symtab (if there is one). 1080 */ 1081 if (kc_format != KCFormatFileset) { 1082 kernel_section_t * sect; 1083 sect = getsectbyname("__PRELINK", "__symtab"); 1084 if (sect && sect->addr && sect->size) { 1085 ml_static_mfree(sect->addr, sect->size); 1086 } 1087 } 1088 1089 seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT"); 1090 1091 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it 1092 * pageable, unless keepsyms is set. To do that, we have to copy it from 1093 * its booter-allocated memory, free the booter memory, reallocate proper 1094 * managed memory, then copy the segment back in. 1095 * 1096 * NOTE: This optimization is not valid for fileset KCs because each 1097 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment 1098 * that points to one fileset-global LINKEDIT segment. This 1099 * optimization is also only valid for platforms that support vm 1100 * mapped kexts or mapped kext collections (pageable KCs) 1101 */ 1102 #if VM_MAPPED_KEXTS 1103 if (!sKeepSymbols && kc_format != KCFormatFileset) { 1104 kern_return_t mem_result; 1105 void *seg_copy = NULL; 1106 void *seg_data = NULL; 1107 vm_map_offset_t seg_offset = 0; 1108 vm_map_offset_t seg_copy_offset = 0; 1109 vm_map_size_t seg_length = 0; 1110 1111 seg_data = (void *) seg_linkedit->vmaddr; 1112 seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr; 1113 seg_length = (vm_map_size_t) seg_linkedit->vmsize; 1114 1115 /* Allocate space for the LINKEDIT copy. 1116 */ 1117 mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy, 1118 seg_length, VM_KERN_MEMORY_KEXT); 1119 if (mem_result != KERN_SUCCESS) { 1120 OSKextLog(/* kext */ NULL, 1121 kOSKextLogErrorLevel | 1122 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1123 "Can't copy __LINKEDIT segment for VM reassign."); 1124 return result; 1125 } 1126 seg_copy_offset = (vm_map_offset_t) seg_copy; 1127 1128 /* Copy it out. 1129 */ 1130 memcpy(seg_copy, seg_data, seg_length); 1131 1132 /* Dump the booter memory. 1133 */ 1134 ml_static_mfree(seg_offset, seg_length); 1135 1136 /* Set up the VM region. 1137 */ 1138 mem_result = vm_map_enter_mem_object( 1139 kernel_map, 1140 &seg_offset, 1141 seg_length, /* mask */ 0, 1142 VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, 1143 VM_MAP_KERNEL_FLAGS_NONE, 1144 VM_KERN_MEMORY_NONE, 1145 (ipc_port_t)NULL, 1146 (vm_object_offset_t) 0, 1147 /* copy */ FALSE, 1148 /* cur_protection */ VM_PROT_READ | VM_PROT_WRITE, 1149 /* max_protection */ VM_PROT_ALL, 1150 /* inheritance */ VM_INHERIT_DEFAULT); 1151 if ((mem_result != KERN_SUCCESS) || 1152 (seg_offset != (vm_map_offset_t) seg_data)) { 1153 OSKextLog(/* kext */ NULL, 1154 kOSKextLogErrorLevel | 1155 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1156 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).", 1157 seg_data, seg_length, mem_result); 1158 return result; 1159 } 1160 1161 /* And copy it back. 1162 */ 1163 memcpy(seg_data, seg_copy, seg_length); 1164 1165 /* Free the copy. 1166 */ 1167 kmem_free(kernel_map, seg_copy_offset, seg_length); 1168 } else if (!sKeepSymbols && kc_format == KCFormatFileset) { 1169 /* Remove the linkedit segment of the Boot KC */ 1170 kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary); 1171 OSKext::jettisonFileSetLinkeditSegment(mh); 1172 } 1173 #else // !VM_MAPPED_KEXTS 1174 /***** 1175 * Dump the LINKEDIT segment, unless keepsyms is set. 1176 */ 1177 if (!sKeepSymbols && kc_format != KCFormatFileset) { 1178 dt_segment_name = "Kernel-__LINKEDIT"; 1179 if (0 == IODTGetLoaderInfo(dt_segment_name, 1180 &segment_paddress, &segment_size)) { 1181 #ifdef SECURE_KERNEL 1182 vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress); 1183 bzero((void*)vmaddr, segment_size); 1184 #endif 1185 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1186 (int)segment_size); 1187 } 1188 } else if (!sKeepSymbols && kc_format == KCFormatFileset) { 1189 /* Remove the linkedit segment of the Boot KC */ 1190 kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary); 1191 OSKext::jettisonFileSetLinkeditSegment(mh); 1192 } else { 1193 OSKextLog(/* kext */ NULL, 1194 kOSKextLogBasicLevel | 1195 kOSKextLogGeneralFlag, 1196 "keepsyms boot arg specified; keeping linkedit segment for symbols."); 1197 } 1198 #endif // VM_MAPPED_KEXTS 1199 1200 result = kOSReturnSuccess; 1201 1202 return result; 1203 } 1204 1205 #if CONFIG_KXLD 1206 /********************************************************************* 1207 *********************************************************************/ 1208 void 1209 OSKext::flushNonloadedKexts( 1210 Boolean flushPrelinkedKexts) 1211 { 1212 OSSharedPtr<OSSet> keepKexts; 1213 1214 /* TODO: make this more efficient with MH_FILESET kexts */ 1215 1216 // Do not unload prelinked kexts on arm because the kernelcache is not 1217 // structured in a way that allows them to be unmapped 1218 #if !defined(__x86_64__) 1219 flushPrelinkedKexts = false; 1220 #endif /* defined(__x86_64__) */ 1221 1222 IORecursiveLockLock(sKextLock); 1223 1224 OSKextLog(/* kext */ NULL, 1225 kOSKextLogProgressLevel | 1226 kOSKextLogKextBookkeepingFlag, 1227 "Flushing nonloaded kexts and other unused data."); 1228 1229 OSKext::considerDestroyingLinkContext(); 1230 1231 /* If we aren't flushing unused prelinked kexts, we have to put them 1232 * aside while we flush everything else so make a container for them. 1233 */ 1234 keepKexts = OSSet::withCapacity(16); 1235 if (!keepKexts) { 1236 goto finish; 1237 } 1238 1239 /* Set aside prelinked kexts (in-use or not) and break 1240 * any lingering inter-kext references for nonloaded kexts 1241 * so they have min. retain counts. 1242 */ 1243 { 1244 sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) { 1245 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1246 if (!thisKext) { 1247 return false; 1248 } 1249 if (!flushPrelinkedKexts && thisKext->isPrelinked()) { 1250 keepKexts->setObject(thisKext); 1251 } else if (!thisKext->declaresExecutable()) { 1252 /* 1253 * Don't unload codeless kexts, because they never appear in the loadedKexts array. 1254 * Requesting one from the IOKit daemon will load it and then immediately remove it by calling 1255 * flushNonloadedKexts(). 1256 * And adding one to loadedKexts breaks code assuming they have kmod_info etc. 1257 */ 1258 keepKexts->setObject(thisKext); 1259 } else if (thisKext->isInFileset()) { 1260 /* keep all kexts in the new MH_FILESET KC */ 1261 keepKexts->setObject(thisKext); 1262 } 1263 1264 thisKext->flushDependencies(/* forceIfLoaded */ false); 1265 return false; 1266 }); 1267 } 1268 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly. 1269 */ 1270 sKextsByID->flushCollection(); 1271 1272 /* Now put the loaded kexts back into the ID dictionary. 1273 */ 1274 sLoadedKexts->iterateObjects(^bool (OSObject * obj) { 1275 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1276 if (!thisKext) { 1277 return false; 1278 } 1279 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1280 return false; 1281 }); 1282 1283 /* Finally, put back the kept kexts if we saved any. 1284 */ 1285 keepKexts->iterateObjects(^bool (OSObject * obj) { 1286 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1287 if (!thisKext) { 1288 return false; 1289 } 1290 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1291 return false; 1292 }); 1293 1294 finish: 1295 IORecursiveLockUnlock(sKextLock); 1296 return; 1297 } 1298 #else /* !CONFIG_KXLD */ 1299 1300 void 1301 OSKext::flushNonloadedKexts( 1302 Boolean flushPrelinkedKexts __unused) 1303 { 1304 IORecursiveLockLock(sKextLock); 1305 1306 OSKextLog(/* kext */ NULL, 1307 kOSKextLogProgressLevel | 1308 kOSKextLogKextBookkeepingFlag, 1309 "Flushing dependency info for non-loaded kexts."); 1310 1311 /* 1312 * In a world where we don't dynamically link kexts, they all come 1313 * from a kext collection that's either in wired memory, or 1314 * wire-on-demand. We don't need to mess around with moving kexts in 1315 * and out of the sKextsByID array - they can all just stay there. 1316 * Here we just flush the dependency list for kexts that are not 1317 * loaded. 1318 */ 1319 sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) { 1320 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1321 if (!thisKext) { 1322 return false; 1323 } 1324 thisKext->flushDependencies(/* forceIfLoaded */ false); 1325 return false; 1326 }); 1327 1328 IORecursiveLockUnlock(sKextLock); 1329 return; 1330 } 1331 1332 #endif /* CONFIG_KXLD */ 1333 1334 /********************************************************************* 1335 *********************************************************************/ 1336 /* static */ 1337 void 1338 OSKext::setIOKitDaemonActive(bool active) 1339 { 1340 IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0); 1341 IORecursiveLockLock(sKextLock); 1342 sIOKitDaemonActive = active; 1343 if (sKernelRequests->getCount()) { 1344 OSKext::pingIOKitDaemon(); 1345 } 1346 IORecursiveLockUnlock(sKextLock); 1347 1348 return; 1349 } 1350 1351 /********************************************************************* 1352 * OSKextLib.cpp might need access to this someday but for now it's 1353 * private. 1354 *********************************************************************/ 1355 extern "C" { 1356 extern void ipc_port_release_send(ipc_port_t); 1357 }; 1358 1359 /* static */ 1360 OSReturn 1361 OSKext::pingIOKitDaemon(void) 1362 { 1363 OSReturn result = kOSReturnError; 1364 #if !NO_KEXTD 1365 mach_port_t kextd_port = IPC_PORT_NULL; 1366 1367 if (!sIOKitDaemonActive) { 1368 result = kOSKextReturnDisabled; // basically unavailable 1369 goto finish; 1370 } 1371 1372 result = host_get_kextd_port(host_priv_self(), &kextd_port); 1373 if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) { 1374 OSKextLog(/* kext */ NULL, 1375 kOSKextLogErrorLevel | 1376 kOSKextLogIPCFlag, 1377 "Can't get " kIOKitDaemonName " port."); 1378 goto finish; 1379 } 1380 1381 result = kextd_ping(kextd_port); 1382 if (result != KERN_SUCCESS) { 1383 OSKextLog(/* kext */ NULL, 1384 kOSKextLogErrorLevel | 1385 kOSKextLogIPCFlag, 1386 kIOKitDaemonName " ping failed (0x%x).", (int)result); 1387 goto finish; 1388 } 1389 1390 finish: 1391 if (IPC_PORT_VALID(kextd_port)) { 1392 ipc_port_release_send(kextd_port); 1393 } 1394 #endif 1395 1396 return result; 1397 } 1398 1399 /********************************************************************* 1400 *********************************************************************/ 1401 /* static */ 1402 void 1403 OSKext::setDeferredLoadSucceeded(Boolean succeeded) 1404 { 1405 IORecursiveLockLock(sKextLock); 1406 sDeferredLoadSucceeded = succeeded; 1407 IORecursiveLockUnlock(sKextLock); 1408 1409 return; 1410 } 1411 1412 /********************************************************************* 1413 * Called from IOSystemShutdownNotification. 1414 *********************************************************************/ 1415 /* static */ 1416 void 1417 OSKext::willShutdown(void) 1418 { 1419 #if !NO_KEXTD 1420 OSReturn checkResult = kOSReturnError; 1421 #endif 1422 OSSharedPtr<OSDictionary> exitRequest; 1423 1424 IORecursiveLockLock(sKextLock); 1425 1426 OSKext::setLoadEnabled(false); 1427 OSKext::setUnloadEnabled(false); 1428 OSKext::setAutounloadsEnabled(false); 1429 OSKext::setKernelRequestsEnabled(false); 1430 1431 #if defined(__x86_64__) || defined(__i386__) 1432 if (IOPMRootDomainGetWillShutdown()) { 1433 OSKext::freeKCFileSetcontrol(); 1434 } 1435 #endif // (__x86_64__) || defined(__i386__) 1436 1437 #if !NO_KEXTD 1438 OSKextLog(/* kext */ NULL, 1439 kOSKextLogProgressLevel | 1440 kOSKextLogGeneralFlag, 1441 "System shutdown; requesting immediate " kIOKitDaemonName " exit."); 1442 1443 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit, 1444 exitRequest); 1445 if (checkResult != kOSReturnSuccess) { 1446 goto finish; 1447 } 1448 if (!sKernelRequests->setObject(exitRequest.get())) { 1449 goto finish; 1450 } 1451 1452 OSKext::pingIOKitDaemon(); 1453 1454 finish: 1455 #endif 1456 1457 IORecursiveLockUnlock(sKextLock); 1458 return; 1459 } 1460 1461 void 1462 OSKext::willUserspaceReboot(void) 1463 { 1464 OSKext::willShutdown(); 1465 IOService::userSpaceWillReboot(); 1466 gIOCatalogue->terminateDriversForUserspaceReboot(); 1467 } 1468 1469 void 1470 OSKext::resetAfterUserspaceReboot(void) 1471 { 1472 OSSharedPtr<OSArray> arr = OSArray::withCapacity(1); 1473 IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */); 1474 1475 IORecursiveLockLock(sKextLock); 1476 gIOCatalogue->resetAfterUserspaceReboot(); 1477 IOService::userSpaceDidReboot(); 1478 OSKext::removeDaemonExitRequests(); 1479 OSKext::setLoadEnabled(true); 1480 OSKext::setUnloadEnabled(true); 1481 OSKext::setAutounloadsEnabled(true); 1482 OSKext::setKernelRequestsEnabled(true); 1483 sOSKextWasResetAfterUserspaceReboot = true; 1484 IORecursiveLockUnlock(sKextLock); 1485 } 1486 1487 extern "C" void 1488 OSKextResetAfterUserspaceReboot(void) 1489 { 1490 OSKext::resetAfterUserspaceReboot(); 1491 } 1492 1493 /* 1494 * Remove daemon exit requests from sKernelRequests 1495 * 1496 * If we sent a daemon exit request during a userspace reboot and launchd 1497 * killed the IOKit daemon before it was able to dequeue the exit request, the 1498 * next time the daemon starts up it will immediately exit as it gets the old exit request. 1499 * 1500 * This removes exit requests so that this does not happen. 1501 */ 1502 void 1503 OSKext::removeDaemonExitRequests(void) 1504 { 1505 OSDictionary * current = NULL; 1506 OSString * predicate = NULL; 1507 size_t index = 0; 1508 OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey); 1509 1510 while (index < sKernelRequests->getCount()) { 1511 current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index)); 1512 if (current) { 1513 predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get())); 1514 if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) { 1515 sKernelRequests->removeObject(index); 1516 continue; 1517 } 1518 } 1519 index++; 1520 } 1521 } 1522 1523 /********************************************************************* 1524 *********************************************************************/ 1525 /* static */ 1526 bool 1527 OSKext::getLoadEnabled(void) 1528 { 1529 bool result; 1530 1531 IORecursiveLockLock(sKextLock); 1532 result = sLoadEnabled; 1533 IORecursiveLockUnlock(sKextLock); 1534 return result; 1535 } 1536 1537 /********************************************************************* 1538 *********************************************************************/ 1539 /* static */ 1540 bool 1541 OSKext::setLoadEnabled(bool flag) 1542 { 1543 bool result; 1544 1545 IORecursiveLockLock(sKextLock); 1546 result = sLoadEnabled; 1547 sLoadEnabled = (flag ? true : false); 1548 1549 if (sLoadEnabled != result) { 1550 OSKextLog(/* kext */ NULL, 1551 kOSKextLogBasicLevel | 1552 kOSKextLogLoadFlag, 1553 "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis"); 1554 } 1555 1556 IORecursiveLockUnlock(sKextLock); 1557 1558 return result; 1559 } 1560 1561 /********************************************************************* 1562 *********************************************************************/ 1563 /* static */ 1564 bool 1565 OSKext::getUnloadEnabled(void) 1566 { 1567 bool result; 1568 1569 IORecursiveLockLock(sKextLock); 1570 result = sUnloadEnabled; 1571 IORecursiveLockUnlock(sKextLock); 1572 return result; 1573 } 1574 1575 /********************************************************************* 1576 *********************************************************************/ 1577 /* static */ 1578 bool 1579 OSKext::setUnloadEnabled(bool flag) 1580 { 1581 bool result; 1582 1583 IORecursiveLockLock(sKextLock); 1584 result = sUnloadEnabled; 1585 sUnloadEnabled = (flag ? true : false); 1586 IORecursiveLockUnlock(sKextLock); 1587 1588 if (sUnloadEnabled != result) { 1589 OSKextLog(/* kext */ NULL, 1590 kOSKextLogBasicLevel | 1591 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1592 "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis"); 1593 } 1594 1595 return result; 1596 } 1597 1598 /********************************************************************* 1599 * Do not call any function that takes sKextLock here! 1600 *********************************************************************/ 1601 /* static */ 1602 bool 1603 OSKext::getAutounloadEnabled(void) 1604 { 1605 #if XNU_TARGET_OS_OSX 1606 bool result; 1607 1608 IORecursiveLockLock(sKextInnerLock); 1609 result = sAutounloadEnabled ? true : false; 1610 IORecursiveLockUnlock(sKextInnerLock); 1611 return result; 1612 #else 1613 return false; 1614 #endif /* XNU_TARGET_OS_OSX */ 1615 } 1616 1617 /********************************************************************* 1618 * Do not call any function that takes sKextLock here! 1619 *********************************************************************/ 1620 /* static */ 1621 bool 1622 OSKext::setAutounloadsEnabled(bool flag) 1623 { 1624 #if XNU_TARGET_OS_OSX 1625 bool result; 1626 1627 IORecursiveLockLock(sKextInnerLock); 1628 1629 result = sAutounloadEnabled; 1630 sAutounloadEnabled = (flag ? true : false); 1631 if (!sAutounloadEnabled && sUnloadCallout) { 1632 thread_call_cancel(sUnloadCallout); 1633 } 1634 1635 if (sAutounloadEnabled != result) { 1636 OSKextLog(/* kext */ NULL, 1637 kOSKextLogBasicLevel | 1638 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1639 "Kext autounloading now %sabled.", 1640 sAutounloadEnabled ? "en" : "dis"); 1641 } 1642 1643 IORecursiveLockUnlock(sKextInnerLock); 1644 1645 return result; 1646 #else 1647 (void)flag; 1648 return false; 1649 #endif /* XNU_TARGET_OS_OSX */ 1650 } 1651 1652 /********************************************************************* 1653 *********************************************************************/ 1654 /* instance method operating on OSKext field */ 1655 bool 1656 OSKext::setAutounloadEnabled(bool flag) 1657 { 1658 bool result = flags.autounloadEnabled ? true : false; 1659 flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0; 1660 1661 if (result != (flag ? true : false)) { 1662 OSKextLog(this, 1663 kOSKextLogProgressLevel | 1664 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 1665 "Autounloading for kext %s now %sabled.", 1666 getIdentifierCString(), 1667 flags.autounloadEnabled ? "en" : "dis"); 1668 } 1669 return result; 1670 } 1671 1672 /********************************************************************* 1673 *********************************************************************/ 1674 /* static */ 1675 bool 1676 OSKext::setKernelRequestsEnabled(bool flag) 1677 { 1678 bool result; 1679 1680 IORecursiveLockLock(sKextLock); 1681 result = sKernelRequestsEnabled; 1682 sKernelRequestsEnabled = flag ? true : false; 1683 1684 if (sKernelRequestsEnabled != result) { 1685 OSKextLog(/* kext */ NULL, 1686 kOSKextLogBasicLevel | 1687 kOSKextLogGeneralFlag, 1688 "Kernel requests now %sabled.", 1689 sKernelRequestsEnabled ? "en" : "dis"); 1690 } 1691 IORecursiveLockUnlock(sKextLock); 1692 return result; 1693 } 1694 1695 /********************************************************************* 1696 *********************************************************************/ 1697 /* static */ 1698 bool 1699 OSKext::getKernelRequestsEnabled(void) 1700 { 1701 bool result; 1702 1703 IORecursiveLockLock(sKextLock); 1704 result = sKernelRequestsEnabled; 1705 IORecursiveLockUnlock(sKextLock); 1706 return result; 1707 } 1708 1709 static bool 1710 segmentIsMutable(kernel_segment_command_t *seg) 1711 { 1712 /* Mutable segments have to have VM_PROT_WRITE */ 1713 if ((seg->maxprot & VM_PROT_WRITE) == 0) { 1714 return false; 1715 } 1716 /* Exclude the __DATA_CONST segment */ 1717 if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) { 1718 return false; 1719 } 1720 /* Exclude __LINKEDIT */ 1721 if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) { 1722 return false; 1723 } 1724 return true; 1725 } 1726 1727 #if PRAGMA_MARK 1728 #pragma mark Kext Life Cycle 1729 #endif 1730 /********************************************************************* 1731 *********************************************************************/ 1732 OSSharedPtr<OSKext> 1733 OSKext::withPrelinkedInfoDict( 1734 OSDictionary * anInfoDict, 1735 bool doCoalescedSlides, 1736 kc_kind_t type) 1737 { 1738 OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>()); 1739 1740 if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) { 1741 return NULL; 1742 } 1743 1744 return newKext; 1745 } 1746 1747 /********************************************************************* 1748 *********************************************************************/ 1749 bool 1750 OSKext::initWithPrelinkedInfoDict( 1751 OSDictionary * anInfoDict, 1752 bool doCoalescedSlides, 1753 kc_kind_t type) 1754 { 1755 bool result = false; 1756 OSString * kextPath = NULL; // do not release 1757 OSNumber * addressNum = NULL; // reused; do not release 1758 OSNumber * lengthNum = NULL; // reused; do not release 1759 OSBoolean * scratchBool = NULL; // do not release 1760 void * data = NULL; // do not free 1761 void * srcData = NULL; // do not free 1762 OSSharedPtr<OSData> prelinkedExecutable; 1763 uint32_t length = 0; // reused 1764 uintptr_t kext_slide = PE_get_kc_slide(type); 1765 bool shouldSaveSegments = false; 1766 1767 if (!super::init()) { 1768 goto finish; 1769 } 1770 1771 /* Get the path. Don't look for an arch-specific path property. 1772 */ 1773 kextPath = OSDynamicCast(OSString, 1774 anInfoDict->getObject(kPrelinkBundlePathKey)); 1775 1776 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 1777 goto finish; 1778 } 1779 1780 #if KASLR_KEXT_DEBUG 1781 IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString()); 1782 #endif 1783 1784 /* Also get the executable's bundle-relative path if present. 1785 * Don't look for an arch-specific path property. 1786 */ 1787 executableRelPath.reset(OSDynamicCast(OSString, 1788 anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain); 1789 userExecutableRelPath.reset(OSDynamicCast(OSString, 1790 anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain); 1791 1792 /* Don't need the paths to be in the info dictionary any more. 1793 */ 1794 anInfoDict->removeObject(kPrelinkBundlePathKey); 1795 anInfoDict->removeObject(kPrelinkExecutableRelativePathKey); 1796 1797 scratchBool = OSDynamicCast(OSBoolean, 1798 getPropertyForHostArch(kOSBundleRequireExplicitLoadKey)); 1799 if (scratchBool == kOSBooleanTrue) { 1800 flags.requireExplicitLoad = 1; 1801 } 1802 1803 /* Create an OSData wrapper around the linked executable. 1804 */ 1805 addressNum = OSDynamicCast(OSNumber, 1806 anInfoDict->getObject(kPrelinkExecutableLoadKey)); 1807 if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) { 1808 lengthNum = OSDynamicCast(OSNumber, 1809 anInfoDict->getObject(kPrelinkExecutableSizeKey)); 1810 if (!lengthNum) { 1811 OSKextLog(this, 1812 kOSKextLogErrorLevel | 1813 kOSKextLogArchiveFlag, 1814 "Kext %s can't find prelinked kext executable size.", 1815 getIdentifierCString()); 1816 return result; 1817 } 1818 1819 data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 1820 length = (uint32_t) (lengthNum->unsigned32BitValue()); 1821 1822 #if KASLR_KEXT_DEBUG 1823 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n", 1824 (unsigned long)ml_static_unslide((vm_offset_t)data), 1825 (unsigned long)data, 1826 length); 1827 #endif 1828 1829 anInfoDict->removeObject(kPrelinkExecutableLoadKey); 1830 anInfoDict->removeObject(kPrelinkExecutableSizeKey); 1831 1832 /* If the kext's load address differs from its source address, allocate 1833 * space in the kext map at the load address and copy the kext over. 1834 */ 1835 addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey)); 1836 if (addressNum) { 1837 srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 1838 1839 #if KASLR_KEXT_DEBUG 1840 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n", 1841 (unsigned long)ml_static_unslide((vm_offset_t)srcData), 1842 (unsigned long)srcData); 1843 #endif 1844 1845 if (data != srcData) { 1846 #if __LP64__ 1847 kern_return_t alloc_result; 1848 1849 alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE); 1850 if (alloc_result != KERN_SUCCESS) { 1851 OSKextLog(this, 1852 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 1853 "Failed to allocate space for prelinked kext %s.", 1854 getIdentifierCString()); 1855 goto finish; 1856 } 1857 memcpy(data, srcData, length); 1858 #else 1859 OSKextLog(this, 1860 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 1861 "Error: prelinked kext %s - source and load addresses " 1862 "differ on ILP32 architecture.", 1863 getIdentifierCString()); 1864 goto finish; 1865 #endif /* __LP64__ */ 1866 } 1867 1868 anInfoDict->removeObject(kPrelinkExecutableSourceKey); 1869 } 1870 1871 prelinkedExecutable = OSData::withBytesNoCopy(data, length); 1872 if (!prelinkedExecutable) { 1873 OSKextLog(this, 1874 kOSKextLogErrorLevel | 1875 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1876 "Kext %s failed to create executable wrapper.", 1877 getIdentifierCString()); 1878 goto finish; 1879 } 1880 1881 #if VM_MAPPED_KEXTS 1882 prelinkedExecutable->setDeallocFunction(osdata_kext_free); 1883 #else 1884 prelinkedExecutable->setDeallocFunction(osdata_phys_free); 1885 #endif 1886 setLinkedExecutable(prelinkedExecutable.get()); 1887 addressNum = OSDynamicCast(OSNumber, 1888 anInfoDict->getObject(kPrelinkKmodInfoKey)); 1889 if (!addressNum) { 1890 OSKextLog(this, 1891 kOSKextLogErrorLevel | 1892 kOSKextLogArchiveFlag, 1893 "Kext %s can't find prelinked kext kmod_info address.", 1894 getIdentifierCString()); 1895 goto finish; 1896 } 1897 1898 if (addressNum->unsigned64BitValue() != 0) { 1899 kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 1900 if (kmod_info->address) { 1901 kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide); 1902 } else { 1903 kmod_info->address = (uintptr_t)data; 1904 kmod_info->size = length; 1905 } 1906 #if KASLR_KEXT_DEBUG 1907 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n", 1908 (unsigned long)((vm_offset_t)kmod_info) - kext_slide, 1909 (unsigned long)kmod_info); 1910 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n", 1911 (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide, 1912 (unsigned long)kmod_info->address); 1913 #endif 1914 } 1915 1916 anInfoDict->removeObject(kPrelinkKmodInfoKey); 1917 } 1918 1919 if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) { 1920 uintptr_t builtinTextStart; 1921 uintptr_t builtinTextEnd; 1922 1923 flags.builtin = true; 1924 builtinKmodIdx = addressNum->unsigned32BitValue(); 1925 assert(builtinKmodIdx < gBuiltinKmodsCount); 1926 1927 builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx]; 1928 builtinTextEnd = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1]; 1929 1930 kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx]; 1931 kmod_info->address = builtinTextStart; 1932 kmod_info->size = builtinTextEnd - builtinTextStart; 1933 } 1934 1935 /* If the plist has a UUID for an interface, save that off. 1936 */ 1937 if (isInterface()) { 1938 interfaceUUID.reset(OSDynamicCast(OSData, 1939 anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain); 1940 if (interfaceUUID) { 1941 anInfoDict->removeObject(kPrelinkInterfaceUUIDKey); 1942 } 1943 } 1944 1945 result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides)); 1946 if (!result) { 1947 goto finish; 1948 } 1949 1950 kc_type = type; 1951 /* Exclude builtin and codeless kexts */ 1952 if (prelinkedExecutable && kmod_info) { 1953 switch (kc_type) { 1954 case KCKindPrimary: 1955 shouldSaveSegments = ( 1956 getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue || 1957 getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue); 1958 if (shouldSaveSegments) { 1959 flags.resetSegmentsFromImmutableCopy = 1; 1960 } else { 1961 flags.unloadUnsupported = 1; 1962 } 1963 break; 1964 case KCKindPageable: 1965 flags.resetSegmentsFromVnode = 1; 1966 break; 1967 case KCKindAuxiliary: 1968 if (!pageableKCloaded) { 1969 flags.resetSegmentsFromImmutableCopy = 1; 1970 } else if (resetAuxKCSegmentOnUnload) { 1971 flags.resetSegmentsFromVnode = 1; 1972 } else { 1973 flags.unloadUnsupported = 1; 1974 } 1975 break; 1976 default: 1977 break; 1978 } 1979 } 1980 1981 if (flags.resetSegmentsFromImmutableCopy) { 1982 /* Save a pristine copy of the mutable segments */ 1983 kernel_segment_command_t *seg = NULL; 1984 kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address; 1985 1986 savedMutableSegments = OSArray::withCapacity(0); 1987 1988 for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) { 1989 if (!segmentIsMutable(seg)) { 1990 continue; 1991 } 1992 uint64_t unslid_vmaddr = seg->vmaddr - kext_slide; 1993 uint64_t vmsize = seg->vmsize; 1994 OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag, 1995 "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1); 1996 OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg); 1997 if (!savedSegment) { 1998 OSKextLog(this, 1999 kOSKextLogErrorLevel | 2000 kOSKextLogGeneralFlag, 2001 "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 2002 result = kOSKextReturnInternalError; 2003 goto finish; 2004 } 2005 savedMutableSegments->setObject(savedSegment); 2006 } 2007 } 2008 2009 if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) { 2010 /* 2011 * set VM protections now, wire pages for the old style Aux KC now, 2012 * wire pages for the rest of the KC types at load time. 2013 */ 2014 result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false)); 2015 if (!result) { 2016 goto finish; 2017 } 2018 } 2019 2020 flags.prelinked = true; 2021 2022 /* If we created a kext from prelink info, 2023 * we must be booting from a prelinked kernel. 2024 */ 2025 sPrelinkBoot = true; 2026 2027 result = registerIdentifier(); 2028 2029 finish: 2030 return result; 2031 } 2032 2033 /********************************************************************* 2034 *********************************************************************/ 2035 /* static */ 2036 OSSharedPtr<OSKext> 2037 OSKext::withCodelessInfo(OSDictionary * anInfoDict) 2038 { 2039 OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>(); 2040 2041 if (newKext && !newKext->initWithCodelessInfo(anInfoDict)) { 2042 return NULL; 2043 } 2044 2045 return newKext; 2046 } 2047 2048 /********************************************************************* 2049 *********************************************************************/ 2050 bool 2051 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict) 2052 { 2053 bool result = false; 2054 OSString * kextPath = NULL; // do not release 2055 OSBoolean * scratchBool = NULL; // do not release 2056 2057 if (anInfoDict == NULL || !super::init()) { 2058 goto finish; 2059 } 2060 2061 /* 2062 * Get the path. Don't look for an arch-specific path property. 2063 */ 2064 kextPath = OSDynamicCast(OSString, 2065 anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey)); 2066 if (!kextPath) { 2067 OSKextLog(NULL, 2068 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 2069 "Requested codeless kext dictionary does not contain the '%s' key", 2070 kKextRequestArgumentCodelessInfoBundlePathKey); 2071 goto finish; 2072 } 2073 2074 uniquePersonalityProperties(anInfoDict); 2075 2076 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 2077 goto finish; 2078 } 2079 2080 /* 2081 * This path is meant to initialize codeless kexts only. Refuse 2082 * anything that looks like it has an executable and/or declares 2083 * itself as a kernel component. 2084 */ 2085 if (declaresExecutable() || isKernelComponent()) { 2086 OSKextLog(NULL, 2087 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 2088 "Refusing to register codeless kext that declares an executable/kernel component: %s", 2089 getIdentifierCString()); 2090 goto finish; 2091 } 2092 2093 if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) { 2094 boolean_t updated = updateExcludeList(infoDict.get()); 2095 if (updated) { 2096 OSKextLog(this, 2097 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2098 "KextExcludeList was updated to version: %lld", sExcludeListVersion); 2099 } 2100 } 2101 2102 kc_type = KCKindNone; 2103 2104 scratchBool = OSDynamicCast(OSBoolean, 2105 getPropertyForHostArch(kOSBundleRequireExplicitLoadKey)); 2106 if (scratchBool == kOSBooleanTrue) { 2107 flags.requireExplicitLoad = 1; 2108 } 2109 2110 /* Also get the executable's bundle-relative path if present. 2111 * Don't look for an arch-specific path property. 2112 */ 2113 userExecutableRelPath.reset(OSDynamicCast(OSString, 2114 anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain); 2115 2116 /* remove unnecessary paths from the info dict */ 2117 anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey); 2118 2119 result = registerIdentifier(); 2120 2121 finish: 2122 return result; 2123 } 2124 2125 /********************************************************************* 2126 *********************************************************************/ 2127 /* static */ 2128 void 2129 OSKext::setAllVMAttributes(void) 2130 { 2131 OSSharedPtr<OSCollectionIterator> kextIterator; 2132 const OSSymbol * thisID = NULL; // do not release 2133 2134 IORecursiveLockLock(sKextLock); 2135 2136 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 2137 if (!kextIterator) { 2138 goto finish; 2139 } 2140 2141 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 2142 OSKext * thisKext; // do not release 2143 2144 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 2145 if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) { 2146 continue; 2147 } 2148 2149 if (!thisKext->flags.resetSegmentsFromVnode) { 2150 /* 2151 * set VM protections now, wire pages for the old style Aux KC now, 2152 * wire pages for the rest of the KC types at load time. 2153 */ 2154 thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false); 2155 } 2156 } 2157 2158 finish: 2159 IORecursiveLockUnlock(sKextLock); 2160 2161 return; 2162 } 2163 2164 /********************************************************************* 2165 *********************************************************************/ 2166 OSSharedPtr<OSKext> 2167 OSKext::withBooterData( 2168 OSString * deviceTreeName, 2169 OSData * booterData) 2170 { 2171 OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>()); 2172 2173 if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) { 2174 return NULL; 2175 } 2176 2177 return newKext; 2178 } 2179 2180 /********************************************************************* 2181 *********************************************************************/ 2182 typedef struct _BooterKextFileInfo { 2183 uint32_t infoDictPhysAddr; 2184 uint32_t infoDictLength; 2185 uint32_t executablePhysAddr; 2186 uint32_t executableLength; 2187 uint32_t bundlePathPhysAddr; 2188 uint32_t bundlePathLength; 2189 } _BooterKextFileInfo; 2190 2191 bool 2192 OSKext::initWithBooterData( 2193 OSString * deviceTreeName, 2194 OSData * booterData) 2195 { 2196 bool result = false; 2197 _BooterKextFileInfo * kextFileInfo = NULL; // do not free 2198 char * infoDictAddr = NULL; // do not free 2199 void * executableAddr = NULL; // do not free 2200 char * bundlePathAddr = NULL; // do not free 2201 2202 OSDictionary * theInfoDict = NULL; // do not release 2203 OSSharedPtr<OSObject> parsedXML; 2204 OSSharedPtr<OSString> kextPath; 2205 2206 OSSharedPtr<OSString> errorString; 2207 OSSharedPtr<OSData> executable; 2208 2209 if (!super::init()) { 2210 goto finish; 2211 } 2212 2213 kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy(); 2214 if (!kextFileInfo) { 2215 OSKextLog(this, 2216 kOSKextLogErrorLevel | 2217 kOSKextLogGeneralFlag, 2218 "No booter-provided data for kext device tree entry %s.", 2219 deviceTreeName->getCStringNoCopy()); 2220 goto finish; 2221 } 2222 2223 /* The info plist must exist or we can't read the kext. 2224 */ 2225 if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) { 2226 OSKextLog(this, 2227 kOSKextLogErrorLevel | 2228 kOSKextLogGeneralFlag, 2229 "No kext info dictionary for booter device tree entry %s.", 2230 deviceTreeName->getCStringNoCopy()); 2231 goto finish; 2232 } 2233 2234 infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 2235 if (!infoDictAddr) { 2236 OSKextLog(this, 2237 kOSKextLogErrorLevel | 2238 kOSKextLogGeneralFlag, 2239 "Can't translate physical address 0x%x of kext info dictionary " 2240 "for device tree entry %s.", 2241 (int)kextFileInfo->infoDictPhysAddr, 2242 deviceTreeName->getCStringNoCopy()); 2243 goto finish; 2244 } 2245 2246 parsedXML = OSUnserializeXML(infoDictAddr, errorString); 2247 if (parsedXML) { 2248 theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 2249 } 2250 if (!theInfoDict) { 2251 const char * errorCString = "(unknown error)"; 2252 2253 if (errorString && errorString->getCStringNoCopy()) { 2254 errorCString = errorString->getCStringNoCopy(); 2255 } else if (parsedXML) { 2256 errorCString = "not a dictionary"; 2257 } 2258 OSKextLog(this, 2259 kOSKextLogErrorLevel | 2260 kOSKextLogGeneralFlag, 2261 "Error unserializing info dictionary for device tree entry %s: %s.", 2262 deviceTreeName->getCStringNoCopy(), errorCString); 2263 goto finish; 2264 } 2265 2266 /* A bundle path is not mandatory. 2267 */ 2268 if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) { 2269 bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr); 2270 if (!bundlePathAddr) { 2271 OSKextLog(this, 2272 kOSKextLogErrorLevel | 2273 kOSKextLogGeneralFlag, 2274 "Can't translate physical address 0x%x of kext bundle path " 2275 "for device tree entry %s.", 2276 (int)kextFileInfo->bundlePathPhysAddr, 2277 deviceTreeName->getCStringNoCopy()); 2278 goto finish; 2279 } 2280 bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0'; // just in case! 2281 2282 kextPath = OSString::withCString(bundlePathAddr); 2283 if (!kextPath) { 2284 OSKextLog(this, 2285 kOSKextLogErrorLevel | 2286 kOSKextLogGeneralFlag, 2287 "Failed to create wrapper for device tree entry %s kext path %s.", 2288 deviceTreeName->getCStringNoCopy(), bundlePathAddr); 2289 goto finish; 2290 } 2291 } 2292 2293 if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) { 2294 goto finish; 2295 } 2296 2297 /* An executable is not mandatory. 2298 */ 2299 if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) { 2300 executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr); 2301 if (!executableAddr) { 2302 OSKextLog(this, 2303 kOSKextLogErrorLevel | 2304 kOSKextLogGeneralFlag, 2305 "Can't translate physical address 0x%x of kext executable " 2306 "for device tree entry %s.", 2307 (int)kextFileInfo->executablePhysAddr, 2308 deviceTreeName->getCStringNoCopy()); 2309 goto finish; 2310 } 2311 2312 executable = OSData::withBytesNoCopy(executableAddr, 2313 kextFileInfo->executableLength); 2314 if (!executable) { 2315 OSKextLog(this, 2316 kOSKextLogErrorLevel | 2317 kOSKextLogGeneralFlag, 2318 "Failed to create executable wrapper for device tree entry %s.", 2319 deviceTreeName->getCStringNoCopy()); 2320 goto finish; 2321 } 2322 2323 /* A kext with an executable needs to retain the whole booterData 2324 * object to keep the executable in memory. 2325 */ 2326 if (!setExecutable(executable.get(), booterData)) { 2327 OSKextLog(this, 2328 kOSKextLogErrorLevel | 2329 kOSKextLogGeneralFlag, 2330 "Failed to set kext executable for device tree entry %s.", 2331 deviceTreeName->getCStringNoCopy()); 2332 goto finish; 2333 } 2334 } 2335 2336 result = registerIdentifier(); 2337 2338 finish: 2339 return result; 2340 } 2341 2342 /********************************************************************* 2343 *********************************************************************/ 2344 bool 2345 OSKext::registerIdentifier(void) 2346 { 2347 bool result = false; 2348 OSKext * existingKext = NULL; // do not release 2349 bool existingIsLoaded = false; 2350 bool existingIsPrelinked = false; 2351 bool existingIsCodeless = false; 2352 bool existingIsDext = false; 2353 OSKextVersion newVersion = -1; 2354 OSKextVersion existingVersion = -1; 2355 char newVersionCString[kOSKextVersionMaxLength]; 2356 char existingVersionCString[kOSKextVersionMaxLength]; 2357 OSSharedPtr<OSData> newUUID; 2358 OSSharedPtr<OSData> existingUUID; 2359 2360 IORecursiveLockLock(sKextLock); 2361 2362 /* Get the new kext's version for checks & log messages. 2363 */ 2364 newVersion = getVersion(); 2365 OSKextVersionGetString(newVersion, newVersionCString, 2366 kOSKextVersionMaxLength); 2367 2368 /* If we don't have an existing kext with this identifier, 2369 * just record the new kext and we're done! 2370 */ 2371 existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get())); 2372 if (!existingKext) { 2373 sKextsByID->setObject(bundleID.get(), this); 2374 result = true; 2375 goto finish; 2376 } 2377 2378 /* Get the existing kext's version for checks & log messages. 2379 */ 2380 existingVersion = existingKext->getVersion(); 2381 OSKextVersionGetString(existingVersion, 2382 existingVersionCString, kOSKextVersionMaxLength); 2383 2384 existingIsLoaded = existingKext->isLoaded(); 2385 existingIsPrelinked = existingKext->isPrelinked(); 2386 existingIsDext = existingKext->isDriverKit(); 2387 existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext; 2388 2389 /* If we have a non-codeless kext with this identifier that's already 2390 * loaded/prelinked, we can't use the new one, but let's be really 2391 * thorough and check how the two are related for a precise diagnostic 2392 * log message. 2393 * 2394 * This check is valid for kexts that declare an executable and for 2395 * dexts, but not for codeless kexts - we can just replace those. 2396 */ 2397 if ((!existingIsCodeless || existingIsDext) && 2398 (existingIsLoaded || existingIsPrelinked)) { 2399 bool sameVersion = (newVersion == existingVersion); 2400 bool sameExecutable = true; // assume true unless we have UUIDs 2401 2402 /* Only get the UUID if the existing kext is loaded. Doing so 2403 * might have to uncompress an mkext executable and we shouldn't 2404 * take that hit when neither kext is loaded. 2405 * 2406 * Note: there is no decompression that happens when all kexts 2407 * are loaded from kext collecitons. 2408 */ 2409 newUUID = copyUUID(); 2410 existingUUID = existingKext->copyUUID(); 2411 2412 if (existingIsDext && !isDriverKit()) { 2413 OSKextLog(this, 2414 kOSKextLogWarningLevel | 2415 kOSKextLogKextBookkeepingFlag, 2416 "Notice - new kext %s, v%s matches a %s dext" 2417 "with the same bundle ID, v%s.", 2418 getIdentifierCString(), newVersionCString, 2419 (existingIsLoaded ? "loaded" : "prelinked"), 2420 existingVersionCString); 2421 goto finish; 2422 } 2423 2424 /* I'm entirely too paranoid about checking equivalence of executables, 2425 * but I remember nasty problems with it in the past. 2426 * 2427 * - If we have UUIDs for both kexts, compare them. 2428 * - If only one kext has a UUID, they're definitely different. 2429 */ 2430 if (newUUID && existingUUID) { 2431 sameExecutable = newUUID->isEqualTo(existingUUID.get()); 2432 } else if (newUUID || existingUUID) { 2433 sameExecutable = false; 2434 } 2435 2436 if (!newUUID && !existingUUID) { 2437 /* If there are no UUIDs, we can't really tell that the executables 2438 * are *different* without a lot of work; the loaded kext's 2439 * unrelocated executable is no longer around (and we never had it 2440 * in-kernel for a prelinked kext). We certainly don't want to do 2441 * a whole fake link for the new kext just to compare, either. 2442 */ 2443 OSKextLog(this, 2444 kOSKextLogWarningLevel | 2445 kOSKextLogKextBookkeepingFlag, 2446 "Notice - new kext %s, v%s matches %s kext " 2447 "but can't determine if executables are the same (no UUIDs).", 2448 getIdentifierCString(), 2449 newVersionCString, 2450 (existingIsLoaded ? "loaded" : "prelinked")); 2451 } 2452 2453 if (sameVersion && sameExecutable) { 2454 OSKextLog(this, 2455 (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) | 2456 kOSKextLogKextBookkeepingFlag, 2457 "Refusing new kext %s, v%s: a %s copy is already present " 2458 "(same version and executable).", 2459 getIdentifierCString(), newVersionCString, 2460 (existingIsLoaded ? "loaded" : "prelinked")); 2461 } else { 2462 if (!sameVersion) { 2463 /* This condition is significant so log it under warnings. 2464 */ 2465 OSKextLog(this, 2466 kOSKextLogWarningLevel | 2467 kOSKextLogKextBookkeepingFlag, 2468 "Refusing new kext %s, v%s: already have %s v%s.", 2469 getIdentifierCString(), 2470 newVersionCString, 2471 (existingIsLoaded ? "loaded" : "prelinked"), 2472 existingVersionCString); 2473 } else { 2474 /* This condition is significant so log it under warnings. 2475 */ 2476 OSKextLog(this, 2477 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 2478 "Refusing new kext %s, v%s: a %s copy with a different " 2479 "executable UUID is already present.", 2480 getIdentifierCString(), newVersionCString, 2481 (existingIsLoaded ? "loaded" : "prelinked")); 2482 } 2483 } 2484 goto finish; 2485 } /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */ 2486 2487 /* Refuse to allow an existing loaded codeless kext be replaced by a 2488 * normal kext with the same bundle ID. 2489 */ 2490 if (existingIsCodeless && declaresExecutable()) { 2491 OSKextLog(this, 2492 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 2493 "Refusing new kext %s, v%s: a codeless copy is already %s", 2494 getIdentifierCString(), newVersionCString, 2495 (existingIsLoaded ? "loaded" : "prelinked")); 2496 goto finish; 2497 } 2498 2499 /* Dexts packaged in the BootKC will be protected against replacement 2500 * by non-dexts by the logic above which checks if they are prelinked. 2501 * Dexts which are prelinked into the System KC will be registered 2502 * before any other kexts in the AuxKC are registered, and we never 2503 * put dexts in the AuxKC. Therefore, there is no need to check if an 2504 * existing object is a dext and is being replaced by a non-dext. 2505 * The scenario cannot happen by construction. 2506 * 2507 * See: OSKext::loadFileSetKexts() 2508 */ 2509 2510 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether 2511 * user loads are happening or if we're still in early boot. User agents are 2512 * supposed to resolve dependencies topside and include only the exact 2513 * kexts needed; so we always accept the new kext (in fact we should never 2514 * see an older unloaded copy hanging around). 2515 */ 2516 if (sUserLoadsActive) { 2517 sKextsByID->setObject(bundleID.get(), this); 2518 result = true; 2519 2520 OSKextLog(this, 2521 kOSKextLogStepLevel | 2522 kOSKextLogKextBookkeepingFlag, 2523 "Dropping old copy of kext %s (v%s) for newly-added (v%s).", 2524 getIdentifierCString(), 2525 existingVersionCString, 2526 newVersionCString); 2527 2528 goto finish; 2529 } 2530 2531 /* During early boot, the kext with the highest version always wins out. 2532 * Prelinked kernels will never hit this, but mkexts and booter-read 2533 * kexts might have duplicates. 2534 */ 2535 if (newVersion > existingVersion) { 2536 sKextsByID->setObject(bundleID.get(), this); 2537 result = true; 2538 2539 OSKextLog(this, 2540 kOSKextLogStepLevel | 2541 kOSKextLogKextBookkeepingFlag, 2542 "Dropping lower version (v%s) of registered kext %s for higher (v%s).", 2543 existingVersionCString, 2544 getIdentifierCString(), 2545 newVersionCString); 2546 } else { 2547 OSKextLog(this, 2548 kOSKextLogStepLevel | 2549 kOSKextLogKextBookkeepingFlag, 2550 "Kext %s is already registered with a higher/same version (v%s); " 2551 "dropping newly-added (v%s).", 2552 getIdentifierCString(), 2553 existingVersionCString, 2554 newVersionCString); 2555 } 2556 2557 /* result has been set appropriately by now. */ 2558 2559 finish: 2560 2561 IORecursiveLockUnlock(sKextLock); 2562 2563 if (result) { 2564 OSKextLog(this, 2565 kOSKextLogStepLevel | 2566 kOSKextLogKextBookkeepingFlag, 2567 "Kext %s, v%s registered and available for loading.", 2568 getIdentifierCString(), newVersionCString); 2569 } 2570 2571 return result; 2572 } 2573 2574 /********************************************************************* 2575 * Does the bare minimum validation to look up a kext. 2576 * All other validation is done on the spot as needed. 2577 **********************************************************************/ 2578 bool 2579 OSKext::setInfoDictionaryAndPath( 2580 OSDictionary * aDictionary, 2581 OSString * aPath) 2582 { 2583 bool result = false; 2584 OSString * bundleIDString = NULL; // do not release 2585 OSString * versionString = NULL; // do not release 2586 OSString * compatibleVersionString = NULL; // do not release 2587 const char * versionCString = NULL; // do not free 2588 const char * compatibleVersionCString = NULL; // do not free 2589 OSBoolean * scratchBool = NULL; // do not release 2590 OSDictionary * scratchDict = NULL; // do not release 2591 2592 if (infoDict) { 2593 panic("Attempt to set info dictionary on a kext " 2594 "that already has one (%s).", 2595 getIdentifierCString()); 2596 } 2597 2598 if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) { 2599 goto finish; 2600 } 2601 2602 infoDict.reset(aDictionary, OSRetain); 2603 2604 /* Check right away if the info dictionary has any log flags. 2605 */ 2606 scratchBool = OSDynamicCast(OSBoolean, 2607 getPropertyForHostArch(kOSBundleEnableKextLoggingKey)); 2608 if (scratchBool == kOSBooleanTrue) { 2609 flags.loggingEnabled = 1; 2610 } 2611 2612 /* The very next thing to get is the bundle identifier. Unlike 2613 * in user space, a kext with no bundle identifier gets axed 2614 * immediately. 2615 */ 2616 bundleIDString = OSDynamicCast(OSString, 2617 getPropertyForHostArch(kCFBundleIdentifierKey)); 2618 if (!bundleIDString) { 2619 OSKextLog(this, 2620 kOSKextLogErrorLevel | 2621 kOSKextLogValidationFlag, 2622 "CFBundleIdentifier missing/invalid type in kext %s.", 2623 aPath ? aPath->getCStringNoCopy() : "(unknown)"); 2624 goto finish; 2625 } 2626 bundleID = OSSymbol::withString(bundleIDString); 2627 if (!bundleID) { 2628 OSKextLog(this, 2629 kOSKextLogErrorLevel | 2630 kOSKextLogValidationFlag, 2631 "Can't copy bundle identifier as symbol for kext %s.", 2632 bundleIDString->getCStringNoCopy()); 2633 goto finish; 2634 } 2635 2636 /* Save the path if we got one (it should always be available but it's 2637 * just something nice to have for bookkeeping). 2638 */ 2639 if (aPath) { 2640 path.reset(aPath, OSRetain); 2641 } 2642 2643 /***** 2644 * Minimal validation to initialize. We'll do other validation on the spot. 2645 */ 2646 if (bundleID->getLength() >= KMOD_MAX_NAME) { 2647 OSKextLog(this, 2648 kOSKextLogErrorLevel | 2649 kOSKextLogValidationFlag, 2650 "Kext %s error - CFBundleIdentifier over max length %d.", 2651 getIdentifierCString(), KMOD_MAX_NAME - 1); 2652 goto finish; 2653 } 2654 2655 version = compatibleVersion = -1; 2656 2657 versionString = OSDynamicCast(OSString, 2658 getPropertyForHostArch(kCFBundleVersionKey)); 2659 if (!versionString) { 2660 OSKextLog(this, 2661 kOSKextLogErrorLevel | 2662 kOSKextLogValidationFlag, 2663 "Kext %s error - CFBundleVersion missing/invalid type.", 2664 getIdentifierCString()); 2665 goto finish; 2666 } 2667 versionCString = versionString->getCStringNoCopy(); 2668 version = OSKextParseVersionString(versionCString); 2669 if (version < 0) { 2670 OSKextLog(this, 2671 kOSKextLogErrorLevel | 2672 kOSKextLogValidationFlag, 2673 "Kext %s error - CFBundleVersion bad value '%s'.", 2674 getIdentifierCString(), versionCString); 2675 goto finish; 2676 } 2677 2678 compatibleVersion = -1; // set to illegal value for kexts that don't have 2679 2680 compatibleVersionString = OSDynamicCast(OSString, 2681 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 2682 if (compatibleVersionString) { 2683 compatibleVersionCString = compatibleVersionString->getCStringNoCopy(); 2684 compatibleVersion = OSKextParseVersionString(compatibleVersionCString); 2685 if (compatibleVersion < 0) { 2686 OSKextLog(this, 2687 kOSKextLogErrorLevel | 2688 kOSKextLogValidationFlag, 2689 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.", 2690 getIdentifierCString(), compatibleVersionCString); 2691 goto finish; 2692 } 2693 2694 if (compatibleVersion > version) { 2695 OSKextLog(this, 2696 kOSKextLogErrorLevel | 2697 kOSKextLogValidationFlag, 2698 "Kext %s error - %s %s > %s %s (must be <=).", 2699 getIdentifierCString(), 2700 kOSBundleCompatibleVersionKey, compatibleVersionCString, 2701 kCFBundleVersionKey, versionCString); 2702 goto finish; 2703 } 2704 } 2705 2706 /* Check to see if this kext is in exclude list */ 2707 if (isInExcludeList()) { 2708 OSKextLog(this, 2709 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 2710 "Kext %s is in exclude list, not loadable", 2711 getIdentifierCString()); 2712 goto finish; 2713 } 2714 2715 /* Set flags for later use if the infoDict gets flushed. We only 2716 * check for true values, not false ones(!) 2717 */ 2718 scratchBool = OSDynamicCast(OSBoolean, 2719 getPropertyForHostArch(kOSBundleIsInterfaceKey)); 2720 if (scratchBool == kOSBooleanTrue) { 2721 flags.interface = 1; 2722 } 2723 2724 scratchBool = OSDynamicCast(OSBoolean, 2725 getPropertyForHostArch(kOSKernelResourceKey)); 2726 if (scratchBool == kOSBooleanTrue) { 2727 flags.kernelComponent = 1; 2728 flags.interface = 1; // xxx - hm. the kernel itself isn't an interface... 2729 flags.started = 1; 2730 2731 /* A kernel component has one implicit dependency on the kernel. 2732 */ 2733 flags.hasAllDependencies = 1; 2734 } 2735 2736 /* Make sure common string values in personalities are uniqued to OSSymbols. 2737 */ 2738 scratchDict = OSDynamicCast(OSDictionary, 2739 getPropertyForHostArch(kIOKitPersonalitiesKey)); 2740 if (scratchDict) { 2741 uniquePersonalityProperties(scratchDict); 2742 } 2743 2744 result = true; 2745 2746 finish: 2747 2748 return result; 2749 } 2750 2751 /********************************************************************* 2752 * Not used for prelinked kernel boot as there is no unrelocated 2753 * executable. 2754 *********************************************************************/ 2755 bool 2756 OSKext::setExecutable( 2757 OSData * anExecutable, 2758 OSData * externalData, 2759 bool externalDataIsMkext) 2760 { 2761 bool result = false; 2762 const char * executableKey = NULL; // do not free 2763 2764 if (!anExecutable) { 2765 infoDict->removeObject(_kOSKextExecutableKey); 2766 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 2767 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 2768 result = true; 2769 goto finish; 2770 } 2771 2772 if (infoDict->getObject(_kOSKextExecutableKey) || 2773 infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) { 2774 panic("Attempt to set an executable on a kext " 2775 "that already has one (%s).", 2776 getIdentifierCString()); 2777 goto finish; 2778 } 2779 2780 if (externalDataIsMkext) { 2781 executableKey = _kOSKextMkextExecutableReferenceKey; 2782 } else { 2783 executableKey = _kOSKextExecutableKey; 2784 } 2785 2786 if (anExecutable) { 2787 infoDict->setObject(executableKey, anExecutable); 2788 if (externalData) { 2789 infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData); 2790 } 2791 } 2792 2793 result = true; 2794 2795 finish: 2796 return result; 2797 } 2798 2799 /********************************************************************* 2800 *********************************************************************/ 2801 static void 2802 uniqueStringPlistProperty(OSDictionary * dict, const char * key) 2803 { 2804 OSObject * value = NULL; // do not release 2805 OSString * stringValue = NULL; // do not release 2806 OSSharedPtr<const OSSymbol> symbolValue; 2807 2808 value = dict->getObject(key); 2809 if (!value) { 2810 goto finish; 2811 } 2812 if (OSDynamicCast(OSSymbol, value)) { 2813 /* this is already an OSSymbol: we're good */ 2814 goto finish; 2815 } 2816 2817 stringValue = OSDynamicCast(OSString, value); 2818 if (!stringValue) { 2819 goto finish; 2820 } 2821 2822 symbolValue = OSSymbol::withString(stringValue); 2823 if (!symbolValue) { 2824 goto finish; 2825 } 2826 2827 dict->setObject(key, symbolValue.get()); 2828 2829 finish: 2830 return; 2831 } 2832 2833 /********************************************************************* 2834 *********************************************************************/ 2835 static void 2836 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key) 2837 { 2838 OSObject * value = NULL; // do not release 2839 OSString * stringValue = NULL; // do not release 2840 OSSharedPtr<const OSSymbol> symbolValue; 2841 2842 value = dict->getObject(key); 2843 if (!value) { 2844 goto finish; 2845 } 2846 if (OSDynamicCast(OSSymbol, value)) { 2847 /* this is already an OSSymbol: we're good */ 2848 goto finish; 2849 } 2850 2851 stringValue = OSDynamicCast(OSString, value); 2852 if (!stringValue) { 2853 goto finish; 2854 } 2855 2856 symbolValue = OSSymbol::withString(stringValue); 2857 if (!symbolValue) { 2858 goto finish; 2859 } 2860 2861 dict->setObject(key, symbolValue.get()); 2862 2863 finish: 2864 return; 2865 } 2866 2867 void 2868 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict) 2869 { 2870 OSKext::uniquePersonalityProperties(personalityDict, true); 2871 } 2872 2873 /********************************************************************* 2874 * Replace common personality property values with uniqued instances 2875 * to save on wired memory. 2876 *********************************************************************/ 2877 /* static */ 2878 void 2879 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier) 2880 { 2881 /* Properties every personality has. 2882 */ 2883 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey); 2884 uniqueStringPlistProperty(personalityDict, kIOProviderClassKey); 2885 uniqueStringPlistProperty(personalityDict, gIOClassKey.get()); 2886 if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) { 2887 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey); 2888 } else if (defaultAddKernelBundleIdentifier) { 2889 personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey)); 2890 } 2891 2892 /* Other commonly used properties. 2893 */ 2894 uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey); 2895 uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey); 2896 uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey); 2897 2898 uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior"); 2899 uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType"); 2900 uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType"); 2901 uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType"); 2902 uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher"); 2903 uniqueStringPlistProperty(personalityDict, "Physical Interconnect"); 2904 uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location"); 2905 uniqueStringPlistProperty(personalityDict, "Vendor"); 2906 uniqueStringPlistProperty(personalityDict, "Vendor Identification"); 2907 uniqueStringPlistProperty(personalityDict, "Vendor Name"); 2908 uniqueStringPlistProperty(personalityDict, "bConfigurationValue"); 2909 uniqueStringPlistProperty(personalityDict, "bInterfaceNumber"); 2910 uniqueStringPlistProperty(personalityDict, "idProduct"); 2911 2912 return; 2913 } 2914 2915 /********************************************************************* 2916 *********************************************************************/ 2917 void 2918 OSKext::free(void) 2919 { 2920 if (isLoaded()) { 2921 panic("Attempt to free loaded kext %s.", getIdentifierCString()); 2922 } 2923 2924 infoDict.reset(); 2925 bundleID.reset(); 2926 path.reset(); 2927 executableRelPath.reset(); 2928 userExecutableRelPath.reset(); 2929 dependencies.reset(); 2930 linkedExecutable.reset(); 2931 metaClasses.reset(); 2932 interfaceUUID.reset(); 2933 driverKitUUID.reset(); 2934 2935 if (isInterface() && kmod_info) { 2936 kfree_type(kmod_info_t, kmod_info); 2937 } 2938 2939 super::free(); 2940 return; 2941 } 2942 2943 #if PRAGMA_MARK 2944 #pragma mark Mkext files 2945 #endif 2946 2947 #if CONFIG_KXLD 2948 /* 2949 * mkext archives are really only relevant on kxld-enabled kernels. 2950 * Without a dynamic kernel linker, we don't need to support any mkexts. 2951 */ 2952 2953 /********************************************************************* 2954 *********************************************************************/ 2955 OSReturn 2956 OSKext::readMkextArchive(OSData * mkextData, 2957 uint32_t * checksumPtr) 2958 { 2959 OSReturn result = kOSKextReturnBadData; 2960 uint32_t mkextLength = 0; 2961 mkext_header * mkextHeader = NULL; // do not free 2962 uint32_t mkextVersion = 0; 2963 2964 /* Note default return of kOSKextReturnBadData above. 2965 */ 2966 mkextLength = mkextData->getLength(); 2967 if (mkextLength < sizeof(mkext_basic_header)) { 2968 OSKextLog(/* kext */ NULL, 2969 kOSKextLogErrorLevel | 2970 kOSKextLogArchiveFlag, 2971 "Mkext archive too small to be valid."); 2972 goto finish; 2973 } 2974 2975 mkextHeader = (mkext_header *)mkextData->getBytesNoCopy(); 2976 2977 if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC || 2978 MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) { 2979 OSKextLog(/* kext */ NULL, 2980 kOSKextLogErrorLevel | 2981 kOSKextLogArchiveFlag, 2982 "Mkext archive has invalid magic or signature."); 2983 goto finish; 2984 } 2985 2986 if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) { 2987 OSKextLog(/* kext */ NULL, 2988 kOSKextLogErrorLevel | 2989 kOSKextLogArchiveFlag, 2990 "Mkext archive recorded length doesn't match actual file length."); 2991 goto finish; 2992 } 2993 2994 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 2995 2996 if (mkextVersion == MKEXT_VERS_2) { 2997 result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr); 2998 } else { 2999 OSKextLog(/* kext */ NULL, 3000 kOSKextLogErrorLevel | 3001 kOSKextLogArchiveFlag, 3002 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion); 3003 result = kOSKextReturnUnsupported; 3004 } 3005 3006 finish: 3007 return result; 3008 } 3009 3010 /********************************************************************* 3011 * Assumes magic, signature, version, length have been checked. 3012 * xxx - need to add further bounds checking for each file entry 3013 * 3014 * Should keep track of all kexts created so far, and if we hit a 3015 * fatal error halfway through, remove those kexts. If we've dropped 3016 * an older version that had already been read, whoops! Might want to 3017 * add a level of buffering? 3018 *********************************************************************/ 3019 /* static */ 3020 OSReturn 3021 OSKext::readMkext2Archive( 3022 OSData * mkextData, 3023 OSDictionary ** mkextPlistOut, 3024 uint32_t * checksumPtr) 3025 { 3026 OSReturn result = kOSReturnError; 3027 uint32_t mkextLength; 3028 mkext2_header * mkextHeader = NULL; // do not free 3029 void * mkextEnd = NULL; // do not free 3030 uint32_t mkextVersion; 3031 uint8_t * crc_address = NULL; 3032 size_t crc_buffer_size = 0; 3033 uint32_t checksum; 3034 uint32_t mkextPlistOffset; 3035 uint32_t mkextPlistCompressedSize; 3036 char * mkextPlistEnd = NULL; // do not free 3037 uint32_t mkextPlistFullSize; 3038 OSSharedPtr<OSString> errorString; 3039 OSSharedPtr<OSData> mkextPlistUncompressedData; 3040 const char * mkextPlistDataBuffer = NULL; // do not free 3041 OSSharedPtr<OSObject> parsedXML; 3042 OSDictionary * mkextPlist = NULL; // do not release 3043 OSArray * mkextInfoDictArray = NULL; // do not release 3044 uint32_t count, i; 3045 kc_format_t kc_format; 3046 3047 if (!PE_get_primary_kc_format(&kc_format)) { 3048 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 3049 "Unable to determine primary KC format"); 3050 goto finish; 3051 } 3052 3053 mkextLength = mkextData->getLength(); 3054 mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy(); 3055 mkextEnd = (char *)mkextHeader + mkextLength; 3056 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 3057 3058 crc_address = (u_int8_t *)&mkextHeader->version; 3059 crc_buffer_size = (uintptr_t)mkextHeader + 3060 MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address; 3061 if (crc_buffer_size > INT32_MAX) { 3062 OSKextLog(/* kext */ NULL, 3063 kOSKextLogErrorLevel | 3064 kOSKextLogArchiveFlag, 3065 "Mkext archive size is too large (%lu > INT32_MAX).", 3066 crc_buffer_size); 3067 result = kOSKextReturnBadData; 3068 goto finish; 3069 } 3070 checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size); 3071 3072 if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) { 3073 OSKextLog(/* kext */ NULL, 3074 kOSKextLogErrorLevel | 3075 kOSKextLogArchiveFlag, 3076 "Mkext archive has bad checksum."); 3077 result = kOSKextReturnBadData; 3078 goto finish; 3079 } 3080 3081 if (checksumPtr) { 3082 *checksumPtr = checksum; 3083 } 3084 3085 /* Check that the CPU type & subtype match that of the running kernel. */ 3086 if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) { 3087 OSKextLog(/* kext */ NULL, 3088 kOSKextLogErrorLevel | 3089 kOSKextLogArchiveFlag, 3090 "Mkext archive must have a specific CPU type."); 3091 result = kOSKextReturnBadData; 3092 goto finish; 3093 } else { 3094 if ((UInt32)_mh_execute_header.cputype != 3095 MKEXT_GET_CPUTYPE(mkextHeader)) { 3096 OSKextLog(/* kext */ NULL, 3097 kOSKextLogErrorLevel | 3098 kOSKextLogArchiveFlag, 3099 "Mkext archive does not match the running kernel's CPU type."); 3100 result = kOSKextReturnArchNotFound; 3101 goto finish; 3102 } 3103 } 3104 3105 mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader); 3106 mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader); 3107 mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset + 3108 mkextPlistCompressedSize; 3109 if (mkextPlistEnd > mkextEnd) { 3110 OSKextLog(/* kext */ NULL, 3111 kOSKextLogErrorLevel | 3112 kOSKextLogArchiveFlag, 3113 "Mkext archive file overrun."); 3114 result = kOSKextReturnBadData; 3115 } 3116 3117 mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader); 3118 if (mkextPlistCompressedSize) { 3119 mkextPlistUncompressedData = sKernelKext->extractMkext2FileData( 3120 (UInt8 *)mkextHeader + mkextPlistOffset, 3121 "plist", 3122 mkextPlistCompressedSize, mkextPlistFullSize); 3123 if (!mkextPlistUncompressedData) { 3124 goto finish; 3125 } 3126 mkextPlistDataBuffer = (const char *) 3127 mkextPlistUncompressedData->getBytesNoCopy(); 3128 } else { 3129 mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset; 3130 } 3131 3132 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it. 3133 */ 3134 parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString); 3135 if (parsedXML) { 3136 mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get()); 3137 } 3138 if (!mkextPlist) { 3139 const char * errorCString = "(unknown error)"; 3140 3141 if (errorString && errorString->getCStringNoCopy()) { 3142 errorCString = errorString->getCStringNoCopy(); 3143 } else if (parsedXML) { 3144 errorCString = "not a dictionary"; 3145 } 3146 OSKextLog(/* kext */ NULL, 3147 kOSKextLogErrorLevel | 3148 kOSKextLogArchiveFlag, 3149 "Error unserializing mkext plist: %s.", errorCString); 3150 goto finish; 3151 } 3152 3153 mkextInfoDictArray = OSDynamicCast(OSArray, 3154 mkextPlist->getObject(kMKEXTInfoDictionariesKey)); 3155 if (!mkextInfoDictArray) { 3156 OSKextLog(/* kext */ NULL, 3157 kOSKextLogErrorLevel | 3158 kOSKextLogArchiveFlag, 3159 "Mkext archive contains no kext info dictionaries."); 3160 goto finish; 3161 } 3162 3163 count = mkextInfoDictArray->getCount(); 3164 for (i = 0; i < count; i++) { 3165 OSDictionary * infoDict; 3166 3167 3168 infoDict = OSDynamicCast(OSDictionary, 3169 mkextInfoDictArray->getObject(i)); 3170 3171 /* Create the kext for the entry, then release it, because the 3172 * kext system keeps them around until explicitly removed. 3173 * Any creation/registration failures are already logged for us. 3174 */ 3175 if (infoDict) { 3176 OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData); 3177 3178 /* Fail dynamic loading of a kext when booted from MH_FILESET */ 3179 if (kc_format == KCFormatFileset && 3180 newKext && 3181 !(newKext->isPrelinked()) && 3182 newKext->declaresExecutable()) { 3183 result = kOSReturnError; 3184 printf("Kext LOG: Dynamic loading of kext denied for kext %s\n", 3185 newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext"); 3186 3187 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 3188 "Dynamic loading of kext denied for kext %s\n", 3189 newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext"); 3190 goto finish; 3191 } 3192 } 3193 } 3194 3195 /* If the caller needs the plist, hand them back our copy 3196 */ 3197 if (mkextPlistOut) { 3198 *mkextPlistOut = mkextPlist; 3199 parsedXML.detach(); 3200 } 3201 3202 /* Even if we didn't keep any kexts from the mkext, we may have a load 3203 * request to process, so we are successful (no errors occurred). 3204 */ 3205 result = kOSReturnSuccess; 3206 3207 finish: 3208 return result; 3209 } 3210 3211 /* static */ 3212 OSReturn 3213 OSKext::readMkext2Archive( 3214 OSData * mkextData, 3215 OSSharedPtr<OSDictionary> &mkextPlistOut, 3216 uint32_t * checksumPtr) 3217 { 3218 OSDictionary * mkextPlist = NULL; 3219 OSReturn ret; 3220 3221 if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData, 3222 &mkextPlist, 3223 checksumPtr))) { 3224 mkextPlistOut.reset(mkextPlist, OSNoRetain); 3225 } 3226 return ret; 3227 } 3228 3229 /********************************************************************* 3230 *********************************************************************/ 3231 /* static */ 3232 OSSharedPtr<OSKext> 3233 OSKext::withMkext2Info( 3234 OSDictionary * anInfoDict, 3235 OSData * mkextData) 3236 { 3237 OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>(); 3238 3239 if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) { 3240 return NULL; 3241 } 3242 3243 return newKext; 3244 } 3245 3246 /********************************************************************* 3247 *********************************************************************/ 3248 bool 3249 OSKext::initWithMkext2Info( 3250 OSDictionary * anInfoDict, 3251 OSData * mkextData) 3252 { 3253 bool result = false; 3254 OSString * kextPath = NULL; // do not release 3255 OSNumber * executableOffsetNum = NULL; // do not release 3256 OSSharedPtr<OSData> executable; 3257 3258 if (anInfoDict == NULL || !super::init()) { 3259 goto finish; 3260 } 3261 3262 /* Get the path. Don't look for an arch-specific path property. 3263 */ 3264 kextPath = OSDynamicCast(OSString, 3265 anInfoDict->getObject(kMKEXTBundlePathKey)); 3266 3267 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 3268 goto finish; 3269 } 3270 3271 /* If we have a path to the executable, save it. 3272 */ 3273 executableRelPath.reset(OSDynamicCast(OSString, 3274 anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain); 3275 3276 /* Don't need the paths to be in the info dictionary any more. 3277 */ 3278 anInfoDict->removeObject(kMKEXTBundlePathKey); 3279 anInfoDict->removeObject(kMKEXTExecutableRelativePathKey); 3280 3281 executableOffsetNum = OSDynamicCast(OSNumber, 3282 infoDict->getObject(kMKEXTExecutableKey)); 3283 if (executableOffsetNum) { 3284 executable = createMkext2FileEntry(mkextData, 3285 executableOffsetNum, "executable"); 3286 infoDict->removeObject(kMKEXTExecutableKey); 3287 if (!executable) { 3288 goto finish; 3289 } 3290 if (!setExecutable(executable.get(), mkextData, true)) { 3291 goto finish; 3292 } 3293 } 3294 3295 result = registerIdentifier(); 3296 3297 finish: 3298 return result; 3299 } 3300 3301 /********************************************************************* 3302 *********************************************************************/ 3303 OSSharedPtr<OSData> 3304 OSKext::createMkext2FileEntry( 3305 OSData * mkextData, 3306 OSNumber * offsetNum, 3307 const char * name) 3308 { 3309 OSSharedPtr<OSData> result; 3310 MkextEntryRef entryRef; 3311 uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy(); 3312 uint32_t entryOffset = offsetNum->unsigned32BitValue(); 3313 3314 result = OSData::withCapacity(sizeof(entryRef)); 3315 if (!result) { 3316 goto finish; 3317 } 3318 3319 entryRef.mkext = (mkext_basic_header *)mkextBuffer; 3320 entryRef.fileinfo = mkextBuffer + entryOffset; 3321 if (!result->appendBytes(&entryRef, sizeof(entryRef))) { 3322 result.reset(); 3323 goto finish; 3324 } 3325 3326 finish: 3327 if (!result) { 3328 OSKextLog(this, 3329 kOSKextLogErrorLevel | 3330 kOSKextLogArchiveFlag, 3331 "Can't create wrapper for mkext file entry '%s' of kext %s.", 3332 name, getIdentifierCString()); 3333 } 3334 return result; 3335 } 3336 3337 /********************************************************************* 3338 *********************************************************************/ 3339 extern "C" { 3340 static void * z_alloc(void *, u_int items, u_int size); 3341 static void z_free(void *, void *ptr); 3342 3343 typedef struct z_mem { 3344 uint32_t alloc_size; 3345 uint8_t data[0]; 3346 } z_mem; 3347 3348 /* 3349 * Space allocation and freeing routines for use by zlib routines. 3350 */ 3351 void * 3352 z_alloc(void * notused __unused, u_int num_items, u_int size) 3353 { 3354 void * result = NULL; 3355 z_mem * zmem = NULL; 3356 3357 uint64_t total = ((uint64_t)num_items) * ((uint64_t)size); 3358 //Check for overflow due to multiplication 3359 if (total > UINT32_MAX) { 3360 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x", 3361 notused, num_items, size, num_items, size); 3362 } 3363 3364 uint64_t allocSize64 = total + ((uint64_t)sizeof(zmem)); 3365 //Check for overflow due to addition 3366 if (allocSize64 > UINT32_MAX) { 3367 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx", 3368 notused, num_items, size, (uint32_t)total, sizeof(zmem)); 3369 } 3370 uint32_t allocSize = (uint32_t)allocSize64; 3371 3372 zmem = (z_mem *)kheap_alloc_tag(KHEAP_DATA_BUFFERS, allocSize, 3373 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 3374 if (!zmem) { 3375 goto finish; 3376 } 3377 zmem->alloc_size = allocSize; 3378 result = (void *)&(zmem->data); 3379 finish: 3380 return result; 3381 } 3382 3383 void 3384 z_free(void * notused __unused, void * ptr) 3385 { 3386 uint32_t * skipper = (uint32_t *)ptr - 1; 3387 z_mem * zmem = (z_mem *)skipper; 3388 kheap_free(KHEAP_DATA_BUFFERS, zmem, zmem->alloc_size); 3389 return; 3390 } 3391 }; 3392 3393 OSSharedPtr<OSData> 3394 OSKext::extractMkext2FileData( 3395 UInt8 * data, 3396 const char * name, 3397 uint32_t compressedSize, 3398 uint32_t fullSize) 3399 { 3400 OSSharedPtr<OSData> result; 3401 OSSharedPtr<OSData> uncompressedData; // release on error 3402 3403 uint8_t * uncompressedDataBuffer = NULL; // do not free 3404 unsigned long uncompressedSize; 3405 z_stream zstream; 3406 bool zstream_inited = false; 3407 int zlib_result; 3408 3409 /* If the file isn't compressed, we want to make a copy 3410 * so that we don't have the tie to the larger mkext file buffer any more. 3411 */ 3412 if (!compressedSize) { 3413 uncompressedData = OSData::withBytes(data, fullSize); 3414 // xxx - no check for failure? 3415 result = uncompressedData; 3416 goto finish; 3417 } 3418 3419 if (KERN_SUCCESS != kmem_alloc(kernel_map, 3420 (vm_offset_t*)&uncompressedDataBuffer, fullSize, VM_KERN_MEMORY_OSKEXT)) { 3421 /* How's this for cheesy? The kernel is only asked to extract 3422 * kext plists so we tailor the log messages. 3423 */ 3424 if (isKernel()) { 3425 OSKextLog(this, 3426 kOSKextLogErrorLevel | 3427 kOSKextLogArchiveFlag, 3428 "Allocation failure extracting %s from mkext.", name); 3429 } else { 3430 OSKextLog(this, 3431 kOSKextLogErrorLevel | 3432 kOSKextLogArchiveFlag, 3433 "Allocation failure extracting %s from mkext for kext %s.", 3434 name, getIdentifierCString()); 3435 } 3436 3437 goto finish; 3438 } 3439 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize); 3440 if (!uncompressedData) { 3441 if (isKernel()) { 3442 OSKextLog(this, 3443 kOSKextLogErrorLevel | 3444 kOSKextLogArchiveFlag, 3445 "Allocation failure extracting %s from mkext.", name); 3446 } else { 3447 OSKextLog(this, 3448 kOSKextLogErrorLevel | 3449 kOSKextLogArchiveFlag, 3450 "Allocation failure extracting %s from mkext for kext %s.", 3451 name, getIdentifierCString()); 3452 } 3453 goto finish; 3454 } 3455 uncompressedData->setDeallocFunction(&osdata_kmem_free); 3456 3457 if (isKernel()) { 3458 OSKextLog(this, 3459 kOSKextLogDetailLevel | 3460 kOSKextLogArchiveFlag, 3461 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.", 3462 name, compressedSize, fullSize); 3463 } else { 3464 OSKextLog(this, 3465 kOSKextLogDetailLevel | 3466 kOSKextLogArchiveFlag, 3467 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.", 3468 getIdentifierCString(), name, compressedSize, fullSize); 3469 } 3470 3471 bzero(&zstream, sizeof(zstream)); 3472 zstream.next_in = (UInt8 *)data; 3473 zstream.avail_in = compressedSize; 3474 3475 zstream.next_out = uncompressedDataBuffer; 3476 zstream.avail_out = fullSize; 3477 3478 zstream.zalloc = z_alloc; 3479 zstream.zfree = z_free; 3480 3481 zlib_result = inflateInit(&zstream); 3482 if (Z_OK != zlib_result) { 3483 if (isKernel()) { 3484 OSKextLog(this, 3485 kOSKextLogErrorLevel | 3486 kOSKextLogArchiveFlag, 3487 "Mkext error; zlib inflateInit failed (%d) for %s.", 3488 zlib_result, name); 3489 } else { 3490 OSKextLog(this, 3491 kOSKextLogErrorLevel | 3492 kOSKextLogArchiveFlag, 3493 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .", 3494 getIdentifierCString(), zlib_result, name); 3495 } 3496 goto finish; 3497 } else { 3498 zstream_inited = true; 3499 } 3500 3501 zlib_result = inflate(&zstream, Z_FINISH); 3502 3503 if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) { 3504 uncompressedSize = zstream.total_out; 3505 } else { 3506 if (isKernel()) { 3507 OSKextLog(this, 3508 kOSKextLogErrorLevel | 3509 kOSKextLogArchiveFlag, 3510 "Mkext error; zlib inflate failed (%d) for %s.", 3511 zlib_result, name); 3512 } else { 3513 OSKextLog(this, 3514 kOSKextLogErrorLevel | 3515 kOSKextLogArchiveFlag, 3516 "Kext %s - mkext error; zlib inflate failed (%d) for %s .", 3517 getIdentifierCString(), zlib_result, name); 3518 } 3519 if (zstream.msg) { 3520 OSKextLog(this, 3521 kOSKextLogErrorLevel | 3522 kOSKextLogArchiveFlag, 3523 "zlib error: %s.", zstream.msg); 3524 } 3525 goto finish; 3526 } 3527 3528 if (uncompressedSize != fullSize) { 3529 if (isKernel()) { 3530 OSKextLog(this, 3531 kOSKextLogErrorLevel | 3532 kOSKextLogArchiveFlag, 3533 "Mkext error; zlib inflate discrepancy for %s, " 3534 "uncompressed size != original size.", name); 3535 } else { 3536 OSKextLog(this, 3537 kOSKextLogErrorLevel | 3538 kOSKextLogArchiveFlag, 3539 "Kext %s - mkext error; zlib inflate discrepancy for %s, " 3540 "uncompressed size != original size.", 3541 getIdentifierCString(), name); 3542 } 3543 goto finish; 3544 } 3545 3546 result = os::move(uncompressedData); 3547 3548 finish: 3549 /* Don't bother checking return, nothing we can do on fail. 3550 */ 3551 if (zstream_inited) { 3552 inflateEnd(&zstream); 3553 } 3554 3555 return result; 3556 } 3557 3558 /********************************************************************* 3559 *********************************************************************/ 3560 /* static */ 3561 OSReturn 3562 OSKext::loadFromMkext( 3563 OSKextLogSpec clientLogFilter, 3564 char * mkextBuffer, 3565 uint32_t mkextBufferLength, 3566 char ** logInfoOut, 3567 uint32_t * logInfoLengthOut) 3568 { 3569 OSReturn result = kOSReturnError; 3570 OSReturn tempResult = kOSReturnError; 3571 3572 OSSharedPtr<OSData> mkextData; 3573 OSSharedPtr<OSDictionary> mkextPlist; 3574 3575 OSSharedPtr<OSArray> logInfoArray; 3576 OSSharedPtr<OSSerialize> serializer; 3577 3578 OSString * predicate = NULL; // do not release 3579 OSDictionary * requestArgs = NULL; // do not release 3580 3581 OSString * kextIdentifier = NULL; // do not release 3582 OSNumber * startKextExcludeNum = NULL; // do not release 3583 OSNumber * startMatchingExcludeNum = NULL; // do not release 3584 OSBoolean * delayAutounloadBool = NULL; // do not release 3585 OSArray * personalityNames = NULL; // do not release 3586 3587 /* Default values for these two options: regular autounload behavior, 3588 * load all kexts, send no personalities. 3589 */ 3590 Boolean delayAutounload = false; 3591 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 3592 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll; 3593 3594 IORecursiveLockLock(sKextLock); 3595 3596 if (logInfoOut) { 3597 *logInfoOut = NULL; 3598 *logInfoLengthOut = 0; 3599 } 3600 3601 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 3602 3603 OSKextLog(/* kext */ NULL, 3604 kOSKextLogDebugLevel | 3605 kOSKextLogIPCFlag, 3606 "Received kext load request from user space."); 3607 3608 /* Regardless of processing, the fact that we have gotten here means some 3609 * user-space program is up and talking to us, so we'll switch our kext 3610 * registration to reflect that. 3611 */ 3612 if (!sUserLoadsActive) { 3613 OSKextLog(/* kext */ NULL, 3614 kOSKextLogProgressLevel | 3615 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 3616 "Switching to late startup (user-space) kext loading policy."); 3617 3618 sUserLoadsActive = true; 3619 } 3620 3621 if (!sLoadEnabled) { 3622 OSKextLog(/* kext */ NULL, 3623 kOSKextLogErrorLevel | 3624 kOSKextLogLoadFlag, 3625 "Kext loading is disabled."); 3626 result = kOSKextReturnDisabled; 3627 goto finish; 3628 } 3629 3630 /* Note that we do not set a dealloc function on this OSData 3631 * object! No references to it can remain after the loadFromMkext() 3632 * call since we are in a MIG function, and will vm_deallocate() 3633 * the buffer. 3634 */ 3635 mkextData = OSData::withBytesNoCopy(mkextBuffer, 3636 mkextBufferLength); 3637 if (!mkextData) { 3638 OSKextLog(/* kext */ NULL, 3639 kOSKextLogErrorLevel | 3640 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 3641 "Failed to create wrapper for kext load request."); 3642 result = kOSKextReturnNoMemory; 3643 goto finish; 3644 } 3645 3646 result = readMkext2Archive(mkextData.get(), mkextPlist, NULL); 3647 if (result != kOSReturnSuccess) { 3648 OSKextLog(/* kext */ NULL, 3649 kOSKextLogErrorLevel | 3650 kOSKextLogLoadFlag, 3651 "Failed to read kext load request."); 3652 goto finish; 3653 } 3654 3655 predicate = _OSKextGetRequestPredicate(mkextPlist.get()); 3656 if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) { 3657 OSKextLog(/* kext */ NULL, 3658 kOSKextLogErrorLevel | 3659 kOSKextLogLoadFlag, 3660 "Received kext load request with no predicate; skipping."); 3661 result = kOSKextReturnInvalidArgument; 3662 goto finish; 3663 } 3664 3665 requestArgs = OSDynamicCast(OSDictionary, 3666 mkextPlist->getObject(kKextRequestArgumentsKey)); 3667 if (!requestArgs || !requestArgs->getCount()) { 3668 OSKextLog(/* kext */ NULL, 3669 kOSKextLogErrorLevel | 3670 kOSKextLogLoadFlag, 3671 "Received kext load request with no arguments."); 3672 result = kOSKextReturnInvalidArgument; 3673 goto finish; 3674 } 3675 3676 kextIdentifier = OSDynamicCast(OSString, 3677 requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey)); 3678 3679 if (!kextIdentifier) { 3680 OSKextLog(/* kext */ NULL, 3681 kOSKextLogErrorLevel | 3682 kOSKextLogLoadFlag, 3683 "Received kext load request with no kext identifier."); 3684 result = kOSKextReturnInvalidArgument; 3685 goto finish; 3686 } 3687 3688 startKextExcludeNum = OSDynamicCast(OSNumber, 3689 requestArgs->getObject(kKextRequestArgumentStartExcludeKey)); 3690 startMatchingExcludeNum = OSDynamicCast(OSNumber, 3691 requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey)); 3692 delayAutounloadBool = OSDynamicCast(OSBoolean, 3693 requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey)); 3694 personalityNames = OSDynamicCast(OSArray, 3695 requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey)); 3696 3697 if (delayAutounloadBool) { 3698 delayAutounload = delayAutounloadBool->getValue(); 3699 } 3700 if (startKextExcludeNum) { 3701 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 3702 } 3703 if (startMatchingExcludeNum) { 3704 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 3705 } 3706 3707 OSKextLog(/* kext */ NULL, 3708 kOSKextLogProgressLevel | 3709 kOSKextLogIPCFlag, 3710 "Received request from user space to load kext %s.", 3711 kextIdentifier->getCStringNoCopy()); 3712 3713 /* Load the kext, with no deferral, since this is a load from outside 3714 * the kernel. 3715 * xxx - Would like a better way to handle the default values for the 3716 * xxx - start/match opt args. 3717 */ 3718 result = OSKext::loadKextWithIdentifier( 3719 kextIdentifier, 3720 /* kextRef */ NULL, 3721 /* allowDefer */ false, 3722 delayAutounload, 3723 startKextExcludeLevel, 3724 startMatchingExcludeLevel, 3725 personalityNames); 3726 if (result != kOSReturnSuccess) { 3727 goto finish; 3728 } 3729 /* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue 3730 * for matching via a separate IOKit calldown. 3731 */ 3732 3733 finish: 3734 3735 /* Gather up the collected log messages for user space. Any 3736 * error messages past this call will not make it up as log messages 3737 * but will be in the system log. 3738 */ 3739 logInfoArray = OSKext::clearUserSpaceLogFilter(); 3740 3741 if (logInfoArray && logInfoOut && logInfoLengthOut) { 3742 tempResult = OSKext::serializeLogInfo(logInfoArray.get(), 3743 logInfoOut, logInfoLengthOut); 3744 if (tempResult != kOSReturnSuccess) { 3745 result = tempResult; 3746 } 3747 } 3748 3749 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false); 3750 3751 IORecursiveLockUnlock(sKextLock); 3752 3753 /* Note: mkextDataObject will have been retained by every kext w/an 3754 * executable in it. That should all have been flushed out at the 3755 * and of the load operation, but you never know.... 3756 */ 3757 if (mkextData && mkextData->getRetainCount() > 1) { 3758 OSKextLog(/* kext */ NULL, 3759 kOSKextLogErrorLevel | 3760 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 3761 "Kext load request buffer from user space still retained by a kext; " 3762 "probable memory leak."); 3763 } 3764 3765 return result; 3766 } 3767 3768 #endif // CONFIG_KXLD 3769 3770 /********************************************************************* 3771 *********************************************************************/ 3772 /* static */ 3773 OSReturn 3774 OSKext::serializeLogInfo( 3775 OSArray * logInfoArray, 3776 char ** logInfoOut, 3777 uint32_t * logInfoLengthOut) 3778 { 3779 OSReturn result = kOSReturnError; 3780 char * buffer = NULL; 3781 kern_return_t kmem_result = KERN_FAILURE; 3782 OSSharedPtr<OSSerialize> serializer; 3783 char * logInfo = NULL; // returned by reference 3784 uint32_t logInfoLength = 0; 3785 3786 if (!logInfoArray || !logInfoOut || !logInfoLengthOut) { 3787 OSKextLog(/* kext */ NULL, 3788 kOSKextLogErrorLevel | 3789 kOSKextLogIPCFlag, 3790 "Internal error; invalid arguments to OSKext::serializeLogInfo()."); 3791 /* Bad programmer. */ 3792 result = kOSKextReturnInvalidArgument; 3793 goto finish; 3794 } 3795 3796 serializer = OSSerialize::withCapacity(0); 3797 if (!serializer) { 3798 OSKextLog(/* kext */ NULL, 3799 kOSKextLogErrorLevel | 3800 kOSKextLogIPCFlag, 3801 "Failed to create serializer on log info for request from user space."); 3802 /* Incidental error; we're going to (try to) allow the request 3803 * itself to succeed. */ 3804 } 3805 3806 if (!logInfoArray->serialize(serializer.get())) { 3807 OSKextLog(/* kext */ NULL, 3808 kOSKextLogErrorLevel | 3809 kOSKextLogIPCFlag, 3810 "Failed to serialize log info for request from user space."); 3811 /* Incidental error; we're going to (try to) allow the request 3812 * itself to succeed. */ 3813 } else { 3814 logInfo = serializer->text(); 3815 logInfoLength = serializer->getLength(); 3816 3817 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT); 3818 if (kmem_result != KERN_SUCCESS) { 3819 OSKextLog(/* kext */ NULL, 3820 kOSKextLogErrorLevel | 3821 kOSKextLogIPCFlag, 3822 "Failed to copy log info for request from user space."); 3823 /* Incidental error; we're going to (try to) allow the request 3824 * to succeed. */ 3825 } else { 3826 /* 11981737 - clear uninitialized data in last page */ 3827 bzero((void *)(buffer + logInfoLength), 3828 (round_page(logInfoLength) - logInfoLength)); 3829 memcpy(buffer, logInfo, logInfoLength); 3830 *logInfoOut = buffer; 3831 *logInfoLengthOut = logInfoLength; 3832 } 3833 } 3834 3835 result = kOSReturnSuccess; 3836 finish: 3837 return result; 3838 } 3839 3840 #if PRAGMA_MARK 3841 #pragma mark Instance Management Methods 3842 #endif 3843 /********************************************************************* 3844 *********************************************************************/ 3845 OSSharedPtr<OSKext> 3846 OSKext::lookupKextWithIdentifier(const char * kextIdentifier) 3847 { 3848 OSSharedPtr<OSKext> foundKext; 3849 3850 IORecursiveLockLock(sKextLock); 3851 foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain); 3852 IORecursiveLockUnlock(sKextLock); 3853 3854 return foundKext; 3855 } 3856 3857 /********************************************************************* 3858 *********************************************************************/ 3859 OSSharedPtr<OSKext> 3860 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier) 3861 { 3862 return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy()); 3863 } 3864 3865 /********************************************************************* 3866 *********************************************************************/ 3867 OSSharedPtr<OSKext> 3868 OSKext::lookupKextWithLoadTag(uint32_t aTag) 3869 { 3870 OSSharedPtr<OSKext> foundKext; // returned 3871 uint32_t i, j; 3872 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 3873 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 3874 3875 IORecursiveLockLock(sKextLock); 3876 3877 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 3878 for (i = 0; i < count[j]; i++) { 3879 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 3880 if (thisKext->getLoadTag() == aTag) { 3881 foundKext.reset(thisKext, OSRetain); 3882 goto finish; 3883 } 3884 } 3885 } 3886 3887 finish: 3888 IORecursiveLockUnlock(sKextLock); 3889 3890 return foundKext; 3891 } 3892 3893 /********************************************************************* 3894 *********************************************************************/ 3895 OSSharedPtr<OSKext> 3896 OSKext::lookupKextWithAddress(vm_address_t address) 3897 { 3898 OSSharedPtr<OSKext> foundKext; // returned 3899 uint32_t count, i; 3900 kmod_info_t *kmod_info; 3901 vm_address_t originalAddress; 3902 #if defined(__arm64__) 3903 uint64_t textExecBase; 3904 size_t textExecSize; 3905 #endif /* defined(__arm64__) */ 3906 3907 originalAddress = address; 3908 #if __has_feature(ptrauth_calls) 3909 address = (vm_address_t)VM_KERNEL_STRIP_PTR(address); 3910 #endif /* __has_feature(ptrauth_calls) */ 3911 3912 IORecursiveLockLock(sKextLock); 3913 3914 count = sLoadedKexts->getCount(); 3915 for (i = 0; i < count; i++) { 3916 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 3917 if (thisKext == sKernelKext) { 3918 continue; 3919 } 3920 if (thisKext->kmod_info && thisKext->kmod_info->address) { 3921 kmod_info = thisKext->kmod_info; 3922 vm_address_t kext_start = kmod_info->address; 3923 vm_address_t kext_end = kext_start + kmod_info->size; 3924 if ((kext_start <= address) && (address < kext_end)) { 3925 foundKext.reset(thisKext, OSRetain); 3926 goto finish; 3927 } 3928 #if defined(__arm64__) 3929 textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize); 3930 if ((textExecBase <= address) && (address < textExecBase + textExecSize)) { 3931 foundKext.reset(thisKext, OSRetain); 3932 goto finish; 3933 } 3934 #endif /* defined (__arm64__) */ 3935 } 3936 } 3937 if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) { 3938 foundKext.reset(sKernelKext, OSRetain); 3939 goto finish; 3940 } 3941 /* 3942 * DriverKit userspace executables do not have a kernel linkedExecutable, 3943 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address 3944 * here, so use the original address passed to this method. 3945 * 3946 * This is supposed to be used for logging reasons only. When logd 3947 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we 3948 * remove it here before checking it against the LoadTag. 3949 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line. 3950 */ 3951 3952 address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT); 3953 count = sLoadedDriverKitKexts->getCount(); 3954 for (i = 0; i < count; i++) { 3955 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i)); 3956 if (thisKext->getLoadTag() == address) { 3957 foundKext.reset(thisKext, OSRetain); 3958 } 3959 } 3960 3961 finish: 3962 IORecursiveLockUnlock(sKextLock); 3963 3964 return foundKext; 3965 } 3966 3967 OSSharedPtr<OSData> 3968 OSKext::copyKextUUIDForAddress(OSNumber *address) 3969 { 3970 OSSharedPtr<OSData> uuid; 3971 OSSharedPtr<OSKext> kext; 3972 3973 if (!address) { 3974 return NULL; 3975 } 3976 3977 #if CONFIG_MACF 3978 /* Is the calling process allowed to query kext info? */ 3979 if (current_task() != kernel_task) { 3980 int macCheckResult = 0; 3981 kauth_cred_t cred = NULL; 3982 3983 cred = kauth_cred_get_with_ref(); 3984 macCheckResult = mac_kext_check_query(cred); 3985 kauth_cred_unref(&cred); 3986 3987 if (macCheckResult != 0) { 3988 OSKextLog(/* kext */ NULL, 3989 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 3990 "Failed to query kext UUID (MAC policy error 0x%x).", 3991 macCheckResult); 3992 return NULL; 3993 } 3994 } 3995 #endif 3996 3997 uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue()); 3998 if (slidAddress != 0) { 3999 kext = lookupKextWithAddress(slidAddress); 4000 if (kext) { 4001 uuid = kext->copyTextUUID(); 4002 } 4003 } 4004 4005 if (!uuid) { 4006 /* 4007 * If we still don't have a UUID, then we failed to match the slid + stripped address with 4008 * a kext. This might have happened because the log message came from a dext. 4009 * 4010 * Try again with the original address. 4011 */ 4012 kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue()); 4013 if (kext && kext->isDriverKit()) { 4014 uuid = kext->copyTextUUID(); 4015 } 4016 } 4017 4018 return uuid; 4019 } 4020 4021 /********************************************************************* 4022 *********************************************************************/ 4023 OSSharedPtr<OSKext> 4024 OSKext::lookupKextWithUUID(uuid_t wanted) 4025 { 4026 OSSharedPtr<OSKext> foundKext; // returned 4027 uint32_t j, i; 4028 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 4029 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 4030 4031 4032 IORecursiveLockLock(sKextLock); 4033 4034 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 4035 for (i = 0; i < count[j]; i++) { 4036 OSKext * thisKext = NULL; 4037 4038 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 4039 if (!thisKext) { 4040 continue; 4041 } 4042 4043 OSSharedPtr<OSData> uuid_data = thisKext->copyUUID(); 4044 if (!uuid_data) { 4045 continue; 4046 } 4047 4048 uuid_t uuid; 4049 memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 4050 4051 if (0 == uuid_compare(wanted, uuid)) { 4052 foundKext.reset(thisKext, OSRetain); 4053 goto finish; 4054 } 4055 } 4056 } 4057 finish: 4058 IORecursiveLockUnlock(sKextLock); 4059 4060 return foundKext; 4061 } 4062 4063 4064 4065 4066 /********************************************************************* 4067 *********************************************************************/ 4068 /* static */ 4069 bool 4070 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier) 4071 { 4072 bool result = false; 4073 OSKext * foundKext = NULL; // returned 4074 4075 IORecursiveLockLock(sKextLock); 4076 4077 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 4078 if (foundKext && foundKext->isLoaded()) { 4079 result = true; 4080 } 4081 4082 IORecursiveLockUnlock(sKextLock); 4083 4084 return result; 4085 } 4086 4087 /********************************************************************* 4088 * xxx - should spawn a separate thread so a kext can safely have 4089 * xxx - itself unloaded. 4090 *********************************************************************/ 4091 /* static */ 4092 OSReturn 4093 OSKext::removeKext( 4094 OSKext * aKext, 4095 #if CONFIG_EMBEDDED 4096 __unused 4097 #endif 4098 bool terminateServicesAndRemovePersonalitiesFlag) 4099 { 4100 #if CONFIG_EMBEDDED 4101 OSKextLog(aKext, 4102 kOSKextLogErrorLevel | 4103 kOSKextLogKextBookkeepingFlag, 4104 "removeKext() called for %s, not supported on embedded", 4105 aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext"); 4106 4107 return kOSReturnSuccess; 4108 #else /* CONFIG_EMBEDDED */ 4109 4110 OSReturn result = kOSKextReturnInUse; 4111 OSKext * checkKext = NULL; // do not release 4112 #if CONFIG_MACF 4113 int macCheckResult = 0; 4114 kauth_cred_t cred = NULL; 4115 #endif 4116 4117 IORecursiveLockLock(sKextLock); 4118 4119 /* If the kext has no identifier, it failed to init 4120 * so isn't in sKextsByID and it isn't loaded. 4121 */ 4122 if (!aKext->getIdentifier()) { 4123 result = kOSReturnSuccess; 4124 goto finish; 4125 } 4126 4127 checkKext = OSDynamicCast(OSKext, 4128 sKextsByID->getObject(aKext->getIdentifier())); 4129 if (checkKext != aKext) { 4130 result = kOSKextReturnNotFound; 4131 goto finish; 4132 } 4133 4134 if (aKext->isLoaded()) { 4135 #if CONFIG_MACF 4136 if (current_task() != kernel_task) { 4137 cred = kauth_cred_get_with_ref(); 4138 macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString()); 4139 kauth_cred_unref(&cred); 4140 } 4141 4142 if (macCheckResult != 0) { 4143 result = kOSReturnError; 4144 OSKextLog(aKext, 4145 kOSKextLogErrorLevel | 4146 kOSKextLogKextBookkeepingFlag, 4147 "Failed to remove kext %s (MAC policy error 0x%x).", 4148 aKext->getIdentifierCString(), macCheckResult); 4149 goto finish; 4150 } 4151 #endif 4152 4153 /* make sure there are no resource requests in flight - 17187548 */ 4154 if (aKext->countRequestCallbacks()) { 4155 goto finish; 4156 } 4157 if (aKext->flags.unloadUnsupported) { 4158 result = kOSKextReturnInUse; 4159 OSKextLog(aKext, 4160 kOSKextLogErrorLevel | 4161 kOSKextLogKextBookkeepingFlag, 4162 "Can't remove kext %s; unsupported by cache.", 4163 aKext->getIdentifierCString()); 4164 goto finish; 4165 } 4166 4167 /* If we are terminating, send the request to the IOCatalogue 4168 * (which will actually call us right back but that's ok we have 4169 * a recursive lock don't you know) but do not ask the IOCatalogue 4170 * to call back with an unload, we'll do that right here. 4171 */ 4172 if (terminateServicesAndRemovePersonalitiesFlag) { 4173 result = gIOCatalogue->terminateDriversForModule( 4174 aKext->getIdentifierCString(), /* unload */ false); 4175 if (result != kOSReturnSuccess) { 4176 OSKextLog(aKext, 4177 kOSKextLogErrorLevel | 4178 kOSKextLogKextBookkeepingFlag, 4179 "Can't remove kext %s; services failed to terminate - 0x%x.", 4180 aKext->getIdentifierCString(), result); 4181 goto finish; 4182 } 4183 } 4184 4185 result = aKext->unload(); 4186 if (result != kOSReturnSuccess) { 4187 goto finish; 4188 } 4189 } 4190 4191 /* Remove personalities as requested. This is a bit redundant for a loaded 4192 * kext as IOCatalogue::terminateDriversForModule() removes driver 4193 * personalities, but it doesn't restart matching, which we always want 4194 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures 4195 * that happens. 4196 */ 4197 if (terminateServicesAndRemovePersonalitiesFlag) { 4198 aKext->removePersonalitiesFromCatalog(); 4199 } 4200 4201 if (aKext->isInFileset()) { 4202 OSKextLog(aKext, 4203 kOSKextLogProgressLevel | 4204 kOSKextLogKextBookkeepingFlag, 4205 "Fileset kext %s unloaded.", 4206 aKext->getIdentifierCString()); 4207 } else { 4208 OSKextLog(aKext, 4209 kOSKextLogProgressLevel | 4210 kOSKextLogKextBookkeepingFlag, 4211 "Removing kext %s.", 4212 aKext->getIdentifierCString()); 4213 4214 sKextsByID->removeObject(aKext->getIdentifier()); 4215 } 4216 result = kOSReturnSuccess; 4217 4218 finish: 4219 IORecursiveLockUnlock(sKextLock); 4220 return result; 4221 #endif /* CONFIG_EMBEDDED */ 4222 } 4223 4224 /********************************************************************* 4225 *********************************************************************/ 4226 /* static */ 4227 OSReturn 4228 OSKext::removeKextWithIdentifier( 4229 const char * kextIdentifier, 4230 bool terminateServicesAndRemovePersonalitiesFlag) 4231 { 4232 OSReturn result = kOSReturnError; 4233 4234 IORecursiveLockLock(sKextLock); 4235 4236 OSKext * aKext = OSDynamicCast(OSKext, 4237 sKextsByID->getObject(kextIdentifier)); 4238 if (!aKext) { 4239 result = kOSKextReturnNotFound; 4240 OSKextLog(/* kext */ NULL, 4241 kOSKextLogErrorLevel | 4242 kOSKextLogKextBookkeepingFlag, 4243 "Can't remove kext %s - not found.", 4244 kextIdentifier); 4245 goto finish; 4246 } 4247 4248 result = OSKext::removeKext(aKext, 4249 terminateServicesAndRemovePersonalitiesFlag); 4250 4251 finish: 4252 IORecursiveLockUnlock(sKextLock); 4253 4254 return result; 4255 } 4256 4257 /********************************************************************* 4258 *********************************************************************/ 4259 /* static */ 4260 OSReturn 4261 OSKext::removeKextWithLoadTag( 4262 OSKextLoadTag loadTag, 4263 bool terminateServicesAndRemovePersonalitiesFlag) 4264 { 4265 OSReturn result = kOSReturnError; 4266 OSKext * foundKext = NULL; 4267 uint32_t i, j; 4268 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 4269 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 4270 4271 4272 IORecursiveLockLock(sKextLock); 4273 4274 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 4275 for (i = 0; i < count[j]; i++) { 4276 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 4277 if (thisKext->loadTag == loadTag) { 4278 foundKext = thisKext; 4279 break; 4280 } 4281 } 4282 } 4283 4284 if (!foundKext) { 4285 result = kOSKextReturnNotFound; 4286 OSKextLog(/* kext */ NULL, 4287 kOSKextLogErrorLevel | 4288 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 4289 "Can't remove kext with load tag %d - not found.", 4290 loadTag); 4291 goto finish; 4292 } 4293 4294 result = OSKext::removeKext(foundKext, 4295 terminateServicesAndRemovePersonalitiesFlag); 4296 4297 finish: 4298 IORecursiveLockUnlock(sKextLock); 4299 4300 return result; 4301 } 4302 4303 /********************************************************************* 4304 *********************************************************************/ 4305 OSSharedPtr<OSDictionary> 4306 OSKext::copyKexts(void) 4307 { 4308 OSSharedPtr<OSDictionary> result; 4309 4310 IORecursiveLockLock(sKextLock); 4311 result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection()); 4312 IORecursiveLockUnlock(sKextLock); 4313 4314 return result; 4315 } 4316 4317 /********************************************************************* 4318 *********************************************************************/ 4319 #define BOOTER_KEXT_PREFIX "Driver-" 4320 4321 typedef struct _DeviceTreeBuffer { 4322 uint32_t paddr; 4323 uint32_t length; 4324 } _DeviceTreeBuffer; 4325 4326 /********************************************************************* 4327 * Create a dictionary of excluded kexts from the given booter data. 4328 *********************************************************************/ 4329 /* static */ 4330 void 4331 OSKext::createExcludeListFromBooterData( 4332 OSDictionary * theDictionary, 4333 OSCollectionIterator * theIterator ) 4334 { 4335 OSString * deviceTreeName = NULL; // do not release 4336 const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not release 4337 char * booterDataPtr = NULL; // do not release 4338 _BooterKextFileInfo * kextFileInfo = NULL; // do not release 4339 char * infoDictAddr = NULL; // do not release 4340 OSSharedPtr<OSObject> parsedXML; 4341 OSDictionary * theInfoDict = NULL; // do not release 4342 4343 theIterator->reset(); 4344 4345 /* look for AppleKextExcludeList.kext */ 4346 while ((deviceTreeName = 4347 OSDynamicCast(OSString, theIterator->getNextObject()))) { 4348 const char * devTreeNameCString; 4349 OSData * deviceTreeEntry; // do not release 4350 OSString * myBundleID; // do not release 4351 4352 deviceTreeEntry = 4353 OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName)); 4354 if (!deviceTreeEntry) { 4355 continue; 4356 } 4357 4358 /* Make sure it is a kext */ 4359 devTreeNameCString = deviceTreeName->getCStringNoCopy(); 4360 if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX, 4361 (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) { 4362 OSKextLog(NULL, 4363 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4364 "\"%s\" not a kext", 4365 devTreeNameCString); 4366 continue; 4367 } 4368 4369 deviceTreeBuffer = (const _DeviceTreeBuffer *) 4370 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer)); 4371 if (!deviceTreeBuffer) { 4372 continue; 4373 } 4374 4375 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr); 4376 if (!booterDataPtr) { 4377 continue; 4378 } 4379 4380 kextFileInfo = (_BooterKextFileInfo *) booterDataPtr; 4381 if (!kextFileInfo->infoDictPhysAddr || 4382 !kextFileInfo->infoDictLength) { 4383 continue; 4384 } 4385 4386 infoDictAddr = (char *) 4387 ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 4388 if (!infoDictAddr) { 4389 continue; 4390 } 4391 4392 parsedXML = OSUnserializeXML(infoDictAddr); 4393 if (!parsedXML) { 4394 continue; 4395 } 4396 4397 theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 4398 if (!theInfoDict) { 4399 continue; 4400 } 4401 4402 myBundleID = 4403 OSDynamicCast(OSString, 4404 theInfoDict->getObject(kCFBundleIdentifierKey)); 4405 if (myBundleID && 4406 strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) { 4407 boolean_t updated = updateExcludeList(theInfoDict); 4408 if (!updated) { 4409 /* 25322874 */ 4410 panic("Missing OSKextExcludeList dictionary"); 4411 } 4412 break; 4413 } 4414 } // while ( (deviceTreeName = ...) ) 4415 4416 return; 4417 } 4418 4419 /********************************************************************* 4420 * Create a dictionary of excluded kexts from the given prelink 4421 * info (kernelcache). 4422 *********************************************************************/ 4423 /* static */ 4424 void 4425 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray ) 4426 { 4427 OSDictionary * myInfoDict = NULL; // do not release 4428 OSString * myBundleID; // do not release 4429 u_int i; 4430 4431 /* Find the Apple Kext Exclude List. */ 4432 for (i = 0; i < theInfoArray->getCount(); i++) { 4433 myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i)); 4434 if (!myInfoDict) { 4435 continue; 4436 } 4437 myBundleID = 4438 OSDynamicCast(OSString, 4439 myInfoDict->getObject(kCFBundleIdentifierKey)); 4440 if (myBundleID && 4441 strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) { 4442 boolean_t updated = updateExcludeList(myInfoDict); 4443 if (!updated) { 4444 /* 25322874 */ 4445 panic("Missing OSKextExcludeList dictionary"); 4446 } 4447 break; 4448 } 4449 } // for (i = 0; i < theInfoArray->getCount()... 4450 4451 return; 4452 } 4453 4454 /* static */ 4455 boolean_t 4456 OSKext::updateExcludeList(OSDictionary *infoDict) 4457 { 4458 OSDictionary *myTempDict = NULL; // do not free 4459 OSString *myTempString = NULL; // do not free 4460 OSKextVersion newVersion = 0; 4461 boolean_t updated = false; 4462 4463 if (!infoDict) { 4464 return false; 4465 } 4466 4467 myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList")); 4468 if (!myTempDict) { 4469 return false; 4470 } 4471 4472 myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey)); 4473 if (!myTempString) { 4474 return false; 4475 } 4476 4477 newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy()); 4478 if (newVersion == 0) { 4479 return false; 4480 } 4481 4482 IORecursiveLockLock(sKextLock); 4483 4484 if (newVersion > sExcludeListVersion) { 4485 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0); 4486 sExcludeListVersion = newVersion; 4487 updated = true; 4488 } 4489 4490 IORecursiveLockUnlock(sKextLock); 4491 return updated; 4492 } 4493 4494 #if PRAGMA_MARK 4495 #pragma mark Accessors 4496 #endif 4497 /********************************************************************* 4498 *********************************************************************/ 4499 const OSSymbol * 4500 OSKext::getIdentifier(void) 4501 { 4502 return bundleID.get(); 4503 } 4504 4505 /********************************************************************* 4506 * A kext must have a bundle identifier to even survive initialization; 4507 * this is guaranteed to exist past then. 4508 *********************************************************************/ 4509 const char * 4510 OSKext::getIdentifierCString(void) 4511 { 4512 return bundleID->getCStringNoCopy(); 4513 } 4514 4515 /********************************************************************* 4516 *********************************************************************/ 4517 OSKextVersion 4518 OSKext::getVersion(void) 4519 { 4520 return version; 4521 } 4522 4523 /********************************************************************* 4524 *********************************************************************/ 4525 OSKextVersion 4526 OSKext::getCompatibleVersion(void) 4527 { 4528 return compatibleVersion; 4529 } 4530 4531 /********************************************************************* 4532 *********************************************************************/ 4533 bool 4534 OSKext::isLibrary(void) 4535 { 4536 return getCompatibleVersion() > 0; 4537 } 4538 4539 /********************************************************************* 4540 *********************************************************************/ 4541 bool 4542 OSKext::isCompatibleWithVersion(OSKextVersion aVersion) 4543 { 4544 if ((compatibleVersion > -1 && version > -1) && 4545 (compatibleVersion <= version && aVersion <= version)) { 4546 return true; 4547 } 4548 return false; 4549 } 4550 4551 /********************************************************************* 4552 *********************************************************************/ 4553 bool 4554 OSKext::declaresExecutable(void) 4555 { 4556 if (isDriverKit()) { 4557 return false; 4558 } 4559 return getPropertyForHostArch(kCFBundleExecutableKey) != NULL; 4560 } 4561 4562 /********************************************************************* 4563 *********************************************************************/ 4564 OSData * 4565 OSKext::getExecutable(void) 4566 { 4567 OSData * result = NULL; 4568 OSSharedPtr<OSData> extractedExecutable; 4569 4570 if (flags.builtin) { 4571 return sKernelKext->linkedExecutable.get(); 4572 } 4573 4574 result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey)); 4575 if (result) { 4576 return result; 4577 } 4578 4579 #if CONFIG_KXLD 4580 OSData * mkextExecutableRef = NULL; // do not release 4581 mkextExecutableRef = OSDynamicCast(OSData, 4582 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey)); 4583 4584 if (mkextExecutableRef) { 4585 MkextEntryRef * mkextEntryRef = (MkextEntryRef *) 4586 mkextExecutableRef->getBytesNoCopy(); 4587 uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext); 4588 if (mkextVersion == MKEXT_VERS_2) { 4589 mkext2_file_entry * fileinfo = 4590 (mkext2_file_entry *)mkextEntryRef->fileinfo; 4591 uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo); 4592 uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo); 4593 extractedExecutable = extractMkext2FileData( 4594 MKEXT2_GET_ENTRY_DATA(fileinfo), "executable", 4595 compressedSize, fullSize); 4596 } else { 4597 OSKextLog(this, kOSKextLogErrorLevel | 4598 kOSKextLogArchiveFlag, 4599 "Kext %s - unknown mkext version 0x%x for executable.", 4600 getIdentifierCString(), mkextVersion); 4601 } 4602 4603 /* Regardless of success, remove the mkext executable, 4604 * and drop one reference on the mkext. (setExecutable() does not 4605 * replace, it removes, or panics if asked to replace.) 4606 */ 4607 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 4608 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 4609 4610 if (extractedExecutable && extractedExecutable->getLength()) { 4611 if (!setExecutable(extractedExecutable.get())) { 4612 goto finish; 4613 } 4614 result = extractedExecutable.get(); 4615 } else { 4616 goto finish; 4617 } 4618 } 4619 4620 finish: 4621 #endif // CONFIG_KXLD 4622 return result; 4623 } 4624 4625 /********************************************************************* 4626 *********************************************************************/ 4627 bool 4628 OSKext::isInterface(void) 4629 { 4630 return flags.interface; 4631 } 4632 4633 /********************************************************************* 4634 *********************************************************************/ 4635 bool 4636 OSKext::isKernel(void) 4637 { 4638 return this == sKernelKext; 4639 } 4640 4641 /********************************************************************* 4642 *********************************************************************/ 4643 bool 4644 OSKext::isKernelComponent(void) 4645 { 4646 return flags.kernelComponent ? true : false; 4647 } 4648 4649 /********************************************************************* 4650 *********************************************************************/ 4651 bool 4652 OSKext::isExecutable(void) 4653 { 4654 return !isKernel() && !isInterface() && declaresExecutable(); 4655 } 4656 4657 /********************************************************************* 4658 * We might want to check this recursively for all dependencies, 4659 * since a subtree of dependencies could get loaded before we hit 4660 * a dependency that isn't safe-boot-loadable. 4661 * 4662 * xxx - Might want to return false if OSBundleEnableKextLogging or 4663 * OSBundleDebugLevel 4664 * or IOKitDebug is nonzero too (we used to do that, but I don't see 4665 * the point except it's usually development drivers, which might 4666 * cause panics on startup, that have those properties). Heh; could 4667 * use a "kx" boot-arg! 4668 *********************************************************************/ 4669 bool 4670 OSKext::isLoadableInSafeBoot(void) 4671 { 4672 bool result = false; 4673 OSString * required = NULL; // do not release 4674 4675 if (isKernel()) { 4676 result = true; 4677 goto finish; 4678 } 4679 4680 if (isDriverKit()) { 4681 result = true; 4682 goto finish; 4683 } 4684 4685 required = OSDynamicCast(OSString, 4686 getPropertyForHostArch(kOSBundleRequiredKey)); 4687 if (!required) { 4688 goto finish; 4689 } 4690 if (required->isEqualTo(kOSBundleRequiredRoot) || 4691 required->isEqualTo(kOSBundleRequiredLocalRoot) || 4692 required->isEqualTo(kOSBundleRequiredNetworkRoot) || 4693 required->isEqualTo(kOSBundleRequiredSafeBoot) || 4694 required->isEqualTo(kOSBundleRequiredConsole)) { 4695 result = true; 4696 } 4697 4698 finish: 4699 return result; 4700 } 4701 4702 /********************************************************************* 4703 *********************************************************************/ 4704 bool 4705 OSKext::isPrelinked(void) 4706 { 4707 return flags.prelinked ? true : false; 4708 } 4709 4710 /********************************************************************* 4711 *********************************************************************/ 4712 bool 4713 OSKext::isLoaded(void) 4714 { 4715 return flags.loaded ? true : false; 4716 } 4717 4718 /********************************************************************* 4719 *********************************************************************/ 4720 bool 4721 OSKext::isStarted(void) 4722 { 4723 return flags.started ? true : false; 4724 } 4725 4726 /********************************************************************* 4727 *********************************************************************/ 4728 bool 4729 OSKext::isCPPInitialized(void) 4730 { 4731 return flags.CPPInitialized; 4732 } 4733 4734 /********************************************************************* 4735 *********************************************************************/ 4736 void 4737 OSKext::setCPPInitialized(bool initialized) 4738 { 4739 flags.CPPInitialized = initialized; 4740 } 4741 4742 /********************************************************************* 4743 *********************************************************************/ 4744 uint32_t 4745 OSKext::getLoadTag(void) 4746 { 4747 return loadTag; 4748 } 4749 4750 /********************************************************************* 4751 *********************************************************************/ 4752 void 4753 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize) 4754 { 4755 if (linkedExecutable) { 4756 *loadSize = linkedExecutable->getLength(); 4757 4758 /* If we have a kmod_info struct, calculated the wired size 4759 * from that. Otherwise it's the full load size. 4760 */ 4761 if (kmod_info) { 4762 *wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size; 4763 } else { 4764 *wiredSize = *loadSize; 4765 } 4766 } else { 4767 *wiredSize = 0; 4768 *loadSize = 0; 4769 } 4770 } 4771 4772 /********************************************************************* 4773 *********************************************************************/ 4774 OSSharedPtr<OSData> 4775 OSKext::copyUUID(void) 4776 { 4777 OSSharedPtr<OSData> result; 4778 OSData * theExecutable = NULL; // do not release 4779 const kernel_mach_header_t * header; 4780 4781 /* An interface kext doesn't have a linked executable with an LC_UUID, 4782 * we create one when it's linked. 4783 */ 4784 if (interfaceUUID) { 4785 result = interfaceUUID; 4786 goto finish; 4787 } 4788 4789 if (flags.builtin || isInterface()) { 4790 return sKernelKext->copyUUID(); 4791 } 4792 4793 if (isDriverKit() && infoDict) { 4794 return driverKitUUID; 4795 } 4796 4797 /* For real kexts, try to get the UUID from the linked executable, 4798 * or if is hasn't been linked yet, the unrelocated executable. 4799 */ 4800 theExecutable = linkedExecutable.get(); 4801 if (!theExecutable) { 4802 theExecutable = getExecutable(); 4803 } 4804 4805 if (!theExecutable) { 4806 goto finish; 4807 } 4808 4809 header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy(); 4810 result = copyMachoUUID(header); 4811 4812 finish: 4813 return result; 4814 } 4815 4816 /********************************************************************* 4817 *********************************************************************/ 4818 OSSharedPtr<OSData> 4819 OSKext::copyTextUUID(void) 4820 { 4821 if (flags.builtin) { 4822 return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address); 4823 } 4824 return copyUUID(); 4825 } 4826 4827 /********************************************************************* 4828 *********************************************************************/ 4829 OSSharedPtr<OSData> 4830 OSKext::copyMachoUUID(const kernel_mach_header_t * header) 4831 { 4832 OSSharedPtr<OSData> result; 4833 const struct load_command * load_cmd = NULL; 4834 const struct uuid_command * uuid_cmd = NULL; 4835 uint32_t i; 4836 4837 load_cmd = (const struct load_command *)&header[1]; 4838 4839 if (header->magic != MH_MAGIC_KERNEL) { 4840 OSKextLog(NULL, 4841 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4842 "%s: bad header %p", 4843 __func__, 4844 header); 4845 goto finish; 4846 } 4847 4848 for (i = 0; i < header->ncmds; i++) { 4849 if (load_cmd->cmd == LC_UUID) { 4850 uuid_cmd = (struct uuid_command *)load_cmd; 4851 result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid)); 4852 goto finish; 4853 } 4854 load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize); 4855 } 4856 4857 finish: 4858 return result; 4859 } 4860 4861 void 4862 OSKext::setDriverKitUUID(OSData *uuid) 4863 { 4864 if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) { 4865 OSSafeReleaseNULL(uuid); 4866 } 4867 } 4868 4869 /********************************************************************* 4870 *********************************************************************/ 4871 #if defined (__arm__) 4872 #include <arm/arch.h> 4873 #endif 4874 4875 #if defined (__x86_64__) 4876 #define ARCHNAME "x86_64" 4877 #elif defined (__arm64__) 4878 #define ARCHNAME "arm64" 4879 #elif defined (__arm__) 4880 4881 #if defined (__ARM_ARCH_7S__) 4882 #define ARCHNAME "armv7s" 4883 #elif defined (__ARM_ARCH_7F__) 4884 #define ARCHNAME "armv7f" 4885 #elif defined (__ARM_ARCH_7K__) 4886 #define ARCHNAME "armv7k" 4887 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */ 4888 #define ARCHNAME "armv7" 4889 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */ 4890 #define ARCHNAME "armv6" 4891 #endif 4892 4893 #elif defined (__arm64__) 4894 #define ARCHNAME "arm64" 4895 #else 4896 #error architecture not supported 4897 #endif 4898 4899 #define ARCH_SEPARATOR_CHAR '_' 4900 4901 static char * 4902 makeHostArchKey(const char * key, size_t * keySizeOut) 4903 { 4904 char * result = NULL; 4905 size_t keyLength = strlen(key); 4906 size_t keySize; 4907 4908 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'. 4909 */ 4910 keySize = 1 + 1 + keyLength + strlen(ARCHNAME); 4911 result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 4912 4913 if (!result) { 4914 goto finish; 4915 } 4916 strlcpy(result, key, keySize); 4917 result[keyLength++] = ARCH_SEPARATOR_CHAR; 4918 result[keyLength] = '\0'; 4919 strlcat(result, ARCHNAME, keySize); 4920 *keySizeOut = keySize; 4921 4922 finish: 4923 return result; 4924 } 4925 4926 /********************************************************************* 4927 *********************************************************************/ 4928 OSObject * 4929 OSKext::getPropertyForHostArch(const char * key) 4930 { 4931 OSObject * result = NULL;// do not release 4932 size_t hostArchKeySize = 0; 4933 char * hostArchKey = NULL;// must kfree 4934 4935 if (!key || !infoDict) { 4936 goto finish; 4937 } 4938 4939 /* Some properties are not allowed to be arch-variant: 4940 * - Any CFBundle... property. 4941 * - OSBundleIsInterface. 4942 * - OSKernelResource. 4943 */ 4944 if (STRING_HAS_PREFIX(key, "OS") || 4945 STRING_HAS_PREFIX(key, "IO")) { 4946 hostArchKey = makeHostArchKey(key, &hostArchKeySize); 4947 if (!hostArchKey) { 4948 OSKextLog(/* kext (this isn't about a kext) */ NULL, 4949 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4950 "Allocation failure."); 4951 goto finish; 4952 } 4953 result = infoDict->getObject(hostArchKey); 4954 } 4955 4956 if (!result) { 4957 result = infoDict->getObject(key); 4958 } 4959 4960 finish: 4961 if (hostArchKey) { 4962 kfree_data(hostArchKey, hostArchKeySize); 4963 } 4964 return result; 4965 } 4966 4967 #if PRAGMA_MARK 4968 #pragma mark Load/Start/Stop/Unload 4969 #endif 4970 4971 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n') 4972 4973 /********************************************************************* 4974 * sExcludeListByID is a dictionary with keys / values of: 4975 * key = bundleID string of kext we will not allow to load 4976 * value = version string(s) of the kext that is to be denied loading. 4977 * The version strings can be comma delimited. For example if kext 4978 * com.foocompany.fookext has two versions that we want to deny 4979 * loading then the version strings might look like: 4980 * 1.0.0, 1.0.1 4981 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will 4982 * not load the kext. 4983 * 4984 * Value may also be in the form of "LE 2.0.0" (version numbers 4985 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version 4986 * number less than 2.0.0 will not load) 4987 * 4988 * NOTE - we cannot use the characters "<=" or "<" because we have code 4989 * that serializes plists and treats '<' as a special character. 4990 *********************************************************************/ 4991 bool 4992 OSKext::isInExcludeList(void) 4993 { 4994 OSString * versionString = NULL; // do not release 4995 char * versionCString = NULL; // do not free 4996 size_t i; 4997 boolean_t wantLessThan = false; 4998 boolean_t wantLessThanEqualTo = false; 4999 boolean_t isInExcludeList = true; 5000 char myBuffer[32]; 5001 5002 IORecursiveLockLock(sKextLock); 5003 5004 if (!sExcludeListByID) { 5005 isInExcludeList = false; 5006 } else { 5007 /* look up by bundleID in our exclude list and if found get version 5008 * string (or strings) that we will not allow to load 5009 */ 5010 versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get())); 5011 if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) { 5012 isInExcludeList = false; 5013 } 5014 } 5015 5016 IORecursiveLockUnlock(sKextLock); 5017 5018 if (!isInExcludeList) { 5019 return false; 5020 } 5021 5022 /* parse version strings */ 5023 versionCString = (char *) versionString->getCStringNoCopy(); 5024 5025 /* look for "LT" or "LE" form of version string, must be in first two 5026 * positions. 5027 */ 5028 if (*versionCString == 'L' && *(versionCString + 1) == 'T') { 5029 wantLessThan = true; 5030 versionCString += 2; 5031 } else if (*versionCString == 'L' && *(versionCString + 1) == 'E') { 5032 wantLessThanEqualTo = true; 5033 versionCString += 2; 5034 } 5035 5036 for (i = 0; *versionCString != 0x00; versionCString++) { 5037 /* skip whitespace */ 5038 if (isWhiteSpace(*versionCString)) { 5039 continue; 5040 } 5041 5042 /* peek ahead for version string separator or null terminator */ 5043 if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) { 5044 /* OK, we have a version string */ 5045 myBuffer[i++] = *versionCString; 5046 myBuffer[i] = 0x00; 5047 5048 OSKextVersion excludeVers; 5049 excludeVers = OSKextParseVersionString(myBuffer); 5050 5051 if (wantLessThanEqualTo) { 5052 if (version <= excludeVers) { 5053 return true; 5054 } 5055 } else if (wantLessThan) { 5056 if (version < excludeVers) { 5057 return true; 5058 } 5059 } else if (version == excludeVers) { 5060 return true; 5061 } 5062 5063 /* reset for the next (if any) version string */ 5064 i = 0; 5065 wantLessThan = false; 5066 wantLessThanEqualTo = false; 5067 } else { 5068 /* save valid version character */ 5069 myBuffer[i++] = *versionCString; 5070 5071 /* make sure bogus version string doesn't overrun local buffer */ 5072 if (i >= sizeof(myBuffer)) { 5073 break; 5074 } 5075 } 5076 } 5077 5078 return false; 5079 } 5080 5081 /********************************************************************* 5082 * sNonLoadableKextsByID is a dictionary with keys / values of: 5083 * key = bundleID string of kext we will not allow to load 5084 * value = boolean (true == loadable, false == not loadable) 5085 * 5086 * Only kexts which are in the AuxKC will be marked as "not loadble," 5087 * i.e., the value for the kext's bundleID will be false. All kexts in 5088 * the primary and system KCs will always be marked as "loadable." 5089 * 5090 * This list ultimately comes from kexts which have been uninstalled 5091 * in user space by deleting the kext from disk, but which have not 5092 * yet been removed from the AuxKC. Because the user could choose to 5093 * re-install the exact same version of the kext, we need to keep 5094 * a dictionary of boolean values so that user space only needs to 5095 * keep a simple list of "uninstalled" or "missing" bundles. When 5096 * a bundle is re-installed, the iokit daemon can use the 5097 * AucKCBundleAvailable predicate to set the individual kext's 5098 * availability to true. 5099 *********************************************************************/ 5100 bool 5101 OSKext::isLoadable(void) 5102 { 5103 bool isLoadable = true; 5104 5105 if (kc_type != KCKindAuxiliary) { 5106 /* this filtering only applies to kexts in the auxkc */ 5107 return true; 5108 } 5109 5110 IORecursiveLockLock(sKextLock); 5111 5112 if (sNonLoadableKextsByID) { 5113 /* look up by bundleID in our exclude list and if found get version 5114 * string (or strings) that we will not allow to load 5115 */ 5116 OSBoolean *loadableVal; 5117 loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get())); 5118 if (loadableVal && !loadableVal->getValue()) { 5119 isLoadable = false; 5120 } 5121 } 5122 IORecursiveLockUnlock(sKextLock); 5123 5124 return isLoadable; 5125 } 5126 5127 /********************************************************************* 5128 *********************************************************************/ 5129 /* static */ 5130 OSReturn 5131 OSKext::loadKextWithIdentifier( 5132 const char * kextIdentifierCString, 5133 Boolean allowDeferFlag, 5134 Boolean delayAutounloadFlag, 5135 OSKextExcludeLevel startOpt, 5136 OSKextExcludeLevel startMatchingOpt, 5137 OSArray * personalityNames) 5138 { 5139 OSReturn result = kOSReturnError; 5140 OSSharedPtr<OSString> kextIdentifier; 5141 5142 kextIdentifier = OSString::withCString(kextIdentifierCString); 5143 if (!kextIdentifier) { 5144 result = kOSKextReturnNoMemory; 5145 goto finish; 5146 } 5147 result = OSKext::loadKextWithIdentifier(kextIdentifier.get(), 5148 NULL /* kextRef */, 5149 allowDeferFlag, delayAutounloadFlag, 5150 startOpt, startMatchingOpt, personalityNames); 5151 5152 finish: 5153 return result; 5154 } 5155 5156 OSReturn 5157 OSKext::loadKextWithIdentifier( 5158 OSString * kextIdentifier, 5159 OSSharedPtr<OSObject> &kextRef, 5160 Boolean allowDeferFlag, 5161 Boolean delayAutounloadFlag, 5162 OSKextExcludeLevel startOpt, 5163 OSKextExcludeLevel startMatchingOpt, 5164 OSArray * personalityNames) 5165 { 5166 OSObject * kextRefRaw = NULL; 5167 OSReturn result; 5168 5169 result = loadKextWithIdentifier(kextIdentifier, 5170 &kextRefRaw, 5171 allowDeferFlag, 5172 delayAutounloadFlag, 5173 startOpt, 5174 startMatchingOpt, 5175 personalityNames); 5176 if ((kOSReturnSuccess == result) && kextRefRaw) { 5177 kextRef.reset(kextRefRaw, OSNoRetain); 5178 } 5179 return result; 5180 } 5181 5182 /********************************************************************* 5183 *********************************************************************/ 5184 OSReturn 5185 OSKext::loadKextWithIdentifier( 5186 OSString * kextIdentifier, 5187 OSObject ** kextRef, 5188 Boolean allowDeferFlag, 5189 Boolean delayAutounloadFlag, 5190 OSKextExcludeLevel startOpt, 5191 OSKextExcludeLevel startMatchingOpt, 5192 OSArray * personalityNames) 5193 { 5194 OSReturn result = kOSReturnError; 5195 OSReturn pingResult = kOSReturnError; 5196 OSKext * theKext = NULL; // do not release 5197 OSSharedPtr<OSDictionary> loadRequest; 5198 OSSharedPtr<const OSSymbol> kextIdentifierSymbol; 5199 5200 if (kextRef) { 5201 *kextRef = NULL; 5202 } 5203 5204 IORecursiveLockLock(sKextLock); 5205 5206 if (!kextIdentifier) { 5207 result = kOSKextReturnInvalidArgument; 5208 goto finish; 5209 } 5210 5211 OSKext::recordIdentifierRequest(kextIdentifier); 5212 5213 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 5214 if (!theKext) { 5215 if (!allowDeferFlag) { 5216 OSKextLog(/* kext */ NULL, 5217 kOSKextLogErrorLevel | 5218 kOSKextLogLoadFlag, 5219 "Can't load kext %s - not found.", 5220 kextIdentifier->getCStringNoCopy()); 5221 goto finish; 5222 } 5223 5224 if (!sKernelRequestsEnabled) { 5225 OSKextLog(theKext, 5226 kOSKextLogErrorLevel | 5227 kOSKextLogLoadFlag, 5228 "Can't load kext %s - requests to user space are disabled.", 5229 kextIdentifier->getCStringNoCopy()); 5230 result = kOSKextReturnDisabled; 5231 goto finish; 5232 } 5233 5234 /* Create a new request unless one is already sitting 5235 * in sKernelRequests for this bundle identifier 5236 */ 5237 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 5238 if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) { 5239 result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad, 5240 loadRequest); 5241 if (result != kOSReturnSuccess) { 5242 goto finish; 5243 } 5244 if (!_OSKextSetRequestArgument(loadRequest.get(), 5245 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 5246 result = kOSKextReturnNoMemory; 5247 goto finish; 5248 } 5249 if (!sKernelRequests->setObject(loadRequest.get())) { 5250 result = kOSKextReturnNoMemory; 5251 goto finish; 5252 } 5253 5254 if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) { 5255 result = kOSKextReturnNoMemory; 5256 goto finish; 5257 } 5258 5259 OSKextLog(theKext, 5260 kOSKextLogDebugLevel | 5261 kOSKextLogLoadFlag, 5262 "Kext %s not found; queued load request to user space.", 5263 kextIdentifier->getCStringNoCopy()); 5264 } 5265 5266 pingResult = OSKext::pingIOKitDaemon(); 5267 if (pingResult == kOSKextReturnDisabled) { 5268 OSKextLog(/* kext */ NULL, 5269 ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) | 5270 kOSKextLogLoadFlag, 5271 "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.", 5272 kextIdentifier->getCStringNoCopy()); 5273 } 5274 5275 result = kOSKextReturnDeferred; 5276 goto finish; 5277 } 5278 5279 result = theKext->load(startOpt, startMatchingOpt, personalityNames); 5280 5281 if (result != kOSReturnSuccess) { 5282 OSKextLog(theKext, 5283 kOSKextLogErrorLevel | 5284 kOSKextLogLoadFlag, 5285 "Failed to load kext %s (error 0x%x).", 5286 kextIdentifier->getCStringNoCopy(), (int)result); 5287 5288 if (theKext->kc_type == KCKindUnknown) { 5289 OSKext::removeKext(theKext, 5290 /* terminateService/removePersonalities */ true); 5291 } 5292 goto finish; 5293 } 5294 5295 if (delayAutounloadFlag) { 5296 OSKextLog(theKext, 5297 kOSKextLogProgressLevel | 5298 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 5299 "Setting delayed autounload for %s.", 5300 kextIdentifier->getCStringNoCopy()); 5301 theKext->flags.delayAutounload = 1; 5302 } 5303 5304 finish: 5305 if ((kOSReturnSuccess == result) && kextRef) { 5306 *kextRef = theKext; 5307 theKext->matchingRefCount++; 5308 theKext->retain(); 5309 } 5310 5311 IORecursiveLockUnlock(sKextLock); 5312 5313 return result; 5314 } 5315 5316 /********************************************************************* 5317 *********************************************************************/ 5318 /* static */ 5319 OSReturn 5320 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict) 5321 { 5322 OSReturn result = kOSReturnError; 5323 5324 OSBoolean *delayAutounloadBool = NULL; // do not release 5325 OSNumber *startKextExcludeNum = NULL; // do not release 5326 OSNumber *startMatchingExcludeNum = NULL; // do not release 5327 OSArray *personalityNames = NULL; // do not release 5328 5329 /* 5330 * Default values for these options: 5331 * regular autounload behavior 5332 * start the kext 5333 * send all personalities to the catalog 5334 */ 5335 Boolean delayAutounload = false; 5336 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 5337 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone; 5338 5339 IORecursiveLockLock(sKextLock); 5340 5341 OSKextLog(/* kext */ NULL, 5342 kOSKextLogDebugLevel | 5343 kOSKextLogIPCFlag, 5344 "Received kext KC load request from user space."); 5345 5346 /* Regardless of processing, the fact that we have gotten here means some 5347 * user-space program is up and talking to us, so we'll switch our kext 5348 * registration to reflect that. 5349 */ 5350 if (!sUserLoadsActive) { 5351 OSKextLog(/* kext */ NULL, 5352 kOSKextLogProgressLevel | 5353 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 5354 "Switching to late startup (user-space) kext loading policy."); 5355 sUserLoadsActive = true; 5356 } 5357 5358 delayAutounloadBool = OSDynamicCast(OSBoolean, 5359 _OSKextGetRequestArgument(requestDict, 5360 kKextRequestArgumentDelayAutounloadKey)); 5361 startKextExcludeNum = OSDynamicCast(OSNumber, 5362 _OSKextGetRequestArgument(requestDict, 5363 kKextRequestArgumentStartExcludeKey)); 5364 startMatchingExcludeNum = OSDynamicCast(OSNumber, 5365 _OSKextGetRequestArgument(requestDict, 5366 kKextRequestArgumentStartMatchingExcludeKey)); 5367 personalityNames = OSDynamicCast(OSArray, 5368 _OSKextGetRequestArgument(requestDict, 5369 kKextRequestArgumentPersonalityNamesKey)); 5370 5371 if (delayAutounloadBool) { 5372 delayAutounload = delayAutounloadBool->getValue(); 5373 } 5374 if (startKextExcludeNum) { 5375 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 5376 } 5377 if (startMatchingExcludeNum) { 5378 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 5379 } 5380 5381 OSKextLog(/* kext */ NULL, 5382 kOSKextLogProgressLevel | 5383 kOSKextLogIPCFlag, 5384 "Received request from user space to load KC kext %s.", 5385 theKext->getIdentifierCString()); 5386 5387 /* this could be in the Auxiliary KC, so record the load request */ 5388 OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier())); 5389 5390 /* 5391 * Load the kext 5392 */ 5393 result = theKext->load(startKextExcludeLevel, 5394 startMatchingExcludeLevel, personalityNames); 5395 5396 if (result != kOSReturnSuccess) { 5397 OSKextLog(theKext, 5398 kOSKextLogErrorLevel | 5399 kOSKextLogLoadFlag, 5400 "Failed to load kext %s (error 0x%x).", 5401 theKext->getIdentifierCString(), (int)result); 5402 5403 OSKext::removeKext(theKext, 5404 /* terminateService/removePersonalities */ true); 5405 goto finish; 5406 } else { 5407 OSKextLog(theKext, 5408 kOSKextLogProgressLevel | 5409 kOSKextLogLoadFlag, 5410 "Kext %s Loaded successfully from %s KC", 5411 theKext->getIdentifierCString(), theKext->getKCTypeString()); 5412 } 5413 5414 if (delayAutounload) { 5415 OSKextLog(theKext, 5416 kOSKextLogProgressLevel | 5417 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 5418 "Setting delayed autounload for %s.", 5419 theKext->getIdentifierCString()); 5420 theKext->flags.delayAutounload = 1; 5421 } 5422 5423 finish: 5424 IORecursiveLockUnlock(sKextLock); 5425 5426 return result; 5427 } 5428 5429 /********************************************************************* 5430 *********************************************************************/ 5431 /* static */ 5432 OSReturn 5433 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict) 5434 { 5435 OSReturn result = kOSReturnError; 5436 OSDictionary *anInfoDict = NULL; // do not release 5437 5438 anInfoDict = OSDynamicCast(OSDictionary, 5439 _OSKextGetRequestArgument(requestDict, 5440 kKextRequestArgumentCodelessInfoKey)); 5441 if (anInfoDict == NULL) { 5442 OSKextLog(/* kext */ NULL, 5443 kOSKextLogErrorLevel | 5444 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 5445 "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.", 5446 kextIdentifier->getCStringNoCopy()); 5447 return kOSKextReturnInvalidArgument; 5448 } 5449 5450 IORecursiveLockLock(sKextLock); 5451 5452 OSKextLog(/* kext */ NULL, 5453 kOSKextLogProgressLevel | 5454 kOSKextLogIPCFlag, 5455 "Received request from user space to load codeless kext %s.", 5456 kextIdentifier->getCStringNoCopy()); 5457 5458 { 5459 // instantiate a new kext, and don't hold a reference 5460 // (the kext subsystem will hold one implicitly) 5461 OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict); 5462 if (!newKext) { 5463 OSKextLog(/* kext */ NULL, 5464 kOSKextLogErrorLevel | 5465 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 5466 "Could not instantiate codeless kext."); 5467 result = kOSKextReturnNotLoadable; 5468 goto finish; 5469 } 5470 if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) { 5471 OSKextLog(/* kext */ NULL, 5472 kOSKextLogErrorLevel | 5473 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 5474 "Codeless kext identifiers don't match '%s' != '%s'", 5475 kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString()); 5476 5477 OSKext::removeKext(newKext.get(), false); 5478 result = kOSKextReturnInvalidArgument; 5479 goto finish; 5480 } 5481 5482 /* Record the request for the codeless kext */ 5483 OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier())); 5484 5485 result = kOSReturnSuccess; 5486 /* Send the kext's personalities to the IOCatalog. This is an explicit load. */ 5487 result = newKext->sendPersonalitiesToCatalog(true, NULL); 5488 } 5489 5490 finish: 5491 IORecursiveLockUnlock(sKextLock); 5492 5493 return result; 5494 } 5495 5496 /********************************************************************* 5497 *********************************************************************/ 5498 /* static */ 5499 void 5500 OSKext::dropMatchingReferences( 5501 OSSet * kexts) 5502 { 5503 IORecursiveLockLock(sKextLock); 5504 kexts->iterateObjects(^bool (OSObject * obj) { 5505 OSKext * thisKext = OSDynamicCast(OSKext, obj); 5506 if (!thisKext) { 5507 return false; 5508 } 5509 thisKext->matchingRefCount--; 5510 return false; 5511 }); 5512 IORecursiveLockUnlock(sKextLock); 5513 } 5514 5515 /********************************************************************* 5516 *********************************************************************/ 5517 /* static */ 5518 void 5519 OSKext::recordIdentifierRequest( 5520 OSString * kextIdentifier) 5521 { 5522 OSSharedPtr<const OSSymbol> kextIdentifierSymbol; 5523 bool fail = false; 5524 5525 if (!sAllKextLoadIdentifiers || !kextIdentifier) { 5526 goto finish; 5527 } 5528 5529 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 5530 if (!kextIdentifierSymbol) { 5531 // xxx - this is really a basic alloc failure 5532 fail = true; 5533 goto finish; 5534 } 5535 5536 IORecursiveLockLock(sKextLock); 5537 if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) { 5538 if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) { 5539 fail = true; 5540 } else { 5541 // xxx - need to find a way to associate this whole func w/the kext 5542 OSKextLog(/* kext */ NULL, 5543 // xxx - check level 5544 kOSKextLogStepLevel | 5545 kOSKextLogArchiveFlag, 5546 "Recorded kext %s as a candidate for inclusion in prelinked kernel.", 5547 kextIdentifier->getCStringNoCopy()); 5548 } 5549 } 5550 IORecursiveLockUnlock(sKextLock); 5551 5552 finish: 5553 5554 if (fail) { 5555 OSKextLog(/* kext */ NULL, 5556 kOSKextLogErrorLevel | 5557 kOSKextLogArchiveFlag, 5558 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.", 5559 kextIdentifier->getCStringNoCopy()); 5560 } 5561 return; 5562 } 5563 5564 /********************************************************************* 5565 *********************************************************************/ 5566 OSReturn 5567 OSKext::load( 5568 OSKextExcludeLevel startOpt, 5569 OSKextExcludeLevel startMatchingOpt, 5570 OSArray * personalityNames) 5571 { 5572 OSReturn result = kOSReturnError; 5573 OSKextExcludeLevel dependenciesStartOpt = startOpt; 5574 OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt; 5575 unsigned int i, count; 5576 Boolean alreadyLoaded = false; 5577 OSKext * lastLoadedKext = NULL; // do not release 5578 5579 if (isInExcludeList()) { 5580 OSKextLog(this, 5581 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | 5582 kOSKextLogLoadFlag, 5583 "Kext %s is in exclude list, not loadable", 5584 getIdentifierCString()); 5585 5586 result = kOSKextReturnNotLoadable; 5587 goto finish; 5588 } 5589 if (!isLoadable()) { 5590 OSKextLog(this, 5591 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | 5592 kOSKextLogLoadFlag, 5593 "Kext %s is not loadable", 5594 getIdentifierCString()); 5595 5596 result = kOSKextReturnNotLoadable; 5597 goto finish; 5598 } 5599 5600 if (isLoaded()) { 5601 alreadyLoaded = true; 5602 result = kOSReturnSuccess; 5603 5604 OSKextLog(this, 5605 kOSKextLogDebugLevel | 5606 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 5607 "Kext %s is already loaded.", 5608 getIdentifierCString()); 5609 goto loaded; 5610 } 5611 5612 #if CONFIG_MACF 5613 /* 5614 * On kxld and on embedded, only call into the MAC hook when on a 5615 * user thread, for access control over userspace kextloads. 5616 * 5617 * On non-kxld systems, additionally check the MAC hook for kexts in 5618 * the Pageable and Aux KCs, regardless of whether we are on a user 5619 * thread or not. This means on Apple silicon devices that the MAC 5620 * hook will only be useful to block 3rd party kexts loaded via 5621 * matching, and any kexts loaded from userspace kextloads. 5622 * 5623 * Note that this should _not_ be called on kexts loaded from the 5624 * kernel bootstrap thread as the kernel proc's cred struct is not 5625 * yet initialized! This won't happen on macOS because all the kexts 5626 * in the BootKC are self-contained and their kc_type = KCKindPrimary. 5627 */ 5628 if (current_task() != kernel_task 5629 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD 5630 || (kc_type != KCKindPrimary && kc_type != KCKindUnknown) 5631 #endif 5632 ) { 5633 int macCheckResult = 0; 5634 kauth_cred_t cred = NULL; 5635 5636 cred = kauth_cred_get_with_ref(); 5637 macCheckResult = mac_kext_check_load(cred, getIdentifierCString()); 5638 kauth_cred_unref(&cred); 5639 5640 if (macCheckResult != 0) { 5641 result = kOSReturnError; 5642 OSKextLog(this, 5643 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5644 "Failed to load kext %s (MAC policy error 0x%x).", 5645 getIdentifierCString(), macCheckResult); 5646 goto finish; 5647 } 5648 } 5649 #endif /* CONFIG_MACF */ 5650 5651 if (!sLoadEnabled) { 5652 OSKextLog(this, 5653 kOSKextLogErrorLevel | 5654 kOSKextLogLoadFlag, 5655 "Kext loading is disabled (attempt to load kext %s).", 5656 getIdentifierCString()); 5657 result = kOSKextReturnDisabled; 5658 goto finish; 5659 } 5660 5661 /* If we've pushed the next available load tag to the invalid value, 5662 * we can't load any more kexts. 5663 */ 5664 if (sNextLoadTag == kOSKextInvalidLoadTag) { 5665 OSKextLog(this, 5666 kOSKextLogErrorLevel | 5667 kOSKextLogLoadFlag, 5668 "Can't load kext %s - no more load tags to assign.", 5669 getIdentifierCString()); 5670 result = kOSKextReturnNoResources; 5671 goto finish; 5672 } 5673 5674 /* This is a bit of a hack, because we shouldn't be handling 5675 * personalities within the load function. 5676 */ 5677 if (!declaresExecutable()) { 5678 /* There is a special case where a non-executable kext can be loaded: the 5679 * AppleKextExcludeList. Detect that special kext by bundle identifier and 5680 * load its metadata into the global data structures, if appropriate 5681 */ 5682 if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) { 5683 boolean_t updated = updateExcludeList(infoDict.get()); 5684 if (updated) { 5685 OSKextLog(this, 5686 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 5687 "KextExcludeList was updated to version: %lld", sExcludeListVersion); 5688 } 5689 } 5690 5691 if (isDriverKit()) { 5692 if (loadTag == 0) { 5693 sLoadedDriverKitKexts->setObject(this); 5694 loadTag = sNextLoadTag++; 5695 } 5696 } 5697 result = kOSReturnSuccess; 5698 goto loaded; 5699 } 5700 5701 /* Are we in safe boot? 5702 */ 5703 if (sSafeBoot && !isLoadableInSafeBoot()) { 5704 OSKextLog(this, 5705 kOSKextLogErrorLevel | 5706 kOSKextLogLoadFlag, 5707 "Can't load kext %s - not loadable during safe boot.", 5708 getIdentifierCString()); 5709 result = kOSKextReturnBootLevel; 5710 goto finish; 5711 } 5712 5713 OSKextLog(this, 5714 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5715 "Loading kext %s.", 5716 getIdentifierCString()); 5717 5718 #if !VM_MAPPED_KEXTS 5719 if (isPrelinked() == false) { 5720 OSKextLog(this, 5721 kOSKextLogErrorLevel | 5722 kOSKextLogLoadFlag, 5723 "Can't load kext %s - not in a kext collection.", 5724 getIdentifierCString()); 5725 result = kOSKextReturnDisabled; 5726 goto finish; 5727 } 5728 #endif /* defined(__x86_64__) */ 5729 5730 #if CONFIG_KXLD 5731 if (!sKxldContext) { 5732 kern_return_t kxldResult; 5733 kxldResult = kxld_create_context(&sKxldContext, &kern_allocate, 5734 &kxld_log_callback, /* Flags */ (KXLDFlags) 0, 5735 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0); 5736 if (kxldResult) { 5737 OSKextLog(this, 5738 kOSKextLogErrorLevel | 5739 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 5740 "Can't load kext %s - failed to create link context.", 5741 getIdentifierCString()); 5742 result = kOSKextReturnNoMemory; 5743 goto finish; 5744 } 5745 } 5746 #endif // CONFIG_KXLD 5747 5748 /* We only need to resolve dependencies once for the whole graph, but 5749 * resolveDependencies will just return if there's no work to do, so it's 5750 * safe to call it more than once. 5751 */ 5752 if (!resolveDependencies()) { 5753 // xxx - check resolveDependencies() for log msg 5754 OSKextLog(this, 5755 kOSKextLogErrorLevel | 5756 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 5757 "Can't load kext %s - failed to resolve library dependencies.", 5758 getIdentifierCString()); 5759 result = kOSKextReturnDependencies; 5760 goto finish; 5761 } 5762 5763 /* If we are excluding just the kext being loaded now (and not its 5764 * dependencies), drop the exclusion level to none so dependencies 5765 * start and/or add their personalities. 5766 */ 5767 if (dependenciesStartOpt == kOSKextExcludeKext) { 5768 dependenciesStartOpt = kOSKextExcludeNone; 5769 } 5770 5771 if (dependenciesStartMatchingOpt == kOSKextExcludeKext) { 5772 dependenciesStartMatchingOpt = kOSKextExcludeNone; 5773 } 5774 5775 /* Load the dependencies, recursively. 5776 */ 5777 count = getNumDependencies(); 5778 for (i = 0; i < count; i++) { 5779 OSKext * dependency = OSDynamicCast(OSKext, 5780 dependencies->getObject(i)); 5781 if (dependency == NULL) { 5782 OSKextLog(this, 5783 kOSKextLogErrorLevel | 5784 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 5785 "Internal error loading kext %s; dependency disappeared.", 5786 getIdentifierCString()); 5787 result = kOSKextReturnInternalError; 5788 goto finish; 5789 } 5790 5791 /* Dependencies must be started accorting to the opt, 5792 * but not given the personality names of the main kext. 5793 */ 5794 result = dependency->load(dependenciesStartOpt, 5795 dependenciesStartMatchingOpt, 5796 /* personalityNames */ NULL); 5797 if (result != KERN_SUCCESS) { 5798 OSKextLog(this, 5799 kOSKextLogErrorLevel | 5800 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 5801 "Dependency %s of kext %s failed to load.", 5802 dependency->getIdentifierCString(), 5803 getIdentifierCString()); 5804 5805 OSKext::removeKext(dependency, 5806 /* terminateService/removePersonalities */ true); 5807 result = kOSKextReturnDependencyLoadError; 5808 5809 goto finish; 5810 } 5811 } 5812 5813 result = loadExecutable(); 5814 if (result != KERN_SUCCESS) { 5815 goto finish; 5816 } 5817 5818 pendingPgoHead.next = &pendingPgoHead; 5819 pendingPgoHead.prev = &pendingPgoHead; 5820 5821 // The kernel PRNG is not initialized when the first kext is 5822 // loaded, so use early random 5823 uuid_generate_early_random(instance_uuid); 5824 account = IOMallocType(OSKextAccount); 5825 5826 account->loadTag = kmod_info->id; 5827 account->site.refcount = 0; 5828 account->site.flags = VM_TAG_KMOD; 5829 5830 #if DEVELOPMENT || DEBUG 5831 /* Setup the task reference group. */ 5832 (void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name), 5833 "task_%s", getIdentifierCString()); 5834 account->task_refgrp.grp_name = account->task_refgrp_name; 5835 account->task_refgrp.grp_parent = &task_external_refgrp; 5836 os_ref_log_init(&account->task_refgrp); 5837 #endif /* DEVELOPMENT || DEBUG */ 5838 5839 account->kext = this; 5840 if (gIOSurfaceIdentifier == bundleID) { 5841 vm_tag_alloc(&account->site); 5842 gIOSurfaceTag = account->site.tag; 5843 } 5844 5845 flags.loaded = true; 5846 5847 /* Add the kext to the list of loaded kexts and update the kmod_info 5848 * struct to point to that of the last loaded kext (which is the way 5849 * it's always been done, though I'd rather do them in order now). 5850 */ 5851 lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 5852 sLoadedKexts->setObject(this); 5853 5854 /* Keep the kernel itself out of the kmod list. 5855 */ 5856 if (lastLoadedKext->isKernel()) { 5857 lastLoadedKext = NULL; 5858 } 5859 5860 if (lastLoadedKext) { 5861 kmod_info->next = lastLoadedKext->kmod_info; 5862 } 5863 5864 notifyKextLoadObservers(this, kmod_info); 5865 5866 /* Make the global kmod list point at the just-loaded kext. Note that the 5867 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard, 5868 * although we do report it in kextstat these days by using the newer 5869 * OSArray of loaded kexts, which does contain it. 5870 * 5871 * (The OSKext object representing the kernel doesn't even have a kmod_info 5872 * struct, though I suppose we could stick a pointer to it from the 5873 * static struct in OSRuntime.cpp.) 5874 */ 5875 kmod = kmod_info; 5876 5877 /* Save the list of loaded kexts in case we panic. 5878 */ 5879 OSKext::saveLoadedKextPanicList(); 5880 5881 if (isExecutable()) { 5882 OSKext::updateLoadedKextSummaries(); 5883 savePanicString(/* isLoading */ true); 5884 5885 #if CONFIG_DTRACE 5886 registerWithDTrace(); 5887 #else 5888 jettisonLinkeditSegment(); 5889 #endif /* CONFIG_DTRACE */ 5890 5891 #if !VM_MAPPED_KEXTS 5892 /* If there is a page (or more) worth of padding after the end 5893 * of the last data section but before the end of the data segment 5894 * then free it in the same manner the LinkeditSegment is freed 5895 */ 5896 jettisonDATASegmentPadding(); 5897 #endif 5898 } 5899 5900 loaded: 5901 if (isExecutable() && !flags.started) { 5902 if (startOpt == kOSKextExcludeNone) { 5903 result = start(); 5904 if (result != kOSReturnSuccess) { 5905 OSKextLog(this, 5906 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5907 "Kext %s start failed (result 0x%x).", 5908 getIdentifierCString(), result); 5909 result = kOSKextReturnStartStopError; 5910 } 5911 } 5912 } 5913 5914 /* If not excluding matching, send the personalities to the kernel. 5915 * This never affects the result of the load operation. 5916 * This is a bit of a hack, because we shouldn't be handling 5917 * personalities within the load function. 5918 */ 5919 if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) { 5920 result = sendPersonalitiesToCatalog(true, personalityNames); 5921 } 5922 5923 finish: 5924 5925 if (result != kOSReturnSuccess) { 5926 OSKextLog(this, 5927 kOSKextLogErrorLevel | 5928 kOSKextLogLoadFlag, 5929 "Kext %s failed to load (0x%x).", 5930 getIdentifierCString(), (int)result); 5931 } else if (!alreadyLoaded) { 5932 OSKextLog(this, 5933 kOSKextLogProgressLevel | 5934 kOSKextLogLoadFlag, 5935 "Kext %s loaded.", 5936 getIdentifierCString()); 5937 5938 queueKextNotification(kKextRequestPredicateLoadNotification, 5939 OSDynamicCast(OSString, bundleID.get())); 5940 } 5941 return result; 5942 } 5943 5944 #if CONFIG_KXLD 5945 /********************************************************************* 5946 * 5947 *********************************************************************/ 5948 static char * 5949 strdup(const char * string) 5950 { 5951 char * result = NULL; 5952 size_t size; 5953 5954 if (!string) { 5955 goto finish; 5956 } 5957 5958 size = 1 + strlen(string); 5959 result = (char *)kheap_alloc_tag(KHEAP_DATA_BUFFERS, size, 5960 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 5961 if (!result) { 5962 goto finish; 5963 } 5964 5965 memcpy(result, string, size); 5966 5967 finish: 5968 return result; 5969 } 5970 #endif // CONFIG_KXLD 5971 5972 /********************************************************************* 5973 * 5974 *********************************************************************/ 5975 5976 kernel_section_t * 5977 OSKext::lookupSection(const char *segname, const char *secname) 5978 { 5979 kernel_section_t * found_section = NULL; 5980 kernel_mach_header_t * mh = NULL; 5981 kernel_segment_command_t * seg = NULL; 5982 kernel_section_t * sec = NULL; 5983 5984 if (!linkedExecutable) { 5985 return NULL; 5986 } 5987 5988 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 5989 5990 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 5991 if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) { 5992 continue; 5993 } 5994 5995 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 5996 if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) { 5997 found_section = sec; 5998 goto out; 5999 } 6000 } 6001 } 6002 6003 out: 6004 return found_section; 6005 } 6006 6007 /********************************************************************* 6008 * 6009 *********************************************************************/ 6010 6011 OSReturn 6012 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides) 6013 { 6014 OSReturn result = kOSKextReturnBadData; 6015 kernel_mach_header_t * mh = NULL; 6016 kernel_segment_command_t * seg = NULL; 6017 kernel_segment_command_t * linkeditSeg = NULL; 6018 kernel_section_t * sec = NULL; 6019 char * linkeditBase = NULL; 6020 bool haveLinkeditBase = false; 6021 char * relocBase = NULL; 6022 bool haveRelocBase = false; 6023 struct dysymtab_command * dysymtab = NULL; 6024 struct linkedit_data_command * segmentSplitInfo = NULL; 6025 struct symtab_command * symtab = NULL; 6026 kernel_nlist_t * sym = NULL; 6027 struct relocation_info * reloc = NULL; 6028 uint32_t i = 0; 6029 int reloc_size; 6030 vm_offset_t new_kextsize; 6031 6032 if (linkedExecutable == NULL || flags.builtin) { 6033 result = kOSReturnSuccess; 6034 goto finish; 6035 } 6036 6037 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 6038 if (kernel_mach_header_is_in_fileset(mh)) { 6039 // kexts in filesets are slid as part of collection sliding 6040 result = kOSReturnSuccess; 6041 goto finish; 6042 } 6043 6044 segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO); 6045 6046 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 6047 if (!seg->vmaddr) { 6048 continue; 6049 } 6050 6051 seg->vmaddr = ml_static_slide(seg->vmaddr); 6052 6053 #if KASLR_KEXT_DEBUG 6054 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n", 6055 seg->segname, 6056 (unsigned long)ml_static_unslide(seg->vmaddr), 6057 (unsigned long)seg->vmaddr); 6058 #endif 6059 6060 if (!haveRelocBase) { 6061 relocBase = (char *) seg->vmaddr; 6062 haveRelocBase = true; 6063 } 6064 if (!strcmp(seg->segname, "__LINKEDIT")) { 6065 linkeditBase = (char *) seg->vmaddr - seg->fileoff; 6066 haveLinkeditBase = true; 6067 linkeditSeg = seg; 6068 } 6069 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 6070 sec->addr = ml_static_slide(sec->addr); 6071 6072 #if KASLR_KEXT_DEBUG 6073 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n", 6074 sec->sectname, 6075 (unsigned long)ml_static_unslide(sec->addr), 6076 (unsigned long)sec->addr); 6077 #endif 6078 } 6079 } 6080 6081 dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB); 6082 6083 symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB); 6084 6085 if (symtab != NULL && doCoalescedSlides == false) { 6086 /* Some pseudo-kexts have symbol tables without segments. 6087 * Ignore them. */ 6088 if (symtab->nsyms > 0 && haveLinkeditBase) { 6089 sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff); 6090 for (i = 0; i < symtab->nsyms; i++) { 6091 if (sym[i].n_type & N_STAB) { 6092 continue; 6093 } 6094 sym[i].n_value = ml_static_slide(sym[i].n_value); 6095 6096 #if KASLR_KEXT_DEBUG 6097 #define MAX_SYMS_TO_LOG 5 6098 if (i < MAX_SYMS_TO_LOG) { 6099 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n", 6100 (unsigned long)ml_static_unslide(sym[i].n_value), 6101 (unsigned long)sym[i].n_value); 6102 } 6103 #endif 6104 } 6105 } 6106 } 6107 6108 if (dysymtab != NULL && doCoalescedSlides == false) { 6109 if (dysymtab->nextrel > 0) { 6110 OSKextLog(this, 6111 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6112 kOSKextLogLinkFlag, 6113 "Sliding kext %s: External relocations found.", 6114 getIdentifierCString()); 6115 goto finish; 6116 } 6117 6118 if (dysymtab->nlocrel > 0) { 6119 if (!haveLinkeditBase) { 6120 OSKextLog(this, 6121 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6122 kOSKextLogLinkFlag, 6123 "Sliding kext %s: No linkedit segment.", 6124 getIdentifierCString()); 6125 goto finish; 6126 } 6127 6128 if (!haveRelocBase) { 6129 OSKextLog(this, 6130 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6131 kOSKextLogLinkFlag, 6132 #if __x86_64__ 6133 "Sliding kext %s: No writable segments.", 6134 #else 6135 "Sliding kext %s: No segments.", 6136 #endif 6137 getIdentifierCString()); 6138 goto finish; 6139 } 6140 6141 reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff); 6142 reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info); 6143 6144 for (i = 0; i < dysymtab->nlocrel; i++) { 6145 if (reloc[i].r_extern != 0 6146 || reloc[i].r_type != 0 6147 || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2) 6148 ) { 6149 OSKextLog(this, 6150 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6151 kOSKextLogLinkFlag, 6152 "Sliding kext %s: Unexpected relocation found.", 6153 getIdentifierCString()); 6154 goto finish; 6155 } 6156 if (reloc[i].r_pcrel != 0) { 6157 continue; 6158 } 6159 uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address); 6160 *relocAddr = ml_static_slide(*relocAddr); 6161 6162 #if KASLR_KEXT_DEBUG 6163 #define MAX_DYSYMS_TO_LOG 5 6164 if (i < MAX_DYSYMS_TO_LOG) { 6165 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n", 6166 (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))), 6167 (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address))); 6168 } 6169 #endif 6170 } 6171 6172 /* We should free these relocations, not just delete the reference to them. 6173 * <rdar://problem/10535549> Free relocations from PIE kexts. 6174 * 6175 * For now, we do not free LINKEDIT for kexts with split segments. 6176 */ 6177 new_kextsize = round_page(kmod_info->size - reloc_size); 6178 if (new_kextsize > UINT_MAX) { 6179 OSKextLog(this, 6180 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6181 kOSKextLogLinkFlag, 6182 "Kext %s: new kext size is too large.", 6183 getIdentifierCString()); 6184 goto finish; 6185 } 6186 if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) { 6187 vm_offset_t endofkext = kmod_info->address + kmod_info->size; 6188 vm_offset_t new_endofkext = kmod_info->address + new_kextsize; 6189 vm_offset_t endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size); 6190 size_t bytes_remaining = endofkext - endofrelocInfo; 6191 OSSharedPtr<OSData> new_osdata; 6192 6193 /* fix up symbol offsets if they are after the dsymtab local relocs */ 6194 if (symtab) { 6195 if (dysymtab->locreloff < symtab->symoff) { 6196 symtab->symoff -= reloc_size; 6197 } 6198 if (dysymtab->locreloff < symtab->stroff) { 6199 symtab->stroff -= reloc_size; 6200 } 6201 } 6202 if (dysymtab->locreloff < dysymtab->extreloff) { 6203 dysymtab->extreloff -= reloc_size; 6204 } 6205 6206 /* move data behind reloc info down to new offset */ 6207 if (endofrelocInfo < endofkext) { 6208 memcpy(reloc, (void *)endofrelocInfo, bytes_remaining); 6209 } 6210 6211 /* Create a new OSData for the smaller kext object and reflect 6212 * new linkedit segment size. 6213 */ 6214 linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size); 6215 linkeditSeg->filesize = linkeditSeg->vmsize; 6216 6217 new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize); 6218 if (new_osdata) { 6219 /* Fix up kmod info and linkedExecutable. 6220 */ 6221 kmod_info->size = new_kextsize; 6222 #if VM_MAPPED_KEXTS 6223 new_osdata->setDeallocFunction(osdata_kext_free); 6224 #else 6225 new_osdata->setDeallocFunction(osdata_phys_free); 6226 #endif 6227 linkedExecutable->setDeallocFunction(NULL); 6228 linkedExecutable = os::move(new_osdata); 6229 6230 #if VM_MAPPED_KEXTS 6231 kext_free(new_endofkext, (endofkext - new_endofkext)); 6232 #else 6233 ml_static_mfree(new_endofkext, (endofkext - new_endofkext)); 6234 #endif 6235 } 6236 } 6237 dysymtab->nlocrel = 0; 6238 dysymtab->locreloff = 0; 6239 } 6240 } 6241 6242 result = kOSReturnSuccess; 6243 finish: 6244 return result; 6245 } 6246 6247 /********************************************************************* 6248 * called only by load() 6249 *********************************************************************/ 6250 OSReturn 6251 OSKext::loadExecutable() 6252 { 6253 OSReturn result = kOSReturnError; 6254 OSSharedPtr<OSArray> linkDependencies; 6255 uint32_t num_kmod_refs = 0; 6256 OSData * theExecutable = NULL; // do not release 6257 OSString * versString = NULL; // do not release 6258 const char * versCString = NULL; // do not free 6259 const char * string = NULL; // do not free 6260 6261 #if CONFIG_KXLD 6262 unsigned int i; 6263 uint32_t numDirectDependencies = 0; 6264 kern_return_t kxldResult; 6265 KXLDDependency * kxlddeps = NULL; // must kfree 6266 uint32_t num_kxlddeps = 0; 6267 struct mach_header ** kxldHeaderPtr = NULL; // do not free 6268 struct mach_header * kxld_header = NULL; // xxx - need to free here? 6269 #endif // CONFIG_KXLD 6270 6271 /* We need the version string for a variety of bits below. 6272 */ 6273 versString = OSDynamicCast(OSString, 6274 getPropertyForHostArch(kCFBundleVersionKey)); 6275 if (!versString) { 6276 goto finish; 6277 } 6278 versCString = versString->getCStringNoCopy(); 6279 6280 if (isKernelComponent()) { 6281 if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) { 6282 if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) { 6283 OSKextLog(this, 6284 kOSKextLogErrorLevel | 6285 kOSKextLogLoadFlag, 6286 "Kernel component %s has incorrect version %s; " 6287 "expected %s.", 6288 getIdentifierCString(), 6289 versCString, KERNEL6_VERSION); 6290 result = kOSKextReturnInternalError; 6291 goto finish; 6292 } else if (strcmp(versCString, osrelease)) { 6293 OSKextLog(this, 6294 kOSKextLogErrorLevel | 6295 kOSKextLogLoadFlag, 6296 "Kernel component %s has incorrect version %s; " 6297 "expected %s.", 6298 getIdentifierCString(), 6299 versCString, osrelease); 6300 result = kOSKextReturnInternalError; 6301 goto finish; 6302 } 6303 } 6304 } 6305 6306 #if defined(__x86_64__) || defined(__i386__) 6307 if (flags.resetSegmentsFromVnode) { 6308 /* Fixup the chains and slide the mach headers */ 6309 kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address; 6310 6311 if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) { 6312 result = kOSKextReturnValidation; 6313 goto finish; 6314 } 6315 } 6316 #endif //(__x86_64__) || defined(__i386__) 6317 6318 if (isPrelinked()) { 6319 goto register_kmod; 6320 } 6321 6322 /* <rdar://problem/21444003> all callers must be entitled */ 6323 if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) { 6324 OSKextLog(this, 6325 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 6326 "Not entitled to link kext '%s'", 6327 getIdentifierCString()); 6328 result = kOSKextReturnNotPrivileged; 6329 goto finish; 6330 } 6331 6332 theExecutable = getExecutable(); 6333 if (!theExecutable) { 6334 if (declaresExecutable()) { 6335 OSKextLog(this, 6336 kOSKextLogErrorLevel | 6337 kOSKextLogLoadFlag, 6338 "Can't load kext %s - executable is missing.", 6339 getIdentifierCString()); 6340 result = kOSKextReturnValidation; 6341 goto finish; 6342 } 6343 goto register_kmod; 6344 } 6345 6346 if (isInterface()) { 6347 OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable); 6348 if (executableCopy) { 6349 setLinkedExecutable(executableCopy.get()); 6350 } 6351 goto register_kmod; 6352 } 6353 6354 #if CONFIG_KXLD 6355 numDirectDependencies = getNumDependencies(); 6356 6357 if (flags.hasBleedthrough) { 6358 linkDependencies = dependencies; 6359 } else { 6360 linkDependencies = OSArray::withArray(dependencies.get()); 6361 if (!linkDependencies) { 6362 OSKextLog(this, 6363 kOSKextLogErrorLevel | 6364 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 6365 "Can't allocate link dependencies to load kext %s.", 6366 getIdentifierCString()); 6367 goto finish; 6368 } 6369 6370 for (i = 0; i < numDirectDependencies; ++i) { 6371 OSKext * dependencyKext = OSDynamicCast(OSKext, 6372 dependencies->getObject(i)); 6373 dependencyKext->addBleedthroughDependencies(linkDependencies.get()); 6374 } 6375 } 6376 6377 num_kxlddeps = linkDependencies->getCount(); 6378 if (!num_kxlddeps) { 6379 OSKextLog(this, 6380 kOSKextLogErrorLevel | 6381 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 6382 "Can't load kext %s - it has no library dependencies.", 6383 getIdentifierCString()); 6384 goto finish; 6385 } 6386 6387 kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 6388 if (!kxlddeps) { 6389 OSKextLog(this, 6390 kOSKextLogErrorLevel | 6391 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 6392 "Can't allocate link context to load kext %s.", 6393 getIdentifierCString()); 6394 goto finish; 6395 } 6396 bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps)); 6397 6398 for (i = 0; i < num_kxlddeps; ++i) { 6399 OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i)); 6400 6401 if (dependency->isInterface()) { 6402 OSKext *interfaceTargetKext = NULL; //do not release 6403 OSData * interfaceTarget = NULL; //do not release 6404 6405 if (dependency->isKernelComponent()) { 6406 interfaceTargetKext = sKernelKext; 6407 interfaceTarget = sKernelKext->linkedExecutable.get(); 6408 } else { 6409 interfaceTargetKext = OSDynamicCast(OSKext, 6410 dependency->dependencies->getObject(0)); 6411 6412 interfaceTarget = interfaceTargetKext->linkedExecutable.get(); 6413 } 6414 6415 if (!interfaceTarget) { 6416 // panic? 6417 goto finish; 6418 } 6419 6420 /* The names set here aren't actually logged yet <rdar://problem/7941514>, 6421 * it will be useful to have them in the debugger. 6422 * strdup() failing isn't critical right here so we don't check that. 6423 */ 6424 kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy(); 6425 kxlddeps[i].kext_size = interfaceTarget->getLength(); 6426 kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString()); 6427 6428 if (dependency->linkedExecutable != NULL) { 6429 kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 6430 kxlddeps[i].interface_size = dependency->linkedExecutable->getLength(); 6431 } else { 6432 kxlddeps[i].interface = (u_char *) NULL; 6433 kxlddeps[i].interface_size = 0; 6434 } 6435 kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString()); 6436 } else { 6437 kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 6438 kxlddeps[i].kext_size = dependency->linkedExecutable->getLength(); 6439 kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString()); 6440 } 6441 6442 kxlddeps[i].is_direct_dependency = (i < numDirectDependencies); 6443 } 6444 6445 kxldHeaderPtr = &kxld_header; 6446 6447 #if DEBUG 6448 OSKextLog(this, 6449 kOSKextLogExplicitLevel | 6450 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 6451 "Kext %s - calling kxld_link_file:\n" 6452 " kxld_context: %p\n" 6453 " executable: %p executable_length: %d\n" 6454 " user_data: %p\n" 6455 " kxld_dependencies: %p num_dependencies: %d\n" 6456 " kxld_header_ptr: %p kmod_info_ptr: %p\n", 6457 getIdentifierCString(), sKxldContext, 6458 theExecutable->getBytesNoCopy(), theExecutable->getLength(), 6459 this, kxlddeps, num_kxlddeps, 6460 kxldHeaderPtr, &kmod_info); 6461 #endif 6462 6463 /* After this call, the linkedExecutable instance variable 6464 * should exist. 6465 */ 6466 kxldResult = kxld_link_file(sKxldContext, 6467 (u_char *)theExecutable->getBytesNoCopy(), 6468 theExecutable->getLength(), 6469 getIdentifierCString(), this, kxlddeps, num_kxlddeps, 6470 (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info); 6471 6472 if (kxldResult != KERN_SUCCESS) { 6473 // xxx - add kxldResult here? 6474 OSKextLog(this, 6475 kOSKextLogErrorLevel | 6476 kOSKextLogLoadFlag, 6477 "Can't load kext %s - link failed.", 6478 getIdentifierCString()); 6479 result = kOSKextReturnLinkError; 6480 goto finish; 6481 } 6482 6483 /* We've written data & instructions into kernel memory, so flush the data 6484 * cache and invalidate the instruction cache. 6485 * I/D caches are coherent on x86 6486 */ 6487 #if !defined(__i386__) && !defined(__x86_64__) 6488 flush_dcache(kmod_info->address, kmod_info->size, false); 6489 invalidate_icache(kmod_info->address, kmod_info->size, false); 6490 #endif 6491 6492 #else // !CONFIG_KXLD 6493 OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag, 6494 "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString()); 6495 result = kOSKextReturnLinkError; 6496 goto finish; 6497 #endif // CONFIG_KXLD 6498 6499 register_kmod: 6500 6501 if (isInterface()) { 6502 /* Whip up a fake kmod_info entry for the interface kext. 6503 */ 6504 kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO)); 6505 if (!kmod_info) { 6506 result = KERN_MEMORY_ERROR; 6507 goto finish; 6508 } 6509 6510 /* A pseudokext has almost nothing in its kmod_info struct. 6511 */ 6512 kmod_info->info_version = KMOD_INFO_VERSION; 6513 6514 /* An interface kext doesn't have a linkedExecutable, so save a 6515 * copy of the UUID out of the original executable via copyUUID() 6516 * while we still have the original executable. 6517 */ 6518 interfaceUUID = copyUUID(); 6519 } 6520 6521 kmod_info->id = loadTag = sNextLoadTag++; 6522 kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid). 6523 6524 /* Stamp the bundle ID and version from the OSKext over anything 6525 * resident inside the kmod_info. 6526 */ 6527 string = getIdentifierCString(); 6528 strlcpy(kmod_info->name, string, sizeof(kmod_info->name)); 6529 6530 string = versCString; 6531 strlcpy(kmod_info->version, string, sizeof(kmod_info->version)); 6532 6533 /* Add the dependencies' kmod_info structs as kmod_references. 6534 */ 6535 num_kmod_refs = getNumDependencies(); 6536 if (num_kmod_refs) { 6537 kmod_info->reference_list = kalloc_type_tag(kmod_reference_t, 6538 num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT); 6539 if (!kmod_info->reference_list) { 6540 result = KERN_MEMORY_ERROR; 6541 goto finish; 6542 } 6543 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 6544 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 6545 OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex)); 6546 ref->info = refKext->kmod_info; 6547 ref->info->reference_count++; 6548 6549 if (refIndex + 1 < num_kmod_refs) { 6550 ref->next = kmod_info->reference_list + refIndex + 1; 6551 } 6552 } 6553 } 6554 6555 if (kmod_info->hdr_size > UINT32_MAX) { 6556 OSKextLog(this, 6557 kOSKextLogErrorLevel | 6558 kOSKextLogLoadFlag, 6559 #if __LP64__ 6560 "Kext %s header size is too large (%lu > UINT32_MAX).", 6561 #else 6562 "Kext %s header size is too large (%u > UINT32_MAX).", 6563 #endif 6564 kmod_info->name, 6565 kmod_info->hdr_size); 6566 result = KERN_FAILURE; 6567 goto finish; 6568 } 6569 6570 if (kmod_info->size > UINT32_MAX) { 6571 OSKextLog(this, 6572 kOSKextLogErrorLevel | 6573 kOSKextLogLoadFlag, 6574 #if __LP64__ 6575 "Kext %s size is too large (%lu > UINT32_MAX).", 6576 #else 6577 "Kext %s size is too large (%u > UINT32_MAX).", 6578 #endif 6579 kmod_info->name, 6580 kmod_info->size); 6581 result = KERN_FAILURE; 6582 goto finish; 6583 } 6584 6585 if (!isInterface() && linkedExecutable) { 6586 OSKextLog(this, 6587 kOSKextLogProgressLevel | 6588 kOSKextLogLoadFlag, 6589 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).", 6590 kmod_info->name, 6591 (unsigned)kmod_info->size / PAGE_SIZE, 6592 (unsigned long)ml_static_unslide(kmod_info->address), 6593 (unsigned)kmod_info->id); 6594 } 6595 6596 /* VM protections and wiring for the Aux KC are done at collection loading time */ 6597 if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) { 6598 /* if prelinked and primary KC, VM protections are already set */ 6599 result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true); 6600 if (result != KERN_SUCCESS) { 6601 goto finish; 6602 } 6603 } 6604 6605 #if KASAN 6606 if (linkedExecutable) { 6607 kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), 6608 linkedExecutable->getLength(), getIdentifierCString()); 6609 } 6610 #else 6611 if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) { 6612 OSKextLog(this, 6613 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 6614 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n", 6615 getIdentifierCString() 6616 ); 6617 result = KERN_FAILURE; 6618 goto finish; 6619 } 6620 #endif 6621 6622 result = kOSReturnSuccess; 6623 6624 finish: 6625 6626 #if CONFIG_KXLD 6627 /* Clear up locally allocated dependency info. 6628 */ 6629 for (i = 0; i < num_kxlddeps; ++i) { 6630 size_t size; 6631 6632 if (kxlddeps[i].kext_name) { 6633 size = 1 + strlen(kxlddeps[i].kext_name); 6634 kheap_free(KHEAP_DATA_BUFFERS, kxlddeps[i].kext_name, size); 6635 } 6636 if (kxlddeps[i].interface_name) { 6637 size = 1 + strlen(kxlddeps[i].interface_name); 6638 kheap_free(KHEAP_DATA_BUFFERS, kxlddeps[i].interface_name, size); 6639 } 6640 } 6641 if (kxlddeps) { 6642 kfree_type(KXLDDependency, num_kxlddeps, kxlddeps); 6643 } 6644 #endif // CONFIG_KXLD 6645 6646 /* We no longer need the unrelocated executable (which the linker 6647 * has altered anyhow). 6648 */ 6649 setExecutable(NULL); 6650 6651 if (result != kOSReturnSuccess) { 6652 OSKextLog(this, 6653 kOSKextLogErrorLevel | 6654 kOSKextLogLoadFlag, 6655 "Failed to load executable for kext %s.", 6656 getIdentifierCString()); 6657 6658 if (kmod_info && kmod_info->reference_list) { 6659 kfree_type(kmod_reference_t, num_kmod_refs, 6660 kmod_info->reference_list); 6661 } 6662 if (isInterface()) { 6663 kfree_type(kmod_info_t, kmod_info); 6664 kmod_info = NULL; 6665 } 6666 if (kc_type == KCKindUnknown) { 6667 kmod_info = NULL; 6668 if (linkedExecutable) { 6669 linkedExecutable.reset(); 6670 } 6671 } 6672 } 6673 6674 return result; 6675 } 6676 6677 /* static */ 6678 void 6679 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh) 6680 { 6681 kernel_segment_command_t *linkeditseg = NULL; 6682 6683 linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT); 6684 if (linkeditseg == NULL) { 6685 panic("FileSet booted with no Linkedit segment"); 6686 } 6687 6688 #if VM_MAPPED_KEXTS 6689 /* BootKC on x86_64 is not vm mapped */ 6690 ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize); 6691 6692 OSKextLog(/* kext */ NULL, 6693 kOSKextLogProgressLevel | 6694 kOSKextLogGeneralFlag, 6695 "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu", 6696 linkeditseg->vmaddr, linkeditseg->vmsize); 6697 #else 6698 /* BootKC on arm64 is not vm mapped, but is slid */ 6699 vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase)); 6700 6701 ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize); 6702 6703 OSKextLog(/* kext */ NULL, 6704 kOSKextLogProgressLevel | 6705 kOSKextLogGeneralFlag, 6706 "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu", 6707 (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize); 6708 #endif /* VM_MAPPED_KEXTS */ 6709 } 6710 6711 /********************************************************************* 6712 * The linkedit segment is used by the kext linker for dependency 6713 * resolution, and by dtrace for probe initialization. We can free it 6714 * for non-library kexts, since no kexts depend on non-library kexts 6715 * by definition, once dtrace has been initialized. 6716 *********************************************************************/ 6717 void 6718 OSKext::jettisonLinkeditSegment(void) 6719 { 6720 kernel_mach_header_t * machhdr = (kernel_mach_header_t *)kmod_info->address; 6721 kernel_segment_command_t * linkedit = NULL; 6722 vm_offset_t start; 6723 vm_size_t linkeditsize, kextsize; 6724 OSSharedPtr<OSData> data; 6725 6726 if (isInFileset()) { 6727 return; 6728 } 6729 6730 #if NO_KEXTD 6731 /* We can free symbol tables for all embedded kexts because we don't 6732 * support runtime kext linking. 6733 */ 6734 if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 6735 #else 6736 if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 6737 #endif 6738 goto finish; 6739 } 6740 6741 /* Find the linkedit segment. If it's not the last segment, then freeing 6742 * it will fragment the kext into multiple VM regions, which OSKext is not 6743 * designed to handle, so we'll have to skip it. 6744 */ 6745 linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT); 6746 if (!linkedit) { 6747 goto finish; 6748 } 6749 6750 if (round_page(kmod_info->address + kmod_info->size) != 6751 round_page(linkedit->vmaddr + linkedit->vmsize)) { 6752 goto finish; 6753 } 6754 6755 /* Create a new OSData for the smaller kext object. 6756 */ 6757 linkeditsize = round_page(linkedit->vmsize); 6758 kextsize = kmod_info->size - linkeditsize; 6759 start = linkedit->vmaddr; 6760 6761 if (kextsize > UINT_MAX) { 6762 goto finish; 6763 } 6764 data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize); 6765 if (!data) { 6766 goto finish; 6767 } 6768 6769 /* Fix the kmod info and linkedExecutable. 6770 */ 6771 kmod_info->size = kextsize; 6772 6773 #if VM_MAPPED_KEXTS 6774 data->setDeallocFunction(osdata_kext_free); 6775 #else 6776 data->setDeallocFunction(osdata_phys_free); 6777 #endif 6778 linkedExecutable->setDeallocFunction(NULL); 6779 linkedExecutable = os::move(data); 6780 flags.jettisonLinkeditSeg = 1; 6781 6782 /* Free the linkedit segment. 6783 */ 6784 #if VM_MAPPED_KEXTS 6785 kext_free(start, linkeditsize); 6786 #else 6787 ml_static_mfree(start, linkeditsize); 6788 #endif 6789 6790 finish: 6791 return; 6792 } 6793 6794 /********************************************************************* 6795 * If there are whole pages that are unused betweem the last section 6796 * of the DATA segment and the end of the DATA segment then we can free 6797 * them 6798 *********************************************************************/ 6799 void 6800 OSKext::jettisonDATASegmentPadding(void) 6801 { 6802 kernel_mach_header_t * mh; 6803 kernel_segment_command_t * dataSeg; 6804 kernel_section_t * sec, * lastSec; 6805 vm_offset_t dataSegEnd, lastSecEnd; 6806 vm_size_t padSize; 6807 6808 if (flags.builtin) { 6809 return; 6810 } 6811 mh = (kernel_mach_header_t *)kmod_info->address; 6812 6813 if (isInFileset()) { 6814 return; 6815 } 6816 6817 dataSeg = getsegbynamefromheader(mh, SEG_DATA); 6818 if (dataSeg == NULL) { 6819 return; 6820 } 6821 6822 lastSec = NULL; 6823 sec = firstsect(dataSeg); 6824 while (sec != NULL) { 6825 lastSec = sec; 6826 sec = nextsect(dataSeg, sec); 6827 } 6828 6829 if (lastSec == NULL) { 6830 return; 6831 } 6832 6833 if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) || 6834 (dataSeg->vmsize != round_page(dataSeg->vmsize))) { 6835 return; 6836 } 6837 6838 dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize; 6839 lastSecEnd = round_page(lastSec->addr + lastSec->size); 6840 6841 if (dataSegEnd <= lastSecEnd) { 6842 return; 6843 } 6844 6845 padSize = dataSegEnd - lastSecEnd; 6846 6847 if (padSize >= PAGE_SIZE) { 6848 #if VM_MAPPED_KEXTS 6849 kext_free(lastSecEnd, padSize); 6850 #else 6851 ml_static_mfree(lastSecEnd, padSize); 6852 #endif 6853 } 6854 } 6855 6856 /********************************************************************* 6857 *********************************************************************/ 6858 void 6859 OSKext::setLinkedExecutable(OSData * anExecutable) 6860 { 6861 if (linkedExecutable) { 6862 panic("Attempt to set linked executable on kext " 6863 "that already has one (%s).\n", 6864 getIdentifierCString()); 6865 } 6866 linkedExecutable.reset(anExecutable, OSRetain); 6867 return; 6868 } 6869 6870 #if CONFIG_DTRACE 6871 /********************************************************************* 6872 * Go through all loaded kexts and tell them to register with dtrace. 6873 * The instance method only registers if necessary. 6874 *********************************************************************/ 6875 /* static */ 6876 void 6877 OSKext::registerKextsWithDTrace(void) 6878 { 6879 uint32_t count = sLoadedKexts->getCount(); 6880 uint32_t i; 6881 6882 IORecursiveLockLock(sKextLock); 6883 6884 for (i = 0; i < count; i++) { 6885 OSKext * thisKext = NULL; // do not release 6886 6887 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 6888 if (!thisKext || !thisKext->isExecutable()) { 6889 continue; 6890 } 6891 6892 thisKext->registerWithDTrace(); 6893 } 6894 6895 IORecursiveLockUnlock(sKextLock); 6896 6897 return; 6898 } 6899 6900 extern "C" { 6901 extern int (*dtrace_modload)(struct kmod_info *, uint32_t); 6902 extern int (*dtrace_modunload)(struct kmod_info *); 6903 }; 6904 6905 /********************************************************************* 6906 *********************************************************************/ 6907 void 6908 OSKext::registerWithDTrace(void) 6909 { 6910 /* Register kext with dtrace. A dtrace_modload failure should not 6911 * prevent a kext from loading, so we ignore the return code. 6912 */ 6913 if (!flags.dtraceInitialized && (dtrace_modload != NULL)) { 6914 uint32_t modflag = 0; 6915 OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit"); 6916 6917 #if XNU_TARGET_OS_OSX 6918 if (!sKeepSymbols && kc_type == KCKindPrimary) { 6919 if (forceInit == kOSBooleanTrue) { 6920 OSKextLog(this, 6921 kOSKextLogBasicLevel | 6922 kOSKextLogGeneralFlag, 6923 "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s", 6924 getIdentifierCString()); 6925 forceInit = kOSBooleanFalse; 6926 } 6927 /* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */ 6928 modflag |= KMOD_DTRACE_NO_KERNEL_SYMS; 6929 } 6930 #endif /* XNU_TARGET_OS_OSX */ 6931 if (forceInit == kOSBooleanTrue) { 6932 modflag |= KMOD_DTRACE_FORCE_INIT; 6933 } 6934 if (flags.builtin) { 6935 modflag |= KMOD_DTRACE_STATIC_KEXT; 6936 } 6937 6938 (void)(*dtrace_modload)(kmod_info, modflag); 6939 flags.dtraceInitialized = true; 6940 jettisonLinkeditSegment(); 6941 } 6942 return; 6943 } 6944 /********************************************************************* 6945 *********************************************************************/ 6946 void 6947 OSKext::unregisterWithDTrace(void) 6948 { 6949 /* Unregister kext with dtrace. A dtrace_modunload failure should not 6950 * prevent a kext from loading, so we ignore the return code. 6951 */ 6952 if (flags.dtraceInitialized && (dtrace_modunload != NULL)) { 6953 (void)(*dtrace_modunload)(kmod_info); 6954 flags.dtraceInitialized = false; 6955 } 6956 return; 6957 } 6958 #endif /* CONFIG_DTRACE */ 6959 6960 6961 /********************************************************************* 6962 * called only by loadExecutable() 6963 *********************************************************************/ 6964 #if !VM_MAPPED_KEXTS 6965 #if defined(__arm__) || defined(__arm64__) 6966 static inline kern_return_t 6967 OSKext_protect( 6968 kernel_mach_header_t *kext_mh, 6969 vm_map_t map, 6970 vm_map_offset_t start, 6971 vm_map_offset_t end, 6972 vm_prot_t new_prot, 6973 boolean_t set_max, 6974 kc_kind_t kc_type) 6975 { 6976 #pragma unused(kext_mh,map,kc_type) 6977 assert(map == kernel_map); // we can handle KEXTs arising from the PRELINK segment and no others 6978 assert(start <= end); 6979 if (start >= end) { 6980 return KERN_SUCCESS; // Punt segments of length zero (e.g., headers) or less (i.e., blunders) 6981 } else if (set_max) { 6982 return KERN_SUCCESS; // Punt set_max, as there's no mechanism to record that state 6983 } else { 6984 return ml_static_protect(start, end - start, new_prot); 6985 } 6986 } 6987 6988 static inline kern_return_t 6989 OSKext_wire( 6990 kernel_mach_header_t *kext_mh, 6991 vm_map_t map, 6992 vm_map_offset_t start, 6993 vm_map_offset_t end, 6994 vm_prot_t access_type, 6995 boolean_t user_wire, 6996 kc_kind_t kc_type) 6997 { 6998 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type) 6999 return KERN_SUCCESS; // No-op as PRELINK kexts are cemented into physical memory at boot 7000 } 7001 #else 7002 #error Unrecognized architecture 7003 #endif 7004 #else 7005 static inline kern_return_t 7006 OSKext_protect( 7007 kernel_mach_header_t *kext_mh, 7008 vm_map_t map, 7009 vm_map_offset_t start, 7010 vm_map_offset_t end, 7011 vm_prot_t new_prot, 7012 boolean_t set_max, 7013 kc_kind_t kc_type) 7014 { 7015 if (start == end) { // 10538581 7016 return KERN_SUCCESS; 7017 } 7018 if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) { 7019 /* 7020 * XXX: This will probably need to be different for AuxKC and 7021 * pageableKC! 7022 */ 7023 return ml_static_protect(start, end - start, new_prot); 7024 } 7025 return vm_map_protect(map, start, end, new_prot, set_max); 7026 } 7027 7028 static inline kern_return_t 7029 OSKext_wire( 7030 kernel_mach_header_t *kext_mh, 7031 vm_map_t map, 7032 vm_map_offset_t start, 7033 vm_map_offset_t end, 7034 vm_prot_t access_type, 7035 boolean_t user_wire, 7036 kc_kind_t kc_type) 7037 { 7038 if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) { 7039 /* TODO: we may need to hook this for the pageableKC */ 7040 return KERN_SUCCESS; 7041 } 7042 return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire); 7043 } 7044 #endif 7045 7046 OSReturn 7047 OSKext::setVMAttributes(bool protect, bool wire) 7048 { 7049 vm_map_t kext_map = NULL; 7050 kernel_segment_command_t * seg = NULL; 7051 vm_map_offset_t start_protect = 0; 7052 vm_map_offset_t start_wire = 0; 7053 vm_map_offset_t end_protect = 0; 7054 vm_map_offset_t end_wire = 0; 7055 OSReturn result = kOSReturnError; 7056 7057 if (isInterface() || !declaresExecutable() || flags.builtin) { 7058 result = kOSReturnSuccess; 7059 goto finish; 7060 } 7061 7062 /* Get the kext's vm map */ 7063 kext_map = kext_get_vm_map(kmod_info); 7064 if (!kext_map) { 7065 result = KERN_MEMORY_ERROR; 7066 goto finish; 7067 } 7068 7069 #if !VM_MAPPED_KEXTS 7070 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) { 7071 /* This is a split kext in a prelinked kernelcache; we'll let the 7072 * platform code take care of protecting it. It is already wired. 7073 */ 7074 /* TODO: Should this still allow protections for the first segment 7075 * to go through, in the event that we have a mix of split and 7076 * unsplit kexts? 7077 */ 7078 result = KERN_SUCCESS; 7079 goto finish; 7080 } 7081 7082 if (isInFileset() && kc_type != KCKindPageable) { 7083 // kexts in filesets have protections setup as part of collection loading 7084 result = KERN_SUCCESS; 7085 goto finish; 7086 } 7087 #endif 7088 7089 /* Protect the headers as read-only; they do not need to be wired */ 7090 result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address, 7091 kext_map, kmod_info->address, 7092 kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type) 7093 : KERN_SUCCESS; 7094 if (result != KERN_SUCCESS) { 7095 goto finish; 7096 } 7097 7098 /* Set the VM protections and wire down each of the segments */ 7099 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 7100 while (seg) { 7101 #if __arm__ 7102 /* We build all ARM kexts, so we can ensure they are aligned */ 7103 assert((seg->vmaddr & PAGE_MASK) == 0); 7104 assert((seg->vmsize & PAGE_MASK) == 0); 7105 #endif 7106 7107 /* 7108 * For the non page aligned segments, the range calculation for protection 7109 * and wiring differ as follows: 7110 * 7111 * Protection: The non page aligned data at the start or at the end of the 7112 * segment is excluded from the protection. This exclusion is needed to make 7113 * sure OSKext_protect is not called twice on same page, if the page is shared 7114 * between two segments. 7115 * 7116 * Wiring: The non page aligned data at the start or at the end of the 7117 * segment is included in the wiring range, this inclusion is needed to make sure 7118 * all the data of the segment is wired. 7119 */ 7120 start_protect = round_page(seg->vmaddr); 7121 end_protect = trunc_page(seg->vmaddr + seg->vmsize); 7122 7123 start_wire = trunc_page(seg->vmaddr); 7124 end_wire = round_page(seg->vmaddr + seg->vmsize); 7125 7126 /* 7127 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared 7128 * across kexts and data from kexts is not page aligned 7129 */ 7130 if (protect && (end_protect > start_protect) && 7131 ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 && 7132 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) || 7133 (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) { 7134 result = OSKext_protect((kernel_mach_header_t *)kmod_info->address, 7135 kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type); 7136 if (result != KERN_SUCCESS) { 7137 OSKextLog(this, 7138 kOSKextLogErrorLevel | 7139 kOSKextLogLoadFlag, 7140 "Kext %s failed to set maximum VM protections " 7141 "for segment %s - 0x%x.", 7142 getIdentifierCString(), seg->segname, (int)result); 7143 goto finish; 7144 } 7145 7146 result = OSKext_protect((kernel_mach_header_t *)kmod_info->address, 7147 kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type); 7148 if (result != KERN_SUCCESS) { 7149 OSKextLog(this, 7150 kOSKextLogErrorLevel | 7151 kOSKextLogLoadFlag, 7152 "Kext %s failed to set initial VM protections " 7153 "for segment %s - 0x%x.", 7154 getIdentifierCString(), seg->segname, (int)result); 7155 goto finish; 7156 } 7157 } 7158 7159 if (segmentShouldBeWired(seg) && wire) { 7160 result = OSKext_wire((kernel_mach_header_t *)kmod_info->address, 7161 kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type); 7162 if (result != KERN_SUCCESS) { 7163 goto finish; 7164 } 7165 } 7166 7167 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 7168 } 7169 7170 finish: 7171 return result; 7172 } 7173 7174 /********************************************************************* 7175 *********************************************************************/ 7176 boolean_t 7177 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg) 7178 { 7179 return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) && 7180 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname))); 7181 } 7182 7183 /********************************************************************* 7184 *********************************************************************/ 7185 OSReturn 7186 OSKext::validateKextMapping(bool startFlag) 7187 { 7188 OSReturn result = kOSReturnError; 7189 const char * whichOp = startFlag ? "start" : "stop"; 7190 kern_return_t kern_result = 0; 7191 vm_map_t kext_map = NULL; 7192 kernel_segment_command_t * seg = NULL; 7193 mach_vm_address_t address = 0; 7194 mach_vm_size_t size = 0; 7195 uint32_t depth = 0; 7196 uint64_t kext_segbase = 0; 7197 uint64_t kext_segsize = 0; 7198 mach_msg_type_number_t count; 7199 vm_region_submap_short_info_data_64_t info; 7200 uintptr_t kext_slide = PE_get_kc_slide(kc_type); 7201 7202 if (flags.builtin) { 7203 return kOSReturnSuccess; 7204 } 7205 7206 count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 7207 bzero(&info, sizeof(info)); 7208 7209 // xxx - do we need a distinct OSReturn value for these or is "bad data" 7210 // xxx - sufficient? 7211 7212 /* Verify that the kmod_info and start/stop pointers are non-NULL. 7213 */ 7214 if (!kmod_info) { 7215 OSKextLog(this, 7216 kOSKextLogErrorLevel | 7217 kOSKextLogLoadFlag, 7218 "Kext %s - NULL kmod_info pointer.", 7219 getIdentifierCString()); 7220 result = kOSKextReturnBadData; 7221 goto finish; 7222 } 7223 7224 if (startFlag) { 7225 address = (mach_vm_address_t)kmod_info->start; 7226 } else { 7227 address = (mach_vm_address_t)kmod_info->stop; 7228 } 7229 7230 if (!address) { 7231 OSKextLog(this, 7232 kOSKextLogErrorLevel | 7233 kOSKextLogLoadFlag, 7234 "Kext %s - NULL module %s pointer.", 7235 getIdentifierCString(), whichOp); 7236 result = kOSKextReturnBadData; 7237 goto finish; 7238 } 7239 7240 kext_map = kext_get_vm_map(kmod_info); 7241 depth = (kernel_map == kext_map) ? 1 : 2; 7242 if (isInFileset()) { 7243 #if defined(HAS_APPLE_PAC) 7244 address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0); 7245 #endif /* defined(HAS_APPLE_PAC) */ 7246 } 7247 7248 /* Verify that the start/stop function lies within the kext's address range. 7249 */ 7250 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) || 7251 isInFileset()) { 7252 /* This will likely be how we deal with split kexts; walk the segments to 7253 * check that the function lies inside one of the segments of this kext. 7254 */ 7255 for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 7256 seg != NULL; 7257 seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) { 7258 if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) { 7259 kext_segbase = seg->vmaddr; 7260 kext_segsize = seg->vmsize; 7261 break; 7262 } 7263 } 7264 7265 if (!seg) { 7266 OSKextLog(this, 7267 kOSKextLogErrorLevel | 7268 kOSKextLogLoadFlag, 7269 "Kext %s module %s pointer is outside of kext range " 7270 "(%s %p - kext starts at %p).", 7271 getIdentifierCString(), 7272 whichOp, 7273 whichOp, 7274 (void *)(((uintptr_t)address) - kext_slide), 7275 (void *)(((uintptr_t)kmod_info->address) - kext_slide)); 7276 result = kOSKextReturnBadData; 7277 goto finish; 7278 } 7279 7280 seg = NULL; 7281 } else { 7282 if (address < kmod_info->address + kmod_info->hdr_size || 7283 kmod_info->address + kmod_info->size <= address) { 7284 OSKextLog(this, 7285 kOSKextLogErrorLevel | 7286 kOSKextLogLoadFlag, 7287 "Kext %s module %s pointer is outside of kext range " 7288 "(%s %p - kext at %p-%p).", 7289 getIdentifierCString(), 7290 whichOp, 7291 whichOp, 7292 (void *)(((uintptr_t)address) - kext_slide), 7293 (void *)(((uintptr_t)kmod_info->address) - kext_slide), 7294 (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size)); 7295 result = kOSKextReturnBadData; 7296 goto finish; 7297 } 7298 } 7299 7300 /* Only do these checks before calling the start function; 7301 * If anything goes wrong with the mapping while the kext is running, 7302 * we'll likely have panicked well before any attempt to stop the kext. 7303 */ 7304 if (startFlag) { 7305 if (!isInFileset() || kc_type != KCKindPrimary) { 7306 /* 7307 * Verify that the start/stop function is executable. 7308 */ 7309 kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth, 7310 (vm_region_recurse_info_t)&info, &count); 7311 if (kern_result != KERN_SUCCESS) { 7312 OSKextLog(this, 7313 kOSKextLogErrorLevel | 7314 kOSKextLogLoadFlag, 7315 "Kext %s - bad %s pointer %p.", 7316 getIdentifierCString(), 7317 whichOp, (void *)ml_static_unslide(address)); 7318 result = kOSKextReturnBadData; 7319 goto finish; 7320 } 7321 } else { 7322 /* 7323 * Since kexts loaded from the primary KC are held in memory 7324 * allocated by efiboot, we cannot use mach_vm_region_recurse() to 7325 * discover that memory's protection flags. Instead, we need to 7326 * get that information from the kernel pmap itself. Above, we 7327 * (potentially) saved the size of the segment in which the address 7328 * in question was located. If we have a non-zero size, verify 7329 * that all pages in the (address, address + kext_segsize) range 7330 * are marked executable. If we somehow did not record the size 7331 * (or the base) just verify the single page that includes the address. 7332 */ 7333 if (kext_segbase == 0 || kext_segsize == 0) { 7334 kext_segbase = address & ~(uint64_t)PAGE_MASK; 7335 kext_segsize = PAGE_SIZE; 7336 } 7337 } 7338 7339 #if VM_MAPPED_KEXTS 7340 if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) || 7341 ((isInFileset() && kc_type == KCKindPrimary) && 7342 ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) { 7343 OSKextLog(this, 7344 kOSKextLogErrorLevel | 7345 kOSKextLogLoadFlag, 7346 "Kext %s - memory region containing module %s function " 7347 "is not executable.", 7348 getIdentifierCString(), whichOp); 7349 result = kOSKextReturnBadData; 7350 goto finish; 7351 } 7352 #endif 7353 7354 /* Verify that the kext's segments are backed by physical memory. 7355 */ 7356 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 7357 while (seg) { 7358 if (!verifySegmentMapping(seg)) { 7359 result = kOSKextReturnBadData; 7360 goto finish; 7361 } 7362 7363 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 7364 } 7365 } 7366 7367 result = kOSReturnSuccess; 7368 finish: 7369 return result; 7370 } 7371 7372 /********************************************************************* 7373 *********************************************************************/ 7374 boolean_t 7375 OSKext::verifySegmentMapping(kernel_segment_command_t *seg) 7376 { 7377 mach_vm_address_t address = 0; 7378 7379 if (seg->vmsize > UINT32_MAX) { 7380 return false; 7381 } 7382 7383 if (!segmentShouldBeWired(seg)) { 7384 return true; 7385 } 7386 7387 for (address = seg->vmaddr; 7388 address < round_page(seg->vmaddr + seg->vmsize); 7389 address += PAGE_SIZE) { 7390 if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) { 7391 OSKextLog(this, 7392 kOSKextLogErrorLevel | 7393 kOSKextLogLoadFlag, 7394 "Kext %s - page %p is not backed by physical memory.", 7395 getIdentifierCString(), 7396 (void *)address); 7397 return false; 7398 } 7399 } 7400 7401 return true; 7402 } 7403 7404 /********************************************************************* 7405 *********************************************************************/ 7406 static void 7407 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code) 7408 { 7409 uint64_t stamp = 0; 7410 firehose_tracepoint_id_u trace_id; 7411 struct firehose_trace_uuid_info_s uuid_info_s; 7412 firehose_trace_uuid_info_t uuid_info = &uuid_info_s; 7413 size_t uuid_info_len = sizeof(struct firehose_trace_uuid_info_s); 7414 OSSharedPtr<OSData> uuid_data; 7415 7416 stamp = firehose_tracepoint_time(firehose_activity_flags_default); 7417 trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code); 7418 7419 uuid_data = aKext->copyTextUUID(); 7420 if (uuid_data) { 7421 memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid)); 7422 } 7423 7424 uuid_info->ftui_size = size; 7425 if (aKext->isDriverKit()) { 7426 uuid_info->ftui_address = address; 7427 } else { 7428 uuid_info->ftui_address = ml_static_unslide(address); 7429 } 7430 firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len); 7431 return; 7432 } 7433 7434 void 7435 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext) 7436 { 7437 OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load); 7438 } 7439 7440 /********************************************************************* 7441 *********************************************************************/ 7442 OSReturn 7443 OSKext::start(bool startDependenciesFlag) 7444 { 7445 OSReturn result = kOSReturnError; 7446 kern_return_t (* startfunc)(kmod_info_t *, void *); 7447 unsigned int i, count; 7448 void * kmodStartData = NULL; 7449 7450 if (isStarted() || isInterface() || isKernelComponent()) { 7451 result = kOSReturnSuccess; 7452 goto finish; 7453 } 7454 7455 if (!isLoaded()) { 7456 OSKextLog(this, 7457 kOSKextLogErrorLevel | 7458 kOSKextLogLoadFlag, 7459 "Attempt to start nonloaded kext %s.", 7460 getIdentifierCString()); 7461 result = kOSKextReturnInvalidArgument; 7462 goto finish; 7463 } 7464 7465 if (!sLoadEnabled) { 7466 OSKextLog(this, 7467 kOSKextLogErrorLevel | 7468 kOSKextLogLoadFlag, 7469 "Kext loading is disabled (attempt to start kext %s).", 7470 getIdentifierCString()); 7471 result = kOSKextReturnDisabled; 7472 goto finish; 7473 } 7474 7475 result = validateKextMapping(/* start? */ true); 7476 if (result != kOSReturnSuccess) { 7477 goto finish; 7478 } 7479 7480 startfunc = kmod_info->start; 7481 7482 count = getNumDependencies(); 7483 for (i = 0; i < count; i++) { 7484 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i)); 7485 if (dependency == NULL) { 7486 OSKextLog(this, 7487 kOSKextLogErrorLevel | 7488 kOSKextLogLoadFlag, 7489 "Kext %s start - internal error, dependency disappeared.", 7490 getIdentifierCString()); 7491 goto finish; 7492 } 7493 if (!dependency->isStarted()) { 7494 if (startDependenciesFlag) { 7495 OSReturn dependencyResult = 7496 dependency->start(startDependenciesFlag); 7497 if (dependencyResult != KERN_SUCCESS) { 7498 OSKextLog(this, 7499 kOSKextLogErrorLevel | 7500 kOSKextLogLoadFlag, 7501 "Kext %s start - dependency %s failed to start (error 0x%x).", 7502 getIdentifierCString(), 7503 dependency->getIdentifierCString(), 7504 dependencyResult); 7505 goto finish; 7506 } 7507 } else { 7508 OSKextLog(this, 7509 kOSKextLogErrorLevel | 7510 kOSKextLogLoadFlag, 7511 "Not starting %s - dependency %s not started yet.", 7512 getIdentifierCString(), 7513 dependency->getIdentifierCString()); 7514 result = kOSKextReturnStartStopError; // xxx - make new return? 7515 goto finish; 7516 } 7517 } 7518 } 7519 7520 OSKextLog(this, 7521 kOSKextLogDetailLevel | 7522 kOSKextLogLoadFlag, 7523 "Kext %s calling module start function.", 7524 getIdentifierCString()); 7525 7526 flags.starting = 1; 7527 7528 // Drop a log message so logd can grab the needed information to decode this kext 7529 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load); 7530 result = OSRuntimeInitializeCPP(this); 7531 if (result == KERN_SUCCESS) { 7532 result = startfunc(kmod_info, kmodStartData); 7533 } 7534 7535 flags.starting = 0; 7536 7537 /* On success overlap the setting of started/starting. On failure just 7538 * clear starting. 7539 */ 7540 if (result == KERN_SUCCESS) { 7541 flags.started = 1; 7542 7543 // xxx - log start error from kernel? 7544 OSKextLog(this, 7545 kOSKextLogProgressLevel | 7546 kOSKextLogLoadFlag, 7547 "Kext %s is now started.", 7548 getIdentifierCString()); 7549 } else { 7550 invokeOrCancelRequestCallbacks( 7551 /* result not actually used */ kOSKextReturnStartStopError, 7552 /* invokeFlag */ false); 7553 OSKextLog(this, 7554 kOSKextLogWarningLevel | 7555 kOSKextLogLoadFlag, 7556 "Kext %s did not start (return code 0x%x).", 7557 getIdentifierCString(), result); 7558 } 7559 7560 finish: 7561 return result; 7562 } 7563 7564 /********************************************************************* 7565 *********************************************************************/ 7566 /* static */ 7567 bool 7568 OSKext::canUnloadKextWithIdentifier( 7569 OSString * kextIdentifier, 7570 bool checkClassesFlag) 7571 { 7572 bool result = false; 7573 OSKext * aKext = NULL; // do not release 7574 7575 IORecursiveLockLock(sKextLock); 7576 7577 aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 7578 7579 if (!aKext) { 7580 goto finish; // can't unload what's not loaded 7581 } 7582 7583 if (aKext->isLoaded()) { 7584 if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) { 7585 goto finish; 7586 } 7587 if (checkClassesFlag && aKext->hasOSMetaClassInstances()) { 7588 goto finish; 7589 } 7590 } 7591 7592 result = true; 7593 7594 finish: 7595 IORecursiveLockUnlock(sKextLock); 7596 return result; 7597 } 7598 7599 /********************************************************************* 7600 *********************************************************************/ 7601 OSReturn 7602 OSKext::stop(void) 7603 { 7604 OSReturn result = kOSReturnError; 7605 kern_return_t (*stopfunc)(kmod_info_t *, void *); 7606 7607 if (!isStarted() || isInterface()) { 7608 result = kOSReturnSuccess; 7609 goto finish; 7610 } 7611 7612 if (!isLoaded()) { 7613 OSKextLog(this, 7614 kOSKextLogErrorLevel | 7615 kOSKextLogLoadFlag, 7616 "Attempt to stop nonloaded kext %s.", 7617 getIdentifierCString()); 7618 result = kOSKextReturnInvalidArgument; 7619 goto finish; 7620 } 7621 7622 /* Refuse to stop if we have clients or instances. It is up to 7623 * the caller to make sure those aren't true. 7624 */ 7625 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 7626 OSKextLog(this, 7627 kOSKextLogErrorLevel | 7628 kOSKextLogLoadFlag, 7629 "Kext %s - C++ instances; can't stop.", 7630 getIdentifierCString()); 7631 result = kOSKextReturnInUse; 7632 goto finish; 7633 } 7634 7635 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 7636 OSKextLog(this, 7637 kOSKextLogErrorLevel | 7638 kOSKextLogLoadFlag, 7639 "Kext %s - has references (linkage or tracking object); " 7640 "can't stop.", 7641 getIdentifierCString()); 7642 result = kOSKextReturnInUse; 7643 goto finish; 7644 } 7645 7646 /* Note: If validateKextMapping fails on the stop & unload path, 7647 * we are in serious trouble and a kernel panic is likely whether 7648 * we stop & unload the kext or not. 7649 */ 7650 result = validateKextMapping(/* start? */ false); 7651 if (result != kOSReturnSuccess) { 7652 goto finish; 7653 } 7654 7655 stopfunc = kmod_info->stop; 7656 if (stopfunc) { 7657 OSKextLog(this, 7658 kOSKextLogDetailLevel | 7659 kOSKextLogLoadFlag, 7660 "Kext %s calling module stop function.", 7661 getIdentifierCString()); 7662 7663 flags.stopping = 1; 7664 7665 result = stopfunc(kmod_info, /* userData */ NULL); 7666 if (result == KERN_SUCCESS) { 7667 result = OSRuntimeFinalizeCPP(this); 7668 } 7669 7670 flags.stopping = 0; 7671 7672 if (result == KERN_SUCCESS) { 7673 flags.started = 0; 7674 7675 OSKextLog(this, 7676 kOSKextLogDetailLevel | 7677 kOSKextLogLoadFlag, 7678 "Kext %s is now stopped and ready to unload.", 7679 getIdentifierCString()); 7680 } else { 7681 OSKextLog(this, 7682 kOSKextLogErrorLevel | 7683 kOSKextLogLoadFlag, 7684 "Kext %s did not stop (return code 0x%x).", 7685 getIdentifierCString(), result); 7686 result = kOSKextReturnStartStopError; 7687 } 7688 } 7689 7690 finish: 7691 // Drop a log message so logd can update this kext's metadata 7692 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload); 7693 return result; 7694 } 7695 7696 /********************************************************************* 7697 *********************************************************************/ 7698 OSReturn 7699 OSKext::unload(void) 7700 { 7701 OSReturn result = kOSReturnError; 7702 unsigned int index; 7703 uint32_t num_kmod_refs = 0; 7704 OSKextAccount * freeAccount; 7705 bool in_fileset = false; 7706 7707 if (!sUnloadEnabled) { 7708 OSKextLog(this, 7709 kOSKextLogErrorLevel | 7710 kOSKextLogLoadFlag, 7711 "Kext unloading is disabled (%s).", 7712 this->getIdentifierCString()); 7713 7714 result = kOSKextReturnDisabled; 7715 goto finish; 7716 } 7717 7718 // cache this result so we don't need to access the kmod_info after 7719 // it's been potentially free'd 7720 in_fileset = isInFileset(); 7721 7722 /* Refuse to unload if we have clients or instances. It is up to 7723 * the caller to make sure those aren't true. 7724 */ 7725 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 7726 // xxx - Don't log under errors? this is more of an info thing 7727 OSKextLog(this, 7728 kOSKextLogErrorLevel | 7729 kOSKextLogKextBookkeepingFlag, 7730 "Can't unload kext %s; outstanding references (linkage or tracking object).", 7731 getIdentifierCString()); 7732 result = kOSKextReturnInUse; 7733 goto finish; 7734 } 7735 7736 if (isDriverKit()) { 7737 index = sLoadedKexts->getNextIndexOfObject(this, 0); 7738 if (index != (unsigned int)-1) { 7739 sLoadedDriverKitKexts->removeObject(index); 7740 OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload); 7741 loadTag = 0; 7742 } 7743 } 7744 7745 if (!isLoaded()) { 7746 result = kOSReturnSuccess; 7747 goto finish; 7748 } 7749 7750 if (isKernelComponent()) { 7751 result = kOSKextReturnInvalidArgument; 7752 goto finish; 7753 } 7754 7755 if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) { 7756 OSKextLog(this, 7757 kOSKextLogErrorLevel | 7758 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 7759 "Can't unload kext %s; classes have instances:", 7760 getIdentifierCString()); 7761 reportOSMetaClassInstances(kOSKextLogErrorLevel | 7762 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag); 7763 result = kOSKextReturnInUse; 7764 goto finish; 7765 } 7766 7767 /* Note that the kext is unloading before running any code that 7768 * might be in the kext (request callbacks, module stop function). 7769 * We will deny certain requests made against a kext in the process 7770 * of unloading. 7771 */ 7772 flags.unloading = 1; 7773 7774 /* Update the string describing the last kext to unload in case we panic. 7775 */ 7776 savePanicString(/* isLoading */ false); 7777 7778 if (isStarted()) { 7779 result = stop(); 7780 if (result != KERN_SUCCESS) { 7781 OSKextLog(this, 7782 kOSKextLogErrorLevel | 7783 kOSKextLogLoadFlag, 7784 "Kext %s can't unload - module stop returned 0x%x.", 7785 getIdentifierCString(), (unsigned)result); 7786 result = kOSKextReturnStartStopError; 7787 goto finish; 7788 } 7789 } 7790 7791 OSKextLog(this, 7792 kOSKextLogProgressLevel | 7793 kOSKextLogLoadFlag, 7794 "Kext %s unloading.", 7795 getIdentifierCString()); 7796 7797 { 7798 struct list_head *p; 7799 struct list_head *prev; 7800 struct list_head *next; 7801 for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) { 7802 OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head); 7803 s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize); 7804 prev = p->prev; 7805 next = p->next; 7806 prev->next = next; 7807 next->prev = prev; 7808 p->prev = p; 7809 p->next = p; 7810 IORecursiveLockWakeup(sKextLock, s, false); 7811 } 7812 } 7813 7814 7815 /* Even if we don't call the stop function, we want to be sure we 7816 * have no OSMetaClass references before unloading the kext executable 7817 * from memory. OSMetaClasses may have pointers into the kext executable 7818 * and that would cause a panic on OSKext::free() when metaClasses is freed. 7819 */ 7820 if (metaClasses) { 7821 metaClasses->flushCollection(); 7822 } 7823 (void) OSRuntimeFinalizeCPP(this); 7824 7825 /* Remove the kext from the list of loaded kexts, patch the gap 7826 * in the kmod_info_t linked list, and reset "kmod" to point to the 7827 * last loaded kext that isn't the fake kernel kext (sKernelKext). 7828 */ 7829 index = sLoadedKexts->getNextIndexOfObject(this, 0); 7830 if (index != (unsigned int)-1) { 7831 sLoadedKexts->removeObject(index); 7832 7833 OSKext * nextKext = OSDynamicCast(OSKext, 7834 sLoadedKexts->getObject(index)); 7835 7836 if (nextKext) { 7837 if (index > 0) { 7838 OSKext * gapKext = OSDynamicCast(OSKext, 7839 sLoadedKexts->getObject(index - 1)); 7840 7841 nextKext->kmod_info->next = gapKext->kmod_info; 7842 } else { /* index == 0 */ 7843 nextKext->kmod_info->next = NULL; 7844 } 7845 } 7846 7847 OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 7848 if (lastKext && !lastKext->isKernel()) { 7849 kmod = lastKext->kmod_info; 7850 } else { 7851 kmod = NULL; // clear the global kmod variable 7852 } 7853 } 7854 7855 /* Clear out the kmod references that we're keeping for compatibility 7856 * with current panic backtrace code & kgmacros. 7857 * xxx - will want to update those bits sometime and remove this. 7858 */ 7859 num_kmod_refs = getNumDependencies(); 7860 if (num_kmod_refs && kmod_info && kmod_info->reference_list) { 7861 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 7862 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 7863 ref->info->reference_count--; 7864 } 7865 kfree_type(kmod_reference_t, num_kmod_refs, 7866 kmod_info->reference_list); 7867 } 7868 7869 #if CONFIG_DTRACE 7870 unregisterWithDTrace(); 7871 #endif /* CONFIG_DTRACE */ 7872 7873 notifyKextUnloadObservers(this); 7874 7875 freeAccount = NULL; 7876 IOSimpleLockLock(sKextAccountsLock); 7877 account->kext = NULL; 7878 if (account->site.tag) { 7879 account->site.flags |= VM_TAG_UNLOAD; 7880 } else { 7881 freeAccount = account; 7882 } 7883 7884 #if DEVELOPMENT || DEBUG 7885 assertf(account->task_refgrp.grp_count == 0, 7886 "unloading a kext with active task references"); 7887 #endif /* DEVELOPMENT || DEBUG */ 7888 7889 IOSimpleLockUnlock(sKextAccountsLock); 7890 if (freeAccount) { 7891 IOFreeType(freeAccount, OSKextAccount); 7892 } 7893 7894 /* Unwire and free the linked executable. 7895 */ 7896 if (linkedExecutable) { 7897 #if KASAN 7898 kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength()); 7899 #endif 7900 7901 #if VM_MAPPED_KEXTS 7902 if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) { 7903 kernel_segment_command_t *seg = NULL; 7904 vm_map_t kext_map = kext_get_vm_map(kmod_info); 7905 7906 if (!kext_map) { 7907 OSKextLog(this, 7908 kOSKextLogErrorLevel | 7909 kOSKextLogLoadFlag, 7910 "Failed to free kext %s; couldn't find the kext map.", 7911 getIdentifierCString()); 7912 result = kOSKextReturnInternalError; 7913 goto finish; 7914 } 7915 7916 OSKextLog(this, 7917 kOSKextLogProgressLevel | 7918 kOSKextLogLoadFlag, 7919 "Kext %s unwiring and unmapping linked executable.", 7920 getIdentifierCString()); 7921 7922 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 7923 while (seg) { 7924 if (segmentShouldBeWired(seg)) { 7925 vm_map_offset_t start_wire = trunc_page(seg->vmaddr); 7926 vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize); 7927 7928 result = vm_map_unwire(kext_map, start_wire, 7929 end_wire, FALSE); 7930 if (result != KERN_SUCCESS) { 7931 OSKextLog(this, 7932 kOSKextLogErrorLevel | 7933 kOSKextLogLoadFlag, 7934 "Failed to unwire kext %s.", 7935 getIdentifierCString()); 7936 result = kOSKextReturnInternalError; 7937 goto finish; 7938 } 7939 } 7940 7941 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 7942 } 7943 #if defined(__x86_64__) || defined(__i386__) 7944 if (in_fileset && flags.resetSegmentsFromVnode) { 7945 IORecursiveLockLock(sKextLock); 7946 resetKCFileSetSegments(); 7947 IORecursiveLockUnlock(sKextLock); 7948 } 7949 #endif // (__x86_64__) || defined(__i386__) 7950 } 7951 #endif /* VM_MAPPED_KEXTS */ 7952 if (flags.resetSegmentsFromImmutableCopy) { 7953 result = resetMutableSegments(); 7954 if (result != kOSReturnSuccess) { 7955 OSKextLog(this, 7956 kOSKextLogErrorLevel | 7957 kOSKextLogLoadFlag, 7958 "Failed to reset kext %s.", 7959 getIdentifierCString()); 7960 result = kOSKextReturnInternalError; 7961 goto finish; 7962 } 7963 } 7964 if (kc_type == KCKindUnknown) { 7965 linkedExecutable.reset(); 7966 } 7967 } 7968 7969 /* An interface kext has a fake kmod_info that was allocated, 7970 * so we have to free it. 7971 */ 7972 if (isInterface()) { 7973 kfree_type(kmod_info_t, kmod_info); 7974 kmod_info = NULL; 7975 } 7976 7977 if (!in_fileset) { 7978 kmod_info = NULL; 7979 } 7980 7981 flags.loaded = false; 7982 flushDependencies(); 7983 7984 /* save a copy of the bundle ID for us to check when deciding to 7985 * rebuild the kernel cache file. If a kext was already in the kernel 7986 * cache and unloaded then later loaded we do not need to rebuild the 7987 * kernel cache. 9055303 7988 */ 7989 if (isPrelinked()) { 7990 if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) { 7991 IORecursiveLockLock(sKextLock); 7992 if (sUnloadedPrelinkedKexts) { 7993 sUnloadedPrelinkedKexts->setObject(bundleID.get()); 7994 } 7995 IORecursiveLockUnlock(sKextLock); 7996 } 7997 } 7998 7999 OSKextLog(this, 8000 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 8001 "Kext %s unloaded.", getIdentifierCString()); 8002 8003 queueKextNotification(kKextRequestPredicateUnloadNotification, 8004 OSDynamicCast(OSString, bundleID.get())); 8005 8006 finish: 8007 OSKext::saveLoadedKextPanicList(); 8008 OSKext::updateLoadedKextSummaries(); 8009 8010 flags.unloading = 0; 8011 return result; 8012 } 8013 8014 /********************************************************************* 8015 * Assumes sKextLock is held. 8016 *********************************************************************/ 8017 /* static */ 8018 OSReturn 8019 OSKext::queueKextNotification( 8020 const char * notificationName, 8021 OSString * kextIdentifier) 8022 { 8023 OSReturn result = kOSReturnError; 8024 OSSharedPtr<OSDictionary> loadRequest; 8025 8026 if (!kextIdentifier) { 8027 result = kOSKextReturnInvalidArgument; 8028 goto finish; 8029 } 8030 8031 /* Create a new request unless one is already sitting 8032 * in sKernelRequests for this bundle identifier 8033 */ 8034 result = _OSKextCreateRequest(notificationName, loadRequest); 8035 if (result != kOSReturnSuccess) { 8036 goto finish; 8037 } 8038 if (!_OSKextSetRequestArgument(loadRequest.get(), 8039 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 8040 result = kOSKextReturnNoMemory; 8041 goto finish; 8042 } 8043 if (!sKernelRequests->setObject(loadRequest.get())) { 8044 result = kOSKextReturnNoMemory; 8045 goto finish; 8046 } 8047 8048 /* We might want to only queue the notification if the IOKit daemon is active, 8049 * but that wouldn't work for embedded. Note that we don't care if 8050 * the ping immediately succeeds here so don't do anything with the 8051 * result of this call. 8052 */ 8053 OSKext::pingIOKitDaemon(); 8054 8055 result = kOSReturnSuccess; 8056 8057 finish: 8058 return result; 8059 } 8060 8061 8062 #if CONFIG_KXLD 8063 /********************************************************************* 8064 *********************************************************************/ 8065 static void 8066 _OSKextConsiderDestroyingLinkContext( 8067 __unused thread_call_param_t p0, 8068 __unused thread_call_param_t p1) 8069 { 8070 /* Take multiple locks in the correct order. 8071 */ 8072 IORecursiveLockLock(sKextLock); 8073 IORecursiveLockLock(sKextInnerLock); 8074 8075 /* The first time we destroy the kxldContext is in the first 8076 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled 8077 * before calling this function. Thereafter any call to this function 8078 * will actually destroy the context. 8079 */ 8080 if (sConsiderUnloadsCalled && sKxldContext) { 8081 kxld_destroy_context(sKxldContext); 8082 sKxldContext = NULL; 8083 } 8084 8085 /* Free the thread_call that was allocated to execute this function. 8086 */ 8087 if (sDestroyLinkContextThread) { 8088 if (!thread_call_free(sDestroyLinkContextThread)) { 8089 OSKextLog(/* kext */ NULL, 8090 kOSKextLogErrorLevel | 8091 kOSKextLogGeneralFlag, 8092 "thread_call_free() failed for kext link context."); 8093 } 8094 sDestroyLinkContextThread = NULL; 8095 } 8096 8097 IORecursiveLockUnlock(sKextInnerLock); 8098 IORecursiveLockUnlock(sKextLock); 8099 8100 return; 8101 } 8102 8103 /********************************************************************* 8104 * Destroying the kxldContext requires checking variables under both 8105 * sKextInnerLock and sKextLock, so we do it on a separate thread 8106 * to avoid deadlocks with IOService, with which OSKext has a reciprocal 8107 * call relationship. 8108 * 8109 * This function must be invoked with sKextInnerLock held. 8110 * Do not call any function that takes sKextLock here! 8111 *********************************************************************/ 8112 /* static */ 8113 void 8114 OSKext::considerDestroyingLinkContext(void) 8115 { 8116 IORecursiveLockLock(sKextInnerLock); 8117 8118 /* If we have already queued a thread to destroy the link context, 8119 * don't bother resetting; that thread will take care of it. 8120 */ 8121 if (sDestroyLinkContextThread) { 8122 goto finish; 8123 } 8124 8125 /* The function to be invoked in the thread will deallocate 8126 * this thread_call, so don't share it around. 8127 */ 8128 sDestroyLinkContextThread = thread_call_allocate( 8129 &_OSKextConsiderDestroyingLinkContext, NULL); 8130 if (!sDestroyLinkContextThread) { 8131 OSKextLog(/* kext */ NULL, 8132 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag, 8133 "Can't create thread to destroy kext link context."); 8134 goto finish; 8135 } 8136 8137 thread_call_enter(sDestroyLinkContextThread); 8138 8139 finish: 8140 IORecursiveLockUnlock(sKextInnerLock); 8141 return; 8142 } 8143 8144 #else // !CONFIG_KXLD 8145 8146 /* static */ 8147 void 8148 OSKext::considerDestroyingLinkContext(void) 8149 { 8150 return; 8151 } 8152 8153 #endif // CONFIG_KXLD 8154 8155 #if PRAGMA_MARK 8156 #pragma mark Autounload 8157 #endif 8158 /********************************************************************* 8159 * This is a static method because the kext will be deallocated if it 8160 * does unload! 8161 *********************************************************************/ 8162 /* static */ 8163 OSReturn 8164 OSKext::autounloadKext(OSKext * aKext) 8165 { 8166 OSReturn result = kOSKextReturnInUse; 8167 8168 #if NO_KEXTD 8169 /* 8170 * Do not unload prelinked kexts on platforms that do not have an 8171 * IOKit daemon as there is no way to reload the kext or restart 8172 * matching. 8173 */ 8174 if (aKext->isPrelinked()) { 8175 goto finish; 8176 } 8177 #endif /* defined(__x86_64__) */ 8178 8179 /* Check for external references to this kext (usu. dependents), 8180 * instances of defined classes (or classes derived from them), 8181 * outstanding requests. 8182 */ 8183 if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) || 8184 !aKext->flags.autounloadEnabled || 8185 aKext->isKernelComponent()) { 8186 goto finish; 8187 } 8188 8189 /* Skip a delay-autounload kext, once. 8190 */ 8191 if (aKext->flags.delayAutounload) { 8192 OSKextLog(aKext, 8193 kOSKextLogProgressLevel | 8194 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 8195 "Kext %s has delayed autounload set; skipping and clearing flag.", 8196 aKext->getIdentifierCString()); 8197 aKext->flags.delayAutounload = 0; 8198 goto finish; 8199 } 8200 8201 if (aKext->hasOSMetaClassInstances() || 8202 aKext->countRequestCallbacks()) { 8203 goto finish; 8204 } 8205 8206 result = OSKext::removeKext(aKext); 8207 8208 finish: 8209 return result; 8210 } 8211 8212 /********************************************************************* 8213 *********************************************************************/ 8214 void 8215 _OSKextConsiderUnloads( 8216 __unused thread_call_param_t p0, 8217 __unused thread_call_param_t p1) 8218 { 8219 bool didUnload = false; 8220 unsigned int count, i; 8221 8222 /* Take multiple locks in the correct order 8223 * (note also sKextSummaries lock further down). 8224 */ 8225 IORecursiveLockLock(sKextLock); 8226 IORecursiveLockLock(sKextInnerLock); 8227 8228 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true); 8229 8230 /* If the system is powering down, don't try to unload anything. 8231 */ 8232 if (sSystemSleep) { 8233 goto finish; 8234 } 8235 8236 OSKextLog(/* kext */ NULL, 8237 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 8238 "Checking for unused kexts to autounload."); 8239 8240 /***** 8241 * Remove any request callbacks marked as stale, 8242 * and mark as stale any currently in flight. 8243 */ 8244 count = sRequestCallbackRecords->getCount(); 8245 if (count) { 8246 i = count - 1; 8247 do { 8248 OSDictionary * callbackRecord = OSDynamicCast(OSDictionary, 8249 sRequestCallbackRecords->getObject(i)); 8250 OSBoolean * stale = OSDynamicCast(OSBoolean, 8251 callbackRecord->getObject(kKextRequestStaleKey)); 8252 8253 if (stale == kOSBooleanTrue) { 8254 OSKext::invokeRequestCallback(callbackRecord, 8255 kOSKextReturnTimeout); 8256 } else { 8257 callbackRecord->setObject(kKextRequestStaleKey, 8258 kOSBooleanTrue); 8259 } 8260 } while (i--); 8261 } 8262 8263 /***** 8264 * Make multiple passes through the array of loaded kexts until 8265 * we don't unload any. This handles unwinding of dependency 8266 * chains. We have to go *backwards* through the array because 8267 * kexts are removed from it when unloaded, and we cannot make 8268 * a copy or we'll mess up the retain counts we rely on to 8269 * check whether a kext will unload. If only we could have 8270 * nonretaining collections like CF has.... 8271 */ 8272 do { 8273 didUnload = false; 8274 8275 count = sLoadedKexts->getCount(); 8276 if (count) { 8277 i = count - 1; 8278 do { 8279 OSKext * thisKext = OSDynamicCast(OSKext, 8280 sLoadedKexts->getObject(i)); 8281 didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext)); 8282 } while (i--); 8283 } 8284 } while (didUnload); 8285 8286 finish: 8287 sConsiderUnloadsPending = false; 8288 sConsiderUnloadsExecuted = true; 8289 8290 (void) OSKext::considerRebuildOfPrelinkedKernel(); 8291 8292 IORecursiveLockUnlock(sKextInnerLock); 8293 IORecursiveLockUnlock(sKextLock); 8294 8295 return; 8296 } 8297 8298 /********************************************************************* 8299 * Do not call any function that takes sKextLock here! 8300 *********************************************************************/ 8301 void 8302 OSKext::considerUnloads(Boolean rescheduleOnlyFlag) 8303 { 8304 AbsoluteTime when; 8305 8306 IORecursiveLockLock(sKextInnerLock); 8307 8308 if (!sUnloadCallout) { 8309 sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL); 8310 } 8311 8312 /* we only reset delay value for unloading if we already have something 8313 * pending. rescheduleOnlyFlag should not start the count down. 8314 */ 8315 if (rescheduleOnlyFlag && !sConsiderUnloadsPending) { 8316 goto finish; 8317 } 8318 8319 thread_call_cancel(sUnloadCallout); 8320 if (OSKext::getAutounloadEnabled() && !sSystemSleep 8321 #if !NO_KEXTD 8322 && sIOKitDaemonActive 8323 #endif 8324 ) { 8325 clock_interval_to_deadline(sConsiderUnloadDelay, 8326 1000 * 1000 * 1000, &when); 8327 8328 OSKextLog(/* kext */ NULL, 8329 kOSKextLogProgressLevel | 8330 kOSKextLogLoadFlag, 8331 "%scheduling %sscan for unused kexts in %lu seconds.", 8332 sConsiderUnloadsPending ? "Res" : "S", 8333 sConsiderUnloadsCalled ? "" : "initial ", 8334 (unsigned long)sConsiderUnloadDelay); 8335 8336 sConsiderUnloadsPending = true; 8337 thread_call_enter_delayed(sUnloadCallout, when); 8338 } 8339 8340 finish: 8341 /* The kxld context should be reused throughout boot. We mark the end of 8342 * period as the first time considerUnloads() is called, and we destroy 8343 * the first kxld context in that function. Afterwards, it will be 8344 * destroyed in flushNonloadedKexts. 8345 */ 8346 if (!sConsiderUnloadsCalled) { 8347 sConsiderUnloadsCalled = true; 8348 OSKext::considerDestroyingLinkContext(); 8349 } 8350 8351 IORecursiveLockUnlock(sKextInnerLock); 8352 return; 8353 } 8354 8355 /********************************************************************* 8356 * Do not call any function that takes sKextLock here! 8357 *********************************************************************/ 8358 extern "C" { 8359 IOReturn OSKextSystemSleepOrWake(UInt32 messageType); 8360 IOReturn 8361 OSKextSystemSleepOrWake(UInt32 messageType) 8362 { 8363 IORecursiveLockLock(sKextInnerLock); 8364 8365 /* If the system is going to sleep, cancel the reaper thread timer, 8366 * and note that we're in a sleep state in case it just fired but hasn't 8367 * taken the lock yet. If we are coming back from sleep, just 8368 * clear the sleep flag; IOService's normal operation will cause 8369 * unloads to be considered soon enough. 8370 */ 8371 if (messageType == kIOMessageSystemWillSleep) { 8372 if (sUnloadCallout) { 8373 thread_call_cancel(sUnloadCallout); 8374 } 8375 sSystemSleep = true; 8376 AbsoluteTime_to_scalar(&sLastWakeTime) = 0; 8377 } else if (messageType == kIOMessageSystemHasPoweredOn) { 8378 sSystemSleep = false; 8379 clock_get_uptime(&sLastWakeTime); 8380 } 8381 IORecursiveLockUnlock(sKextInnerLock); 8382 8383 return kIOReturnSuccess; 8384 } 8385 }; 8386 8387 8388 #if PRAGMA_MARK 8389 #pragma mark Prelinked Kernel 8390 #endif 8391 8392 #ifdef CONFIG_KXLD 8393 /********************************************************************* 8394 * Do not access sConsiderUnloads... variables other than 8395 * sConsiderUnloadsExecuted in this function. They are guarded by a 8396 * different lock. 8397 *********************************************************************/ 8398 /* static */ 8399 void 8400 OSKext::considerRebuildOfPrelinkedKernel(void) 8401 { 8402 static bool requestedPrelink = false; 8403 OSReturn checkResult = kOSReturnError; 8404 OSSharedPtr<OSDictionary> prelinkRequest; 8405 OSSharedPtr<OSCollectionIterator> kextIterator; 8406 const OSSymbol * thisID = NULL; // do not release 8407 bool doRebuild = false; 8408 AbsoluteTime my_abstime; 8409 UInt64 my_ns; 8410 SInt32 delta_secs; 8411 8412 /* Only one auto rebuild per boot and only on boot from prelinked kernel */ 8413 if (requestedPrelink || !sPrelinkBoot) { 8414 return; 8415 } 8416 8417 /* no direct return from this point */ 8418 IORecursiveLockLock(sKextLock); 8419 8420 /* We need to wait for the IOKit daemon to get up and running with unloads already done 8421 * and any new startup kexts loaded. 8422 */ 8423 if (!sConsiderUnloadsExecuted || 8424 !sDeferredLoadSucceeded) { 8425 goto finish; 8426 } 8427 8428 /* we really only care about boot / system start up related kexts so bail 8429 * if we're here after REBUILD_MAX_TIME. 8430 */ 8431 if (!_OSKextInPrelinkRebuildWindow()) { 8432 OSKextLog(/* kext */ NULL, 8433 kOSKextLogArchiveFlag, 8434 "%s prebuild rebuild has expired", 8435 __FUNCTION__); 8436 requestedPrelink = true; 8437 goto finish; 8438 } 8439 8440 /* we do not want to trigger a rebuild if we get here too close to waking 8441 * up. (see radar 10233768) 8442 */ 8443 IORecursiveLockLock(sKextInnerLock); 8444 8445 clock_get_uptime(&my_abstime); 8446 delta_secs = MINIMUM_WAKEUP_SECONDS + 1; 8447 if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) { 8448 SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime); 8449 absolutetime_to_nanoseconds(my_abstime, &my_ns); 8450 delta_secs = (SInt32)(my_ns / NSEC_PER_SEC); 8451 } 8452 IORecursiveLockUnlock(sKextInnerLock); 8453 8454 if (delta_secs < MINIMUM_WAKEUP_SECONDS) { 8455 /* too close to time of last wake from sleep */ 8456 goto finish; 8457 } 8458 requestedPrelink = true; 8459 8460 /* Now it's time to see if we have a reason to rebuild. We may have done 8461 * some loads and unloads but the kernel cache didn't actually change. 8462 * We will rebuild if any kext is not marked prelinked AND is not in our 8463 * list of prelinked kexts that got unloaded. (see radar 9055303) 8464 */ 8465 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 8466 if (!kextIterator) { 8467 goto finish; 8468 } 8469 8470 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 8471 OSKext * thisKext; // do not release 8472 8473 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 8474 if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) { 8475 continue; 8476 } 8477 8478 if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) { 8479 continue; 8480 } 8481 /* kext is loaded and was not in current kernel cache so let's rebuild 8482 */ 8483 doRebuild = true; 8484 OSKextLog(/* kext */ NULL, 8485 kOSKextLogArchiveFlag, 8486 "considerRebuildOfPrelinkedKernel %s triggered rebuild", 8487 thisKext->bundleID->getCStringNoCopy()); 8488 break; 8489 } 8490 sUnloadedPrelinkedKexts->flushCollection(); 8491 8492 if (!doRebuild) { 8493 goto finish; 8494 } 8495 8496 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink, 8497 prelinkRequest); 8498 if (checkResult != kOSReturnSuccess) { 8499 goto finish; 8500 } 8501 8502 if (!sKernelRequests->setObject(prelinkRequest.get())) { 8503 goto finish; 8504 } 8505 8506 OSKext::pingIOKitDaemon(); 8507 8508 finish: 8509 IORecursiveLockUnlock(sKextLock); 8510 8511 return; 8512 } 8513 8514 #else /* !CONFIG_KXLD */ 8515 8516 void 8517 OSKext::considerRebuildOfPrelinkedKernel(void) 8518 { 8519 /* in a non-dynamic kext loading world, there is never a reason to rebuild */ 8520 return; 8521 } 8522 8523 #endif /* CONFIG_KXLD */ 8524 8525 #if PRAGMA_MARK 8526 #pragma mark Dependencies 8527 #endif 8528 /********************************************************************* 8529 *********************************************************************/ 8530 bool 8531 OSKext::resolveDependencies( 8532 OSArray * loopStack) 8533 { 8534 bool result = false; 8535 OSSharedPtr<OSArray> localLoopStack; 8536 bool addedToLoopStack = false; 8537 OSDictionary * libraries = NULL; // do not release 8538 OSSharedPtr<OSCollectionIterator> libraryIterator; 8539 OSString * libraryID = NULL; // do not release 8540 OSKext * libraryKext = NULL; // do not release 8541 bool hasRawKernelDependency = false; 8542 bool hasKernelDependency = false; 8543 bool hasKPIDependency = false; 8544 bool hasPrivateKPIDependency = false; 8545 unsigned int count; 8546 8547 #if CONFIG_KXLD 8548 OSString * infoString = NULL; // do not release 8549 OSString * readableString = NULL; // do not release 8550 #endif // CONFIG_KXLD 8551 8552 /* A kernel component will automatically have this flag set, 8553 * and a loaded kext should also have it set (as should all its 8554 * loaded dependencies). 8555 */ 8556 if (flags.hasAllDependencies) { 8557 result = true; 8558 goto finish; 8559 } 8560 8561 /* Check for loops in the dependency graph. 8562 */ 8563 if (loopStack) { 8564 if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) { 8565 OSKextLog(this, 8566 kOSKextLogErrorLevel | 8567 kOSKextLogDependenciesFlag, 8568 "Kext %s has a dependency loop; can't resolve dependencies.", 8569 getIdentifierCString()); 8570 goto finish; 8571 } 8572 } else { 8573 OSKextLog(this, 8574 kOSKextLogStepLevel | 8575 kOSKextLogDependenciesFlag, 8576 "Kext %s resolving dependencies.", 8577 getIdentifierCString()); 8578 8579 localLoopStack = OSArray::withCapacity(6); // any small capacity will do 8580 if (!localLoopStack) { 8581 OSKextLog(this, 8582 kOSKextLogErrorLevel | 8583 kOSKextLogDependenciesFlag, 8584 "Kext %s can't create bookkeeping stack to resolve dependencies.", 8585 getIdentifierCString()); 8586 goto finish; 8587 } 8588 loopStack = localLoopStack.get(); 8589 } 8590 if (!loopStack->setObject(this)) { 8591 OSKextLog(this, 8592 kOSKextLogErrorLevel | 8593 kOSKextLogDependenciesFlag, 8594 "Kext %s - internal error resolving dependencies.", 8595 getIdentifierCString()); 8596 goto finish; 8597 } 8598 addedToLoopStack = true; 8599 8600 /* Purge any existing kexts in the dependency list and start over. 8601 */ 8602 flushDependencies(); 8603 if (dependencies) { 8604 OSKextLog(this, 8605 kOSKextLogErrorLevel | 8606 kOSKextLogDependenciesFlag, 8607 "Kext %s - internal error resolving dependencies.", 8608 getIdentifierCString()); 8609 } 8610 8611 libraries = OSDynamicCast(OSDictionary, 8612 getPropertyForHostArch(kOSBundleLibrariesKey)); 8613 if (libraries == NULL || libraries->getCount() == 0) { 8614 OSKextLog(this, 8615 kOSKextLogErrorLevel | 8616 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 8617 "Kext %s - can't resolve dependencies; %s missing/invalid type.", 8618 getIdentifierCString(), kOSBundleLibrariesKey); 8619 goto finish; 8620 } 8621 8622 /* Make a new array to hold the dependencies (flush freed the old one). 8623 */ 8624 dependencies = OSArray::withCapacity(libraries->getCount()); 8625 if (!dependencies) { 8626 OSKextLog(this, 8627 kOSKextLogErrorLevel | 8628 kOSKextLogDependenciesFlag, 8629 "Kext %s - can't allocate dependencies array.", 8630 getIdentifierCString()); 8631 goto finish; 8632 } 8633 8634 // xxx - compat: We used to add an implicit dependency on kernel 6.0 8635 // xxx - compat: if none were declared. 8636 8637 libraryIterator = OSCollectionIterator::withCollection(libraries); 8638 if (!libraryIterator) { 8639 OSKextLog(this, 8640 kOSKextLogErrorLevel | 8641 kOSKextLogDependenciesFlag, 8642 "Kext %s - can't allocate dependencies iterator.", 8643 getIdentifierCString()); 8644 goto finish; 8645 } 8646 8647 while ((libraryID = OSDynamicCast(OSString, 8648 libraryIterator->getNextObject()))) { 8649 const char * library_id = libraryID->getCStringNoCopy(); 8650 8651 OSString * libraryVersion = OSDynamicCast(OSString, 8652 libraries->getObject(libraryID)); 8653 if (libraryVersion == NULL) { 8654 OSKextLog(this, 8655 kOSKextLogErrorLevel | 8656 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 8657 "Kext %s - illegal type in OSBundleLibraries.", 8658 getIdentifierCString()); 8659 goto finish; 8660 } 8661 8662 OSKextVersion libraryVers = 8663 OSKextParseVersionString(libraryVersion->getCStringNoCopy()); 8664 if (libraryVers == -1) { 8665 OSKextLog(this, 8666 kOSKextLogErrorLevel | 8667 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 8668 "Kext %s - invalid library version %s.", 8669 getIdentifierCString(), 8670 libraryVersion->getCStringNoCopy()); 8671 goto finish; 8672 } 8673 8674 libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID)); 8675 if (libraryKext == NULL) { 8676 OSKextLog(this, 8677 kOSKextLogErrorLevel | 8678 kOSKextLogDependenciesFlag, 8679 "Kext %s - library kext %s not found.", 8680 getIdentifierCString(), library_id); 8681 goto finish; 8682 } 8683 8684 if (!libraryKext->isCompatibleWithVersion(libraryVers)) { 8685 OSKextLog(this, 8686 kOSKextLogErrorLevel | 8687 kOSKextLogDependenciesFlag, 8688 "Kext %s - library kext %s not compatible " 8689 "with requested version %s.", 8690 getIdentifierCString(), library_id, 8691 libraryVersion->getCStringNoCopy()); 8692 goto finish; 8693 } 8694 8695 /* If a nonprelinked library somehow got into the mix for a 8696 * prelinked kext, at any point in the chain, we must fail 8697 * because the prelinked relocs for the library will be all wrong. 8698 */ 8699 if (this->isPrelinked() && 8700 libraryKext->declaresExecutable() && 8701 !libraryKext->isPrelinked()) { 8702 OSKextLog(this, 8703 kOSKextLogErrorLevel | 8704 kOSKextLogDependenciesFlag, 8705 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.", 8706 getIdentifierCString(), library_id, 8707 libraryVersion->getCStringNoCopy()); 8708 goto finish; 8709 } 8710 8711 if (!libraryKext->resolveDependencies(loopStack)) { 8712 goto finish; 8713 } 8714 8715 /* Add the library directly only if it has an executable to link. 8716 * Otherwise it's just used to collect other dependencies, so put 8717 * *its* dependencies on the list for this kext. 8718 */ 8719 // xxx - We are losing info here; would like to make fake entries or 8720 // xxx - keep these in the dependency graph for loaded kexts. 8721 // xxx - I really want to make kernel components not a special case! 8722 if (libraryKext->declaresExecutable() || 8723 libraryKext->isInterface()) { 8724 if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) { 8725 dependencies->setObject(libraryKext); 8726 8727 OSKextLog(this, 8728 kOSKextLogDetailLevel | 8729 kOSKextLogDependenciesFlag, 8730 "Kext %s added dependency %s.", 8731 getIdentifierCString(), 8732 libraryKext->getIdentifierCString()); 8733 } 8734 } else { 8735 int numLibDependencies = libraryKext->getNumDependencies(); 8736 OSArray * libraryDependencies = libraryKext->getDependencies(); 8737 int index; 8738 8739 if (numLibDependencies) { 8740 // xxx - this msg level should be 1 lower than the per-kext one 8741 OSKextLog(this, 8742 kOSKextLogDetailLevel | 8743 kOSKextLogDependenciesFlag, 8744 "Kext %s pulling %d dependencies from codeless library %s.", 8745 getIdentifierCString(), 8746 numLibDependencies, 8747 libraryKext->getIdentifierCString()); 8748 } 8749 for (index = 0; index < numLibDependencies; index++) { 8750 OSKext * thisLibDependency = OSDynamicCast(OSKext, 8751 libraryDependencies->getObject(index)); 8752 if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) { 8753 dependencies->setObject(thisLibDependency); 8754 OSKextLog(this, 8755 kOSKextLogDetailLevel | 8756 kOSKextLogDependenciesFlag, 8757 "Kext %s added dependency %s from codeless library %s.", 8758 getIdentifierCString(), 8759 thisLibDependency->getIdentifierCString(), 8760 libraryKext->getIdentifierCString()); 8761 } 8762 } 8763 } 8764 8765 if ((strlen(library_id) == strlen(KERNEL_LIB)) && 8766 0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) { 8767 hasRawKernelDependency = true; 8768 } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) { 8769 hasKernelDependency = true; 8770 } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) { 8771 hasKPIDependency = true; 8772 if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) { 8773 hasPrivateKPIDependency = true; 8774 } 8775 } 8776 } 8777 8778 if (hasRawKernelDependency) { 8779 OSKextLog(this, 8780 kOSKextLogErrorLevel | 8781 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 8782 "Error - kext %s declares a dependency on %s, which is not permitted.", 8783 getIdentifierCString(), KERNEL_LIB); 8784 goto finish; 8785 } 8786 #if __LP64__ 8787 if (hasKernelDependency) { 8788 OSKextLog(this, 8789 kOSKextLogErrorLevel | 8790 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 8791 "Error - kext %s declares %s dependencies. " 8792 "Only %s* dependencies are supported for 64-bit kexts.", 8793 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 8794 goto finish; 8795 } 8796 if (!hasKPIDependency) { 8797 OSKextLog(this, 8798 kOSKextLogWarningLevel | 8799 kOSKextLogDependenciesFlag, 8800 "Warning - kext %s declares no %s* dependencies. " 8801 "If it uses any KPIs, the link may fail with undefined symbols.", 8802 getIdentifierCString(), KPI_LIB_PREFIX); 8803 } 8804 #else /* __LP64__ */ 8805 // xxx - will change to flatly disallow "kernel" dependencies at some point 8806 // xxx - is it invalid to do both "com.apple.kernel" and any 8807 // xxx - "com.apple.kernel.*"? 8808 8809 if (hasKernelDependency && hasKPIDependency) { 8810 OSKextLog(this, 8811 kOSKextLogWarningLevel | 8812 kOSKextLogDependenciesFlag, 8813 "Warning - kext %s has immediate dependencies on both " 8814 "%s* and %s* components; use only one style.", 8815 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 8816 } 8817 8818 if (!hasKernelDependency && !hasKPIDependency) { 8819 // xxx - do we want to use validation flag for these too? 8820 OSKextLog(this, 8821 kOSKextLogWarningLevel | 8822 kOSKextLogDependenciesFlag, 8823 "Warning - %s declares no kernel dependencies; using %s.", 8824 getIdentifierCString(), KERNEL6_LIB); 8825 OSKext * kernelKext = OSDynamicCast(OSKext, 8826 sKextsByID->getObject(KERNEL6_LIB)); 8827 if (kernelKext) { 8828 dependencies->setObject(kernelKext); 8829 } else { 8830 OSKextLog(this, 8831 kOSKextLogErrorLevel | 8832 kOSKextLogDependenciesFlag, 8833 "Error - Library %s not found for %s.", 8834 KERNEL6_LIB, getIdentifierCString()); 8835 } 8836 } 8837 8838 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of 8839 * its indirect dependencies to simulate old-style linking. XXX - Should 8840 * check for duplicates. 8841 */ 8842 if (!hasKPIDependency) { 8843 unsigned int i; 8844 8845 flags.hasBleedthrough = true; 8846 8847 count = getNumDependencies(); 8848 8849 /* We add to the dependencies array in this loop, but do not iterate 8850 * past its original count. 8851 */ 8852 for (i = 0; i < count; i++) { 8853 OSKext * dependencyKext = OSDynamicCast(OSKext, 8854 dependencies->getObject(i)); 8855 dependencyKext->addBleedthroughDependencies(dependencies.get()); 8856 } 8857 } 8858 #endif /* __LP64__ */ 8859 8860 #if CONFIG_KXLD 8861 /* 8862 * If we're not dynamically linking kexts, then we don't need to check 8863 * copyright strings. The linker in user space has already done this. 8864 */ 8865 if (hasPrivateKPIDependency) { 8866 bool hasApplePrefix = false; 8867 bool infoCopyrightIsValid = false; 8868 bool readableCopyrightIsValid = false; 8869 8870 hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(), 8871 APPLE_KEXT_PREFIX); 8872 8873 infoString = OSDynamicCast(OSString, 8874 getPropertyForHostArch("CFBundleGetInfoString")); 8875 if (infoString) { 8876 infoCopyrightIsValid = 8877 kxld_validate_copyright_string(infoString->getCStringNoCopy()); 8878 } 8879 8880 readableString = OSDynamicCast(OSString, 8881 getPropertyForHostArch("NSHumanReadableCopyright")); 8882 if (readableString) { 8883 readableCopyrightIsValid = 8884 kxld_validate_copyright_string(readableString->getCStringNoCopy()); 8885 } 8886 8887 if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) { 8888 OSKextLog(this, 8889 kOSKextLogErrorLevel | 8890 kOSKextLogDependenciesFlag, 8891 "Error - kext %s declares a dependency on %s. " 8892 "Only Apple kexts may declare a dependency on %s.", 8893 getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI); 8894 goto finish; 8895 } 8896 } 8897 #endif // CONFIG_KXLD 8898 8899 result = true; 8900 flags.hasAllDependencies = 1; 8901 8902 finish: 8903 8904 if (addedToLoopStack) { 8905 count = loopStack->getCount(); 8906 if (count > 0 && (this == loopStack->getObject(count - 1))) { 8907 loopStack->removeObject(count - 1); 8908 } else { 8909 OSKextLog(this, 8910 kOSKextLogErrorLevel | 8911 kOSKextLogDependenciesFlag, 8912 "Kext %s - internal error resolving dependencies.", 8913 getIdentifierCString()); 8914 } 8915 } 8916 8917 if (result && localLoopStack) { 8918 OSKextLog(this, 8919 kOSKextLogStepLevel | 8920 kOSKextLogDependenciesFlag, 8921 "Kext %s successfully resolved dependencies.", 8922 getIdentifierCString()); 8923 } 8924 8925 return result; 8926 } 8927 8928 /********************************************************************* 8929 *********************************************************************/ 8930 bool 8931 OSKext::addBleedthroughDependencies(OSArray * anArray) 8932 { 8933 bool result = false; 8934 unsigned int dependencyIndex, dependencyCount; 8935 8936 dependencyCount = getNumDependencies(); 8937 8938 for (dependencyIndex = 0; 8939 dependencyIndex < dependencyCount; 8940 dependencyIndex++) { 8941 OSKext * dependency = OSDynamicCast(OSKext, 8942 dependencies->getObject(dependencyIndex)); 8943 if (!dependency) { 8944 OSKextLog(this, 8945 kOSKextLogErrorLevel | 8946 kOSKextLogDependenciesFlag, 8947 "Kext %s - internal error propagating compatibility dependencies.", 8948 getIdentifierCString()); 8949 goto finish; 8950 } 8951 if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) { 8952 anArray->setObject(dependency); 8953 } 8954 dependency->addBleedthroughDependencies(anArray); 8955 } 8956 8957 result = true; 8958 8959 finish: 8960 return result; 8961 } 8962 8963 /********************************************************************* 8964 *********************************************************************/ 8965 bool 8966 OSKext::flushDependencies(bool forceFlag) 8967 { 8968 bool result = false; 8969 8970 /* Only clear the dependencies if the kext isn't loaded; 8971 * we need the info for loaded kexts to track references. 8972 */ 8973 if (!isLoaded() || forceFlag) { 8974 if (dependencies) { 8975 // xxx - check level 8976 OSKextLog(this, 8977 kOSKextLogProgressLevel | 8978 kOSKextLogDependenciesFlag, 8979 "Kext %s flushing dependencies.", 8980 getIdentifierCString()); 8981 dependencies.reset(); 8982 } 8983 if (!isKernelComponent()) { 8984 flags.hasAllDependencies = 0; 8985 } 8986 result = true; 8987 } 8988 8989 return result; 8990 } 8991 8992 /********************************************************************* 8993 *********************************************************************/ 8994 uint32_t 8995 OSKext::getNumDependencies(void) 8996 { 8997 if (!dependencies) { 8998 return 0; 8999 } 9000 return dependencies->getCount(); 9001 } 9002 9003 /********************************************************************* 9004 *********************************************************************/ 9005 OSArray * 9006 OSKext::getDependencies(void) 9007 { 9008 return dependencies.get(); 9009 } 9010 9011 bool 9012 OSKext::hasDependency(const OSSymbol * depID) 9013 { 9014 bool result __block; 9015 9016 if (depID == getIdentifier()) { 9017 return true; 9018 } 9019 if (!dependencies) { 9020 return false; 9021 } 9022 result = false; 9023 dependencies->iterateObjects(^bool (OSObject * obj) { 9024 OSKext * kext; 9025 kext = OSDynamicCast(OSKext, obj); 9026 if (!kext) { 9027 return false; 9028 } 9029 result = (depID == kext->getIdentifier()); 9030 return result; 9031 }); 9032 return result; 9033 } 9034 9035 #if PRAGMA_MARK 9036 #pragma mark OSMetaClass Support 9037 #endif 9038 /********************************************************************* 9039 *********************************************************************/ 9040 OSReturn 9041 OSKext::addClass( 9042 OSMetaClass * aClass, 9043 uint32_t numClasses) 9044 { 9045 OSReturn result = kOSMetaClassNoInsKModSet; 9046 9047 if (!metaClasses) { 9048 metaClasses = OSSet::withCapacity(numClasses); 9049 if (!metaClasses) { 9050 goto finish; 9051 } 9052 } 9053 9054 if (metaClasses->containsObject(aClass)) { 9055 OSKextLog(this, 9056 kOSKextLogWarningLevel | 9057 kOSKextLogLoadFlag, 9058 "Notice - kext %s has already registered class %s.", 9059 getIdentifierCString(), 9060 aClass->getClassName()); 9061 result = kOSReturnSuccess; 9062 goto finish; 9063 } 9064 9065 if (!metaClasses->setObject(aClass)) { 9066 goto finish; 9067 } else { 9068 OSKextLog(this, 9069 kOSKextLogDetailLevel | 9070 kOSKextLogLoadFlag, 9071 "Kext %s registered class %s.", 9072 getIdentifierCString(), 9073 aClass->getClassName()); 9074 } 9075 9076 if (!flags.autounloadEnabled) { 9077 const OSMetaClass * metaScan = NULL; // do not release 9078 9079 for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) { 9080 if (metaScan == OSTypeID(IOService)) { 9081 OSKextLog(this, 9082 kOSKextLogProgressLevel | 9083 kOSKextLogLoadFlag, 9084 "Kext %s has IOService subclass %s; enabling autounload.", 9085 getIdentifierCString(), 9086 aClass->getClassName()); 9087 9088 flags.autounloadEnabled = (0 == flags.unloadUnsupported); 9089 break; 9090 } 9091 } 9092 } 9093 9094 notifyAddClassObservers(this, aClass, flags); 9095 9096 result = kOSReturnSuccess; 9097 9098 finish: 9099 if (result != kOSReturnSuccess) { 9100 OSKextLog(this, 9101 kOSKextLogErrorLevel | 9102 kOSKextLogLoadFlag, 9103 "Kext %s failed to register class %s.", 9104 getIdentifierCString(), 9105 aClass->getClassName()); 9106 } 9107 9108 return result; 9109 } 9110 9111 /********************************************************************* 9112 *********************************************************************/ 9113 OSReturn 9114 OSKext::removeClass( 9115 OSMetaClass * aClass) 9116 { 9117 OSReturn result = kOSMetaClassNoKModSet; 9118 9119 if (!metaClasses) { 9120 goto finish; 9121 } 9122 9123 if (!metaClasses->containsObject(aClass)) { 9124 OSKextLog(this, 9125 kOSKextLogWarningLevel | 9126 kOSKextLogLoadFlag, 9127 "Notice - kext %s asked to unregister unknown class %s.", 9128 getIdentifierCString(), 9129 aClass->getClassName()); 9130 result = kOSReturnSuccess; 9131 goto finish; 9132 } 9133 9134 OSKextLog(this, 9135 kOSKextLogDetailLevel | 9136 kOSKextLogLoadFlag, 9137 "Kext %s unregistering class %s.", 9138 getIdentifierCString(), 9139 aClass->getClassName()); 9140 9141 metaClasses->removeObject(aClass); 9142 9143 notifyRemoveClassObservers(this, aClass, flags); 9144 9145 result = kOSReturnSuccess; 9146 9147 finish: 9148 if (result != kOSReturnSuccess) { 9149 OSKextLog(this, 9150 kOSKextLogErrorLevel | 9151 kOSKextLogLoadFlag, 9152 "Failed to unregister kext %s class %s.", 9153 getIdentifierCString(), 9154 aClass->getClassName()); 9155 } 9156 return result; 9157 } 9158 9159 /********************************************************************* 9160 *********************************************************************/ 9161 OSSet * 9162 OSKext::getMetaClasses(void) 9163 { 9164 return metaClasses.get(); 9165 } 9166 9167 /********************************************************************* 9168 *********************************************************************/ 9169 bool 9170 OSKext::hasOSMetaClassInstances(void) 9171 { 9172 bool result = false; 9173 OSSharedPtr<OSCollectionIterator> classIterator; 9174 OSMetaClass * checkClass = NULL; // do not release 9175 9176 if (!metaClasses) { 9177 goto finish; 9178 } 9179 9180 classIterator = OSCollectionIterator::withCollection(metaClasses.get()); 9181 if (!classIterator) { 9182 // xxx - log alloc failure? 9183 goto finish; 9184 } 9185 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 9186 if (checkClass->getInstanceCount()) { 9187 result = true; 9188 goto finish; 9189 } 9190 } 9191 9192 finish: 9193 return result; 9194 } 9195 9196 /********************************************************************* 9197 *********************************************************************/ 9198 /* static */ 9199 void 9200 OSKext::reportOSMetaClassInstances( 9201 const char * kextIdentifier, 9202 OSKextLogSpec msgLogSpec) 9203 { 9204 OSSharedPtr<OSKext> theKext; 9205 9206 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 9207 if (!theKext) { 9208 goto finish; 9209 } 9210 9211 theKext->reportOSMetaClassInstances(msgLogSpec); 9212 finish: 9213 return; 9214 } 9215 9216 /********************************************************************* 9217 *********************************************************************/ 9218 void 9219 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec) 9220 { 9221 OSSharedPtr<OSCollectionIterator> classIterator; 9222 OSMetaClass * checkClass = NULL; // do not release 9223 9224 if (!metaClasses) { 9225 goto finish; 9226 } 9227 9228 classIterator = OSCollectionIterator::withCollection(metaClasses.get()); 9229 if (!classIterator) { 9230 goto finish; 9231 } 9232 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 9233 if (checkClass->getInstanceCount()) { 9234 OSKextLog(this, 9235 msgLogSpec, 9236 " Kext %s class %s has %d instance%s.", 9237 getIdentifierCString(), 9238 checkClass->getClassName(), 9239 checkClass->getInstanceCount(), 9240 checkClass->getInstanceCount() == 1 ? "" : "s"); 9241 } 9242 } 9243 9244 finish: 9245 return; 9246 } 9247 9248 #if PRAGMA_MARK 9249 #pragma mark User-Space Requests 9250 #endif 9251 9252 static kern_return_t 9253 patchDextLaunchRequests(task_t calling_task, OSArray *requests) 9254 { 9255 OSReturn result = kOSReturnSuccess; 9256 for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) { 9257 OSDictionary * request = NULL; //do not release 9258 IOUserServerCheckInToken * token = NULL; //do not release 9259 OSString * requestPredicate = NULL; //do not release 9260 OSSharedPtr<OSNumber> portNameNumber; 9261 mach_port_name_t portName = 0; 9262 request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex)); 9263 if (!request) { 9264 OSKextLog(/* kext */ NULL, 9265 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9266 "Elements of request should be of type OSDictionary"); 9267 result = kOSKextReturnInternalError; 9268 goto finish; 9269 } 9270 requestPredicate = _OSKextGetRequestPredicate(request); 9271 if (!requestPredicate) { 9272 OSKextLog(/* kext */ NULL, 9273 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9274 "Failed to get request predicate"); 9275 result = kOSKextReturnInternalError; 9276 goto finish; 9277 } 9278 // is this a dext launch? 9279 if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) { 9280 token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken)); 9281 if (!token) { 9282 OSKextLog(/* kext */ NULL, 9283 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9284 "Could not find a IOUserServerCheckInToken in daemon launch request."); 9285 result = kOSKextReturnInternalError; 9286 goto finish; 9287 } 9288 portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT); 9289 if (portName == 0 || portName == MACH_PORT_DEAD) { 9290 OSKextLog(/* kext */ NULL, 9291 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9292 "Could not create send right for object."); 9293 result = kOSKextReturnInternalError; 9294 goto finish; 9295 } 9296 // Store the mach port name as a OSNumber 9297 portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName)); 9298 if (!portNameNumber) { 9299 OSKextLog(/* kext */ NULL, 9300 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9301 "Could not create OSNumber object."); 9302 result = kOSKextReturnNoMemory; 9303 goto finish; 9304 } 9305 if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) { 9306 OSKextLog(/* kext */ NULL, 9307 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9308 "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken); 9309 result = kOSKextReturnNoMemory; 9310 goto finish; 9311 } 9312 } 9313 finish: 9314 if (result != kOSReturnSuccess) { 9315 break; 9316 } 9317 } 9318 return result; 9319 } 9320 9321 /********************************************************************* 9322 * XXX - this function is a big ugly mess 9323 *********************************************************************/ 9324 /* static */ 9325 OSReturn 9326 OSKext::handleRequest( 9327 host_priv_t hostPriv, 9328 OSKextLogSpec clientLogFilter, 9329 char * requestBuffer, 9330 uint32_t requestLength, 9331 char ** responseOut, 9332 uint32_t * responseLengthOut, 9333 char ** logInfoOut, 9334 uint32_t * logInfoLengthOut) 9335 { 9336 OSReturn result = kOSReturnError; 9337 kern_return_t kmem_result = KERN_FAILURE; 9338 9339 char * response = NULL; // returned by reference 9340 uint32_t responseLength = 0; 9341 9342 bool taskCanManageAllKCs = false; 9343 bool taskOnlyManagesBootKC = false; 9344 9345 OSSharedPtr<OSObject> parsedXML; 9346 OSDictionary * requestDict = NULL; // do not release 9347 OSSharedPtr<OSString> errorString; 9348 9349 OSSharedPtr<OSObject> responseObject; 9350 9351 OSSharedPtr<OSSerialize> serializer; 9352 9353 OSSharedPtr<OSArray> logInfoArray; 9354 9355 OSString * predicate = NULL; // do not release 9356 OSString * kextIdentifier = NULL; // do not release 9357 OSArray * kextIdentifiers = NULL; // do not release 9358 OSKext * theKext = NULL; // do not release 9359 OSBoolean * boolArg = NULL; // do not release 9360 9361 IORecursiveLockLock(sKextLock); 9362 9363 if (responseOut) { 9364 *responseOut = NULL; 9365 *responseLengthOut = 0; 9366 } 9367 if (logInfoOut) { 9368 *logInfoOut = NULL; 9369 *logInfoLengthOut = 0; 9370 } 9371 9372 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 9373 9374 /* XML must be nul-terminated. 9375 */ 9376 if (requestBuffer[requestLength - 1] != '\0') { 9377 OSKextLog(/* kext */ NULL, 9378 kOSKextLogErrorLevel | 9379 kOSKextLogIPCFlag, 9380 "Invalid request from user space (not nul-terminated)."); 9381 result = kOSKextReturnBadData; 9382 goto finish; 9383 } 9384 parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString); 9385 if (parsedXML) { 9386 requestDict = OSDynamicCast(OSDictionary, parsedXML.get()); 9387 } 9388 if (!requestDict) { 9389 const char * errorCString = "(unknown error)"; 9390 9391 if (errorString && errorString->getCStringNoCopy()) { 9392 errorCString = errorString->getCStringNoCopy(); 9393 } else if (parsedXML) { 9394 errorCString = "not a dictionary"; 9395 } 9396 OSKextLog(/* kext */ NULL, 9397 kOSKextLogErrorLevel | 9398 kOSKextLogIPCFlag, 9399 "Error unserializing request from user space: %s.", 9400 errorCString); 9401 result = kOSKextReturnSerialization; 9402 goto finish; 9403 } 9404 9405 predicate = _OSKextGetRequestPredicate(requestDict); 9406 if (!predicate) { 9407 OSKextLog(/* kext */ NULL, 9408 kOSKextLogErrorLevel | 9409 kOSKextLogIPCFlag, 9410 "Recieved kext request from user space with no predicate."); 9411 result = kOSKextReturnInvalidArgument; 9412 goto finish; 9413 } 9414 9415 OSKextLog(/* kext */ NULL, 9416 kOSKextLogDebugLevel | 9417 kOSKextLogIPCFlag, 9418 "Received '%s' request from user space.", 9419 predicate->getCStringNoCopy()); 9420 9421 /* 9422 * All management of file sets requires an entitlement 9423 */ 9424 result = kOSKextReturnNotPrivileged; 9425 if (predicate->isEqualTo(kKextRequestPredicateUnload) || 9426 predicate->isEqualTo(kKextRequestPredicateStart) || 9427 predicate->isEqualTo(kKextRequestPredicateStop) || 9428 predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) || 9429 predicate->isEqualTo(kKextRequestPredicateSendResource) || 9430 predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) || 9431 predicate->isEqualTo(kKextRequestPredicateLoadCodeless) || 9432 predicate->isEqualTo(kKextRequestPredicateLoadFromKC) || 9433 predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) || 9434 predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) || 9435 predicate->isEqualTo(kKextRequestPredicateDaemonReady)) { 9436 if (hostPriv == HOST_PRIV_NULL) { 9437 OSKextLog(/* kext */ NULL, 9438 kOSKextLogErrorLevel | 9439 kOSKextLogIPCFlag, 9440 "Access Failure - must be root user."); 9441 goto finish; 9442 } 9443 taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE; 9444 taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE; 9445 9446 if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) { 9447 OSKextLog(/* kext */ NULL, 9448 kOSKextLogErrorLevel | 9449 kOSKextLogIPCFlag, 9450 "Access Failure - client not entitled to manage file sets."); 9451 goto finish; 9452 } 9453 9454 /* 9455 * The OnlyBootKC entitlement restricts the 9456 * collection-management entitlement to only managing kexts in 9457 * the BootKC. All other predicates that alter global state or 9458 * add new KCs are disallowed. 9459 */ 9460 if (taskOnlyManagesBootKC && 9461 (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) || 9462 predicate->isEqualTo(kKextRequestPredicateSendResource) || 9463 predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) || 9464 predicate->isEqualTo(kKextRequestPredicateLoadCodeless) || 9465 predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) || 9466 predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) || 9467 predicate->isEqualTo(kKextRequestPredicateDaemonReady))) { 9468 OSKextLog(/* kext */ NULL, 9469 kOSKextLogErrorLevel | 9470 kOSKextLogIPCFlag, 9471 "Access Failure - client not entitled to manage non-primary KCs"); 9472 goto finish; 9473 } 9474 9475 /* 9476 * If we get here, then the process either has the full KC 9477 * management entitlement, or it has the BootKC-only 9478 * entitlement and the request is about the BootKC. 9479 */ 9480 } 9481 9482 /* Get common args in anticipation of use. 9483 */ 9484 kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument( 9485 requestDict, kKextRequestArgumentBundleIdentifierKey)); 9486 kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 9487 requestDict, kKextRequestArgumentBundleIdentifierKey)); 9488 if (kextIdentifier) { 9489 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 9490 } 9491 boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 9492 requestDict, kKextRequestArgumentValueKey)); 9493 9494 if (taskOnlyManagesBootKC && 9495 theKext && 9496 theKext->isInFileset() && 9497 theKext->kc_type != KCKindPrimary) { 9498 OSKextLog(/* kext */ NULL, 9499 kOSKextLogErrorLevel | 9500 kOSKextLogIPCFlag, 9501 "Access Failure - client not entitled to manage kext in non-primary KC"); 9502 result = kOSKextReturnNotPrivileged; 9503 goto finish; 9504 } 9505 9506 result = kOSKextReturnInvalidArgument; 9507 9508 if (predicate->isEqualTo(kKextRequestPredicateStart)) { 9509 if (!kextIdentifier) { 9510 OSKextLog(/* kext */ NULL, 9511 kOSKextLogErrorLevel | 9512 kOSKextLogIPCFlag, 9513 "Invalid arguments to kext start request."); 9514 } else if (!theKext) { 9515 OSKextLog(/* kext */ NULL, 9516 kOSKextLogErrorLevel | 9517 kOSKextLogIPCFlag, 9518 "Kext %s not found for start request.", 9519 kextIdentifier->getCStringNoCopy()); 9520 result = kOSKextReturnNotFound; 9521 } else { 9522 result = theKext->start(); 9523 } 9524 } else if (predicate->isEqualTo(kKextRequestPredicateStop)) { 9525 if (!kextIdentifier) { 9526 OSKextLog(/* kext */ NULL, 9527 kOSKextLogErrorLevel | 9528 kOSKextLogIPCFlag, 9529 "Invalid arguments to kext stop request."); 9530 } else if (!theKext) { 9531 OSKextLog(/* kext */ NULL, 9532 kOSKextLogErrorLevel | 9533 kOSKextLogIPCFlag, 9534 "Kext %s not found for stop request.", 9535 kextIdentifier->getCStringNoCopy()); 9536 result = kOSKextReturnNotFound; 9537 } else { 9538 result = theKext->stop(); 9539 } 9540 } else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) { 9541 result = OSKext::setMissingAuxKCBundles(requestDict); 9542 } else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) { 9543 if (!kextIdentifier) { 9544 OSKextLog(/* kext */ NULL, 9545 kOSKextLogErrorLevel | 9546 kOSKextLogIPCFlag, 9547 "Invalid arguments to AuxKC Bundle Available request."); 9548 } else { 9549 result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict); 9550 } 9551 } else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) { 9552 if (!kextIdentifier) { 9553 OSKextLog(/* kext */ NULL, 9554 kOSKextLogErrorLevel | 9555 kOSKextLogIPCFlag, 9556 "Invalid arguments to kext load from KC request."); 9557 } else if (!theKext) { 9558 OSKextLog(/* kext */ NULL, 9559 kOSKextLogErrorLevel | 9560 kOSKextLogIPCFlag, 9561 "Kext %s not found for load from KC request.", 9562 kextIdentifier->getCStringNoCopy()); 9563 result = kOSKextReturnNotFound; 9564 } else if (!theKext->isInFileset()) { 9565 OSKextLog(/* kext */ NULL, 9566 kOSKextLogErrorLevel | 9567 kOSKextLogIPCFlag, 9568 "Kext %s does not exist in a KC: refusing to load.", 9569 kextIdentifier->getCStringNoCopy()); 9570 result = kOSKextReturnNotLoadable; 9571 } else { 9572 result = OSKext::loadKextFromKC(theKext, requestDict); 9573 } 9574 } else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) { 9575 if (!kextIdentifier) { 9576 OSKextLog(/* kext */ NULL, 9577 kOSKextLogErrorLevel | 9578 kOSKextLogIPCFlag, 9579 "Invalid arguments to codeless kext load interface (missing identifier)."); 9580 } else { 9581 result = OSKext::loadCodelessKext(kextIdentifier, requestDict); 9582 } 9583 } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) { 9584 if (!kextIdentifier) { 9585 OSKextLog(/* kext */ NULL, 9586 kOSKextLogErrorLevel | 9587 kOSKextLogIPCFlag, 9588 "Invalid arguments to kext unload request."); 9589 } else if (!theKext) { 9590 OSKextLog(/* kext */ NULL, 9591 kOSKextLogErrorLevel | 9592 kOSKextLogIPCFlag, 9593 "Kext %s not found for unload request.", 9594 kextIdentifier->getCStringNoCopy()); 9595 result = kOSKextReturnNotFound; 9596 } else { 9597 OSBoolean * terminateFlag = OSDynamicCast(OSBoolean, 9598 _OSKextGetRequestArgument(requestDict, 9599 kKextRequestArgumentTerminateIOServicesKey)); 9600 result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue); 9601 } 9602 } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) { 9603 result = OSKext::dispatchResource(requestDict); 9604 } else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) { 9605 OSNumber *lookupNum = NULL; 9606 lookupNum = OSDynamicCast(OSNumber, 9607 _OSKextGetRequestArgument(requestDict, 9608 kKextRequestArgumentLookupAddressKey)); 9609 9610 responseObject = OSKext::copyKextUUIDForAddress(lookupNum); 9611 if (responseObject) { 9612 result = kOSReturnSuccess; 9613 } else { 9614 goto finish; 9615 } 9616 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) || 9617 predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) || 9618 predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) { 9619 OSBoolean * delayAutounloadBool = NULL; 9620 OSObject * infoKeysRaw = NULL; 9621 OSArray * infoKeys = NULL; 9622 uint32_t infoKeysCount = 0; 9623 9624 delayAutounloadBool = OSDynamicCast(OSBoolean, 9625 _OSKextGetRequestArgument(requestDict, 9626 kKextRequestArgumentDelayAutounloadKey)); 9627 9628 /* If asked to delay autounload, reset the timer if it's currently set. 9629 * (That is, don't schedule an unload if one isn't already pending. 9630 */ 9631 if (delayAutounloadBool == kOSBooleanTrue) { 9632 OSKext::considerUnloads(/* rescheduleOnly? */ true); 9633 } 9634 9635 infoKeysRaw = _OSKextGetRequestArgument(requestDict, 9636 kKextRequestArgumentInfoKeysKey); 9637 infoKeys = OSDynamicCast(OSArray, infoKeysRaw); 9638 if (infoKeysRaw && !infoKeys) { 9639 OSKextLog(/* kext */ NULL, 9640 kOSKextLogErrorLevel | 9641 kOSKextLogIPCFlag, 9642 "Invalid arguments to kext info request."); 9643 goto finish; 9644 } 9645 9646 if (infoKeys) { 9647 infoKeysCount = infoKeys->getCount(); 9648 for (uint32_t i = 0; i < infoKeysCount; i++) { 9649 if (!OSDynamicCast(OSString, infoKeys->getObject(i))) { 9650 OSKextLog(/* kext */ NULL, 9651 kOSKextLogErrorLevel | 9652 kOSKextLogIPCFlag, 9653 "Invalid arguments to kext info request."); 9654 goto finish; 9655 } 9656 } 9657 } 9658 9659 if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) { 9660 responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys); 9661 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) { 9662 responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys); 9663 } else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) { 9664 responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys); 9665 } 9666 9667 if (!responseObject) { 9668 result = kOSKextReturnInternalError; 9669 } else { 9670 OSKextLog(/* kext */ NULL, 9671 kOSKextLogDebugLevel | 9672 kOSKextLogIPCFlag, 9673 "Returning loaded kext info."); 9674 result = kOSReturnSuccess; 9675 } 9676 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 9677 /* Hand the current sKernelRequests array to the caller 9678 * (who must release it), and make a new one. 9679 */ 9680 responseObject = os::move(sKernelRequests); 9681 sKernelRequests = OSArray::withCapacity(0); 9682 sPostedKextLoadIdentifiers->flushCollection(); 9683 OSKextLog(/* kext */ NULL, 9684 kOSKextLogDebugLevel | 9685 kOSKextLogIPCFlag, 9686 "Returning kernel requests."); 9687 result = kOSReturnSuccess; 9688 } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) { 9689 /* Return the set of all requested bundle identifiers */ 9690 responseObject = sAllKextLoadIdentifiers; 9691 OSKextLog(/* kext */ NULL, 9692 kOSKextLogDebugLevel | 9693 kOSKextLogIPCFlag, 9694 "Returning load requests."); 9695 result = kOSReturnSuccess; 9696 } else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) { 9697 printf("KextLog: Loading FileSet KC(s)\n"); 9698 result = OSKext::loadFileSetKexts(requestDict); 9699 } else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) { 9700 printf("KextLog: " kIOKitDaemonName " is %s\n", sIOKitDaemonActive ? "active" : "not active"); 9701 result = (sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot) ? kOSReturnSuccess : kIOReturnNotReady; 9702 } else { 9703 OSKextLog(/* kext */ NULL, 9704 kOSKextLogDebugLevel | 9705 kOSKextLogIPCFlag, 9706 "Received '%s' invalid request from user space.", 9707 predicate->getCStringNoCopy()); 9708 goto finish; 9709 } 9710 9711 /********** 9712 * Now we have handle the request, or not. Gather up the response & logging 9713 * info to ship to user space. 9714 *********/ 9715 9716 /* Note: Nothing in OSKext is supposed to retain requestDict, 9717 * but you never know.... 9718 */ 9719 if (requestDict->getRetainCount() > 1) { 9720 OSKextLog(/* kext */ NULL, 9721 kOSKextLogWarningLevel | 9722 kOSKextLogIPCFlag, 9723 "Request from user space still retained by a kext; " 9724 "probable memory leak."); 9725 } 9726 9727 if (responseOut && responseObject) { 9728 serializer = OSSerialize::withCapacity(0); 9729 if (!serializer) { 9730 result = kOSKextReturnNoMemory; 9731 goto finish; 9732 } 9733 /* 9734 * Before serializing the kernel requests, patch the dext launch requests so 9735 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the 9736 * IOUserServerCheckInToken kernel object. 9737 */ 9738 if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 9739 OSArray * requests = OSDynamicCast(OSArray, responseObject.get()); 9740 task_t calling_task = current_task(); 9741 if (!requests) { 9742 OSKextLog(/* kext */ NULL, 9743 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9744 "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests); 9745 result = kOSKextReturnInternalError; 9746 goto finish; 9747 } 9748 result = patchDextLaunchRequests(calling_task, requests); 9749 if (result != kOSReturnSuccess) { 9750 OSKextLog(/* kext */ NULL, 9751 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9752 "Failed to patch dext launch requests."); 9753 goto finish; 9754 } 9755 } 9756 9757 if (!responseObject->serialize(serializer.get())) { 9758 OSKextLog(/* kext */ NULL, 9759 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9760 "Failed to serialize response to request from user space."); 9761 result = kOSKextReturnSerialization; 9762 goto finish; 9763 } 9764 9765 response = (char *)serializer->text(); 9766 responseLength = serializer->getLength(); 9767 } 9768 9769 if (responseOut && response) { 9770 char * buffer; 9771 9772 /* This kmem_alloc sets the return value of the function. 9773 */ 9774 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, 9775 round_page(responseLength), VM_KERN_MEMORY_OSKEXT); 9776 if (kmem_result != KERN_SUCCESS) { 9777 OSKextLog(/* kext */ NULL, 9778 kOSKextLogErrorLevel | 9779 kOSKextLogIPCFlag, 9780 "Failed to copy response to request from user space."); 9781 result = kmem_result; 9782 goto finish; 9783 } else { 9784 /* 11981737 - clear uninitialized data in last page */ 9785 bzero((void *)(buffer + responseLength), 9786 (round_page(responseLength) - responseLength)); 9787 memcpy(buffer, response, responseLength); 9788 *responseOut = buffer; 9789 *responseLengthOut = responseLength; 9790 } 9791 } 9792 9793 finish: 9794 9795 /* Gather up the collected log messages for user space. Any messages 9796 * messages past this call will not make it up as log messages but 9797 * will be in the system log. Note that we ignore the return of the 9798 * serialize; it has no bearing on the operation at hand even if we 9799 * fail to get the log messages. 9800 */ 9801 logInfoArray = OSKext::clearUserSpaceLogFilter(); 9802 9803 if (logInfoArray && logInfoOut && logInfoLengthOut) { 9804 (void)OSKext::serializeLogInfo(logInfoArray.get(), 9805 logInfoOut, logInfoLengthOut); 9806 } 9807 9808 IORecursiveLockUnlock(sKextLock); 9809 9810 return result; 9811 } 9812 9813 #if PRAGMA_MARK 9814 #pragma mark Linked Kext Collection Support 9815 #endif 9816 9817 static int 9818 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount) 9819 { 9820 for (int i = 0; i < segCount; i++) { 9821 vm_offset_t segStart = segAddrs[i]; 9822 vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i]; 9823 9824 if (theAddr >= segStart && theAddr < segEnd) { 9825 return i; 9826 } 9827 } 9828 return -1; 9829 } 9830 9831 static void 9832 __slideOldKaslrOffsets(kernel_mach_header_t *mh, 9833 kernel_segment_command_t *kextTextSeg, 9834 OSData *kaslrOffsets) 9835 { 9836 static const char *plk_segNames[] = { 9837 "__TEXT", 9838 "__TEXT_EXEC", 9839 "__DATA", 9840 "__DATA_CONST", 9841 "__LINKEDIT", 9842 "__PRELINK_TEXT", 9843 "__PLK_TEXT_EXEC", 9844 "__PRELINK_DATA", 9845 "__PLK_DATA_CONST", 9846 "__PLK_LLVM_COV", 9847 "__PLK_LINKEDIT", 9848 "__PRELINK_INFO" 9849 }; 9850 static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0])); 9851 9852 unsigned long plk_segSizes[num_plk_seg]; 9853 vm_offset_t plk_segAddrs[num_plk_seg]; 9854 9855 for (size_t i = 0; i < num_plk_seg; i++) { 9856 plk_segSizes[i] = 0; 9857 plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]); 9858 } 9859 9860 uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr; 9861 9862 int slidKextAddrCount = 0; 9863 int badSlideAddr = 0; 9864 int badSlideTarget = 0; 9865 9866 struct kaslrPackedOffsets { 9867 uint32_t count; /* number of offsets */ 9868 uint32_t offsetsArray[]; /* offsets to slide */ 9869 }; 9870 const struct kaslrPackedOffsets *myOffsets = NULL; 9871 myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy(); 9872 9873 for (uint32_t j = 0; j < myOffsets->count; j++) { 9874 uint64_t slideOffset = (uint64_t)myOffsets->offsetsArray[j]; 9875 vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset); 9876 int slideAddrSegIndex = -1; 9877 int addrToSlideSegIndex = -1; 9878 9879 slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg); 9880 if (slideAddrSegIndex >= 0) { 9881 addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg); 9882 if (addrToSlideSegIndex < 0) { 9883 badSlideTarget++; 9884 continue; 9885 } 9886 } else { 9887 badSlideAddr++; 9888 continue; 9889 } 9890 9891 slidKextAddrCount++; 9892 *slideAddr = ml_static_slide(*slideAddr); 9893 } // for ... 9894 } 9895 9896 9897 9898 /******************************************************************** 9899 * addKextsFromKextCollection 9900 * 9901 * Input: MachO header of kext collection. The MachO is assumed to 9902 * have a section named 'info_seg_name,info_sect_name' that 9903 * contains a serialized XML info dictionary. This dictionary 9904 * contains a UUID, possibly a set of relocations (for older 9905 * kxld-built binaries), and an array of kext personalities. 9906 * 9907 ********************************************************************/ 9908 bool 9909 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh, 9910 OSDictionary *infoDict, const char *text_seg_name, 9911 OSData **kcUUID, kc_kind_t type) 9912 { 9913 bool result = false; 9914 9915 OSArray *kextArray = NULL; // do not release 9916 OSData *infoDictKCUUID = NULL; // do not release 9917 OSData *kaslrOffsets = NULL; // do not release 9918 9919 IORegistryEntry *registryRoot = NULL; // do not release 9920 OSSharedPtr<OSNumber> kcKextCount; 9921 9922 /* extract the KC UUID from the dictionary */ 9923 infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 9924 if (infoDictKCUUID) { 9925 if (infoDictKCUUID->getLength() != sizeof(uuid_t)) { 9926 panic("kcUUID length is %d, expected %lu", 9927 infoDictKCUUID->getLength(), sizeof(uuid_t)); 9928 } 9929 } 9930 9931 /* locate the array of kext dictionaries */ 9932 kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey)); 9933 if (!kextArray) { 9934 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 9935 "The given KC has no kext info dictionaries"); 9936 goto finish; 9937 } 9938 9939 /* 9940 * old-style KASLR offsets may be present in the info dictionary. If 9941 * we find them, use them and eventually slide them. 9942 */ 9943 kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey)); 9944 9945 /* 9946 * Before processing any kexts, locate the special kext bundle which 9947 * contains a list of kexts that we are to prevent from loading. 9948 */ 9949 createExcludeListFromPrelinkInfo(kextArray); 9950 9951 /* 9952 * Create OSKext objects for each kext we find in the array of kext 9953 * info plist dictionaries. 9954 */ 9955 for (int i = 0; i < (int)kextArray->getCount(); ++i) { 9956 OSDictionary *kextDict = NULL; 9957 kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i)); 9958 if (!kextDict) { 9959 OSKextLog(/* kext */ NULL, 9960 kOSKextLogErrorLevel | 9961 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 9962 "Kext info dictionary for kext #%d isn't a dictionary?", i); 9963 continue; 9964 } 9965 9966 /* 9967 * Create the kext for the entry, then release it, because the 9968 * kext system keeps a reference around until the kext is 9969 * explicitly removed. Any creation/registration failures are 9970 * already logged for us. 9971 */ 9972 withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type); 9973 } 9974 9975 /* 9976 * slide old-style kxld relocations 9977 * NOTE: this is still used on embedded KCs built with kcgen 9978 * TODO: Remove this once we use the new kext linker everywhere! 9979 */ 9980 if (kaslrOffsets && vm_kernel_slide > 0) { 9981 kernel_segment_command_t *text_segment = NULL; 9982 text_segment = getsegbynamefromheader(mh, text_seg_name); 9983 if (!text_segment) { 9984 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 9985 "Can't find a TEXT segment named '%s' in macho header", text_seg_name); 9986 goto finish; 9987 } 9988 9989 __slideOldKaslrOffsets(mh, text_segment, kaslrOffsets); 9990 /* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */ 9991 setAllVMAttributes(); 9992 } 9993 9994 /* Store the number of prelinked kexts in the registry so we can tell 9995 * when the system has been started from a prelinked kernel. 9996 */ 9997 registryRoot = IORegistryEntry::getRegistryRoot(); 9998 assert(registryRoot); 9999 10000 kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t)); 10001 assert(kcKextCount); 10002 if (kcKextCount) { 10003 OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey); 10004 OSNumber *num; 10005 num = OSDynamicCast(OSNumber, prop.get()); 10006 if (num) { 10007 kcKextCount->addValue(num->unsigned64BitValue()); 10008 } 10009 registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get()); 10010 } 10011 10012 OSKextLog(/* kext */ NULL, 10013 kOSKextLogProgressLevel | 10014 kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag | 10015 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 10016 "%u prelinked kexts", infoDict->getCount()); 10017 10018 10019 if (kcUUID && infoDictKCUUID) { 10020 *kcUUID = OSData::withData(infoDictKCUUID).detach(); 10021 } 10022 10023 result = true; 10024 10025 finish: 10026 return result; 10027 } 10028 10029 bool 10030 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh, 10031 OSDictionary *infoDict, const char *text_seg_name, 10032 OSSharedPtr<OSData> &kcUUID, kc_kind_t type) 10033 { 10034 OSData *result = NULL; 10035 bool success = addKextsFromKextCollection(mh, 10036 infoDict, 10037 text_seg_name, 10038 &result, 10039 type); 10040 if (success) { 10041 kcUUID.reset(result, OSNoRetain); 10042 } 10043 return success; 10044 } 10045 10046 static OSSharedPtr<OSObject> deferredAuxKCXML; 10047 bool 10048 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh, 10049 OSSharedPtr<OSObject> &parsedXML, kc_kind_t type) 10050 { 10051 if (type != KCKindAuxiliary) { 10052 return false; 10053 } 10054 10055 kernel_mach_header_t *_mh; 10056 _mh = (kernel_mach_header_t*)PE_get_kc_header(type); 10057 if (!_mh || _mh != mh) { 10058 return false; 10059 } 10060 10061 if (deferredAuxKCXML) { 10062 /* only allow this to be called once */ 10063 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 10064 "An Aux KC has already been registered for deferred processing."); 10065 return false; 10066 } 10067 10068 OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 10069 if (!infoDict) { 10070 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 10071 "The Aux KC has info dictionary"); 10072 return false; 10073 } 10074 10075 OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 10076 if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) { 10077 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 10078 "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey); 10079 return false; 10080 } 10081 10082 /* 10083 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid 10084 * sysctl can return the UUID to user space which will check this 10085 * value for errors. 10086 */ 10087 memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(), 10088 kcUUID->getLength()); 10089 uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string); 10090 auxkc_uuid_valid = TRUE; 10091 10092 deferredAuxKCXML = parsedXML; 10093 10094 return true; 10095 } 10096 10097 OSSharedPtr<OSObject> 10098 OSKext::consumeDeferredKextCollection(kc_kind_t type) 10099 { 10100 if (type != KCKindAuxiliary || !deferredAuxKCXML) { 10101 return NULL; 10102 } 10103 10104 return os::move(deferredAuxKCXML); 10105 } 10106 10107 #if PRAGMA_MARK 10108 #pragma mark Profile-Guided-Optimization Support 10109 #endif 10110 10111 // #include <InstrProfiling.h> 10112 extern "C" { 10113 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin, 10114 const char *DataEnd, 10115 const char *CountersBegin, 10116 const char *CountersEnd, 10117 const char *NamesBegin, 10118 const char *NamesEnd); 10119 int __llvm_profile_write_buffer_internal(char *Buffer, 10120 const char *DataBegin, 10121 const char *DataEnd, 10122 const char *CountersBegin, 10123 const char *CountersEnd, 10124 const char *NamesBegin, 10125 const char *NamesEnd); 10126 } 10127 10128 10129 static 10130 void 10131 OSKextPgoMetadataPut(char *pBuffer, 10132 size_t *position, 10133 size_t bufferSize, 10134 uint32_t *num_pairs, 10135 const char *key, 10136 const char *value) 10137 { 10138 size_t strlen_key = strlen(key); 10139 size_t strlen_value = strlen(value); 10140 size_t len = strlen(key) + 1 + strlen(value) + 1; 10141 char *pos = pBuffer + *position; 10142 *position += len; 10143 if (pBuffer && bufferSize && *position <= bufferSize) { 10144 memcpy(pos, key, strlen_key); pos += strlen_key; 10145 *(pos++) = '='; 10146 memcpy(pos, value, strlen_value); pos += strlen_value; 10147 *(pos++) = 0; 10148 if (num_pairs) { 10149 (*num_pairs)++; 10150 } 10151 } 10152 } 10153 10154 10155 static 10156 void 10157 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max) 10158 { 10159 *position += strlen(key) + 1 + value_max + 1; 10160 } 10161 10162 10163 static 10164 void 10165 OSKextPgoMetadataPutAll(OSKext *kext, 10166 uuid_t instance_uuid, 10167 char *pBuffer, 10168 size_t *position, 10169 size_t bufferSize, 10170 uint32_t *num_pairs) 10171 { 10172 _static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0); 10173 //log_10 2^16 ≈ 4.82 10174 const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2; 10175 const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6; 10176 10177 if (!pBuffer) { 10178 OSKextPgoMetadataPutMax(position, "INSTANCE", 36); 10179 OSKextPgoMetadataPutMax(position, "UUID", 36); 10180 OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size); 10181 } else { 10182 uuid_string_t instance_uuid_string; 10183 uuid_unparse(instance_uuid, instance_uuid_string); 10184 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10185 "INSTANCE", instance_uuid_string); 10186 10187 OSSharedPtr<OSData> uuid_data; 10188 uuid_t uuid; 10189 uuid_string_t uuid_string; 10190 uuid_data = kext->copyUUID(); 10191 if (uuid_data) { 10192 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 10193 uuid_unparse(uuid, uuid_string); 10194 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10195 "UUID", uuid_string); 10196 } 10197 10198 clock_sec_t secs; 10199 clock_usec_t usecs; 10200 clock_get_calendar_microtime(&secs, &usecs); 10201 assert(usecs < 1000000); 10202 char timestamp[max_timestamp_string_size + 1]; 10203 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t)); 10204 snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs); 10205 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10206 "TIMESTAMP", timestamp); 10207 } 10208 10209 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10210 "NAME", kext->getIdentifierCString()); 10211 10212 char versionCString[kOSKextVersionMaxLength]; 10213 OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength); 10214 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10215 "VERSION", versionCString); 10216 } 10217 10218 static 10219 size_t 10220 OSKextPgoMetadataSize(OSKext *kext) 10221 { 10222 size_t position = 0; 10223 uuid_t fakeuuid = {}; 10224 OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL); 10225 return position; 10226 } 10227 10228 int 10229 OSKextGrabPgoDataLocked(OSKext *kext, 10230 bool metadata, 10231 uuid_t instance_uuid, 10232 uint64_t *pSize, 10233 char *pBuffer, 10234 uint64_t bufferSize) 10235 { 10236 int err = 0; 10237 10238 kernel_section_t *sect_prf_data = NULL; 10239 kernel_section_t *sect_prf_name = NULL; 10240 kernel_section_t *sect_prf_cnts = NULL; 10241 uint64_t size; 10242 size_t metadata_size = 0; 10243 size_t offset_to_pairs = 0; 10244 10245 sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data"); 10246 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names"); 10247 if (!sect_prf_name) { 10248 // kextcache sometimes truncates the section name to 15 chars 10249 // <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache 10250 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name"); 10251 } 10252 sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 10253 10254 if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) { 10255 err = ENOTSUP; 10256 goto out; 10257 } 10258 10259 size = __llvm_profile_get_size_for_buffer_internal( 10260 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 10261 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 10262 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 10263 10264 if (metadata) { 10265 metadata_size = OSKextPgoMetadataSize(kext); 10266 size += metadata_size; 10267 size += sizeof(pgo_metadata_footer); 10268 } 10269 10270 10271 if (pSize) { 10272 *pSize = size; 10273 } 10274 10275 if (pBuffer && bufferSize) { 10276 if (bufferSize < size) { 10277 err = ERANGE; 10278 goto out; 10279 } 10280 10281 err = __llvm_profile_write_buffer_internal( 10282 pBuffer, 10283 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 10284 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 10285 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 10286 10287 if (err) { 10288 err = EIO; 10289 goto out; 10290 } 10291 10292 if (metadata) { 10293 offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size; 10294 if (offset_to_pairs > UINT32_MAX) { 10295 err = E2BIG; 10296 goto out; 10297 } 10298 10299 char *end_of_buffer = pBuffer + size; 10300 struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer)); 10301 char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size); 10302 10303 size_t metadata_position = 0; 10304 uint32_t num_pairs = 0; 10305 OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs); 10306 while (metadata_position < metadata_size) { 10307 metadata_buffer[metadata_position++] = 0; 10308 } 10309 10310 struct pgo_metadata_footer footer; 10311 footer.magic = htonl(0x6d657461); 10312 footer.number_of_pairs = htonl( num_pairs ); 10313 footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs ); 10314 memcpy(footerp, &footer, sizeof(footer)); 10315 } 10316 } 10317 10318 out: 10319 return err; 10320 } 10321 10322 10323 int 10324 OSKextGrabPgoData(uuid_t uuid, 10325 uint64_t *pSize, 10326 char *pBuffer, 10327 uint64_t bufferSize, 10328 int wait_for_unload, 10329 int metadata) 10330 { 10331 int err = 0; 10332 OSSharedPtr<OSKext> kext; 10333 10334 10335 IORecursiveLockLock(sKextLock); 10336 10337 kext = OSKext::lookupKextWithUUID(uuid); 10338 if (!kext) { 10339 err = ENOENT; 10340 goto out; 10341 } 10342 10343 if (wait_for_unload) { 10344 OSKextGrabPgoStruct s; 10345 10346 s.metadata = metadata; 10347 s.pSize = pSize; 10348 s.pBuffer = pBuffer; 10349 s.bufferSize = bufferSize; 10350 s.err = EINTR; 10351 10352 struct list_head *prev = &kext->pendingPgoHead; 10353 struct list_head *next = kext->pendingPgoHead.next; 10354 10355 s.list_head.prev = prev; 10356 s.list_head.next = next; 10357 10358 prev->next = &s.list_head; 10359 next->prev = &s.list_head; 10360 10361 kext.reset(); 10362 10363 IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE); 10364 10365 prev = s.list_head.prev; 10366 next = s.list_head.next; 10367 10368 prev->next = next; 10369 next->prev = prev; 10370 10371 err = s.err; 10372 } else { 10373 err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize); 10374 } 10375 10376 out: 10377 10378 IORecursiveLockUnlock(sKextLock); 10379 10380 return err; 10381 } 10382 10383 void 10384 OSKextResetPgoCountersLock() 10385 { 10386 IORecursiveLockLock(sKextLock); 10387 } 10388 10389 void 10390 OSKextResetPgoCountersUnlock() 10391 { 10392 IORecursiveLockUnlock(sKextLock); 10393 } 10394 10395 10396 extern unsigned int not_in_kdp; 10397 10398 void 10399 OSKextResetPgoCounters() 10400 { 10401 assert(!not_in_kdp); 10402 uint32_t count = sLoadedKexts->getCount(); 10403 for (uint32_t i = 0; i < count; i++) { 10404 OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 10405 kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 10406 if (!sect_prf_cnts) { 10407 continue; 10408 } 10409 memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size); 10410 } 10411 } 10412 10413 OSSharedPtr<OSDictionary> 10414 OSKext::copyLoadedKextInfoByUUID( 10415 OSArray * kextIdentifiers, 10416 OSArray * infoKeys) 10417 { 10418 OSSharedPtr<OSDictionary> result; 10419 OSSharedPtr<OSDictionary> kextInfo; 10420 uint32_t max_count, i, j; 10421 uint32_t idCount = 0; 10422 uint32_t idIndex = 0; 10423 IORecursiveLockLock(sKextLock); 10424 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 10425 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 10426 10427 #if CONFIG_MACF 10428 /* Is the calling process allowed to query kext info? */ 10429 if (current_task() != kernel_task) { 10430 int macCheckResult = 0; 10431 kauth_cred_t cred = NULL; 10432 10433 cred = kauth_cred_get_with_ref(); 10434 macCheckResult = mac_kext_check_query(cred); 10435 kauth_cred_unref(&cred); 10436 10437 if (macCheckResult != 0) { 10438 OSKextLog(/* kext */ NULL, 10439 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 10440 "Failed to query kext info (MAC policy error 0x%x).", 10441 macCheckResult); 10442 goto finish; 10443 } 10444 } 10445 #endif 10446 10447 /* Empty list of UUIDs is equivalent to no list (get all). 10448 */ 10449 if (kextIdentifiers && !kextIdentifiers->getCount()) { 10450 kextIdentifiers = NULL; 10451 } else if (kextIdentifiers) { 10452 idCount = kextIdentifiers->getCount(); 10453 } 10454 10455 /* Same for keys. 10456 */ 10457 if (infoKeys && !infoKeys->getCount()) { 10458 infoKeys = NULL; 10459 } 10460 10461 max_count = count[0] + count[1]; 10462 result = OSDictionary::withCapacity(max_count); 10463 if (!result) { 10464 goto finish; 10465 } 10466 10467 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 10468 for (i = 0; i < count[j]; i++) { 10469 OSKext *thisKext = NULL; // do not release 10470 Boolean includeThis = true; 10471 uuid_t thisKextUUID; 10472 uuid_t thisKextTextUUID; 10473 OSSharedPtr<OSData> uuid_data; 10474 uuid_string_t uuid_key; 10475 10476 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 10477 if (!thisKext) { 10478 continue; 10479 } 10480 10481 uuid_data = thisKext->copyUUID(); 10482 if (!uuid_data) { 10483 continue; 10484 } 10485 10486 memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID)); 10487 10488 uuid_unparse(thisKextUUID, uuid_key); 10489 10490 uuid_data = thisKext->copyTextUUID(); 10491 if (!uuid_data) { 10492 continue; 10493 } 10494 memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID)); 10495 10496 /* Skip current kext if we have a list of UUIDs and 10497 * it isn't in the list. 10498 */ 10499 if (kextIdentifiers) { 10500 includeThis = false; 10501 10502 for (idIndex = 0; idIndex < idCount; idIndex++) { 10503 const OSString* wantedUUID = OSDynamicCast(OSString, 10504 kextIdentifiers->getObject(idIndex)); 10505 10506 uuid_t uuid; 10507 uuid_parse(wantedUUID->getCStringNoCopy(), uuid); 10508 10509 if ((0 == uuid_compare(uuid, thisKextUUID)) 10510 || (0 == uuid_compare(uuid, thisKextTextUUID))) { 10511 includeThis = true; 10512 /* Only need to find the first kext if multiple match, 10513 * ie. asking for the kernel uuid does not need to find 10514 * interface kexts or builtin static kexts. 10515 */ 10516 kextIdentifiers->removeObject(idIndex); 10517 uuid_unparse(uuid, uuid_key); 10518 break; 10519 } 10520 } 10521 } 10522 10523 if (!includeThis) { 10524 continue; 10525 } 10526 10527 kextInfo = thisKext->copyInfo(infoKeys); 10528 if (kextInfo) { 10529 result->setObject(uuid_key, kextInfo.get()); 10530 } 10531 10532 if (kextIdentifiers && !kextIdentifiers->getCount()) { 10533 goto finish; 10534 } 10535 } 10536 } 10537 10538 finish: 10539 IORecursiveLockUnlock(sKextLock); 10540 10541 return result; 10542 } 10543 10544 /********************************************************************* 10545 *********************************************************************/ 10546 /* static */ 10547 OSSharedPtr<OSDictionary> 10548 OSKext::copyKextCollectionInfo( 10549 OSDictionary *requestDict, 10550 OSArray *infoKeys) 10551 { 10552 OSSharedPtr<OSDictionary> result; 10553 OSString *collectionType = NULL; 10554 OSObject *rawLoadedState = NULL; 10555 OSString *loadedState = NULL; 10556 10557 kc_kind_t kc_request_kind = KCKindUnknown; 10558 bool onlyLoaded = false; 10559 bool onlyUnloaded = false; 10560 10561 #if CONFIG_MACF 10562 /* Is the calling process allowed to query kext info? */ 10563 if (current_task() != kernel_task) { 10564 int macCheckResult = 0; 10565 kauth_cred_t cred = NULL; 10566 10567 cred = kauth_cred_get_with_ref(); 10568 macCheckResult = mac_kext_check_query(cred); 10569 kauth_cred_unref(&cred); 10570 10571 if (macCheckResult != 0) { 10572 OSKextLog(/* kext */ NULL, 10573 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 10574 "Failed to query kext info (MAC policy error 0x%x).", 10575 macCheckResult); 10576 goto finish; 10577 } 10578 } 10579 #endif 10580 10581 if (infoKeys && !infoKeys->getCount()) { 10582 infoKeys = NULL; 10583 } 10584 10585 collectionType = OSDynamicCast(OSString, 10586 _OSKextGetRequestArgument(requestDict, 10587 kKextRequestArgumentCollectionTypeKey)); 10588 if (!collectionType) { 10589 OSKextLog(/* kext */ NULL, 10590 kOSKextLogErrorLevel | 10591 kOSKextLogIPCFlag, 10592 "Invalid '%s' argument to kext collection info request.", 10593 kKextRequestArgumentCollectionTypeKey); 10594 goto finish; 10595 } 10596 if (collectionType->isEqualTo(kKCTypePrimary)) { 10597 kc_request_kind = KCKindPrimary; 10598 } else if (collectionType->isEqualTo(kKCTypeSystem)) { 10599 kc_request_kind = KCKindPageable; 10600 } else if (collectionType->isEqualTo(kKCTypeAuxiliary)) { 10601 kc_request_kind = KCKindAuxiliary; 10602 } else if (collectionType->isEqualTo(kKCTypeCodeless)) { 10603 kc_request_kind = KCKindNone; 10604 } else if (!collectionType->isEqualTo(kKCTypeAny)) { 10605 OSKextLog(/* kext */ NULL, 10606 kOSKextLogErrorLevel | 10607 kOSKextLogIPCFlag, 10608 "Invalid '%s' argument value '%s' to kext collection info request.", 10609 kKextRequestArgumentCollectionTypeKey, 10610 collectionType->getCStringNoCopy()); 10611 goto finish; 10612 } 10613 10614 rawLoadedState = _OSKextGetRequestArgument(requestDict, 10615 kKextRequestArgumentLoadedStateKey); 10616 if (rawLoadedState) { 10617 loadedState = OSDynamicCast(OSString, rawLoadedState); 10618 if (!loadedState) { 10619 OSKextLog(/* kext */ NULL, 10620 kOSKextLogErrorLevel | 10621 kOSKextLogIPCFlag, 10622 "Invalid '%s' argument to kext collection info request.", 10623 kKextRequestArgumentLoadedStateKey); 10624 goto finish; 10625 } 10626 } 10627 if (loadedState) { 10628 if (loadedState->isEqualTo("Loaded")) { 10629 onlyLoaded = true; 10630 } else if (loadedState->isEqualTo("Unloaded")) { 10631 onlyUnloaded = true; 10632 } else if (!loadedState->isEqualTo("Any")) { 10633 OSKextLog(/* kext */ NULL, 10634 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 10635 "Invalid '%s' argument value '%s' for '%s' collection info", 10636 kKextRequestArgumentLoadedStateKey, 10637 loadedState->getCStringNoCopy(), 10638 collectionType->getCStringNoCopy()); 10639 goto finish; 10640 } 10641 } 10642 10643 result = OSDictionary::withCapacity(sKextsByID->getCount()); 10644 if (!result) { 10645 goto finish; 10646 } 10647 10648 IORecursiveLockLock(sKextLock); 10649 { // start block scope 10650 sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj) 10651 { 10652 OSKext *thisKext = NULL; // do not release 10653 OSSharedPtr<OSDictionary> kextInfo; 10654 10655 (void)thisKextID; 10656 10657 thisKext = OSDynamicCast(OSKext, obj); 10658 if (!thisKext) { 10659 return false; 10660 } 10661 10662 /* 10663 * skip the kext if it came from the wrong collection type 10664 * (and the caller requested a specific type) 10665 */ 10666 if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) { 10667 return false; 10668 } 10669 10670 /* 10671 * respect the caller's desire to find only loaded or 10672 * unloaded kexts 10673 */ 10674 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 10675 return false; 10676 } 10677 if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 10678 return false; 10679 } 10680 10681 kextInfo = thisKext->copyInfo(infoKeys); 10682 if (kextInfo) { 10683 result->setObject(thisKext->getIdentifier(), kextInfo.get()); 10684 } 10685 return false; 10686 }); 10687 } // end block scope 10688 IORecursiveLockUnlock(sKextLock); 10689 10690 finish: 10691 return result; 10692 } 10693 10694 /********************************************************************* 10695 *********************************************************************/ 10696 /* static */ 10697 OSSharedPtr<OSDictionary> 10698 OSKext::copyLoadedKextInfo( 10699 OSArray * kextIdentifiers, 10700 OSArray * infoKeys) 10701 { 10702 OSSharedPtr<OSDictionary> result; 10703 uint32_t idCount = 0; 10704 bool onlyLoaded; 10705 10706 IORecursiveLockLock(sKextLock); 10707 10708 #if CONFIG_MACF 10709 /* Is the calling process allowed to query kext info? */ 10710 if (current_task() != kernel_task) { 10711 int macCheckResult = 0; 10712 kauth_cred_t cred = NULL; 10713 10714 cred = kauth_cred_get_with_ref(); 10715 macCheckResult = mac_kext_check_query(cred); 10716 kauth_cred_unref(&cred); 10717 10718 if (macCheckResult != 0) { 10719 OSKextLog(/* kext */ NULL, 10720 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 10721 "Failed to query kext info (MAC policy error 0x%x).", 10722 macCheckResult); 10723 goto finish; 10724 } 10725 } 10726 #endif 10727 10728 /* Empty list of bundle ids is equivalent to no list (get all). 10729 */ 10730 if (kextIdentifiers && !kextIdentifiers->getCount()) { 10731 kextIdentifiers = NULL; 10732 } else if (kextIdentifiers) { 10733 idCount = kextIdentifiers->getCount(); 10734 } 10735 10736 /* Same for keys. 10737 */ 10738 if (infoKeys && !infoKeys->getCount()) { 10739 infoKeys = NULL; 10740 } 10741 10742 onlyLoaded = (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey)); 10743 10744 result = OSDictionary::withCapacity(128); 10745 if (!result) { 10746 goto finish; 10747 } 10748 10749 #if 0 10750 OSKextLog(/* kext */ NULL, 10751 kOSKextLogErrorLevel | 10752 kOSKextLogGeneralFlag, 10753 "kaslr: vm_kernel_slide 0x%lx \n", 10754 vm_kernel_slide); 10755 OSKextLog(/* kext */ NULL, 10756 kOSKextLogErrorLevel | 10757 kOSKextLogGeneralFlag, 10758 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n", 10759 vm_kernel_stext, vm_kernel_etext); 10760 OSKextLog(/* kext */ NULL, 10761 kOSKextLogErrorLevel | 10762 kOSKextLogGeneralFlag, 10763 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n", 10764 vm_kernel_base, vm_kernel_top); 10765 OSKextLog(/* kext */ NULL, 10766 kOSKextLogErrorLevel | 10767 kOSKextLogGeneralFlag, 10768 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n", 10769 vm_kext_base, vm_kext_top); 10770 OSKextLog(/* kext */ NULL, 10771 kOSKextLogErrorLevel | 10772 kOSKextLogGeneralFlag, 10773 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n", 10774 vm_prelink_stext, vm_prelink_etext); 10775 OSKextLog(/* kext */ NULL, 10776 kOSKextLogErrorLevel | 10777 kOSKextLogGeneralFlag, 10778 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n", 10779 vm_prelink_sinfo, vm_prelink_einfo); 10780 OSKextLog(/* kext */ NULL, 10781 kOSKextLogErrorLevel | 10782 kOSKextLogGeneralFlag, 10783 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n", 10784 vm_slinkedit, vm_elinkedit); 10785 #endif 10786 { // start block scope 10787 sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj) 10788 { 10789 OSKext * thisKext = NULL; // do not release 10790 Boolean includeThis = true; 10791 OSSharedPtr<OSDictionary> kextInfo; 10792 10793 thisKext = OSDynamicCast(OSKext, obj); 10794 if (!thisKext) { 10795 return false; 10796 } 10797 10798 /* Skip current kext if not yet started and caller didn't request all. 10799 */ 10800 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 10801 return false; 10802 } 10803 10804 /* Skip current kext if we have a list of bundle IDs and 10805 * it isn't in the list. 10806 */ 10807 if (kextIdentifiers) { 10808 includeThis = false; 10809 10810 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) { 10811 const OSString * thisRequestID = OSDynamicCast(OSString, 10812 kextIdentifiers->getObject(idIndex)); 10813 if (thisKextID->isEqualTo(thisRequestID)) { 10814 includeThis = true; 10815 break; 10816 } 10817 } 10818 } 10819 10820 if (!includeThis) { 10821 return false; 10822 } 10823 10824 kextInfo = thisKext->copyInfo(infoKeys); 10825 if (kextInfo) { 10826 result->setObject(thisKext->getIdentifier(), kextInfo.get()); 10827 } 10828 return false; 10829 }); 10830 } // end block scope 10831 10832 finish: 10833 IORecursiveLockUnlock(sKextLock); 10834 10835 return result; 10836 } 10837 10838 /********************************************************************* 10839 * Any info that needs to do allocations must goto finish on alloc 10840 * failure. Info that is just a lookup should just not set the object 10841 * if the info does not exist. 10842 *********************************************************************/ 10843 #define _OSKextLoadInfoDictCapacity (12) 10844 10845 OSSharedPtr<OSDictionary> 10846 OSKext::copyInfo(OSArray * infoKeys) 10847 { 10848 OSSharedPtr<OSDictionary> result; 10849 bool success = false; 10850 OSSharedPtr<OSData> headerData; 10851 OSSharedPtr<OSData> logData; 10852 OSSharedPtr<OSNumber> cpuTypeNumber; 10853 OSSharedPtr<OSNumber> cpuSubtypeNumber; 10854 OSString * versionString = NULL; // do not release 10855 OSString * bundleType = NULL; // do not release 10856 uint32_t executablePathCStringSize = 0; 10857 char * executablePathCString = NULL; // must kfree 10858 OSSharedPtr<OSString> executablePathString; 10859 OSSharedPtr<OSData> uuid; 10860 OSSharedPtr<OSArray> dependencyLoadTags; 10861 OSSharedPtr<OSCollectionIterator> metaClassIterator; 10862 OSSharedPtr<OSArray> metaClassInfo; 10863 OSSharedPtr<OSDictionary> metaClassDict; 10864 OSMetaClass * thisMetaClass = NULL; // do not release 10865 OSSharedPtr<OSString> metaClassName; 10866 OSSharedPtr<OSString> superclassName; 10867 kc_format_t kcformat; 10868 uint32_t count, i; 10869 10870 result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity); 10871 if (!result) { 10872 goto finish; 10873 } 10874 10875 10876 /* Empty keys means no keys, but NULL is quicker to check. 10877 */ 10878 if (infoKeys && !infoKeys->getCount()) { 10879 infoKeys = NULL; 10880 } 10881 10882 if (!PE_get_primary_kc_format(&kcformat)) { 10883 goto finish; 10884 } 10885 10886 /* Headers, CPU type, and CPU subtype. 10887 */ 10888 if (!infoKeys || 10889 _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) || 10890 _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) || 10891 _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) || 10892 _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 10893 if (linkedExecutable && !isInterface()) { 10894 kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *) 10895 linkedExecutable->getBytesNoCopy(); 10896 10897 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX 10898 // do not return macho header info on shipping embedded - 19095897 10899 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) { 10900 kernel_mach_header_t * temp_kext_mach_hdr; 10901 struct load_command * lcp; 10902 10903 headerData = OSData::withBytes(kext_mach_hdr, 10904 (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds)); 10905 if (!headerData) { 10906 goto finish; 10907 } 10908 10909 // unslide any vmaddrs we return to userspace - 10726716 10910 temp_kext_mach_hdr = (kernel_mach_header_t *) 10911 headerData->getBytesNoCopy(); 10912 if (temp_kext_mach_hdr == NULL) { 10913 goto finish; 10914 } 10915 10916 lcp = (struct load_command *) (temp_kext_mach_hdr + 1); 10917 for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) { 10918 if (lcp->cmd == LC_SEGMENT_KERNEL) { 10919 kernel_segment_command_t * segp; 10920 kernel_section_t * secp; 10921 10922 segp = (kernel_segment_command_t *) lcp; 10923 // 10543468 - if we jettisoned __LINKEDIT clear size info 10924 if (flags.jettisonLinkeditSeg) { 10925 if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) { 10926 segp->vmsize = 0; 10927 segp->fileoff = 0; 10928 segp->filesize = 0; 10929 } 10930 } 10931 10932 #if __arm__ || __arm64__ 10933 // iBoot disregards zero-size segments, just set their addresses to gVirtBase 10934 // and unslide them to avoid vm assertion failures / kernel logging breakage. 10935 if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) { 10936 segp->vmaddr = gVirtBase; 10937 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { 10938 secp->size = 0; // paranoia :) 10939 secp->addr = gVirtBase; 10940 } 10941 } 10942 #endif 10943 10944 #if 0 10945 OSKextLog(/* kext */ NULL, 10946 kOSKextLogErrorLevel | 10947 kOSKextLogGeneralFlag, 10948 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u", 10949 __FUNCTION__, segp->segname, segp->vmaddr, 10950 VM_KERNEL_UNSLIDE(segp->vmaddr), 10951 segp->vmsize, segp->nsects); 10952 if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) && 10953 (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) && 10954 (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) && 10955 (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) && 10956 (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) { 10957 OSKextLog(/* kext */ NULL, 10958 kOSKextLogErrorLevel | 10959 kOSKextLogGeneralFlag, 10960 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX", 10961 __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top); 10962 } 10963 #endif 10964 segp->vmaddr = ml_static_unslide(segp->vmaddr); 10965 10966 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { 10967 secp->addr = ml_static_unslide(secp->addr); 10968 } 10969 } 10970 lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize); 10971 } 10972 result->setObject(kOSBundleMachOHeadersKey, headerData.get()); 10973 } 10974 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX 10975 10976 if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) { 10977 osLogDataHeaderRef *header; 10978 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])]; 10979 10980 void *os_log_data = NULL; 10981 void *cstring_data = NULL; 10982 void *asan_cstring_data = NULL; 10983 unsigned long os_log_size = 0; 10984 unsigned long cstring_size = 0; 10985 unsigned long asan_cstring_size = 0; 10986 uint32_t os_log_offset = 0; 10987 uint32_t cstring_offset = 0; 10988 uint32_t asan_cstring_offset = 0; 10989 bool res; 10990 10991 os_log_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size); 10992 os_log_offset = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr; 10993 cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size); 10994 cstring_offset = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr; 10995 asan_cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size); 10996 asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr; 10997 10998 header = (osLogDataHeaderRef *) headerBytes; 10999 header->version = OS_LOG_HDR_VERSION; 11000 header->sect_count = NUM_OS_LOG_SECTIONS; 11001 header->sections[OS_LOG_SECT_IDX].sect_offset = os_log_offset; 11002 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) os_log_size; 11003 header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset; 11004 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) cstring_size; 11005 header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset; 11006 header->sections[ASAN_CSTRING_SECT_IDX].sect_size = (uint32_t) asan_cstring_size; 11007 11008 11009 logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef))); 11010 if (!logData) { 11011 goto finish; 11012 } 11013 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0]))); 11014 if (!res) { 11015 goto finish; 11016 } 11017 if (os_log_data) { 11018 res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size); 11019 if (!res) { 11020 goto finish; 11021 } 11022 } 11023 if (cstring_data) { 11024 res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size); 11025 if (!res) { 11026 goto finish; 11027 } 11028 } 11029 if (asan_cstring_data) { 11030 res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size); 11031 if (!res) { 11032 goto finish; 11033 } 11034 } 11035 result->setObject(kOSBundleLogStringsKey, logData.get()); 11036 } 11037 11038 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) { 11039 cpuTypeNumber = OSNumber::withNumber( 11040 (uint64_t) kext_mach_hdr->cputype, 11041 8 * sizeof(kext_mach_hdr->cputype)); 11042 if (!cpuTypeNumber) { 11043 goto finish; 11044 } 11045 result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get()); 11046 } 11047 11048 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 11049 cpuSubtypeNumber = OSNumber::withNumber( 11050 (uint64_t) kext_mach_hdr->cpusubtype, 11051 8 * sizeof(kext_mach_hdr->cpusubtype)); 11052 if (!cpuSubtypeNumber) { 11053 goto finish; 11054 } 11055 result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get()); 11056 } 11057 } else { 11058 if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) { 11059 osLogDataHeaderRef *header; 11060 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])]; 11061 bool res; 11062 11063 header = (osLogDataHeaderRef *) headerBytes; 11064 header->version = OS_LOG_HDR_VERSION; 11065 header->sect_count = NUM_OS_LOG_SECTIONS; 11066 header->sections[OS_LOG_SECT_IDX].sect_offset = 0; 11067 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) 0; 11068 header->sections[CSTRING_SECT_IDX].sect_offset = 0; 11069 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) 0; 11070 header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0; 11071 header->sections[ASAN_CSTRING_SECT_IDX].sect_size = (uint32_t) 0; 11072 11073 logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef))); 11074 if (!logData) { 11075 goto finish; 11076 } 11077 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0]))); 11078 if (!res) { 11079 goto finish; 11080 } 11081 result->setObject(kOSBundleLogStringsKey, logData.get()); 11082 } 11083 } 11084 } 11085 11086 /* CFBundleIdentifier. We set this regardless because it's just stupid not to. 11087 */ 11088 result->setObject(kCFBundleIdentifierKey, bundleID.get()); 11089 11090 /* CFBundlePackageType 11091 */ 11092 bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL; 11093 if (bundleType) { 11094 result->setObject(kCFBundlePackageTypeKey, bundleType); 11095 } 11096 11097 /* CFBundleVersion. 11098 */ 11099 if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) { 11100 versionString = OSDynamicCast(OSString, 11101 getPropertyForHostArch(kCFBundleVersionKey)); 11102 if (versionString) { 11103 result->setObject(kCFBundleVersionKey, versionString); 11104 } 11105 } 11106 11107 /* OSBundleCompatibleVersion. 11108 */ 11109 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) { 11110 versionString = OSDynamicCast(OSString, 11111 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 11112 if (versionString) { 11113 result->setObject(kOSBundleCompatibleVersionKey, versionString); 11114 } 11115 } 11116 11117 /* Path. 11118 */ 11119 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) { 11120 if (path) { 11121 result->setObject(kOSBundlePathKey, path.get()); 11122 } 11123 } 11124 11125 11126 /* OSBundleExecutablePath. 11127 */ 11128 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) { 11129 if (path && executableRelPath) { 11130 uint32_t pathLength = path->getLength(); // gets incremented below 11131 11132 // +1 for slash, +1 for \0 11133 executablePathCStringSize = pathLength + executableRelPath->getLength() + 2; 11134 11135 executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize, 11136 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); // +1 for \0 11137 if (!executablePathCString) { 11138 goto finish; 11139 } 11140 strlcpy(executablePathCString, path->getCStringNoCopy(), 11141 executablePathCStringSize); 11142 executablePathCString[pathLength++] = '/'; 11143 executablePathCString[pathLength++] = '\0'; 11144 strlcat(executablePathCString, executableRelPath->getCStringNoCopy(), 11145 executablePathCStringSize); 11146 11147 executablePathString = OSString::withCString(executablePathCString); 11148 11149 if (!executablePathString) { 11150 goto finish; 11151 } 11152 11153 result->setObject(kOSBundleExecutablePathKey, executablePathString.get()); 11154 } else if (flags.builtin) { 11155 result->setObject(kOSBundleExecutablePathKey, bundleID.get()); 11156 } else if (isDriverKit()) { 11157 if (path) { 11158 // +1 for slash, +1 for \0 11159 uint32_t pathLength = path->getLength(); 11160 executablePathCStringSize = pathLength + 2; 11161 11162 executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize, 11163 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 11164 if (!executablePathCString) { 11165 goto finish; 11166 } 11167 strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize); 11168 executablePathCString[pathLength++] = '/'; 11169 executablePathCString[pathLength++] = '\0'; 11170 11171 executablePathString = OSString::withCString(executablePathCString); 11172 11173 if (!executablePathString) { 11174 goto finish; 11175 } 11176 11177 result->setObject(kOSBundleExecutablePathKey, executablePathString.get()); 11178 } 11179 } 11180 } 11181 11182 /* UUID, if the kext has one. 11183 */ 11184 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) { 11185 uuid = copyUUID(); 11186 if (uuid) { 11187 result->setObject(kOSBundleUUIDKey, uuid.get()); 11188 } 11189 } 11190 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) { 11191 uuid = copyTextUUID(); 11192 if (uuid) { 11193 result->setObject(kOSBundleTextUUIDKey, uuid.get()); 11194 } 11195 } 11196 11197 /* 11198 * Info.plist digest 11199 */ 11200 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) { 11201 OSData *digest; 11202 digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL; 11203 if (digest) { 11204 result->setObject(kOSKextInfoPlistDigestKey, digest); 11205 } 11206 } 11207 11208 /* 11209 * Collection type 11210 */ 11211 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) { 11212 result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString())); 11213 } 11214 11215 /* 11216 * Collection availability 11217 */ 11218 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) { 11219 result->setObject(kOSKextAuxKCAvailabilityKey, 11220 isLoadable() ? kOSBooleanTrue : kOSBooleanFalse); 11221 } 11222 11223 /* 11224 * Allows user load 11225 */ 11226 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) { 11227 OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey)); 11228 if (allowUserLoad) { 11229 result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad); 11230 } 11231 } 11232 11233 /* 11234 * Bundle Dependencies (OSBundleLibraries) 11235 */ 11236 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) { 11237 OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey)); 11238 if (libraries) { 11239 result->setObject(kOSBundleLibrariesKey, libraries); 11240 } 11241 } 11242 11243 /***** 11244 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted. 11245 */ 11246 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) { 11247 result->setObject(kOSKernelResourceKey, 11248 isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse); 11249 } 11250 11251 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) { 11252 result->setObject(kOSBundleIsInterfaceKey, 11253 isInterface() ? kOSBooleanTrue : kOSBooleanFalse); 11254 } 11255 11256 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) { 11257 result->setObject(kOSBundlePrelinkedKey, 11258 isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse); 11259 } 11260 11261 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) { 11262 result->setObject(kOSBundleStartedKey, 11263 isStarted() ? kOSBooleanTrue : kOSBooleanFalse); 11264 } 11265 11266 /* LoadTag (Index). 11267 */ 11268 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) { 11269 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag, 11270 /* numBits */ 8 * sizeof(loadTag)); 11271 if (!scratchNumber) { 11272 goto finish; 11273 } 11274 result->setObject(kOSBundleLoadTagKey, scratchNumber.get()); 11275 } 11276 11277 /* LoadAddress, LoadSize. 11278 */ 11279 if (!infoKeys || 11280 _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) || 11281 _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) || 11282 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) || 11283 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) || 11284 _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 11285 bool is_dext = isDriverKit(); 11286 if (isInterface() || flags.builtin || linkedExecutable || is_dext) { 11287 /* These go to userspace via serialization, so we don't want any doubts 11288 * about their size. 11289 */ 11290 uint64_t loadAddress = 0; 11291 uint32_t loadSize = 0; 11292 uint32_t wiredSize = 0; 11293 uint64_t execLoadAddress = 0; 11294 uint32_t execLoadSize = 0; 11295 11296 /* Interfaces always report 0 load address & size. 11297 * Just the way they roll. 11298 * 11299 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp 11300 * xxx - shouldn't have one! 11301 */ 11302 11303 if (flags.builtin || linkedExecutable) { 11304 kernel_mach_header_t *mh = NULL; 11305 kernel_segment_command_t *seg = NULL; 11306 11307 if (flags.builtin) { 11308 loadAddress = kmod_info->address; 11309 loadSize = (uint32_t)kmod_info->size; 11310 } else { 11311 loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy(); 11312 loadSize = linkedExecutable->getLength(); 11313 } 11314 mh = (kernel_mach_header_t *)loadAddress; 11315 loadAddress = ml_static_unslide(loadAddress); 11316 11317 /* Walk through the kext, looking for the first executable 11318 * segment in case we were asked for its size/address. 11319 */ 11320 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 11321 if (seg->initprot & VM_PROT_EXECUTE) { 11322 execLoadAddress = ml_static_unslide(seg->vmaddr); 11323 execLoadSize = (uint32_t)seg->vmsize; 11324 break; 11325 } 11326 } 11327 11328 /* If we have a kmod_info struct, calculated the wired size 11329 * from that. Otherwise it's the full load size. 11330 */ 11331 if (kmod_info) { 11332 wiredSize = loadSize - (uint32_t)kmod_info->hdr_size; 11333 } else { 11334 wiredSize = loadSize; 11335 } 11336 } else if (is_dext) { 11337 /* 11338 * DriverKit userspace executables do not have a kernel linkedExecutable, 11339 * so we "fake" their address range with the LoadTag. 11340 */ 11341 if (loadTag) { 11342 loadAddress = execLoadAddress = loadTag; 11343 loadSize = execLoadSize = 1; 11344 } 11345 } 11346 11347 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) { 11348 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11349 (unsigned long long)(loadAddress), 11350 /* numBits */ 8 * sizeof(loadAddress)); 11351 if (!scratchNumber) { 11352 goto finish; 11353 } 11354 result->setObject(kOSBundleLoadAddressKey, scratchNumber.get()); 11355 } 11356 if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) { 11357 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey)) 11358 && loadAddress && loadSize) { 11359 void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary); 11360 if (!baseAddress) { 11361 goto finish; 11362 } 11363 11364 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11365 (unsigned long long)ml_static_unslide((vm_offset_t)baseAddress), 11366 /* numBits */ 8 * sizeof(loadAddress)); 11367 if (!scratchNumber) { 11368 goto finish; 11369 } 11370 result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get()); 11371 } 11372 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey)) 11373 && (this == sKernelKext) && gBuiltinKmodsCount) { 11374 result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue); 11375 } 11376 } 11377 11378 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) { 11379 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11380 (unsigned long long)(execLoadAddress), 11381 /* numBits */ 8 * sizeof(execLoadAddress)); 11382 if (!scratchNumber) { 11383 goto finish; 11384 } 11385 result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get()); 11386 } 11387 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) { 11388 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11389 (unsigned long long)(loadSize), 11390 /* numBits */ 8 * sizeof(loadSize)); 11391 if (!scratchNumber) { 11392 goto finish; 11393 } 11394 result->setObject(kOSBundleLoadSizeKey, scratchNumber.get()); 11395 } 11396 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) { 11397 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11398 (unsigned long long)(execLoadSize), 11399 /* numBits */ 8 * sizeof(execLoadSize)); 11400 if (!scratchNumber) { 11401 goto finish; 11402 } 11403 result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get()); 11404 } 11405 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 11406 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11407 (unsigned long long)(wiredSize), 11408 /* numBits */ 8 * sizeof(wiredSize)); 11409 if (!scratchNumber) { 11410 goto finish; 11411 } 11412 result->setObject(kOSBundleWiredSizeKey, scratchNumber.get()); 11413 } 11414 } 11415 } 11416 11417 /* OSBundleDependencies. In descending order for 11418 * easy compatibility with kextstat(8). 11419 */ 11420 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) { 11421 if ((count = getNumDependencies())) { 11422 dependencyLoadTags = OSArray::withCapacity(count); 11423 result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get()); 11424 11425 i = count - 1; 11426 do { 11427 OSKext * dependency = OSDynamicCast(OSKext, 11428 dependencies->getObject(i)); 11429 11430 if (!dependency) { 11431 continue; 11432 } 11433 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11434 (unsigned long long)dependency->getLoadTag(), 11435 /* numBits*/ 8 * sizeof(loadTag)); 11436 if (!scratchNumber) { 11437 goto finish; 11438 } 11439 dependencyLoadTags->setObject(scratchNumber.get()); 11440 } while (i--); 11441 } 11442 } 11443 11444 /* OSBundleMetaClasses. 11445 */ 11446 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) { 11447 if (metaClasses && metaClasses->getCount()) { 11448 metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get()); 11449 metaClassInfo = OSArray::withCapacity(metaClasses->getCount()); 11450 if (!metaClassIterator || !metaClassInfo) { 11451 goto finish; 11452 } 11453 result->setObject(kOSBundleClassesKey, metaClassInfo.get()); 11454 11455 while ((thisMetaClass = OSDynamicCast(OSMetaClass, 11456 metaClassIterator->getNextObject()))) { 11457 metaClassDict = OSDictionary::withCapacity(3); 11458 if (!metaClassDict) { 11459 goto finish; 11460 } 11461 11462 metaClassName = OSString::withCString(thisMetaClass->getClassName()); 11463 if (thisMetaClass->getSuperClass()) { 11464 superclassName = OSString::withCString( 11465 thisMetaClass->getSuperClass()->getClassName()); 11466 } 11467 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(), 11468 8 * sizeof(unsigned int)); 11469 11470 /* Bail if any of the essentials is missing. The root class lacks a superclass, 11471 * of course. 11472 */ 11473 if (!metaClassDict || !metaClassName || !scratchNumber) { 11474 goto finish; 11475 } 11476 11477 metaClassInfo->setObject(metaClassDict.get()); 11478 metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get()); 11479 if (superclassName) { 11480 metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get()); 11481 } 11482 metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get()); 11483 } 11484 } 11485 } 11486 11487 /* OSBundleRetainCount. 11488 */ 11489 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) { 11490 { 11491 int kextRetainCount = getRetainCount() - 1; 11492 if (isLoaded()) { 11493 kextRetainCount--; 11494 } 11495 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11496 (int)kextRetainCount, 11497 /* numBits*/ 8 * sizeof(int)); 11498 if (scratchNumber) { 11499 result->setObject(kOSBundleRetainCountKey, scratchNumber.get()); 11500 } 11501 } 11502 } 11503 11504 success = true; 11505 11506 finish: 11507 if (executablePathCString) { 11508 kfree_data(executablePathCString, executablePathCStringSize); 11509 } 11510 if (!success) { 11511 result.reset(); 11512 } 11513 return result; 11514 } 11515 11516 /********************************************************************* 11517 *********************************************************************/ 11518 /* static */ 11519 bool 11520 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize) 11521 { 11522 bool ok; 11523 OSSharedPtr<OSKext> kext; 11524 11525 IORecursiveLockLock(sKextLock); 11526 kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain); 11527 IORecursiveLockUnlock(sKextLock); 11528 11529 if (!kext || !kext->path || !kext->userExecutableRelPath) { 11530 return false; 11531 } 11532 snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s", 11533 kext->path->getCStringNoCopy(), 11534 kext->userExecutableRelPath->getCStringNoCopy()); 11535 ok = true; 11536 11537 return ok; 11538 } 11539 11540 /********************************************************************* 11541 *********************************************************************/ 11542 /* static */ 11543 OSReturn 11544 OSKext::requestResource( 11545 const char * kextIdentifierCString, 11546 const char * resourceNameCString, 11547 OSKextRequestResourceCallback callback, 11548 void * context, 11549 OSKextRequestTag * requestTagOut) 11550 { 11551 OSReturn result = kOSReturnError; 11552 OSSharedPtr<OSKext> callbackKext; // looked up 11553 11554 OSKextRequestTag requestTag = -1; 11555 OSSharedPtr<OSNumber> requestTagNum; 11556 OSSharedPtr<OSDictionary> requestDict; 11557 OSSharedPtr<OSString> kextIdentifier; 11558 OSSharedPtr<OSString> resourceName; 11559 11560 OSSharedPtr<OSDictionary> callbackRecord; 11561 OSSharedPtr<OSData> callbackWrapper; 11562 11563 OSSharedPtr<OSData> contextWrapper; 11564 11565 IORecursiveLockLock(sKextLock); 11566 11567 if (requestTagOut) { 11568 *requestTagOut = kOSKextRequestTagInvalid; 11569 } 11570 11571 /* If requests to user space are disabled, don't go any further */ 11572 if (!sKernelRequestsEnabled) { 11573 OSKextLog(/* kext */ NULL, 11574 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 11575 "Can't request resource %s for %s - requests to user space are disabled.", 11576 resourceNameCString, 11577 kextIdentifierCString); 11578 result = kOSKextReturnDisabled; 11579 goto finish; 11580 } 11581 11582 if (!kextIdentifierCString || !resourceNameCString || !callback) { 11583 result = kOSKextReturnInvalidArgument; 11584 goto finish; 11585 } 11586 11587 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 11588 if (!callbackKext) { 11589 OSKextLog(/* kext */ NULL, 11590 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 11591 "Resource request has bad callback address."); 11592 result = kOSKextReturnInvalidArgument; 11593 goto finish; 11594 } 11595 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 11596 OSKextLog(/* kext */ NULL, 11597 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 11598 "Resource request callback is in a kext that is not started."); 11599 result = kOSKextReturnInvalidArgument; 11600 goto finish; 11601 } 11602 11603 /* Do not allow any new requests to be made on a kext that is unloading. 11604 */ 11605 if (callbackKext->flags.stopping) { 11606 result = kOSKextReturnStopping; 11607 goto finish; 11608 } 11609 11610 /* If we're wrapped the next available request tag around to the negative 11611 * numbers, we can't service any more requests. 11612 */ 11613 if (sNextRequestTag == kOSKextRequestTagInvalid) { 11614 OSKextLog(/* kext */ NULL, 11615 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 11616 "No more request tags available; restart required."); 11617 result = kOSKextReturnNoResources; 11618 goto finish; 11619 } 11620 requestTag = sNextRequestTag++; 11621 11622 result = _OSKextCreateRequest(kKextRequestPredicateRequestResource, 11623 requestDict); 11624 if (result != kOSReturnSuccess) { 11625 goto finish; 11626 } 11627 11628 kextIdentifier = OSString::withCString(kextIdentifierCString); 11629 resourceName = OSString::withCString(resourceNameCString); 11630 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 11631 8 * sizeof(requestTag)); 11632 if (!kextIdentifier || 11633 !resourceName || 11634 !requestTagNum || 11635 !_OSKextSetRequestArgument(requestDict.get(), 11636 kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) || 11637 !_OSKextSetRequestArgument(requestDict.get(), 11638 kKextRequestArgumentNameKey, resourceName.get()) || 11639 !_OSKextSetRequestArgument(requestDict.get(), 11640 kKextRequestArgumentRequestTagKey, requestTagNum.get())) { 11641 result = kOSKextReturnNoMemory; 11642 goto finish; 11643 } 11644 11645 callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection()); 11646 if (!callbackRecord) { 11647 result = kOSKextReturnNoMemory; 11648 goto finish; 11649 } 11650 // we validate callback address at call time 11651 callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *)); 11652 if (context) { 11653 contextWrapper = OSData::withBytes((void *)&context, sizeof(void *)); 11654 } 11655 if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(), 11656 kKextRequestArgumentCallbackKey, callbackWrapper.get())) { 11657 result = kOSKextReturnNoMemory; 11658 goto finish; 11659 } 11660 11661 if (context) { 11662 if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(), 11663 kKextRequestArgumentContextKey, contextWrapper.get())) { 11664 result = kOSKextReturnNoMemory; 11665 goto finish; 11666 } 11667 } 11668 11669 /* Only post the requests after all the other potential failure points 11670 * have been passed. 11671 */ 11672 if (!sKernelRequests->setObject(requestDict.get()) || 11673 !sRequestCallbackRecords->setObject(callbackRecord.get())) { 11674 result = kOSKextReturnNoMemory; 11675 goto finish; 11676 } 11677 11678 OSKext::pingIOKitDaemon(); 11679 11680 result = kOSReturnSuccess; 11681 if (requestTagOut) { 11682 *requestTagOut = requestTag; 11683 } 11684 11685 finish: 11686 11687 /* If we didn't succeed, yank the request & callback 11688 * from their holding arrays. 11689 */ 11690 if (result != kOSReturnSuccess) { 11691 unsigned int index; 11692 11693 index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0); 11694 if (index != (unsigned int)-1) { 11695 sKernelRequests->removeObject(index); 11696 } 11697 index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0); 11698 if (index != (unsigned int)-1) { 11699 sRequestCallbackRecords->removeObject(index); 11700 } 11701 } 11702 11703 OSKext::considerUnloads(/* rescheduleOnly? */ true); 11704 11705 IORecursiveLockUnlock(sKextLock); 11706 11707 return result; 11708 } 11709 11710 OSReturn 11711 OSKext::requestDaemonLaunch( 11712 OSString *kextIdentifier, 11713 OSString *serverName, 11714 OSNumber *serverTag, 11715 IOUserServerCheckInToken * checkInToken) 11716 { 11717 OSReturn result = kOSReturnError; 11718 OSSharedPtr<OSDictionary> requestDict; 11719 11720 if (!kextIdentifier || !serverName || !serverTag || !checkInToken) { 11721 return kOSKextReturnInvalidArgument; 11722 } 11723 11724 IORecursiveLockLock(sKextLock); 11725 11726 OSKextLog(/* kext */ NULL, 11727 kOSKextLogDebugLevel | 11728 kOSKextLogGeneralFlag, 11729 "Requesting daemon launch for %s with serverName %s and tag %llu", 11730 kextIdentifier->getCStringNoCopy(), 11731 serverName->getCStringNoCopy(), 11732 serverTag->unsigned64BitValue() 11733 ); 11734 11735 result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict); 11736 if (result != kOSReturnSuccess) { 11737 goto finish; 11738 } 11739 11740 if (!_OSKextSetRequestArgument(requestDict.get(), 11741 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) || 11742 !_OSKextSetRequestArgument(requestDict.get(), 11743 kKextRequestArgumentDriverExtensionServerName, serverName) || 11744 !_OSKextSetRequestArgument(requestDict.get(), 11745 kKextRequestArgumentDriverExtensionServerTag, serverTag) || 11746 !_OSKextSetRequestArgument(requestDict.get(), 11747 kKextRequestArgumentCheckInToken, checkInToken)) { 11748 result = kOSKextReturnNoMemory; 11749 goto finish; 11750 } 11751 11752 /* Only post the requests after all the other potential failure points 11753 * have been passed. 11754 */ 11755 if (!sKernelRequests->setObject(requestDict.get())) { 11756 result = kOSKextReturnNoMemory; 11757 goto finish; 11758 } 11759 OSKext::pingIOKitDaemon(); 11760 11761 result = kOSReturnSuccess; 11762 finish: 11763 IORecursiveLockUnlock(sKextLock); 11764 return result; 11765 } 11766 11767 /********************************************************************* 11768 * Assumes sKextLock is held. 11769 *********************************************************************/ 11770 /* static */ 11771 OSReturn 11772 OSKext::dequeueCallbackForRequestTag( 11773 OSKextRequestTag requestTag, 11774 OSSharedPtr<OSDictionary> &callbackRecordOut) 11775 { 11776 OSDictionary * callbackRecordOutRaw = NULL; 11777 OSReturn result; 11778 11779 result = dequeueCallbackForRequestTag(requestTag, 11780 &callbackRecordOutRaw); 11781 11782 if (kOSReturnSuccess == result) { 11783 callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain); 11784 } 11785 11786 return result; 11787 } 11788 OSReturn 11789 OSKext::dequeueCallbackForRequestTag( 11790 OSKextRequestTag requestTag, 11791 OSDictionary ** callbackRecordOut) 11792 { 11793 OSReturn result = kOSReturnError; 11794 OSSharedPtr<OSNumber> requestTagNum; 11795 11796 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 11797 8 * sizeof(requestTag)); 11798 if (!requestTagNum) { 11799 goto finish; 11800 } 11801 11802 result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(), 11803 callbackRecordOut); 11804 11805 finish: 11806 return result; 11807 } 11808 11809 /********************************************************************* 11810 * Assumes sKextLock is held. 11811 *********************************************************************/ 11812 /* static */ 11813 OSReturn 11814 OSKext::dequeueCallbackForRequestTag( 11815 OSNumber * requestTagNum, 11816 OSSharedPtr<OSDictionary> &callbackRecordOut) 11817 { 11818 OSDictionary * callbackRecordOutRaw = NULL; 11819 OSReturn result; 11820 11821 result = dequeueCallbackForRequestTag(requestTagNum, 11822 &callbackRecordOutRaw); 11823 11824 if (kOSReturnSuccess == result) { 11825 callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain); 11826 } 11827 11828 return result; 11829 } 11830 OSReturn 11831 OSKext::dequeueCallbackForRequestTag( 11832 OSNumber * requestTagNum, 11833 OSDictionary ** callbackRecordOut) 11834 { 11835 OSReturn result = kOSKextReturnInvalidArgument; 11836 OSDictionary * callbackRecord = NULL; // retain if matched! 11837 OSNumber * callbackTagNum = NULL; // do not release 11838 unsigned int count, i; 11839 11840 result = kOSReturnError; 11841 count = sRequestCallbackRecords->getCount(); 11842 for (i = 0; i < count; i++) { 11843 callbackRecord = OSDynamicCast(OSDictionary, 11844 sRequestCallbackRecords->getObject(i)); 11845 if (!callbackRecord) { 11846 goto finish; 11847 } 11848 11849 /* If we don't find a tag, we basically have a leak here. Maybe 11850 * we should just remove it. 11851 */ 11852 callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument( 11853 callbackRecord, kKextRequestArgumentRequestTagKey)); 11854 if (!callbackTagNum) { 11855 goto finish; 11856 } 11857 11858 /* We could be even more paranoid and check that all the incoming 11859 * args match what's in the callback record. 11860 */ 11861 if (callbackTagNum->isEqualTo(requestTagNum)) { 11862 if (callbackRecordOut) { 11863 *callbackRecordOut = callbackRecord; 11864 callbackRecord->retain(); 11865 } 11866 sRequestCallbackRecords->removeObject(i); 11867 result = kOSReturnSuccess; 11868 goto finish; 11869 } 11870 } 11871 result = kOSKextReturnNotFound; 11872 11873 finish: 11874 return result; 11875 } 11876 11877 11878 /********************************************************************* 11879 * Busy timeout triage 11880 *********************************************************************/ 11881 /* static */ 11882 bool 11883 OSKext::pendingIOKitDaemonRequests(void) 11884 { 11885 return sRequestCallbackRecords && sRequestCallbackRecords->getCount(); 11886 } 11887 11888 extern "C" int vm_enable_driverkit_shared_region; 11889 11890 /********************************************************************* 11891 * Acquires and releases sKextLock 11892 * 11893 * This function is designed to be called exactly once on boot by 11894 * the IOKit management daemon, kernelmanagerd. It gathers all codeless 11895 * kext and dext personalities, and then attempts to map a System 11896 * (pageable) KC and an Auxiliary (aux) KC. 11897 * 11898 * Even if the pageable or aux KC fail to load - this function will 11899 * not allow a second call. This avoids security issues where 11900 * kernelmanagerd has been compromised or the pageable kc has been 11901 * tampered with and the attacker attempts to re-load a malicious 11902 * variant. 11903 * 11904 * Return: if a KC fails to load the return value will contain: 11905 * kOSKextReturnKCLoadFailure. If the pageable KC fails, 11906 * the return value will contain kOSKextReturnKCLoadFailureSystemKC. 11907 * Similarly, if the aux kc load fails, the return value will 11908 * contain kOSKextReturnKCLoadFailureAuxKC. The two values 11909 * compose with each other and with kOSKextReturnKCLoadFailure. 11910 *********************************************************************/ 11911 /* static */ 11912 OSReturn 11913 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused) 11914 { 11915 static bool daemon_ready = false; 11916 11917 OSReturn ret = kOSKextReturnInvalidArgument; 11918 OSReturn kcerr = 0; 11919 bool start_matching = false; 11920 11921 bool allow_fileset_load = !daemon_ready; 11922 #if !(defined(__x86_64__) || defined(__i386__)) 11923 /* never allow KCs full of kexts on non-x86 machines */ 11924 allow_fileset_load = false; 11925 #endif 11926 11927 /* 11928 * Change with 70582300 11929 */ 11930 #if 0 || !defined(VM_MAPPED_KEXTS) 11931 /* 11932 * On platforms that don't support the SystemKC or a file-backed 11933 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter 11934 * needs to be queried before we load any codeless kexts or release 11935 * any 3rd party kexts to run. On platforms that support a file-backed 11936 * AuxKC, this process is done via the kext audit mechanism. 11937 */ 11938 11939 printf("KextLog: waiting for kext receipt to be queried.\n"); 11940 while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) { 11941 IOSleep(30); 11942 } 11943 #endif /* !VM_MAPPED_KEXTS */ 11944 11945 /* 11946 * Get the args from the request. Right now we need the file 11947 * name for the pageable and the aux kext collection file sets. 11948 */ 11949 OSDictionary * requestArgs = NULL; // do not release 11950 OSString * pageable_filepath = NULL; // do not release 11951 OSString * aux_filepath = NULL; // do not release 11952 OSArray * codeless_kexts = NULL; // do not release 11953 OSNumber * enable_dk_shared_region = NULL; // do not release 11954 11955 kernel_mach_header_t *akc_mh = NULL; 11956 11957 requestArgs = OSDynamicCast(OSDictionary, 11958 requestDict->getObject(kKextRequestArgumentsKey)); 11959 11960 if (requestArgs == NULL) { 11961 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 11962 "KextLog: No arguments in plist for loading fileset kext\n"); 11963 printf("KextLog: No arguments in plist for loading fileset kext\n"); 11964 return ret; 11965 } 11966 11967 ret = kOSKextReturnDisabled; 11968 11969 IORecursiveLockLock(sKextLock); 11970 11971 if (!sLoadEnabled) { 11972 OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag, 11973 "KextLog: Kext loading is disabled (attempt to load KCs)."); 11974 IORecursiveLockUnlock(sKextLock); 11975 return ret; 11976 } 11977 11978 pageable_filepath = OSDynamicCast(OSString, 11979 requestArgs->getObject(kKextRequestArgumentPageableKCFilename)); 11980 11981 if (allow_fileset_load && pageable_filepath != NULL) { 11982 printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy()); 11983 11984 ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable); 11985 if (ret) { 11986 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 11987 "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret); 11988 11989 printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret); 11990 ret = kOSKextReturnKCLoadFailure; 11991 kcerr |= kOSKextReturnKCLoadFailureSystemKC; 11992 goto try_auxkc; 11993 } 11994 /* 11995 * Even if the AuxKC fails to load, we still want to send 11996 * the System KC personalities to the catalog for matching 11997 */ 11998 start_matching = true; 11999 } else if (pageable_filepath != NULL) { 12000 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 12001 "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy()); 12002 ret = kOSKextReturnUnsupported; 12003 } 12004 12005 try_auxkc: 12006 akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary); 12007 if (akc_mh) { 12008 /* 12009 * If we try to load a deferred AuxKC, then don't ever attempt 12010 * a filesystem map of a file 12011 */ 12012 allow_fileset_load = false; 12013 12014 /* 12015 * This function is only called once per boot, so we haven't 12016 * yet loaded an AuxKC. If we have registered the AuxKC mach 12017 * header, that means that the kext collection has been placed 12018 * in memory for us by the booter, and is waiting for us to 12019 * process it. Grab the deferred XML plist of info 12020 * dictionaries and add all the kexts. 12021 */ 12022 OSSharedPtr<OSObject> parsedXML; 12023 OSSharedPtr<OSData> loaded_kcUUID; 12024 OSDictionary *infoDict; 12025 parsedXML = consumeDeferredKextCollection(KCKindAuxiliary); 12026 infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 12027 #if !defined(VM_MAPPED_KEXTS) 12028 /* 12029 * On platforms where we don't dynamically wire-down / page-in 12030 * kext memory, we need to maintain the invariant that if the 12031 * AuxKC in memory does not contain a kext receipt, then we 12032 * should not load any of the kexts. 12033 */ 12034 size_t receipt_sz = 0; 12035 if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) { 12036 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12037 "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt"); 12038 ret = kOSKextReturnKCLoadFailure; 12039 goto try_codeless; 12040 } 12041 #endif 12042 if (infoDict) { 12043 bool added; 12044 printf("KextLog: Adding kexts from in-memory AuxKC\n"); 12045 added = OSKext::addKextsFromKextCollection(akc_mh, infoDict, 12046 kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary); 12047 if (!loaded_kcUUID) { 12048 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12049 "KextLog: WARNING: did not find UUID in deferred Aux KC!"); 12050 } else if (!added) { 12051 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12052 "KextLog: WARNING: Failed to load AuxKC from memory."); 12053 } 12054 /* only return success if the pageable load (above) was successful */ 12055 if (ret != kOSKextReturnKCLoadFailure) { 12056 ret = kOSReturnSuccess; 12057 } 12058 /* the registration of the AuxKC parsed out the KC's UUID already */ 12059 } else { 12060 if (daemon_ready) { 12061 /* 12062 * Complain, but don't return an error if this isn't the first time the 12063 * IOKit daemon is checking in. If the daemon ever restarts, we will 12064 * hit this case because we've already consumed the deferred personalities. 12065 * We return success here so that a call to this function from a restarted 12066 * daemon with no codeless kexts will succeed. 12067 */ 12068 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 12069 "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart"); 12070 if (ret != kOSKextReturnKCLoadFailure) { 12071 ret = kOSReturnSuccess; 12072 } 12073 } else { 12074 /* this is a real error case */ 12075 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12076 "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary"); 12077 printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n"); 12078 ret = kOSKextReturnKCLoadFailure; 12079 kcerr |= kOSKextReturnKCLoadFailureAuxKC; 12080 } 12081 } 12082 } 12083 12084 aux_filepath = OSDynamicCast(OSString, 12085 requestArgs->getObject(kKextRequestArgumentAuxKCFilename)); 12086 if (allow_fileset_load && aux_filepath != NULL) { 12087 printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy()); 12088 12089 ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary); 12090 if (ret) { 12091 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12092 "KextLog: loadKCFileSet for Aux KC returned %d\n", ret); 12093 12094 printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret); 12095 ret = kOSKextReturnKCLoadFailure; 12096 kcerr |= kOSKextReturnKCLoadFailureAuxKC; 12097 goto try_codeless; 12098 } 12099 start_matching = true; 12100 } else if (aux_filepath != NULL) { 12101 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 12102 "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy()); 12103 if (ret != kOSKextReturnKCLoadFailure) { 12104 ret = kOSKextReturnUnsupported; 12105 } 12106 } 12107 12108 try_codeless: 12109 /* 12110 * Load codeless kexts last so that there is no possibilty of a 12111 * codeless kext bundle ID preventing a kext in the system KC from 12112 * loading 12113 */ 12114 codeless_kexts = OSDynamicCast(OSArray, 12115 requestArgs->getObject(kKextRequestArgumentCodelessPersonalities)); 12116 if (codeless_kexts != NULL) { 12117 uint32_t count = codeless_kexts->getCount(); 12118 OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12119 "KextLog: loading %d codeless kexts/dexts", count); 12120 for (uint32_t i = 0; i < count; i++) { 12121 OSDictionary *infoDict; 12122 infoDict = OSDynamicCast(OSDictionary, 12123 codeless_kexts->getObject(i)); 12124 if (!infoDict) { 12125 continue; 12126 } 12127 // instantiate a new kext, and don't hold a reference 12128 // (the kext subsystem will hold one implicitly) 12129 OSKext::withCodelessInfo(infoDict); 12130 } 12131 /* ignore errors that are not KC load failures */ 12132 if (ret != kOSKextReturnKCLoadFailure) { 12133 ret = kOSReturnSuccess; 12134 } 12135 start_matching = true; 12136 } 12137 12138 enable_dk_shared_region = OSDynamicCast(OSNumber, 12139 requestArgs->getObject(kKextRequestEnableDriverKitSharedRegionKey)); 12140 if (enable_dk_shared_region != NULL && enable_dk_shared_region->unsigned64BitValue() == 1) { 12141 OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12142 "KextLog: Enabling DriverKit shared region."); 12143 vm_enable_driverkit_shared_region = 1; 12144 } 12145 12146 /* send personalities to the IOCatalog once */ 12147 if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) { 12148 OSKext::sendAllKextPersonalitiesToCatalog(true); 12149 /* 12150 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark 12151 * things as active and start all the delayed matching: the 12152 * dext and codeless kext personalities should have all been 12153 * delivered via this one call. 12154 */ 12155 if (!daemon_ready) { 12156 OSKext::setIOKitDaemonActive(); 12157 OSKext::setDeferredLoadSucceeded(TRUE); 12158 IOService::iokitDaemonLaunched(); 12159 } 12160 if (sOSKextWasResetAfterUserspaceReboot) { 12161 sOSKextWasResetAfterUserspaceReboot = false; 12162 OSKext::setIOKitDaemonActive(); 12163 IOService::startDeferredMatches(); 12164 } 12165 } 12166 12167 if (ret == kOSKextReturnKCLoadFailure) { 12168 ret |= kcerr; 12169 } 12170 12171 /* 12172 * Only allow this function to attempt to load the pageable and 12173 * aux KCs once per boot. 12174 */ 12175 daemon_ready = true; 12176 12177 IORecursiveLockUnlock(sKextLock); 12178 12179 return ret; 12180 } 12181 12182 OSReturn 12183 OSKext::resetMutableSegments(void) 12184 { 12185 kernel_segment_command_t *seg = NULL; 12186 kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address; 12187 u_int index = 0; 12188 OSKextSavedMutableSegment *savedSegment = NULL; 12189 uintptr_t kext_slide = PE_get_kc_slide(kc_type); 12190 OSReturn err; 12191 12192 if (!savedMutableSegments) { 12193 OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag, 12194 "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString()); 12195 err = kOSKextReturnInternalError; 12196 goto finish; 12197 } 12198 12199 for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) { 12200 if (!segmentIsMutable(seg)) { 12201 continue; 12202 } 12203 uint64_t unslid_vmaddr = seg->vmaddr - kext_slide; 12204 uint64_t vmsize = seg->vmsize; 12205 err = kOSKextReturnInternalError; 12206 for (index = 0; index < savedMutableSegments->getCount(); index++) { 12207 savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index)); 12208 assert(savedSegment); 12209 if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) { 12210 OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag, 12211 "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1); 12212 err = savedSegment->restoreContents(seg); 12213 if (err != kOSReturnSuccess) { 12214 panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 12215 } 12216 } 12217 } 12218 if (err != kOSReturnSuccess) { 12219 panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 12220 } 12221 } 12222 err = kOSReturnSuccess; 12223 finish: 12224 return err; 12225 } 12226 12227 12228 /********************************************************************* 12229 * Assumes sKextLock is held. 12230 *********************************************************************/ 12231 /* static */ 12232 OSReturn 12233 OSKext::loadKCFileSet( 12234 const char *filepath, 12235 kc_kind_t type) 12236 { 12237 #if VM_MAPPED_KEXTS 12238 /* we only need to load filesets on systems that support VM_MAPPED kexts */ 12239 OSReturn err; 12240 struct vnode *vp = NULL; 12241 void *fileset_control; 12242 off_t fsize; 12243 bool pageable = (type == KCKindPageable); 12244 12245 if ((pageable && pageableKCloaded) || 12246 (!pageable && auxKCloaded)) { 12247 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12248 "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux")); 12249 12250 return kOSKextReturnInvalidArgument; 12251 } 12252 12253 /* Do not allow AuxKC to load if Pageable KC is not loaded */ 12254 if (!pageable && !pageableKCloaded) { 12255 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12256 "Trying to load the Aux KC without loading the Pageable KC"); 12257 return kOSKextReturnInvalidArgument; 12258 } 12259 12260 fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize); 12261 12262 if (fileset_control == NULL) { 12263 printf("Could not get memory control object for file %s", filepath); 12264 12265 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12266 "Could not get memory control object for file %s", filepath); 12267 return kOSKextReturnInvalidArgument; 12268 } 12269 if (vp == NULL) { 12270 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12271 "Could not find vnode for file %s", filepath); 12272 return kOSKextReturnInvalidArgument; 12273 } 12274 12275 kernel_mach_header_t *mh = NULL; 12276 uintptr_t slide = 0; 12277 12278 #if CONFIG_CSR 12279 /* 12280 * When SIP is enabled, the KC we map must be SIP-protected 12281 */ 12282 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) { 12283 struct vnode_attr va; 12284 int error; 12285 VATTR_INIT(&va); 12286 VATTR_WANTED(&va, va_flags); 12287 error = vnode_getattr(vp, &va, vfs_context_current()); 12288 if (error) { 12289 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12290 "vnode_getattr(%s) failed (error=%d)", filepath, error); 12291 err = kOSKextReturnInternalError; 12292 goto finish; 12293 } 12294 if (!(va.va_flags & SF_RESTRICTED)) { 12295 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12296 "Path to KC '%s' is not SIP-protected", filepath); 12297 err = kOSKextReturnInvalidArgument; 12298 goto finish; 12299 } 12300 } 12301 #endif 12302 12303 err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL); 12304 if (err) { 12305 printf("KextLog: mapKCFileSet returned %d\n", err); 12306 12307 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12308 "mapKCFileSet returned %d\n", err); 12309 12310 err = kOSKextReturnInvalidArgument; 12311 } 12312 12313 #if CONFIG_CSR 12314 finish: 12315 #endif 12316 /* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */ 12317 assert(vp != NULL); 12318 if (err == kOSReturnSuccess) { 12319 PE_set_kc_vp(type, vp); 12320 if (pageable) { 12321 pageableKCloaded = true; 12322 } else { 12323 auxKCloaded = true; 12324 } 12325 } else { 12326 vnode_put(vp); 12327 } 12328 12329 return err; 12330 #else 12331 (void)filepath; 12332 (void)type; 12333 return kOSKextReturnUnsupported; 12334 #endif // VM_MAPPED_KEXTS 12335 } 12336 12337 #if defined(__x86_64__) || defined(__i386__) 12338 /********************************************************************* 12339 * Assumes sKextLock is held. 12340 *********************************************************************/ 12341 /* static */ 12342 OSReturn 12343 OSKext::mapKCFileSet( 12344 void *control, 12345 vm_size_t fsize, 12346 kernel_mach_header_t **mhp, 12347 off_t file_offset, 12348 uintptr_t *slidep, 12349 bool pageable, 12350 void *map_entry_list) 12351 { 12352 bool fileset_load = false; 12353 kern_return_t ret; 12354 OSReturn err; 12355 kernel_section_t *infoPlistSection = NULL; 12356 OSDictionary *infoDict = NULL; 12357 12358 OSSharedPtr<OSObject> parsedXML; 12359 OSSharedPtr<OSString> errorString; 12360 OSSharedPtr<OSData> loaded_kcUUID; 12361 12362 /* Check if initial load for file set */ 12363 if (*mhp == NULL) { 12364 fileset_load = true; 12365 12366 /* Get a page aligned address from kext map to map the file */ 12367 vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize); 12368 if (pagealigned_addr == 0) { 12369 return kOSKextReturnNoMemory; 12370 } 12371 12372 *mhp = (kernel_mach_header_t *)pagealigned_addr; 12373 12374 /* Allocate memory for bailout mechanism */ 12375 map_entry_list = allocate_kcfileset_map_entry_list(); 12376 if (map_entry_list == NULL) { 12377 return kOSKextReturnNoMemory; 12378 } 12379 } 12380 12381 uintptr_t *slideptr = fileset_load ? slidep : NULL; 12382 err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list); 12383 /* mhp and slideptr are updated by mapKCTextSegment */ 12384 if (err) { 12385 if (fileset_load) { 12386 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12387 } 12388 return err; 12389 } 12390 12391 /* Initialize the kc header globals */ 12392 if (fileset_load) { 12393 if (pageable) { 12394 PE_set_kc_header(KCKindPageable, *mhp, *slidep); 12395 } else { 12396 PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep); 12397 } 12398 } 12399 12400 /* Iterate through all the segments and map necessary segments */ 12401 struct load_command *lcp = (struct load_command *) (*mhp + 1); 12402 for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) { 12403 vm_map_offset_t start; 12404 kernel_mach_header_t *k_mh = NULL; 12405 kernel_segment_command_t * seg = NULL; 12406 struct fileset_entry_command *fse = NULL; 12407 12408 if (lcp->cmd == LC_SEGMENT_KERNEL) { 12409 seg = (kernel_segment_command_t *)lcp; 12410 start = ((uintptr_t)(seg->vmaddr)) + *slidep; 12411 } else if (lcp->cmd == LC_FILESET_ENTRY) { 12412 fse = (struct fileset_entry_command *)lcp; 12413 k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep); 12414 12415 /* Map the segments of the mach-o binary */ 12416 err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list); 12417 if (err) { 12418 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12419 return kOSKextReturnInvalidArgument; 12420 } 12421 continue; 12422 } else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) { 12423 /* Check if the Aux KC is built pageable style */ 12424 if (!pageable && !fileset_load && !auxKCloaded) { 12425 resetAuxKCSegmentOnUnload = true; 12426 } 12427 continue; 12428 } else { 12429 continue; 12430 } 12431 12432 if (fileset_load) { 12433 if (seg->vmsize == 0) { 12434 continue; 12435 } 12436 12437 /* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */ 12438 if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 && 12439 strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 && 12440 strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 && 12441 strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) { 12442 continue; 12443 } 12444 } else { 12445 if (seg->vmsize == 0) { 12446 continue; 12447 } 12448 12449 /* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */ 12450 if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 || 12451 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 || 12452 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) { 12453 continue; 12454 } 12455 } 12456 12457 ret = vm_map_kcfileset_segment( 12458 &start, seg->vmsize, 12459 (memory_object_control_t)control, seg->fileoff, seg->maxprot); 12460 12461 if (ret != KERN_SUCCESS) { 12462 if (fileset_load) { 12463 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12464 } 12465 return kOSKextReturnInvalidArgument; 12466 } 12467 add_kcfileset_map_entry(map_entry_list, start, seg->vmsize); 12468 } 12469 12470 /* Return if regular mach-o */ 12471 if (!fileset_load) { 12472 return 0; 12473 } 12474 12475 /* 12476 * Fixup for the Pageable KC and the Aux KC is done by 12477 * i386_slide_kext_collection_mh_addrs, but it differs in 12478 * following ways: 12479 * 12480 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands. 12481 * The fixup of kext segments and kext load commands are done at kext 12482 * load time by calling i386_slide_individual_kext. 12483 * 12484 * AuxKC old style: Fixup all the segments and all the load commands. 12485 * 12486 * AuxKC pageable style: Same as the Pageable KC. 12487 */ 12488 bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false)); 12489 ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header); 12490 if (ret != KERN_SUCCESS) { 12491 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12492 return kOSKextReturnInvalidArgument; 12493 } 12494 12495 /* Get the prelink info dictionary */ 12496 infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection); 12497 parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString); 12498 if (parsedXML) { 12499 infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 12500 } 12501 12502 if (!infoDict) { 12503 const char *errorCString = "(unknown error)"; 12504 12505 if (errorString && errorString->getCStringNoCopy()) { 12506 errorCString = errorString->getCStringNoCopy(); 12507 } else if (parsedXML) { 12508 errorCString = "not a dictionary"; 12509 } 12510 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12511 "Error unserializing kext info plist section: %s.", errorCString); 12512 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12513 return kOSKextReturnInvalidArgument; 12514 } 12515 12516 /* Validate that the Kext Collection is prelinked to the loaded KC */ 12517 err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary); 12518 if (err) { 12519 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12520 return kOSKextReturnInvalidArgument; 12521 } 12522 12523 /* Set Protection of Segments */ 12524 OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary); 12525 12526 OSKext::addKextsFromKextCollection(*mhp, 12527 infoDict, kPrelinkTextSegment, 12528 loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary); 12529 12530 /* Copy in the KC UUID */ 12531 if (!loaded_kcUUID) { 12532 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12533 "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux"); 12534 } else if (pageable) { 12535 pageablekc_uuid_valid = TRUE; 12536 memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength()); 12537 uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string); 12538 } else { 12539 auxkc_uuid_valid = TRUE; 12540 memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength()); 12541 uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string); 12542 } 12543 12544 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable); 12545 12546 return 0; 12547 } 12548 12549 /********************************************************************* 12550 * Assumes sKextLock is held. 12551 *********************************************************************/ 12552 /* static */ 12553 OSReturn 12554 OSKext::mapKCTextSegment( 12555 void *control, 12556 kernel_mach_header_t **mhp, 12557 off_t file_offset, 12558 uintptr_t *slidep, 12559 void *map_entry_list) 12560 { 12561 kern_return_t ret; 12562 vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t), 12563 PAGE_MASK); 12564 vm_map_offset_t load_command_map_size = 0; 12565 kernel_mach_header_t *base_mh = *mhp; 12566 12567 /* Map the mach header at start of fileset for now (vmaddr = 0) */ 12568 ret = vm_map_kcfileset_segment( 12569 (vm_map_offset_t *)&base_mh, mach_header_map_size, 12570 (memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE)); 12571 12572 if (ret != KERN_SUCCESS) { 12573 printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret); 12574 12575 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12576 "Failed to map mach header of kc fileset with error %d", ret); 12577 return kOSKextReturnInvalidArgument; 12578 } 12579 12580 if (slidep) { 12581 /* Verify that it's an MH_FILESET */ 12582 if (base_mh->filetype != MH_FILESET) { 12583 printf("Kext Log: mapKCTextSegment mach header filetype" 12584 " is not an MH_FILESET, it is %x", base_mh->filetype); 12585 12586 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12587 "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype); 12588 12589 /* Unmap the mach header */ 12590 vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 12591 return kOSKextReturnInvalidArgument; 12592 } 12593 } 12594 12595 /* Map the remaining pages of load commands */ 12596 if (base_mh->sizeofcmds > mach_header_map_size) { 12597 vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size; 12598 load_command_map_size = base_mh->sizeofcmds - mach_header_map_size; 12599 12600 /* Map the load commands */ 12601 ret = vm_map_kcfileset_segment( 12602 &load_command_addr, load_command_map_size, 12603 (memory_object_control_t)control, file_offset + mach_header_map_size, 12604 (VM_PROT_READ | VM_PROT_WRITE)); 12605 12606 if (ret != KERN_SUCCESS) { 12607 printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret); 12608 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12609 "Failed to map load commands of kc fileset with error %d", ret); 12610 12611 /* Unmap the mach header */ 12612 vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 12613 return kOSKextReturnInvalidArgument; 12614 } 12615 } 12616 12617 kernel_segment_command_t *text_seg; 12618 text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT); 12619 12620 /* Calculate the slide and vm addr of mach header */ 12621 if (slidep) { 12622 *mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr); 12623 *slidep = ((uintptr_t)*mhp) - text_seg->vmaddr; 12624 } 12625 12626 /* Cache the text segment size and file offset before unmapping */ 12627 vm_map_offset_t text_segment_size = text_seg->vmsize; 12628 vm_object_offset_t text_segment_fileoff = text_seg->fileoff; 12629 vm_prot_t text_maxprot = text_seg->maxprot; 12630 12631 /* Unmap the first page and loadcommands and map the text segment */ 12632 ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 12633 assert(ret == KERN_SUCCESS); 12634 12635 if (load_command_map_size) { 12636 vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size; 12637 ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size); 12638 assert(ret == KERN_SUCCESS); 12639 } 12640 12641 /* Map the text segment at actual vm addr specified in fileset */ 12642 ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size, 12643 (memory_object_control_t)control, text_segment_fileoff, text_maxprot); 12644 if (ret != KERN_SUCCESS) { 12645 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12646 "Failed to map Text segment of kc fileset with error %d", ret); 12647 return kOSKextReturnInvalidArgument; 12648 } 12649 12650 add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size); 12651 return 0; 12652 } 12653 12654 /********************************************************************* 12655 * Assumes sKextLock is held. 12656 *********************************************************************/ 12657 /* static */ 12658 OSReturn 12659 OSKext::protectKCFileSet( 12660 kernel_mach_header_t *mh, 12661 kc_kind_t type) 12662 { 12663 vm_map_t kext_map = g_kext_map; 12664 kernel_segment_command_t * seg = NULL; 12665 vm_map_offset_t start = 0; 12666 vm_map_offset_t end = 0; 12667 OSReturn ret = 0; 12668 12669 /* Set VM permissions */ 12670 seg = firstsegfromheader((kernel_mach_header_t *)mh); 12671 while (seg) { 12672 start = round_page(seg->vmaddr); 12673 end = trunc_page(seg->vmaddr + seg->vmsize); 12674 12675 /* 12676 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS 12677 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT 12678 * for the Aux KC as well. 12679 */ 12680 if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 || 12681 strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 || 12682 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 || 12683 (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload && 12684 strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) { 12685 ret = OSKext_protect((kernel_mach_header_t *)mh, 12686 kext_map, start, end, seg->maxprot, TRUE, type); 12687 if (ret != KERN_SUCCESS) { 12688 printf("OSKext protect failed with error %d", ret); 12689 return kOSKextReturnInvalidArgument; 12690 } 12691 12692 ret = OSKext_protect((kernel_mach_header_t *)mh, 12693 kext_map, start, end, seg->initprot, FALSE, type); 12694 if (ret != KERN_SUCCESS) { 12695 printf("OSKext protect failed with error %d", ret); 12696 return kOSKextReturnInvalidArgument; 12697 } 12698 12699 ret = OSKext_wire((kernel_mach_header_t *)mh, 12700 kext_map, start, end, seg->initprot, FALSE, type); 12701 if (ret != KERN_SUCCESS) { 12702 printf("OSKext wire failed with error %d", ret); 12703 return kOSKextReturnInvalidArgument; 12704 } 12705 } 12706 12707 seg = nextsegfromheader((kernel_mach_header_t *) mh, seg); 12708 } 12709 12710 return 0; 12711 } 12712 12713 /********************************************************************* 12714 * Assumes sKextLock is held. 12715 *********************************************************************/ 12716 /* static */ 12717 void 12718 OSKext::freeKCFileSetcontrol(void) 12719 { 12720 PE_reset_all_kc_vp(); 12721 } 12722 12723 /********************************************************************* 12724 * Assumes sKextLock is held. 12725 * 12726 * resetKCFileSetSegments: Kext start function expects data segment to 12727 * be pristine on every load, unmap the dirty segments on unload and 12728 * remap them from FileSet on disk. Remap all segments of kext since 12729 * fixups are done per kext and not per segment. 12730 *********************************************************************/ 12731 OSReturn 12732 OSKext::resetKCFileSetSegments(void) 12733 { 12734 kernel_segment_command_t *seg = NULL; 12735 kernel_segment_command_t *text_seg; 12736 uint32_t text_fileoff; 12737 kernel_mach_header_t *k_mh = NULL; 12738 uintptr_t slide; 12739 struct vnode *vp = NULL; 12740 void *fileset_control = NULL; 12741 bool pageable = (kc_type == KCKindPageable); 12742 OSReturn err; 12743 kern_return_t kr; 12744 12745 /* Check the vnode reference is still available */ 12746 vp = (struct vnode *)PE_get_kc_vp(kc_type); 12747 if (vp == NULL) { 12748 OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag, 12749 "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString()); 12750 return kOSKextReturnInternalError; 12751 } 12752 12753 fileset_control = ubc_getobject(vp, 0); 12754 assert(fileset_control != NULL); 12755 12756 OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag, 12757 "Kext %s resetting all segments", getIdentifierCString()); 12758 12759 k_mh = (kernel_mach_header_t *)kmod_info->address; 12760 text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT); 12761 text_fileoff = text_seg->fileoff; 12762 slide = PE_get_kc_slide(kc_type); 12763 12764 seg = firstsegfromheader((kernel_mach_header_t *)k_mh); 12765 while (seg) { 12766 if (seg->vmsize == 0) { 12767 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 12768 continue; 12769 } 12770 12771 /* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */ 12772 if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 || 12773 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 || 12774 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) { 12775 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 12776 continue; 12777 } 12778 12779 kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize); 12780 assert(kr == KERN_SUCCESS); 12781 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 12782 } 12783 12784 /* Unmap the text segment */ 12785 kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize); 12786 assert(kr == KERN_SUCCESS); 12787 12788 /* Map all the segments of the kext */ 12789 err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL); 12790 if (err) { 12791 panic("Could not reset segments of a mapped kext, error %x", err); 12792 } 12793 12794 /* Update address in kmod_info, since it has been reset */ 12795 if (kmod_info->address) { 12796 kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide); 12797 } 12798 12799 return 0; 12800 } 12801 12802 /********************************************************************* 12803 * Mechanism to track all segment mapping while mapping KC fileset. 12804 *********************************************************************/ 12805 12806 struct kcfileset_map_entry { 12807 vm_map_offset_t me_start; 12808 vm_map_offset_t me_size; 12809 }; 12810 12811 struct kcfileset_map_entry_list { 12812 int kme_list_count; 12813 int kme_list_index; 12814 struct kcfileset_map_entry kme_list[]; 12815 }; 12816 12817 #define KCFILESET_MAP_ENTRY_MAX (16380) 12818 12819 static void * 12820 allocate_kcfileset_map_entry_list(void) 12821 { 12822 struct kcfileset_map_entry_list *entry_list; 12823 12824 entry_list = kalloc_type(struct kcfileset_map_entry_list, 12825 struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO); 12826 12827 entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX; 12828 entry_list->kme_list_index = 0; 12829 return entry_list; 12830 } 12831 12832 static void 12833 add_kcfileset_map_entry( 12834 void *map_entry_list, 12835 vm_map_offset_t start, 12836 vm_map_offset_t size) 12837 { 12838 if (map_entry_list == NULL) { 12839 return; 12840 } 12841 12842 struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list; 12843 12844 if (entry_list->kme_list_index >= entry_list->kme_list_count) { 12845 panic("Ran out of map kc fileset list"); 12846 } 12847 12848 entry_list->kme_list[entry_list->kme_list_index].me_start = start; 12849 entry_list->kme_list[entry_list->kme_list_index].me_size = size; 12850 12851 entry_list->kme_list_index++; 12852 } 12853 12854 static void 12855 deallocate_kcfileset_map_entry_list_and_unmap_entries( 12856 void *map_entry_list, 12857 boolean_t unmap_entries, 12858 bool pageable) 12859 { 12860 struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list; 12861 12862 if (unmap_entries) { 12863 for (int i = 0; i < entry_list->kme_list_index; i++) { 12864 kern_return_t ret; 12865 ret = vm_unmap_kcfileset_segment( 12866 &(entry_list->kme_list[i].me_start), 12867 entry_list->kme_list[i].me_size); 12868 assert(ret == KERN_SUCCESS); 12869 } 12870 12871 PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary); 12872 } 12873 12874 kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry, 12875 KCFILESET_MAP_ENTRY_MAX, entry_list); 12876 } 12877 12878 /********************************************************************* 12879 * Mechanism to map kext segment. 12880 *********************************************************************/ 12881 12882 kern_return_t 12883 vm_map_kcfileset_segment( 12884 vm_map_offset_t *start, 12885 vm_map_offset_t size, 12886 void *control, 12887 vm_object_offset_t fileoffset, 12888 vm_prot_t max_prot) 12889 { 12890 vm_map_kernel_flags_t vmk_flags; 12891 vmk_flags.vmkf_no_copy_on_read = 1; 12892 vmk_flags.vmkf_cs_enforcement = 0; 12893 vmk_flags.vmkf_cs_enforcement_override = 1; 12894 kern_return_t ret; 12895 12896 /* Add Write to max prot to allow fixups */ 12897 max_prot = max_prot | VM_PROT_WRITE; 12898 12899 /* 12900 * Map the segments from file as COPY mappings to 12901 * make sure changes on disk to the file does not affect 12902 * mapped segments. 12903 */ 12904 ret = vm_map_enter_mem_object_control( 12905 g_kext_map, 12906 start, 12907 size, 12908 (mach_vm_offset_t)0, 12909 VM_FLAGS_FIXED, 12910 vmk_flags, 12911 VM_KERN_MEMORY_OSKEXT, 12912 (memory_object_control_t)control, 12913 fileoffset, 12914 TRUE, /* copy */ 12915 (VM_PROT_READ | VM_PROT_WRITE), max_prot, 12916 VM_INHERIT_NONE); 12917 12918 return ret; 12919 } 12920 12921 kern_return_t 12922 vm_unmap_kcfileset_segment( 12923 vm_map_offset_t *start, 12924 vm_map_offset_t size) 12925 { 12926 return mach_vm_deallocate(g_kext_map, *start, size); 12927 } 12928 12929 #endif //(__x86_64__) || defined(__i386__) 12930 12931 /********************************************************************* 12932 * Assumes sKextLock is held. 12933 *********************************************************************/ 12934 /* static */ 12935 OSReturn 12936 OSKext::validateKCFileSetUUID( 12937 OSDictionary *infoDict, 12938 kc_kind_t type) 12939 { 12940 OSReturn ret = kOSReturnSuccess; 12941 12942 if (!kernelcache_uuid_valid) { 12943 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12944 "validateKCFileSetUUID Boot KC UUID was not set at boot."); 12945 ret = kOSKextReturnInvalidArgument; 12946 goto finish; 12947 } 12948 ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey); 12949 if (ret != 0) { 12950 goto finish; 12951 } 12952 12953 #if defined(__x86_64__) || defined(__i386__) 12954 /* Check if the Aux KC is prelinked to correct Pageable KC */ 12955 if (type == KCKindAuxiliary) { 12956 if (!pageablekc_uuid_valid) { 12957 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12958 "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC."); 12959 ret = kOSKextReturnInvalidArgument; 12960 goto finish; 12961 } 12962 ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey); 12963 if (ret != 0) { 12964 goto finish; 12965 } 12966 } 12967 #endif //(__x86_64__) || defined(__i386__) 12968 12969 printf("KextLog: Collection UUID matches with loaded KCs.\n"); 12970 finish: 12971 return ret; 12972 } 12973 12974 /********************************************************************* 12975 * Assumes sKextLock is held. 12976 *********************************************************************/ 12977 /* static */ 12978 OSReturn 12979 OSKext::validateKCUUIDfromPrelinkInfo( 12980 uuid_t *loaded_kcuuid, 12981 kc_kind_t type, 12982 OSDictionary *infoDict, 12983 const char *uuid_key) 12984 { 12985 /* extract the UUID from the dictionary */ 12986 OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key)); 12987 if (!prelinkinfoKCUUID) { 12988 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12989 "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key); 12990 return kOSKextReturnInvalidArgument; 12991 } 12992 12993 if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) { 12994 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12995 "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength()); 12996 return kOSKextReturnInvalidArgument; 12997 } 12998 12999 if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), 13000 prelinkinfoKCUUID->getLength())) { 13001 OSData *info_dict_uuid; 13002 uuid_string_t info_dict_uuid_str = {}; 13003 uuid_string_t expected_uuid_str = {}; 13004 uuid_string_t given_uuid_str = {}; 13005 uuid_t given_uuid; 13006 13007 /* extract the KC UUID from the dictionary */ 13008 info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 13009 if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) { 13010 uuid_t tmp_uuid; 13011 memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid)); 13012 uuid_unparse(tmp_uuid, info_dict_uuid_str); 13013 } 13014 13015 uuid_unparse(*loaded_kcuuid, expected_uuid_str); 13016 memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid)); 13017 uuid_unparse(given_uuid, given_uuid_str); 13018 13019 printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key, 13020 given_uuid_str, expected_uuid_str, info_dict_uuid_str); 13021 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13022 "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key, 13023 given_uuid_str, expected_uuid_str, info_dict_uuid_str); 13024 if (type == KCKindPageable && sPanicOnKCMismatch) { 13025 panic("System KC UUID %s linked against %s, but %s is loaded", 13026 info_dict_uuid_str, given_uuid_str, expected_uuid_str); 13027 } 13028 return kOSKextReturnInvalidArgument; 13029 } 13030 13031 return 0; 13032 } 13033 13034 /********************************************************************* 13035 * Assumes sKextLock is held. 13036 *********************************************************************/ 13037 /* static */ 13038 OSReturn 13039 OSKext::dispatchResource(OSDictionary * requestDict) 13040 { 13041 OSReturn result = kOSReturnError; 13042 OSSharedPtr<OSDictionary> callbackRecord; 13043 OSNumber * requestTag = NULL; // do not release 13044 OSNumber * requestResult = NULL; // do not release 13045 OSData * dataObj = NULL; // do not release 13046 uint32_t dataLength = 0; 13047 const void * dataPtr = NULL; // do not free 13048 OSData * callbackWrapper = NULL; // do not release 13049 OSKextRequestResourceCallback callback = NULL; 13050 OSData * contextWrapper = NULL; // do not release 13051 void * context = NULL; // do not free 13052 OSSharedPtr<OSKext> callbackKext; 13053 13054 /* Get the args from the request. Right now we need the tag 13055 * to look up the callback record, and the result for invoking the callback. 13056 */ 13057 requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 13058 kKextRequestArgumentRequestTagKey)); 13059 requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 13060 kKextRequestArgumentResultKey)); 13061 if (!requestTag || !requestResult) { 13062 result = kOSKextReturnInvalidArgument; 13063 goto finish; 13064 } 13065 13066 /* Look for a callback record matching this request's tag. 13067 */ 13068 result = dequeueCallbackForRequestTag(requestTag, callbackRecord); 13069 if (result != kOSReturnSuccess) { 13070 goto finish; 13071 } 13072 13073 /***** 13074 * Get the context pointer of the callback record (if there is one). 13075 */ 13076 contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord.get(), 13077 kKextRequestArgumentContextKey)); 13078 context = _OSKextExtractPointer(contextWrapper); 13079 if (contextWrapper && !context) { 13080 goto finish; 13081 } 13082 13083 callbackWrapper = OSDynamicCast(OSData, 13084 _OSKextGetRequestArgument(callbackRecord.get(), 13085 kKextRequestArgumentCallbackKey)); 13086 callback = _OSKextExtractCallbackPointer(callbackWrapper); 13087 if (!callback) { 13088 goto finish; 13089 } 13090 13091 /* Check for a data obj. We might not have one and that's ok, that means 13092 * we didn't find the requested resource, and we still have to tell the 13093 * caller that via the callback. 13094 */ 13095 dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict, 13096 kKextRequestArgumentValueKey)); 13097 if (dataObj) { 13098 dataPtr = dataObj->getBytesNoCopy(); 13099 dataLength = dataObj->getLength(); 13100 } 13101 13102 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 13103 if (!callbackKext) { 13104 OSKextLog(/* kext */ NULL, 13105 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 13106 "Can't invoke callback for resource request; "); 13107 goto finish; 13108 } 13109 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 13110 OSKextLog(/* kext */ NULL, 13111 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 13112 "Can't invoke kext resource callback; "); 13113 goto finish; 13114 } 13115 13116 (void)callback(requestTag->unsigned32BitValue(), 13117 (OSReturn)requestResult->unsigned32BitValue(), 13118 dataPtr, dataLength, context); 13119 13120 result = kOSReturnSuccess; 13121 13122 finish: 13123 return result; 13124 } 13125 13126 /********************************************************************* 13127 * Assumes sKextLock is held. 13128 *********************************************************************/ 13129 /* static */ 13130 OSReturn 13131 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict) 13132 { 13133 OSSharedPtr<OSDictionary> missingIDs; 13134 OSArray *bundleIDList = NULL; // do not release 13135 13136 bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 13137 requestDict, kKextRequestArgumentMissingBundleIDs)); 13138 if (!bundleIDList) { 13139 return kOSKextReturnInvalidArgument; 13140 } 13141 13142 missingIDs = OSDictionary::withCapacity(bundleIDList->getCount()); 13143 if (!missingIDs) { 13144 return kOSKextReturnNoMemory; 13145 } 13146 13147 uint32_t count, i; 13148 count = bundleIDList->getCount(); 13149 for (i = 0; i < count; i++) { 13150 OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i)); 13151 if (thisID) { 13152 missingIDs->setObject(thisID, kOSBooleanFalse); 13153 } 13154 } 13155 13156 sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain); 13157 13158 return kOSReturnSuccess; 13159 } 13160 13161 /********************************************************************* 13162 * Assumes sKextLock is held. 13163 *********************************************************************/ 13164 /* static */ 13165 OSReturn 13166 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict) 13167 { 13168 bool loadable = true; 13169 if (!kextIdentifier) { 13170 return kOSKextReturnInvalidArgument; 13171 } 13172 13173 if (requestDict) { 13174 OSBoolean *loadableArg; 13175 loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 13176 requestDict, kKextRequestArgumentBundleAvailability)); 13177 /* If we find the "Bundle Available" arg, and it's false, then 13178 * mark the bundle ID as _not_ loadable 13179 */ 13180 if (loadableArg && !loadableArg->getValue()) { 13181 loadable = false; 13182 } 13183 } 13184 13185 if (!sNonLoadableKextsByID) { 13186 sNonLoadableKextsByID = OSDictionary::withCapacity(1); 13187 } 13188 13189 sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable)); 13190 13191 OSKextLog(/* kext */ NULL, 13192 kOSKextLogBasicLevel | kOSKextLogIPCFlag, 13193 "KextLog: AuxKC bundle %s marked as %s", 13194 kextIdentifier->getCStringNoCopy(), 13195 (loadable ? "loadable" : "NOT loadable")); 13196 13197 return kOSReturnSuccess; 13198 } 13199 13200 /********************************************************************* 13201 *********************************************************************/ 13202 /* static */ 13203 void 13204 OSKext::invokeRequestCallback( 13205 OSDictionary * callbackRecord, 13206 OSReturn callbackResult) 13207 { 13208 OSString * predicate = _OSKextGetRequestPredicate(callbackRecord); 13209 OSSharedPtr<OSNumber> resultNum; 13210 13211 if (!predicate) { 13212 goto finish; 13213 } 13214 13215 resultNum = OSNumber::withNumber((long long unsigned int)callbackResult, 13216 8 * sizeof(callbackResult)); 13217 if (!resultNum) { 13218 goto finish; 13219 } 13220 13221 /* Insert the result into the callback record and dispatch it as if it 13222 * were the reply coming down from user space. 13223 */ 13224 _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey, 13225 resultNum.get()); 13226 13227 if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) { 13228 /* This removes the pending callback record. 13229 */ 13230 OSKext::dispatchResource(callbackRecord); 13231 } 13232 13233 finish: 13234 return; 13235 } 13236 13237 /********************************************************************* 13238 * Assumes sKextLock is held. 13239 *********************************************************************/ 13240 /* static */ 13241 OSReturn 13242 OSKext::cancelRequest( 13243 OSKextRequestTag requestTag, 13244 void ** contextOut) 13245 { 13246 OSReturn result = kOSKextReturnNoMemory; 13247 OSSharedPtr<OSDictionary> callbackRecord; 13248 OSData * contextWrapper = NULL; // do not release 13249 13250 IORecursiveLockLock(sKextLock); 13251 result = OSKext::dequeueCallbackForRequestTag(requestTag, 13252 callbackRecord); 13253 IORecursiveLockUnlock(sKextLock); 13254 13255 if (result == kOSReturnSuccess && contextOut) { 13256 contextWrapper = OSDynamicCast(OSData, 13257 _OSKextGetRequestArgument(callbackRecord.get(), 13258 kKextRequestArgumentContextKey)); 13259 *contextOut = _OSKextExtractPointer(contextWrapper); 13260 } 13261 13262 return result; 13263 } 13264 13265 /********************************************************************* 13266 * Assumes sKextLock is held. 13267 *********************************************************************/ 13268 void 13269 OSKext::invokeOrCancelRequestCallbacks( 13270 OSReturn callbackResult, 13271 bool invokeFlag) 13272 { 13273 unsigned int count, i; 13274 13275 count = sRequestCallbackRecords->getCount(); 13276 if (!count) { 13277 goto finish; 13278 } 13279 13280 i = count - 1; 13281 do { 13282 OSDictionary * request = OSDynamicCast(OSDictionary, 13283 sRequestCallbackRecords->getObject(i)); 13284 13285 if (!request) { 13286 continue; 13287 } 13288 OSData * callbackWrapper = OSDynamicCast(OSData, 13289 _OSKextGetRequestArgument(request, 13290 kKextRequestArgumentCallbackKey)); 13291 13292 if (!callbackWrapper) { 13293 sRequestCallbackRecords->removeObject(i); 13294 continue; 13295 } 13296 13297 vm_address_t callbackAddress = (vm_address_t) 13298 ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer); 13299 13300 if ((kmod_info->address <= callbackAddress) && 13301 (callbackAddress < (kmod_info->address + kmod_info->size))) { 13302 if (invokeFlag) { 13303 /* This removes the callback record. 13304 */ 13305 invokeRequestCallback(request, callbackResult); 13306 } else { 13307 sRequestCallbackRecords->removeObject(i); 13308 } 13309 } 13310 } while (i--); 13311 13312 finish: 13313 return; 13314 } 13315 13316 /********************************************************************* 13317 * Assumes sKextLock is held. 13318 *********************************************************************/ 13319 uint32_t 13320 OSKext::countRequestCallbacks(void) 13321 { 13322 uint32_t result = 0; 13323 unsigned int count, i; 13324 13325 count = sRequestCallbackRecords->getCount(); 13326 if (!count) { 13327 goto finish; 13328 } 13329 13330 i = count - 1; 13331 do { 13332 OSDictionary * request = OSDynamicCast(OSDictionary, 13333 sRequestCallbackRecords->getObject(i)); 13334 13335 if (!request) { 13336 continue; 13337 } 13338 OSData * callbackWrapper = OSDynamicCast(OSData, 13339 _OSKextGetRequestArgument(request, 13340 kKextRequestArgumentCallbackKey)); 13341 13342 if (!callbackWrapper) { 13343 continue; 13344 } 13345 13346 vm_address_t callbackAddress = (vm_address_t) 13347 ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer); 13348 13349 if ((kmod_info->address <= callbackAddress) && 13350 (callbackAddress < (kmod_info->address + kmod_info->size))) { 13351 result++; 13352 } 13353 } while (i--); 13354 13355 finish: 13356 return result; 13357 } 13358 13359 /********************************************************************* 13360 *********************************************************************/ 13361 static OSReturn 13362 _OSKextCreateRequest( 13363 const char * predicate, 13364 OSSharedPtr<OSDictionary> & requestR) 13365 { 13366 OSReturn result = kOSKextReturnNoMemory; 13367 OSSharedPtr<OSDictionary> request; 13368 13369 request = OSDictionary::withCapacity(2); 13370 if (!request) { 13371 goto finish; 13372 } 13373 result = _OSDictionarySetCStringValue(request.get(), 13374 kKextRequestPredicateKey, predicate); 13375 if (result != kOSReturnSuccess) { 13376 goto finish; 13377 } 13378 result = kOSReturnSuccess; 13379 13380 finish: 13381 if (result == kOSReturnSuccess) { 13382 requestR = os::move(request); 13383 } 13384 13385 return result; 13386 } 13387 13388 /********************************************************************* 13389 *********************************************************************/ 13390 static OSString * 13391 _OSKextGetRequestPredicate(OSDictionary * requestDict) 13392 { 13393 return OSDynamicCast(OSString, 13394 requestDict->getObject(kKextRequestPredicateKey)); 13395 } 13396 13397 /********************************************************************* 13398 *********************************************************************/ 13399 static OSObject * 13400 _OSKextGetRequestArgument( 13401 OSDictionary * requestDict, 13402 const char * argName) 13403 { 13404 OSDictionary * args = OSDynamicCast(OSDictionary, 13405 requestDict->getObject(kKextRequestArgumentsKey)); 13406 if (args) { 13407 return args->getObject(argName); 13408 } 13409 return NULL; 13410 } 13411 13412 /********************************************************************* 13413 *********************************************************************/ 13414 static bool 13415 _OSKextSetRequestArgument( 13416 OSDictionary * requestDict, 13417 const char * argName, 13418 OSObject * value) 13419 { 13420 OSDictionary * args = OSDynamicCast(OSDictionary, 13421 requestDict->getObject(kKextRequestArgumentsKey)); 13422 OSSharedPtr<OSDictionary> newArgs; 13423 if (!args) { 13424 newArgs = OSDictionary::withCapacity(2); 13425 args = newArgs.get(); 13426 if (!args) { 13427 goto finish; 13428 } 13429 requestDict->setObject(kKextRequestArgumentsKey, args); 13430 } 13431 if (args) { 13432 return args->setObject(argName, value); 13433 } 13434 finish: 13435 return false; 13436 } 13437 13438 /********************************************************************* 13439 *********************************************************************/ 13440 static void * 13441 _OSKextExtractPointer(OSData * wrapper) 13442 { 13443 void * result = NULL; 13444 const void * resultPtr = NULL; 13445 13446 if (!wrapper) { 13447 goto finish; 13448 } 13449 resultPtr = wrapper->getBytesNoCopy(); 13450 result = *(void **)resultPtr; 13451 finish: 13452 return result; 13453 } 13454 13455 /********************************************************************* 13456 *********************************************************************/ 13457 static OSKextRequestResourceCallback 13458 _OSKextExtractCallbackPointer(OSData * wrapper) 13459 { 13460 OSKextRequestResourceCallback result = NULL; 13461 const void * resultPtr = NULL; 13462 13463 if (!wrapper) { 13464 goto finish; 13465 } 13466 resultPtr = wrapper->getBytesNoCopy(); 13467 result = *(OSKextRequestResourceCallback *)resultPtr; 13468 finish: 13469 return result; 13470 } 13471 13472 13473 /********************************************************************* 13474 *********************************************************************/ 13475 static OSReturn 13476 _OSDictionarySetCStringValue( 13477 OSDictionary * dict, 13478 const char * cKey, 13479 const char * cValue) 13480 { 13481 OSReturn result = kOSKextReturnNoMemory; 13482 OSSharedPtr<const OSSymbol> key; 13483 OSSharedPtr<OSString> value; 13484 13485 key = OSSymbol::withCString(cKey); 13486 value = OSString::withCString(cValue); 13487 if (!key || !value) { 13488 goto finish; 13489 } 13490 if (dict->setObject(key.get(), value.get())) { 13491 result = kOSReturnSuccess; 13492 } 13493 13494 finish: 13495 return result; 13496 } 13497 13498 /********************************************************************* 13499 *********************************************************************/ 13500 static bool 13501 _OSArrayContainsCString( 13502 OSArray * array, 13503 const char * cString) 13504 { 13505 bool result = false; 13506 OSSharedPtr<const OSSymbol> symbol; 13507 uint32_t count, i; 13508 13509 if (!array || !cString) { 13510 goto finish; 13511 } 13512 13513 symbol = OSSymbol::withCStringNoCopy(cString); 13514 if (!symbol) { 13515 goto finish; 13516 } 13517 13518 count = array->getCount(); 13519 for (i = 0; i < count; i++) { 13520 OSObject * thisObject = array->getObject(i); 13521 if (symbol->isEqualTo(thisObject)) { 13522 result = true; 13523 goto finish; 13524 } 13525 } 13526 13527 finish: 13528 return result; 13529 } 13530 13531 #if CONFIG_KXLD 13532 /********************************************************************* 13533 * We really only care about boot / system start up related kexts. 13534 * We return true if we're less than REBUILD_MAX_TIME since start up, 13535 * otherwise return false. 13536 *********************************************************************/ 13537 bool 13538 _OSKextInPrelinkRebuildWindow(void) 13539 { 13540 static bool outside_the_window = false; 13541 AbsoluteTime my_abstime; 13542 UInt64 my_ns; 13543 SInt32 my_secs; 13544 13545 if (outside_the_window) { 13546 return false; 13547 } 13548 clock_get_uptime(&my_abstime); 13549 absolutetime_to_nanoseconds(my_abstime, &my_ns); 13550 my_secs = (SInt32)(my_ns / NSEC_PER_SEC); 13551 if (my_secs > REBUILD_MAX_TIME) { 13552 outside_the_window = true; 13553 return false; 13554 } 13555 return true; 13556 } 13557 #endif /* CONFIG_KXLD */ 13558 13559 /********************************************************************* 13560 *********************************************************************/ 13561 bool 13562 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID ) 13563 { 13564 int unLoadedCount, i; 13565 bool result = false; 13566 13567 IORecursiveLockLock(sKextLock); 13568 13569 if (sUnloadedPrelinkedKexts == NULL) { 13570 goto finish; 13571 } 13572 unLoadedCount = sUnloadedPrelinkedKexts->getCount(); 13573 if (unLoadedCount == 0) { 13574 goto finish; 13575 } 13576 13577 for (i = 0; i < unLoadedCount; i++) { 13578 const OSSymbol * myBundleID; // do not release 13579 13580 myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i)); 13581 if (!myBundleID) { 13582 continue; 13583 } 13584 if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) { 13585 result = true; 13586 break; 13587 } 13588 } 13589 finish: 13590 IORecursiveLockUnlock(sKextLock); 13591 return result; 13592 } 13593 13594 #if PRAGMA_MARK 13595 #pragma mark Personalities (IOKit Drivers) 13596 #endif 13597 /********************************************************************* 13598 *********************************************************************/ 13599 /* static */ 13600 OSSharedPtr<OSArray> 13601 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag) 13602 { 13603 OSSharedPtr<OSArray> result; 13604 OSSharedPtr<OSCollectionIterator> kextIterator; 13605 OSSharedPtr<OSArray> personalities; 13606 13607 OSString * kextID = NULL; // do not release 13608 OSKext * theKext = NULL; // do not release 13609 13610 IORecursiveLockLock(sKextLock); 13611 13612 /* Let's conservatively guess that any given kext has around 3 13613 * personalities for now. 13614 */ 13615 result = OSArray::withCapacity(sKextsByID->getCount() * 3); 13616 if (!result) { 13617 goto finish; 13618 } 13619 13620 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 13621 if (!kextIterator) { 13622 goto finish; 13623 } 13624 13625 while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) { 13626 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID)); 13627 if (theKext->flags.requireExplicitLoad) { 13628 OSKextLog(theKext, 13629 kOSKextLogDebugLevel | 13630 kOSKextLogLoadFlag, 13631 "Kext %s requires an explicit kextload; " 13632 "omitting its personalities.", 13633 theKext->getIdentifierCString()); 13634 } else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) { 13635 personalities = theKext->copyPersonalitiesArray(); 13636 if (!personalities) { 13637 continue; 13638 } 13639 result->merge(personalities.get()); 13640 } else { 13641 // xxx - check for better place to put this log msg 13642 OSKextLog(theKext, 13643 kOSKextLogWarningLevel | 13644 kOSKextLogLoadFlag, 13645 "Kext %s is not loadable during safe boot; " 13646 "omitting its personalities.", 13647 theKext->getIdentifierCString()); 13648 } 13649 } 13650 13651 finish: 13652 IORecursiveLockUnlock(sKextLock); 13653 13654 return result; 13655 } 13656 13657 /********************************************************************* 13658 *********************************************************************/ 13659 /* static */ 13660 void 13661 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching) 13662 { 13663 int numPersonalities = 0; 13664 13665 OSKextLog(/* kext */ NULL, 13666 kOSKextLogStepLevel | 13667 kOSKextLogLoadFlag, 13668 "Sending all eligible registered kexts' personalities " 13669 "to the IOCatalogue %s.", 13670 startMatching ? "and starting matching" : "but not starting matching"); 13671 13672 OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities( 13673 /* filterSafeBootFlag */ true); 13674 13675 if (personalities) { 13676 gIOCatalogue->addDrivers(personalities.get(), startMatching); 13677 numPersonalities = personalities->getCount(); 13678 } 13679 13680 OSKextLog(/* kext */ NULL, 13681 kOSKextLogStepLevel | 13682 kOSKextLogLoadFlag, 13683 "%d kext personalit%s sent to the IOCatalogue; %s.", 13684 numPersonalities, numPersonalities > 0 ? "ies" : "y", 13685 startMatching ? "matching started" : "matching not started"); 13686 return; 13687 } 13688 13689 /********************************************************************* 13690 * Do not make a deep copy, just convert the IOKitPersonalities dict 13691 * to an array for sending to the IOCatalogue. 13692 *********************************************************************/ 13693 OSSharedPtr<OSArray> 13694 OSKext::copyPersonalitiesArray(void) 13695 { 13696 OSSharedPtr<OSArray> result; 13697 OSDictionary * personalities = NULL; // do not release 13698 OSSharedPtr<OSCollectionIterator> personalitiesIterator; 13699 13700 OSString * personalityName = NULL; // do not release 13701 OSString * personalityBundleIdentifier = NULL; // do not release 13702 13703 personalities = OSDynamicCast(OSDictionary, 13704 getPropertyForHostArch(kIOKitPersonalitiesKey)); 13705 if (!personalities) { 13706 goto finish; 13707 } 13708 13709 result = OSArray::withCapacity(personalities->getCount()); 13710 if (!result) { 13711 goto finish; 13712 } 13713 13714 personalitiesIterator = 13715 OSCollectionIterator::withCollection(personalities); 13716 if (!personalitiesIterator) { 13717 goto finish; 13718 } 13719 while ((personalityName = OSDynamicCast(OSString, 13720 personalitiesIterator->getNextObject()))) { 13721 OSDictionary * personality = OSDynamicCast(OSDictionary, 13722 personalities->getObject(personalityName)); 13723 13724 /****** 13725 * If the personality doesn't have a CFBundleIdentifier, or if it 13726 * differs from the kext's, insert the kext's ID so we can find it. 13727 * The publisher ID is used to remove personalities from bundles 13728 * correctly. 13729 */ 13730 personalityBundleIdentifier = OSDynamicCast(OSString, 13731 personality->getObject(kCFBundleIdentifierKey)); 13732 13733 if (!personalityBundleIdentifier) { 13734 personality->setObject(kCFBundleIdentifierKey, bundleID.get()); 13735 } else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) { 13736 personality->setObject(kIOPersonalityPublisherKey, bundleID.get()); 13737 } 13738 13739 result->setObject(personality); 13740 } 13741 13742 finish: 13743 return result; 13744 } 13745 13746 /********************************************************************* 13747 * Might want to change this to a bool return? 13748 *********************************************************************/ 13749 OSReturn 13750 OSKext::sendPersonalitiesToCatalog( 13751 bool startMatching, 13752 OSArray * personalityNames) 13753 { 13754 OSReturn result = kOSReturnSuccess; 13755 OSSharedPtr<OSArray> personalitiesToSend; 13756 OSDictionary * kextPersonalities = NULL; // do not release 13757 int count, i; 13758 13759 if (!sLoadEnabled) { 13760 OSKextLog(this, 13761 kOSKextLogErrorLevel | 13762 kOSKextLogLoadFlag, 13763 "Kext loading is disabled (attempt to start matching for kext %s).", 13764 getIdentifierCString()); 13765 result = kOSKextReturnDisabled; 13766 goto finish; 13767 } 13768 13769 if (sSafeBoot && !isLoadableInSafeBoot()) { 13770 OSKextLog(this, 13771 kOSKextLogErrorLevel | 13772 kOSKextLogLoadFlag, 13773 "Kext %s is not loadable during safe boot; " 13774 "not sending personalities to the IOCatalogue.", 13775 getIdentifierCString()); 13776 result = kOSKextReturnNotLoadable; 13777 goto finish; 13778 } 13779 13780 if (!personalityNames || !personalityNames->getCount()) { 13781 personalitiesToSend = copyPersonalitiesArray(); 13782 } else { 13783 kextPersonalities = OSDynamicCast(OSDictionary, 13784 getPropertyForHostArch(kIOKitPersonalitiesKey)); 13785 if (!kextPersonalities || !kextPersonalities->getCount()) { 13786 // not an error 13787 goto finish; 13788 } 13789 personalitiesToSend = OSArray::withCapacity(0); 13790 if (!personalitiesToSend) { 13791 result = kOSKextReturnNoMemory; 13792 goto finish; 13793 } 13794 count = personalityNames->getCount(); 13795 for (i = 0; i < count; i++) { 13796 OSString * name = OSDynamicCast(OSString, 13797 personalityNames->getObject(i)); 13798 if (!name) { 13799 continue; 13800 } 13801 OSDictionary * personality = OSDynamicCast(OSDictionary, 13802 kextPersonalities->getObject(name)); 13803 if (personality) { 13804 personalitiesToSend->setObject(personality); 13805 } 13806 } 13807 } 13808 if (personalitiesToSend) { 13809 unsigned numPersonalities = personalitiesToSend->getCount(); 13810 OSKextLog(this, 13811 kOSKextLogStepLevel | 13812 kOSKextLogLoadFlag, 13813 "Kext %s sending %d personalit%s to the IOCatalogue%s.", 13814 getIdentifierCString(), 13815 numPersonalities, 13816 numPersonalities > 1 ? "ies" : "y", 13817 startMatching ? " and starting matching" : " but not starting matching"); 13818 gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching); 13819 } 13820 finish: 13821 return result; 13822 } 13823 13824 /********************************************************************* 13825 * xxx - We should allow removing the kext's declared personalities, 13826 * xxx - even with other bundle identifiers. 13827 *********************************************************************/ 13828 void 13829 OSKext::removePersonalitiesFromCatalog(void) 13830 { 13831 OSSharedPtr<OSDictionary> personality; 13832 13833 personality = OSDictionary::withCapacity(1); 13834 if (!personality) { 13835 goto finish; 13836 } 13837 personality->setObject(kCFBundleIdentifierKey, getIdentifier()); 13838 13839 OSKextLog(this, 13840 kOSKextLogStepLevel | 13841 kOSKextLogLoadFlag, 13842 "Kext %s removing all personalities naming it from the IOCatalogue.", 13843 getIdentifierCString()); 13844 13845 /* Have the IOCatalog remove all personalities matching this kext's 13846 * bundle ID and trigger matching anew. 13847 */ 13848 gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true); 13849 13850 finish: 13851 return; 13852 } 13853 13854 13855 #if PRAGMA_MARK 13856 #pragma mark Logging 13857 #endif 13858 /********************************************************************* 13859 * Do not call any function that takes sKextLock here! 13860 *********************************************************************/ 13861 /* static */ 13862 OSKextLogSpec 13863 OSKext::setUserSpaceLogFilter( 13864 OSKextLogSpec newUserLogFilter, 13865 bool captureFlag) 13866 { 13867 OSKextLogSpec result; 13868 bool allocError = false; 13869 13870 /* Do not call any function that takes sKextLoggingLock during 13871 * this critical block. That means do logging after. 13872 */ 13873 IOLockLock(sKextLoggingLock); 13874 13875 result = sUserSpaceKextLogFilter; 13876 sUserSpaceKextLogFilter = newUserLogFilter; 13877 13878 if (newUserLogFilter && captureFlag && 13879 !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) { 13880 // xxx - do some measurements for a good initial capacity? 13881 sUserSpaceLogSpecArray = OSArray::withCapacity(0); 13882 sUserSpaceLogMessageArray = OSArray::withCapacity(0); 13883 13884 if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) { 13885 allocError = true; 13886 } 13887 } 13888 13889 IOLockUnlock(sKextLoggingLock); 13890 13891 /* If the config flag itself is changing, log the state change 13892 * going both ways, before setting up the user-space log arrays, 13893 * so that this is only logged in the kernel. 13894 */ 13895 if (result != newUserLogFilter) { 13896 OSKextLog(/* kext */ NULL, 13897 kOSKextLogDebugLevel | 13898 kOSKextLogGeneralFlag, 13899 "User-space log flags changed from 0x%x to 0x%x.", 13900 result, newUserLogFilter); 13901 } 13902 if (allocError) { 13903 OSKextLog(/* kext */ NULL, 13904 kOSKextLogErrorLevel | 13905 kOSKextLogGeneralFlag, 13906 "Failed to allocate user-space log message arrays."); 13907 } 13908 13909 return result; 13910 } 13911 13912 /********************************************************************* 13913 * Do not call any function that takes sKextLock here! 13914 *********************************************************************/ 13915 /* static */ 13916 OSSharedPtr<OSArray> 13917 OSKext::clearUserSpaceLogFilter(void) 13918 { 13919 OSSharedPtr<OSArray> result; 13920 OSKextLogSpec oldLogFilter; 13921 OSKextLogSpec newLogFilter = kOSKextLogSilentFilter; 13922 13923 /* Do not call any function that takes sKextLoggingLock during 13924 * this critical block. That means do logging after. 13925 */ 13926 IOLockLock(sKextLoggingLock); 13927 13928 result = OSArray::withCapacity(2); 13929 if (result) { 13930 result->setObject(sUserSpaceLogSpecArray.get()); 13931 result->setObject(sUserSpaceLogMessageArray.get()); 13932 } 13933 sUserSpaceLogSpecArray.reset(); 13934 sUserSpaceLogMessageArray.reset(); 13935 13936 oldLogFilter = sUserSpaceKextLogFilter; 13937 sUserSpaceKextLogFilter = newLogFilter; 13938 13939 IOLockUnlock(sKextLoggingLock); 13940 13941 /* If the config flag itself is changing, log the state change 13942 * going both ways, after tearing down the user-space log 13943 * arrays, so this is only logged within the kernel. 13944 */ 13945 if (oldLogFilter != newLogFilter) { 13946 OSKextLog(/* kext */ NULL, 13947 kOSKextLogDebugLevel | 13948 kOSKextLogGeneralFlag, 13949 "User-space log flags changed from 0x%x to 0x%x.", 13950 oldLogFilter, newLogFilter); 13951 } 13952 13953 return result; 13954 } 13955 13956 13957 /********************************************************************* 13958 * Do not call any function that takes sKextLock here! 13959 *********************************************************************/ 13960 /* static */ 13961 OSKextLogSpec 13962 OSKext::getUserSpaceLogFilter(void) 13963 { 13964 OSKextLogSpec result; 13965 13966 IOLockLock(sKextLoggingLock); 13967 result = sUserSpaceKextLogFilter; 13968 IOLockUnlock(sKextLoggingLock); 13969 13970 return result; 13971 } 13972 13973 /********************************************************************* 13974 * This function is called by OSMetaClass during kernel C++ setup. 13975 * Be careful what you access here; assume only OSKext::initialize() 13976 * has been called. 13977 * 13978 * Do not call any function that takes sKextLock here! 13979 *********************************************************************/ 13980 #define VTRESET "\033[0m" 13981 13982 #define VTBOLD "\033[1m" 13983 #define VTUNDER "\033[4m" 13984 13985 #define VTRED "\033[31m" 13986 #define VTGREEN "\033[32m" 13987 #define VTYELLOW "\033[33m" 13988 #define VTBLUE "\033[34m" 13989 #define VTMAGENTA "\033[35m" 13990 #define VTCYAN "\033[36m" 13991 13992 inline const char * 13993 colorForFlags(OSKextLogSpec flags) 13994 { 13995 OSKextLogSpec logLevel = flags & kOSKextLogLevelMask; 13996 13997 switch (logLevel) { 13998 case kOSKextLogErrorLevel: 13999 return VTRED VTBOLD; 14000 case kOSKextLogWarningLevel: 14001 return VTRED; 14002 case kOSKextLogBasicLevel: 14003 return VTYELLOW VTUNDER; 14004 case kOSKextLogProgressLevel: 14005 return VTYELLOW; 14006 case kOSKextLogStepLevel: 14007 return VTGREEN; 14008 case kOSKextLogDetailLevel: 14009 return VTCYAN; 14010 case kOSKextLogDebugLevel: 14011 return VTMAGENTA; 14012 default: 14013 return ""; // white 14014 } 14015 } 14016 14017 inline bool 14018 logSpecMatch( 14019 OSKextLogSpec msgLogSpec, 14020 OSKextLogSpec logFilter) 14021 { 14022 OSKextLogSpec filterKextGlobal = logFilter & kOSKextLogKextOrGlobalMask; 14023 OSKextLogSpec filterLevel = logFilter & kOSKextLogLevelMask; 14024 OSKextLogSpec filterFlags = logFilter & kOSKextLogFlagsMask; 14025 14026 OSKextLogSpec msgKextGlobal = msgLogSpec & kOSKextLogKextOrGlobalMask; 14027 OSKextLogSpec msgLevel = msgLogSpec & kOSKextLogLevelMask; 14028 OSKextLogSpec msgFlags = msgLogSpec & kOSKextLogFlagsMask; 14029 14030 /* Explicit messages always get logged. 14031 */ 14032 if (msgLevel == kOSKextLogExplicitLevel) { 14033 return true; 14034 } 14035 14036 /* Warnings and errors are logged regardless of the flags. 14037 */ 14038 if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) { 14039 return true; 14040 } 14041 14042 /* A verbose message that isn't for a logging-enabled kext and isn't global 14043 * does *not* get logged. 14044 */ 14045 if (!msgKextGlobal && !filterKextGlobal) { 14046 return false; 14047 } 14048 14049 /* Warnings and errors are logged regardless of the flags. 14050 * All other messages must fit the flags and 14051 * have a level at or below the filter. 14052 * 14053 */ 14054 if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) { 14055 return true; 14056 } 14057 return false; 14058 } 14059 14060 extern "C" { 14061 void 14062 OSKextLog( 14063 OSKext * aKext, 14064 OSKextLogSpec msgLogSpec, 14065 const char * format, ...) 14066 { 14067 va_list argList; 14068 14069 va_start(argList, format); 14070 OSKextVLog(aKext, msgLogSpec, format, argList); 14071 va_end(argList); 14072 } 14073 14074 void 14075 OSKextVLog( 14076 OSKext * aKext, 14077 OSKextLogSpec msgLogSpec, 14078 const char * format, 14079 va_list srcArgList) 14080 { 14081 extern int disableConsoleOutput; 14082 14083 bool logForKernel = false; 14084 bool logForUser = false; 14085 va_list argList; 14086 char stackBuffer[120]; 14087 uint32_t length = 0; 14088 char * allocBuffer = NULL; // must kfree 14089 OSSharedPtr<OSNumber> logSpecNum; 14090 OSSharedPtr<OSString> logString; 14091 char * buffer = stackBuffer; // do not free 14092 14093 IOLockLock(sKextLoggingLock); 14094 14095 /* Set the kext/global bit in the message spec if we have no 14096 * kext or if the kext requests logging. 14097 */ 14098 if (!aKext || aKext->flags.loggingEnabled) { 14099 msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask; 14100 } 14101 14102 logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter); 14103 if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 14104 logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter); 14105 } 14106 14107 if (!(logForKernel || logForUser)) { 14108 goto finish; 14109 } 14110 14111 /* No goto from here until past va_end()! 14112 */ 14113 va_copy(argList, srcArgList); 14114 length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList); 14115 va_end(argList); 14116 14117 if (length + 1 >= sizeof(stackBuffer)) { 14118 allocBuffer = (char *)kalloc_data_tag(length + 1, 14119 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 14120 if (!allocBuffer) { 14121 goto finish; 14122 } 14123 14124 /* No goto from here until past va_end()! 14125 */ 14126 va_copy(argList, srcArgList); 14127 vsnprintf(allocBuffer, length + 1, format, argList); 14128 va_end(argList); 14129 14130 buffer = allocBuffer; 14131 } 14132 14133 /* If user space wants the log message, queue it up. 14134 */ 14135 if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 14136 logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec)); 14137 logString = OSString::withCString(buffer); 14138 if (logSpecNum && logString) { 14139 sUserSpaceLogSpecArray->setObject(logSpecNum.get()); 14140 sUserSpaceLogMessageArray->setObject(logString.get()); 14141 } 14142 } 14143 14144 /* Always log messages from the kernel according to the kernel's 14145 * log flags. 14146 */ 14147 if (logForKernel) { 14148 /* If we are in console mode and have a custom log filter, 14149 * colorize the log message. 14150 */ 14151 if (!disableConsoleOutput && sBootArgLogFilterFound) { 14152 const char * color = ""; // do not free 14153 color = colorForFlags(msgLogSpec); 14154 printf("%s%s%s\n", colorForFlags(msgLogSpec), 14155 buffer, color[0] ? VTRESET : ""); 14156 } else { 14157 printf("%s\n", buffer); 14158 } 14159 } 14160 14161 finish: 14162 IOLockUnlock(sKextLoggingLock); 14163 14164 if (allocBuffer) { 14165 kfree_data(allocBuffer, length + 1); 14166 } 14167 return; 14168 } 14169 14170 #if KASLR_IOREG_DEBUG 14171 14172 #define IOLOG_INDENT( the_indention ) \ 14173 { \ 14174 int i; \ 14175 for ( i = 0; i < (the_indention); i++ ) { \ 14176 IOLog(" "); \ 14177 } \ 14178 } 14179 14180 extern vm_offset_t vm_kernel_stext; 14181 extern vm_offset_t vm_kernel_etext; 14182 extern mach_vm_offset_t kext_alloc_base; 14183 extern mach_vm_offset_t kext_alloc_max; 14184 14185 bool ScanForAddrInObject(OSObject * theObject, 14186 int indent ); 14187 14188 bool 14189 ScanForAddrInObject(OSObject * theObject, 14190 int indent) 14191 { 14192 const OSMetaClass * myTypeID; 14193 OSSharedPtr<OSCollectionIterator> myIter; 14194 OSSymbol * myKey; 14195 OSObject * myValue; 14196 bool myResult = false; 14197 14198 if (theObject == NULL) { 14199 IOLog("%s: theObject is NULL \n", 14200 __FUNCTION__); 14201 return myResult; 14202 } 14203 14204 myTypeID = OSTypeIDInst(theObject); 14205 14206 if (myTypeID == OSTypeID(OSDictionary)) { 14207 OSDictionary * myDictionary; 14208 14209 myDictionary = OSDynamicCast(OSDictionary, theObject); 14210 myIter = OSCollectionIterator::withCollection( myDictionary ); 14211 if (myIter == NULL) { 14212 return myResult; 14213 } 14214 14215 // !! reset the iterator 14216 myIter->reset(); 14217 14218 while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) { 14219 bool myTempResult; 14220 14221 myValue = myDictionary->getObject(myKey); 14222 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 14223 if (myTempResult) { 14224 // if we ever get a true result return true 14225 myResult = true; 14226 IOLOG_INDENT(indent); 14227 IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy()); 14228 } 14229 } 14230 14231 // !! release the iterator 14232 myIter.reset(); 14233 } else if (myTypeID == OSTypeID(OSArray)) { 14234 OSArray * myArray; 14235 14236 myArray = OSDynamicCast(OSArray, theObject); 14237 myIter = OSCollectionIterator::withCollection(myArray); 14238 if (myIter == NULL) { 14239 return myResult; 14240 } 14241 // !! reset the iterator 14242 myIter->reset(); 14243 14244 while ((myValue = myIter->getNextObject())) { 14245 bool myTempResult; 14246 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 14247 if (myTempResult) { 14248 // if we ever get a true result return true 14249 myResult = true; 14250 IOLOG_INDENT(indent); 14251 IOLog("OSArray: \n"); 14252 } 14253 } 14254 // !! release the iterator 14255 myIter.reset(); 14256 } else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) { 14257 // should we look for addresses in strings? 14258 } else if (myTypeID == OSTypeID(OSData)) { 14259 void * * myPtrPtr; 14260 unsigned int myLen; 14261 OSData * myDataObj; 14262 14263 myDataObj = OSDynamicCast(OSData, theObject); 14264 myPtrPtr = (void * *) myDataObj->getBytesNoCopy(); 14265 myLen = myDataObj->getLength(); 14266 14267 if (myPtrPtr && myLen && myLen > 7) { 14268 int i; 14269 int myPtrCount = (myLen / sizeof(void *)); 14270 14271 for (i = 0; i < myPtrCount; i++) { 14272 UInt64 numberValue = (UInt64) * (myPtrPtr); 14273 14274 if (kext_alloc_max != 0 && 14275 numberValue >= kext_alloc_base && 14276 numberValue < kext_alloc_max) { 14277 OSSharedPtr<OSKext> myKext; 14278 // IOLog("found OSData %p in kext map %p to %p \n", 14279 // *(myPtrPtr), 14280 // (void *) kext_alloc_base, 14281 // (void *) kext_alloc_max); 14282 14283 myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr)); 14284 if (myKext) { 14285 IOLog("found addr %p from an OSData obj within kext \"%s\" \n", 14286 *(myPtrPtr), 14287 myKext->getIdentifierCString()); 14288 } 14289 myResult = true; 14290 } 14291 if (vm_kernel_etext != 0 && 14292 numberValue >= vm_kernel_stext && 14293 numberValue < vm_kernel_etext) { 14294 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n", 14295 *(myPtrPtr), 14296 (void *) vm_kernel_stext, 14297 (void *) vm_kernel_etext); 14298 myResult = true; 14299 } 14300 myPtrPtr++; 14301 } 14302 } 14303 } else if (myTypeID == OSTypeID(OSBoolean)) { 14304 // do nothing here... 14305 } else if (myTypeID == OSTypeID(OSNumber)) { 14306 OSNumber * number = OSDynamicCast(OSNumber, theObject); 14307 14308 UInt64 numberValue = number->unsigned64BitValue(); 14309 14310 if (kext_alloc_max != 0 && 14311 numberValue >= kext_alloc_base && 14312 numberValue < kext_alloc_max) { 14313 OSSharedPtr<OSKext> myKext; 14314 IOLog("found OSNumber in kext map %p to %p \n", 14315 (void *) kext_alloc_base, 14316 (void *) kext_alloc_max); 14317 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 14318 14319 myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue ); 14320 if (myKext) { 14321 IOLog("found in kext \"%s\" \n", 14322 myKext->getIdentifierCString()); 14323 } 14324 14325 myResult = true; 14326 } 14327 if (vm_kernel_etext != 0 && 14328 numberValue >= vm_kernel_stext && 14329 numberValue < vm_kernel_etext) { 14330 IOLog("found OSNumber in kernel text segment %p to %p \n", 14331 (void *) vm_kernel_stext, 14332 (void *) vm_kernel_etext); 14333 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 14334 myResult = true; 14335 } 14336 } 14337 #if 0 14338 else { 14339 const OSMetaClass* myMetaClass = NULL; 14340 14341 myMetaClass = theObject->getMetaClass(); 14342 if (myMetaClass) { 14343 IOLog("class %s \n", myMetaClass->getClassName()); 14344 } else { 14345 IOLog("Unknown object \n" ); 14346 } 14347 } 14348 #endif 14349 14350 return myResult; 14351 } 14352 #endif // KASLR_KEXT_DEBUG 14353 }; /* extern "C" */ 14354 14355 #if PRAGMA_MARK 14356 #pragma mark Backtrace Dump & kmod_get_info() support 14357 #endif 14358 /********************************************************************* 14359 * This function must be safe to call in panic context. 14360 *********************************************************************/ 14361 /* static */ 14362 void 14363 OSKext::printKextsInBacktrace( 14364 vm_offset_t * addr __unused, 14365 unsigned int cnt __unused, 14366 int (* printf_func)(const char *fmt, ...) __unused, 14367 uint32_t flags __unused) 14368 { 14369 addr64_t summary_page = 0; 14370 addr64_t last_summary_page = 0; 14371 bool found_kmod = false; 14372 u_int i = 0; 14373 14374 if (kPrintKextsLock & flags) { 14375 if (!sKextSummariesLock) { 14376 return; 14377 } 14378 IOLockLock(sKextSummariesLock); 14379 } 14380 14381 if (!gLoadedKextSummaries) { 14382 (*printf_func)(" can't perform kext scan: no kext summary"); 14383 goto finish; 14384 } 14385 14386 summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries); 14387 last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize); 14388 for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) { 14389 if (pmap_find_phys(kernel_pmap, summary_page) == 0) { 14390 (*printf_func)(" can't perform kext scan: " 14391 "missing kext summary page %p", summary_page); 14392 goto finish; 14393 } 14394 } 14395 14396 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 14397 OSKextLoadedKextSummary * summary; 14398 14399 summary = gLoadedKextSummaries->summaries + i; 14400 if (!summary->address) { 14401 continue; 14402 } 14403 14404 if (!summaryIsInBacktrace(summary, addr, cnt)) { 14405 continue; 14406 } 14407 14408 if (!found_kmod) { 14409 if (!(kPrintKextsTerse & flags)) { 14410 (*printf_func)(" Kernel Extensions in backtrace:\n"); 14411 } 14412 found_kmod = true; 14413 } 14414 14415 printSummary(summary, printf_func, flags); 14416 } 14417 14418 finish: 14419 if (kPrintKextsLock & flags) { 14420 IOLockUnlock(sKextSummariesLock); 14421 } 14422 14423 return; 14424 } 14425 14426 /********************************************************************* 14427 * This function must be safe to call in panic context. 14428 *********************************************************************/ 14429 /* static */ 14430 boolean_t 14431 OSKext::summaryIsInBacktrace( 14432 OSKextLoadedKextSummary * summary, 14433 vm_offset_t * addr, 14434 unsigned int cnt) 14435 { 14436 u_int i = 0; 14437 14438 for (i = 0; i < cnt; i++) { 14439 vm_offset_t kscan_addr = addr[i]; 14440 #if __has_feature(ptrauth_calls) 14441 kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr); 14442 #endif /* __has_feature(ptrauth_calls) */ 14443 if ((kscan_addr >= summary->text_exec_address) && 14444 (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) { 14445 return TRUE; 14446 } 14447 } 14448 14449 return FALSE; 14450 } 14451 14452 /* 14453 * Get the kext summary object for the kext where 'addr' lies. Must be called with 14454 * sKextSummariesLock held. 14455 */ 14456 OSKextLoadedKextSummary * 14457 OSKext::summaryForAddress(uintptr_t addr) 14458 { 14459 #if __has_feature(ptrauth_calls) 14460 addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr); 14461 #endif /* __has_feature(ptrauth_calls) */ 14462 for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 14463 OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i]; 14464 if (!summary->address) { 14465 continue; 14466 } 14467 14468 #if VM_MAPPED_KEXTS 14469 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not 14470 * support split kexts, but we also may unmap the kexts, which can 14471 * race with the above codepath (see OSKext::unload). As such, 14472 * use a simple range lookup if we are using VM_MAPPED_KEXTS. 14473 */ 14474 if ((addr >= summary->address) && (addr < (summary->address + summary->size))) { 14475 return summary; 14476 } 14477 #else 14478 kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address; 14479 kernel_segment_command_t *seg; 14480 14481 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 14482 if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) { 14483 return summary; 14484 } 14485 } 14486 #endif 14487 } 14488 14489 /* addr did not map to any kext */ 14490 return NULL; 14491 } 14492 14493 /* static */ 14494 void * 14495 OSKext::kextForAddress(const void *address) 14496 { 14497 void * image = NULL; 14498 OSKextActiveAccount * active; 14499 OSKext * kext = NULL; 14500 uint32_t baseIdx; 14501 uint32_t lim; 14502 uintptr_t addr = (uintptr_t) address; 14503 size_t i; 14504 14505 if (!addr) { 14506 return NULL; 14507 } 14508 #if __has_feature(ptrauth_calls) 14509 addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr); 14510 #endif /* __has_feature(ptrauth_calls) */ 14511 14512 if (sKextAccountsCount) { 14513 IOSimpleLockLock(sKextAccountsLock); 14514 // bsearch sKextAccounts list 14515 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 14516 active = &sKextAccounts[baseIdx + (lim >> 1)]; 14517 if ((addr >= active->address) && (addr < active->address_end)) { 14518 kext = active->account->kext; 14519 if (kext && kext->kmod_info) { 14520 image = (void *) kext->kmod_info->address; 14521 } 14522 break; 14523 } else if (addr > active->address) { 14524 // move right 14525 baseIdx += (lim >> 1) + 1; 14526 lim--; 14527 } 14528 // else move left 14529 } 14530 IOSimpleLockUnlock(sKextAccountsLock); 14531 } 14532 if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) { 14533 image = (void *) &_mh_execute_header; 14534 } 14535 if (!image && gLoadedKextSummaries) { 14536 IOLockLock(sKextSummariesLock); 14537 for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) { 14538 OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i; 14539 if (addr >= summary->address && addr < summary->address + summary->size) { 14540 image = (void *)summary->address; 14541 } 14542 } 14543 IOLockUnlock(sKextSummariesLock); 14544 } 14545 14546 return image; 14547 } 14548 14549 /* 14550 * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t * 14551 * Safe to call in panic context. 14552 */ 14553 static OSKextLoadedKextSummary * 14554 findSummary(uint32_t tagID) 14555 { 14556 OSKextLoadedKextSummary * summary; 14557 for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 14558 summary = gLoadedKextSummaries->summaries + i; 14559 if (summary->loadTag == tagID) { 14560 return summary; 14561 } 14562 } 14563 return NULL; 14564 } 14565 14566 /********************************************************************* 14567 * This function must be safe to call in panic context. 14568 *********************************************************************/ 14569 void 14570 OSKext::printSummary( 14571 OSKextLoadedKextSummary * summary, 14572 int (* printf_func)(const char *fmt, ...), 14573 uint32_t flags) 14574 { 14575 kmod_reference_t * kmod_ref = NULL; 14576 uuid_string_t uuid; 14577 char version[kOSKextVersionMaxLength]; 14578 uint64_t tmpAddr; 14579 uint64_t tmpSize; 14580 OSKextLoadedKextSummary *dependencySummary; 14581 14582 if (!OSKextVersionGetString(summary->version, version, sizeof(version))) { 14583 strlcpy(version, "unknown version", sizeof(version)); 14584 } 14585 (void) uuid_unparse(summary->uuid, uuid); 14586 14587 #if defined(__arm__) || defined(__arm64__) 14588 tmpAddr = summary->text_exec_address; 14589 tmpSize = summary->text_exec_size; 14590 #else 14591 tmpAddr = summary->address; 14592 tmpSize = summary->size; 14593 #endif 14594 if (kPrintKextsUnslide & flags) { 14595 tmpAddr = ml_static_unslide(tmpAddr); 14596 } 14597 (*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n", 14598 (kPrintKextsTerse & flags) ? "" : " ", 14599 summary->name, version, uuid, 14600 tmpAddr, tmpAddr + tmpSize - 1); 14601 14602 if (kPrintKextsTerse & flags) { 14603 return; 14604 } 14605 14606 /* print dependency info */ 14607 for (kmod_ref = (kmod_reference_t *) summary->reference_list; 14608 kmod_ref; 14609 kmod_ref = kmod_ref->next) { 14610 kmod_info_t * rinfo; 14611 14612 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) { 14613 (*printf_func)(" kmod dependency scan stopped " 14614 "due to missing dependency page: %p\n", 14615 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref); 14616 break; 14617 } 14618 rinfo = kmod_ref->info; 14619 14620 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) { 14621 (*printf_func)(" kmod dependency scan stopped " 14622 "due to missing kmod page: %p\n", 14623 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo); 14624 break; 14625 } 14626 14627 if (!rinfo->address) { 14628 continue; // skip fake entries for built-ins 14629 } 14630 14631 dependencySummary = findSummary(rinfo->id); 14632 uuid[0] = 0x00; 14633 tmpAddr = rinfo->address; 14634 tmpSize = rinfo->size; 14635 if (dependencySummary) { 14636 (void) uuid_unparse(dependencySummary->uuid, uuid); 14637 #if defined(__arm__) || defined(__arm64__) 14638 tmpAddr = dependencySummary->text_exec_address; 14639 tmpSize = dependencySummary->text_exec_size; 14640 #endif 14641 } 14642 14643 if (kPrintKextsUnslide & flags) { 14644 tmpAddr = ml_static_unslide(tmpAddr); 14645 } 14646 (*printf_func)(" dependency: %s(%s)[%s]@%p->%p\n", 14647 rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1); 14648 } 14649 return; 14650 } 14651 14652 14653 #if !defined(__arm__) && !defined(__arm64__) 14654 /******************************************************************************* 14655 * substitute() looks at an input string (a pointer within a larger buffer) 14656 * for a match to a substring, and on match it writes the marker & substitution 14657 * character to an output string, updating the scan (from) and 14658 * output (to) indexes as appropriate. 14659 *******************************************************************************/ 14660 static int substitute( 14661 const char * scan_string, 14662 char * string_out, 14663 uint32_t * to_index, 14664 uint32_t * from_index, 14665 const char * substring, 14666 char marker, 14667 char substitution); 14668 14669 /* string_out must be at least KMOD_MAX_NAME bytes. 14670 */ 14671 static int 14672 substitute( 14673 const char * scan_string, 14674 char * string_out, 14675 uint32_t * to_index, 14676 uint32_t * from_index, 14677 const char * substring, 14678 char marker, 14679 char substitution) 14680 { 14681 size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1); 14682 14683 /* On a substring match, append the marker (if there is one) and then 14684 * the substitution character, updating the output (to) index accordingly. 14685 * Then update the input (from) length by the length of the substring 14686 * that got replaced. 14687 */ 14688 if (!strncmp(scan_string, substring, substring_length)) { 14689 if (marker) { 14690 string_out[(*to_index)++] = marker; 14691 } 14692 string_out[(*to_index)++] = substitution; 14693 (*from_index) += substring_length; 14694 return 1; 14695 } 14696 return 0; 14697 } 14698 14699 /******************************************************************************* 14700 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least 14701 * KMOD_MAX_NAME characters and performs various substitutions of common 14702 * prefixes & substrings as defined by tables in kext_panic_report.h. 14703 *******************************************************************************/ 14704 static void compactIdentifier( 14705 const char * identifier, 14706 char * identifier_out, 14707 char ** identifier_out_end); 14708 14709 static void 14710 compactIdentifier( 14711 const char * identifier, 14712 char * identifier_out, 14713 char ** identifier_out_end) 14714 { 14715 uint32_t from_index, to_index; 14716 uint32_t scan_from_index = 0; 14717 uint32_t scan_to_index = 0; 14718 subs_entry_t * subs_entry = NULL; 14719 int did_sub = 0; 14720 14721 from_index = to_index = 0; 14722 identifier_out[0] = '\0'; 14723 14724 /* Replace certain identifier prefixes with shorter @+character sequences. 14725 * Check the return value of substitute() so we only replace the prefix. 14726 */ 14727 for (subs_entry = &kext_identifier_prefix_subs[0]; 14728 subs_entry->substring && !did_sub; 14729 subs_entry++) { 14730 did_sub = substitute(identifier, identifier_out, 14731 &scan_to_index, &scan_from_index, 14732 subs_entry->substring, /* marker */ '\0', subs_entry->substitute); 14733 } 14734 did_sub = 0; 14735 14736 /* Now scan through the identifier looking for the common substrings 14737 * and replacing them with shorter !+character sequences via substitute(). 14738 */ 14739 for (/* see above */; 14740 scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index]; 14741 /* see loop */) { 14742 const char * scan_string = &identifier[scan_from_index]; 14743 14744 did_sub = 0; 14745 14746 if (scan_from_index) { 14747 for (subs_entry = &kext_identifier_substring_subs[0]; 14748 subs_entry->substring && !did_sub; 14749 subs_entry++) { 14750 did_sub = substitute(scan_string, identifier_out, 14751 &scan_to_index, &scan_from_index, 14752 subs_entry->substring, '!', subs_entry->substitute); 14753 } 14754 } 14755 14756 /* If we didn't substitute, copy the input character to the output. 14757 */ 14758 if (!did_sub) { 14759 identifier_out[scan_to_index++] = identifier[scan_from_index++]; 14760 } 14761 } 14762 14763 identifier_out[scan_to_index] = '\0'; 14764 if (identifier_out_end) { 14765 *identifier_out_end = &identifier_out[scan_to_index]; 14766 } 14767 14768 return; 14769 } 14770 #endif /* !defined(__arm__) && !defined(__arm64__) */ 14771 14772 /******************************************************************************* 14773 * assemble_identifier_and_version() adds to a string buffer a compacted 14774 * bundle identifier followed by a version string. 14775 *******************************************************************************/ 14776 14777 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length. 14778 */ 14779 static size_t assemble_identifier_and_version( 14780 kmod_info_t * kmod_info, 14781 char * identPlusVers, 14782 size_t bufSize); 14783 14784 static size_t 14785 assemble_identifier_and_version( 14786 kmod_info_t * kmod_info, 14787 char * identPlusVers, 14788 size_t bufSize) 14789 { 14790 size_t result = 0; 14791 14792 #if defined(__arm__) || defined(__arm64__) 14793 result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME); 14794 #else 14795 compactIdentifier(kmod_info->name, identPlusVers, NULL); 14796 result = strnlen(identPlusVers, KMOD_MAX_NAME - 1); 14797 #endif 14798 identPlusVers[result++] = '\t'; // increment for real char 14799 identPlusVers[result] = '\0'; // don't increment for nul char 14800 result = strlcat(identPlusVers, kmod_info->version, bufSize); 14801 if (result >= bufSize) { 14802 identPlusVers[bufSize - 1] = '\0'; 14803 result = bufSize - 1; 14804 } 14805 14806 return result; 14807 } 14808 14809 /******************************************************************************* 14810 * Assumes sKextLock is held. 14811 *******************************************************************************/ 14812 /* static */ 14813 int 14814 OSKext::saveLoadedKextPanicListTyped( 14815 const char * prefix, 14816 int invertFlag, 14817 int libsFlag, 14818 char * paniclist, 14819 uint32_t list_size) 14820 { 14821 int result = -1; 14822 unsigned int count, i; 14823 14824 count = sLoadedKexts->getCount(); 14825 if (!count) { 14826 goto finish; 14827 } 14828 14829 i = count - 1; 14830 do { 14831 OSObject * rawKext = sLoadedKexts->getObject(i); 14832 OSKext * theKext = OSDynamicCast(OSKext, rawKext); 14833 int match; 14834 size_t identPlusVersLength; 14835 size_t tempLen; 14836 char identPlusVers[2 * KMOD_MAX_NAME]; 14837 14838 if (!rawKext) { 14839 printf("OSKext::saveLoadedKextPanicListTyped - " 14840 "NULL kext in loaded kext list; continuing\n"); 14841 continue; 14842 } 14843 14844 if (!theKext) { 14845 printf("OSKext::saveLoadedKextPanicListTyped - " 14846 "Kext type cast failed in loaded kext list; continuing\n"); 14847 continue; 14848 } 14849 14850 /* Skip all built-in kexts. 14851 */ 14852 if (theKext->isKernelComponent()) { 14853 continue; 14854 } 14855 14856 kmod_info_t * kmod_info = theKext->kmod_info; 14857 14858 /* Filter for kmod name (bundle identifier). 14859 */ 14860 match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME)); 14861 if ((match && invertFlag) || (!match && !invertFlag)) { 14862 continue; 14863 } 14864 14865 /* Filter for libraries (kexts that have a compatible version). 14866 */ 14867 if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) || 14868 (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) { 14869 continue; 14870 } 14871 14872 if (!kmod_info || 14873 !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) { 14874 printf("kext scan stopped due to missing kmod_info page: %p\n", 14875 kmod_info); 14876 goto finish; 14877 } 14878 14879 identPlusVersLength = assemble_identifier_and_version(kmod_info, 14880 identPlusVers, 14881 sizeof(identPlusVers)); 14882 if (!identPlusVersLength) { 14883 printf("error saving loaded kext info\n"); 14884 goto finish; 14885 } 14886 14887 /* make sure everything fits and we null terminate. 14888 */ 14889 tempLen = strlcat(paniclist, identPlusVers, list_size); 14890 if (tempLen >= list_size) { 14891 // panic list is full, keep it and null terminate 14892 paniclist[list_size - 1] = 0x00; 14893 result = 0; 14894 goto finish; 14895 } 14896 tempLen = strlcat(paniclist, "\n", list_size); 14897 if (tempLen >= list_size) { 14898 // panic list is full, keep it and null terminate 14899 paniclist[list_size - 1] = 0x00; 14900 result = 0; 14901 goto finish; 14902 } 14903 } while (i--); 14904 14905 result = 0; 14906 finish: 14907 14908 return result; 14909 } 14910 14911 /********************************************************************* 14912 *********************************************************************/ 14913 /* static */ 14914 void 14915 OSKext::saveLoadedKextPanicList(void) 14916 { 14917 char * newlist = NULL; 14918 uint32_t newlist_size = 0; 14919 14920 newlist_size = KEXT_PANICLIST_SIZE; 14921 newlist = (char *)kalloc_data_tag(newlist_size, 14922 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 14923 14924 if (!newlist) { 14925 OSKextLog(/* kext */ NULL, 14926 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 14927 "Couldn't allocate kext panic log buffer."); 14928 goto finish; 14929 } 14930 14931 newlist[0] = '\0'; 14932 14933 // non-"com.apple." kexts 14934 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1, 14935 /* libs? */ -1, newlist, newlist_size) != 0) { 14936 goto finish; 14937 } 14938 // "com.apple." nonlibrary kexts 14939 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 14940 /* libs? */ 0, newlist, newlist_size) != 0) { 14941 goto finish; 14942 } 14943 // "com.apple." library kexts 14944 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 14945 /* libs? */ 1, newlist, newlist_size) != 0) { 14946 goto finish; 14947 } 14948 14949 if (loaded_kext_paniclist) { 14950 kheap_free(KHEAP_DATA_BUFFERS, loaded_kext_paniclist, 14951 loaded_kext_paniclist_size); 14952 } 14953 loaded_kext_paniclist = newlist; 14954 newlist = NULL; 14955 loaded_kext_paniclist_size = newlist_size; 14956 14957 finish: 14958 if (newlist) { 14959 kfree_data(newlist, newlist_size); 14960 } 14961 return; 14962 } 14963 14964 /********************************************************************* 14965 * Assumes sKextLock is held. 14966 *********************************************************************/ 14967 void 14968 OSKext::savePanicString(bool isLoading) 14969 { 14970 u_long len; 14971 14972 if (!kmod_info) { 14973 return; // do not goto finish here b/c of lock 14974 } 14975 14976 len = assemble_identifier_and_version( kmod_info, 14977 (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf, 14978 (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf)); 14979 if (!len) { 14980 printf("error saving unloaded kext info\n"); 14981 goto finish; 14982 } 14983 14984 if (isLoading) { 14985 last_loaded_strlen = len; 14986 last_loaded_address = (void *)kmod_info->address; 14987 last_loaded_size = kmod_info->size; 14988 clock_get_uptime(&last_loaded_timestamp); 14989 } else { 14990 last_unloaded_strlen = len; 14991 last_unloaded_address = (void *)kmod_info->address; 14992 last_unloaded_size = kmod_info->size; 14993 clock_get_uptime(&last_unloaded_timestamp); 14994 } 14995 14996 finish: 14997 return; 14998 } 14999 15000 /********************************************************************* 15001 *********************************************************************/ 15002 /* static */ 15003 void 15004 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...)) 15005 { 15006 if (last_loaded_strlen) { 15007 printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n", 15008 AbsoluteTime_to_scalar(&last_loaded_timestamp), 15009 last_loaded_strlen, last_loaded_str_buf, 15010 last_loaded_address, last_loaded_size); 15011 } 15012 15013 if (last_unloaded_strlen) { 15014 printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n", 15015 AbsoluteTime_to_scalar(&last_unloaded_timestamp), 15016 last_unloaded_strlen, last_unloaded_str_buf, 15017 last_unloaded_address, last_unloaded_size); 15018 } 15019 15020 printf_func("loaded kexts:\n"); 15021 if (loaded_kext_paniclist && 15022 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) && 15023 loaded_kext_paniclist[0]) { 15024 printf_func("%.*s", 15025 strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size), 15026 loaded_kext_paniclist); 15027 } else { 15028 printf_func("(none)\n"); 15029 } 15030 return; 15031 } 15032 15033 /********************************************************************* 15034 * Assumes sKextLock is held. 15035 *********************************************************************/ 15036 /* static */ 15037 void 15038 OSKext::updateLoadedKextSummaries(void) 15039 { 15040 kern_return_t result = KERN_FAILURE; 15041 OSKextLoadedKextSummaryHeader *summaryHeader = NULL; 15042 OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL; 15043 OSKext *aKext; 15044 vm_map_offset_t start, end; 15045 size_t summarySize = 0; 15046 size_t size; 15047 u_int count; 15048 u_int maxKexts; 15049 u_int i, j; 15050 OSKextActiveAccount * accountingList; 15051 OSKextActiveAccount * prevAccountingList; 15052 uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount; 15053 15054 prevAccountingList = NULL; 15055 prevAccountingListCount = 0; 15056 15057 #if DEVELOPMENT || DEBUG 15058 if (IORecursiveLockHaveLock(sKextLock) == false) { 15059 panic("sKextLock must be held"); 15060 } 15061 #endif 15062 15063 IOLockLock(sKextSummariesLock); 15064 15065 count = sLoadedKexts->getCount(); 15066 for (i = 0, maxKexts = 0; i < count; ++i) { 15067 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 15068 maxKexts += (aKext && aKext->isExecutable()); 15069 } 15070 15071 if (!maxKexts) { 15072 goto finish; 15073 } 15074 if (maxKexts < kOSKextTypicalLoadCount) { 15075 maxKexts = kOSKextTypicalLoadCount; 15076 } 15077 15078 /* Calculate the size needed for the new summary headers. 15079 */ 15080 15081 size = sizeof(*gLoadedKextSummaries); 15082 size += maxKexts * sizeof(*gLoadedKextSummaries->summaries); 15083 size = round_page(size); 15084 15085 if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) { 15086 if (gLoadedKextSummaries) { 15087 kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize); 15088 gLoadedKextSummaries = NULL; 15089 gLoadedKextSummariesTimestamp = mach_absolute_time(); 15090 sLoadedKextSummariesAllocSize = 0; 15091 } 15092 result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, VM_KERN_MEMORY_OSKEXT); 15093 if (result != KERN_SUCCESS) { 15094 goto finish; 15095 } 15096 summaryHeader = summaryHeaderAlloc; 15097 summarySize = size; 15098 } else { 15099 summaryHeader = gLoadedKextSummaries; 15100 summarySize = sLoadedKextSummariesAllocSize; 15101 15102 start = (vm_map_offset_t) summaryHeader; 15103 end = start + summarySize; 15104 result = vm_map_protect(kernel_map, 15105 start, 15106 end, 15107 VM_PROT_DEFAULT, 15108 FALSE); 15109 if (result != KERN_SUCCESS) { 15110 goto finish; 15111 } 15112 } 15113 15114 /* Populate the summary header. 15115 */ 15116 15117 bzero(summaryHeader, summarySize); 15118 summaryHeader->version = kOSKextLoadedKextSummaryVersion; 15119 summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary); 15120 15121 /* Populate each kext summary. 15122 */ 15123 15124 count = sLoadedKexts->getCount(); 15125 accountingListAlloc = 0; 15126 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 15127 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 15128 if (!aKext || !aKext->isExecutable()) { 15129 continue; 15130 } 15131 15132 aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]); 15133 summaryHeader->numSummaries++; 15134 accountingListAlloc++; 15135 } 15136 15137 accountingList = IONew(typeof(accountingList[0]), accountingListAlloc); 15138 accountingListCount = 0; 15139 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 15140 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 15141 if (!aKext || !aKext->isExecutable()) { 15142 continue; 15143 } 15144 15145 OSKextActiveAccount activeAccount; 15146 aKext->updateActiveAccount(&activeAccount); 15147 // order by address 15148 for (idx = 0; idx < accountingListCount; idx++) { 15149 if (activeAccount.address < accountingList[idx].address) { 15150 break; 15151 } 15152 } 15153 bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0])); 15154 accountingList[idx] = activeAccount; 15155 accountingListCount++; 15156 } 15157 assert(accountingListCount == accountingListAlloc); 15158 /* Write protect the buffer and move it into place. 15159 */ 15160 15161 start = (vm_map_offset_t) summaryHeader; 15162 end = start + summarySize; 15163 15164 result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE); 15165 if (result != KERN_SUCCESS) { 15166 goto finish; 15167 } 15168 15169 gLoadedKextSummaries = summaryHeader; 15170 gLoadedKextSummariesTimestamp = mach_absolute_time(); 15171 sLoadedKextSummariesAllocSize = summarySize; 15172 summaryHeaderAlloc = NULL; 15173 15174 /* Call the magic breakpoint function through a static function pointer so 15175 * the compiler can't optimize the function away. 15176 */ 15177 if (sLoadedKextSummariesUpdated) { 15178 (*sLoadedKextSummariesUpdated)(); 15179 } 15180 15181 IOSimpleLockLock(sKextAccountsLock); 15182 prevAccountingList = sKextAccounts; 15183 prevAccountingListCount = sKextAccountsCount; 15184 sKextAccounts = accountingList; 15185 sKextAccountsCount = accountingListCount; 15186 IOSimpleLockUnlock(sKextAccountsLock); 15187 15188 finish: 15189 IOLockUnlock(sKextSummariesLock); 15190 15191 /* If we had to allocate a new buffer but failed to generate the summaries, 15192 * free that now. 15193 */ 15194 if (summaryHeaderAlloc) { 15195 kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize); 15196 } 15197 if (prevAccountingList) { 15198 IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount); 15199 } 15200 15201 return; 15202 } 15203 15204 /********************************************************************* 15205 *********************************************************************/ 15206 void 15207 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary) 15208 { 15209 OSSharedPtr<OSData> uuid; 15210 15211 strlcpy(summary->name, getIdentifierCString(), 15212 sizeof(summary->name)); 15213 15214 uuid = copyUUID(); 15215 if (uuid) { 15216 memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid)); 15217 } 15218 15219 if (flags.builtin) { 15220 // this value will stop lldb from parsing the mach-o header 15221 // summary->address = UINT64_MAX; 15222 // summary->size = 0; 15223 summary->address = kmod_info->address; 15224 summary->size = kmod_info->size; 15225 } else { 15226 summary->address = kmod_info->address; 15227 summary->size = kmod_info->size; 15228 } 15229 summary->version = getVersion(); 15230 summary->loadTag = kmod_info->id; 15231 summary->flags = 0; 15232 summary->reference_list = (uint64_t) kmod_info->reference_list; 15233 15234 summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size); 15235 if (summary->text_exec_address == 0) { 15236 // Fallback to __TEXT 15237 summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size); 15238 } 15239 return; 15240 } 15241 15242 /********************************************************************* 15243 *********************************************************************/ 15244 15245 void 15246 OSKext::updateActiveAccount(OSKextActiveAccount *accountp) 15247 { 15248 kernel_mach_header_t *hdr = NULL; 15249 kernel_segment_command_t *seg = NULL; 15250 15251 bzero(accountp, sizeof(*accountp)); 15252 15253 hdr = (kernel_mach_header_t *)kmod_info->address; 15254 if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) { 15255 /* 15256 * If this kext supports split segments (or is in a new 15257 * MH_FILESET kext collection), use the first 15258 * executable segment as the range for instructions 15259 * (and thus for backtracing. 15260 */ 15261 for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) { 15262 if (seg->initprot & VM_PROT_EXECUTE) { 15263 break; 15264 } 15265 } 15266 } 15267 if (seg) { 15268 accountp->address = seg->vmaddr; 15269 if (accountp->address) { 15270 accountp->address_end = seg->vmaddr + seg->vmsize; 15271 } 15272 } else { 15273 /* For non-split kexts and for kexts without executable 15274 * segments, just use the kmod_info range (as the kext 15275 * is either all in one range or should not show up in 15276 * instruction backtraces). 15277 */ 15278 accountp->address = kmod_info->address; 15279 if (accountp->address) { 15280 accountp->address_end = kmod_info->address + kmod_info->size; 15281 } 15282 } 15283 15284 accountp->account = this->account; 15285 } 15286 15287 bool 15288 OSKext::isDriverKit(void) 15289 { 15290 OSString *bundleType; 15291 15292 if (infoDict) { 15293 bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)); 15294 if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) { 15295 return TRUE; 15296 } 15297 } 15298 return FALSE; 15299 } 15300 15301 bool 15302 OSKext::isInFileset(void) 15303 { 15304 if (!kmod_info) { 15305 goto check_prelinked; 15306 } 15307 15308 if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) { 15309 return true; 15310 } 15311 15312 check_prelinked: 15313 if (isPrelinked()) { 15314 /* 15315 * If we haven't setup kmod_info yet, but we know 15316 * we're loading a prelinked kext in an MH_FILESET KC, 15317 * then return true 15318 */ 15319 kc_format_t kc_format; 15320 if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) { 15321 return true; 15322 } 15323 } 15324 return false; 15325 } 15326 15327 bool 15328 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg) 15329 { 15330 kern_return_t result; 15331 if (!super::init()) { 15332 return false; 15333 } 15334 if (seg == nullptr) { 15335 return false; 15336 } 15337 result = kmem_alloc_pageable(kernel_map, (vm_offset_t *)&data, seg->vmsize, VM_KERN_MEMORY_KEXT); 15338 if (result != KERN_SUCCESS) { 15339 return false; 15340 } 15341 memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize); 15342 savedSegment = seg; 15343 vmsize = seg->vmsize; 15344 vmaddr = seg->vmaddr; 15345 return true; 15346 } 15347 15348 OSSharedPtr<OSKextSavedMutableSegment> 15349 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg) 15350 { 15351 OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>(); 15352 if (me && !me->initWithSegment(seg)) { 15353 return nullptr; 15354 } 15355 return me; 15356 } 15357 15358 void 15359 OSKextSavedMutableSegment::free(void) 15360 { 15361 if (data) { 15362 kmem_free(kernel_map, (vm_offset_t)data, vmsize); 15363 } 15364 } 15365 15366 vm_offset_t 15367 OSKextSavedMutableSegment::getVMAddr() const 15368 { 15369 return vmaddr; 15370 } 15371 15372 vm_offset_t 15373 OSKextSavedMutableSegment::getVMSize() const 15374 { 15375 return vmsize; 15376 } 15377 15378 OSReturn 15379 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg) 15380 { 15381 if (seg != savedSegment) { 15382 return kOSKextReturnInvalidArgument; 15383 } 15384 if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) { 15385 return kOSKextReturnInvalidArgument; 15386 } 15387 memcpy((void *)seg->vmaddr, data, vmsize); 15388 return kOSReturnSuccess; 15389 } 15390 15391 extern "C" kern_return_t 15392 OSKextSetReceiptQueried(void) 15393 { 15394 OSKextLog(/* kext */ NULL, 15395 kOSKextLogStepLevel | kOSKextLogGeneralFlag, 15396 "Setting kext receipt as queried"); 15397 15398 IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue); 15399 return KERN_SUCCESS; 15400 } 15401 15402 extern "C" const vm_allocation_site_t * 15403 OSKextGetAllocationSiteForCaller(uintptr_t address) 15404 { 15405 OSKextActiveAccount * active; 15406 vm_allocation_site_t * site; 15407 vm_allocation_site_t * releasesite; 15408 15409 uint32_t baseIdx; 15410 uint32_t lim; 15411 #if __has_feature(ptrauth_calls) 15412 address = (uintptr_t)VM_KERNEL_STRIP_PTR(address); 15413 #endif /* __has_feature(ptrauth_calls) */ 15414 15415 IOSimpleLockLock(sKextAccountsLock); 15416 site = releasesite = NULL; 15417 15418 // bsearch sKextAccounts list 15419 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 15420 active = &sKextAccounts[baseIdx + (lim >> 1)]; 15421 if ((address >= active->address) && (address < active->address_end)) { 15422 site = &active->account->site; 15423 if (!site->tag) { 15424 vm_tag_alloc_locked(site, &releasesite); 15425 } 15426 break; 15427 } else if (address > active->address) { 15428 // move right 15429 baseIdx += (lim >> 1) + 1; 15430 lim--; 15431 } 15432 // else move left 15433 } 15434 IOSimpleLockUnlock(sKextAccountsLock); 15435 if (releasesite) { 15436 kern_allocation_name_release(releasesite); 15437 } 15438 15439 return site; 15440 } 15441 15442 #if DEVELOPMENT || DEBUG 15443 extern "C" void 15444 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *)) 15445 { 15446 OSKextActiveAccount * active; 15447 15448 uint32_t baseIdx; 15449 uint32_t lim; 15450 #if __has_feature(ptrauth_calls) 15451 address = (uintptr_t)VM_KERNEL_STRIP_PTR(address); 15452 #endif /* __has_feature(ptrauth_calls) */ 15453 15454 IOSimpleLockLock(sKextAccountsLock); 15455 15456 // bsearch sKextAccounts list 15457 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 15458 active = &sKextAccounts[baseIdx + (lim >> 1)]; 15459 if ((address >= active->address) && (address < active->address_end)) { 15460 cb(&active->account->task_refgrp); 15461 break; 15462 } else if (address > active->address) { 15463 // move right 15464 baseIdx += (lim >> 1) + 1; 15465 lim--; 15466 } 15467 // else move left 15468 } 15469 IOSimpleLockUnlock(sKextAccountsLock); 15470 } 15471 #endif /* DEVELOPMENT || DEBUG */ 15472 15473 extern "C" uint32_t 15474 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen) 15475 { 15476 OSKextAccount * account = (typeof(account))site; 15477 const char * kname; 15478 15479 if (name) { 15480 if (account->kext) { 15481 kname = account->kext->getIdentifierCString(); 15482 } else { 15483 kname = "<>"; 15484 } 15485 strlcpy(name, kname, namelen); 15486 } 15487 15488 return account->loadTag; 15489 } 15490 15491 extern "C" void 15492 OSKextFreeSite(vm_allocation_site_t * site) 15493 { 15494 OSKextAccount * freeAccount = (typeof(freeAccount))site; 15495 IOFreeType(freeAccount, OSKextAccount); 15496 } 15497 15498 /********************************************************************* 15499 *********************************************************************/ 15500 15501 #if CONFIG_IMAGEBOOT 15502 int 15503 OSKextGetUUIDForName(const char *name, uuid_t uuid) 15504 { 15505 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name); 15506 if (!kext) { 15507 return 1; 15508 } 15509 15510 OSSharedPtr<OSData> uuid_data = kext->copyUUID(); 15511 if (uuid_data) { 15512 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t)); 15513 return 0; 15514 } 15515 15516 return 1; 15517 } 15518 #endif 15519 15520 static int 15521 sysctl_willuserspacereboot 15522 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 15523 { 15524 int new_value = 0, old_value = 0, changed = 0; 15525 int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed); 15526 if (error) { 15527 return error; 15528 } 15529 if (changed) { 15530 OSKext::willUserspaceReboot(); 15531 } 15532 return 0; 15533 } 15534 15535 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot, 15536 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 15537 NULL, 0, sysctl_willuserspacereboot, "I", ""); 15538