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 91 #if PRAGMA_MARK 92 #pragma mark External & Internal Function Protos 93 #endif 94 /********************************************************************* 95 *********************************************************************/ 96 extern "C" { 97 extern int IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize); 98 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize); 99 100 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */ 101 extern int dtrace_keep_kernel_symbols(void); 102 103 #if defined(__x86_64__) || defined(__i386__) 104 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide); 105 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers); 106 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size); 107 static void *allocate_kcfileset_map_entry_list(void); 108 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size); 109 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable); 110 int vnode_put(struct vnode *vp); 111 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size, 112 void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot); 113 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size); 114 void * ubc_getobject(struct vnode *vp, __unused int flags); 115 #endif //(__x86_64__) || defined(__i386__) 116 } 117 118 extern unsigned long gVirtBase; 119 extern unsigned long gPhysBase; 120 extern vm_map_t g_kext_map; 121 122 bool pageableKCloaded = false; 123 bool auxKCloaded = false; 124 bool resetAuxKCSegmentOnUnload = false; 125 126 extern boolean_t pageablekc_uuid_valid; 127 extern uuid_t pageablekc_uuid; 128 extern uuid_string_t pageablekc_uuid_string; 129 130 extern boolean_t auxkc_uuid_valid; 131 extern uuid_t auxkc_uuid; 132 extern uuid_string_t auxkc_uuid_string; 133 134 static OSReturn _OSKextCreateRequest( 135 const char * predicate, 136 OSSharedPtr<OSDictionary> & requestP); 137 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict); 138 static OSObject * _OSKextGetRequestArgument( 139 OSDictionary * requestDict, 140 const char * argName); 141 static bool _OSKextSetRequestArgument( 142 OSDictionary * requestDict, 143 const char * argName, 144 OSMetaClassBase * value); 145 template <typename T> 146 static T * _OSKextExtractPointer(OSValueObject<T *> * wrapper); 147 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper); 148 static OSReturn _OSDictionarySetCStringValue( 149 OSDictionary * dict, 150 const char * key, 151 const char * value); 152 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID); 153 #if CONFIG_KXLD 154 static bool _OSKextInPrelinkRebuildWindow(void); 155 #endif 156 157 // We really should add containsObject() & containsCString to OSCollection & subclasses. 158 // So few pad slots, though.... 159 static bool _OSArrayContainsCString(OSArray * array, const char * cString); 160 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code); 161 162 static const char *getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size); 163 164 /* Prelinked arm kexts do not have VM entries because the method we use to 165 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does 166 * not work on ARM. To get around that, we must free prelinked kext 167 * executables with ml_static_mfree() instead of kext_free(). 168 */ 169 #if __i386__ || __x86_64__ 170 #define VM_MAPPED_KEXTS 1 171 #define KASLR_KEXT_DEBUG 0 172 #define KASLR_IOREG_DEBUG 0 173 #elif __arm__ || __arm64__ 174 #define VM_MAPPED_KEXTS 0 175 #define KASLR_KEXT_DEBUG 0 176 #else 177 #error Unsupported architecture 178 #endif 179 180 #if PRAGMA_MARK 181 #pragma mark Constants & Macros 182 #endif 183 /********************************************************************* 184 * Constants & Macros 185 *********************************************************************/ 186 187 /* Use this number to create containers. 188 */ 189 #define kOSKextTypicalLoadCount (150) 190 #define kOSKextTypicalUpgradeCount (5) 191 192 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict. 193 * A loaded kext will no dependents or external retains will have 2 retains. 194 */ 195 #define kOSKextMinRetainCount (1) 196 #define kOSKextMinLoadedRetainCount (2) 197 198 #define kOSKextMaxDextLaunchedCount (~((uint32_t)0)) 199 #define KOSBundleDextUniqueIdentifierMaxStringLength (KOSBundleDextUniqueIdentifierMaxLength * 2 +1) 200 201 /********** 202 * Strings and substrings used in dependency resolution. 203 */ 204 #define APPLE_KEXT_PREFIX "com.apple." 205 #define KERNEL_LIB "com.apple.kernel" 206 207 #define PRIVATE_KPI "com.apple.kpi.private" 208 209 /* Version for compatbility pseudokexts (com.apple.kernel.*), 210 * compatible back to v6.0. 211 */ 212 #define KERNEL6_LIB "com.apple.kernel.6.0" 213 #define KERNEL6_VERSION "7.9.9" 214 215 #define KERNEL_LIB_PREFIX "com.apple.kernel." 216 #define KPI_LIB_PREFIX "com.apple.kpi." 217 218 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0) 219 220 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes 221 #define MINIMUM_WAKEUP_SECONDS (30) 222 223 /********************************************************************* 224 * infoDict keys for internally-stored data. Saves on ivar slots for 225 * objects we don't keep around past boot time or during active load. 226 *********************************************************************/ 227 228 /* A usable, uncompressed file is stored under this key. 229 */ 230 #define _kOSKextExecutableKey "_OSKextExecutable" 231 232 /* An indirect reference to the executable file from an mkext 233 * is stored under this key. 234 */ 235 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference" 236 237 /* If the file is contained in a larger buffer laid down by the booter or 238 * sent from user space, the OSKext stores that OSData under this key so that 239 * references are properly tracked. This is always an mkext, right now. 240 */ 241 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData" 242 243 #define OS_LOG_HDR_VERSION 1 244 #define NUM_OS_LOG_SECTIONS 3 245 246 #define OS_LOG_SECT_IDX 0 247 #define CSTRING_SECT_IDX 1 248 #define ASAN_CSTRING_SECT_IDX 2 249 250 #if PRAGMA_MARK 251 #pragma mark Typedefs 252 #endif 253 /********************************************************************* 254 * Typedefs 255 *********************************************************************/ 256 257 /********************************************************************* 258 * osLogDataHeaderRef describes the header information of an OSData 259 * object that is returned when querying for kOSBundleLogStringsKey. 260 * We currently return information regarding 2 sections - os_log and 261 * cstring. In the case that the os_log section doesn't exist, we just 262 * return an offset and length of 0 for that section. 263 *********************************************************************/ 264 typedef struct osLogDataHeader { 265 uint32_t version; 266 uint32_t sect_count; 267 struct { 268 uint32_t sect_offset; 269 uint32_t sect_size; 270 } sections[0]; 271 } osLogDataHeaderRef; 272 273 /********************************************************************* 274 * MkextEntryRef describes the contents of an OSData object 275 * referencing a file entry from an mkext so that we can uncompress 276 * (if necessary) and extract it on demand. 277 * 278 * It contains the mkextVersion in case we ever wind up supporting 279 * multiple mkext formats. Mkext format 1 is officially retired as of 280 * Snow Leopard. 281 *********************************************************************/ 282 typedef struct MkextEntryRef { 283 mkext_basic_header * mkext; // beginning of whole mkext file 284 void * fileinfo;// mkext2_file_entry or equiv; see mkext.h 285 } MkextEntryRef; 286 287 #if PRAGMA_MARK 288 #pragma mark Global and static Module Variables 289 #endif 290 /********************************************************************* 291 * Global & static variables, used to keep track of kexts. 292 *********************************************************************/ 293 294 static bool sPrelinkBoot = false; 295 static bool sSafeBoot = false; 296 static bool sKeepSymbols = false; 297 static bool sPanicOnKCMismatch = false; 298 static bool sOSKextWasResetAfterUserspaceReboot = false; 299 300 /********************************************************************* 301 * sKextLock is the principal lock for OSKext, and guards all static 302 * and global variables not owned by other locks (declared further 303 * below). It must be taken by any entry-point method or function, 304 * including internal functions called on scheduled threads. 305 * 306 * sKextLock and sKextInnerLock are recursive due to multiple functions 307 * that are called both externally and internally. The other locks are 308 * nonrecursive. 309 * 310 * Which locks are taken depends on what they protect, but if more than 311 * one must be taken, they must always be locked in this order 312 * (and unlocked in reverse order) to prevent deadlocks: 313 * 314 * 1. sKextLock 315 * 2. sKextInnerLock 316 * 3. sKextSummariesLock 317 * 4. sKextLoggingLock 318 */ 319 static IORecursiveLock * sKextLock = NULL; 320 321 static OSSharedPtr<OSDictionary> sKextsByID; 322 static OSSharedPtr<OSDictionary> sExcludeListByID; 323 static OSKextVersion sExcludeListVersion = 0; 324 static OSSharedPtr<OSArray> sLoadedKexts; 325 static OSSharedPtr<OSDictionary> sNonLoadableKextsByID; 326 static OSSharedPtr<OSArray> sUnloadedPrelinkedKexts; 327 static OSSharedPtr<OSArray> sLoadedDriverKitKexts; 328 static OSSharedPtr<OSDictionary> sDriverKitToUpgradeByID; 329 330 // Requests to the IOKit daemon waiting to be picked up. 331 static OSSharedPtr<OSArray> sKernelRequests; 332 // Identifier of kext load requests in sKernelRequests 333 static OSSharedPtr<OSSet> sPostedKextLoadIdentifiers; 334 static OSSharedPtr<OSArray> sRequestCallbackRecords; 335 336 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel 337 static OSSharedPtr<OSSet> sAllKextLoadIdentifiers; 338 #if CONFIG_KXLD 339 static KXLDContext * sKxldContext = NULL; 340 #endif 341 static uint32_t sNextLoadTag = 0; 342 static uint32_t sNextRequestTag = 0; 343 344 static bool sUserLoadsActive = false; 345 static bool sIOKitDaemonActive = false; 346 static bool sDeferredLoadSucceeded = false; 347 static bool sConsiderUnloadsExecuted = false; 348 349 #if NO_KEXTD 350 static bool sKernelRequestsEnabled = false; 351 #else 352 static bool sKernelRequestsEnabled = true; 353 #endif 354 static bool sLoadEnabled = true; 355 static bool sUnloadEnabled = true; 356 357 /********************************************************************* 358 * Stuff for the OSKext representing the kernel itself. 359 **********/ 360 static OSKext * sKernelKext = NULL; 361 362 /* Load Tag IDs used by statically loaded binaries (e.g, the kernel itself). */ 363 enum : uint32_t { 364 kOSKextKernelLoadTag = 0, 365 kOSKextLoadTagCount 366 }; 367 368 /* Set up a fake kmod_info struct for the kernel. 369 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP() 370 * before OSKext is initialized; that call only needs the name 371 * and address to be set correctly. 372 * 373 * We don't do much else with the kerne's kmod_info; we never 374 * put it into the kmod list, never adjust the reference count, 375 * and never have kernel components reference it. 376 * For that matter, we don't do much with kmod_info structs 377 * at all anymore! We just keep them filled in for gdb and 378 * binary compability. 379 */ 380 kmod_info_t g_kernel_kmod_info = { 381 .next = NULL, 382 .info_version = KMOD_INFO_VERSION, 383 .id = kOSKextKernelLoadTag, // loadTag: kernel is always 0 384 .name = kOSKextKernelIdentifier,// bundle identifier 385 .version = "0", // filled in in OSKext::initialize() 386 .reference_count = -1, // never adjusted; kernel never unloads 387 .reference_list = NULL, 388 .address = 0, 389 .size = 0, // filled in in OSKext::initialize() 390 .hdr_size = 0, 391 .start = NULL, 392 .stop = NULL 393 }; 394 395 396 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */ 397 398 kmod_info_t invalid_kmod_info = { 399 .next = NULL, 400 .info_version = KMOD_INFO_VERSION, 401 .id = UINT32_MAX, 402 .name = "invalid", 403 .version = "0", 404 .reference_count = -1, 405 .reference_list = NULL, 406 .address = 0, 407 .size = 0, 408 .hdr_size = 0, 409 .start = NULL, 410 .stop = NULL 411 }; 412 413 extern "C" { 414 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c, 415 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s, 416 // misc_protos.h, db_low_trace.c, kgmacros 417 // 'kmod' is a holdover from the old kmod system, we can't rename it. 418 kmod_info_t * kmod = NULL; 419 420 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE) 421 422 423 static char * loaded_kext_paniclist = NULL; 424 static uint32_t loaded_kext_paniclist_size = 0; 425 426 AbsoluteTime last_loaded_timestamp; 427 static char last_loaded_str_buf[2 * KMOD_MAX_NAME]; 428 static u_long last_loaded_strlen = 0; 429 static void * last_loaded_address = NULL; 430 static u_long last_loaded_size = 0; 431 432 AbsoluteTime last_unloaded_timestamp; 433 static char last_unloaded_str_buf[2 * KMOD_MAX_NAME]; 434 static u_long last_unloaded_strlen = 0; 435 static void * last_unloaded_address = NULL; 436 static u_long last_unloaded_size = 0; 437 438 // Statically linked kmods described by several mach-o sections: 439 // 440 // kPrelinkInfoSegment:kBuiltinInfoSection 441 // Array of pointers to kmod_info_t structs. 442 // 443 // kPrelinkInfoSegment:kBuiltinInfoSection 444 // Array of pointers to an embedded mach-o header. 445 // 446 // __DATA:kBuiltinInitSection, kBuiltinTermSection 447 // Structors for all kmods. Has to be filtered by proc address. 448 // 449 450 static uint32_t gBuiltinKmodsCount; 451 static kernel_section_t * gBuiltinKmodsSectionInfo; 452 static kernel_section_t * gBuiltinKmodsSectionStart; 453 454 const OSSymbol * gIOSurfaceIdentifier; 455 vm_tag_t gIOSurfaceTag; 456 457 /********************************************************************* 458 * sKextInnerLock protects against cross-calls with IOService and 459 * IOCatalogue, and owns the variables declared immediately below. 460 * 461 * Note that sConsiderUnloadsExecuted above belongs to sKextLock! 462 * 463 * When both sKextLock and sKextInnerLock need to be taken, 464 * always lock sKextLock first and unlock it second. Never take both 465 * locks in an entry point to OSKext; if you need to do so, you must 466 * spawn an independent thread to avoid potential deadlocks for threads 467 * calling into OSKext. 468 **********/ 469 static IORecursiveLock * sKextInnerLock = NULL; 470 471 #if XNU_TARGET_OS_OSX 472 static bool sAutounloadEnabled = true; 473 #endif 474 static bool sConsiderUnloadsCalled = false; 475 static bool sConsiderUnloadsPending = false; 476 477 static unsigned int sConsiderUnloadDelay = 60; // seconds 478 static thread_call_t sUnloadCallout = NULL; 479 #if CONFIG_KXLD 480 static thread_call_t sDestroyLinkContextThread = NULL; // one-shot, one-at-a-time thread 481 #endif // CONFIG_KXLD 482 static bool sSystemSleep = false; // true when system going to sleep 483 static AbsoluteTime sLastWakeTime; // last time we woke up 484 485 /********************************************************************* 486 * Backtraces can be printed at various times so we need a tight lock 487 * on data used for that. sKextSummariesLock protects the variables 488 * declared immediately below. 489 * 490 * gLoadedKextSummaries is accessed by other modules, but only during 491 * a panic so the lock isn't needed then. 492 * 493 * gLoadedKextSummaries has the "used" attribute in order to ensure 494 * that it remains visible even when we are performing extremely 495 * aggressive optimizations, as it is needed to allow the debugger 496 * to automatically parse the list of loaded kexts. 497 **********/ 498 static IOLock * sKextSummariesLock = NULL; 499 extern "C" lck_ticket_t vm_allocation_sites_lock; 500 extern "C" lck_grp_t vm_page_lck_grp_bucket; 501 static lck_ticket_t * sKextAccountsLock = &vm_allocation_sites_lock; 502 static lck_grp_t * sKextAccountsLockGrp = &vm_page_lck_grp_bucket; 503 504 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated; 505 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL; 506 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0; 507 static size_t sLoadedKextSummariesAllocSize = 0; 508 509 static OSKextActiveAccount * sKextAccounts; 510 static uint32_t sKextAccountsCount; 511 }; 512 513 /********************************************************************* 514 * sKextLoggingLock protects the logging variables declared immediately below. 515 **********/ 516 static IOLock * sKextLoggingLock = NULL; 517 518 static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel | 519 kOSKextLogVerboseFlagsMask; 520 static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter; 521 static bool sBootArgLogFilterFound = false; 522 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter, 523 0, "kernel kext logging"); 524 525 static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter; 526 static OSSharedPtr<OSArray> sUserSpaceLogSpecArray; 527 static OSSharedPtr<OSArray> sUserSpaceLogMessageArray; 528 529 /********* 530 * End scope for sKextInnerLock-protected variables. 531 *********************************************************************/ 532 533 /********************************************************************* 534 * OSValueObject concrete type instantiations 535 **********/ 536 OSDefineValueObjectForDependentType(void*) 537 OSDefineValueObjectForDependentType(OSKextRequestResourceCallback) 538 539 540 /**********************************************************************/ 541 542 TUNABLE(uint32_t, kMaxDextCrashesInOneDay, "daily_max_dext_crashes", kMaxDextCrashesInOneDayDefault); 543 544 /********************************************************************* 545 * helper function used for collecting PGO data upon unload of a kext 546 */ 547 548 static int OSKextGrabPgoDataLocked(OSKext *kext, 549 bool metadata, 550 uuid_t instance_uuid, 551 uint64_t *pSize, 552 char *pBuffer, 553 uint64_t bufferSize); 554 555 /**********************************************************************/ 556 557 558 559 #if PRAGMA_MARK 560 #pragma mark OSData callbacks (need to move to OSData) 561 #endif 562 /********************************************************************* 563 * C functions used for callbacks. 564 *********************************************************************/ 565 extern "C" { 566 void 567 osdata_kmem_free(void * ptr, unsigned int length) 568 { 569 kmem_free(kernel_map, (vm_address_t)ptr, length); 570 return; 571 } 572 573 void 574 osdata_phys_free(void * ptr, unsigned int length) 575 { 576 ml_static_mfree((vm_offset_t)ptr, length); 577 return; 578 } 579 580 void 581 osdata_vm_deallocate(void * ptr, unsigned int length) 582 { 583 (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length); 584 return; 585 } 586 587 void 588 osdata_kext_free(void * ptr, unsigned int length) 589 { 590 (void)kext_free((vm_offset_t)ptr, length); 591 } 592 }; 593 594 #if PRAGMA_MARK 595 #pragma mark KXLD Allocation Callback 596 #endif 597 #if CONFIG_KXLD 598 /********************************************************************* 599 * KXLD Allocation Callback 600 *********************************************************************/ 601 kxld_addr_t 602 kern_allocate( 603 u_long size, 604 KXLDAllocateFlags * flags, 605 void * user_data) 606 { 607 vm_address_t result = 0; // returned 608 kern_return_t mach_result = KERN_FAILURE; 609 bool success = false; 610 OSKext * theKext = (OSKext *)user_data; 611 unsigned int roundSize = 0; 612 OSSharedPtr<OSData> linkBuffer; 613 614 if (round_page(size) > UINT_MAX) { 615 OSKextLog(theKext, 616 kOSKextLogErrorLevel | 617 kOSKextLogGeneralFlag, 618 "%s: Requested memory size is greater than UINT_MAX.", 619 theKext->getIdentifierCString()); 620 goto finish; 621 } 622 623 roundSize = (unsigned int)round_page(size); 624 625 mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE); 626 if (mach_result != KERN_SUCCESS) { 627 OSKextLog(theKext, 628 kOSKextLogErrorLevel | 629 kOSKextLogGeneralFlag, 630 "Can't allocate kernel memory to link %s.", 631 theKext->getIdentifierCString()); 632 goto finish; 633 } 634 635 /* Create an OSData wrapper for the allocated buffer. 636 */ 637 linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize); 638 if (!linkBuffer) { 639 OSKextLog(theKext, 640 kOSKextLogErrorLevel | 641 kOSKextLogGeneralFlag, 642 "Can't allocate linked executable wrapper for %s.", 643 theKext->getIdentifierCString()); 644 goto finish; 645 } 646 linkBuffer->setDeallocFunction(osdata_kext_free); 647 OSKextLog(theKext, 648 kOSKextLogProgressLevel | 649 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 650 "Allocated link buffer for kext %s at %p (%lu bytes).", 651 theKext->getIdentifierCString(), 652 (void *)result, (unsigned long)roundSize); 653 654 theKext->setLinkedExecutable(linkBuffer.get()); 655 656 *flags = kKxldAllocateWritable; 657 success = true; 658 659 finish: 660 if (!success && result) { 661 kext_free(result, roundSize); 662 result = 0; 663 } 664 665 return (kxld_addr_t)result; 666 } 667 668 /********************************************************************* 669 *********************************************************************/ 670 void 671 kxld_log_callback( 672 KXLDLogSubsystem subsystem, 673 KXLDLogLevel level, 674 const char * format, 675 va_list argList, 676 void * user_data) 677 { 678 OSKext *theKext = (OSKext *) user_data; 679 OSKextLogSpec logSpec = 0; 680 681 switch (subsystem) { 682 case kKxldLogLinking: 683 logSpec |= kOSKextLogLinkFlag; 684 break; 685 case kKxldLogPatching: 686 logSpec |= kOSKextLogPatchFlag; 687 break; 688 } 689 690 switch (level) { 691 case kKxldLogExplicit: 692 logSpec |= kOSKextLogExplicitLevel; 693 break; 694 case kKxldLogErr: 695 logSpec |= kOSKextLogErrorLevel; 696 break; 697 case kKxldLogWarn: 698 logSpec |= kOSKextLogWarningLevel; 699 break; 700 case kKxldLogBasic: 701 logSpec |= kOSKextLogProgressLevel; 702 break; 703 case kKxldLogDetail: 704 logSpec |= kOSKextLogDetailLevel; 705 break; 706 case kKxldLogDebug: 707 logSpec |= kOSKextLogDebugLevel; 708 break; 709 } 710 711 OSKextVLog(theKext, logSpec, format, argList); 712 } 713 #endif // CONFIG_KXLD 714 715 #if PRAGMA_MARK 716 #pragma mark IOStatistics defines 717 #endif 718 719 #if IOKITSTATS 720 721 #define notifyKextLoadObservers(kext, kmod_info) \ 722 do { \ 723 IOStatistics::onKextLoad(kext, kmod_info); \ 724 } while (0) 725 726 #define notifyKextUnloadObservers(kext) \ 727 do { \ 728 IOStatistics::onKextUnload(kext); \ 729 } while (0) 730 731 #define notifyAddClassObservers(kext, addedClass, flags) \ 732 do { \ 733 IOStatistics::onClassAdded(kext, addedClass); \ 734 } while (0) 735 736 #define notifyRemoveClassObservers(kext, removedClass, flags) \ 737 do { \ 738 IOStatistics::onClassRemoved(kext, removedClass); \ 739 } while (0) 740 741 #else 742 743 #define notifyKextLoadObservers(kext, kmod_info) 744 #define notifyKextUnloadObservers(kext) 745 #define notifyAddClassObservers(kext, addedClass, flags) 746 #define notifyRemoveClassObservers(kext, removedClass, flags) 747 748 #endif /* IOKITSTATS */ 749 750 #if PRAGMA_MARK 751 #pragma mark Module Config (Startup & Shutdown) 752 #endif 753 /********************************************************************* 754 * Module Config (Class Definition & Class Methods) 755 *********************************************************************/ 756 #define super OSObject 757 OSDefineMetaClassAndStructors(OSKext, OSObject) 758 759 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject); 760 761 OSDefineMetaClassAndStructors(OSDextStatistics, OSObject); 762 763 /********************************************************************* 764 *********************************************************************/ 765 /** 766 * Allocate and intialize a fake/representative OSKext object for a statically 767 * loaded (by iBoot) binary (e.g., the XNU kernel itself). 768 * 769 * @param kmod_info Pointer to the kmod_info structure for the binary being 770 * setup. At least the "name" and "id" fields needs to already 771 * be set correctly. 772 * 773 * @return The allocated and initialized OSKext object. 774 */ 775 /* static */ 776 OSKext * 777 OSKext::allocAndInitFakeKext(kmod_info_t *kmod_info) 778 { 779 vm_offset_t load_address = 0; 780 const char *bundle_name = NULL; 781 bool macho_is_unslid = false; 782 bool set_custom_path = false; 783 const char *executable_fallback_name = NULL; 784 785 if (kmod_info->id == kOSKextKernelLoadTag) { 786 load_address = (vm_offset_t)&_mh_execute_header; 787 bundle_name = "mach_kernel"; 788 789 /* The kernel Mach-O header is fixed up to slide all of its addresses. */ 790 macho_is_unslid = false; 791 792 /** 793 * No path to the binary is set for the kernel in its OSKext object. The 794 * kernel binary is located in fixed directories depending on the OS. 795 */ 796 set_custom_path = false; 797 executable_fallback_name = NULL; 798 } else { 799 panic("%s: Unsupported kmod_info->id (%d)", __func__, kmod_info->id); 800 } 801 802 /* Set up an OSKext instance to represent the statically loaded binary. */ 803 OSKext *fakeKext = new OSKext; 804 assert(fakeKext); 805 assert(load_address != 0); 806 807 /* 808 * The start address is always a slid address whereas the last VA returned 809 * by getlastaddr() might be unslid depending on the Mach-O. If the address 810 * coming from the Mach-O is unslid, then unslide the start address before 811 * computing the length of the executable. 812 */ 813 size_t binaryLength = getlastaddr((kernel_mach_header_t*)load_address); 814 binaryLength -= (macho_is_unslid) ? ml_static_unslide(load_address) : load_address; 815 assert(binaryLength <= UINT_MAX); 816 817 /** 818 * The load address is always slid. That value will be unslid before being 819 * exposed to userspace. 820 */ 821 OSSharedPtr<OSData> executable = OSData::withBytesNoCopy( 822 (void*)load_address, (unsigned int)binaryLength); 823 assert(executable); 824 825 fakeKext->loadTag = sNextLoadTag++; 826 fakeKext->bundleID = OSSymbol::withCString(kmod_info->name); 827 828 fakeKext->version = OSKextParseVersionString(osrelease); 829 fakeKext->compatibleVersion = fakeKext->version; 830 fakeKext->linkedExecutable = os::move(executable); 831 fakeKext->interfaceUUID = fakeKext->copyUUID(); 832 833 fakeKext->flags.hasAllDependencies = 1; 834 fakeKext->flags.kernelComponent = 1; 835 fakeKext->flags.prelinked = 0; 836 fakeKext->flags.loaded = 1; 837 fakeKext->flags.started = 1; 838 fakeKext->flags.CPPInitialized = 0; 839 fakeKext->flags.jettisonLinkeditSeg = 0; 840 fakeKext->flags.unslidMachO = macho_is_unslid; 841 842 843 fakeKext->kmod_info = kmod_info; 844 strlcpy(kmod_info->version, osrelease, 845 sizeof(kmod_info->version)); 846 kmod_info->size = binaryLength; 847 assert(kmod_info->id == fakeKext->loadTag); 848 849 /* 850 * Con up an info dict, so we don't have to have special-case checking all 851 * over. 852 */ 853 fakeKext->infoDict = OSDictionary::withCapacity(5); 854 assert(fakeKext->infoDict); 855 bool setResult = fakeKext->infoDict->setObject(kCFBundleIdentifierKey, 856 fakeKext->bundleID.get()); 857 assert(setResult); 858 setResult = fakeKext->infoDict->setObject(kOSKernelResourceKey, 859 kOSBooleanTrue); 860 assert(setResult); 861 862 { 863 OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease)); 864 assert(scratchString); 865 setResult = fakeKext->infoDict->setObject(kCFBundleVersionKey, 866 scratchString.get()); 867 assert(setResult); 868 } 869 870 { 871 OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(bundle_name)); 872 assert(scratchString); 873 setResult = fakeKext->infoDict->setObject(kCFBundleNameKey, 874 scratchString.get()); 875 assert(setResult); 876 } 877 878 return fakeKext; 879 } 880 881 /* static */ 882 void 883 OSKext::initialize(void) 884 { 885 OSSharedPtr<OSData> kernelExecutable = NULL;// do not release 886 IORegistryEntry * registryRoot = NULL;// do not release 887 OSSharedPtr<OSNumber> kernelCPUType; 888 OSSharedPtr<OSNumber> kernelCPUSubtype; 889 OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter; 890 bool setResult = false; 891 uint64_t * timestamp = NULL; 892 __unused char bootArgBuffer[16];// for PE_parse_boot_argn w/strings 893 894 /* This must be the first thing allocated. Everything else grabs this lock. 895 */ 896 sKextLock = IORecursiveLockAlloc(); 897 sKextInnerLock = IORecursiveLockAlloc(); 898 sKextSummariesLock = IOLockAlloc(); 899 sKextLoggingLock = IOLockAlloc(); 900 assert(sKextLock); 901 assert(sKextInnerLock); 902 assert(sKextSummariesLock); 903 assert(sKextLoggingLock); 904 905 sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount); 906 sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 907 sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 908 sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10); 909 sKernelRequests = OSArray::withCapacity(0); 910 sPostedKextLoadIdentifiers = OSSet::withCapacity(0); 911 sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount); 912 sRequestCallbackRecords = OSArray::withCapacity(0); 913 sDriverKitToUpgradeByID = OSDictionary::withCapacity(kOSKextTypicalUpgradeCount); 914 915 assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests && 916 sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers && 917 sRequestCallbackRecords && sUnloadedPrelinkedKexts && sDriverKitToUpgradeByID); 918 919 /* Read the log flag boot-args and set the log flags. 920 */ 921 if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) { 922 sBootArgLogFilterFound = true; 923 sKernelLogFilter = bootLogFilter; 924 // log this if any flags are set 925 OSKextLog(/* kext */ NULL, 926 kOSKextLogBasicLevel | 927 kOSKextLogFlagsMask, 928 "Kernel kext log filter 0x%x per kextlog boot arg.", 929 (unsigned)sKernelLogFilter); 930 } 931 932 #if !defined(__arm__) && !defined(__arm64__) 933 /* 934 * On our ARM targets, the kernelcache/boot kernel collection contains 935 * the set of kexts required to boot, as specified by KCB. Safeboot is 936 * either unsupported, or is supported by the bootloader only loading 937 * the boot kernel collection; as a result OSKext has no role to play 938 * in safeboot policy on ARM. 939 */ 940 sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer, 941 sizeof(bootArgBuffer)) ? true : false; 942 #endif /* defined(__arm__) && defined(__arm64__) */ 943 944 if (sSafeBoot) { 945 OSKextLog(/* kext */ NULL, 946 kOSKextLogWarningLevel | 947 kOSKextLogGeneralFlag, 948 "SAFE BOOT DETECTED - " 949 "only valid OSBundleRequired kexts will be loaded."); 950 } 951 952 PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols)); 953 #if CONFIG_DTRACE 954 if (dtrace_keep_kernel_symbols()) { 955 sKeepSymbols = true; 956 } 957 #endif /* CONFIG_DTRACE */ 958 #if KASAN_DYNAMIC_BLACKLIST 959 /* needed for function lookup */ 960 sKeepSymbols = true; 961 #endif 962 963 /* 964 * Should we panic when the SystemKC is not linked against the 965 * BootKC that was loaded by the booter? By default: yes, if the 966 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic 967 * on mis-match and instead just print an error and continue. 968 */ 969 sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer, 970 sizeof(bootArgBuffer)) ? false : true; 971 972 /* Set up an OSKext instance to represent the kernel itself. */ 973 sKernelKext = allocAndInitFakeKext(&g_kernel_kmod_info); 974 assert(sKernelKext); 975 976 977 /* Add the kernel kext to the bookkeeping dictionaries. Note that 978 * the kernel kext doesn't have a kmod_info struct. copyInfo() 979 * gathers info from other places anyhow. 980 */ 981 setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext); 982 assert(setResult); 983 setResult = sLoadedKexts->setObject(sKernelKext); 984 assert(setResult); 985 986 987 // XXX: better way with OSSharedPtr? 988 // sKernelKext remains a valid pointer even after the decref 989 sKernelKext->release(); 990 991 registryRoot = IORegistryEntry::getRegistryRoot(); 992 kernelCPUType = OSNumber::withNumber( 993 (long long unsigned int)_mh_execute_header.cputype, 994 8 * sizeof(_mh_execute_header.cputype)); 995 kernelCPUSubtype = OSNumber::withNumber( 996 (long long unsigned int)_mh_execute_header.cpusubtype, 997 8 * sizeof(_mh_execute_header.cpusubtype)); 998 assert(registryRoot && kernelCPUSubtype && kernelCPUType); 999 1000 registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get()); 1001 registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get()); 1002 1003 gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection); 1004 if (gBuiltinKmodsSectionInfo) { 1005 uint32_t count; 1006 1007 assert(gBuiltinKmodsSectionInfo->addr); 1008 assert(gBuiltinKmodsSectionInfo->size); 1009 assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX); 1010 gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *)); 1011 1012 gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection); 1013 assert(gBuiltinKmodsSectionStart); 1014 assert(gBuiltinKmodsSectionStart->addr); 1015 assert(gBuiltinKmodsSectionStart->size); 1016 assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX); 1017 count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t)); 1018 // one extra pointer for the end of last kmod 1019 assert(count == (gBuiltinKmodsCount + 1)); 1020 1021 vm_kernel_builtinkmod_text = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0]; 1022 vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1]; 1023 } 1024 1025 // Don't track this object -- it's never released 1026 gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach(); 1027 1028 timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp); 1029 *timestamp = 0; 1030 timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp); 1031 *timestamp = 0; 1032 timestamp = __OSAbsoluteTimePtr(&sLastWakeTime); 1033 *timestamp = 0; 1034 1035 OSKextLog(/* kext */ NULL, 1036 kOSKextLogProgressLevel | 1037 kOSKextLogGeneralFlag, 1038 "Kext system initialized."); 1039 1040 notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info); 1041 1042 return; 1043 } 1044 1045 /********************************************************************* 1046 * This is expected to be called exactly once, from exactly one thread 1047 * context, during kernel bootstrap. 1048 *********************************************************************/ 1049 /* static */ 1050 OSReturn 1051 OSKext::removeKextBootstrap(void) 1052 { 1053 OSReturn result = kOSReturnError; 1054 1055 const char * dt_kernel_header_name = "Kernel-__HEADER"; 1056 const char * dt_kernel_symtab_name = "Kernel-__SYMTAB"; 1057 kernel_mach_header_t * dt_mach_header = NULL; 1058 int dt_mach_header_size = 0; 1059 struct symtab_command * dt_symtab = NULL; 1060 int dt_symtab_size = 0; 1061 int dt_result = 0; 1062 1063 kernel_segment_command_t * seg_kld = NULL; 1064 kernel_segment_command_t * seg_klddata = NULL; 1065 kernel_segment_command_t * seg_linkedit = NULL; 1066 1067 const char __unused * dt_segment_name = NULL; 1068 void __unused * segment_paddress = NULL; 1069 int __unused segment_size = 0; 1070 1071 OSKextLog(/* kext */ NULL, 1072 kOSKextLogProgressLevel | 1073 kOSKextLogGeneralFlag, 1074 "Jettisoning kext bootstrap segments."); 1075 1076 /* 1077 * keep the linkedit segment around when booted from a new MH_FILESET 1078 * KC because all the kexts shared a linkedit segment. 1079 */ 1080 kc_format_t kc_format; 1081 if (!PE_get_primary_kc_format(&kc_format)) { 1082 OSKextLog(/* kext */ NULL, 1083 kOSKextLogErrorLevel | 1084 kOSKextLogGeneralFlag, 1085 "Unable to determine primary KC format"); 1086 } 1087 1088 /***** 1089 * Dispose of unnecessary stuff that the booter didn't need to load. 1090 */ 1091 dt_result = IODTGetLoaderInfo(dt_kernel_header_name, 1092 (void **)&dt_mach_header, &dt_mach_header_size); 1093 if (dt_result == 0 && dt_mach_header) { 1094 IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header, 1095 round_page_32(dt_mach_header_size)); 1096 } 1097 dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name, 1098 (void **)&dt_symtab, &dt_symtab_size); 1099 if (dt_result == 0 && dt_symtab) { 1100 IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab, 1101 round_page_32(dt_symtab_size)); 1102 } 1103 1104 /***** 1105 * KLD & KLDDATA bootstrap segments. 1106 */ 1107 // xxx - should rename KLD segment 1108 seg_kld = getsegbyname("__KLD"); 1109 seg_klddata = getsegbyname("__KLDDATA"); 1110 if (seg_klddata) { 1111 // __mod_term_func is part of __KLDDATA 1112 OSRuntimeUnloadCPPForSegment(seg_klddata); 1113 } 1114 1115 #if __arm__ || __arm64__ 1116 /* Free the memory that was set up by iBoot. 1117 */ 1118 #if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR) 1119 /* We cannot free the KLD segment with CTRR enabled as it contains text and 1120 * is covered by the contiguous rorgn. 1121 */ 1122 dt_segment_name = "Kernel-__KLD"; 1123 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) { 1124 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1125 (int)segment_size); // calls ml_static_mfree 1126 } else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) { 1127 /* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */ 1128 ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase), 1129 seg_kld->vmsize); 1130 } 1131 #endif 1132 dt_segment_name = "Kernel-__KLDDATA"; 1133 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) { 1134 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1135 (int)segment_size); // calls ml_static_mfree 1136 } else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) { 1137 /* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */ 1138 ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase), 1139 seg_klddata->vmsize); 1140 } 1141 #elif __i386__ || __x86_64__ 1142 /* On x86, use the mapping data from the segment load command to 1143 * unload KLD & KLDDATA directly. 1144 * This may invalidate any assumptions about "avail_start" 1145 * defining the lower bound for valid physical addresses. 1146 */ 1147 if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) { 1148 bzero((void *)seg_kld->vmaddr, seg_kld->vmsize); 1149 ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize); 1150 } 1151 if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) { 1152 bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize); 1153 ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize); 1154 } 1155 #else 1156 #error arch 1157 #endif 1158 1159 /***** 1160 * Prelinked kernel's symtab (if there is one). 1161 */ 1162 if (kc_format != KCFormatFileset) { 1163 kernel_section_t * sect; 1164 sect = getsectbyname("__PRELINK", "__symtab"); 1165 if (sect && sect->addr && sect->size) { 1166 ml_static_mfree(sect->addr, sect->size); 1167 } 1168 } 1169 1170 seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT"); 1171 1172 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it 1173 * pageable, unless keepsyms is set. To do that, we have to copy it from 1174 * its booter-allocated memory, free the booter memory, reallocate proper 1175 * managed memory, then copy the segment back in. 1176 * 1177 * NOTE: This optimization is not valid for fileset KCs because each 1178 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment 1179 * that points to one fileset-global LINKEDIT segment. This 1180 * optimization is also only valid for platforms that support vm 1181 * mapped kexts or mapped kext collections (pageable KCs) 1182 */ 1183 #if VM_MAPPED_KEXTS 1184 if (!sKeepSymbols && kc_format != KCFormatFileset) { 1185 kern_return_t mem_result; 1186 void *seg_copy = NULL; 1187 void *seg_data = NULL; 1188 vm_map_offset_t seg_offset = 0; 1189 vm_map_offset_t seg_copy_offset = 0; 1190 vm_map_size_t seg_length = 0; 1191 1192 seg_data = (void *) seg_linkedit->vmaddr; 1193 seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr; 1194 seg_length = (vm_map_size_t) seg_linkedit->vmsize; 1195 1196 /* Allocate space for the LINKEDIT copy. 1197 */ 1198 mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy, 1199 seg_length, KMA_ZERO, VM_KERN_MEMORY_KEXT); 1200 if (mem_result != KERN_SUCCESS) { 1201 OSKextLog(/* kext */ NULL, 1202 kOSKextLogErrorLevel | 1203 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1204 "Can't copy __LINKEDIT segment for VM reassign."); 1205 return result; 1206 } 1207 seg_copy_offset = (vm_map_offset_t) seg_copy; 1208 1209 /* Copy it out. 1210 */ 1211 memcpy(seg_copy, seg_data, seg_length); 1212 1213 /* Dump the booter memory. 1214 */ 1215 ml_static_mfree(seg_offset, seg_length); 1216 1217 /* Set up the VM region. 1218 */ 1219 mem_result = vm_map_enter_mem_object( 1220 kernel_map, 1221 &seg_offset, 1222 seg_length, /* mask */ 0, 1223 VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true), 1224 (ipc_port_t)NULL, 1225 (vm_object_offset_t) 0, 1226 /* copy */ FALSE, 1227 /* cur_protection */ VM_PROT_READ | VM_PROT_WRITE, 1228 /* max_protection */ VM_PROT_ALL, 1229 /* inheritance */ VM_INHERIT_DEFAULT); 1230 if ((mem_result != KERN_SUCCESS) || 1231 (seg_offset != (vm_map_offset_t) seg_data)) { 1232 OSKextLog(/* kext */ NULL, 1233 kOSKextLogErrorLevel | 1234 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1235 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).", 1236 seg_data, seg_length, mem_result); 1237 return result; 1238 } 1239 1240 /* And copy it back. 1241 */ 1242 memcpy(seg_data, seg_copy, seg_length); 1243 1244 /* Free the copy. 1245 */ 1246 kmem_free(kernel_map, seg_copy_offset, seg_length); 1247 } else if (!sKeepSymbols && kc_format == KCFormatFileset) { 1248 /* Remove the linkedit segment of the Boot KC */ 1249 kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary); 1250 OSKext::jettisonFileSetLinkeditSegment(mh); 1251 } 1252 #else // !VM_MAPPED_KEXTS 1253 /***** 1254 * Dump the LINKEDIT segment, unless keepsyms is set. 1255 */ 1256 if (!sKeepSymbols && kc_format != KCFormatFileset) { 1257 dt_segment_name = "Kernel-__LINKEDIT"; 1258 if (0 == IODTGetLoaderInfo(dt_segment_name, 1259 &segment_paddress, &segment_size)) { 1260 #ifdef SECURE_KERNEL 1261 vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress); 1262 bzero((void*)vmaddr, segment_size); 1263 #endif 1264 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1265 (int)segment_size); 1266 } 1267 } else if (!sKeepSymbols && kc_format == KCFormatFileset) { 1268 /* Remove the linkedit segment of the Boot KC */ 1269 kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary); 1270 OSKext::jettisonFileSetLinkeditSegment(mh); 1271 } else { 1272 OSKextLog(/* kext */ NULL, 1273 kOSKextLogBasicLevel | 1274 kOSKextLogGeneralFlag, 1275 "keepsyms boot arg specified; keeping linkedit segment for symbols."); 1276 } 1277 #endif // VM_MAPPED_KEXTS 1278 1279 result = kOSReturnSuccess; 1280 1281 return result; 1282 } 1283 1284 #if CONFIG_KXLD 1285 /********************************************************************* 1286 *********************************************************************/ 1287 void 1288 OSKext::flushNonloadedKexts( 1289 Boolean flushPrelinkedKexts) 1290 { 1291 OSSharedPtr<OSSet> keepKexts; 1292 1293 /* TODO: make this more efficient with MH_FILESET kexts */ 1294 1295 // Do not unload prelinked kexts on arm because the kernelcache is not 1296 // structured in a way that allows them to be unmapped 1297 #if !defined(__x86_64__) 1298 flushPrelinkedKexts = false; 1299 #endif /* defined(__x86_64__) */ 1300 1301 IORecursiveLockLock(sKextLock); 1302 1303 OSKextLog(/* kext */ NULL, 1304 kOSKextLogProgressLevel | 1305 kOSKextLogKextBookkeepingFlag, 1306 "Flushing nonloaded kexts and other unused data."); 1307 1308 OSKext::considerDestroyingLinkContext(); 1309 1310 /* If we aren't flushing unused prelinked kexts, we have to put them 1311 * aside while we flush everything else so make a container for them. 1312 */ 1313 keepKexts = OSSet::withCapacity(16); 1314 if (!keepKexts) { 1315 goto finish; 1316 } 1317 1318 /* Set aside prelinked kexts (in-use or not) and break 1319 * any lingering inter-kext references for nonloaded kexts 1320 * so they have min. retain counts. 1321 */ 1322 { 1323 sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) { 1324 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1325 if (!thisKext) { 1326 return false; 1327 } 1328 if (!flushPrelinkedKexts && thisKext->isPrelinked()) { 1329 keepKexts->setObject(thisKext); 1330 } else if (!thisKext->declaresExecutable()) { 1331 /* 1332 * Don't unload codeless kexts, because they never appear in the loadedKexts array. 1333 * Requesting one from the IOKit daemon will load it and then immediately remove it by calling 1334 * flushNonloadedKexts(). 1335 * And adding one to loadedKexts breaks code assuming they have kmod_info etc. 1336 */ 1337 keepKexts->setObject(thisKext); 1338 } else if (thisKext->isInFileset()) { 1339 /* keep all kexts in the new MH_FILESET KC */ 1340 keepKexts->setObject(thisKext); 1341 } 1342 1343 thisKext->flushDependencies(/* forceIfLoaded */ false); 1344 return false; 1345 }); 1346 } 1347 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly. 1348 */ 1349 sKextsByID->flushCollection(); 1350 1351 /* Now put the loaded kexts back into the ID dictionary. 1352 */ 1353 sLoadedKexts->iterateObjects(^bool (OSObject * obj) { 1354 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1355 if (!thisKext) { 1356 return false; 1357 } 1358 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1359 return false; 1360 }); 1361 1362 /* Finally, put back the kept kexts if we saved any. 1363 */ 1364 keepKexts->iterateObjects(^bool (OSObject * obj) { 1365 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1366 if (!thisKext) { 1367 return false; 1368 } 1369 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1370 return false; 1371 }); 1372 1373 finish: 1374 IORecursiveLockUnlock(sKextLock); 1375 return; 1376 } 1377 #else /* !CONFIG_KXLD */ 1378 1379 void 1380 OSKext::flushNonloadedKexts( 1381 Boolean flushPrelinkedKexts __unused) 1382 { 1383 IORecursiveLockLock(sKextLock); 1384 1385 OSKextLog(/* kext */ NULL, 1386 kOSKextLogProgressLevel | 1387 kOSKextLogKextBookkeepingFlag, 1388 "Flushing dependency info for non-loaded kexts."); 1389 1390 /* 1391 * In a world where we don't dynamically link kexts, they all come 1392 * from a kext collection that's either in wired memory, or 1393 * wire-on-demand. We don't need to mess around with moving kexts in 1394 * and out of the sKextsByID array - they can all just stay there. 1395 * Here we just flush the dependency list for kexts that are not 1396 * loaded. 1397 */ 1398 sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) { 1399 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1400 if (!thisKext) { 1401 return false; 1402 } 1403 thisKext->flushDependencies(/* forceIfLoaded */ false); 1404 return false; 1405 }); 1406 1407 IORecursiveLockUnlock(sKextLock); 1408 return; 1409 } 1410 1411 #endif /* CONFIG_KXLD */ 1412 1413 /********************************************************************* 1414 *********************************************************************/ 1415 /* static */ 1416 void 1417 OSKext::setIOKitDaemonActive(bool active) 1418 { 1419 IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0); 1420 IORecursiveLockLock(sKextLock); 1421 sIOKitDaemonActive = active; 1422 if (sKernelRequests->getCount()) { 1423 OSKext::pingIOKitDaemon(); 1424 } 1425 IORecursiveLockUnlock(sKextLock); 1426 1427 return; 1428 } 1429 1430 /********************************************************************* 1431 * OSKextLib.cpp might need access to this someday but for now it's 1432 * private. 1433 *********************************************************************/ 1434 extern "C" { 1435 extern void ipc_port_release_send(ipc_port_t); 1436 }; 1437 1438 /* static */ 1439 OSReturn 1440 OSKext::pingIOKitDaemon(void) 1441 { 1442 OSReturn result = kOSReturnError; 1443 #if !NO_KEXTD 1444 mach_port_t kextd_port = IPC_PORT_NULL; 1445 1446 if (!sIOKitDaemonActive) { 1447 result = kOSKextReturnDisabled; // basically unavailable 1448 goto finish; 1449 } 1450 1451 result = host_get_kextd_port(host_priv_self(), &kextd_port); 1452 if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) { 1453 OSKextLog(/* kext */ NULL, 1454 kOSKextLogErrorLevel | 1455 kOSKextLogIPCFlag, 1456 "Can't get " kIOKitDaemonName " port."); 1457 goto finish; 1458 } 1459 1460 result = kextd_ping(kextd_port); 1461 if (result != KERN_SUCCESS) { 1462 OSKextLog(/* kext */ NULL, 1463 kOSKextLogErrorLevel | 1464 kOSKextLogIPCFlag, 1465 kIOKitDaemonName " ping failed (0x%x).", (int)result); 1466 goto finish; 1467 } 1468 1469 finish: 1470 if (IPC_PORT_VALID(kextd_port)) { 1471 ipc_port_release_send(kextd_port); 1472 } 1473 #endif 1474 1475 return result; 1476 } 1477 1478 /********************************************************************* 1479 *********************************************************************/ 1480 /* static */ 1481 bool 1482 OSKext::iokitDaemonAvailable(void) 1483 { 1484 int notused; 1485 if (PE_parse_boot_argn("-restore", ¬used, sizeof(notused))) { 1486 return false; 1487 } 1488 return true; 1489 } 1490 1491 /********************************************************************* 1492 *********************************************************************/ 1493 /* static */ 1494 void 1495 OSKext::setDeferredLoadSucceeded(Boolean succeeded) 1496 { 1497 IORecursiveLockLock(sKextLock); 1498 sDeferredLoadSucceeded = succeeded; 1499 IORecursiveLockUnlock(sKextLock); 1500 1501 return; 1502 } 1503 1504 /********************************************************************* 1505 * Called from IOSystemShutdownNotification. 1506 *********************************************************************/ 1507 /* static */ 1508 void 1509 OSKext::willShutdown(void) 1510 { 1511 #if !NO_KEXTD 1512 OSReturn checkResult = kOSReturnError; 1513 #endif 1514 OSSharedPtr<OSDictionary> exitRequest; 1515 1516 IORecursiveLockLock(sKextLock); 1517 1518 OSKext::setLoadEnabled(false); 1519 OSKext::setUnloadEnabled(false); 1520 OSKext::setAutounloadsEnabled(false); 1521 OSKext::setKernelRequestsEnabled(false); 1522 1523 #if defined(__x86_64__) || defined(__i386__) 1524 if (IOPMRootDomainGetWillShutdown()) { 1525 OSKext::freeKCFileSetcontrol(); 1526 } 1527 #endif // (__x86_64__) || defined(__i386__) 1528 1529 #if !NO_KEXTD 1530 OSKextLog(/* kext */ NULL, 1531 kOSKextLogProgressLevel | 1532 kOSKextLogGeneralFlag, 1533 "System shutdown; requesting immediate " kIOKitDaemonName " exit."); 1534 1535 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit, 1536 exitRequest); 1537 if (checkResult != kOSReturnSuccess) { 1538 goto finish; 1539 } 1540 if (!sKernelRequests->setObject(exitRequest.get())) { 1541 goto finish; 1542 } 1543 1544 OSKext::pingIOKitDaemon(); 1545 1546 finish: 1547 #endif 1548 1549 IORecursiveLockUnlock(sKextLock); 1550 return; 1551 } 1552 1553 void 1554 OSKext::willUserspaceReboot(void) 1555 { 1556 OSKext::willShutdown(); 1557 IOService::userSpaceWillReboot(); 1558 gIOCatalogue->terminateDriversForUserspaceReboot(); 1559 } 1560 1561 void 1562 OSKext::resetAfterUserspaceReboot(void) 1563 { 1564 OSSharedPtr<OSArray> arr = OSArray::withCapacity(1); 1565 IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */); 1566 1567 IORecursiveLockLock(sKextLock); 1568 gIOCatalogue->resetAfterUserspaceReboot(); 1569 IOService::userSpaceDidReboot(); 1570 OSKext::removeDaemonExitRequests(); 1571 OSKext::setLoadEnabled(true); 1572 OSKext::setUnloadEnabled(true); 1573 OSKext::setAutounloadsEnabled(true); 1574 OSKext::setKernelRequestsEnabled(true); 1575 sOSKextWasResetAfterUserspaceReboot = true; 1576 IORecursiveLockUnlock(sKextLock); 1577 } 1578 1579 extern "C" void 1580 OSKextResetAfterUserspaceReboot(void) 1581 { 1582 OSKext::resetAfterUserspaceReboot(); 1583 } 1584 1585 /* 1586 * Remove daemon exit requests from sKernelRequests 1587 * 1588 * If we sent a daemon exit request during a userspace reboot and launchd 1589 * killed the IOKit daemon before it was able to dequeue the exit request, the 1590 * next time the daemon starts up it will immediately exit as it gets the old exit request. 1591 * 1592 * This removes exit requests so that this does not happen. 1593 */ 1594 void 1595 OSKext::removeDaemonExitRequests(void) 1596 { 1597 OSDictionary * current = NULL; 1598 OSString * predicate = NULL; 1599 size_t index = 0; 1600 OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey); 1601 1602 while (index < sKernelRequests->getCount()) { 1603 current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index)); 1604 if (current) { 1605 predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get())); 1606 if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) { 1607 sKernelRequests->removeObject(index); 1608 continue; 1609 } 1610 } 1611 index++; 1612 } 1613 } 1614 1615 /********************************************************************* 1616 *********************************************************************/ 1617 /* static */ 1618 bool 1619 OSKext::getLoadEnabled(void) 1620 { 1621 bool result; 1622 1623 IORecursiveLockLock(sKextLock); 1624 result = sLoadEnabled; 1625 IORecursiveLockUnlock(sKextLock); 1626 return result; 1627 } 1628 1629 /********************************************************************* 1630 *********************************************************************/ 1631 /* static */ 1632 bool 1633 OSKext::setLoadEnabled(bool flag) 1634 { 1635 bool result; 1636 1637 IORecursiveLockLock(sKextLock); 1638 result = sLoadEnabled; 1639 sLoadEnabled = (flag ? true : false); 1640 1641 if (sLoadEnabled != result) { 1642 OSKextLog(/* kext */ NULL, 1643 kOSKextLogBasicLevel | 1644 kOSKextLogLoadFlag, 1645 "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis"); 1646 } 1647 1648 IORecursiveLockUnlock(sKextLock); 1649 1650 return result; 1651 } 1652 1653 /********************************************************************* 1654 *********************************************************************/ 1655 /* static */ 1656 bool 1657 OSKext::getUnloadEnabled(void) 1658 { 1659 bool result; 1660 1661 IORecursiveLockLock(sKextLock); 1662 result = sUnloadEnabled; 1663 IORecursiveLockUnlock(sKextLock); 1664 return result; 1665 } 1666 1667 /********************************************************************* 1668 *********************************************************************/ 1669 /* static */ 1670 bool 1671 OSKext::setUnloadEnabled(bool flag) 1672 { 1673 bool result; 1674 1675 IORecursiveLockLock(sKextLock); 1676 result = sUnloadEnabled; 1677 sUnloadEnabled = (flag ? true : false); 1678 IORecursiveLockUnlock(sKextLock); 1679 1680 if (sUnloadEnabled != result) { 1681 OSKextLog(/* kext */ NULL, 1682 kOSKextLogBasicLevel | 1683 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1684 "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis"); 1685 } 1686 1687 return result; 1688 } 1689 1690 /********************************************************************* 1691 * Do not call any function that takes sKextLock here! 1692 *********************************************************************/ 1693 /* static */ 1694 bool 1695 OSKext::getAutounloadEnabled(void) 1696 { 1697 #if XNU_TARGET_OS_OSX 1698 bool result; 1699 1700 IORecursiveLockLock(sKextInnerLock); 1701 result = sAutounloadEnabled ? true : false; 1702 IORecursiveLockUnlock(sKextInnerLock); 1703 return result; 1704 #else 1705 return false; 1706 #endif /* XNU_TARGET_OS_OSX */ 1707 } 1708 1709 /********************************************************************* 1710 * Do not call any function that takes sKextLock here! 1711 *********************************************************************/ 1712 /* static */ 1713 bool 1714 OSKext::setAutounloadsEnabled(bool flag) 1715 { 1716 #if XNU_TARGET_OS_OSX 1717 bool result; 1718 1719 IORecursiveLockLock(sKextInnerLock); 1720 1721 result = sAutounloadEnabled; 1722 sAutounloadEnabled = (flag ? true : false); 1723 if (!sAutounloadEnabled && sUnloadCallout) { 1724 thread_call_cancel(sUnloadCallout); 1725 } 1726 1727 if (sAutounloadEnabled != result) { 1728 OSKextLog(/* kext */ NULL, 1729 kOSKextLogBasicLevel | 1730 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1731 "Kext autounloading now %sabled.", 1732 sAutounloadEnabled ? "en" : "dis"); 1733 } 1734 1735 IORecursiveLockUnlock(sKextInnerLock); 1736 1737 return result; 1738 #else 1739 (void)flag; 1740 return false; 1741 #endif /* XNU_TARGET_OS_OSX */ 1742 } 1743 1744 /********************************************************************* 1745 *********************************************************************/ 1746 /* instance method operating on OSKext field */ 1747 bool 1748 OSKext::setAutounloadEnabled(bool flag) 1749 { 1750 bool result = flags.autounloadEnabled ? true : false; 1751 flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0; 1752 1753 if (result != (flag ? true : false)) { 1754 OSKextLog(this, 1755 kOSKextLogProgressLevel | 1756 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 1757 "Autounloading for kext %s now %sabled.", 1758 getIdentifierCString(), 1759 flags.autounloadEnabled ? "en" : "dis"); 1760 } 1761 return result; 1762 } 1763 1764 /********************************************************************* 1765 *********************************************************************/ 1766 /* static */ 1767 bool 1768 OSKext::setKernelRequestsEnabled(bool flag) 1769 { 1770 bool result; 1771 1772 IORecursiveLockLock(sKextLock); 1773 result = sKernelRequestsEnabled; 1774 sKernelRequestsEnabled = flag ? true : false; 1775 1776 if (sKernelRequestsEnabled != result) { 1777 OSKextLog(/* kext */ NULL, 1778 kOSKextLogBasicLevel | 1779 kOSKextLogGeneralFlag, 1780 "Kernel requests now %sabled.", 1781 sKernelRequestsEnabled ? "en" : "dis"); 1782 } 1783 IORecursiveLockUnlock(sKextLock); 1784 return result; 1785 } 1786 1787 /********************************************************************* 1788 *********************************************************************/ 1789 /* static */ 1790 bool 1791 OSKext::getKernelRequestsEnabled(void) 1792 { 1793 bool result; 1794 1795 IORecursiveLockLock(sKextLock); 1796 result = sKernelRequestsEnabled; 1797 IORecursiveLockUnlock(sKextLock); 1798 return result; 1799 } 1800 1801 static bool 1802 segmentIsMutable(kernel_segment_command_t *seg) 1803 { 1804 /* Mutable segments have to have VM_PROT_WRITE */ 1805 if ((seg->maxprot & VM_PROT_WRITE) == 0) { 1806 return false; 1807 } 1808 /* Exclude the __DATA_CONST segment */ 1809 if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) { 1810 return false; 1811 } 1812 /* Exclude __LINKEDIT */ 1813 if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) { 1814 return false; 1815 } 1816 return true; 1817 } 1818 1819 #if PRAGMA_MARK 1820 #pragma mark Kext Life Cycle 1821 #endif 1822 /********************************************************************* 1823 *********************************************************************/ 1824 OSSharedPtr<OSKext> 1825 OSKext::withPrelinkedInfoDict( 1826 OSDictionary * anInfoDict, 1827 bool doCoalescedSlides, 1828 kc_kind_t type) 1829 { 1830 OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>()); 1831 1832 if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) { 1833 return NULL; 1834 } 1835 1836 return newKext; 1837 } 1838 1839 OSData * 1840 OSKext::parseDextUniqueID( 1841 OSDictionary * anInfoDict, 1842 const char *dextIDCS) 1843 { 1844 OSData *ret = NULL; 1845 OSData *data_duid = OSDynamicCast(OSData, anInfoDict->getObject(kOSBundleDextUniqueIdentifierKey)); 1846 if (data_duid != NULL) { 1847 if (data_duid->getLength() > KOSBundleDextUniqueIdentifierMaxLength) { 1848 OSKextLog(NULL, 1849 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 1850 "Dext %s DextUniqueIdentifier too long.", 1851 dextIDCS); 1852 } else { 1853 /* 1854 * If the DextUniqueID exists it should be 1855 * present also into the personalities. 1856 */ 1857 setDextUniqueIDInPersonalities(anInfoDict, data_duid); 1858 ret = data_duid; 1859 } 1860 } else { 1861 OSKextLog(NULL, 1862 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 1863 "Dext %s does not have a DextUniqueIdentifier", 1864 dextIDCS); 1865 } 1866 return ret; 1867 } 1868 1869 void 1870 OSKext::setDextUniqueIDInPersonalities( 1871 OSDictionary * anInfoDict, 1872 OSData * dextUniqueID) 1873 { 1874 OSDictionary * dextPersonalities = NULL; 1875 OSSharedPtr<OSCollectionIterator> personalitiesIterator; 1876 OSString * personalityName = NULL; 1877 1878 dextPersonalities = OSDynamicCast(OSDictionary, 1879 anInfoDict->getObject(kIOKitPersonalitiesKey)); 1880 if (!dextPersonalities || !dextPersonalities->getCount()) { 1881 return; 1882 } 1883 1884 personalitiesIterator = 1885 OSCollectionIterator::withCollection(dextPersonalities); 1886 if (!personalitiesIterator) { 1887 return; 1888 } 1889 while ((personalityName = OSDynamicCast(OSString, 1890 personalitiesIterator->getNextObject()))) { 1891 OSDictionary * personality = OSDynamicCast(OSDictionary, 1892 dextPersonalities->getObject(personalityName)); 1893 if (personality) { 1894 OSObject *duid = personality->getObject(kOSBundleDextUniqueIdentifierKey); 1895 if (duid == NULL) { 1896 personality->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID); 1897 } 1898 } 1899 } 1900 } 1901 /********************************************************************* 1902 *********************************************************************/ 1903 bool 1904 OSKext::initWithPrelinkedInfoDict( 1905 OSDictionary * anInfoDict, 1906 bool doCoalescedSlides, 1907 kc_kind_t type) 1908 { 1909 bool result = false; 1910 OSString * kextPath = NULL; // do not release 1911 OSNumber * addressNum = NULL; // reused; do not release 1912 OSNumber * lengthNum = NULL; // reused; do not release 1913 OSBoolean * scratchBool = NULL; // do not release 1914 void * data = NULL; // do not free 1915 void * srcData = NULL; // do not free 1916 OSSharedPtr<OSData> prelinkedExecutable; 1917 uint32_t length = 0; // reused 1918 uintptr_t kext_slide = PE_get_kc_slide(type); 1919 bool shouldSaveSegments = false; 1920 kc_format format = KCFormatUnknown; 1921 1922 if (!super::init()) { 1923 goto finish; 1924 } 1925 1926 /* Get the path. Don't look for an arch-specific path property. 1927 */ 1928 kextPath = OSDynamicCast(OSString, 1929 anInfoDict->getObject(kPrelinkBundlePathKey)); 1930 1931 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 1932 goto finish; 1933 } 1934 1935 #if KASLR_KEXT_DEBUG 1936 IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString()); 1937 #endif 1938 1939 /* Also get the executable's bundle-relative path if present. 1940 * Don't look for an arch-specific path property. 1941 */ 1942 executableRelPath.reset(OSDynamicCast(OSString, 1943 anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain); 1944 userExecutableRelPath.reset(OSDynamicCast(OSString, 1945 anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain); 1946 1947 /* Don't need the paths to be in the info dictionary any more. 1948 */ 1949 anInfoDict->removeObject(kPrelinkBundlePathKey); 1950 anInfoDict->removeObject(kPrelinkExecutableRelativePathKey); 1951 1952 scratchBool = OSDynamicCast(OSBoolean, 1953 getPropertyForHostArch(kOSBundleRequireExplicitLoadKey)); 1954 if (scratchBool == kOSBooleanTrue) { 1955 flags.requireExplicitLoad = 1; 1956 } 1957 1958 /* Create an OSData wrapper around the linked executable. 1959 */ 1960 addressNum = OSDynamicCast(OSNumber, 1961 anInfoDict->getObject(kPrelinkExecutableLoadKey)); 1962 if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) { 1963 lengthNum = OSDynamicCast(OSNumber, 1964 anInfoDict->getObject(kPrelinkExecutableSizeKey)); 1965 if (!lengthNum) { 1966 OSKextLog(this, 1967 kOSKextLogErrorLevel | 1968 kOSKextLogArchiveFlag, 1969 "Kext %s can't find prelinked kext executable size.", 1970 getIdentifierCString()); 1971 return result; 1972 } 1973 1974 data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 1975 length = (uint32_t) (lengthNum->unsigned32BitValue()); 1976 1977 #if KASLR_KEXT_DEBUG 1978 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n", 1979 (unsigned long)ml_static_unslide((vm_offset_t)data), 1980 (unsigned long)data, 1981 length); 1982 #endif 1983 1984 anInfoDict->removeObject(kPrelinkExecutableLoadKey); 1985 anInfoDict->removeObject(kPrelinkExecutableSizeKey); 1986 1987 /* If the kext's load address differs from its source address, allocate 1988 * space in the kext map at the load address and copy the kext over. 1989 */ 1990 addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey)); 1991 if (addressNum) { 1992 srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 1993 1994 #if KASLR_KEXT_DEBUG 1995 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n", 1996 (unsigned long)ml_static_unslide((vm_offset_t)srcData), 1997 (unsigned long)srcData); 1998 #endif 1999 2000 if (data != srcData) { 2001 #if __LP64__ 2002 kern_return_t alloc_result; 2003 2004 alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE); 2005 if (alloc_result != KERN_SUCCESS) { 2006 OSKextLog(this, 2007 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 2008 "Failed to allocate space for prelinked kext %s.", 2009 getIdentifierCString()); 2010 goto finish; 2011 } 2012 memcpy(data, srcData, length); 2013 #else 2014 OSKextLog(this, 2015 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 2016 "Error: prelinked kext %s - source and load addresses " 2017 "differ on ILP32 architecture.", 2018 getIdentifierCString()); 2019 goto finish; 2020 #endif /* __LP64__ */ 2021 } 2022 2023 anInfoDict->removeObject(kPrelinkExecutableSourceKey); 2024 } 2025 2026 prelinkedExecutable = OSData::withBytesNoCopy(data, length); 2027 if (!prelinkedExecutable) { 2028 OSKextLog(this, 2029 kOSKextLogErrorLevel | 2030 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 2031 "Kext %s failed to create executable wrapper.", 2032 getIdentifierCString()); 2033 goto finish; 2034 } 2035 2036 /* 2037 * Fileset KCs are mapped as a whole by iBoot. 2038 * Individual kext executables should not be unmapped 2039 * by xnu. 2040 * Doing so may result in panics like rdar://85419651 2041 */ 2042 if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) { 2043 prelinkedExecutable->setDeallocFunction(NULL); 2044 } else { // Not from a Fileset KC 2045 #if VM_MAPPED_KEXTS 2046 prelinkedExecutable->setDeallocFunction(osdata_kext_free); 2047 #else 2048 prelinkedExecutable->setDeallocFunction(osdata_phys_free); 2049 #endif 2050 } 2051 setLinkedExecutable(prelinkedExecutable.get()); 2052 addressNum = OSDynamicCast(OSNumber, 2053 anInfoDict->getObject(kPrelinkKmodInfoKey)); 2054 if (!addressNum) { 2055 OSKextLog(this, 2056 kOSKextLogErrorLevel | 2057 kOSKextLogArchiveFlag, 2058 "Kext %s can't find prelinked kext kmod_info address.", 2059 getIdentifierCString()); 2060 goto finish; 2061 } 2062 2063 if (addressNum->unsigned64BitValue() != 0) { 2064 kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 2065 if (kmod_info->address) { 2066 kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide); 2067 } else { 2068 kmod_info->address = (uintptr_t)data; 2069 kmod_info->size = length; 2070 } 2071 #if KASLR_KEXT_DEBUG 2072 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n", 2073 (unsigned long)((vm_offset_t)kmod_info) - kext_slide, 2074 (unsigned long)kmod_info); 2075 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n", 2076 (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide, 2077 (unsigned long)kmod_info->address); 2078 #endif 2079 } 2080 2081 anInfoDict->removeObject(kPrelinkKmodInfoKey); 2082 } 2083 2084 if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) { 2085 uintptr_t builtinTextStart; 2086 uintptr_t builtinTextEnd; 2087 2088 flags.builtin = true; 2089 builtinKmodIdx = addressNum->unsigned32BitValue(); 2090 assert(builtinKmodIdx < gBuiltinKmodsCount); 2091 2092 builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx]; 2093 builtinTextEnd = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1]; 2094 2095 kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx]; 2096 kmod_info->address = builtinTextStart; 2097 kmod_info->size = builtinTextEnd - builtinTextStart; 2098 } 2099 2100 /* If the plist has a UUID for an interface, save that off. 2101 */ 2102 if (isInterface()) { 2103 interfaceUUID.reset(OSDynamicCast(OSData, 2104 anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain); 2105 if (interfaceUUID) { 2106 anInfoDict->removeObject(kPrelinkInterfaceUUIDKey); 2107 } 2108 } 2109 2110 result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides)); 2111 if (!result) { 2112 goto finish; 2113 } 2114 2115 kc_type = type; 2116 /* Exclude builtin and codeless kexts */ 2117 if (prelinkedExecutable && kmod_info) { 2118 switch (kc_type) { 2119 case KCKindPrimary: 2120 shouldSaveSegments = ( 2121 getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue || 2122 getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue); 2123 if (shouldSaveSegments) { 2124 flags.resetSegmentsFromImmutableCopy = 1; 2125 } else { 2126 flags.unloadUnsupported = 1; 2127 } 2128 break; 2129 case KCKindPageable: 2130 flags.resetSegmentsFromVnode = 1; 2131 break; 2132 case KCKindAuxiliary: 2133 if (!pageableKCloaded) { 2134 flags.resetSegmentsFromImmutableCopy = 1; 2135 } else if (resetAuxKCSegmentOnUnload) { 2136 flags.resetSegmentsFromVnode = 1; 2137 } else { 2138 flags.unloadUnsupported = 1; 2139 } 2140 break; 2141 default: 2142 break; 2143 } 2144 } 2145 2146 if (flags.resetSegmentsFromImmutableCopy) { 2147 /* Save a pristine copy of the mutable segments */ 2148 kernel_segment_command_t *seg = NULL; 2149 kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address; 2150 2151 savedMutableSegments = OSArray::withCapacity(0); 2152 2153 for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) { 2154 if (!segmentIsMutable(seg)) { 2155 continue; 2156 } 2157 uint64_t unslid_vmaddr = seg->vmaddr - kext_slide; 2158 uint64_t vmsize = seg->vmsize; 2159 OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2160 "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1); 2161 OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg); 2162 if (!savedSegment) { 2163 OSKextLog(this, 2164 kOSKextLogErrorLevel | 2165 kOSKextLogGeneralFlag, 2166 "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 2167 result = false; 2168 goto finish; 2169 } 2170 savedMutableSegments->setObject(savedSegment); 2171 } 2172 } 2173 2174 if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) { 2175 /* 2176 * set VM protections now, wire pages for the old style Aux KC now, 2177 * wire pages for the rest of the KC types at load time. 2178 */ 2179 result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false)); 2180 if (!result) { 2181 goto finish; 2182 } 2183 } 2184 2185 flags.prelinked = true; 2186 2187 if (isDriverKit()) { 2188 dextStatistics = OSDextStatistics::create(); 2189 dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain); 2190 dextLaunchedCount = 0; 2191 } 2192 2193 /* If we created a kext from prelink info, 2194 * we must be booting from a prelinked kernel. 2195 */ 2196 sPrelinkBoot = true; 2197 2198 result = (registerIdentifier() == kOSKextInitialized); 2199 finish: 2200 return result; 2201 } 2202 2203 /********************************************************************* 2204 *********************************************************************/ 2205 /* static */ 2206 OSSharedPtr<OSKext> 2207 OSKext::withCodelessInfo(OSDictionary * anInfoDict, OSKextInitResult *result) 2208 { 2209 OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>(); 2210 if (!newKext) { 2211 return NULL; 2212 } 2213 2214 OSKextInitResult ret = newKext->initWithCodelessInfo(anInfoDict); 2215 if (result != NULL) { 2216 *result = ret; 2217 } 2218 if (ret != kOSKextInitialized) { 2219 return NULL; 2220 } 2221 2222 return newKext; 2223 } 2224 2225 /********************************************************************* 2226 *********************************************************************/ 2227 OSKextInitResult 2228 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict) 2229 { 2230 OSKextInitResult result = kOSKextInitFailure; 2231 OSString * kextPath = NULL; // do not release 2232 OSBoolean * scratchBool = NULL; // do not release 2233 2234 if (anInfoDict == NULL || !super::init()) { 2235 goto finish; 2236 } 2237 2238 /* 2239 * Get the path. Don't look for an arch-specific path property. 2240 */ 2241 kextPath = OSDynamicCast(OSString, 2242 anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey)); 2243 if (!kextPath) { 2244 OSKextLog(NULL, 2245 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 2246 "Requested codeless kext dictionary does not contain the '%s' key", 2247 kKextRequestArgumentCodelessInfoBundlePathKey); 2248 goto finish; 2249 } 2250 2251 uniquePersonalityProperties(anInfoDict); 2252 2253 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 2254 goto finish; 2255 } 2256 2257 /* 2258 * This path is meant to initialize codeless kexts only. Refuse 2259 * anything that looks like it has an executable and/or declares 2260 * itself as a kernel component. 2261 */ 2262 if (declaresExecutable() || isKernelComponent()) { 2263 OSKextLog(NULL, 2264 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 2265 "Refusing to register codeless kext that declares an executable/kernel component: %s", 2266 getIdentifierCString()); 2267 goto finish; 2268 } 2269 2270 if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) { 2271 boolean_t updated = updateExcludeList(infoDict.get()); 2272 if (updated) { 2273 OSKextLog(this, 2274 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2275 "KextExcludeList was updated to version: %lld", sExcludeListVersion); 2276 } 2277 } 2278 2279 kc_type = KCKindNone; 2280 2281 scratchBool = OSDynamicCast(OSBoolean, 2282 getPropertyForHostArch(kOSBundleRequireExplicitLoadKey)); 2283 if (scratchBool == kOSBooleanTrue) { 2284 flags.requireExplicitLoad = 1; 2285 } 2286 2287 /* Also get the executable's bundle-relative path if present. 2288 * Don't look for an arch-specific path property. 2289 */ 2290 userExecutableRelPath.reset(OSDynamicCast(OSString, 2291 anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain); 2292 2293 /* remove unnecessary paths from the info dict */ 2294 anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey); 2295 2296 if (isDriverKit()) { 2297 dextStatistics = OSDextStatistics::create(); 2298 dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain); 2299 dextLaunchedCount = 0; 2300 } 2301 2302 result = registerIdentifier(); 2303 2304 finish: 2305 return result; 2306 } 2307 2308 /********************************************************************* 2309 *********************************************************************/ 2310 /* static */ 2311 void 2312 OSKext::setAllVMAttributes(void) 2313 { 2314 OSSharedPtr<OSCollectionIterator> kextIterator; 2315 const OSSymbol * thisID = NULL; // do not release 2316 2317 IORecursiveLockLock(sKextLock); 2318 2319 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 2320 if (!kextIterator) { 2321 goto finish; 2322 } 2323 2324 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 2325 OSKext * thisKext; // do not release 2326 2327 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 2328 if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) { 2329 continue; 2330 } 2331 2332 if (!thisKext->flags.resetSegmentsFromVnode) { 2333 /* 2334 * set VM protections now, wire pages for the old style Aux KC now, 2335 * wire pages for the rest of the KC types at load time. 2336 */ 2337 thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false); 2338 } 2339 } 2340 2341 finish: 2342 IORecursiveLockUnlock(sKextLock); 2343 2344 return; 2345 } 2346 2347 /********************************************************************* 2348 *********************************************************************/ 2349 OSSharedPtr<OSKext> 2350 OSKext::withBooterData( 2351 OSString * deviceTreeName, 2352 OSData * booterData) 2353 { 2354 OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>()); 2355 2356 if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) { 2357 return NULL; 2358 } 2359 2360 return newKext; 2361 } 2362 2363 /********************************************************************* 2364 *********************************************************************/ 2365 typedef struct _BooterKextFileInfo { 2366 uint32_t infoDictPhysAddr; 2367 uint32_t infoDictLength; 2368 uint32_t executablePhysAddr; 2369 uint32_t executableLength; 2370 uint32_t bundlePathPhysAddr; 2371 uint32_t bundlePathLength; 2372 } _BooterKextFileInfo; 2373 2374 bool 2375 OSKext::initWithBooterData( 2376 OSString * deviceTreeName, 2377 OSData * booterData) 2378 { 2379 bool result = false; 2380 _BooterKextFileInfo * kextFileInfo = NULL; // do not free 2381 char * infoDictAddr = NULL; // do not free 2382 void * executableAddr = NULL; // do not free 2383 char * bundlePathAddr = NULL; // do not free 2384 2385 OSDictionary * theInfoDict = NULL; // do not release 2386 OSSharedPtr<OSObject> parsedXML; 2387 OSSharedPtr<OSString> kextPath; 2388 2389 OSSharedPtr<OSString> errorString; 2390 OSSharedPtr<OSData> executable; 2391 2392 if (!super::init()) { 2393 goto finish; 2394 } 2395 2396 kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy(); 2397 if (!kextFileInfo) { 2398 OSKextLog(this, 2399 kOSKextLogErrorLevel | 2400 kOSKextLogGeneralFlag, 2401 "No booter-provided data for kext device tree entry %s.", 2402 deviceTreeName->getCStringNoCopy()); 2403 goto finish; 2404 } 2405 2406 /* The info plist must exist or we can't read the kext. 2407 */ 2408 if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) { 2409 OSKextLog(this, 2410 kOSKextLogErrorLevel | 2411 kOSKextLogGeneralFlag, 2412 "No kext info dictionary for booter device tree entry %s.", 2413 deviceTreeName->getCStringNoCopy()); 2414 goto finish; 2415 } 2416 2417 infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 2418 if (!infoDictAddr) { 2419 OSKextLog(this, 2420 kOSKextLogErrorLevel | 2421 kOSKextLogGeneralFlag, 2422 "Can't translate physical address 0x%x of kext info dictionary " 2423 "for device tree entry %s.", 2424 (int)kextFileInfo->infoDictPhysAddr, 2425 deviceTreeName->getCStringNoCopy()); 2426 goto finish; 2427 } 2428 2429 parsedXML = OSUnserializeXML(infoDictAddr, errorString); 2430 if (parsedXML) { 2431 theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 2432 } 2433 if (!theInfoDict) { 2434 const char * errorCString = "(unknown error)"; 2435 2436 if (errorString && errorString->getCStringNoCopy()) { 2437 errorCString = errorString->getCStringNoCopy(); 2438 } else if (parsedXML) { 2439 errorCString = "not a dictionary"; 2440 } 2441 OSKextLog(this, 2442 kOSKextLogErrorLevel | 2443 kOSKextLogGeneralFlag, 2444 "Error unserializing info dictionary for device tree entry %s: %s.", 2445 deviceTreeName->getCStringNoCopy(), errorCString); 2446 goto finish; 2447 } 2448 2449 /* A bundle path is not mandatory. 2450 */ 2451 if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) { 2452 bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr); 2453 if (!bundlePathAddr) { 2454 OSKextLog(this, 2455 kOSKextLogErrorLevel | 2456 kOSKextLogGeneralFlag, 2457 "Can't translate physical address 0x%x of kext bundle path " 2458 "for device tree entry %s.", 2459 (int)kextFileInfo->bundlePathPhysAddr, 2460 deviceTreeName->getCStringNoCopy()); 2461 goto finish; 2462 } 2463 bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0'; // just in case! 2464 2465 kextPath = OSString::withCString(bundlePathAddr); 2466 if (!kextPath) { 2467 OSKextLog(this, 2468 kOSKextLogErrorLevel | 2469 kOSKextLogGeneralFlag, 2470 "Failed to create wrapper for device tree entry %s kext path %s.", 2471 deviceTreeName->getCStringNoCopy(), bundlePathAddr); 2472 goto finish; 2473 } 2474 } 2475 2476 if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) { 2477 goto finish; 2478 } 2479 2480 /* An executable is not mandatory. 2481 */ 2482 if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) { 2483 executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr); 2484 if (!executableAddr) { 2485 OSKextLog(this, 2486 kOSKextLogErrorLevel | 2487 kOSKextLogGeneralFlag, 2488 "Can't translate physical address 0x%x of kext executable " 2489 "for device tree entry %s.", 2490 (int)kextFileInfo->executablePhysAddr, 2491 deviceTreeName->getCStringNoCopy()); 2492 goto finish; 2493 } 2494 2495 executable = OSData::withBytesNoCopy(executableAddr, 2496 kextFileInfo->executableLength); 2497 if (!executable) { 2498 OSKextLog(this, 2499 kOSKextLogErrorLevel | 2500 kOSKextLogGeneralFlag, 2501 "Failed to create executable wrapper for device tree entry %s.", 2502 deviceTreeName->getCStringNoCopy()); 2503 goto finish; 2504 } 2505 2506 /* A kext with an executable needs to retain the whole booterData 2507 * object to keep the executable in memory. 2508 */ 2509 if (!setExecutable(executable.get(), booterData)) { 2510 OSKextLog(this, 2511 kOSKextLogErrorLevel | 2512 kOSKextLogGeneralFlag, 2513 "Failed to set kext executable for device tree entry %s.", 2514 deviceTreeName->getCStringNoCopy()); 2515 goto finish; 2516 } 2517 } 2518 2519 if (isDriverKit()) { 2520 dextStatistics = OSDextStatistics::create(); 2521 dextUniqueID.reset(parseDextUniqueID(theInfoDict, getIdentifierCString()), OSRetain); 2522 dextLaunchedCount = 0; 2523 } 2524 2525 result = (registerIdentifier() == kOSKextInitialized); 2526 2527 finish: 2528 return result; 2529 } 2530 2531 /********************************************************************* 2532 *********************************************************************/ 2533 OSKextInitResult 2534 OSKext::registerIdentifier(void) 2535 { 2536 OSKextInitResult result = kOSKextInitFailure; 2537 OSKext * existingKext = NULL; // do not release 2538 bool existingIsLoaded = false; 2539 bool existingIsPrelinked = false; 2540 bool existingIsCodeless = false; 2541 bool existingIsDext = false; 2542 OSKextVersion newVersion = -1; 2543 OSKextVersion existingVersion = -1; 2544 char newVersionCString[kOSKextVersionMaxLength]; 2545 char existingVersionCString[kOSKextVersionMaxLength]; 2546 OSSharedPtr<OSData> newUUID; 2547 OSSharedPtr<OSData> existingUUID; 2548 const char *newDextUniqueIDCString = NULL; 2549 const char *existingDextUniqueIDCString = NULL; 2550 unsigned int newDextUniqueIDCStringSize = 0; 2551 unsigned int existingDextUniqueIDCStringSize = 0; 2552 2553 IORecursiveLockLock(sKextLock); 2554 2555 /* Get the new kext's version for checks & log messages. 2556 */ 2557 newVersion = getVersion(); 2558 OSKextVersionGetString(newVersion, newVersionCString, 2559 kOSKextVersionMaxLength); 2560 2561 /* If we don't have an existing kext with this identifier, 2562 * just record the new kext and we're done! 2563 */ 2564 existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get())); 2565 if (!existingKext) { 2566 sKextsByID->setObject(bundleID.get(), this); 2567 result = kOSKextInitialized; 2568 goto finish; 2569 } 2570 2571 /* Get the existing kext's version for checks & log messages. 2572 */ 2573 existingVersion = existingKext->getVersion(); 2574 OSKextVersionGetString(existingVersion, 2575 existingVersionCString, kOSKextVersionMaxLength); 2576 2577 existingIsLoaded = existingKext->isLoaded(); 2578 existingIsPrelinked = existingKext->isPrelinked(); 2579 existingIsDext = existingKext->isDriverKit(); 2580 existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext; 2581 2582 /* 2583 * Check if we are trying to upgrade a dext 2584 * with another dext. 2585 */ 2586 if (isDriverKit() && existingIsDext) { 2587 OSData *newDextUID = getDextUniqueID(); 2588 if (!newDextUID) { 2589 OSKextLog(this, 2590 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2591 "New dext %s, v%s requested does not have a unique dext identifier\n", 2592 getIdentifierCString(), newVersionCString); 2593 goto finish; 2594 } 2595 newDextUniqueIDCString = getDextUniqueIDCString(newDextUID, &newDextUniqueIDCStringSize); 2596 assert(newDextUniqueIDCString != NULL); 2597 2598 OSData *existingDextUID = existingKext->getDextUniqueID(); 2599 if (!existingDextUID) { 2600 OSKextLog(this, 2601 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2602 "Found a dext %s, v%s: with no unique dext identifier\n", 2603 existingKext->getIdentifierCString(), existingVersionCString); 2604 goto finish; 2605 } 2606 existingDextUniqueIDCString = getDextUniqueIDCString(existingDextUID, &existingDextUniqueIDCStringSize); 2607 assert(existingDextUniqueIDCString != NULL); 2608 2609 /* 2610 * We might get multiple requests to save the same dext. 2611 * Check if we already have saved it or if this is an upgrade 2612 * for a dext with the same BundleID. 2613 * Dexts are uniquely identified by DextUniqueID, if a new DextUniqueID 2614 * is requested for a BundleID we are going to upgrade to the newest 2615 * received irrespective from the dext version. 2616 */ 2617 if (newDextUID->isEqualTo(existingDextUID) && existingKext->flags.dextToReplace == 0) { 2618 OSKextLog(this, 2619 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2620 "Refusing new dext %s, v%s:" 2621 "a dext v %s with the same unique dext identifier (%s) already exists\n", 2622 getIdentifierCString(), newVersionCString, 2623 existingVersionCString, newDextUniqueIDCString); 2624 result = kOSKextAlreadyExist; 2625 goto finish; 2626 } 2627 2628 bool upgraded = upgradeDext(existingKext, this); 2629 if (upgraded) { 2630 /* If the dext was upgraded existingKext might have been deallocated */ 2631 existingKext = NULL; 2632 OSKextLog(this, 2633 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2634 "Dext %s, v%s , unique dext identifier %s " 2635 "Upgraded to v%s, unique dext identifier %s \n", 2636 getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString, 2637 newVersionCString, newDextUniqueIDCString); 2638 result = kOSKextInitialized; 2639 } else { 2640 OSKextLog(this, 2641 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2642 "Upgrade delayed for %s v%s, unique dext identifier %s " 2643 "with v%s, unique dext identifier %s.\n", 2644 getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString, 2645 newVersionCString, newDextUniqueIDCString); 2646 result = kOSKextAlreadyExist; 2647 } 2648 2649 goto finish; 2650 } 2651 2652 /* If we have a non-codeless kext with this identifier that's already 2653 * loaded/prelinked, we can't use the new one, but let's be really 2654 * thorough and check how the two are related for a precise diagnostic 2655 * log message. 2656 * 2657 * This check is valid for kexts that declare an executable and for 2658 * dexts, but not for codeless kexts - we can just replace those. 2659 */ 2660 if ((!existingIsCodeless || existingIsDext) && 2661 (existingIsLoaded || existingIsPrelinked)) { 2662 bool sameVersion = (newVersion == existingVersion); 2663 bool sameExecutable = true; // assume true unless we have UUIDs 2664 2665 /* Only get the UUID if the existing kext is loaded. Doing so 2666 * might have to uncompress an mkext executable and we shouldn't 2667 * take that hit when neither kext is loaded. 2668 * 2669 * Note: there is no decompression that happens when all kexts 2670 * are loaded from kext collecitons. 2671 */ 2672 newUUID = copyUUID(); 2673 existingUUID = existingKext->copyUUID(); 2674 2675 if (existingIsDext && !isDriverKit()) { 2676 OSKextLog(this, 2677 kOSKextLogWarningLevel | 2678 kOSKextLogKextBookkeepingFlag, 2679 "Notice - new kext %s, v%s matches a %s dext" 2680 "with the same bundle ID, v%s.", 2681 getIdentifierCString(), newVersionCString, 2682 (existingIsLoaded ? "loaded" : "prelinked"), 2683 existingVersionCString); 2684 goto finish; 2685 } 2686 2687 /* I'm entirely too paranoid about checking equivalence of executables, 2688 * but I remember nasty problems with it in the past. 2689 * 2690 * - If we have UUIDs for both kexts, compare them. 2691 * - If only one kext has a UUID, they're definitely different. 2692 */ 2693 if (newUUID && existingUUID) { 2694 sameExecutable = newUUID->isEqualTo(existingUUID.get()); 2695 } else if (newUUID || existingUUID) { 2696 sameExecutable = false; 2697 } 2698 2699 if (!newUUID && !existingUUID) { 2700 /* If there are no UUIDs, we can't really tell that the executables 2701 * are *different* without a lot of work; the loaded kext's 2702 * unrelocated executable is no longer around (and we never had it 2703 * in-kernel for a prelinked kext). We certainly don't want to do 2704 * a whole fake link for the new kext just to compare, either. 2705 */ 2706 OSKextLog(this, 2707 kOSKextLogWarningLevel | 2708 kOSKextLogKextBookkeepingFlag, 2709 "Notice - new kext %s, v%s matches %s kext " 2710 "but can't determine if executables are the same (no UUIDs).", 2711 getIdentifierCString(), 2712 newVersionCString, 2713 (existingIsLoaded ? "loaded" : "prelinked")); 2714 } 2715 2716 if (sameVersion && sameExecutable) { 2717 OSKextLog(this, 2718 (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) | 2719 kOSKextLogKextBookkeepingFlag, 2720 "Refusing new kext %s, v%s: a %s copy is already present " 2721 "(same version and executable).", 2722 getIdentifierCString(), newVersionCString, 2723 (existingIsLoaded ? "loaded" : "prelinked")); 2724 } else { 2725 if (!sameVersion) { 2726 /* This condition is significant so log it under warnings. 2727 */ 2728 OSKextLog(this, 2729 kOSKextLogWarningLevel | 2730 kOSKextLogKextBookkeepingFlag, 2731 "Refusing new kext %s, v%s: already have %s v%s.", 2732 getIdentifierCString(), 2733 newVersionCString, 2734 (existingIsLoaded ? "loaded" : "prelinked"), 2735 existingVersionCString); 2736 } else { 2737 /* This condition is significant so log it under warnings. 2738 */ 2739 OSKextLog(this, 2740 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 2741 "Refusing new kext %s, v%s: a %s copy with a different " 2742 "executable UUID is already present.", 2743 getIdentifierCString(), newVersionCString, 2744 (existingIsLoaded ? "loaded" : "prelinked")); 2745 } 2746 } 2747 goto finish; 2748 } /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */ 2749 2750 /* Refuse to allow an existing loaded codeless kext be replaced by a 2751 * normal kext with the same bundle ID. 2752 */ 2753 if (existingIsCodeless && declaresExecutable()) { 2754 OSKextLog(this, 2755 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 2756 "Refusing new kext %s, v%s: a codeless copy is already %s", 2757 getIdentifierCString(), newVersionCString, 2758 (existingIsLoaded ? "loaded" : "prelinked")); 2759 goto finish; 2760 } 2761 2762 /* Dexts packaged in the BootKC will be protected against replacement 2763 * by non-dexts by the logic above which checks if they are prelinked. 2764 * Dexts which are prelinked into the System KC will be registered 2765 * before any other kexts in the AuxKC are registered, and we never 2766 * put dexts in the AuxKC. Therefore, there is no need to check if an 2767 * existing object is a dext and is being replaced by a non-dext. 2768 * The scenario cannot happen by construction. 2769 * 2770 * See: OSKext::loadFileSetKexts() 2771 */ 2772 2773 2774 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether 2775 * user loads are happening or if we're still in early boot. User agents are 2776 * supposed to resolve dependencies topside and include only the exact 2777 * kexts needed; so we always accept the new kext (in fact we should never 2778 * see an older unloaded copy hanging around). 2779 */ 2780 if (sUserLoadsActive) { 2781 sKextsByID->setObject(bundleID.get(), this); 2782 result = kOSKextInitialized; 2783 2784 OSKextLog(this, 2785 kOSKextLogStepLevel | 2786 kOSKextLogKextBookkeepingFlag, 2787 "Dropping old copy of kext %s (v%s) for newly-added (v%s).", 2788 getIdentifierCString(), 2789 existingVersionCString, 2790 newVersionCString); 2791 2792 goto finish; 2793 } 2794 2795 /* During early boot, the kext with the highest version always wins out. 2796 * Prelinked kernels will never hit this, but mkexts and booter-read 2797 * kexts might have duplicates. 2798 */ 2799 if (newVersion > existingVersion) { 2800 sKextsByID->setObject(bundleID.get(), this); 2801 result = kOSKextInitialized; 2802 2803 OSKextLog(this, 2804 kOSKextLogStepLevel | 2805 kOSKextLogKextBookkeepingFlag, 2806 "Dropping lower version (v%s) of registered kext %s for higher (v%s).", 2807 existingVersionCString, 2808 getIdentifierCString(), 2809 newVersionCString); 2810 } else { 2811 OSKextLog(this, 2812 kOSKextLogStepLevel | 2813 kOSKextLogKextBookkeepingFlag, 2814 "Kext %s is already registered with a higher/same version (v%s); " 2815 "dropping newly-added (v%s).", 2816 getIdentifierCString(), 2817 existingVersionCString, 2818 newVersionCString); 2819 } 2820 2821 /* result has been set appropriately by now. */ 2822 2823 finish: 2824 2825 IORecursiveLockUnlock(sKextLock); 2826 2827 if (newDextUniqueIDCString != NULL) { 2828 kfree_data(newDextUniqueIDCString, newDextUniqueIDCStringSize); 2829 } 2830 if (existingDextUniqueIDCString != NULL) { 2831 kfree_data(existingDextUniqueIDCString, existingDextUniqueIDCStringSize); 2832 } 2833 2834 if (result == kOSKextInitialized) { 2835 OSKextLog(this, 2836 kOSKextLogStepLevel | 2837 kOSKextLogKextBookkeepingFlag, 2838 "Kext %s, v%s registered and available for loading.", 2839 getIdentifierCString(), newVersionCString); 2840 } 2841 2842 return result; 2843 } 2844 2845 /********************************************************************* 2846 * Does the bare minimum validation to look up a kext. 2847 * All other validation is done on the spot as needed. 2848 **********************************************************************/ 2849 bool 2850 OSKext::setInfoDictionaryAndPath( 2851 OSDictionary * aDictionary, 2852 OSString * aPath) 2853 { 2854 bool result = false; 2855 OSString * bundleIDString = NULL; // do not release 2856 OSString * versionString = NULL; // do not release 2857 OSString * compatibleVersionString = NULL; // do not release 2858 const char * versionCString = NULL; // do not free 2859 const char * compatibleVersionCString = NULL; // do not free 2860 OSBoolean * scratchBool = NULL; // do not release 2861 OSDictionary * scratchDict = NULL; // do not release 2862 2863 if (infoDict) { 2864 panic("Attempt to set info dictionary on a kext " 2865 "that already has one (%s).", 2866 getIdentifierCString()); 2867 } 2868 2869 if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) { 2870 goto finish; 2871 } 2872 2873 infoDict.reset(aDictionary, OSRetain); 2874 2875 /* Check right away if the info dictionary has any log flags. 2876 */ 2877 scratchBool = OSDynamicCast(OSBoolean, 2878 getPropertyForHostArch(kOSBundleEnableKextLoggingKey)); 2879 if (scratchBool == kOSBooleanTrue) { 2880 flags.loggingEnabled = 1; 2881 } 2882 2883 /* The very next thing to get is the bundle identifier. Unlike 2884 * in user space, a kext with no bundle identifier gets axed 2885 * immediately. 2886 */ 2887 bundleIDString = OSDynamicCast(OSString, 2888 getPropertyForHostArch(kCFBundleIdentifierKey)); 2889 if (!bundleIDString) { 2890 OSKextLog(this, 2891 kOSKextLogErrorLevel | 2892 kOSKextLogValidationFlag, 2893 "CFBundleIdentifier missing/invalid type in kext %s.", 2894 aPath ? aPath->getCStringNoCopy() : "(unknown)"); 2895 goto finish; 2896 } 2897 bundleID = OSSymbol::withString(bundleIDString); 2898 if (!bundleID) { 2899 OSKextLog(this, 2900 kOSKextLogErrorLevel | 2901 kOSKextLogValidationFlag, 2902 "Can't copy bundle identifier as symbol for kext %s.", 2903 bundleIDString->getCStringNoCopy()); 2904 goto finish; 2905 } 2906 2907 /* Save the path if we got one (it should always be available but it's 2908 * just something nice to have for bookkeeping). 2909 */ 2910 if (aPath) { 2911 path.reset(aPath, OSRetain); 2912 } 2913 2914 /***** 2915 * Minimal validation to initialize. We'll do other validation on the spot. 2916 */ 2917 if (bundleID->getLength() >= KMOD_MAX_NAME) { 2918 OSKextLog(this, 2919 kOSKextLogErrorLevel | 2920 kOSKextLogValidationFlag, 2921 "Kext %s error - CFBundleIdentifier over max length %d.", 2922 getIdentifierCString(), KMOD_MAX_NAME - 1); 2923 goto finish; 2924 } 2925 2926 version = compatibleVersion = -1; 2927 2928 versionString = OSDynamicCast(OSString, 2929 getPropertyForHostArch(kCFBundleVersionKey)); 2930 if (!versionString) { 2931 OSKextLog(this, 2932 kOSKextLogErrorLevel | 2933 kOSKextLogValidationFlag, 2934 "Kext %s error - CFBundleVersion missing/invalid type.", 2935 getIdentifierCString()); 2936 goto finish; 2937 } 2938 versionCString = versionString->getCStringNoCopy(); 2939 version = OSKextParseVersionString(versionCString); 2940 if (version < 0) { 2941 OSKextLog(this, 2942 kOSKextLogErrorLevel | 2943 kOSKextLogValidationFlag, 2944 "Kext %s error - CFBundleVersion bad value '%s'.", 2945 getIdentifierCString(), versionCString); 2946 goto finish; 2947 } 2948 2949 compatibleVersion = -1; // set to illegal value for kexts that don't have 2950 2951 compatibleVersionString = OSDynamicCast(OSString, 2952 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 2953 if (compatibleVersionString) { 2954 compatibleVersionCString = compatibleVersionString->getCStringNoCopy(); 2955 compatibleVersion = OSKextParseVersionString(compatibleVersionCString); 2956 if (compatibleVersion < 0) { 2957 OSKextLog(this, 2958 kOSKextLogErrorLevel | 2959 kOSKextLogValidationFlag, 2960 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.", 2961 getIdentifierCString(), compatibleVersionCString); 2962 goto finish; 2963 } 2964 2965 if (compatibleVersion > version) { 2966 OSKextLog(this, 2967 kOSKextLogErrorLevel | 2968 kOSKextLogValidationFlag, 2969 "Kext %s error - %s %s > %s %s (must be <=).", 2970 getIdentifierCString(), 2971 kOSBundleCompatibleVersionKey, compatibleVersionCString, 2972 kCFBundleVersionKey, versionCString); 2973 goto finish; 2974 } 2975 } 2976 2977 /* Check to see if this kext is in exclude list */ 2978 if (isInExcludeList()) { 2979 OSKextLog(this, 2980 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 2981 "Kext %s is in exclude list, not loadable", 2982 getIdentifierCString()); 2983 goto finish; 2984 } 2985 2986 /* Set flags for later use if the infoDict gets flushed. We only 2987 * check for true values, not false ones(!) 2988 */ 2989 scratchBool = OSDynamicCast(OSBoolean, 2990 getPropertyForHostArch(kOSBundleIsInterfaceKey)); 2991 if (scratchBool == kOSBooleanTrue) { 2992 flags.interface = 1; 2993 } 2994 2995 scratchBool = OSDynamicCast(OSBoolean, 2996 getPropertyForHostArch(kOSKernelResourceKey)); 2997 if (scratchBool == kOSBooleanTrue) { 2998 flags.kernelComponent = 1; 2999 flags.interface = 1; // xxx - hm. the kernel itself isn't an interface... 3000 flags.started = 1; 3001 3002 /* A kernel component has one implicit dependency on the kernel. 3003 */ 3004 flags.hasAllDependencies = 1; 3005 } 3006 3007 /* Make sure common string values in personalities are uniqued to OSSymbols. 3008 */ 3009 scratchDict = OSDynamicCast(OSDictionary, 3010 getPropertyForHostArch(kIOKitPersonalitiesKey)); 3011 if (scratchDict) { 3012 uniquePersonalityProperties(scratchDict); 3013 } 3014 3015 result = true; 3016 3017 finish: 3018 3019 return result; 3020 } 3021 3022 /********************************************************************* 3023 * Not used for prelinked kernel boot as there is no unrelocated 3024 * executable. 3025 *********************************************************************/ 3026 bool 3027 OSKext::setExecutable( 3028 OSData * anExecutable, 3029 OSData * externalData, 3030 bool externalDataIsMkext) 3031 { 3032 bool result = false; 3033 const char * executableKey = NULL; // do not free 3034 3035 if (!anExecutable) { 3036 infoDict->removeObject(_kOSKextExecutableKey); 3037 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 3038 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 3039 result = true; 3040 goto finish; 3041 } 3042 3043 if (infoDict->getObject(_kOSKextExecutableKey) || 3044 infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) { 3045 panic("Attempt to set an executable on a kext " 3046 "that already has one (%s).", 3047 getIdentifierCString()); 3048 goto finish; 3049 } 3050 3051 if (externalDataIsMkext) { 3052 executableKey = _kOSKextMkextExecutableReferenceKey; 3053 } else { 3054 executableKey = _kOSKextExecutableKey; 3055 } 3056 3057 if (anExecutable) { 3058 infoDict->setObject(executableKey, anExecutable); 3059 if (externalData) { 3060 infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData); 3061 } 3062 } 3063 3064 result = true; 3065 3066 finish: 3067 return result; 3068 } 3069 3070 /********************************************************************* 3071 *********************************************************************/ 3072 static void 3073 uniqueStringPlistProperty(OSDictionary * dict, const char * key) 3074 { 3075 OSObject * value = NULL; // do not release 3076 OSString * stringValue = NULL; // do not release 3077 OSSharedPtr<const OSSymbol> symbolValue; 3078 3079 value = dict->getObject(key); 3080 if (!value) { 3081 goto finish; 3082 } 3083 if (OSDynamicCast(OSSymbol, value)) { 3084 /* this is already an OSSymbol: we're good */ 3085 goto finish; 3086 } 3087 3088 stringValue = OSDynamicCast(OSString, value); 3089 if (!stringValue) { 3090 goto finish; 3091 } 3092 3093 symbolValue = OSSymbol::withString(stringValue); 3094 if (!symbolValue) { 3095 goto finish; 3096 } 3097 3098 dict->setObject(key, symbolValue.get()); 3099 3100 finish: 3101 return; 3102 } 3103 3104 /********************************************************************* 3105 *********************************************************************/ 3106 static void 3107 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key) 3108 { 3109 OSObject * value = NULL; // do not release 3110 OSString * stringValue = NULL; // do not release 3111 OSSharedPtr<const OSSymbol> symbolValue; 3112 3113 value = dict->getObject(key); 3114 if (!value) { 3115 goto finish; 3116 } 3117 if (OSDynamicCast(OSSymbol, value)) { 3118 /* this is already an OSSymbol: we're good */ 3119 goto finish; 3120 } 3121 3122 stringValue = OSDynamicCast(OSString, value); 3123 if (!stringValue) { 3124 goto finish; 3125 } 3126 3127 symbolValue = OSSymbol::withString(stringValue); 3128 if (!symbolValue) { 3129 goto finish; 3130 } 3131 3132 dict->setObject(key, symbolValue.get()); 3133 3134 finish: 3135 return; 3136 } 3137 3138 void 3139 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict) 3140 { 3141 OSKext::uniquePersonalityProperties(personalityDict, true); 3142 } 3143 3144 /********************************************************************* 3145 * Replace common personality property values with uniqued instances 3146 * to save on wired memory. 3147 *********************************************************************/ 3148 /* static */ 3149 void 3150 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier) 3151 { 3152 /* Properties every personality has. 3153 */ 3154 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey); 3155 uniqueStringPlistProperty(personalityDict, kIOProviderClassKey); 3156 uniqueStringPlistProperty(personalityDict, gIOClassKey.get()); 3157 if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) { 3158 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey); 3159 } else if (defaultAddKernelBundleIdentifier) { 3160 personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey)); 3161 } 3162 3163 /* Other commonly used properties. 3164 */ 3165 uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey); 3166 uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey); 3167 uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey); 3168 3169 uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior"); 3170 uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType"); 3171 uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType"); 3172 uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType"); 3173 uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher"); 3174 uniqueStringPlistProperty(personalityDict, "Physical Interconnect"); 3175 uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location"); 3176 uniqueStringPlistProperty(personalityDict, "Vendor"); 3177 uniqueStringPlistProperty(personalityDict, "Vendor Identification"); 3178 uniqueStringPlistProperty(personalityDict, "Vendor Name"); 3179 uniqueStringPlistProperty(personalityDict, "bConfigurationValue"); 3180 uniqueStringPlistProperty(personalityDict, "bInterfaceNumber"); 3181 uniqueStringPlistProperty(personalityDict, "idProduct"); 3182 3183 return; 3184 } 3185 3186 /********************************************************************* 3187 *********************************************************************/ 3188 void 3189 OSKext::free(void) 3190 { 3191 if (isLoaded()) { 3192 panic("Attempt to free loaded kext %s.", getIdentifierCString()); 3193 } 3194 3195 if (isDriverKit()) { 3196 if (dextLaunchedCount > 0) { 3197 panic("Freeing dext %s but dextLaunchedCount is %d\n", getIdentifierCString(), dextLaunchedCount); 3198 } 3199 } 3200 3201 infoDict.reset(); 3202 bundleID.reset(); 3203 path.reset(); 3204 executableRelPath.reset(); 3205 userExecutableRelPath.reset(); 3206 dependencies.reset(); 3207 linkedExecutable.reset(); 3208 metaClasses.reset(); 3209 interfaceUUID.reset(); 3210 driverKitUUID.reset(); 3211 dextStatistics.reset(); 3212 dextUniqueID.reset(); 3213 3214 if (isInterface() && kmod_info) { 3215 kfree_type(kmod_info_t, kmod_info); 3216 } 3217 3218 super::free(); 3219 return; 3220 } 3221 3222 #if PRAGMA_MARK 3223 #pragma mark Mkext files 3224 #endif 3225 3226 #if CONFIG_KXLD 3227 /* 3228 * mkext archives are really only relevant on kxld-enabled kernels. 3229 * Without a dynamic kernel linker, we don't need to support any mkexts. 3230 */ 3231 3232 /********************************************************************* 3233 *********************************************************************/ 3234 OSReturn 3235 OSKext::readMkextArchive(OSData * mkextData, 3236 uint32_t * checksumPtr) 3237 { 3238 OSReturn result = kOSKextReturnBadData; 3239 uint32_t mkextLength = 0; 3240 mkext_header * mkextHeader = NULL; // do not free 3241 uint32_t mkextVersion = 0; 3242 3243 /* Note default return of kOSKextReturnBadData above. 3244 */ 3245 mkextLength = mkextData->getLength(); 3246 if (mkextLength < sizeof(mkext_basic_header)) { 3247 OSKextLog(/* kext */ NULL, 3248 kOSKextLogErrorLevel | 3249 kOSKextLogArchiveFlag, 3250 "Mkext archive too small to be valid."); 3251 goto finish; 3252 } 3253 3254 mkextHeader = (mkext_header *)mkextData->getBytesNoCopy(); 3255 3256 if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC || 3257 MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) { 3258 OSKextLog(/* kext */ NULL, 3259 kOSKextLogErrorLevel | 3260 kOSKextLogArchiveFlag, 3261 "Mkext archive has invalid magic or signature."); 3262 goto finish; 3263 } 3264 3265 if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) { 3266 OSKextLog(/* kext */ NULL, 3267 kOSKextLogErrorLevel | 3268 kOSKextLogArchiveFlag, 3269 "Mkext archive recorded length doesn't match actual file length."); 3270 goto finish; 3271 } 3272 3273 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 3274 3275 if (mkextVersion == MKEXT_VERS_2) { 3276 result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr); 3277 } else { 3278 OSKextLog(/* kext */ NULL, 3279 kOSKextLogErrorLevel | 3280 kOSKextLogArchiveFlag, 3281 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion); 3282 result = kOSKextReturnUnsupported; 3283 } 3284 3285 finish: 3286 return result; 3287 } 3288 3289 /********************************************************************* 3290 * Assumes magic, signature, version, length have been checked. 3291 * xxx - need to add further bounds checking for each file entry 3292 * 3293 * Should keep track of all kexts created so far, and if we hit a 3294 * fatal error halfway through, remove those kexts. If we've dropped 3295 * an older version that had already been read, whoops! Might want to 3296 * add a level of buffering? 3297 *********************************************************************/ 3298 /* static */ 3299 OSReturn 3300 OSKext::readMkext2Archive( 3301 OSData * mkextData, 3302 OSDictionary ** mkextPlistOut, 3303 uint32_t * checksumPtr) 3304 { 3305 OSReturn result = kOSReturnError; 3306 uint32_t mkextLength; 3307 mkext2_header * mkextHeader = NULL; // do not free 3308 void * mkextEnd = NULL; // do not free 3309 uint32_t mkextVersion; 3310 uint8_t * crc_address = NULL; 3311 size_t crc_buffer_size = 0; 3312 uint32_t checksum; 3313 uint32_t mkextPlistOffset; 3314 uint32_t mkextPlistCompressedSize; 3315 char * mkextPlistEnd = NULL; // do not free 3316 uint32_t mkextPlistFullSize; 3317 OSSharedPtr<OSString> errorString; 3318 OSSharedPtr<OSData> mkextPlistUncompressedData; 3319 const char * mkextPlistDataBuffer = NULL; // do not free 3320 OSSharedPtr<OSObject> parsedXML; 3321 OSDictionary * mkextPlist = NULL; // do not release 3322 OSArray * mkextInfoDictArray = NULL; // do not release 3323 uint32_t count, i; 3324 kc_format_t kc_format; 3325 3326 if (!PE_get_primary_kc_format(&kc_format)) { 3327 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 3328 "Unable to determine primary KC format"); 3329 goto finish; 3330 } 3331 3332 mkextLength = mkextData->getLength(); 3333 mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy(); 3334 mkextEnd = (char *)mkextHeader + mkextLength; 3335 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 3336 3337 crc_address = (u_int8_t *)&mkextHeader->version; 3338 crc_buffer_size = (uintptr_t)mkextHeader + 3339 MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address; 3340 if (crc_buffer_size > INT32_MAX) { 3341 OSKextLog(/* kext */ NULL, 3342 kOSKextLogErrorLevel | 3343 kOSKextLogArchiveFlag, 3344 "Mkext archive size is too large (%lu > INT32_MAX).", 3345 crc_buffer_size); 3346 result = kOSKextReturnBadData; 3347 goto finish; 3348 } 3349 checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size); 3350 3351 if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) { 3352 OSKextLog(/* kext */ NULL, 3353 kOSKextLogErrorLevel | 3354 kOSKextLogArchiveFlag, 3355 "Mkext archive has bad checksum."); 3356 result = kOSKextReturnBadData; 3357 goto finish; 3358 } 3359 3360 if (checksumPtr) { 3361 *checksumPtr = checksum; 3362 } 3363 3364 /* Check that the CPU type & subtype match that of the running kernel. */ 3365 if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) { 3366 OSKextLog(/* kext */ NULL, 3367 kOSKextLogErrorLevel | 3368 kOSKextLogArchiveFlag, 3369 "Mkext archive must have a specific CPU type."); 3370 result = kOSKextReturnBadData; 3371 goto finish; 3372 } else { 3373 if ((UInt32)_mh_execute_header.cputype != 3374 MKEXT_GET_CPUTYPE(mkextHeader)) { 3375 OSKextLog(/* kext */ NULL, 3376 kOSKextLogErrorLevel | 3377 kOSKextLogArchiveFlag, 3378 "Mkext archive does not match the running kernel's CPU type."); 3379 result = kOSKextReturnArchNotFound; 3380 goto finish; 3381 } 3382 } 3383 3384 mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader); 3385 mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader); 3386 mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset + 3387 mkextPlistCompressedSize; 3388 if (mkextPlistEnd > mkextEnd) { 3389 OSKextLog(/* kext */ NULL, 3390 kOSKextLogErrorLevel | 3391 kOSKextLogArchiveFlag, 3392 "Mkext archive file overrun."); 3393 result = kOSKextReturnBadData; 3394 } 3395 3396 mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader); 3397 if (mkextPlistCompressedSize) { 3398 mkextPlistUncompressedData = sKernelKext->extractMkext2FileData( 3399 (UInt8 *)mkextHeader + mkextPlistOffset, 3400 "plist", 3401 mkextPlistCompressedSize, mkextPlistFullSize); 3402 if (!mkextPlistUncompressedData) { 3403 goto finish; 3404 } 3405 mkextPlistDataBuffer = (const char *) 3406 mkextPlistUncompressedData->getBytesNoCopy(); 3407 } else { 3408 mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset; 3409 } 3410 3411 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it. 3412 */ 3413 parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString); 3414 if (parsedXML) { 3415 mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get()); 3416 } 3417 if (!mkextPlist) { 3418 const char * errorCString = "(unknown error)"; 3419 3420 if (errorString && errorString->getCStringNoCopy()) { 3421 errorCString = errorString->getCStringNoCopy(); 3422 } else if (parsedXML) { 3423 errorCString = "not a dictionary"; 3424 } 3425 OSKextLog(/* kext */ NULL, 3426 kOSKextLogErrorLevel | 3427 kOSKextLogArchiveFlag, 3428 "Error unserializing mkext plist: %s.", errorCString); 3429 goto finish; 3430 } 3431 3432 mkextInfoDictArray = OSDynamicCast(OSArray, 3433 mkextPlist->getObject(kMKEXTInfoDictionariesKey)); 3434 if (!mkextInfoDictArray) { 3435 OSKextLog(/* kext */ NULL, 3436 kOSKextLogErrorLevel | 3437 kOSKextLogArchiveFlag, 3438 "Mkext archive contains no kext info dictionaries."); 3439 goto finish; 3440 } 3441 3442 count = mkextInfoDictArray->getCount(); 3443 for (i = 0; i < count; i++) { 3444 OSDictionary * infoDict; 3445 3446 3447 infoDict = OSDynamicCast(OSDictionary, 3448 mkextInfoDictArray->getObject(i)); 3449 3450 /* Create the kext for the entry, then release it, because the 3451 * kext system keeps them around until explicitly removed. 3452 * Any creation/registration failures are already logged for us. 3453 */ 3454 if (infoDict) { 3455 OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData); 3456 3457 /* Fail dynamic loading of a kext when booted from MH_FILESET */ 3458 if (kc_format == KCFormatFileset && 3459 newKext && 3460 !(newKext->isPrelinked()) && 3461 newKext->declaresExecutable()) { 3462 result = kOSReturnError; 3463 printf("Kext LOG: Dynamic loading of kext denied for kext %s\n", 3464 newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext"); 3465 3466 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 3467 "Dynamic loading of kext denied for kext %s\n", 3468 newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext"); 3469 goto finish; 3470 } 3471 } 3472 } 3473 3474 /* If the caller needs the plist, hand them back our copy 3475 */ 3476 if (mkextPlistOut) { 3477 *mkextPlistOut = mkextPlist; 3478 parsedXML.detach(); 3479 } 3480 3481 /* Even if we didn't keep any kexts from the mkext, we may have a load 3482 * request to process, so we are successful (no errors occurred). 3483 */ 3484 result = kOSReturnSuccess; 3485 3486 finish: 3487 return result; 3488 } 3489 3490 /* static */ 3491 OSReturn 3492 OSKext::readMkext2Archive( 3493 OSData * mkextData, 3494 OSSharedPtr<OSDictionary> &mkextPlistOut, 3495 uint32_t * checksumPtr) 3496 { 3497 OSDictionary * mkextPlist = NULL; 3498 OSReturn ret; 3499 3500 if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData, 3501 &mkextPlist, 3502 checksumPtr))) { 3503 mkextPlistOut.reset(mkextPlist, OSNoRetain); 3504 } 3505 return ret; 3506 } 3507 3508 /********************************************************************* 3509 *********************************************************************/ 3510 /* static */ 3511 OSSharedPtr<OSKext> 3512 OSKext::withMkext2Info( 3513 OSDictionary * anInfoDict, 3514 OSData * mkextData) 3515 { 3516 OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>(); 3517 3518 if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) { 3519 return NULL; 3520 } 3521 3522 return newKext; 3523 } 3524 3525 /********************************************************************* 3526 *********************************************************************/ 3527 bool 3528 OSKext::initWithMkext2Info( 3529 OSDictionary * anInfoDict, 3530 OSData * mkextData) 3531 { 3532 bool result = false; 3533 OSString * kextPath = NULL; // do not release 3534 OSNumber * executableOffsetNum = NULL; // do not release 3535 OSSharedPtr<OSData> executable; 3536 3537 if (anInfoDict == NULL || !super::init()) { 3538 goto finish; 3539 } 3540 3541 /* Get the path. Don't look for an arch-specific path property. 3542 */ 3543 kextPath = OSDynamicCast(OSString, 3544 anInfoDict->getObject(kMKEXTBundlePathKey)); 3545 3546 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 3547 goto finish; 3548 } 3549 3550 /* If we have a path to the executable, save it. 3551 */ 3552 executableRelPath.reset(OSDynamicCast(OSString, 3553 anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain); 3554 3555 /* Don't need the paths to be in the info dictionary any more. 3556 */ 3557 anInfoDict->removeObject(kMKEXTBundlePathKey); 3558 anInfoDict->removeObject(kMKEXTExecutableRelativePathKey); 3559 3560 executableOffsetNum = OSDynamicCast(OSNumber, 3561 infoDict->getObject(kMKEXTExecutableKey)); 3562 if (executableOffsetNum) { 3563 executable = createMkext2FileEntry(mkextData, 3564 executableOffsetNum, "executable"); 3565 infoDict->removeObject(kMKEXTExecutableKey); 3566 if (!executable) { 3567 goto finish; 3568 } 3569 if (!setExecutable(executable.get(), mkextData, true)) { 3570 goto finish; 3571 } 3572 } 3573 3574 result = (registerIdentifier() == kOSKextInitialized); 3575 finish: 3576 return result; 3577 } 3578 3579 /********************************************************************* 3580 *********************************************************************/ 3581 OSSharedPtr<OSData> 3582 OSKext::createMkext2FileEntry( 3583 OSData * mkextData, 3584 OSNumber * offsetNum, 3585 const char * name) 3586 { 3587 OSSharedPtr<OSData> result; 3588 MkextEntryRef entryRef; 3589 uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy(); 3590 uint32_t entryOffset = offsetNum->unsigned32BitValue(); 3591 3592 result = OSData::withCapacity(sizeof(entryRef)); 3593 if (!result) { 3594 goto finish; 3595 } 3596 3597 entryRef.mkext = (mkext_basic_header *)mkextBuffer; 3598 entryRef.fileinfo = mkextBuffer + entryOffset; 3599 if (!result->appendValue(entryRef)) { 3600 result.reset(); 3601 goto finish; 3602 } 3603 3604 finish: 3605 if (!result) { 3606 OSKextLog(this, 3607 kOSKextLogErrorLevel | 3608 kOSKextLogArchiveFlag, 3609 "Can't create wrapper for mkext file entry '%s' of kext %s.", 3610 name, getIdentifierCString()); 3611 } 3612 return result; 3613 } 3614 3615 /********************************************************************* 3616 *********************************************************************/ 3617 extern "C" { 3618 static void * z_alloc(void *, u_int items, u_int size); 3619 static void z_free(void *, void *ptr); 3620 3621 typedef struct z_mem { 3622 uint32_t alloc_size; 3623 uint8_t data[0]; 3624 } z_mem; 3625 3626 /* 3627 * Space allocation and freeing routines for use by zlib routines. 3628 */ 3629 void * 3630 z_alloc(void * notused __unused, u_int num_items, u_int size) 3631 { 3632 void * result = NULL; 3633 z_mem * zmem = NULL; 3634 3635 uint64_t total = ((uint64_t)num_items) * ((uint64_t)size); 3636 //Check for overflow due to multiplication 3637 if (total > UINT32_MAX) { 3638 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x", 3639 notused, num_items, size, num_items, size); 3640 } 3641 3642 uint64_t allocSize64 = total + ((uint64_t)sizeof(zmem)); 3643 //Check for overflow due to addition 3644 if (allocSize64 > UINT32_MAX) { 3645 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx", 3646 notused, num_items, size, (uint32_t)total, sizeof(zmem)); 3647 } 3648 uint32_t allocSize = (uint32_t)allocSize64; 3649 3650 zmem = (z_mem *)kalloc_data_tag(allocSize, Z_WAITOK, 3651 VM_KERN_MEMORY_OSKEXT); 3652 if (!zmem) { 3653 goto finish; 3654 } 3655 zmem->alloc_size = allocSize; 3656 result = (void *)&(zmem->data); 3657 finish: 3658 return result; 3659 } 3660 3661 void 3662 z_free(void * notused __unused, void * ptr) 3663 { 3664 uint32_t * skipper = (uint32_t *)ptr - 1; 3665 z_mem * zmem = (z_mem *)skipper; 3666 kfree_data(zmem, zmem->alloc_size); 3667 } 3668 }; 3669 3670 OSSharedPtr<OSData> 3671 OSKext::extractMkext2FileData( 3672 UInt8 * data, 3673 const char * name, 3674 uint32_t compressedSize, 3675 uint32_t fullSize) 3676 { 3677 OSSharedPtr<OSData> result; 3678 OSSharedPtr<OSData> uncompressedData; // release on error 3679 3680 uint8_t * uncompressedDataBuffer = NULL; // do not free 3681 unsigned long uncompressedSize; 3682 z_stream zstream; 3683 bool zstream_inited = false; 3684 int zlib_result; 3685 3686 /* If the file isn't compressed, we want to make a copy 3687 * so that we don't have the tie to the larger mkext file buffer any more. 3688 */ 3689 if (!compressedSize) { 3690 uncompressedData = OSData::withBytes(data, fullSize); 3691 // xxx - no check for failure? 3692 result = uncompressedData; 3693 goto finish; 3694 } 3695 3696 if (KERN_SUCCESS != kmem_alloc(kernel_map, 3697 (vm_offset_t*)&uncompressedDataBuffer, fullSize, 3698 KMA_DATA, VM_KERN_MEMORY_OSKEXT)) { 3699 /* How's this for cheesy? The kernel is only asked to extract 3700 * kext plists so we tailor the log messages. 3701 */ 3702 if (isKernel()) { 3703 OSKextLog(this, 3704 kOSKextLogErrorLevel | 3705 kOSKextLogArchiveFlag, 3706 "Allocation failure extracting %s from mkext.", name); 3707 } else { 3708 OSKextLog(this, 3709 kOSKextLogErrorLevel | 3710 kOSKextLogArchiveFlag, 3711 "Allocation failure extracting %s from mkext for kext %s.", 3712 name, getIdentifierCString()); 3713 } 3714 3715 goto finish; 3716 } 3717 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize); 3718 if (!uncompressedData) { 3719 if (isKernel()) { 3720 OSKextLog(this, 3721 kOSKextLogErrorLevel | 3722 kOSKextLogArchiveFlag, 3723 "Allocation failure extracting %s from mkext.", name); 3724 } else { 3725 OSKextLog(this, 3726 kOSKextLogErrorLevel | 3727 kOSKextLogArchiveFlag, 3728 "Allocation failure extracting %s from mkext for kext %s.", 3729 name, getIdentifierCString()); 3730 } 3731 goto finish; 3732 } 3733 uncompressedData->setDeallocFunction(&osdata_kmem_free); 3734 3735 if (isKernel()) { 3736 OSKextLog(this, 3737 kOSKextLogDetailLevel | 3738 kOSKextLogArchiveFlag, 3739 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.", 3740 name, compressedSize, fullSize); 3741 } else { 3742 OSKextLog(this, 3743 kOSKextLogDetailLevel | 3744 kOSKextLogArchiveFlag, 3745 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.", 3746 getIdentifierCString(), name, compressedSize, fullSize); 3747 } 3748 3749 bzero(&zstream, sizeof(zstream)); 3750 zstream.next_in = (UInt8 *)data; 3751 zstream.avail_in = compressedSize; 3752 3753 zstream.next_out = uncompressedDataBuffer; 3754 zstream.avail_out = fullSize; 3755 3756 zstream.zalloc = z_alloc; 3757 zstream.zfree = z_free; 3758 3759 zlib_result = inflateInit(&zstream); 3760 if (Z_OK != zlib_result) { 3761 if (isKernel()) { 3762 OSKextLog(this, 3763 kOSKextLogErrorLevel | 3764 kOSKextLogArchiveFlag, 3765 "Mkext error; zlib inflateInit failed (%d) for %s.", 3766 zlib_result, name); 3767 } else { 3768 OSKextLog(this, 3769 kOSKextLogErrorLevel | 3770 kOSKextLogArchiveFlag, 3771 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .", 3772 getIdentifierCString(), zlib_result, name); 3773 } 3774 goto finish; 3775 } else { 3776 zstream_inited = true; 3777 } 3778 3779 zlib_result = inflate(&zstream, Z_FINISH); 3780 3781 if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) { 3782 uncompressedSize = zstream.total_out; 3783 } else { 3784 if (isKernel()) { 3785 OSKextLog(this, 3786 kOSKextLogErrorLevel | 3787 kOSKextLogArchiveFlag, 3788 "Mkext error; zlib inflate failed (%d) for %s.", 3789 zlib_result, name); 3790 } else { 3791 OSKextLog(this, 3792 kOSKextLogErrorLevel | 3793 kOSKextLogArchiveFlag, 3794 "Kext %s - mkext error; zlib inflate failed (%d) for %s .", 3795 getIdentifierCString(), zlib_result, name); 3796 } 3797 if (zstream.msg) { 3798 OSKextLog(this, 3799 kOSKextLogErrorLevel | 3800 kOSKextLogArchiveFlag, 3801 "zlib error: %s.", zstream.msg); 3802 } 3803 goto finish; 3804 } 3805 3806 if (uncompressedSize != fullSize) { 3807 if (isKernel()) { 3808 OSKextLog(this, 3809 kOSKextLogErrorLevel | 3810 kOSKextLogArchiveFlag, 3811 "Mkext error; zlib inflate discrepancy for %s, " 3812 "uncompressed size != original size.", name); 3813 } else { 3814 OSKextLog(this, 3815 kOSKextLogErrorLevel | 3816 kOSKextLogArchiveFlag, 3817 "Kext %s - mkext error; zlib inflate discrepancy for %s, " 3818 "uncompressed size != original size.", 3819 getIdentifierCString(), name); 3820 } 3821 goto finish; 3822 } 3823 3824 result = os::move(uncompressedData); 3825 3826 finish: 3827 /* Don't bother checking return, nothing we can do on fail. 3828 */ 3829 if (zstream_inited) { 3830 inflateEnd(&zstream); 3831 } 3832 3833 return result; 3834 } 3835 3836 /********************************************************************* 3837 *********************************************************************/ 3838 /* static */ 3839 OSReturn 3840 OSKext::loadFromMkext( 3841 OSKextLogSpec clientLogFilter, 3842 char * mkextBuffer, 3843 uint32_t mkextBufferLength, 3844 char ** logInfoOut, 3845 uint32_t * logInfoLengthOut) 3846 { 3847 OSReturn result = kOSReturnError; 3848 OSReturn tempResult = kOSReturnError; 3849 3850 OSSharedPtr<OSData> mkextData; 3851 OSSharedPtr<OSDictionary> mkextPlist; 3852 3853 OSSharedPtr<OSArray> logInfoArray; 3854 OSSharedPtr<OSSerialize> serializer; 3855 3856 OSString * predicate = NULL; // do not release 3857 OSDictionary * requestArgs = NULL; // do not release 3858 3859 OSString * kextIdentifier = NULL; // do not release 3860 OSNumber * startKextExcludeNum = NULL; // do not release 3861 OSNumber * startMatchingExcludeNum = NULL; // do not release 3862 OSBoolean * delayAutounloadBool = NULL; // do not release 3863 OSArray * personalityNames = NULL; // do not release 3864 3865 /* Default values for these two options: regular autounload behavior, 3866 * load all kexts, send no personalities. 3867 */ 3868 Boolean delayAutounload = false; 3869 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 3870 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll; 3871 3872 IORecursiveLockLock(sKextLock); 3873 3874 if (logInfoOut) { 3875 *logInfoOut = NULL; 3876 *logInfoLengthOut = 0; 3877 } 3878 3879 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 3880 3881 OSKextLog(/* kext */ NULL, 3882 kOSKextLogDebugLevel | 3883 kOSKextLogIPCFlag, 3884 "Received kext load request from user space."); 3885 3886 /* Regardless of processing, the fact that we have gotten here means some 3887 * user-space program is up and talking to us, so we'll switch our kext 3888 * registration to reflect that. 3889 */ 3890 if (!sUserLoadsActive) { 3891 OSKextLog(/* kext */ NULL, 3892 kOSKextLogProgressLevel | 3893 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 3894 "Switching to late startup (user-space) kext loading policy."); 3895 3896 sUserLoadsActive = true; 3897 } 3898 3899 if (!sLoadEnabled) { 3900 OSKextLog(/* kext */ NULL, 3901 kOSKextLogErrorLevel | 3902 kOSKextLogLoadFlag, 3903 "Kext loading is disabled."); 3904 result = kOSKextReturnDisabled; 3905 goto finish; 3906 } 3907 3908 /* Note that we do not set a dealloc function on this OSData 3909 * object! No references to it can remain after the loadFromMkext() 3910 * call since we are in a MIG function, and will vm_deallocate() 3911 * the buffer. 3912 */ 3913 mkextData = OSData::withBytesNoCopy(mkextBuffer, 3914 mkextBufferLength); 3915 if (!mkextData) { 3916 OSKextLog(/* kext */ NULL, 3917 kOSKextLogErrorLevel | 3918 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 3919 "Failed to create wrapper for kext load request."); 3920 result = kOSKextReturnNoMemory; 3921 goto finish; 3922 } 3923 3924 result = readMkext2Archive(mkextData.get(), mkextPlist, NULL); 3925 if (result != kOSReturnSuccess) { 3926 OSKextLog(/* kext */ NULL, 3927 kOSKextLogErrorLevel | 3928 kOSKextLogLoadFlag, 3929 "Failed to read kext load request."); 3930 goto finish; 3931 } 3932 3933 predicate = _OSKextGetRequestPredicate(mkextPlist.get()); 3934 if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) { 3935 OSKextLog(/* kext */ NULL, 3936 kOSKextLogErrorLevel | 3937 kOSKextLogLoadFlag, 3938 "Received kext load request with no predicate; skipping."); 3939 result = kOSKextReturnInvalidArgument; 3940 goto finish; 3941 } 3942 3943 requestArgs = OSDynamicCast(OSDictionary, 3944 mkextPlist->getObject(kKextRequestArgumentsKey)); 3945 if (!requestArgs || !requestArgs->getCount()) { 3946 OSKextLog(/* kext */ NULL, 3947 kOSKextLogErrorLevel | 3948 kOSKextLogLoadFlag, 3949 "Received kext load request with no arguments."); 3950 result = kOSKextReturnInvalidArgument; 3951 goto finish; 3952 } 3953 3954 kextIdentifier = OSDynamicCast(OSString, 3955 requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey)); 3956 3957 if (!kextIdentifier) { 3958 OSKextLog(/* kext */ NULL, 3959 kOSKextLogErrorLevel | 3960 kOSKextLogLoadFlag, 3961 "Received kext load request with no kext identifier."); 3962 result = kOSKextReturnInvalidArgument; 3963 goto finish; 3964 } 3965 3966 startKextExcludeNum = OSDynamicCast(OSNumber, 3967 requestArgs->getObject(kKextRequestArgumentStartExcludeKey)); 3968 startMatchingExcludeNum = OSDynamicCast(OSNumber, 3969 requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey)); 3970 delayAutounloadBool = OSDynamicCast(OSBoolean, 3971 requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey)); 3972 personalityNames = OSDynamicCast(OSArray, 3973 requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey)); 3974 3975 if (delayAutounloadBool) { 3976 delayAutounload = delayAutounloadBool->getValue(); 3977 } 3978 if (startKextExcludeNum) { 3979 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 3980 } 3981 if (startMatchingExcludeNum) { 3982 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 3983 } 3984 3985 OSKextLog(/* kext */ NULL, 3986 kOSKextLogProgressLevel | 3987 kOSKextLogIPCFlag, 3988 "Received request from user space to load kext %s.", 3989 kextIdentifier->getCStringNoCopy()); 3990 3991 /* Load the kext, with no deferral, since this is a load from outside 3992 * the kernel. 3993 * xxx - Would like a better way to handle the default values for the 3994 * xxx - start/match opt args. 3995 */ 3996 result = OSKext::loadKextWithIdentifier( 3997 kextIdentifier, 3998 /* kextRef */ NULL, 3999 /* allowDefer */ false, 4000 delayAutounload, 4001 startKextExcludeLevel, 4002 startMatchingExcludeLevel, 4003 personalityNames); 4004 if (result != kOSReturnSuccess) { 4005 goto finish; 4006 } 4007 /* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue 4008 * for matching via a separate IOKit calldown. 4009 */ 4010 4011 finish: 4012 4013 /* Gather up the collected log messages for user space. Any 4014 * error messages past this call will not make it up as log messages 4015 * but will be in the system log. 4016 */ 4017 logInfoArray = OSKext::clearUserSpaceLogFilter(); 4018 4019 if (logInfoArray && logInfoOut && logInfoLengthOut) { 4020 tempResult = OSKext::serializeLogInfo(logInfoArray.get(), 4021 logInfoOut, logInfoLengthOut); 4022 if (tempResult != kOSReturnSuccess) { 4023 result = tempResult; 4024 } 4025 } 4026 4027 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false); 4028 4029 IORecursiveLockUnlock(sKextLock); 4030 4031 /* Note: mkextDataObject will have been retained by every kext w/an 4032 * executable in it. That should all have been flushed out at the 4033 * and of the load operation, but you never know.... 4034 */ 4035 if (mkextData && mkextData->getRetainCount() > 1) { 4036 OSKextLog(/* kext */ NULL, 4037 kOSKextLogErrorLevel | 4038 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 4039 "Kext load request buffer from user space still retained by a kext; " 4040 "probable memory leak."); 4041 } 4042 4043 return result; 4044 } 4045 4046 #endif // CONFIG_KXLD 4047 4048 /********************************************************************* 4049 *********************************************************************/ 4050 /* static */ 4051 OSReturn 4052 OSKext::serializeLogInfo( 4053 OSArray * logInfoArray, 4054 char ** logInfoOut, 4055 uint32_t * logInfoLengthOut) 4056 { 4057 OSReturn result = kOSReturnError; 4058 char * buffer = NULL; 4059 kern_return_t kmem_result = KERN_FAILURE; 4060 OSSharedPtr<OSSerialize> serializer; 4061 char * logInfo = NULL; // returned by reference 4062 uint32_t logInfoLength = 0; 4063 4064 if (!logInfoArray || !logInfoOut || !logInfoLengthOut) { 4065 OSKextLog(/* kext */ NULL, 4066 kOSKextLogErrorLevel | 4067 kOSKextLogIPCFlag, 4068 "Internal error; invalid arguments to OSKext::serializeLogInfo()."); 4069 /* Bad programmer. */ 4070 result = kOSKextReturnInvalidArgument; 4071 goto finish; 4072 } 4073 4074 serializer = OSSerialize::withCapacity(0); 4075 if (!serializer) { 4076 OSKextLog(/* kext */ NULL, 4077 kOSKextLogErrorLevel | 4078 kOSKextLogIPCFlag, 4079 "Failed to create serializer on log info for request from user space."); 4080 /* Incidental error; we're going to (try to) allow the request 4081 * itself to succeed. */ 4082 } 4083 4084 if (!logInfoArray->serialize(serializer.get())) { 4085 OSKextLog(/* kext */ NULL, 4086 kOSKextLogErrorLevel | 4087 kOSKextLogIPCFlag, 4088 "Failed to serialize log info for request from user space."); 4089 /* Incidental error; we're going to (try to) allow the request 4090 * itself to succeed. */ 4091 } else { 4092 logInfo = serializer->text(); 4093 logInfoLength = serializer->getLength(); 4094 4095 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), 4096 KMA_DATA, VM_KERN_MEMORY_OSKEXT); 4097 if (kmem_result != KERN_SUCCESS) { 4098 OSKextLog(/* kext */ NULL, 4099 kOSKextLogErrorLevel | 4100 kOSKextLogIPCFlag, 4101 "Failed to copy log info for request from user space."); 4102 /* Incidental error; we're going to (try to) allow the request 4103 * to succeed. */ 4104 } else { 4105 /* 11981737 - clear uninitialized data in last page */ 4106 bzero((void *)(buffer + logInfoLength), 4107 (round_page(logInfoLength) - logInfoLength)); 4108 memcpy(buffer, logInfo, logInfoLength); 4109 *logInfoOut = buffer; 4110 *logInfoLengthOut = logInfoLength; 4111 } 4112 } 4113 4114 result = kOSReturnSuccess; 4115 finish: 4116 return result; 4117 } 4118 4119 #if PRAGMA_MARK 4120 #pragma mark Instance Management Methods 4121 #endif 4122 /********************************************************************* 4123 *********************************************************************/ 4124 OSSharedPtr<OSKext> 4125 OSKext::lookupKextWithIdentifier(const char * kextIdentifier) 4126 { 4127 OSSharedPtr<OSKext> foundKext; 4128 4129 IORecursiveLockLock(sKextLock); 4130 foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain); 4131 IORecursiveLockUnlock(sKextLock); 4132 4133 return foundKext; 4134 } 4135 4136 /********************************************************************* 4137 *********************************************************************/ 4138 OSSharedPtr<OSKext> 4139 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier) 4140 { 4141 return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy()); 4142 } 4143 4144 /********************************************************************* 4145 *********************************************************************/ 4146 OSSharedPtr<OSKext> 4147 OSKext::lookupDextWithIdentifier(OSString * dextIdentifier, OSData *dextUniqueIdentifier) 4148 { 4149 OSSharedPtr<OSKext> foundDext; 4150 foundDext.reset(); 4151 4152 IORecursiveLockLock(sKextLock); 4153 OSKext *dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIdentifier->getCStringNoCopy())); 4154 if (dext != NULL && dext->isDriverKit()) { 4155 if (dext->dextUniqueID == NULL || dext->dextUniqueID->isEqualTo(dextUniqueIdentifier)) { 4156 foundDext.reset(dext, OSRetain); 4157 } 4158 } 4159 IORecursiveLockUnlock(sKextLock); 4160 4161 return foundDext; 4162 } 4163 4164 /********************************************************************* 4165 *********************************************************************/ 4166 OSSharedPtr<OSKext> 4167 OSKext::lookupKextWithLoadTag(uint32_t aTag) 4168 { 4169 OSSharedPtr<OSKext> foundKext; // returned 4170 uint32_t i, j; 4171 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 4172 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 4173 4174 IORecursiveLockLock(sKextLock); 4175 4176 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 4177 for (i = 0; i < count[j]; i++) { 4178 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 4179 if (thisKext->getLoadTag() == aTag) { 4180 foundKext.reset(thisKext, OSRetain); 4181 goto finish; 4182 } 4183 } 4184 } 4185 4186 finish: 4187 IORecursiveLockUnlock(sKextLock); 4188 4189 return foundKext; 4190 } 4191 4192 /********************************************************************* 4193 *********************************************************************/ 4194 OSSharedPtr<OSKext> 4195 OSKext::lookupKextWithAddress(vm_address_t address) 4196 { 4197 OSSharedPtr<OSKext> foundKext; // returned 4198 uint32_t count, i; 4199 kmod_info_t *kmod_info; 4200 vm_address_t originalAddress; 4201 #if defined(__arm64__) 4202 uint64_t textExecBase; 4203 size_t textExecSize; 4204 #endif /* defined(__arm64__) */ 4205 4206 originalAddress = address; 4207 #if __has_feature(ptrauth_calls) 4208 address = (vm_address_t)VM_KERNEL_STRIP_PTR(address); 4209 #endif /* __has_feature(ptrauth_calls) */ 4210 4211 IORecursiveLockLock(sKextLock); 4212 4213 count = sLoadedKexts->getCount(); 4214 for (i = 0; i < count; i++) { 4215 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 4216 if (thisKext == sKernelKext) { 4217 continue; 4218 } 4219 if (thisKext->kmod_info && thisKext->kmod_info->address) { 4220 kmod_info = thisKext->kmod_info; 4221 vm_address_t kext_start = kmod_info->address; 4222 vm_address_t kext_end = kext_start + kmod_info->size; 4223 if ((kext_start <= address) && (address < kext_end)) { 4224 foundKext.reset(thisKext, OSRetain); 4225 goto finish; 4226 } 4227 #if defined(__arm64__) 4228 textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize); 4229 if ((textExecBase <= address) && (address < textExecBase + textExecSize)) { 4230 foundKext.reset(thisKext, OSRetain); 4231 goto finish; 4232 } 4233 #endif /* defined (__arm64__) */ 4234 } 4235 } 4236 if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) { 4237 foundKext.reset(sKernelKext, OSRetain); 4238 goto finish; 4239 } 4240 /* 4241 * DriverKit userspace executables do not have a kernel linkedExecutable, 4242 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address 4243 * here, so use the original address passed to this method. 4244 * 4245 * This is supposed to be used for logging reasons only. When logd 4246 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we 4247 * remove it here before checking it against the LoadTag. 4248 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line. 4249 */ 4250 4251 address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT); 4252 count = sLoadedDriverKitKexts->getCount(); 4253 for (i = 0; i < count; i++) { 4254 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i)); 4255 if (thisKext->getLoadTag() == address) { 4256 foundKext.reset(thisKext, OSRetain); 4257 } 4258 } 4259 4260 finish: 4261 IORecursiveLockUnlock(sKextLock); 4262 4263 return foundKext; 4264 } 4265 4266 OSSharedPtr<OSData> 4267 OSKext::copyKextUUIDForAddress(OSNumber *address) 4268 { 4269 OSSharedPtr<OSData> uuid; 4270 OSSharedPtr<OSKext> kext; 4271 4272 if (!address) { 4273 return NULL; 4274 } 4275 4276 #if CONFIG_MACF 4277 /* Is the calling process allowed to query kext info? */ 4278 if (current_task() != kernel_task) { 4279 int macCheckResult = 0; 4280 kauth_cred_t cred = NULL; 4281 4282 cred = kauth_cred_get_with_ref(); 4283 macCheckResult = mac_kext_check_query(cred); 4284 kauth_cred_unref(&cred); 4285 4286 if (macCheckResult != 0) { 4287 OSKextLog(/* kext */ NULL, 4288 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 4289 "Failed to query kext UUID (MAC policy error 0x%x).", 4290 macCheckResult); 4291 return NULL; 4292 } 4293 } 4294 #endif 4295 4296 uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue()); 4297 if (slidAddress != 0) { 4298 kext = lookupKextWithAddress(slidAddress); 4299 if (kext) { 4300 uuid = kext->copyTextUUID(); 4301 } 4302 } 4303 4304 if (!uuid) { 4305 /* 4306 * If we still don't have a UUID, then we failed to match the slid + stripped address with 4307 * a kext. This might have happened because the log message came from a dext. 4308 * 4309 * Try again with the original address. 4310 */ 4311 kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue()); 4312 if (kext && kext->isDriverKit()) { 4313 uuid = kext->copyTextUUID(); 4314 } 4315 } 4316 4317 return uuid; 4318 } 4319 4320 /********************************************************************* 4321 *********************************************************************/ 4322 OSSharedPtr<OSKext> 4323 OSKext::lookupKextWithUUID(uuid_t wanted) 4324 { 4325 OSSharedPtr<OSKext> foundKext; // returned 4326 uint32_t j, i; 4327 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 4328 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 4329 4330 4331 IORecursiveLockLock(sKextLock); 4332 4333 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 4334 for (i = 0; i < count[j]; i++) { 4335 OSKext * thisKext = NULL; 4336 4337 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 4338 if (!thisKext) { 4339 continue; 4340 } 4341 4342 OSSharedPtr<OSData> uuid_data = thisKext->copyUUID(); 4343 if (!uuid_data) { 4344 continue; 4345 } 4346 4347 uuid_t uuid; 4348 memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 4349 4350 if (0 == uuid_compare(wanted, uuid)) { 4351 foundKext.reset(thisKext, OSRetain); 4352 goto finish; 4353 } 4354 } 4355 } 4356 finish: 4357 IORecursiveLockUnlock(sKextLock); 4358 4359 return foundKext; 4360 } 4361 4362 4363 4364 4365 /********************************************************************* 4366 *********************************************************************/ 4367 /* static */ 4368 bool 4369 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier) 4370 { 4371 bool result = false; 4372 OSKext * foundKext = NULL; // returned 4373 4374 IORecursiveLockLock(sKextLock); 4375 4376 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 4377 if (foundKext && foundKext->isLoaded()) { 4378 result = true; 4379 } 4380 4381 IORecursiveLockUnlock(sKextLock); 4382 4383 return result; 4384 } 4385 4386 /********************************************************************* 4387 * xxx - should spawn a separate thread so a kext can safely have 4388 * xxx - itself unloaded. 4389 *********************************************************************/ 4390 /* static */ 4391 OSReturn 4392 OSKext::removeKext( 4393 OSKext * aKext, 4394 #if CONFIG_EMBEDDED 4395 __unused 4396 #endif 4397 bool terminateServicesAndRemovePersonalitiesFlag) 4398 { 4399 #if CONFIG_EMBEDDED 4400 if (!aKext->isDriverKit()) { 4401 OSKextLog(aKext, 4402 kOSKextLogErrorLevel | 4403 kOSKextLogKextBookkeepingFlag, 4404 "removeKext() called for %s, only supported on embedded for DriverKit dexts", 4405 aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext"); 4406 4407 return kOSReturnSuccess; 4408 } 4409 #endif /* CONFIG_EMBEDDED */ 4410 OSReturn result = kOSKextReturnInUse; 4411 OSKext * checkKext = NULL; // do not release 4412 #if CONFIG_MACF 4413 int macCheckResult = 0; 4414 kauth_cred_t cred = NULL; 4415 #endif 4416 4417 IORecursiveLockLock(sKextLock); 4418 4419 /* If the kext has no identifier, it failed to init 4420 * so isn't in sKextsByID and it isn't loaded. 4421 */ 4422 if (!aKext->getIdentifier()) { 4423 result = kOSReturnSuccess; 4424 goto finish; 4425 } 4426 4427 checkKext = OSDynamicCast(OSKext, 4428 sKextsByID->getObject(aKext->getIdentifier())); 4429 if (checkKext != aKext) { 4430 result = kOSKextReturnNotFound; 4431 goto finish; 4432 } 4433 4434 if (aKext->isLoaded() || aKext->isDriverKit()) { 4435 #if CONFIG_MACF 4436 if (current_task() != kernel_task) { 4437 cred = kauth_cred_get_with_ref(); 4438 macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString()); 4439 kauth_cred_unref(&cred); 4440 } 4441 4442 if (macCheckResult != 0) { 4443 result = kOSReturnError; 4444 OSKextLog(aKext, 4445 kOSKextLogErrorLevel | 4446 kOSKextLogKextBookkeepingFlag, 4447 "Failed to remove kext %s (MAC policy error 0x%x).", 4448 aKext->getIdentifierCString(), macCheckResult); 4449 goto finish; 4450 } 4451 #endif 4452 4453 /* make sure there are no resource requests in flight - 17187548 */ 4454 if (aKext->declaresExecutable() && aKext->countRequestCallbacks()) { 4455 goto finish; 4456 } 4457 if (aKext->flags.unloadUnsupported) { 4458 result = kOSKextReturnInUse; 4459 OSKextLog(aKext, 4460 kOSKextLogErrorLevel | 4461 kOSKextLogKextBookkeepingFlag, 4462 "Can't remove kext %s; unsupported by cache.", 4463 aKext->getIdentifierCString()); 4464 goto finish; 4465 } 4466 4467 /* If we are terminating, send the request to the IOCatalogue 4468 * (which will actually call us right back but that's ok we have 4469 * a recursive lock don't you know) but do not ask the IOCatalogue 4470 * to call back with an unload, we'll do that right here. 4471 */ 4472 if (terminateServicesAndRemovePersonalitiesFlag) { 4473 result = gIOCatalogue->terminateDriversForModule( 4474 aKext->getIdentifierCString(), /* unload */ false); 4475 if (result != kOSReturnSuccess) { 4476 OSKextLog(aKext, 4477 kOSKextLogErrorLevel | 4478 kOSKextLogKextBookkeepingFlag, 4479 "Can't remove kext %s; services failed to terminate - 0x%x.", 4480 aKext->getIdentifierCString(), result); 4481 goto finish; 4482 } 4483 } 4484 4485 result = aKext->unload(); 4486 if (result != kOSReturnSuccess) { 4487 OSKextLog(aKext, 4488 kOSKextLogErrorLevel | 4489 kOSKextLogKextBookkeepingFlag, 4490 "Can't remove kext %s; kext failed to unload - 0x%x.", 4491 aKext->getIdentifierCString(), result); 4492 goto finish; 4493 } 4494 } 4495 4496 /* Remove personalities as requested. This is a bit redundant for a loaded 4497 * kext as IOCatalogue::terminateDriversForModule() removes driver 4498 * personalities, but it doesn't restart matching, which we always want 4499 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures 4500 * that happens. 4501 */ 4502 if (terminateServicesAndRemovePersonalitiesFlag) { 4503 aKext->removePersonalitiesFromCatalog(); 4504 } 4505 4506 if (aKext->isInFileset()) { 4507 OSKextLog(aKext, 4508 kOSKextLogProgressLevel | 4509 kOSKextLogKextBookkeepingFlag, 4510 "Fileset kext %s unloaded.", 4511 aKext->getIdentifierCString()); 4512 } else { 4513 OSKextLog(aKext, 4514 kOSKextLogProgressLevel | 4515 kOSKextLogKextBookkeepingFlag, 4516 "Removing kext %s.", 4517 aKext->getIdentifierCString()); 4518 4519 sKextsByID->removeObject(aKext->getIdentifier()); 4520 } 4521 result = kOSReturnSuccess; 4522 4523 finish: 4524 IORecursiveLockUnlock(sKextLock); 4525 return result; 4526 } 4527 4528 /********************************************************************* 4529 *********************************************************************/ 4530 /* static */ 4531 OSReturn 4532 OSKext::removeKextWithIdentifier( 4533 const char * kextIdentifier, 4534 bool terminateServicesAndRemovePersonalitiesFlag) 4535 { 4536 OSReturn result = kOSReturnError; 4537 4538 IORecursiveLockLock(sKextLock); 4539 4540 OSKext * aKext = OSDynamicCast(OSKext, 4541 sKextsByID->getObject(kextIdentifier)); 4542 if (!aKext) { 4543 result = kOSKextReturnNotFound; 4544 OSKextLog(/* kext */ NULL, 4545 kOSKextLogErrorLevel | 4546 kOSKextLogKextBookkeepingFlag, 4547 "Can't remove kext %s - not found.", 4548 kextIdentifier); 4549 goto finish; 4550 } 4551 4552 result = OSKext::removeKext(aKext, 4553 terminateServicesAndRemovePersonalitiesFlag); 4554 4555 finish: 4556 IORecursiveLockUnlock(sKextLock); 4557 4558 return result; 4559 } 4560 4561 /********************************************************************* 4562 *********************************************************************/ 4563 /* static */ 4564 OSReturn 4565 OSKext::removeKextWithLoadTag( 4566 OSKextLoadTag loadTag, 4567 bool terminateServicesAndRemovePersonalitiesFlag) 4568 { 4569 OSReturn result = kOSReturnError; 4570 OSKext * foundKext = NULL; 4571 uint32_t i, j; 4572 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 4573 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 4574 4575 4576 IORecursiveLockLock(sKextLock); 4577 4578 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 4579 for (i = 0; i < count[j]; i++) { 4580 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 4581 if (thisKext->loadTag == loadTag) { 4582 foundKext = thisKext; 4583 break; 4584 } 4585 } 4586 } 4587 4588 if (!foundKext) { 4589 result = kOSKextReturnNotFound; 4590 OSKextLog(/* kext */ NULL, 4591 kOSKextLogErrorLevel | 4592 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 4593 "Can't remove kext with load tag %d - not found.", 4594 loadTag); 4595 goto finish; 4596 } 4597 4598 result = OSKext::removeKext(foundKext, 4599 terminateServicesAndRemovePersonalitiesFlag); 4600 4601 finish: 4602 IORecursiveLockUnlock(sKextLock); 4603 4604 return result; 4605 } 4606 4607 /********************************************************************* 4608 *********************************************************************/ 4609 OSSharedPtr<OSDictionary> 4610 OSKext::copyKexts(void) 4611 { 4612 OSSharedPtr<OSDictionary> result; 4613 4614 IORecursiveLockLock(sKextLock); 4615 result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection()); 4616 IORecursiveLockUnlock(sKextLock); 4617 4618 return result; 4619 } 4620 4621 /********************************************************************* 4622 *********************************************************************/ 4623 #define BOOTER_KEXT_PREFIX "Driver-" 4624 4625 typedef struct _DeviceTreeBuffer { 4626 uint32_t paddr; 4627 uint32_t length; 4628 } _DeviceTreeBuffer; 4629 4630 /********************************************************************* 4631 * Create a dictionary of excluded kexts from the given booter data. 4632 *********************************************************************/ 4633 /* static */ 4634 void 4635 OSKext::createExcludeListFromBooterData( 4636 OSDictionary * theDictionary, 4637 OSCollectionIterator * theIterator ) 4638 { 4639 OSString * deviceTreeName = NULL; // do not release 4640 const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not release 4641 char * booterDataPtr = NULL; // do not release 4642 _BooterKextFileInfo * kextFileInfo = NULL; // do not release 4643 char * infoDictAddr = NULL; // do not release 4644 OSSharedPtr<OSObject> parsedXML; 4645 OSDictionary * theInfoDict = NULL; // do not release 4646 4647 theIterator->reset(); 4648 4649 /* look for AppleKextExcludeList.kext */ 4650 while ((deviceTreeName = 4651 OSDynamicCast(OSString, theIterator->getNextObject()))) { 4652 const char * devTreeNameCString; 4653 OSData * deviceTreeEntry; // do not release 4654 OSString * myBundleID; // do not release 4655 4656 deviceTreeEntry = 4657 OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName)); 4658 if (!deviceTreeEntry) { 4659 continue; 4660 } 4661 4662 /* Make sure it is a kext */ 4663 devTreeNameCString = deviceTreeName->getCStringNoCopy(); 4664 if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX, 4665 (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) { 4666 OSKextLog(NULL, 4667 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4668 "\"%s\" not a kext", 4669 devTreeNameCString); 4670 continue; 4671 } 4672 4673 deviceTreeBuffer = (const _DeviceTreeBuffer *) 4674 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer)); 4675 if (!deviceTreeBuffer) { 4676 continue; 4677 } 4678 4679 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr); 4680 if (!booterDataPtr) { 4681 continue; 4682 } 4683 4684 kextFileInfo = (_BooterKextFileInfo *) booterDataPtr; 4685 if (!kextFileInfo->infoDictPhysAddr || 4686 !kextFileInfo->infoDictLength) { 4687 continue; 4688 } 4689 4690 infoDictAddr = (char *) 4691 ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 4692 if (!infoDictAddr) { 4693 continue; 4694 } 4695 4696 parsedXML = OSUnserializeXML(infoDictAddr); 4697 if (!parsedXML) { 4698 continue; 4699 } 4700 4701 theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 4702 if (!theInfoDict) { 4703 continue; 4704 } 4705 4706 myBundleID = 4707 OSDynamicCast(OSString, 4708 theInfoDict->getObject(kCFBundleIdentifierKey)); 4709 if (myBundleID && 4710 strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) { 4711 boolean_t updated = updateExcludeList(theInfoDict); 4712 if (!updated) { 4713 /* 25322874 */ 4714 panic("Missing OSKextExcludeList dictionary"); 4715 } 4716 break; 4717 } 4718 } // while ( (deviceTreeName = ...) ) 4719 4720 return; 4721 } 4722 4723 /********************************************************************* 4724 * Create a dictionary of excluded kexts from the given prelink 4725 * info (kernelcache). 4726 *********************************************************************/ 4727 /* static */ 4728 void 4729 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray ) 4730 { 4731 OSDictionary * myInfoDict = NULL; // do not release 4732 OSString * myBundleID; // do not release 4733 u_int i; 4734 4735 /* Find the Apple Kext Exclude List. */ 4736 for (i = 0; i < theInfoArray->getCount(); i++) { 4737 myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i)); 4738 if (!myInfoDict) { 4739 continue; 4740 } 4741 myBundleID = 4742 OSDynamicCast(OSString, 4743 myInfoDict->getObject(kCFBundleIdentifierKey)); 4744 if (myBundleID && 4745 strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) { 4746 boolean_t updated = updateExcludeList(myInfoDict); 4747 if (!updated) { 4748 /* 25322874 */ 4749 panic("Missing OSKextExcludeList dictionary"); 4750 } 4751 break; 4752 } 4753 } // for (i = 0; i < theInfoArray->getCount()... 4754 4755 return; 4756 } 4757 4758 /* static */ 4759 boolean_t 4760 OSKext::updateExcludeList(OSDictionary *infoDict) 4761 { 4762 OSDictionary *myTempDict = NULL; // do not free 4763 OSString *myTempString = NULL; // do not free 4764 OSKextVersion newVersion = 0; 4765 boolean_t updated = false; 4766 4767 if (!infoDict) { 4768 return false; 4769 } 4770 4771 myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList")); 4772 if (!myTempDict) { 4773 return false; 4774 } 4775 4776 myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey)); 4777 if (!myTempString) { 4778 return false; 4779 } 4780 4781 newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy()); 4782 if (newVersion == 0) { 4783 return false; 4784 } 4785 4786 IORecursiveLockLock(sKextLock); 4787 4788 if (newVersion > sExcludeListVersion) { 4789 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0); 4790 sExcludeListVersion = newVersion; 4791 updated = true; 4792 } 4793 4794 IORecursiveLockUnlock(sKextLock); 4795 return updated; 4796 } 4797 4798 #if PRAGMA_MARK 4799 #pragma mark Accessors 4800 #endif 4801 4802 /********************************************************************* 4803 *********************************************************************/ 4804 const OSObject * 4805 OSKext::getBundleExecutable(void) 4806 { 4807 return infoDict->getObject(kCFBundleExecutableKey); 4808 } 4809 4810 /********************************************************************* 4811 *********************************************************************/ 4812 const OSSymbol * 4813 OSKext::getIdentifier(void) 4814 { 4815 return bundleID.get(); 4816 } 4817 4818 /********************************************************************* 4819 * A kext must have a bundle identifier to even survive initialization; 4820 * this is guaranteed to exist past then. 4821 *********************************************************************/ 4822 const char * 4823 OSKext::getIdentifierCString(void) 4824 { 4825 return bundleID->getCStringNoCopy(); 4826 } 4827 4828 /********************************************************************* 4829 *********************************************************************/ 4830 OSKextVersion 4831 OSKext::getVersion(void) 4832 { 4833 return version; 4834 } 4835 4836 /********************************************************************* 4837 *********************************************************************/ 4838 OSKextVersion 4839 OSKext::getCompatibleVersion(void) 4840 { 4841 return compatibleVersion; 4842 } 4843 4844 /********************************************************************* 4845 *********************************************************************/ 4846 bool 4847 OSKext::isLibrary(void) 4848 { 4849 return getCompatibleVersion() > 0; 4850 } 4851 4852 /********************************************************************* 4853 *********************************************************************/ 4854 bool 4855 OSKext::isCompatibleWithVersion(OSKextVersion aVersion) 4856 { 4857 if ((compatibleVersion > -1 && version > -1) && 4858 (compatibleVersion <= version && aVersion <= version)) { 4859 return true; 4860 } 4861 return false; 4862 } 4863 4864 /********************************************************************* 4865 *********************************************************************/ 4866 bool 4867 OSKext::declaresExecutable(void) 4868 { 4869 if (isDriverKit()) { 4870 return false; 4871 } 4872 return getPropertyForHostArch(kCFBundleExecutableKey) != NULL; 4873 } 4874 4875 /********************************************************************* 4876 *********************************************************************/ 4877 OSData * 4878 OSKext::getExecutable(void) 4879 { 4880 OSData * result = NULL; 4881 OSSharedPtr<OSData> extractedExecutable; 4882 4883 if (flags.builtin) { 4884 return sKernelKext->linkedExecutable.get(); 4885 } 4886 4887 result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey)); 4888 if (result) { 4889 return result; 4890 } 4891 4892 #if CONFIG_KXLD 4893 OSData * mkextExecutableRef = NULL; // do not release 4894 mkextExecutableRef = OSDynamicCast(OSData, 4895 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey)); 4896 4897 if (mkextExecutableRef) { 4898 MkextEntryRef * mkextEntryRef = (MkextEntryRef *) 4899 mkextExecutableRef->getBytesNoCopy(); 4900 uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext); 4901 if (mkextVersion == MKEXT_VERS_2) { 4902 mkext2_file_entry * fileinfo = 4903 (mkext2_file_entry *)mkextEntryRef->fileinfo; 4904 uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo); 4905 uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo); 4906 extractedExecutable = extractMkext2FileData( 4907 MKEXT2_GET_ENTRY_DATA(fileinfo), "executable", 4908 compressedSize, fullSize); 4909 } else { 4910 OSKextLog(this, kOSKextLogErrorLevel | 4911 kOSKextLogArchiveFlag, 4912 "Kext %s - unknown mkext version 0x%x for executable.", 4913 getIdentifierCString(), mkextVersion); 4914 } 4915 4916 /* Regardless of success, remove the mkext executable, 4917 * and drop one reference on the mkext. (setExecutable() does not 4918 * replace, it removes, or panics if asked to replace.) 4919 */ 4920 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 4921 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 4922 4923 if (extractedExecutable && extractedExecutable->getLength()) { 4924 if (!setExecutable(extractedExecutable.get())) { 4925 goto finish; 4926 } 4927 result = extractedExecutable.get(); 4928 } else { 4929 goto finish; 4930 } 4931 } 4932 4933 finish: 4934 #endif // CONFIG_KXLD 4935 return result; 4936 } 4937 4938 /********************************************************************* 4939 *********************************************************************/ 4940 bool 4941 OSKext::isInterface(void) 4942 { 4943 return flags.interface; 4944 } 4945 4946 /********************************************************************* 4947 *********************************************************************/ 4948 bool 4949 OSKext::isKernel(void) 4950 { 4951 return this == sKernelKext; 4952 } 4953 4954 /********************************************************************* 4955 *********************************************************************/ 4956 bool 4957 OSKext::isKernelComponent(void) 4958 { 4959 return flags.kernelComponent ? true : false; 4960 } 4961 4962 /********************************************************************* 4963 *********************************************************************/ 4964 bool 4965 OSKext::isExecutable(void) 4966 { 4967 return !isKernel() && !isInterface() && declaresExecutable(); 4968 } 4969 4970 /********************************************************************* 4971 * We might want to check this recursively for all dependencies, 4972 * since a subtree of dependencies could get loaded before we hit 4973 * a dependency that isn't safe-boot-loadable. 4974 * 4975 * xxx - Might want to return false if OSBundleEnableKextLogging or 4976 * OSBundleDebugLevel 4977 * or IOKitDebug is nonzero too (we used to do that, but I don't see 4978 * the point except it's usually development drivers, which might 4979 * cause panics on startup, that have those properties). Heh; could 4980 * use a "kx" boot-arg! 4981 *********************************************************************/ 4982 bool 4983 OSKext::isLoadableInSafeBoot(void) 4984 { 4985 bool result = false; 4986 OSString * required = NULL; // do not release 4987 4988 if (isKernel()) { 4989 result = true; 4990 goto finish; 4991 } 4992 4993 if (isDriverKit()) { 4994 result = true; 4995 goto finish; 4996 } 4997 4998 required = OSDynamicCast(OSString, 4999 getPropertyForHostArch(kOSBundleRequiredKey)); 5000 if (!required) { 5001 goto finish; 5002 } 5003 if (required->isEqualTo(kOSBundleRequiredRoot) || 5004 required->isEqualTo(kOSBundleRequiredLocalRoot) || 5005 required->isEqualTo(kOSBundleRequiredNetworkRoot) || 5006 required->isEqualTo(kOSBundleRequiredSafeBoot) || 5007 required->isEqualTo(kOSBundleRequiredConsole)) { 5008 result = true; 5009 } 5010 5011 finish: 5012 return result; 5013 } 5014 5015 /********************************************************************* 5016 *********************************************************************/ 5017 bool 5018 OSKext::isPrelinked(void) 5019 { 5020 return flags.prelinked ? true : false; 5021 } 5022 5023 /********************************************************************* 5024 *********************************************************************/ 5025 bool 5026 OSKext::isLoaded(void) 5027 { 5028 return flags.loaded ? true : false; 5029 } 5030 5031 /********************************************************************* 5032 *********************************************************************/ 5033 bool 5034 OSKext::isStarted(void) 5035 { 5036 return flags.started ? true : false; 5037 } 5038 5039 /********************************************************************* 5040 *********************************************************************/ 5041 bool 5042 OSKext::isCPPInitialized(void) 5043 { 5044 return flags.CPPInitialized; 5045 } 5046 5047 /********************************************************************* 5048 *********************************************************************/ 5049 void 5050 OSKext::setCPPInitialized(bool initialized) 5051 { 5052 flags.CPPInitialized = initialized; 5053 } 5054 5055 /********************************************************************* 5056 *********************************************************************/ 5057 uint32_t 5058 OSKext::getLoadTag(void) 5059 { 5060 return loadTag; 5061 } 5062 5063 /********************************************************************* 5064 *********************************************************************/ 5065 void 5066 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize) 5067 { 5068 if (linkedExecutable) { 5069 *loadSize = linkedExecutable->getLength(); 5070 5071 /* If we have a kmod_info struct, calculated the wired size 5072 * from that. Otherwise it's the full load size. 5073 */ 5074 if (kmod_info) { 5075 *wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size; 5076 } else { 5077 *wiredSize = *loadSize; 5078 } 5079 } else { 5080 *wiredSize = 0; 5081 *loadSize = 0; 5082 } 5083 } 5084 5085 /********************************************************************* 5086 *********************************************************************/ 5087 OSSharedPtr<OSData> 5088 OSKext::copyUUID(void) 5089 { 5090 OSSharedPtr<OSData> result; 5091 OSData * theExecutable = NULL; // do not release 5092 const kernel_mach_header_t * header; 5093 5094 /* An interface kext doesn't have a linked executable with an LC_UUID, 5095 * we create one when it's linked. 5096 */ 5097 if (interfaceUUID) { 5098 result = interfaceUUID; 5099 goto finish; 5100 } 5101 5102 if (flags.builtin || isInterface()) { 5103 return sKernelKext->copyUUID(); 5104 } 5105 5106 if (isDriverKit() && infoDict) { 5107 return driverKitUUID; 5108 } 5109 5110 /* For real kexts, try to get the UUID from the linked executable, 5111 * or if is hasn't been linked yet, the unrelocated executable. 5112 */ 5113 theExecutable = linkedExecutable.get(); 5114 if (!theExecutable) { 5115 theExecutable = getExecutable(); 5116 } 5117 5118 if (!theExecutable) { 5119 goto finish; 5120 } 5121 5122 header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy(); 5123 result = copyMachoUUID(header); 5124 5125 finish: 5126 return result; 5127 } 5128 5129 /********************************************************************* 5130 *********************************************************************/ 5131 OSSharedPtr<OSData> 5132 OSKext::copyTextUUID(void) 5133 { 5134 if (flags.builtin) { 5135 return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address); 5136 } 5137 return copyUUID(); 5138 } 5139 5140 /********************************************************************* 5141 *********************************************************************/ 5142 OSSharedPtr<OSData> 5143 OSKext::copyMachoUUID(const kernel_mach_header_t * header) 5144 { 5145 OSSharedPtr<OSData> result; 5146 const struct load_command * load_cmd = NULL; 5147 const struct uuid_command * uuid_cmd = NULL; 5148 uint32_t i; 5149 5150 load_cmd = (const struct load_command *)&header[1]; 5151 5152 if (header->magic != MH_MAGIC_KERNEL) { 5153 OSKextLog(NULL, 5154 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 5155 "%s: bad header %p", 5156 __func__, 5157 header); 5158 goto finish; 5159 } 5160 5161 for (i = 0; i < header->ncmds; i++) { 5162 if (load_cmd->cmd == LC_UUID) { 5163 uuid_cmd = (struct uuid_command *)load_cmd; 5164 result = OSData::withValue(uuid_cmd->uuid); 5165 goto finish; 5166 } 5167 load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize); 5168 } 5169 5170 finish: 5171 return result; 5172 } 5173 5174 void 5175 OSKext::setDriverKitUUID(OSData *uuid) 5176 { 5177 if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) { 5178 OSSafeReleaseNULL(uuid); 5179 } 5180 } 5181 5182 OSData * 5183 OSKext::getDextUniqueID(void) 5184 { 5185 if (isDriverKit() && dextUniqueID != NULL) { 5186 return dextUniqueID.get(); 5187 } 5188 5189 return NULL; 5190 } 5191 5192 /* 5193 * In case a DextUniqueID exists this function returns 5194 * an allocated char* with the hexadecimal represantition of 5195 * DextUniqueID. 5196 * The returned pinter needs to be freed with kfree_data, the 5197 * size of the allocated buffer is returned in size. 5198 */ 5199 static const char * 5200 getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size) 5201 { 5202 if (dextUniqueID != NULL) { 5203 char *s_buffer = NULL; 5204 unsigned int d_length = dextUniqueID->getLength(); 5205 /* 5206 * We are converting in hex, so for every byte we will have 5207 * 2 hex chars and one last \0. 5208 */ 5209 unsigned int s_length = d_length * 2 + 1; 5210 s_buffer = (char *) kalloc_data(s_length, Z_WAITOK_ZERO); 5211 5212 char *uid = (char*) dextUniqueID->getBytesNoCopy(); 5213 int cpos = 0; 5214 for (unsigned int i = 0; i < d_length && cpos < (s_length - 1); i++) { 5215 int ret = snprintf(s_buffer + cpos, s_length - cpos - 1, "%02X", uid[i]); 5216 if (ret <= 0) { 5217 break; 5218 } 5219 cpos += ret; 5220 } 5221 *size = s_length; 5222 5223 return s_buffer; 5224 } 5225 5226 return NULL; 5227 } 5228 5229 /* 5230 * Atomically swaps the olddext with newdext. 5231 * olddext will be unloaded, so it might be freed 5232 * after this call unless it was previously retained. 5233 * 5234 * If newdext is NULL, this unloads olddext and does not perform an upgrade 5235 */ 5236 void 5237 OSKext::replaceDextInternal(OSKext *olddext, OSKext *newdext) 5238 { 5239 OSReturn result; 5240 const OSSymbol * dextID = olddext->getIdentifier(); 5241 OSSharedPtr<OSArray> new_personalities; 5242 OSSharedPtr<OSString> kextIdentifier; 5243 __assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock); 5244 assert(lock_held); 5245 5246 // The old dext will be unloaded and release dextID, so we need to retain dextID here 5247 dextID->retain(); 5248 5249 if (newdext != NULL) { 5250 __assert_only bool eq = dextID->isEqualTo(newdext->getIdentifier()); 5251 assert(eq); 5252 } 5253 5254 if (newdext != NULL) { 5255 /* 5256 * Swap the catalog personalities. 5257 */ 5258 new_personalities = newdext->copyPersonalitiesArray(); 5259 olddext->updatePersonalitiesInCatalog(new_personalities.get()); 5260 } 5261 5262 /* 5263 * Unload the dext. 5264 */ 5265 result = olddext->unload(); 5266 if (result != kOSReturnSuccess) { 5267 OSKextLog(NULL, 5268 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5269 "Cannot unload dext for upgrade %s: %d\n", 5270 dextID->getCStringNoCopy(), result); 5271 } 5272 5273 if (newdext != NULL) { 5274 /* 5275 * Swap the dexts on the OSKext dictionary. 5276 * This might free the dext. 5277 */ 5278 sKextsByID->setObject(dextID, newdext); 5279 } else { 5280 /* 5281 * Remove the old dext 5282 */ 5283 removeKext(olddext, true); 5284 } 5285 5286 /* 5287 * Inform userspace. 5288 */ 5289 if (newdext != NULL) { 5290 result = notifyDextUpgrade(OSDynamicCast(OSString, dextID), newdext->getDextUniqueID()); 5291 if (result != kOSReturnSuccess) { 5292 OSKextLog(NULL, 5293 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5294 "Cannot send upgrade notification for %s\n", 5295 dextID->getCStringNoCopy()); 5296 } 5297 } else { 5298 // notify dext removal 5299 queueKextNotification(kKextRequestPredicateUnloadNotification, OSDynamicCast(OSString, dextID)); 5300 } 5301 5302 OSSafeReleaseNULL(dextID); 5303 } 5304 5305 /* 5306 * To be called with sKextLock held. 5307 * NOTE: this could unload the olddext. 5308 */ 5309 bool 5310 OSKext::upgradeDext(OSKext *olddext, OSKext *newdext) 5311 { 5312 const char * dextIDCS = newdext->getIdentifierCString(); 5313 __assert_only bool old_isDext = olddext->isDriverKit(); 5314 __assert_only bool new_isDext = newdext->isDriverKit(); 5315 __assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock); 5316 5317 assert(old_isDext && new_isDext); 5318 assert(lock_held); 5319 5320 /* 5321 * New dext and old dext have the same ID. 5322 * We use this ID as key on the OSKext 5323 * dictionarys/arrays. 5324 */ 5325 const OSSymbol * dextID = newdext->getIdentifier(); 5326 __assert_only bool eq = dextID->isEqualTo(olddext->getIdentifier()); 5327 assert(eq); 5328 5329 /* 5330 * Set this OSKect as to update. 5331 * Note that this flags will never be removed once set. 5332 * When a OSKext is marked, it will be substitued by a new 5333 * OSKext, and every subsystem having a reference on this 5334 * OSKext need to know they have check if they can use 5335 * this OSKext or look for a new one. 5336 */ 5337 olddext->flags.dextToReplace = 1; 5338 5339 /* 5340 * Check if the current OSKext has any 5341 * userspace processes launched. 5342 * In this case we cannot upgrade and we have to 5343 * delay the upgrade until all processes 5344 * are done. 5345 */ 5346 if (olddext->dextLaunchedCount == 0) { 5347 /* 5348 * Be sure that if there are no launched dexts, no 5349 * pending upgrades exist. 5350 * This is an error if it happens, as the decrement 5351 * should have removed the dext from sDriverKitToUpgradeByID 5352 * in case it reached 0. 5353 */ 5354 OSObject *pending_upgdare = sDriverKitToUpgradeByID->getObject(dextID); 5355 if (pending_upgdare != NULL) { 5356 OSKextLog(NULL, 5357 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5358 "Pending upgrade found for %s but dextLaunchedCount is 0!\n", 5359 dextIDCS); 5360 goto out; 5361 } 5362 5363 replaceDextInternal(olddext, newdext); 5364 return true; 5365 } 5366 5367 out: 5368 5369 /* 5370 * Delay the upgrade. 5371 * Make the new dext available in sDriverKitToUpgradeByID. 5372 * In case there was already a pending upgrade, this will 5373 * overwrite it. 5374 */ 5375 sDriverKitToUpgradeByID->setObject(dextID, newdext); 5376 return false; 5377 } 5378 5379 /* 5380 * To be called with sKextLock held. 5381 * NOTE: this could unload the dext. 5382 */ 5383 bool 5384 OSKext::removeDext(OSKext *dext) 5385 { 5386 __assert_only bool dext_isDext = dext->isDriverKit(); 5387 __assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock); 5388 IOReturn result; 5389 5390 assert(dext_isDext); 5391 assert(lock_held); 5392 5393 /* 5394 * Set this OSKext to be unloaded when all running instances exit. 5395 */ 5396 dext->flags.dextToReplace = 1; 5397 5398 result = gIOCatalogue->terminateDriversForModule( 5399 dext->getIdentifierCString(), /* unload */ false, /* asynchronous */ true); 5400 if (result != kOSReturnSuccess) { 5401 OSKextLog(dext, 5402 kOSKextLogErrorLevel | 5403 kOSKextLogKextBookkeepingFlag, 5404 "%s services failed to terminate - 0x%x.", 5405 dext->getIdentifierCString(), result); 5406 } 5407 5408 dext->removePersonalitiesFromCatalog(); 5409 sDriverKitToUpgradeByID->removeObject(dext->getIdentifier()); 5410 5411 /* 5412 * Check if the current OSKext has any 5413 * userspace processes launched. 5414 * In this case we cannot unload and we have to 5415 * delay the unload until all processes 5416 * are done. 5417 */ 5418 if (dext->dextLaunchedCount == 0) { 5419 replaceDextInternal(dext, NULL); 5420 return true; 5421 } 5422 5423 return false; 5424 } 5425 5426 bool 5427 OSKext::incrementDextLaunchCount(OSKext *dext, OSData *dextUniqueIDToMatch) 5428 { 5429 bool ret = false; 5430 __assert_only bool isDext = dext->isDriverKit(); 5431 assert(isDext); 5432 5433 const char * dextIDCS = dext->getIdentifierCString(); 5434 OSData *myDextUniqueID = dext->getDextUniqueID(); 5435 5436 if (!myDextUniqueID || !dextUniqueIDToMatch) { 5437 OSKextLog(dext, 5438 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5439 "Cannot find dext UniqueID for %s, cannot increment dext launches\n", 5440 dextIDCS); 5441 return ret; 5442 } 5443 5444 unsigned int dextUniqueIDCStringSize = 0, dextUniqueIDToMatchCStringSize = 0; 5445 const char *dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize); 5446 const char *dextUniqueIDToMatchCString = getDextUniqueIDCString(dextUniqueIDToMatch, &dextUniqueIDToMatchCStringSize); 5447 assert(dextUniqueIDCString != NULL); 5448 assert(dextUniqueIDToMatchCString != NULL); 5449 5450 IORecursiveLockLock(sKextLock); 5451 5452 /* 5453 * Check that the dext we are referencing is the same 5454 * looked for the match. 5455 */ 5456 if (myDextUniqueID->isEqualTo(dextUniqueIDToMatch)) { 5457 if (dext->flags.dextToReplace == 0 || dext->dextLaunchedCount > 0) { 5458 if (dext->dextLaunchedCount == kOSKextMaxDextLaunchedCount) { 5459 OSKextLog(dext, 5460 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5461 "Too many dexts launched for %s UniqueID %s\n", 5462 dextIDCS, dextUniqueIDCString); 5463 } else { 5464 dext->dextLaunchedCount++; 5465 ret = true; 5466 5467 OSKextLog(dext, 5468 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5469 "New dext launched for %s UniqueID %s", 5470 dextIDCS, dextUniqueIDCString); 5471 } 5472 } else { 5473 OSKextLog(dext, 5474 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5475 "Dext %s UniqueID %s requires update, cannot launch a new dext\n", 5476 dextIDCS, dextUniqueIDCString); 5477 } 5478 } else { 5479 OSKextLog(dext, 5480 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5481 "Dext %s: UniqueID %s does not match UniqueID looked for %s, cannot launch a new dext\n", 5482 dextIDCS, dextUniqueIDCString, dextUniqueIDToMatchCString); 5483 } 5484 5485 IORecursiveLockUnlock(sKextLock); 5486 5487 if (dextUniqueIDCString != NULL) { 5488 kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize); 5489 } 5490 if (dextUniqueIDToMatchCString != NULL) { 5491 kfree_data(dextUniqueIDToMatchCString, dextUniqueIDToMatchCStringSize); 5492 } 5493 return ret; 5494 } 5495 5496 bool 5497 OSKext::decrementDextLaunchCount(OSString *bundleID) 5498 { 5499 bool ret = false; 5500 const char * dextIDCS; 5501 OSData *myDextUniqueID; 5502 unsigned int dextUniqueIDCStringSize = 0; 5503 const char * dextUniqueIDCString = NULL; 5504 OSKext* dext = NULL; 5505 5506 if (!bundleID) { 5507 return ret; 5508 } 5509 dextIDCS = bundleID->getCStringNoCopy(); 5510 5511 IORecursiveLockLock(sKextLock); 5512 5513 /* 5514 * Look for the dext with the bundle it. This 5515 * call is triggered only if a previous increment was 5516 * performed. It means that the dext could have not 5517 * been upgraded as its dextLaunchedCount was at least 1. 5518 * Because of this it still needs to be available 5519 * in sKextsByID. 5520 */ 5521 dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIDCS)); 5522 if (!dext || !dext->isDriverKit()) { 5523 OSKextLog(NULL, 5524 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5525 "Cannot find dext for %s, cannot decrement dext launches\n", 5526 dextIDCS); 5527 5528 goto out_locked; 5529 } 5530 5531 myDextUniqueID = dext->getDextUniqueID(); 5532 if (!myDextUniqueID) { 5533 OSKextLog(dext, 5534 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5535 "Cannot find dext UniqueID for %s, cannot decrement dext launches\n", 5536 dextIDCS); 5537 5538 goto out_locked; 5539 } 5540 dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize); 5541 assert(dextUniqueIDCString != NULL); 5542 5543 if (dext->dextLaunchedCount == 0) { 5544 OSKextLog(dext, 5545 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5546 "Over decrementing dext launch for %s UniqueID %s\n", 5547 dextIDCS, dextUniqueIDCString); 5548 5549 goto out_locked; 5550 } 5551 5552 dext->dextLaunchedCount--; 5553 5554 OSKextLog(dext, 5555 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5556 "Dext terminated for %s UniqueID %s", 5557 dextIDCS, dextUniqueIDCString); 5558 5559 if (dext->dextLaunchedCount == 0 && dext->flags.dextToReplace == 1) { 5560 /* 5561 * Find the upgraded dext. 5562 */ 5563 OSKext *newdext = OSDynamicCast(OSKext, sDriverKitToUpgradeByID->getObject(dextIDCS)); 5564 if (newdext) { 5565 OSKextLog(dext, 5566 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5567 "Dext upgrade for %s UniqueID %s", 5568 dextIDCS, dextUniqueIDCString); 5569 replaceDextInternal(dext, newdext); 5570 /* NOTE dext could have been freed past this point */ 5571 5572 sDriverKitToUpgradeByID->removeObject(dextIDCS); 5573 } else { 5574 OSKextLog(dext, 5575 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5576 "Dext unload for %s UniqueID %s", 5577 dextIDCS, dextUniqueIDCString); 5578 replaceDextInternal(dext, NULL); 5579 } 5580 5581 ret = true; 5582 } 5583 out_locked: 5584 IORecursiveLockUnlock(sKextLock); 5585 5586 if (dextUniqueIDCString != NULL) { 5587 kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize); 5588 } 5589 5590 return ret; 5591 } 5592 5593 /********************************************************************* 5594 *********************************************************************/ 5595 #if defined (__arm__) 5596 #include <arm/arch.h> 5597 #endif 5598 5599 #if defined (__x86_64__) 5600 #define ARCHNAME "x86_64" 5601 #elif defined (__arm64__) 5602 #define ARCHNAME "arm64" 5603 #elif defined (__arm__) 5604 5605 #if defined (__ARM_ARCH_7S__) 5606 #define ARCHNAME "armv7s" 5607 #elif defined (__ARM_ARCH_7F__) 5608 #define ARCHNAME "armv7f" 5609 #elif defined (__ARM_ARCH_7K__) 5610 #define ARCHNAME "armv7k" 5611 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */ 5612 #define ARCHNAME "armv7" 5613 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */ 5614 #define ARCHNAME "armv6" 5615 #endif 5616 5617 #elif defined (__arm64__) 5618 #define ARCHNAME "arm64" 5619 #else 5620 #error architecture not supported 5621 #endif 5622 5623 #define ARCH_SEPARATOR_CHAR '_' 5624 5625 static char * 5626 makeHostArchKey(const char * key, size_t * keySizeOut) 5627 { 5628 char * result = NULL; 5629 size_t keyLength = strlen(key); 5630 size_t keySize; 5631 5632 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'. 5633 */ 5634 keySize = 1 + 1 + keyLength + strlen(ARCHNAME); 5635 result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 5636 5637 if (!result) { 5638 goto finish; 5639 } 5640 strlcpy(result, key, keySize); 5641 result[keyLength++] = ARCH_SEPARATOR_CHAR; 5642 result[keyLength] = '\0'; 5643 strlcat(result, ARCHNAME, keySize); 5644 *keySizeOut = keySize; 5645 5646 finish: 5647 return result; 5648 } 5649 5650 /********************************************************************* 5651 *********************************************************************/ 5652 OSObject * 5653 OSKext::getPropertyForHostArch(const char * key) 5654 { 5655 OSObject * result = NULL;// do not release 5656 size_t hostArchKeySize = 0; 5657 char * hostArchKey = NULL;// must kfree 5658 5659 if (!key || !infoDict) { 5660 goto finish; 5661 } 5662 5663 /* Some properties are not allowed to be arch-variant: 5664 * - Any CFBundle... property. 5665 * - OSBundleIsInterface. 5666 * - OSKernelResource. 5667 */ 5668 if (STRING_HAS_PREFIX(key, "OS") || 5669 STRING_HAS_PREFIX(key, "IO")) { 5670 hostArchKey = makeHostArchKey(key, &hostArchKeySize); 5671 if (!hostArchKey) { 5672 OSKextLog(/* kext (this isn't about a kext) */ NULL, 5673 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 5674 "Allocation failure."); 5675 goto finish; 5676 } 5677 result = infoDict->getObject(hostArchKey); 5678 } 5679 5680 if (!result) { 5681 result = infoDict->getObject(key); 5682 } 5683 5684 finish: 5685 if (hostArchKey) { 5686 kfree_data(hostArchKey, hostArchKeySize); 5687 } 5688 return result; 5689 } 5690 5691 #if PRAGMA_MARK 5692 #pragma mark Load/Start/Stop/Unload 5693 #endif 5694 5695 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n') 5696 5697 /********************************************************************* 5698 * sExcludeListByID is a dictionary with keys / values of: 5699 * key = bundleID string of kext we will not allow to load 5700 * value = version string(s) of the kext that is to be denied loading. 5701 * The version strings can be comma delimited. For example if kext 5702 * com.foocompany.fookext has two versions that we want to deny 5703 * loading then the version strings might look like: 5704 * 1.0.0, 1.0.1 5705 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will 5706 * not load the kext. 5707 * 5708 * Value may also be in the form of "LE 2.0.0" (version numbers 5709 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version 5710 * number less than 2.0.0 will not load) 5711 * 5712 * NOTE - we cannot use the characters "<=" or "<" because we have code 5713 * that serializes plists and treats '<' as a special character. 5714 *********************************************************************/ 5715 bool 5716 OSKext::isInExcludeList(void) 5717 { 5718 OSString * versionString = NULL; // do not release 5719 char * versionCString = NULL; // do not free 5720 size_t i; 5721 boolean_t wantLessThan = false; 5722 boolean_t wantLessThanEqualTo = false; 5723 boolean_t isInExcludeList = true; 5724 char myBuffer[32]; 5725 5726 IORecursiveLockLock(sKextLock); 5727 5728 if (!sExcludeListByID) { 5729 isInExcludeList = false; 5730 } else { 5731 /* look up by bundleID in our exclude list and if found get version 5732 * string (or strings) that we will not allow to load 5733 */ 5734 versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get())); 5735 if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) { 5736 isInExcludeList = false; 5737 } 5738 } 5739 5740 IORecursiveLockUnlock(sKextLock); 5741 5742 if (!isInExcludeList) { 5743 return false; 5744 } 5745 5746 /* parse version strings */ 5747 versionCString = (char *) versionString->getCStringNoCopy(); 5748 5749 /* look for "LT" or "LE" form of version string, must be in first two 5750 * positions. 5751 */ 5752 if (*versionCString == 'L' && *(versionCString + 1) == 'T') { 5753 wantLessThan = true; 5754 versionCString += 2; 5755 } else if (*versionCString == 'L' && *(versionCString + 1) == 'E') { 5756 wantLessThanEqualTo = true; 5757 versionCString += 2; 5758 } 5759 5760 for (i = 0; *versionCString != 0x00; versionCString++) { 5761 /* skip whitespace */ 5762 if (isWhiteSpace(*versionCString)) { 5763 continue; 5764 } 5765 5766 /* peek ahead for version string separator or null terminator */ 5767 if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) { 5768 /* OK, we have a version string */ 5769 myBuffer[i++] = *versionCString; 5770 myBuffer[i] = 0x00; 5771 5772 OSKextVersion excludeVers; 5773 excludeVers = OSKextParseVersionString(myBuffer); 5774 5775 if (wantLessThanEqualTo) { 5776 if (version <= excludeVers) { 5777 return true; 5778 } 5779 } else if (wantLessThan) { 5780 if (version < excludeVers) { 5781 return true; 5782 } 5783 } else if (version == excludeVers) { 5784 return true; 5785 } 5786 5787 /* reset for the next (if any) version string */ 5788 i = 0; 5789 wantLessThan = false; 5790 wantLessThanEqualTo = false; 5791 } else { 5792 /* save valid version character */ 5793 myBuffer[i++] = *versionCString; 5794 5795 /* make sure bogus version string doesn't overrun local buffer */ 5796 if (i >= sizeof(myBuffer)) { 5797 break; 5798 } 5799 } 5800 } 5801 5802 return false; 5803 } 5804 5805 /********************************************************************* 5806 * sNonLoadableKextsByID is a dictionary with keys / values of: 5807 * key = bundleID string of kext we will not allow to load 5808 * value = boolean (true == loadable, false == not loadable) 5809 * 5810 * Only kexts which are in the AuxKC will be marked as "not loadble," 5811 * i.e., the value for the kext's bundleID will be false. All kexts in 5812 * the primary and system KCs will always be marked as "loadable." 5813 * 5814 * This list ultimately comes from kexts which have been uninstalled 5815 * in user space by deleting the kext from disk, but which have not 5816 * yet been removed from the AuxKC. Because the user could choose to 5817 * re-install the exact same version of the kext, we need to keep 5818 * a dictionary of boolean values so that user space only needs to 5819 * keep a simple list of "uninstalled" or "missing" bundles. When 5820 * a bundle is re-installed, the iokit daemon can use the 5821 * AucKCBundleAvailable predicate to set the individual kext's 5822 * availability to true. 5823 *********************************************************************/ 5824 bool 5825 OSKext::isLoadable(void) 5826 { 5827 bool isLoadable = true; 5828 5829 if (kc_type != KCKindAuxiliary) { 5830 /* this filtering only applies to kexts in the auxkc */ 5831 return true; 5832 } 5833 5834 IORecursiveLockLock(sKextLock); 5835 5836 if (sNonLoadableKextsByID) { 5837 /* look up by bundleID in our exclude list and if found get version 5838 * string (or strings) that we will not allow to load 5839 */ 5840 OSBoolean *loadableVal; 5841 loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get())); 5842 if (loadableVal && !loadableVal->getValue()) { 5843 isLoadable = false; 5844 } 5845 } 5846 IORecursiveLockUnlock(sKextLock); 5847 5848 return isLoadable; 5849 } 5850 5851 /********************************************************************* 5852 *********************************************************************/ 5853 /* static */ 5854 OSReturn 5855 OSKext::loadKextWithIdentifier( 5856 const char * kextIdentifierCString, 5857 Boolean allowDeferFlag, 5858 Boolean delayAutounloadFlag, 5859 OSKextExcludeLevel startOpt, 5860 OSKextExcludeLevel startMatchingOpt, 5861 OSArray * personalityNames) 5862 { 5863 OSReturn result = kOSReturnError; 5864 OSSharedPtr<OSString> kextIdentifier; 5865 5866 kextIdentifier = OSString::withCString(kextIdentifierCString); 5867 if (!kextIdentifier) { 5868 result = kOSKextReturnNoMemory; 5869 goto finish; 5870 } 5871 result = OSKext::loadKextWithIdentifier(kextIdentifier.get(), 5872 NULL /* kextRef */, 5873 allowDeferFlag, delayAutounloadFlag, 5874 startOpt, startMatchingOpt, personalityNames); 5875 5876 finish: 5877 return result; 5878 } 5879 5880 OSReturn 5881 OSKext::loadKextWithIdentifier( 5882 OSString * kextIdentifier, 5883 OSSharedPtr<OSObject> &kextRef, 5884 Boolean allowDeferFlag, 5885 Boolean delayAutounloadFlag, 5886 OSKextExcludeLevel startOpt, 5887 OSKextExcludeLevel startMatchingOpt, 5888 OSArray * personalityNames) 5889 { 5890 OSObject * kextRefRaw = NULL; 5891 OSReturn result; 5892 5893 result = loadKextWithIdentifier(kextIdentifier, 5894 &kextRefRaw, 5895 allowDeferFlag, 5896 delayAutounloadFlag, 5897 startOpt, 5898 startMatchingOpt, 5899 personalityNames); 5900 if ((kOSReturnSuccess == result) && kextRefRaw) { 5901 kextRef.reset(kextRefRaw, OSNoRetain); 5902 } 5903 return result; 5904 } 5905 5906 /********************************************************************* 5907 *********************************************************************/ 5908 OSReturn 5909 OSKext::loadKextWithIdentifier( 5910 OSString * kextIdentifier, 5911 OSObject ** kextRef, 5912 Boolean allowDeferFlag, 5913 Boolean delayAutounloadFlag, 5914 OSKextExcludeLevel startOpt, 5915 OSKextExcludeLevel startMatchingOpt, 5916 OSArray * personalityNames) 5917 { 5918 OSReturn result = kOSReturnError; 5919 OSReturn pingResult = kOSReturnError; 5920 OSKext * theKext = NULL; // do not release 5921 OSSharedPtr<OSDictionary> loadRequest; 5922 OSSharedPtr<const OSSymbol> kextIdentifierSymbol; 5923 5924 if (kextRef) { 5925 *kextRef = NULL; 5926 } 5927 5928 IORecursiveLockLock(sKextLock); 5929 5930 if (!kextIdentifier) { 5931 result = kOSKextReturnInvalidArgument; 5932 goto finish; 5933 } 5934 5935 OSKext::recordIdentifierRequest(kextIdentifier); 5936 5937 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 5938 if (!theKext) { 5939 if (!allowDeferFlag) { 5940 OSKextLog(/* kext */ NULL, 5941 kOSKextLogErrorLevel | 5942 kOSKextLogLoadFlag, 5943 "Can't load kext %s - not found.", 5944 kextIdentifier->getCStringNoCopy()); 5945 goto finish; 5946 } 5947 5948 if (!sKernelRequestsEnabled) { 5949 OSKextLog(theKext, 5950 kOSKextLogErrorLevel | 5951 kOSKextLogLoadFlag, 5952 "Can't load kext %s - requests to user space are disabled.", 5953 kextIdentifier->getCStringNoCopy()); 5954 result = kOSKextReturnDisabled; 5955 goto finish; 5956 } 5957 5958 /* Create a new request unless one is already sitting 5959 * in sKernelRequests for this bundle identifier 5960 */ 5961 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 5962 if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) { 5963 result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad, 5964 loadRequest); 5965 if (result != kOSReturnSuccess) { 5966 goto finish; 5967 } 5968 if (!_OSKextSetRequestArgument(loadRequest.get(), 5969 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 5970 result = kOSKextReturnNoMemory; 5971 goto finish; 5972 } 5973 if (!sKernelRequests->setObject(loadRequest.get())) { 5974 result = kOSKextReturnNoMemory; 5975 goto finish; 5976 } 5977 5978 if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) { 5979 result = kOSKextReturnNoMemory; 5980 goto finish; 5981 } 5982 5983 OSKextLog(theKext, 5984 kOSKextLogDebugLevel | 5985 kOSKextLogLoadFlag, 5986 "Kext %s not found; queued load request to user space.", 5987 kextIdentifier->getCStringNoCopy()); 5988 } 5989 5990 pingResult = OSKext::pingIOKitDaemon(); 5991 if (pingResult == kOSKextReturnDisabled) { 5992 OSKextLog(/* kext */ NULL, 5993 ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) | 5994 kOSKextLogLoadFlag, 5995 "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.", 5996 kextIdentifier->getCStringNoCopy()); 5997 } 5998 5999 result = kOSKextReturnDeferred; 6000 goto finish; 6001 } 6002 6003 result = theKext->load(startOpt, startMatchingOpt, personalityNames); 6004 6005 if (result != kOSReturnSuccess) { 6006 OSKextLog(theKext, 6007 kOSKextLogErrorLevel | 6008 kOSKextLogLoadFlag, 6009 "Failed to load kext %s (error 0x%x).", 6010 kextIdentifier->getCStringNoCopy(), (int)result); 6011 6012 if (theKext->kc_type == KCKindUnknown) { 6013 OSKext::removeKext(theKext, 6014 /* terminateService/removePersonalities */ true); 6015 } 6016 goto finish; 6017 } 6018 6019 if (delayAutounloadFlag) { 6020 OSKextLog(theKext, 6021 kOSKextLogProgressLevel | 6022 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 6023 "Setting delayed autounload for %s.", 6024 kextIdentifier->getCStringNoCopy()); 6025 theKext->flags.delayAutounload = 1; 6026 } 6027 6028 finish: 6029 if ((kOSReturnSuccess == result) && kextRef) { 6030 *kextRef = theKext; 6031 theKext->matchingRefCount++; 6032 theKext->retain(); 6033 } 6034 6035 IORecursiveLockUnlock(sKextLock); 6036 6037 return result; 6038 } 6039 6040 /********************************************************************* 6041 *********************************************************************/ 6042 /* static */ 6043 OSReturn 6044 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict) 6045 { 6046 OSReturn result = kOSReturnError; 6047 6048 OSBoolean *delayAutounloadBool = NULL; // do not release 6049 OSNumber *startKextExcludeNum = NULL; // do not release 6050 OSNumber *startMatchingExcludeNum = NULL; // do not release 6051 OSArray *personalityNames = NULL; // do not release 6052 6053 /* 6054 * Default values for these options: 6055 * regular autounload behavior 6056 * start the kext 6057 * send all personalities to the catalog 6058 */ 6059 Boolean delayAutounload = false; 6060 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 6061 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone; 6062 6063 IORecursiveLockLock(sKextLock); 6064 6065 OSKextLog(/* kext */ NULL, 6066 kOSKextLogDebugLevel | 6067 kOSKextLogIPCFlag, 6068 "Received kext KC load request from user space."); 6069 6070 /* Regardless of processing, the fact that we have gotten here means some 6071 * user-space program is up and talking to us, so we'll switch our kext 6072 * registration to reflect that. 6073 */ 6074 if (!sUserLoadsActive) { 6075 OSKextLog(/* kext */ NULL, 6076 kOSKextLogProgressLevel | 6077 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 6078 "Switching to late startup (user-space) kext loading policy."); 6079 sUserLoadsActive = true; 6080 } 6081 6082 delayAutounloadBool = OSDynamicCast(OSBoolean, 6083 _OSKextGetRequestArgument(requestDict, 6084 kKextRequestArgumentDelayAutounloadKey)); 6085 startKextExcludeNum = OSDynamicCast(OSNumber, 6086 _OSKextGetRequestArgument(requestDict, 6087 kKextRequestArgumentStartExcludeKey)); 6088 startMatchingExcludeNum = OSDynamicCast(OSNumber, 6089 _OSKextGetRequestArgument(requestDict, 6090 kKextRequestArgumentStartMatchingExcludeKey)); 6091 personalityNames = OSDynamicCast(OSArray, 6092 _OSKextGetRequestArgument(requestDict, 6093 kKextRequestArgumentPersonalityNamesKey)); 6094 6095 if (delayAutounloadBool) { 6096 delayAutounload = delayAutounloadBool->getValue(); 6097 } 6098 if (startKextExcludeNum) { 6099 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 6100 } 6101 if (startMatchingExcludeNum) { 6102 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 6103 } 6104 6105 OSKextLog(/* kext */ NULL, 6106 kOSKextLogProgressLevel | 6107 kOSKextLogIPCFlag, 6108 "Received request from user space to load KC kext %s.", 6109 theKext->getIdentifierCString()); 6110 6111 /* this could be in the Auxiliary KC, so record the load request */ 6112 OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier())); 6113 6114 /* 6115 * Load the kext 6116 */ 6117 result = theKext->load(startKextExcludeLevel, 6118 startMatchingExcludeLevel, personalityNames); 6119 6120 if (result != kOSReturnSuccess) { 6121 OSKextLog(theKext, 6122 kOSKextLogErrorLevel | 6123 kOSKextLogLoadFlag, 6124 "Failed to load kext %s (error 0x%x).", 6125 theKext->getIdentifierCString(), (int)result); 6126 6127 OSKext::removeKext(theKext, 6128 /* terminateService/removePersonalities */ true); 6129 goto finish; 6130 } else { 6131 OSKextLog(theKext, 6132 kOSKextLogProgressLevel | 6133 kOSKextLogLoadFlag, 6134 "Kext %s Loaded successfully from %s KC", 6135 theKext->getIdentifierCString(), theKext->getKCTypeString()); 6136 } 6137 6138 if (delayAutounload) { 6139 OSKextLog(theKext, 6140 kOSKextLogProgressLevel | 6141 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 6142 "Setting delayed autounload for %s.", 6143 theKext->getIdentifierCString()); 6144 theKext->flags.delayAutounload = 1; 6145 } 6146 6147 finish: 6148 IORecursiveLockUnlock(sKextLock); 6149 6150 return result; 6151 } 6152 6153 /********************************************************************* 6154 *********************************************************************/ 6155 /* static */ 6156 OSReturn 6157 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict) 6158 { 6159 OSReturn result = kOSReturnError; 6160 OSDictionary *anInfoDict = NULL; // do not release 6161 6162 anInfoDict = OSDynamicCast(OSDictionary, 6163 _OSKextGetRequestArgument(requestDict, 6164 kKextRequestArgumentCodelessInfoKey)); 6165 if (anInfoDict == NULL) { 6166 OSKextLog(/* kext */ NULL, 6167 kOSKextLogErrorLevel | 6168 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 6169 "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.", 6170 kextIdentifier->getCStringNoCopy()); 6171 return kOSKextReturnInvalidArgument; 6172 } 6173 6174 IORecursiveLockLock(sKextLock); 6175 6176 OSKextLog(/* kext */ NULL, 6177 kOSKextLogProgressLevel | 6178 kOSKextLogIPCFlag, 6179 "Received request from user space to load codeless kext %s.", 6180 kextIdentifier->getCStringNoCopy()); 6181 6182 { 6183 // instantiate a new kext, and don't hold a reference 6184 // (the kext subsystem will hold one implicitly) 6185 OSKextInitResult ret; 6186 OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict, &ret); 6187 if (!newKext) { 6188 /* 6189 * We might have failed to create a new OSKext 6190 * because the old one should still be used. 6191 * Check if that is the case. 6192 */ 6193 if (ret != kOSKextInitFailure) { 6194 result = kOSReturnSuccess; 6195 goto finish; 6196 } 6197 OSKextLog(/* kext */ NULL, 6198 kOSKextLogErrorLevel | 6199 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 6200 "Could not instantiate codeless kext."); 6201 result = kOSKextReturnNotLoadable; 6202 goto finish; 6203 } 6204 if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) { 6205 OSKextLog(/* kext */ NULL, 6206 kOSKextLogErrorLevel | 6207 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 6208 "Codeless kext identifiers don't match '%s' != '%s'", 6209 kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString()); 6210 6211 OSKext::removeKext(newKext.get(), false); 6212 result = kOSKextReturnInvalidArgument; 6213 goto finish; 6214 } 6215 6216 /* Record the request for the codeless kext */ 6217 OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier())); 6218 6219 result = kOSReturnSuccess; 6220 /* Send the kext's personalities to the IOCatalog. This is an explicit load. */ 6221 result = newKext->sendPersonalitiesToCatalog(true, NULL); 6222 } 6223 6224 finish: 6225 IORecursiveLockUnlock(sKextLock); 6226 6227 return result; 6228 } 6229 6230 /********************************************************************* 6231 *********************************************************************/ 6232 /* static */ 6233 void 6234 OSKext::dropMatchingReferences( 6235 OSSet * kexts) 6236 { 6237 IORecursiveLockLock(sKextLock); 6238 kexts->iterateObjects(^bool (OSObject * obj) { 6239 OSKext * thisKext = OSDynamicCast(OSKext, obj); 6240 if (!thisKext) { 6241 return false; 6242 } 6243 thisKext->matchingRefCount--; 6244 return false; 6245 }); 6246 IORecursiveLockUnlock(sKextLock); 6247 } 6248 6249 /********************************************************************* 6250 *********************************************************************/ 6251 /* static */ 6252 void 6253 OSKext::recordIdentifierRequest( 6254 OSString * kextIdentifier) 6255 { 6256 OSSharedPtr<const OSSymbol> kextIdentifierSymbol; 6257 bool fail = false; 6258 6259 if (!sAllKextLoadIdentifiers || !kextIdentifier) { 6260 goto finish; 6261 } 6262 6263 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 6264 if (!kextIdentifierSymbol) { 6265 // xxx - this is really a basic alloc failure 6266 fail = true; 6267 goto finish; 6268 } 6269 6270 IORecursiveLockLock(sKextLock); 6271 if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) { 6272 if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) { 6273 fail = true; 6274 } else { 6275 // xxx - need to find a way to associate this whole func w/the kext 6276 OSKextLog(/* kext */ NULL, 6277 // xxx - check level 6278 kOSKextLogStepLevel | 6279 kOSKextLogArchiveFlag, 6280 "Recorded kext %s as a candidate for inclusion in prelinked kernel.", 6281 kextIdentifier->getCStringNoCopy()); 6282 } 6283 } 6284 IORecursiveLockUnlock(sKextLock); 6285 6286 finish: 6287 6288 if (fail) { 6289 OSKextLog(/* kext */ NULL, 6290 kOSKextLogErrorLevel | 6291 kOSKextLogArchiveFlag, 6292 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.", 6293 kextIdentifier->getCStringNoCopy()); 6294 } 6295 return; 6296 } 6297 6298 /********************************************************************* 6299 *********************************************************************/ 6300 OSReturn 6301 OSKext::load( 6302 OSKextExcludeLevel startOpt, 6303 OSKextExcludeLevel startMatchingOpt, 6304 OSArray * personalityNames) 6305 { 6306 OSReturn result = kOSReturnError; 6307 OSKextExcludeLevel dependenciesStartOpt = startOpt; 6308 OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt; 6309 unsigned int i, count; 6310 Boolean alreadyLoaded = false; 6311 OSKext * lastLoadedKext = NULL; // do not release 6312 6313 if (isInExcludeList()) { 6314 OSKextLog(this, 6315 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | 6316 kOSKextLogLoadFlag, 6317 "Kext %s is in exclude list, not loadable", 6318 getIdentifierCString()); 6319 6320 result = kOSKextReturnNotLoadable; 6321 goto finish; 6322 } 6323 if (!isLoadable()) { 6324 OSKextLog(this, 6325 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | 6326 kOSKextLogLoadFlag, 6327 "Kext %s is not loadable", 6328 getIdentifierCString()); 6329 6330 result = kOSKextReturnNotLoadable; 6331 goto finish; 6332 } 6333 6334 if (isLoaded()) { 6335 alreadyLoaded = true; 6336 result = kOSReturnSuccess; 6337 6338 OSKextLog(this, 6339 kOSKextLogDebugLevel | 6340 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 6341 "Kext %s is already loaded.", 6342 getIdentifierCString()); 6343 goto loaded; 6344 } 6345 6346 #if CONFIG_MACF 6347 /* 6348 * On kxld and on embedded, only call into the MAC hook when on a 6349 * user thread, for access control over userspace kextloads. 6350 * 6351 * On non-kxld systems, additionally check the MAC hook for kexts in 6352 * the Pageable and Aux KCs, regardless of whether we are on a user 6353 * thread or not. This means on Apple silicon devices that the MAC 6354 * hook will only be useful to block 3rd party kexts loaded via 6355 * matching, and any kexts loaded from userspace kextloads. 6356 * 6357 * Note that this should _not_ be called on kexts loaded from the 6358 * kernel bootstrap thread as the kernel proc's cred struct is not 6359 * yet initialized! This won't happen on macOS because all the kexts 6360 * in the BootKC are self-contained and their kc_type = KCKindPrimary. 6361 */ 6362 if (current_task() != kernel_task 6363 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD 6364 || (kc_type != KCKindPrimary && kc_type != KCKindUnknown) 6365 #endif 6366 ) { 6367 int macCheckResult = 0; 6368 kauth_cred_t cred = NULL; 6369 6370 cred = kauth_cred_get_with_ref(); 6371 macCheckResult = mac_kext_check_load(cred, getIdentifierCString()); 6372 kauth_cred_unref(&cred); 6373 6374 if (macCheckResult != 0) { 6375 result = kOSReturnError; 6376 OSKextLog(this, 6377 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 6378 "Failed to load kext %s (MAC policy error 0x%x).", 6379 getIdentifierCString(), macCheckResult); 6380 goto finish; 6381 } 6382 } 6383 #endif /* CONFIG_MACF */ 6384 6385 if (!sLoadEnabled) { 6386 OSKextLog(this, 6387 kOSKextLogErrorLevel | 6388 kOSKextLogLoadFlag, 6389 "Kext loading is disabled (attempt to load kext %s).", 6390 getIdentifierCString()); 6391 result = kOSKextReturnDisabled; 6392 goto finish; 6393 } 6394 6395 /* If we've pushed the next available load tag to the invalid value, 6396 * we can't load any more kexts. 6397 */ 6398 if (sNextLoadTag == kOSKextInvalidLoadTag) { 6399 OSKextLog(this, 6400 kOSKextLogErrorLevel | 6401 kOSKextLogLoadFlag, 6402 "Can't load kext %s - no more load tags to assign.", 6403 getIdentifierCString()); 6404 result = kOSKextReturnNoResources; 6405 goto finish; 6406 } 6407 6408 /* This is a bit of a hack, because we shouldn't be handling 6409 * personalities within the load function. 6410 */ 6411 if (!declaresExecutable()) { 6412 /* There is a special case where a non-executable kext can be loaded: the 6413 * AppleKextExcludeList. Detect that special kext by bundle identifier and 6414 * load its metadata into the global data structures, if appropriate 6415 */ 6416 if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) { 6417 boolean_t updated = updateExcludeList(infoDict.get()); 6418 if (updated) { 6419 OSKextLog(this, 6420 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 6421 "KextExcludeList was updated to version: %lld", sExcludeListVersion); 6422 } 6423 } 6424 6425 if (isDriverKit()) { 6426 if (loadTag == 0) { 6427 sLoadedDriverKitKexts->setObject(this); 6428 loadTag = sNextLoadTag++; 6429 } 6430 } 6431 result = kOSReturnSuccess; 6432 goto loaded; 6433 } 6434 6435 /* Are we in safe boot? 6436 */ 6437 if (sSafeBoot && !isLoadableInSafeBoot()) { 6438 OSKextLog(this, 6439 kOSKextLogErrorLevel | 6440 kOSKextLogLoadFlag, 6441 "Can't load kext %s - not loadable during safe boot.", 6442 getIdentifierCString()); 6443 result = kOSKextReturnBootLevel; 6444 goto finish; 6445 } 6446 6447 OSKextLog(this, 6448 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 6449 "Loading kext %s.", 6450 getIdentifierCString()); 6451 6452 #if !VM_MAPPED_KEXTS 6453 if (isPrelinked() == false) { 6454 OSKextLog(this, 6455 kOSKextLogErrorLevel | 6456 kOSKextLogLoadFlag, 6457 "Can't load kext %s - not in a kext collection.", 6458 getIdentifierCString()); 6459 result = kOSKextReturnDisabled; 6460 goto finish; 6461 } 6462 #endif /* defined(__x86_64__) */ 6463 6464 #if CONFIG_KXLD 6465 if (!sKxldContext) { 6466 kern_return_t kxldResult; 6467 kxldResult = kxld_create_context(&sKxldContext, &kern_allocate, 6468 &kxld_log_callback, /* Flags */ (KXLDFlags) 0, 6469 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0); 6470 if (kxldResult) { 6471 OSKextLog(this, 6472 kOSKextLogErrorLevel | 6473 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 6474 "Can't load kext %s - failed to create link context.", 6475 getIdentifierCString()); 6476 result = kOSKextReturnNoMemory; 6477 goto finish; 6478 } 6479 } 6480 #endif // CONFIG_KXLD 6481 6482 /* We only need to resolve dependencies once for the whole graph, but 6483 * resolveDependencies will just return if there's no work to do, so it's 6484 * safe to call it more than once. 6485 */ 6486 if (!resolveDependencies()) { 6487 // xxx - check resolveDependencies() for log msg 6488 OSKextLog(this, 6489 kOSKextLogErrorLevel | 6490 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 6491 "Can't load kext %s - failed to resolve library dependencies.", 6492 getIdentifierCString()); 6493 result = kOSKextReturnDependencies; 6494 goto finish; 6495 } 6496 6497 /* If we are excluding just the kext being loaded now (and not its 6498 * dependencies), drop the exclusion level to none so dependencies 6499 * start and/or add their personalities. 6500 */ 6501 if (dependenciesStartOpt == kOSKextExcludeKext) { 6502 dependenciesStartOpt = kOSKextExcludeNone; 6503 } 6504 6505 if (dependenciesStartMatchingOpt == kOSKextExcludeKext) { 6506 dependenciesStartMatchingOpt = kOSKextExcludeNone; 6507 } 6508 6509 /* Load the dependencies, recursively. 6510 */ 6511 count = getNumDependencies(); 6512 for (i = 0; i < count; i++) { 6513 OSKext * dependency = OSDynamicCast(OSKext, 6514 dependencies->getObject(i)); 6515 if (dependency == NULL) { 6516 OSKextLog(this, 6517 kOSKextLogErrorLevel | 6518 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 6519 "Internal error loading kext %s; dependency disappeared.", 6520 getIdentifierCString()); 6521 result = kOSKextReturnInternalError; 6522 goto finish; 6523 } 6524 6525 /* Dependencies must be started accorting to the opt, 6526 * but not given the personality names of the main kext. 6527 */ 6528 result = dependency->load(dependenciesStartOpt, 6529 dependenciesStartMatchingOpt, 6530 /* personalityNames */ NULL); 6531 if (result != KERN_SUCCESS) { 6532 OSKextLog(this, 6533 kOSKextLogErrorLevel | 6534 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 6535 "Dependency %s of kext %s failed to load.", 6536 dependency->getIdentifierCString(), 6537 getIdentifierCString()); 6538 6539 OSKext::removeKext(dependency, 6540 /* terminateService/removePersonalities */ true); 6541 result = kOSKextReturnDependencyLoadError; 6542 6543 goto finish; 6544 } 6545 } 6546 6547 result = loadExecutable(); 6548 if (result != KERN_SUCCESS) { 6549 goto finish; 6550 } 6551 6552 pendingPgoHead.next = &pendingPgoHead; 6553 pendingPgoHead.prev = &pendingPgoHead; 6554 6555 // The kernel PRNG is not initialized when the first kext is 6556 // loaded, so use early random 6557 uuid_generate_early_random(instance_uuid); 6558 account = IOMallocType(OSKextAccount); 6559 6560 account->loadTag = kmod_info->id; 6561 account->site.refcount = 0; 6562 account->site.flags = VM_TAG_KMOD; 6563 6564 #if DEVELOPMENT || DEBUG 6565 /* Setup the task reference group. */ 6566 (void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name), 6567 "task_%s", getIdentifierCString()); 6568 account->task_refgrp.grp_name = account->task_refgrp_name; 6569 account->task_refgrp.grp_parent = &task_external_refgrp; 6570 account->task_refgrp.grp_flags = OS_REFGRP_F_ALWAYS_ENABLED; 6571 os_ref_log_init(&account->task_refgrp); 6572 #endif /* DEVELOPMENT || DEBUG */ 6573 6574 account->kext = this; 6575 if (gIOSurfaceIdentifier == bundleID) { 6576 vm_tag_alloc(&account->site); 6577 gIOSurfaceTag = account->site.tag; 6578 } 6579 6580 flags.loaded = true; 6581 6582 /* Add the kext to the list of loaded kexts and update the kmod_info 6583 * struct to point to that of the last loaded kext (which is the way 6584 * it's always been done, though I'd rather do them in order now). 6585 */ 6586 lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 6587 sLoadedKexts->setObject(this); 6588 6589 /* Keep the kernel itself out of the kmod list. 6590 */ 6591 if (lastLoadedKext->isKernel()) { 6592 lastLoadedKext = NULL; 6593 } 6594 6595 if (lastLoadedKext) { 6596 kmod_info->next = lastLoadedKext->kmod_info; 6597 } 6598 6599 notifyKextLoadObservers(this, kmod_info); 6600 6601 /* Make the global kmod list point at the just-loaded kext. Note that the 6602 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard, 6603 * although we do report it in kextstat these days by using the newer 6604 * OSArray of loaded kexts, which does contain it. 6605 * 6606 * (The OSKext object representing the kernel doesn't even have a kmod_info 6607 * struct, though I suppose we could stick a pointer to it from the 6608 * static struct in OSRuntime.cpp.) 6609 */ 6610 kmod = kmod_info; 6611 6612 /* Save the list of loaded kexts in case we panic. 6613 */ 6614 OSKext::saveLoadedKextPanicList(); 6615 6616 if (isExecutable()) { 6617 OSKext::updateLoadedKextSummaries(); 6618 savePanicString(/* isLoading */ true); 6619 6620 #if CONFIG_DTRACE 6621 registerWithDTrace(); 6622 #else 6623 jettisonLinkeditSegment(); 6624 #endif /* CONFIG_DTRACE */ 6625 6626 #if !VM_MAPPED_KEXTS 6627 /* If there is a page (or more) worth of padding after the end 6628 * of the last data section but before the end of the data segment 6629 * then free it in the same manner the LinkeditSegment is freed 6630 */ 6631 jettisonDATASegmentPadding(); 6632 #endif 6633 } 6634 6635 loaded: 6636 if (isExecutable() && !flags.started) { 6637 if (startOpt == kOSKextExcludeNone) { 6638 result = start(); 6639 if (result != kOSReturnSuccess) { 6640 OSKextLog(this, 6641 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 6642 "Kext %s start failed (result 0x%x).", 6643 getIdentifierCString(), result); 6644 result = kOSKextReturnStartStopError; 6645 } 6646 } 6647 } 6648 6649 /* If not excluding matching, send the personalities to the kernel. 6650 * This never affects the result of the load operation. 6651 * This is a bit of a hack, because we shouldn't be handling 6652 * personalities within the load function. 6653 */ 6654 if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) { 6655 result = sendPersonalitiesToCatalog(true, personalityNames); 6656 } 6657 6658 finish: 6659 6660 if (result != kOSReturnSuccess) { 6661 OSKextLog(this, 6662 kOSKextLogErrorLevel | 6663 kOSKextLogLoadFlag, 6664 "Kext %s failed to load (0x%x).", 6665 getIdentifierCString(), (int)result); 6666 } else if (!alreadyLoaded) { 6667 OSKextLog(this, 6668 kOSKextLogProgressLevel | 6669 kOSKextLogLoadFlag, 6670 "Kext %s loaded.", 6671 getIdentifierCString()); 6672 6673 queueKextNotification(kKextRequestPredicateLoadNotification, 6674 OSDynamicCast(OSString, bundleID.get())); 6675 } 6676 return result; 6677 } 6678 6679 #if CONFIG_KXLD 6680 /********************************************************************* 6681 * 6682 *********************************************************************/ 6683 static char * 6684 strdup(const char * string) 6685 { 6686 char * result = NULL; 6687 size_t size; 6688 6689 if (!string) { 6690 goto finish; 6691 } 6692 6693 size = 1 + strlen(string); 6694 result = (char *)kalloc_data_tag(size, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 6695 if (!result) { 6696 goto finish; 6697 } 6698 6699 memcpy(result, string, size); 6700 6701 finish: 6702 return result; 6703 } 6704 #endif // CONFIG_KXLD 6705 6706 /********************************************************************* 6707 * 6708 *********************************************************************/ 6709 6710 kernel_section_t * 6711 OSKext::lookupSection(const char *segname, const char *secname) 6712 { 6713 kernel_section_t * found_section = NULL; 6714 kernel_mach_header_t * mh = NULL; 6715 kernel_segment_command_t * seg = NULL; 6716 kernel_section_t * sec = NULL; 6717 6718 if (!linkedExecutable) { 6719 return NULL; 6720 } 6721 6722 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 6723 6724 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 6725 if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) { 6726 continue; 6727 } 6728 6729 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 6730 if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) { 6731 found_section = sec; 6732 goto out; 6733 } 6734 } 6735 } 6736 6737 out: 6738 return found_section; 6739 } 6740 6741 /********************************************************************* 6742 * 6743 *********************************************************************/ 6744 6745 OSReturn 6746 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides) 6747 { 6748 OSReturn result = kOSKextReturnBadData; 6749 kernel_mach_header_t * mh = NULL; 6750 kernel_segment_command_t * seg = NULL; 6751 kernel_segment_command_t * linkeditSeg = NULL; 6752 kernel_section_t * sec = NULL; 6753 char * linkeditBase = NULL; 6754 bool haveLinkeditBase = false; 6755 char * relocBase = NULL; 6756 bool haveRelocBase = false; 6757 struct dysymtab_command * dysymtab = NULL; 6758 struct linkedit_data_command * segmentSplitInfo = NULL; 6759 struct symtab_command * symtab = NULL; 6760 kernel_nlist_t * sym = NULL; 6761 struct relocation_info * reloc = NULL; 6762 uint32_t i = 0; 6763 int reloc_size; 6764 vm_offset_t new_kextsize; 6765 kc_format format = KCFormatUnknown; 6766 6767 if (linkedExecutable == NULL || flags.builtin) { 6768 result = kOSReturnSuccess; 6769 goto finish; 6770 } 6771 6772 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 6773 if (kernel_mach_header_is_in_fileset(mh)) { 6774 // kexts in filesets are slid as part of collection sliding 6775 result = kOSReturnSuccess; 6776 goto finish; 6777 } 6778 6779 segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO); 6780 6781 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 6782 if (!seg->vmaddr) { 6783 continue; 6784 } 6785 6786 seg->vmaddr = ml_static_slide(seg->vmaddr); 6787 6788 #if KASLR_KEXT_DEBUG 6789 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n", 6790 seg->segname, 6791 (unsigned long)ml_static_unslide(seg->vmaddr), 6792 (unsigned long)seg->vmaddr); 6793 #endif 6794 6795 if (!haveRelocBase) { 6796 relocBase = (char *) seg->vmaddr; 6797 haveRelocBase = true; 6798 } 6799 if (!strcmp(seg->segname, "__LINKEDIT")) { 6800 linkeditBase = (char *) seg->vmaddr - seg->fileoff; 6801 haveLinkeditBase = true; 6802 linkeditSeg = seg; 6803 } 6804 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 6805 sec->addr = ml_static_slide(sec->addr); 6806 6807 #if KASLR_KEXT_DEBUG 6808 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n", 6809 sec->sectname, 6810 (unsigned long)ml_static_unslide(sec->addr), 6811 (unsigned long)sec->addr); 6812 #endif 6813 } 6814 } 6815 6816 dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB); 6817 6818 symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB); 6819 6820 if (symtab != NULL && doCoalescedSlides == false) { 6821 /* Some pseudo-kexts have symbol tables without segments. 6822 * Ignore them. */ 6823 if (symtab->nsyms > 0 && haveLinkeditBase) { 6824 sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff); 6825 for (i = 0; i < symtab->nsyms; i++) { 6826 if (sym[i].n_type & N_STAB) { 6827 continue; 6828 } 6829 sym[i].n_value = ml_static_slide(sym[i].n_value); 6830 6831 #if KASLR_KEXT_DEBUG 6832 #define MAX_SYMS_TO_LOG 5 6833 if (i < MAX_SYMS_TO_LOG) { 6834 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n", 6835 (unsigned long)ml_static_unslide(sym[i].n_value), 6836 (unsigned long)sym[i].n_value); 6837 } 6838 #endif 6839 } 6840 } 6841 } 6842 6843 if (dysymtab != NULL && doCoalescedSlides == false) { 6844 if (dysymtab->nextrel > 0) { 6845 OSKextLog(this, 6846 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6847 kOSKextLogLinkFlag, 6848 "Sliding kext %s: External relocations found.", 6849 getIdentifierCString()); 6850 goto finish; 6851 } 6852 6853 if (dysymtab->nlocrel > 0) { 6854 if (!haveLinkeditBase) { 6855 OSKextLog(this, 6856 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6857 kOSKextLogLinkFlag, 6858 "Sliding kext %s: No linkedit segment.", 6859 getIdentifierCString()); 6860 goto finish; 6861 } 6862 6863 if (!haveRelocBase) { 6864 OSKextLog(this, 6865 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6866 kOSKextLogLinkFlag, 6867 #if __x86_64__ 6868 "Sliding kext %s: No writable segments.", 6869 #else 6870 "Sliding kext %s: No segments.", 6871 #endif 6872 getIdentifierCString()); 6873 goto finish; 6874 } 6875 6876 reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff); 6877 reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info); 6878 6879 for (i = 0; i < dysymtab->nlocrel; i++) { 6880 if (reloc[i].r_extern != 0 6881 || reloc[i].r_type != 0 6882 || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2) 6883 ) { 6884 OSKextLog(this, 6885 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6886 kOSKextLogLinkFlag, 6887 "Sliding kext %s: Unexpected relocation found.", 6888 getIdentifierCString()); 6889 goto finish; 6890 } 6891 if (reloc[i].r_pcrel != 0) { 6892 continue; 6893 } 6894 uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address); 6895 *relocAddr = ml_static_slide(*relocAddr); 6896 6897 #if KASLR_KEXT_DEBUG 6898 #define MAX_DYSYMS_TO_LOG 5 6899 if (i < MAX_DYSYMS_TO_LOG) { 6900 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n", 6901 (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))), 6902 (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address))); 6903 } 6904 #endif 6905 } 6906 6907 /* We should free these relocations, not just delete the reference to them. 6908 * <rdar://problem/10535549> Free relocations from PIE kexts. 6909 * 6910 * For now, we do not free LINKEDIT for kexts with split segments. 6911 */ 6912 new_kextsize = round_page(kmod_info->size - reloc_size); 6913 if (new_kextsize > UINT_MAX) { 6914 OSKextLog(this, 6915 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6916 kOSKextLogLinkFlag, 6917 "Kext %s: new kext size is too large.", 6918 getIdentifierCString()); 6919 goto finish; 6920 } 6921 if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) { 6922 vm_offset_t endofkext = kmod_info->address + kmod_info->size; 6923 vm_offset_t new_endofkext = kmod_info->address + new_kextsize; 6924 vm_offset_t endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size); 6925 size_t bytes_remaining = endofkext - endofrelocInfo; 6926 OSSharedPtr<OSData> new_osdata; 6927 6928 /* fix up symbol offsets if they are after the dsymtab local relocs */ 6929 if (symtab) { 6930 if (dysymtab->locreloff < symtab->symoff) { 6931 symtab->symoff -= reloc_size; 6932 } 6933 if (dysymtab->locreloff < symtab->stroff) { 6934 symtab->stroff -= reloc_size; 6935 } 6936 } 6937 if (dysymtab->locreloff < dysymtab->extreloff) { 6938 dysymtab->extreloff -= reloc_size; 6939 } 6940 6941 /* move data behind reloc info down to new offset */ 6942 if (endofrelocInfo < endofkext) { 6943 memcpy(reloc, (void *)endofrelocInfo, bytes_remaining); 6944 } 6945 6946 /* Create a new OSData for the smaller kext object and reflect 6947 * new linkedit segment size. 6948 */ 6949 linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size); 6950 linkeditSeg->filesize = linkeditSeg->vmsize; 6951 6952 new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize); 6953 if (new_osdata) { 6954 /* Fix up kmod info and linkedExecutable. 6955 */ 6956 kmod_info->size = new_kextsize; 6957 /* 6958 * Fileset KCs are mapped as a whole by iBoot. 6959 * Individual kext executables should not be unmapped 6960 * by xnu. 6961 * Doing so may result in panics like rdar://85419651 6962 */ 6963 if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) { 6964 new_osdata->setDeallocFunction(NULL); 6965 } else { // Not from a Fileset KC 6966 #if VM_MAPPED_KEXTS 6967 new_osdata->setDeallocFunction(osdata_kext_free); 6968 #else 6969 new_osdata->setDeallocFunction(osdata_phys_free); 6970 #endif 6971 } 6972 linkedExecutable->setDeallocFunction(NULL); 6973 linkedExecutable = os::move(new_osdata); 6974 6975 #if VM_MAPPED_KEXTS 6976 kext_free(new_endofkext, (endofkext - new_endofkext)); 6977 #else 6978 ml_static_mfree(new_endofkext, (endofkext - new_endofkext)); 6979 #endif 6980 } 6981 } 6982 dysymtab->nlocrel = 0; 6983 dysymtab->locreloff = 0; 6984 } 6985 } 6986 6987 result = kOSReturnSuccess; 6988 finish: 6989 return result; 6990 } 6991 6992 /********************************************************************* 6993 * called only by load() 6994 *********************************************************************/ 6995 OSReturn 6996 OSKext::loadExecutable() 6997 { 6998 OSReturn result = kOSReturnError; 6999 OSSharedPtr<OSArray> linkDependencies; 7000 uint32_t num_kmod_refs = 0; 7001 OSData * theExecutable = NULL; // do not release 7002 OSString * versString = NULL; // do not release 7003 const char * versCString = NULL; // do not free 7004 const char * string = NULL; // do not free 7005 7006 #if CONFIG_KXLD 7007 unsigned int i; 7008 uint32_t numDirectDependencies = 0; 7009 kern_return_t kxldResult; 7010 KXLDDependency * kxlddeps = NULL; // must kfree 7011 uint32_t num_kxlddeps = 0; 7012 struct mach_header ** kxldHeaderPtr = NULL; // do not free 7013 struct mach_header * kxld_header = NULL; // xxx - need to free here? 7014 #endif // CONFIG_KXLD 7015 7016 /* We need the version string for a variety of bits below. 7017 */ 7018 versString = OSDynamicCast(OSString, 7019 getPropertyForHostArch(kCFBundleVersionKey)); 7020 if (!versString) { 7021 goto finish; 7022 } 7023 versCString = versString->getCStringNoCopy(); 7024 7025 if (isKernelComponent()) { 7026 if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) { 7027 if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) { 7028 OSKextLog(this, 7029 kOSKextLogErrorLevel | 7030 kOSKextLogLoadFlag, 7031 "Kernel component %s has incorrect version %s; " 7032 "expected %s.", 7033 getIdentifierCString(), 7034 versCString, KERNEL6_VERSION); 7035 result = kOSKextReturnInternalError; 7036 goto finish; 7037 } else if (strcmp(versCString, osrelease)) { 7038 OSKextLog(this, 7039 kOSKextLogErrorLevel | 7040 kOSKextLogLoadFlag, 7041 "Kernel component %s has incorrect version %s; " 7042 "expected %s.", 7043 getIdentifierCString(), 7044 versCString, osrelease); 7045 result = kOSKextReturnInternalError; 7046 goto finish; 7047 } 7048 } 7049 } 7050 7051 #if defined(__x86_64__) || defined(__i386__) 7052 if (flags.resetSegmentsFromVnode) { 7053 /* Fixup the chains and slide the mach headers */ 7054 kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address; 7055 7056 if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) { 7057 result = kOSKextReturnValidation; 7058 goto finish; 7059 } 7060 } 7061 #endif //(__x86_64__) || defined(__i386__) 7062 7063 if (isPrelinked()) { 7064 goto register_kmod; 7065 } 7066 7067 /* <rdar://problem/21444003> all callers must be entitled */ 7068 if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) { 7069 OSKextLog(this, 7070 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 7071 "Not entitled to link kext '%s'", 7072 getIdentifierCString()); 7073 result = kOSKextReturnNotPrivileged; 7074 goto finish; 7075 } 7076 7077 theExecutable = getExecutable(); 7078 if (!theExecutable) { 7079 if (declaresExecutable()) { 7080 OSKextLog(this, 7081 kOSKextLogErrorLevel | 7082 kOSKextLogLoadFlag, 7083 "Can't load kext %s - executable is missing.", 7084 getIdentifierCString()); 7085 result = kOSKextReturnValidation; 7086 goto finish; 7087 } 7088 goto register_kmod; 7089 } 7090 7091 if (isInterface()) { 7092 OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable); 7093 if (executableCopy) { 7094 setLinkedExecutable(executableCopy.get()); 7095 } 7096 goto register_kmod; 7097 } 7098 7099 #if CONFIG_KXLD 7100 numDirectDependencies = getNumDependencies(); 7101 7102 if (flags.hasBleedthrough) { 7103 linkDependencies = dependencies; 7104 } else { 7105 linkDependencies = OSArray::withArray(dependencies.get()); 7106 if (!linkDependencies) { 7107 OSKextLog(this, 7108 kOSKextLogErrorLevel | 7109 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 7110 "Can't allocate link dependencies to load kext %s.", 7111 getIdentifierCString()); 7112 goto finish; 7113 } 7114 7115 for (i = 0; i < numDirectDependencies; ++i) { 7116 OSKext * dependencyKext = OSDynamicCast(OSKext, 7117 dependencies->getObject(i)); 7118 dependencyKext->addBleedthroughDependencies(linkDependencies.get()); 7119 } 7120 } 7121 7122 num_kxlddeps = linkDependencies->getCount(); 7123 if (!num_kxlddeps) { 7124 OSKextLog(this, 7125 kOSKextLogErrorLevel | 7126 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 7127 "Can't load kext %s - it has no library dependencies.", 7128 getIdentifierCString()); 7129 goto finish; 7130 } 7131 7132 kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 7133 if (!kxlddeps) { 7134 OSKextLog(this, 7135 kOSKextLogErrorLevel | 7136 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 7137 "Can't allocate link context to load kext %s.", 7138 getIdentifierCString()); 7139 goto finish; 7140 } 7141 bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps)); 7142 7143 for (i = 0; i < num_kxlddeps; ++i) { 7144 OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i)); 7145 7146 if (dependency->isInterface()) { 7147 OSKext *interfaceTargetKext = NULL; //do not release 7148 OSData * interfaceTarget = NULL; //do not release 7149 7150 if (dependency->isKernelComponent()) { 7151 interfaceTargetKext = sKernelKext; 7152 interfaceTarget = sKernelKext->linkedExecutable.get(); 7153 } else { 7154 interfaceTargetKext = OSDynamicCast(OSKext, 7155 dependency->dependencies->getObject(0)); 7156 7157 interfaceTarget = interfaceTargetKext->linkedExecutable.get(); 7158 } 7159 7160 if (!interfaceTarget) { 7161 // panic? 7162 goto finish; 7163 } 7164 7165 /* The names set here aren't actually logged yet <rdar://problem/7941514>, 7166 * it will be useful to have them in the debugger. 7167 * strdup() failing isn't critical right here so we don't check that. 7168 */ 7169 kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy(); 7170 kxlddeps[i].kext_size = interfaceTarget->getLength(); 7171 kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString()); 7172 7173 if (dependency->linkedExecutable != NULL) { 7174 kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 7175 kxlddeps[i].interface_size = dependency->linkedExecutable->getLength(); 7176 } else { 7177 kxlddeps[i].interface = (u_char *) NULL; 7178 kxlddeps[i].interface_size = 0; 7179 } 7180 kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString()); 7181 } else { 7182 kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 7183 kxlddeps[i].kext_size = dependency->linkedExecutable->getLength(); 7184 kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString()); 7185 } 7186 7187 kxlddeps[i].is_direct_dependency = (i < numDirectDependencies); 7188 } 7189 7190 kxldHeaderPtr = &kxld_header; 7191 7192 #if DEBUG 7193 OSKextLog(this, 7194 kOSKextLogExplicitLevel | 7195 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 7196 "Kext %s - calling kxld_link_file:\n" 7197 " kxld_context: %p\n" 7198 " executable: %p executable_length: %d\n" 7199 " user_data: %p\n" 7200 " kxld_dependencies: %p num_dependencies: %d\n" 7201 " kxld_header_ptr: %p kmod_info_ptr: %p\n", 7202 getIdentifierCString(), sKxldContext, 7203 theExecutable->getBytesNoCopy(), theExecutable->getLength(), 7204 this, kxlddeps, num_kxlddeps, 7205 kxldHeaderPtr, &kmod_info); 7206 #endif 7207 7208 /* After this call, the linkedExecutable instance variable 7209 * should exist. 7210 */ 7211 kxldResult = kxld_link_file(sKxldContext, 7212 (u_char *)theExecutable->getBytesNoCopy(), 7213 theExecutable->getLength(), 7214 getIdentifierCString(), this, kxlddeps, num_kxlddeps, 7215 (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info); 7216 7217 if (kxldResult != KERN_SUCCESS) { 7218 // xxx - add kxldResult here? 7219 OSKextLog(this, 7220 kOSKextLogErrorLevel | 7221 kOSKextLogLoadFlag, 7222 "Can't load kext %s - link failed.", 7223 getIdentifierCString()); 7224 result = kOSKextReturnLinkError; 7225 goto finish; 7226 } 7227 7228 /* We've written data & instructions into kernel memory, so flush the data 7229 * cache and invalidate the instruction cache. 7230 * I/D caches are coherent on x86 7231 */ 7232 #if !defined(__i386__) && !defined(__x86_64__) 7233 flush_dcache(kmod_info->address, kmod_info->size, false); 7234 invalidate_icache(kmod_info->address, kmod_info->size, false); 7235 #endif 7236 7237 #else // !CONFIG_KXLD 7238 OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag, 7239 "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString()); 7240 result = kOSKextReturnLinkError; 7241 goto finish; 7242 #endif // CONFIG_KXLD 7243 7244 register_kmod: 7245 7246 if (isInterface()) { 7247 /* Whip up a fake kmod_info entry for the interface kext. 7248 */ 7249 kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO)); 7250 if (!kmod_info) { 7251 result = KERN_MEMORY_ERROR; 7252 goto finish; 7253 } 7254 7255 /* A pseudokext has almost nothing in its kmod_info struct. 7256 */ 7257 kmod_info->info_version = KMOD_INFO_VERSION; 7258 7259 /* An interface kext doesn't have a linkedExecutable, so save a 7260 * copy of the UUID out of the original executable via copyUUID() 7261 * while we still have the original executable. 7262 */ 7263 interfaceUUID = copyUUID(); 7264 } 7265 7266 kmod_info->id = loadTag = sNextLoadTag++; 7267 kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid). 7268 7269 /* Stamp the bundle ID and version from the OSKext over anything 7270 * resident inside the kmod_info. 7271 */ 7272 string = getIdentifierCString(); 7273 strlcpy(kmod_info->name, string, sizeof(kmod_info->name)); 7274 7275 string = versCString; 7276 strlcpy(kmod_info->version, string, sizeof(kmod_info->version)); 7277 7278 /* Add the dependencies' kmod_info structs as kmod_references. 7279 */ 7280 num_kmod_refs = getNumDependencies(); 7281 if (num_kmod_refs) { 7282 kmod_info->reference_list = kalloc_type_tag(kmod_reference_t, 7283 num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT); 7284 if (!kmod_info->reference_list) { 7285 result = KERN_MEMORY_ERROR; 7286 goto finish; 7287 } 7288 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 7289 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 7290 OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex)); 7291 ref->info = refKext->kmod_info; 7292 ref->info->reference_count++; 7293 7294 if (refIndex + 1 < num_kmod_refs) { 7295 ref->next = kmod_info->reference_list + refIndex + 1; 7296 } 7297 } 7298 } 7299 7300 if (kmod_info->hdr_size > UINT32_MAX) { 7301 OSKextLog(this, 7302 kOSKextLogErrorLevel | 7303 kOSKextLogLoadFlag, 7304 #if __LP64__ 7305 "Kext %s header size is too large (%lu > UINT32_MAX).", 7306 #else 7307 "Kext %s header size is too large (%u > UINT32_MAX).", 7308 #endif 7309 kmod_info->name, 7310 kmod_info->hdr_size); 7311 result = KERN_FAILURE; 7312 goto finish; 7313 } 7314 7315 if (kmod_info->size > UINT32_MAX) { 7316 OSKextLog(this, 7317 kOSKextLogErrorLevel | 7318 kOSKextLogLoadFlag, 7319 #if __LP64__ 7320 "Kext %s size is too large (%lu > UINT32_MAX).", 7321 #else 7322 "Kext %s size is too large (%u > UINT32_MAX).", 7323 #endif 7324 kmod_info->name, 7325 kmod_info->size); 7326 result = KERN_FAILURE; 7327 goto finish; 7328 } 7329 7330 if (!isInterface() && linkedExecutable) { 7331 OSKextLog(this, 7332 kOSKextLogProgressLevel | 7333 kOSKextLogLoadFlag, 7334 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).", 7335 kmod_info->name, 7336 (unsigned)kmod_info->size / PAGE_SIZE, 7337 (unsigned long)ml_static_unslide(kmod_info->address), 7338 (unsigned)kmod_info->id); 7339 } 7340 7341 /* VM protections and wiring for the Aux KC are done at collection loading time */ 7342 if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) { 7343 /* if prelinked and primary KC, VM protections are already set */ 7344 result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true); 7345 if (result != KERN_SUCCESS) { 7346 goto finish; 7347 } 7348 } 7349 7350 #if KASAN 7351 if (linkedExecutable) { 7352 kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), 7353 linkedExecutable->getLength(), getIdentifierCString()); 7354 } 7355 #else 7356 if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) { 7357 OSKextLog(this, 7358 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 7359 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n", 7360 getIdentifierCString() 7361 ); 7362 result = KERN_FAILURE; 7363 goto finish; 7364 } 7365 #endif 7366 7367 result = kOSReturnSuccess; 7368 7369 finish: 7370 7371 #if CONFIG_KXLD 7372 /* Clear up locally allocated dependency info. 7373 */ 7374 for (i = 0; i < num_kxlddeps; ++i) { 7375 size_t size; 7376 7377 if (kxlddeps[i].kext_name) { 7378 size = 1 + strlen(kxlddeps[i].kext_name); 7379 kfree_data(kxlddeps[i].kext_name, size); 7380 } 7381 if (kxlddeps[i].interface_name) { 7382 size = 1 + strlen(kxlddeps[i].interface_name); 7383 kfree_data(kxlddeps[i].interface_name, size); 7384 } 7385 } 7386 if (kxlddeps) { 7387 kfree_type(KXLDDependency, num_kxlddeps, kxlddeps); 7388 } 7389 #endif // CONFIG_KXLD 7390 7391 /* We no longer need the unrelocated executable (which the linker 7392 * has altered anyhow). 7393 */ 7394 setExecutable(NULL); 7395 7396 if (result != kOSReturnSuccess) { 7397 OSKextLog(this, 7398 kOSKextLogErrorLevel | 7399 kOSKextLogLoadFlag, 7400 "Failed to load executable for kext %s.", 7401 getIdentifierCString()); 7402 7403 if (kmod_info && kmod_info->reference_list) { 7404 kfree_type(kmod_reference_t, num_kmod_refs, 7405 kmod_info->reference_list); 7406 } 7407 if (isInterface()) { 7408 kfree_type(kmod_info_t, kmod_info); 7409 kmod_info = NULL; 7410 } 7411 if (kc_type == KCKindUnknown) { 7412 kmod_info = NULL; 7413 if (linkedExecutable) { 7414 linkedExecutable.reset(); 7415 } 7416 } 7417 } 7418 7419 return result; 7420 } 7421 7422 /* static */ 7423 void 7424 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh) 7425 { 7426 kernel_segment_command_t *linkeditseg = NULL; 7427 7428 linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT); 7429 if (linkeditseg == NULL) { 7430 panic("FileSet booted with no Linkedit segment"); 7431 } 7432 7433 #if VM_MAPPED_KEXTS 7434 /* BootKC on x86_64 is not vm mapped */ 7435 ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize); 7436 7437 OSKextLog(/* kext */ NULL, 7438 kOSKextLogProgressLevel | 7439 kOSKextLogGeneralFlag, 7440 "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu", 7441 linkeditseg->vmaddr, linkeditseg->vmsize); 7442 #else 7443 /* BootKC on arm64 is not vm mapped, but is slid */ 7444 vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase)); 7445 7446 ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize); 7447 7448 OSKextLog(/* kext */ NULL, 7449 kOSKextLogProgressLevel | 7450 kOSKextLogGeneralFlag, 7451 "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu", 7452 (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize); 7453 #endif /* VM_MAPPED_KEXTS */ 7454 } 7455 7456 /********************************************************************* 7457 * The linkedit segment is used by the kext linker for dependency 7458 * resolution, and by dtrace for probe initialization. We can free it 7459 * for non-library kexts, since no kexts depend on non-library kexts 7460 * by definition, once dtrace has been initialized. 7461 *********************************************************************/ 7462 void 7463 OSKext::jettisonLinkeditSegment(void) 7464 { 7465 kernel_mach_header_t * machhdr = (kernel_mach_header_t *)kmod_info->address; 7466 kernel_segment_command_t * linkedit = NULL; 7467 vm_offset_t start; 7468 vm_size_t linkeditsize, kextsize; 7469 OSSharedPtr<OSData> data; 7470 kc_format format = KCFormatUnknown; 7471 7472 if (isInFileset()) { 7473 return; 7474 } 7475 7476 #if NO_KEXTD 7477 /* We can free symbol tables for all embedded kexts because we don't 7478 * support runtime kext linking. 7479 */ 7480 if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 7481 #else 7482 if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 7483 #endif 7484 goto finish; 7485 } 7486 7487 /* Find the linkedit segment. If it's not the last segment, then freeing 7488 * it will fragment the kext into multiple VM regions, which OSKext is not 7489 * designed to handle, so we'll have to skip it. 7490 */ 7491 linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT); 7492 if (!linkedit) { 7493 goto finish; 7494 } 7495 7496 if (round_page(kmod_info->address + kmod_info->size) != 7497 round_page(linkedit->vmaddr + linkedit->vmsize)) { 7498 goto finish; 7499 } 7500 7501 /* Create a new OSData for the smaller kext object. 7502 */ 7503 linkeditsize = round_page(linkedit->vmsize); 7504 kextsize = kmod_info->size - linkeditsize; 7505 start = linkedit->vmaddr; 7506 7507 if (kextsize > UINT_MAX) { 7508 goto finish; 7509 } 7510 data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize); 7511 if (!data) { 7512 goto finish; 7513 } 7514 7515 /* Fix the kmod info and linkedExecutable. 7516 */ 7517 kmod_info->size = kextsize; 7518 7519 /* 7520 * Fileset KCs are mapped as a whole by iBoot. 7521 * Individual kext executables should not be unmapped by xnu 7522 * Doing so may result in panics like rdar://85419651 7523 */ 7524 if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) { 7525 data->setDeallocFunction(NULL); 7526 } else { // Not from a Fileset KC 7527 #if VM_MAPPED_KEXTS 7528 data->setDeallocFunction(osdata_kext_free); 7529 #else 7530 data->setDeallocFunction(osdata_phys_free); 7531 #endif 7532 } 7533 linkedExecutable->setDeallocFunction(NULL); 7534 linkedExecutable = os::move(data); 7535 flags.jettisonLinkeditSeg = 1; 7536 7537 /* Free the linkedit segment. 7538 */ 7539 #if VM_MAPPED_KEXTS 7540 kext_free(start, linkeditsize); 7541 #else 7542 ml_static_mfree(start, linkeditsize); 7543 #endif 7544 7545 finish: 7546 return; 7547 } 7548 7549 /********************************************************************* 7550 * If there are whole pages that are unused betweem the last section 7551 * of the DATA segment and the end of the DATA segment then we can free 7552 * them 7553 *********************************************************************/ 7554 void 7555 OSKext::jettisonDATASegmentPadding(void) 7556 { 7557 kernel_mach_header_t * mh; 7558 kernel_segment_command_t * dataSeg; 7559 kernel_section_t * sec, * lastSec; 7560 vm_offset_t dataSegEnd, lastSecEnd; 7561 vm_size_t padSize; 7562 7563 if (flags.builtin) { 7564 return; 7565 } 7566 mh = (kernel_mach_header_t *)kmod_info->address; 7567 7568 if (isInFileset()) { 7569 return; 7570 } 7571 7572 dataSeg = getsegbynamefromheader(mh, SEG_DATA); 7573 if (dataSeg == NULL) { 7574 return; 7575 } 7576 7577 lastSec = NULL; 7578 sec = firstsect(dataSeg); 7579 while (sec != NULL) { 7580 lastSec = sec; 7581 sec = nextsect(dataSeg, sec); 7582 } 7583 7584 if (lastSec == NULL) { 7585 return; 7586 } 7587 7588 if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) || 7589 (dataSeg->vmsize != round_page(dataSeg->vmsize))) { 7590 return; 7591 } 7592 7593 dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize; 7594 lastSecEnd = round_page(lastSec->addr + lastSec->size); 7595 7596 if (dataSegEnd <= lastSecEnd) { 7597 return; 7598 } 7599 7600 padSize = dataSegEnd - lastSecEnd; 7601 7602 if (padSize >= PAGE_SIZE) { 7603 #if VM_MAPPED_KEXTS 7604 kext_free(lastSecEnd, padSize); 7605 #else 7606 ml_static_mfree(lastSecEnd, padSize); 7607 #endif 7608 } 7609 } 7610 7611 /********************************************************************* 7612 *********************************************************************/ 7613 void 7614 OSKext::setLinkedExecutable(OSData * anExecutable) 7615 { 7616 if (linkedExecutable) { 7617 panic("Attempt to set linked executable on kext " 7618 "that already has one (%s).\n", 7619 getIdentifierCString()); 7620 } 7621 linkedExecutable.reset(anExecutable, OSRetain); 7622 return; 7623 } 7624 7625 #if CONFIG_DTRACE 7626 /********************************************************************* 7627 * Go through all loaded kexts and tell them to register with dtrace. 7628 * The instance method only registers if necessary. 7629 *********************************************************************/ 7630 /* static */ 7631 void 7632 OSKext::registerKextsWithDTrace(void) 7633 { 7634 uint32_t count = sLoadedKexts->getCount(); 7635 uint32_t i; 7636 7637 IORecursiveLockLock(sKextLock); 7638 7639 for (i = 0; i < count; i++) { 7640 OSKext * thisKext = NULL; // do not release 7641 7642 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 7643 if (!thisKext || !thisKext->isExecutable()) { 7644 continue; 7645 } 7646 7647 thisKext->registerWithDTrace(); 7648 } 7649 7650 IORecursiveLockUnlock(sKextLock); 7651 7652 return; 7653 } 7654 7655 extern "C" { 7656 extern int (*dtrace_modload)(struct kmod_info *, uint32_t); 7657 extern int (*dtrace_modunload)(struct kmod_info *); 7658 }; 7659 7660 /********************************************************************* 7661 *********************************************************************/ 7662 void 7663 OSKext::registerWithDTrace(void) 7664 { 7665 /* Register kext with dtrace. A dtrace_modload failure should not 7666 * prevent a kext from loading, so we ignore the return code. 7667 */ 7668 if (!flags.dtraceInitialized && (dtrace_modload != NULL)) { 7669 uint32_t modflag = 0; 7670 OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit"); 7671 7672 if (!sKeepSymbols && kc_type == KCKindPrimary) { 7673 if (forceInit == kOSBooleanTrue) { 7674 OSKextLog(this, 7675 kOSKextLogBasicLevel | 7676 kOSKextLogGeneralFlag, 7677 "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s", 7678 getIdentifierCString()); 7679 forceInit = kOSBooleanFalse; 7680 } 7681 /* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */ 7682 modflag |= KMOD_DTRACE_NO_KERNEL_SYMS; 7683 } 7684 7685 if (forceInit == kOSBooleanTrue) { 7686 modflag |= KMOD_DTRACE_FORCE_INIT; 7687 } 7688 if (flags.builtin) { 7689 modflag |= KMOD_DTRACE_STATIC_KEXT; 7690 } 7691 7692 (void)(*dtrace_modload)(kmod_info, modflag); 7693 flags.dtraceInitialized = true; 7694 jettisonLinkeditSegment(); 7695 } 7696 return; 7697 } 7698 /********************************************************************* 7699 *********************************************************************/ 7700 void 7701 OSKext::unregisterWithDTrace(void) 7702 { 7703 /* Unregister kext with dtrace. A dtrace_modunload failure should not 7704 * prevent a kext from loading, so we ignore the return code. 7705 */ 7706 if (flags.dtraceInitialized && (dtrace_modunload != NULL)) { 7707 (void)(*dtrace_modunload)(kmod_info); 7708 flags.dtraceInitialized = false; 7709 } 7710 return; 7711 } 7712 #endif /* CONFIG_DTRACE */ 7713 7714 7715 /********************************************************************* 7716 * called only by loadExecutable() 7717 *********************************************************************/ 7718 #if !VM_MAPPED_KEXTS 7719 #if defined(__arm__) || defined(__arm64__) 7720 static inline kern_return_t 7721 OSKext_protect( 7722 kernel_mach_header_t *kext_mh, 7723 vm_map_t map, 7724 vm_map_offset_t start, 7725 vm_map_offset_t end, 7726 vm_prot_t new_prot, 7727 boolean_t set_max, 7728 kc_kind_t kc_type) 7729 { 7730 #pragma unused(kext_mh,map,kc_type) 7731 assert(map == kernel_map); // we can handle KEXTs arising from the PRELINK segment and no others 7732 assert(start <= end); 7733 if (start >= end) { 7734 return KERN_SUCCESS; // Punt segments of length zero (e.g., headers) or less (i.e., blunders) 7735 } else if (set_max) { 7736 return KERN_SUCCESS; // Punt set_max, as there's no mechanism to record that state 7737 } else { 7738 return ml_static_protect(start, end - start, new_prot); 7739 } 7740 } 7741 7742 static inline kern_return_t 7743 OSKext_wire( 7744 kernel_mach_header_t *kext_mh, 7745 vm_map_t map, 7746 vm_map_offset_t start, 7747 vm_map_offset_t end, 7748 vm_prot_t access_type, 7749 boolean_t user_wire, 7750 kc_kind_t kc_type) 7751 { 7752 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type) 7753 return KERN_SUCCESS; // No-op as PRELINK kexts are cemented into physical memory at boot 7754 } 7755 #else 7756 #error Unrecognized architecture 7757 #endif 7758 #else 7759 static inline kern_return_t 7760 OSKext_protect( 7761 kernel_mach_header_t *kext_mh, 7762 vm_map_t map, 7763 vm_map_offset_t start, 7764 vm_map_offset_t end, 7765 vm_prot_t new_prot, 7766 boolean_t set_max, 7767 kc_kind_t kc_type) 7768 { 7769 if (start == end) { // 10538581 7770 return KERN_SUCCESS; 7771 } 7772 if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) { 7773 /* 7774 * XXX: This will probably need to be different for AuxKC and 7775 * pageableKC! 7776 */ 7777 return ml_static_protect(start, end - start, new_prot); 7778 } 7779 return vm_map_protect(map, start, end, new_prot, set_max); 7780 } 7781 7782 static inline kern_return_t 7783 OSKext_wire( 7784 kernel_mach_header_t *kext_mh, 7785 vm_map_t map, 7786 vm_map_offset_t start, 7787 vm_map_offset_t end, 7788 vm_prot_t access_type, 7789 boolean_t user_wire, 7790 kc_kind_t kc_type) 7791 { 7792 if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) { 7793 /* TODO: we may need to hook this for the pageableKC */ 7794 return KERN_SUCCESS; 7795 } 7796 return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire); 7797 } 7798 #endif 7799 7800 OSReturn 7801 OSKext::setVMAttributes(bool protect, bool wire) 7802 { 7803 vm_map_t kext_map = NULL; 7804 kernel_segment_command_t * seg = NULL; 7805 vm_map_offset_t start_protect = 0; 7806 vm_map_offset_t start_wire = 0; 7807 vm_map_offset_t end_protect = 0; 7808 vm_map_offset_t end_wire = 0; 7809 OSReturn result = kOSReturnError; 7810 7811 if (isInterface() || !declaresExecutable() || flags.builtin) { 7812 result = kOSReturnSuccess; 7813 goto finish; 7814 } 7815 7816 /* Get the kext's vm map */ 7817 kext_map = kext_get_vm_map(kmod_info); 7818 if (!kext_map) { 7819 result = KERN_MEMORY_ERROR; 7820 goto finish; 7821 } 7822 7823 #if !VM_MAPPED_KEXTS 7824 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) { 7825 /* This is a split kext in a prelinked kernelcache; we'll let the 7826 * platform code take care of protecting it. It is already wired. 7827 */ 7828 /* TODO: Should this still allow protections for the first segment 7829 * to go through, in the event that we have a mix of split and 7830 * unsplit kexts? 7831 */ 7832 result = KERN_SUCCESS; 7833 goto finish; 7834 } 7835 7836 if (isInFileset() && kc_type != KCKindPageable) { 7837 // kexts in filesets have protections setup as part of collection loading 7838 result = KERN_SUCCESS; 7839 goto finish; 7840 } 7841 #endif 7842 7843 /* Protect the headers as read-only; they do not need to be wired */ 7844 result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address, 7845 kext_map, kmod_info->address, 7846 kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type) 7847 : KERN_SUCCESS; 7848 if (result != KERN_SUCCESS) { 7849 goto finish; 7850 } 7851 7852 /* Set the VM protections and wire down each of the segments */ 7853 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 7854 while (seg) { 7855 #if __arm__ 7856 /* We build all ARM kexts, so we can ensure they are aligned */ 7857 assert((seg->vmaddr & PAGE_MASK) == 0); 7858 assert((seg->vmsize & PAGE_MASK) == 0); 7859 #endif 7860 7861 /* 7862 * For the non page aligned segments, the range calculation for protection 7863 * and wiring differ as follows: 7864 * 7865 * Protection: The non page aligned data at the start or at the end of the 7866 * segment is excluded from the protection. This exclusion is needed to make 7867 * sure OSKext_protect is not called twice on same page, if the page is shared 7868 * between two segments. 7869 * 7870 * Wiring: The non page aligned data at the start or at the end of the 7871 * segment is included in the wiring range, this inclusion is needed to make sure 7872 * all the data of the segment is wired. 7873 */ 7874 start_protect = round_page(seg->vmaddr); 7875 end_protect = trunc_page(seg->vmaddr + seg->vmsize); 7876 7877 start_wire = trunc_page(seg->vmaddr); 7878 end_wire = round_page(seg->vmaddr + seg->vmsize); 7879 7880 /* 7881 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared 7882 * across kexts and data from kexts is not page aligned 7883 */ 7884 if (protect && (end_protect > start_protect) && 7885 ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 && 7886 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) || 7887 (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) { 7888 result = OSKext_protect((kernel_mach_header_t *)kmod_info->address, 7889 kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type); 7890 if (result != KERN_SUCCESS) { 7891 OSKextLog(this, 7892 kOSKextLogErrorLevel | 7893 kOSKextLogLoadFlag, 7894 "Kext %s failed to set maximum VM protections " 7895 "for segment %s - 0x%x.", 7896 getIdentifierCString(), seg->segname, (int)result); 7897 goto finish; 7898 } 7899 7900 result = OSKext_protect((kernel_mach_header_t *)kmod_info->address, 7901 kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type); 7902 if (result != KERN_SUCCESS) { 7903 OSKextLog(this, 7904 kOSKextLogErrorLevel | 7905 kOSKextLogLoadFlag, 7906 "Kext %s failed to set initial VM protections " 7907 "for segment %s - 0x%x.", 7908 getIdentifierCString(), seg->segname, (int)result); 7909 goto finish; 7910 } 7911 } 7912 7913 if (segmentShouldBeWired(seg) && wire) { 7914 result = OSKext_wire((kernel_mach_header_t *)kmod_info->address, 7915 kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type); 7916 if (result != KERN_SUCCESS) { 7917 goto finish; 7918 } 7919 } 7920 7921 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 7922 } 7923 7924 finish: 7925 return result; 7926 } 7927 7928 /********************************************************************* 7929 *********************************************************************/ 7930 boolean_t 7931 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg) 7932 { 7933 return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) && 7934 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname))); 7935 } 7936 7937 /********************************************************************* 7938 *********************************************************************/ 7939 OSReturn 7940 OSKext::validateKextMapping(bool startFlag) 7941 { 7942 OSReturn result = kOSReturnError; 7943 const char * whichOp = startFlag ? "start" : "stop"; 7944 kern_return_t kern_result = 0; 7945 vm_map_t kext_map = NULL; 7946 kernel_segment_command_t * seg = NULL; 7947 mach_vm_address_t address = 0; 7948 mach_vm_size_t size = 0; 7949 uint32_t depth = 0; 7950 uint64_t kext_segbase = 0; 7951 uint64_t kext_segsize = 0; 7952 mach_msg_type_number_t count; 7953 vm_region_submap_short_info_data_64_t info; 7954 uintptr_t kext_slide = PE_get_kc_slide(kc_type); 7955 7956 if (flags.builtin) { 7957 return kOSReturnSuccess; 7958 } 7959 7960 count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 7961 bzero(&info, sizeof(info)); 7962 7963 // xxx - do we need a distinct OSReturn value for these or is "bad data" 7964 // xxx - sufficient? 7965 7966 /* Verify that the kmod_info and start/stop pointers are non-NULL. 7967 */ 7968 if (!kmod_info) { 7969 OSKextLog(this, 7970 kOSKextLogErrorLevel | 7971 kOSKextLogLoadFlag, 7972 "Kext %s - NULL kmod_info pointer.", 7973 getIdentifierCString()); 7974 result = kOSKextReturnBadData; 7975 goto finish; 7976 } 7977 7978 if (startFlag) { 7979 address = (mach_vm_address_t)kmod_info->start; 7980 } else { 7981 address = (mach_vm_address_t)kmod_info->stop; 7982 } 7983 7984 if (!address) { 7985 OSKextLog(this, 7986 kOSKextLogErrorLevel | 7987 kOSKextLogLoadFlag, 7988 "Kext %s - NULL module %s pointer.", 7989 getIdentifierCString(), whichOp); 7990 result = kOSKextReturnBadData; 7991 goto finish; 7992 } 7993 7994 kext_map = kext_get_vm_map(kmod_info); 7995 depth = (kernel_map == kext_map) ? 1 : 2; 7996 if (isInFileset()) { 7997 #if defined(HAS_APPLE_PAC) 7998 address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0); 7999 #endif /* defined(HAS_APPLE_PAC) */ 8000 } 8001 8002 /* Verify that the start/stop function lies within the kext's address range. 8003 */ 8004 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) || 8005 isInFileset()) { 8006 /* This will likely be how we deal with split kexts; walk the segments to 8007 * check that the function lies inside one of the segments of this kext. 8008 */ 8009 for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 8010 seg != NULL; 8011 seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) { 8012 if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) { 8013 kext_segbase = seg->vmaddr; 8014 kext_segsize = seg->vmsize; 8015 break; 8016 } 8017 } 8018 8019 if (!seg) { 8020 OSKextLog(this, 8021 kOSKextLogErrorLevel | 8022 kOSKextLogLoadFlag, 8023 "Kext %s module %s pointer is outside of kext range " 8024 "(%s %p - kext starts at %p).", 8025 getIdentifierCString(), 8026 whichOp, 8027 whichOp, 8028 (void *)(((uintptr_t)address) - kext_slide), 8029 (void *)(((uintptr_t)kmod_info->address) - kext_slide)); 8030 result = kOSKextReturnBadData; 8031 goto finish; 8032 } 8033 8034 seg = NULL; 8035 } else { 8036 if (address < kmod_info->address + kmod_info->hdr_size || 8037 kmod_info->address + kmod_info->size <= address) { 8038 OSKextLog(this, 8039 kOSKextLogErrorLevel | 8040 kOSKextLogLoadFlag, 8041 "Kext %s module %s pointer is outside of kext range " 8042 "(%s %p - kext at %p-%p).", 8043 getIdentifierCString(), 8044 whichOp, 8045 whichOp, 8046 (void *)(((uintptr_t)address) - kext_slide), 8047 (void *)(((uintptr_t)kmod_info->address) - kext_slide), 8048 (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size)); 8049 result = kOSKextReturnBadData; 8050 goto finish; 8051 } 8052 } 8053 8054 /* Only do these checks before calling the start function; 8055 * If anything goes wrong with the mapping while the kext is running, 8056 * we'll likely have panicked well before any attempt to stop the kext. 8057 */ 8058 if (startFlag) { 8059 if (!isInFileset() || kc_type != KCKindPrimary) { 8060 /* 8061 * Verify that the start/stop function is executable. 8062 */ 8063 kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth, 8064 (vm_region_recurse_info_t)&info, &count); 8065 if (kern_result != KERN_SUCCESS) { 8066 OSKextLog(this, 8067 kOSKextLogErrorLevel | 8068 kOSKextLogLoadFlag, 8069 "Kext %s - bad %s pointer %p.", 8070 getIdentifierCString(), 8071 whichOp, (void *)ml_static_unslide(address)); 8072 result = kOSKextReturnBadData; 8073 goto finish; 8074 } 8075 } else { 8076 /* 8077 * Since kexts loaded from the primary KC are held in memory 8078 * allocated by efiboot, we cannot use mach_vm_region_recurse() to 8079 * discover that memory's protection flags. Instead, we need to 8080 * get that information from the kernel pmap itself. Above, we 8081 * (potentially) saved the size of the segment in which the address 8082 * in question was located. If we have a non-zero size, verify 8083 * that all pages in the (address, address + kext_segsize) range 8084 * are marked executable. If we somehow did not record the size 8085 * (or the base) just verify the single page that includes the address. 8086 */ 8087 if (kext_segbase == 0 || kext_segsize == 0) { 8088 kext_segbase = address & ~(uint64_t)PAGE_MASK; 8089 kext_segsize = PAGE_SIZE; 8090 } 8091 } 8092 8093 #if VM_MAPPED_KEXTS 8094 if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) || 8095 ((isInFileset() && kc_type == KCKindPrimary) && 8096 ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) { 8097 OSKextLog(this, 8098 kOSKextLogErrorLevel | 8099 kOSKextLogLoadFlag, 8100 "Kext %s - memory region containing module %s function " 8101 "is not executable.", 8102 getIdentifierCString(), whichOp); 8103 result = kOSKextReturnBadData; 8104 goto finish; 8105 } 8106 #endif 8107 8108 /* Verify that the kext's segments are backed by physical memory. 8109 */ 8110 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 8111 while (seg) { 8112 if (!verifySegmentMapping(seg)) { 8113 result = kOSKextReturnBadData; 8114 goto finish; 8115 } 8116 8117 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 8118 } 8119 } 8120 8121 result = kOSReturnSuccess; 8122 finish: 8123 return result; 8124 } 8125 8126 /********************************************************************* 8127 *********************************************************************/ 8128 boolean_t 8129 OSKext::verifySegmentMapping(kernel_segment_command_t *seg) 8130 { 8131 mach_vm_address_t address = 0; 8132 8133 if (seg->vmsize > UINT32_MAX) { 8134 return false; 8135 } 8136 8137 if (!segmentShouldBeWired(seg)) { 8138 return true; 8139 } 8140 8141 for (address = seg->vmaddr; 8142 address < round_page(seg->vmaddr + seg->vmsize); 8143 address += PAGE_SIZE) { 8144 if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) { 8145 OSKextLog(this, 8146 kOSKextLogErrorLevel | 8147 kOSKextLogLoadFlag, 8148 "Kext %s - page %p is not backed by physical memory.", 8149 getIdentifierCString(), 8150 (void *)address); 8151 return false; 8152 } 8153 } 8154 8155 return true; 8156 } 8157 8158 /********************************************************************* 8159 *********************************************************************/ 8160 static void 8161 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code) 8162 { 8163 uint64_t stamp = 0; 8164 firehose_tracepoint_id_u trace_id; 8165 struct firehose_trace_uuid_info_s uuid_info_s; 8166 firehose_trace_uuid_info_t uuid_info = &uuid_info_s; 8167 size_t uuid_info_len = sizeof(struct firehose_trace_uuid_info_s); 8168 OSSharedPtr<OSData> uuid_data; 8169 8170 stamp = firehose_tracepoint_time(firehose_activity_flags_default); 8171 trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code); 8172 8173 uuid_data = aKext->copyTextUUID(); 8174 if (uuid_data) { 8175 memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid)); 8176 } 8177 8178 uuid_info->ftui_size = size; 8179 if (aKext->isDriverKit()) { 8180 uuid_info->ftui_address = address; 8181 } else { 8182 uuid_info->ftui_address = ml_static_unslide(address); 8183 } 8184 firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len); 8185 return; 8186 } 8187 8188 void 8189 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext) 8190 { 8191 OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load); 8192 } 8193 8194 /********************************************************************* 8195 *********************************************************************/ 8196 OSReturn 8197 OSKext::start(bool startDependenciesFlag) 8198 { 8199 OSReturn result = kOSReturnError; 8200 kern_return_t (* startfunc)(kmod_info_t *, void *); 8201 unsigned int i, count; 8202 void * kmodStartData = NULL; 8203 8204 if (isStarted() || isInterface() || isKernelComponent()) { 8205 result = kOSReturnSuccess; 8206 goto finish; 8207 } 8208 8209 if (!isLoaded()) { 8210 OSKextLog(this, 8211 kOSKextLogErrorLevel | 8212 kOSKextLogLoadFlag, 8213 "Attempt to start nonloaded kext %s.", 8214 getIdentifierCString()); 8215 result = kOSKextReturnInvalidArgument; 8216 goto finish; 8217 } 8218 8219 if (!sLoadEnabled) { 8220 OSKextLog(this, 8221 kOSKextLogErrorLevel | 8222 kOSKextLogLoadFlag, 8223 "Kext loading is disabled (attempt to start kext %s).", 8224 getIdentifierCString()); 8225 result = kOSKextReturnDisabled; 8226 goto finish; 8227 } 8228 8229 result = validateKextMapping(/* start? */ true); 8230 if (result != kOSReturnSuccess) { 8231 goto finish; 8232 } 8233 8234 startfunc = kmod_info->start; 8235 8236 count = getNumDependencies(); 8237 for (i = 0; i < count; i++) { 8238 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i)); 8239 if (dependency == NULL) { 8240 OSKextLog(this, 8241 kOSKextLogErrorLevel | 8242 kOSKextLogLoadFlag, 8243 "Kext %s start - internal error, dependency disappeared.", 8244 getIdentifierCString()); 8245 goto finish; 8246 } 8247 if (!dependency->isStarted()) { 8248 if (startDependenciesFlag) { 8249 OSReturn dependencyResult = 8250 dependency->start(startDependenciesFlag); 8251 if (dependencyResult != KERN_SUCCESS) { 8252 OSKextLog(this, 8253 kOSKextLogErrorLevel | 8254 kOSKextLogLoadFlag, 8255 "Kext %s start - dependency %s failed to start (error 0x%x).", 8256 getIdentifierCString(), 8257 dependency->getIdentifierCString(), 8258 dependencyResult); 8259 goto finish; 8260 } 8261 } else { 8262 OSKextLog(this, 8263 kOSKextLogErrorLevel | 8264 kOSKextLogLoadFlag, 8265 "Not starting %s - dependency %s not started yet.", 8266 getIdentifierCString(), 8267 dependency->getIdentifierCString()); 8268 result = kOSKextReturnStartStopError; // xxx - make new return? 8269 goto finish; 8270 } 8271 } 8272 } 8273 8274 OSKextLog(this, 8275 kOSKextLogDetailLevel | 8276 kOSKextLogLoadFlag, 8277 "Kext %s calling module start function.", 8278 getIdentifierCString()); 8279 8280 flags.starting = 1; 8281 8282 // Drop a log message so logd can grab the needed information to decode this kext 8283 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load); 8284 result = OSRuntimeInitializeCPP(this); 8285 if (result == KERN_SUCCESS) { 8286 result = startfunc(kmod_info, kmodStartData); 8287 } 8288 8289 flags.starting = 0; 8290 8291 /* On success overlap the setting of started/starting. On failure just 8292 * clear starting. 8293 */ 8294 if (result == KERN_SUCCESS) { 8295 flags.started = 1; 8296 8297 // xxx - log start error from kernel? 8298 OSKextLog(this, 8299 kOSKextLogProgressLevel | 8300 kOSKextLogLoadFlag, 8301 "Kext %s is now started.", 8302 getIdentifierCString()); 8303 } else { 8304 invokeOrCancelRequestCallbacks( 8305 /* result not actually used */ kOSKextReturnStartStopError, 8306 /* invokeFlag */ false); 8307 OSKextLog(this, 8308 kOSKextLogWarningLevel | 8309 kOSKextLogLoadFlag, 8310 "Kext %s did not start (return code 0x%x).", 8311 getIdentifierCString(), result); 8312 } 8313 8314 finish: 8315 return result; 8316 } 8317 8318 /********************************************************************* 8319 *********************************************************************/ 8320 /* static */ 8321 bool 8322 OSKext::canUnloadKextWithIdentifier( 8323 OSString * kextIdentifier, 8324 bool checkClassesFlag) 8325 { 8326 bool result = false; 8327 OSKext * aKext = NULL; // do not release 8328 8329 IORecursiveLockLock(sKextLock); 8330 8331 aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 8332 8333 if (!aKext) { 8334 goto finish; // can't unload what's not loaded 8335 } 8336 8337 if (aKext->isLoaded()) { 8338 if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) { 8339 goto finish; 8340 } 8341 if (checkClassesFlag && aKext->hasOSMetaClassInstances()) { 8342 goto finish; 8343 } 8344 } 8345 8346 result = true; 8347 8348 finish: 8349 IORecursiveLockUnlock(sKextLock); 8350 return result; 8351 } 8352 8353 /********************************************************************* 8354 *********************************************************************/ 8355 OSReturn 8356 OSKext::stop(void) 8357 { 8358 OSReturn result = kOSReturnError; 8359 kern_return_t (*stopfunc)(kmod_info_t *, void *); 8360 8361 if (!isStarted() || isInterface()) { 8362 result = kOSReturnSuccess; 8363 goto finish; 8364 } 8365 8366 if (!isLoaded()) { 8367 OSKextLog(this, 8368 kOSKextLogErrorLevel | 8369 kOSKextLogLoadFlag, 8370 "Attempt to stop nonloaded kext %s.", 8371 getIdentifierCString()); 8372 result = kOSKextReturnInvalidArgument; 8373 goto finish; 8374 } 8375 8376 /* Refuse to stop if we have clients or instances. It is up to 8377 * the caller to make sure those aren't true. 8378 */ 8379 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 8380 OSKextLog(this, 8381 kOSKextLogErrorLevel | 8382 kOSKextLogLoadFlag, 8383 "Kext %s - C++ instances; can't stop.", 8384 getIdentifierCString()); 8385 result = kOSKextReturnInUse; 8386 goto finish; 8387 } 8388 8389 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 8390 OSKextLog(this, 8391 kOSKextLogErrorLevel | 8392 kOSKextLogLoadFlag, 8393 "Kext %s - has references (linkage or tracking object); " 8394 "can't stop.", 8395 getIdentifierCString()); 8396 result = kOSKextReturnInUse; 8397 goto finish; 8398 } 8399 8400 /* Note: If validateKextMapping fails on the stop & unload path, 8401 * we are in serious trouble and a kernel panic is likely whether 8402 * we stop & unload the kext or not. 8403 */ 8404 result = validateKextMapping(/* start? */ false); 8405 if (result != kOSReturnSuccess) { 8406 goto finish; 8407 } 8408 8409 stopfunc = kmod_info->stop; 8410 if (stopfunc) { 8411 OSKextLog(this, 8412 kOSKextLogDetailLevel | 8413 kOSKextLogLoadFlag, 8414 "Kext %s calling module stop function.", 8415 getIdentifierCString()); 8416 8417 flags.stopping = 1; 8418 8419 result = stopfunc(kmod_info, /* userData */ NULL); 8420 if (result == KERN_SUCCESS) { 8421 result = OSRuntimeFinalizeCPP(this); 8422 } 8423 8424 flags.stopping = 0; 8425 8426 if (result == KERN_SUCCESS) { 8427 flags.started = 0; 8428 8429 OSKextLog(this, 8430 kOSKextLogDetailLevel | 8431 kOSKextLogLoadFlag, 8432 "Kext %s is now stopped and ready to unload.", 8433 getIdentifierCString()); 8434 } else { 8435 OSKextLog(this, 8436 kOSKextLogErrorLevel | 8437 kOSKextLogLoadFlag, 8438 "Kext %s did not stop (return code 0x%x).", 8439 getIdentifierCString(), result); 8440 result = kOSKextReturnStartStopError; 8441 } 8442 } 8443 8444 finish: 8445 // Drop a log message so logd can update this kext's metadata 8446 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload); 8447 return result; 8448 } 8449 8450 /********************************************************************* 8451 *********************************************************************/ 8452 OSReturn 8453 OSKext::unload(void) 8454 { 8455 OSReturn result = kOSReturnError; 8456 unsigned int index; 8457 uint32_t num_kmod_refs = 0; 8458 OSKextAccount * freeAccount; 8459 bool in_fileset = false; 8460 8461 if (!sUnloadEnabled) { 8462 OSKextLog(this, 8463 kOSKextLogErrorLevel | 8464 kOSKextLogLoadFlag, 8465 "Kext unloading is disabled (%s).", 8466 this->getIdentifierCString()); 8467 8468 result = kOSKextReturnDisabled; 8469 goto finish; 8470 } 8471 8472 // cache this result so we don't need to access the kmod_info after 8473 // it's been potentially free'd 8474 in_fileset = isInFileset(); 8475 8476 /* Refuse to unload if we have clients or instances. It is up to 8477 * the caller to make sure those aren't true. 8478 */ 8479 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 8480 // xxx - Don't log under errors? this is more of an info thing 8481 OSKextLog(this, 8482 kOSKextLogErrorLevel | 8483 kOSKextLogKextBookkeepingFlag, 8484 "Can't unload kext %s; outstanding references %d (linkage or tracking object).", 8485 getIdentifierCString(), getRetainCount()); 8486 result = kOSKextReturnInUse; 8487 goto finish; 8488 } 8489 8490 if (isDriverKit()) { 8491 index = sLoadedDriverKitKexts->getNextIndexOfObject(this, 0); 8492 if (index != (unsigned int)-1) { 8493 sLoadedDriverKitKexts->removeObject(index); 8494 OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload); 8495 loadTag = 0; 8496 } 8497 } 8498 8499 if (!isLoaded()) { 8500 result = kOSReturnSuccess; 8501 goto finish; 8502 } 8503 8504 if (isKernelComponent()) { 8505 result = kOSKextReturnInvalidArgument; 8506 goto finish; 8507 } 8508 8509 if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) { 8510 OSKextLog(this, 8511 kOSKextLogErrorLevel | 8512 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 8513 "Can't unload kext %s; classes have instances:", 8514 getIdentifierCString()); 8515 reportOSMetaClassInstances(kOSKextLogErrorLevel | 8516 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag); 8517 result = kOSKextReturnInUse; 8518 goto finish; 8519 } 8520 8521 /* Note that the kext is unloading before running any code that 8522 * might be in the kext (request callbacks, module stop function). 8523 * We will deny certain requests made against a kext in the process 8524 * of unloading. 8525 */ 8526 flags.unloading = 1; 8527 8528 /* Update the string describing the last kext to unload in case we panic. 8529 */ 8530 savePanicString(/* isLoading */ false); 8531 8532 if (isStarted()) { 8533 result = stop(); 8534 if (result != KERN_SUCCESS) { 8535 OSKextLog(this, 8536 kOSKextLogErrorLevel | 8537 kOSKextLogLoadFlag, 8538 "Kext %s can't unload - module stop returned 0x%x.", 8539 getIdentifierCString(), (unsigned)result); 8540 result = kOSKextReturnStartStopError; 8541 goto finish; 8542 } 8543 } 8544 8545 OSKextLog(this, 8546 kOSKextLogProgressLevel | 8547 kOSKextLogLoadFlag, 8548 "Kext %s unloading.", 8549 getIdentifierCString()); 8550 8551 { 8552 struct list_head *p; 8553 struct list_head *prev; 8554 struct list_head *next; 8555 for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) { 8556 OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head); 8557 s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize); 8558 prev = p->prev; 8559 next = p->next; 8560 prev->next = next; 8561 next->prev = prev; 8562 p->prev = p; 8563 p->next = p; 8564 IORecursiveLockWakeup(sKextLock, s, false); 8565 } 8566 } 8567 8568 8569 /* Even if we don't call the stop function, we want to be sure we 8570 * have no OSMetaClass references before unloading the kext executable 8571 * from memory. OSMetaClasses may have pointers into the kext executable 8572 * and that would cause a panic on OSKext::free() when metaClasses is freed. 8573 */ 8574 if (metaClasses) { 8575 metaClasses->flushCollection(); 8576 } 8577 (void) OSRuntimeFinalizeCPP(this); 8578 8579 /* Remove the kext from the list of loaded kexts, patch the gap 8580 * in the kmod_info_t linked list, and reset "kmod" to point to the 8581 * last loaded kext that isn't the fake kernel kext (sKernelKext). 8582 */ 8583 index = sLoadedKexts->getNextIndexOfObject(this, 0); 8584 if (index != (unsigned int)-1) { 8585 sLoadedKexts->removeObject(index); 8586 8587 OSKext * nextKext = OSDynamicCast(OSKext, 8588 sLoadedKexts->getObject(index)); 8589 8590 if (nextKext) { 8591 if (index > 0) { 8592 OSKext * gapKext = OSDynamicCast(OSKext, 8593 sLoadedKexts->getObject(index - 1)); 8594 8595 nextKext->kmod_info->next = gapKext->kmod_info; 8596 } else { /* index == 0 */ 8597 nextKext->kmod_info->next = NULL; 8598 } 8599 } 8600 8601 OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 8602 if (lastKext && !lastKext->isKernel()) { 8603 kmod = lastKext->kmod_info; 8604 } else { 8605 kmod = NULL; // clear the global kmod variable 8606 } 8607 } 8608 8609 /* Clear out the kmod references that we're keeping for compatibility 8610 * with current panic backtrace code & kgmacros. 8611 * xxx - will want to update those bits sometime and remove this. 8612 */ 8613 num_kmod_refs = getNumDependencies(); 8614 if (num_kmod_refs && kmod_info && kmod_info->reference_list) { 8615 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 8616 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 8617 ref->info->reference_count--; 8618 } 8619 kfree_type(kmod_reference_t, num_kmod_refs, 8620 kmod_info->reference_list); 8621 } 8622 8623 #if CONFIG_DTRACE 8624 unregisterWithDTrace(); 8625 #endif /* CONFIG_DTRACE */ 8626 8627 notifyKextUnloadObservers(this); 8628 8629 freeAccount = NULL; 8630 lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp); 8631 account->kext = NULL; 8632 if (account->site.tag) { 8633 account->site.flags |= VM_TAG_UNLOAD; 8634 } else { 8635 freeAccount = account; 8636 } 8637 8638 #if DEVELOPMENT || DEBUG 8639 assertf(account->task_refgrp.grp_count == 0, 8640 "unloading a kext with active task references"); 8641 #endif /* DEVELOPMENT || DEBUG */ 8642 8643 lck_ticket_unlock(sKextAccountsLock); 8644 if (freeAccount) { 8645 IOFreeType(freeAccount, OSKextAccount); 8646 } 8647 8648 /* Unwire and free the linked executable. 8649 */ 8650 if (linkedExecutable) { 8651 #if KASAN 8652 kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength()); 8653 #endif 8654 8655 #if VM_MAPPED_KEXTS 8656 if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) { 8657 kernel_segment_command_t *seg = NULL; 8658 vm_map_t kext_map = kext_get_vm_map(kmod_info); 8659 8660 if (!kext_map) { 8661 OSKextLog(this, 8662 kOSKextLogErrorLevel | 8663 kOSKextLogLoadFlag, 8664 "Failed to free kext %s; couldn't find the kext map.", 8665 getIdentifierCString()); 8666 result = kOSKextReturnInternalError; 8667 goto finish; 8668 } 8669 8670 OSKextLog(this, 8671 kOSKextLogProgressLevel | 8672 kOSKextLogLoadFlag, 8673 "Kext %s unwiring and unmapping linked executable.", 8674 getIdentifierCString()); 8675 8676 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 8677 while (seg) { 8678 if (segmentShouldBeWired(seg)) { 8679 vm_map_offset_t start_wire = trunc_page(seg->vmaddr); 8680 vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize); 8681 8682 result = vm_map_unwire(kext_map, start_wire, 8683 end_wire, FALSE); 8684 if (result != KERN_SUCCESS) { 8685 OSKextLog(this, 8686 kOSKextLogErrorLevel | 8687 kOSKextLogLoadFlag, 8688 "Failed to unwire kext %s.", 8689 getIdentifierCString()); 8690 result = kOSKextReturnInternalError; 8691 goto finish; 8692 } 8693 } 8694 8695 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 8696 } 8697 #if defined(__x86_64__) || defined(__i386__) 8698 if (in_fileset && flags.resetSegmentsFromVnode) { 8699 IORecursiveLockLock(sKextLock); 8700 resetKCFileSetSegments(); 8701 IORecursiveLockUnlock(sKextLock); 8702 } 8703 #endif // (__x86_64__) || defined(__i386__) 8704 } 8705 #endif /* VM_MAPPED_KEXTS */ 8706 if (flags.resetSegmentsFromImmutableCopy) { 8707 result = resetMutableSegments(); 8708 if (result != kOSReturnSuccess) { 8709 OSKextLog(this, 8710 kOSKextLogErrorLevel | 8711 kOSKextLogLoadFlag, 8712 "Failed to reset kext %s.", 8713 getIdentifierCString()); 8714 result = kOSKextReturnInternalError; 8715 goto finish; 8716 } 8717 } 8718 if (kc_type == KCKindUnknown) { 8719 linkedExecutable.reset(); 8720 } 8721 } 8722 8723 /* An interface kext has a fake kmod_info that was allocated, 8724 * so we have to free it. 8725 */ 8726 if (isInterface()) { 8727 kfree_type(kmod_info_t, kmod_info); 8728 kmod_info = NULL; 8729 } 8730 8731 if (!in_fileset) { 8732 kmod_info = NULL; 8733 } 8734 8735 flags.loaded = false; 8736 flushDependencies(); 8737 8738 /* save a copy of the bundle ID for us to check when deciding to 8739 * rebuild the kernel cache file. If a kext was already in the kernel 8740 * cache and unloaded then later loaded we do not need to rebuild the 8741 * kernel cache. 9055303 8742 */ 8743 if (isPrelinked()) { 8744 if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) { 8745 IORecursiveLockLock(sKextLock); 8746 if (sUnloadedPrelinkedKexts) { 8747 sUnloadedPrelinkedKexts->setObject(bundleID.get()); 8748 } 8749 IORecursiveLockUnlock(sKextLock); 8750 } 8751 } 8752 8753 OSKextLog(this, 8754 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 8755 "Kext %s unloaded.", getIdentifierCString()); 8756 8757 queueKextNotification(kKextRequestPredicateUnloadNotification, 8758 OSDynamicCast(OSString, bundleID.get())); 8759 8760 finish: 8761 OSKext::saveLoadedKextPanicList(); 8762 OSKext::updateLoadedKextSummaries(); 8763 8764 flags.unloading = 0; 8765 return result; 8766 } 8767 8768 /********************************************************************* 8769 * Assumes sKextLock is held. 8770 *********************************************************************/ 8771 /* static */ 8772 OSReturn 8773 OSKext::queueKextNotification( 8774 const char * notificationName, 8775 OSString * kextIdentifier) 8776 { 8777 OSReturn result = kOSReturnError; 8778 OSSharedPtr<OSDictionary> loadRequest; 8779 8780 if (!kextIdentifier) { 8781 result = kOSKextReturnInvalidArgument; 8782 goto finish; 8783 } 8784 8785 /* Create a new request unless one is already sitting 8786 * in sKernelRequests for this bundle identifier 8787 */ 8788 result = _OSKextCreateRequest(notificationName, loadRequest); 8789 if (result != kOSReturnSuccess) { 8790 goto finish; 8791 } 8792 if (!_OSKextSetRequestArgument(loadRequest.get(), 8793 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 8794 result = kOSKextReturnNoMemory; 8795 goto finish; 8796 } 8797 if (!sKernelRequests->setObject(loadRequest.get())) { 8798 result = kOSKextReturnNoMemory; 8799 goto finish; 8800 } 8801 8802 /* We might want to only queue the notification if the IOKit daemon is active, 8803 * but that wouldn't work for embedded. Note that we don't care if 8804 * the ping immediately succeeds here so don't do anything with the 8805 * result of this call. 8806 */ 8807 OSKext::pingIOKitDaemon(); 8808 8809 result = kOSReturnSuccess; 8810 8811 finish: 8812 return result; 8813 } 8814 8815 8816 #if CONFIG_KXLD 8817 /********************************************************************* 8818 *********************************************************************/ 8819 static void 8820 _OSKextConsiderDestroyingLinkContext( 8821 __unused thread_call_param_t p0, 8822 __unused thread_call_param_t p1) 8823 { 8824 /* Take multiple locks in the correct order. 8825 */ 8826 IORecursiveLockLock(sKextLock); 8827 IORecursiveLockLock(sKextInnerLock); 8828 8829 /* The first time we destroy the kxldContext is in the first 8830 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled 8831 * before calling this function. Thereafter any call to this function 8832 * will actually destroy the context. 8833 */ 8834 if (sConsiderUnloadsCalled && sKxldContext) { 8835 kxld_destroy_context(sKxldContext); 8836 sKxldContext = NULL; 8837 } 8838 8839 /* Free the thread_call that was allocated to execute this function. 8840 */ 8841 if (sDestroyLinkContextThread) { 8842 if (!thread_call_free(sDestroyLinkContextThread)) { 8843 OSKextLog(/* kext */ NULL, 8844 kOSKextLogErrorLevel | 8845 kOSKextLogGeneralFlag, 8846 "thread_call_free() failed for kext link context."); 8847 } 8848 sDestroyLinkContextThread = NULL; 8849 } 8850 8851 IORecursiveLockUnlock(sKextInnerLock); 8852 IORecursiveLockUnlock(sKextLock); 8853 8854 return; 8855 } 8856 8857 /********************************************************************* 8858 * Destroying the kxldContext requires checking variables under both 8859 * sKextInnerLock and sKextLock, so we do it on a separate thread 8860 * to avoid deadlocks with IOService, with which OSKext has a reciprocal 8861 * call relationship. 8862 * 8863 * This function must be invoked with sKextInnerLock held. 8864 * Do not call any function that takes sKextLock here! 8865 *********************************************************************/ 8866 /* static */ 8867 void 8868 OSKext::considerDestroyingLinkContext(void) 8869 { 8870 IORecursiveLockLock(sKextInnerLock); 8871 8872 /* If we have already queued a thread to destroy the link context, 8873 * don't bother resetting; that thread will take care of it. 8874 */ 8875 if (sDestroyLinkContextThread) { 8876 goto finish; 8877 } 8878 8879 /* The function to be invoked in the thread will deallocate 8880 * this thread_call, so don't share it around. 8881 */ 8882 sDestroyLinkContextThread = thread_call_allocate( 8883 &_OSKextConsiderDestroyingLinkContext, NULL); 8884 if (!sDestroyLinkContextThread) { 8885 OSKextLog(/* kext */ NULL, 8886 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag, 8887 "Can't create thread to destroy kext link context."); 8888 goto finish; 8889 } 8890 8891 thread_call_enter(sDestroyLinkContextThread); 8892 8893 finish: 8894 IORecursiveLockUnlock(sKextInnerLock); 8895 return; 8896 } 8897 8898 #else // !CONFIG_KXLD 8899 8900 /* static */ 8901 void 8902 OSKext::considerDestroyingLinkContext(void) 8903 { 8904 return; 8905 } 8906 8907 #endif // CONFIG_KXLD 8908 8909 #if PRAGMA_MARK 8910 #pragma mark Autounload 8911 #endif 8912 /********************************************************************* 8913 * This is a static method because the kext will be deallocated if it 8914 * does unload! 8915 *********************************************************************/ 8916 /* static */ 8917 OSReturn 8918 OSKext::autounloadKext(OSKext * aKext) 8919 { 8920 OSReturn result = kOSKextReturnInUse; 8921 8922 #if NO_KEXTD 8923 /* 8924 * Do not unload prelinked kexts on platforms that do not have an 8925 * IOKit daemon as there is no way to reload the kext or restart 8926 * matching. 8927 */ 8928 if (aKext->isPrelinked()) { 8929 goto finish; 8930 } 8931 #endif /* defined(__x86_64__) */ 8932 8933 /* Check for external references to this kext (usu. dependents), 8934 * instances of defined classes (or classes derived from them), 8935 * outstanding requests. 8936 */ 8937 if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) || 8938 !aKext->flags.autounloadEnabled || 8939 aKext->isKernelComponent()) { 8940 goto finish; 8941 } 8942 8943 /* Skip a delay-autounload kext, once. 8944 */ 8945 if (aKext->flags.delayAutounload) { 8946 OSKextLog(aKext, 8947 kOSKextLogProgressLevel | 8948 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 8949 "Kext %s has delayed autounload set; skipping and clearing flag.", 8950 aKext->getIdentifierCString()); 8951 aKext->flags.delayAutounload = 0; 8952 goto finish; 8953 } 8954 8955 if (aKext->hasOSMetaClassInstances() || 8956 aKext->countRequestCallbacks()) { 8957 goto finish; 8958 } 8959 8960 result = OSKext::removeKext(aKext); 8961 8962 finish: 8963 return result; 8964 } 8965 8966 /********************************************************************* 8967 *********************************************************************/ 8968 void 8969 _OSKextConsiderUnloads( 8970 __unused thread_call_param_t p0, 8971 __unused thread_call_param_t p1) 8972 { 8973 bool didUnload = false; 8974 unsigned int count, i; 8975 8976 /* Take multiple locks in the correct order 8977 * (note also sKextSummaries lock further down). 8978 */ 8979 IORecursiveLockLock(sKextLock); 8980 IORecursiveLockLock(sKextInnerLock); 8981 8982 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true); 8983 8984 /* If the system is powering down, don't try to unload anything. 8985 */ 8986 if (sSystemSleep) { 8987 goto finish; 8988 } 8989 8990 OSKextLog(/* kext */ NULL, 8991 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 8992 "Checking for unused kexts to autounload."); 8993 8994 /***** 8995 * Remove any request callbacks marked as stale, 8996 * and mark as stale any currently in flight. 8997 */ 8998 count = sRequestCallbackRecords->getCount(); 8999 if (count) { 9000 i = count - 1; 9001 do { 9002 OSDictionary * callbackRecord = OSDynamicCast(OSDictionary, 9003 sRequestCallbackRecords->getObject(i)); 9004 if (callbackRecord) { 9005 OSBoolean * stale = OSDynamicCast(OSBoolean, 9006 callbackRecord->getObject(kKextRequestStaleKey)); 9007 9008 if (stale == kOSBooleanTrue) { 9009 OSKext::invokeRequestCallback(callbackRecord, 9010 kOSKextReturnTimeout); 9011 } else { 9012 callbackRecord->setObject(kKextRequestStaleKey, 9013 kOSBooleanTrue); 9014 } 9015 } 9016 } while (i--); 9017 } 9018 9019 /***** 9020 * Make multiple passes through the array of loaded kexts until 9021 * we don't unload any. This handles unwinding of dependency 9022 * chains. We have to go *backwards* through the array because 9023 * kexts are removed from it when unloaded, and we cannot make 9024 * a copy or we'll mess up the retain counts we rely on to 9025 * check whether a kext will unload. If only we could have 9026 * nonretaining collections like CF has.... 9027 */ 9028 do { 9029 didUnload = false; 9030 9031 count = sLoadedKexts->getCount(); 9032 if (count) { 9033 i = count - 1; 9034 do { 9035 OSKext * thisKext = OSDynamicCast(OSKext, 9036 sLoadedKexts->getObject(i)); 9037 didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext)); 9038 } while (i--); 9039 } 9040 } while (didUnload); 9041 9042 finish: 9043 sConsiderUnloadsPending = false; 9044 sConsiderUnloadsExecuted = true; 9045 9046 (void) OSKext::considerRebuildOfPrelinkedKernel(); 9047 9048 IORecursiveLockUnlock(sKextInnerLock); 9049 IORecursiveLockUnlock(sKextLock); 9050 9051 return; 9052 } 9053 9054 /********************************************************************* 9055 * Do not call any function that takes sKextLock here! 9056 *********************************************************************/ 9057 void 9058 OSKext::considerUnloads(Boolean rescheduleOnlyFlag) 9059 { 9060 AbsoluteTime when; 9061 9062 IORecursiveLockLock(sKextInnerLock); 9063 9064 if (!sUnloadCallout) { 9065 sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL); 9066 } 9067 9068 /* we only reset delay value for unloading if we already have something 9069 * pending. rescheduleOnlyFlag should not start the count down. 9070 */ 9071 if (rescheduleOnlyFlag && !sConsiderUnloadsPending) { 9072 goto finish; 9073 } 9074 9075 thread_call_cancel(sUnloadCallout); 9076 if (OSKext::getAutounloadEnabled() && !sSystemSleep 9077 #if !NO_KEXTD 9078 && sIOKitDaemonActive 9079 #endif 9080 ) { 9081 clock_interval_to_deadline(sConsiderUnloadDelay, 9082 1000 * 1000 * 1000, &when); 9083 9084 OSKextLog(/* kext */ NULL, 9085 kOSKextLogProgressLevel | 9086 kOSKextLogLoadFlag, 9087 "%scheduling %sscan for unused kexts in %lu seconds.", 9088 sConsiderUnloadsPending ? "Res" : "S", 9089 sConsiderUnloadsCalled ? "" : "initial ", 9090 (unsigned long)sConsiderUnloadDelay); 9091 9092 sConsiderUnloadsPending = true; 9093 thread_call_enter_delayed(sUnloadCallout, when); 9094 } 9095 9096 finish: 9097 /* The kxld context should be reused throughout boot. We mark the end of 9098 * period as the first time considerUnloads() is called, and we destroy 9099 * the first kxld context in that function. Afterwards, it will be 9100 * destroyed in flushNonloadedKexts. 9101 */ 9102 if (!sConsiderUnloadsCalled) { 9103 sConsiderUnloadsCalled = true; 9104 OSKext::considerDestroyingLinkContext(); 9105 } 9106 9107 IORecursiveLockUnlock(sKextInnerLock); 9108 return; 9109 } 9110 9111 /********************************************************************* 9112 * Do not call any function that takes sKextLock here! 9113 *********************************************************************/ 9114 extern "C" { 9115 IOReturn OSKextSystemSleepOrWake(UInt32 messageType); 9116 IOReturn 9117 OSKextSystemSleepOrWake(UInt32 messageType) 9118 { 9119 IORecursiveLockLock(sKextInnerLock); 9120 9121 /* If the system is going to sleep, cancel the reaper thread timer, 9122 * and note that we're in a sleep state in case it just fired but hasn't 9123 * taken the lock yet. If we are coming back from sleep, just 9124 * clear the sleep flag; IOService's normal operation will cause 9125 * unloads to be considered soon enough. 9126 */ 9127 if (messageType == kIOMessageSystemWillSleep) { 9128 if (sUnloadCallout) { 9129 thread_call_cancel(sUnloadCallout); 9130 } 9131 sSystemSleep = true; 9132 AbsoluteTime_to_scalar(&sLastWakeTime) = 0; 9133 } else if (messageType == kIOMessageSystemHasPoweredOn) { 9134 sSystemSleep = false; 9135 clock_get_uptime(&sLastWakeTime); 9136 } 9137 IORecursiveLockUnlock(sKextInnerLock); 9138 9139 return kIOReturnSuccess; 9140 } 9141 }; 9142 9143 9144 #if PRAGMA_MARK 9145 #pragma mark Prelinked Kernel 9146 #endif 9147 9148 #ifdef CONFIG_KXLD 9149 /********************************************************************* 9150 * Do not access sConsiderUnloads... variables other than 9151 * sConsiderUnloadsExecuted in this function. They are guarded by a 9152 * different lock. 9153 *********************************************************************/ 9154 /* static */ 9155 void 9156 OSKext::considerRebuildOfPrelinkedKernel(void) 9157 { 9158 static bool requestedPrelink = false; 9159 OSReturn checkResult = kOSReturnError; 9160 OSSharedPtr<OSDictionary> prelinkRequest; 9161 OSSharedPtr<OSCollectionIterator> kextIterator; 9162 const OSSymbol * thisID = NULL; // do not release 9163 bool doRebuild = false; 9164 AbsoluteTime my_abstime; 9165 UInt64 my_ns; 9166 SInt32 delta_secs; 9167 9168 /* Only one auto rebuild per boot and only on boot from prelinked kernel */ 9169 if (requestedPrelink || !sPrelinkBoot) { 9170 return; 9171 } 9172 9173 /* no direct return from this point */ 9174 IORecursiveLockLock(sKextLock); 9175 9176 /* We need to wait for the IOKit daemon to get up and running with unloads already done 9177 * and any new startup kexts loaded. 9178 */ 9179 if (!sConsiderUnloadsExecuted || 9180 !sDeferredLoadSucceeded) { 9181 goto finish; 9182 } 9183 9184 /* we really only care about boot / system start up related kexts so bail 9185 * if we're here after REBUILD_MAX_TIME. 9186 */ 9187 if (!_OSKextInPrelinkRebuildWindow()) { 9188 OSKextLog(/* kext */ NULL, 9189 kOSKextLogArchiveFlag, 9190 "%s prebuild rebuild has expired", 9191 __FUNCTION__); 9192 requestedPrelink = true; 9193 goto finish; 9194 } 9195 9196 /* we do not want to trigger a rebuild if we get here too close to waking 9197 * up. (see radar 10233768) 9198 */ 9199 IORecursiveLockLock(sKextInnerLock); 9200 9201 clock_get_uptime(&my_abstime); 9202 delta_secs = MINIMUM_WAKEUP_SECONDS + 1; 9203 if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) { 9204 SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime); 9205 absolutetime_to_nanoseconds(my_abstime, &my_ns); 9206 delta_secs = (SInt32)(my_ns / NSEC_PER_SEC); 9207 } 9208 IORecursiveLockUnlock(sKextInnerLock); 9209 9210 if (delta_secs < MINIMUM_WAKEUP_SECONDS) { 9211 /* too close to time of last wake from sleep */ 9212 goto finish; 9213 } 9214 requestedPrelink = true; 9215 9216 /* Now it's time to see if we have a reason to rebuild. We may have done 9217 * some loads and unloads but the kernel cache didn't actually change. 9218 * We will rebuild if any kext is not marked prelinked AND is not in our 9219 * list of prelinked kexts that got unloaded. (see radar 9055303) 9220 */ 9221 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 9222 if (!kextIterator) { 9223 goto finish; 9224 } 9225 9226 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 9227 OSKext * thisKext; // do not release 9228 9229 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 9230 if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) { 9231 continue; 9232 } 9233 9234 if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) { 9235 continue; 9236 } 9237 /* kext is loaded and was not in current kernel cache so let's rebuild 9238 */ 9239 doRebuild = true; 9240 OSKextLog(/* kext */ NULL, 9241 kOSKextLogArchiveFlag, 9242 "considerRebuildOfPrelinkedKernel %s triggered rebuild", 9243 thisKext->bundleID->getCStringNoCopy()); 9244 break; 9245 } 9246 sUnloadedPrelinkedKexts->flushCollection(); 9247 9248 if (!doRebuild) { 9249 goto finish; 9250 } 9251 9252 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink, 9253 prelinkRequest); 9254 if (checkResult != kOSReturnSuccess) { 9255 goto finish; 9256 } 9257 9258 if (!sKernelRequests->setObject(prelinkRequest.get())) { 9259 goto finish; 9260 } 9261 9262 OSKext::pingIOKitDaemon(); 9263 9264 finish: 9265 IORecursiveLockUnlock(sKextLock); 9266 9267 return; 9268 } 9269 9270 #else /* !CONFIG_KXLD */ 9271 9272 void 9273 OSKext::considerRebuildOfPrelinkedKernel(void) 9274 { 9275 /* in a non-dynamic kext loading world, there is never a reason to rebuild */ 9276 return; 9277 } 9278 9279 #endif /* CONFIG_KXLD */ 9280 9281 #if PRAGMA_MARK 9282 #pragma mark Dependencies 9283 #endif 9284 /********************************************************************* 9285 *********************************************************************/ 9286 bool 9287 OSKext::resolveDependencies( 9288 OSArray * loopStack) 9289 { 9290 bool result = false; 9291 OSSharedPtr<OSArray> localLoopStack; 9292 bool addedToLoopStack = false; 9293 OSDictionary * libraries = NULL; // do not release 9294 OSSharedPtr<OSCollectionIterator> libraryIterator; 9295 OSString * libraryID = NULL; // do not release 9296 OSKext * libraryKext = NULL; // do not release 9297 bool hasRawKernelDependency = false; 9298 bool hasKernelDependency = false; 9299 bool hasKPIDependency = false; 9300 bool hasPrivateKPIDependency = false; 9301 unsigned int count; 9302 9303 #if CONFIG_KXLD 9304 OSString * infoString = NULL; // do not release 9305 OSString * readableString = NULL; // do not release 9306 #endif // CONFIG_KXLD 9307 9308 /* A kernel component will automatically have this flag set, 9309 * and a loaded kext should also have it set (as should all its 9310 * loaded dependencies). 9311 */ 9312 if (flags.hasAllDependencies) { 9313 result = true; 9314 goto finish; 9315 } 9316 9317 /* Check for loops in the dependency graph. 9318 */ 9319 if (loopStack) { 9320 if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) { 9321 OSKextLog(this, 9322 kOSKextLogErrorLevel | 9323 kOSKextLogDependenciesFlag, 9324 "Kext %s has a dependency loop; can't resolve dependencies.", 9325 getIdentifierCString()); 9326 goto finish; 9327 } 9328 } else { 9329 OSKextLog(this, 9330 kOSKextLogStepLevel | 9331 kOSKextLogDependenciesFlag, 9332 "Kext %s resolving dependencies.", 9333 getIdentifierCString()); 9334 9335 localLoopStack = OSArray::withCapacity(6); // any small capacity will do 9336 if (!localLoopStack) { 9337 OSKextLog(this, 9338 kOSKextLogErrorLevel | 9339 kOSKextLogDependenciesFlag, 9340 "Kext %s can't create bookkeeping stack to resolve dependencies.", 9341 getIdentifierCString()); 9342 goto finish; 9343 } 9344 loopStack = localLoopStack.get(); 9345 } 9346 if (!loopStack->setObject(this)) { 9347 OSKextLog(this, 9348 kOSKextLogErrorLevel | 9349 kOSKextLogDependenciesFlag, 9350 "Kext %s - internal error resolving dependencies.", 9351 getIdentifierCString()); 9352 goto finish; 9353 } 9354 addedToLoopStack = true; 9355 9356 /* Purge any existing kexts in the dependency list and start over. 9357 */ 9358 flushDependencies(); 9359 if (dependencies) { 9360 OSKextLog(this, 9361 kOSKextLogErrorLevel | 9362 kOSKextLogDependenciesFlag, 9363 "Kext %s - internal error resolving dependencies.", 9364 getIdentifierCString()); 9365 } 9366 9367 libraries = OSDynamicCast(OSDictionary, 9368 getPropertyForHostArch(kOSBundleLibrariesKey)); 9369 if (libraries == NULL || libraries->getCount() == 0) { 9370 OSKextLog(this, 9371 kOSKextLogErrorLevel | 9372 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 9373 "Kext %s - can't resolve dependencies; %s missing/invalid type.", 9374 getIdentifierCString(), kOSBundleLibrariesKey); 9375 goto finish; 9376 } 9377 9378 /* Make a new array to hold the dependencies (flush freed the old one). 9379 */ 9380 dependencies = OSArray::withCapacity(libraries->getCount()); 9381 if (!dependencies) { 9382 OSKextLog(this, 9383 kOSKextLogErrorLevel | 9384 kOSKextLogDependenciesFlag, 9385 "Kext %s - can't allocate dependencies array.", 9386 getIdentifierCString()); 9387 goto finish; 9388 } 9389 9390 // xxx - compat: We used to add an implicit dependency on kernel 6.0 9391 // xxx - compat: if none were declared. 9392 9393 libraryIterator = OSCollectionIterator::withCollection(libraries); 9394 if (!libraryIterator) { 9395 OSKextLog(this, 9396 kOSKextLogErrorLevel | 9397 kOSKextLogDependenciesFlag, 9398 "Kext %s - can't allocate dependencies iterator.", 9399 getIdentifierCString()); 9400 goto finish; 9401 } 9402 9403 while ((libraryID = OSDynamicCast(OSString, 9404 libraryIterator->getNextObject()))) { 9405 const char * library_id = libraryID->getCStringNoCopy(); 9406 9407 OSString * libraryVersion = OSDynamicCast(OSString, 9408 libraries->getObject(libraryID)); 9409 if (libraryVersion == NULL) { 9410 OSKextLog(this, 9411 kOSKextLogErrorLevel | 9412 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 9413 "Kext %s - illegal type in OSBundleLibraries.", 9414 getIdentifierCString()); 9415 goto finish; 9416 } 9417 9418 OSKextVersion libraryVers = 9419 OSKextParseVersionString(libraryVersion->getCStringNoCopy()); 9420 if (libraryVers == -1) { 9421 OSKextLog(this, 9422 kOSKextLogErrorLevel | 9423 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 9424 "Kext %s - invalid library version %s.", 9425 getIdentifierCString(), 9426 libraryVersion->getCStringNoCopy()); 9427 goto finish; 9428 } 9429 9430 libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID)); 9431 if (libraryKext == NULL) { 9432 OSKextLog(this, 9433 kOSKextLogErrorLevel | 9434 kOSKextLogDependenciesFlag, 9435 "Kext %s - library kext %s not found.", 9436 getIdentifierCString(), library_id); 9437 goto finish; 9438 } 9439 9440 if (!libraryKext->isCompatibleWithVersion(libraryVers)) { 9441 OSKextLog(this, 9442 kOSKextLogErrorLevel | 9443 kOSKextLogDependenciesFlag, 9444 "Kext %s - library kext %s not compatible " 9445 "with requested version %s.", 9446 getIdentifierCString(), library_id, 9447 libraryVersion->getCStringNoCopy()); 9448 goto finish; 9449 } 9450 9451 /* If a nonprelinked library somehow got into the mix for a 9452 * prelinked kext, at any point in the chain, we must fail 9453 * because the prelinked relocs for the library will be all wrong. 9454 */ 9455 if (this->isPrelinked() && 9456 libraryKext->declaresExecutable() && 9457 !libraryKext->isPrelinked()) { 9458 OSKextLog(this, 9459 kOSKextLogErrorLevel | 9460 kOSKextLogDependenciesFlag, 9461 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.", 9462 getIdentifierCString(), library_id, 9463 libraryVersion->getCStringNoCopy()); 9464 goto finish; 9465 } 9466 9467 if (!libraryKext->resolveDependencies(loopStack)) { 9468 goto finish; 9469 } 9470 9471 /* Add the library directly only if it has an executable to link. 9472 * Otherwise it's just used to collect other dependencies, so put 9473 * *its* dependencies on the list for this kext. 9474 */ 9475 // xxx - We are losing info here; would like to make fake entries or 9476 // xxx - keep these in the dependency graph for loaded kexts. 9477 // xxx - I really want to make kernel components not a special case! 9478 if (libraryKext->declaresExecutable() || 9479 libraryKext->isInterface()) { 9480 if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) { 9481 dependencies->setObject(libraryKext); 9482 9483 OSKextLog(this, 9484 kOSKextLogDetailLevel | 9485 kOSKextLogDependenciesFlag, 9486 "Kext %s added dependency %s.", 9487 getIdentifierCString(), 9488 libraryKext->getIdentifierCString()); 9489 } 9490 } else { 9491 int numLibDependencies = libraryKext->getNumDependencies(); 9492 OSArray * libraryDependencies = libraryKext->getDependencies(); 9493 int index; 9494 9495 if (numLibDependencies) { 9496 // xxx - this msg level should be 1 lower than the per-kext one 9497 OSKextLog(this, 9498 kOSKextLogDetailLevel | 9499 kOSKextLogDependenciesFlag, 9500 "Kext %s pulling %d dependencies from codeless library %s.", 9501 getIdentifierCString(), 9502 numLibDependencies, 9503 libraryKext->getIdentifierCString()); 9504 } 9505 for (index = 0; index < numLibDependencies; index++) { 9506 OSKext * thisLibDependency = OSDynamicCast(OSKext, 9507 libraryDependencies->getObject(index)); 9508 if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) { 9509 dependencies->setObject(thisLibDependency); 9510 OSKextLog(this, 9511 kOSKextLogDetailLevel | 9512 kOSKextLogDependenciesFlag, 9513 "Kext %s added dependency %s from codeless library %s.", 9514 getIdentifierCString(), 9515 thisLibDependency->getIdentifierCString(), 9516 libraryKext->getIdentifierCString()); 9517 } 9518 } 9519 } 9520 9521 if ((strlen(library_id) == strlen(KERNEL_LIB)) && 9522 0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) { 9523 hasRawKernelDependency = true; 9524 } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) { 9525 hasKernelDependency = true; 9526 } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) { 9527 hasKPIDependency = true; 9528 if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) { 9529 hasPrivateKPIDependency = true; 9530 } 9531 } 9532 } 9533 9534 if (hasRawKernelDependency) { 9535 OSKextLog(this, 9536 kOSKextLogErrorLevel | 9537 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 9538 "Error - kext %s declares a dependency on %s, which is not permitted.", 9539 getIdentifierCString(), KERNEL_LIB); 9540 goto finish; 9541 } 9542 #if __LP64__ 9543 if (hasKernelDependency) { 9544 OSKextLog(this, 9545 kOSKextLogErrorLevel | 9546 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 9547 "Error - kext %s declares %s dependencies. " 9548 "Only %s* dependencies are supported for 64-bit kexts.", 9549 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 9550 goto finish; 9551 } 9552 if (!hasKPIDependency) { 9553 OSKextLog(this, 9554 kOSKextLogWarningLevel | 9555 kOSKextLogDependenciesFlag, 9556 "Warning - kext %s declares no %s* dependencies. " 9557 "If it uses any KPIs, the link may fail with undefined symbols.", 9558 getIdentifierCString(), KPI_LIB_PREFIX); 9559 } 9560 #else /* __LP64__ */ 9561 // xxx - will change to flatly disallow "kernel" dependencies at some point 9562 // xxx - is it invalid to do both "com.apple.kernel" and any 9563 // xxx - "com.apple.kernel.*"? 9564 9565 if (hasKernelDependency && hasKPIDependency) { 9566 OSKextLog(this, 9567 kOSKextLogWarningLevel | 9568 kOSKextLogDependenciesFlag, 9569 "Warning - kext %s has immediate dependencies on both " 9570 "%s* and %s* components; use only one style.", 9571 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 9572 } 9573 9574 if (!hasKernelDependency && !hasKPIDependency) { 9575 // xxx - do we want to use validation flag for these too? 9576 OSKextLog(this, 9577 kOSKextLogWarningLevel | 9578 kOSKextLogDependenciesFlag, 9579 "Warning - %s declares no kernel dependencies; using %s.", 9580 getIdentifierCString(), KERNEL6_LIB); 9581 OSKext * kernelKext = OSDynamicCast(OSKext, 9582 sKextsByID->getObject(KERNEL6_LIB)); 9583 if (kernelKext) { 9584 dependencies->setObject(kernelKext); 9585 } else { 9586 OSKextLog(this, 9587 kOSKextLogErrorLevel | 9588 kOSKextLogDependenciesFlag, 9589 "Error - Library %s not found for %s.", 9590 KERNEL6_LIB, getIdentifierCString()); 9591 } 9592 } 9593 9594 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of 9595 * its indirect dependencies to simulate old-style linking. XXX - Should 9596 * check for duplicates. 9597 */ 9598 if (!hasKPIDependency) { 9599 unsigned int i; 9600 9601 flags.hasBleedthrough = true; 9602 9603 count = getNumDependencies(); 9604 9605 /* We add to the dependencies array in this loop, but do not iterate 9606 * past its original count. 9607 */ 9608 for (i = 0; i < count; i++) { 9609 OSKext * dependencyKext = OSDynamicCast(OSKext, 9610 dependencies->getObject(i)); 9611 dependencyKext->addBleedthroughDependencies(dependencies.get()); 9612 } 9613 } 9614 #endif /* __LP64__ */ 9615 9616 #if CONFIG_KXLD 9617 /* 9618 * If we're not dynamically linking kexts, then we don't need to check 9619 * copyright strings. The linker in user space has already done this. 9620 */ 9621 if (hasPrivateKPIDependency) { 9622 bool hasApplePrefix = false; 9623 bool infoCopyrightIsValid = false; 9624 bool readableCopyrightIsValid = false; 9625 9626 hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(), 9627 APPLE_KEXT_PREFIX); 9628 9629 infoString = OSDynamicCast(OSString, 9630 getPropertyForHostArch("CFBundleGetInfoString")); 9631 if (infoString) { 9632 infoCopyrightIsValid = 9633 kxld_validate_copyright_string(infoString->getCStringNoCopy()); 9634 } 9635 9636 readableString = OSDynamicCast(OSString, 9637 getPropertyForHostArch("NSHumanReadableCopyright")); 9638 if (readableString) { 9639 readableCopyrightIsValid = 9640 kxld_validate_copyright_string(readableString->getCStringNoCopy()); 9641 } 9642 9643 if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) { 9644 OSKextLog(this, 9645 kOSKextLogErrorLevel | 9646 kOSKextLogDependenciesFlag, 9647 "Error - kext %s declares a dependency on %s. " 9648 "Only Apple kexts may declare a dependency on %s.", 9649 getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI); 9650 goto finish; 9651 } 9652 } 9653 #endif // CONFIG_KXLD 9654 9655 result = true; 9656 flags.hasAllDependencies = 1; 9657 9658 finish: 9659 9660 if (addedToLoopStack) { 9661 count = loopStack->getCount(); 9662 if (count > 0 && (this == loopStack->getObject(count - 1))) { 9663 loopStack->removeObject(count - 1); 9664 } else { 9665 OSKextLog(this, 9666 kOSKextLogErrorLevel | 9667 kOSKextLogDependenciesFlag, 9668 "Kext %s - internal error resolving dependencies.", 9669 getIdentifierCString()); 9670 } 9671 } 9672 9673 if (result && localLoopStack) { 9674 OSKextLog(this, 9675 kOSKextLogStepLevel | 9676 kOSKextLogDependenciesFlag, 9677 "Kext %s successfully resolved dependencies.", 9678 getIdentifierCString()); 9679 } 9680 9681 return result; 9682 } 9683 9684 /********************************************************************* 9685 *********************************************************************/ 9686 bool 9687 OSKext::addBleedthroughDependencies(OSArray * anArray) 9688 { 9689 bool result = false; 9690 unsigned int dependencyIndex, dependencyCount; 9691 9692 dependencyCount = getNumDependencies(); 9693 9694 for (dependencyIndex = 0; 9695 dependencyIndex < dependencyCount; 9696 dependencyIndex++) { 9697 OSKext * dependency = OSDynamicCast(OSKext, 9698 dependencies->getObject(dependencyIndex)); 9699 if (!dependency) { 9700 OSKextLog(this, 9701 kOSKextLogErrorLevel | 9702 kOSKextLogDependenciesFlag, 9703 "Kext %s - internal error propagating compatibility dependencies.", 9704 getIdentifierCString()); 9705 goto finish; 9706 } 9707 if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) { 9708 anArray->setObject(dependency); 9709 } 9710 dependency->addBleedthroughDependencies(anArray); 9711 } 9712 9713 result = true; 9714 9715 finish: 9716 return result; 9717 } 9718 9719 /********************************************************************* 9720 *********************************************************************/ 9721 bool 9722 OSKext::flushDependencies(bool forceFlag) 9723 { 9724 bool result = false; 9725 9726 /* Only clear the dependencies if the kext isn't loaded; 9727 * we need the info for loaded kexts to track references. 9728 */ 9729 if (!isLoaded() || forceFlag) { 9730 if (dependencies) { 9731 // xxx - check level 9732 OSKextLog(this, 9733 kOSKextLogProgressLevel | 9734 kOSKextLogDependenciesFlag, 9735 "Kext %s flushing dependencies.", 9736 getIdentifierCString()); 9737 dependencies.reset(); 9738 } 9739 if (!isKernelComponent()) { 9740 flags.hasAllDependencies = 0; 9741 } 9742 result = true; 9743 } 9744 9745 return result; 9746 } 9747 9748 /********************************************************************* 9749 *********************************************************************/ 9750 uint32_t 9751 OSKext::getNumDependencies(void) 9752 { 9753 if (!dependencies) { 9754 return 0; 9755 } 9756 return dependencies->getCount(); 9757 } 9758 9759 /********************************************************************* 9760 *********************************************************************/ 9761 OSArray * 9762 OSKext::getDependencies(void) 9763 { 9764 return dependencies.get(); 9765 } 9766 9767 bool 9768 OSKext::hasDependency(const OSSymbol * depID) 9769 { 9770 bool result __block; 9771 9772 if (depID == getIdentifier()) { 9773 return true; 9774 } 9775 if (!dependencies) { 9776 return false; 9777 } 9778 result = false; 9779 dependencies->iterateObjects(^bool (OSObject * obj) { 9780 OSKext * kext; 9781 kext = OSDynamicCast(OSKext, obj); 9782 if (!kext) { 9783 return false; 9784 } 9785 result = (depID == kext->getIdentifier()); 9786 return result; 9787 }); 9788 return result; 9789 } 9790 9791 #if PRAGMA_MARK 9792 #pragma mark OSMetaClass Support 9793 #endif 9794 /********************************************************************* 9795 *********************************************************************/ 9796 OSReturn 9797 OSKext::addClass( 9798 OSMetaClass * aClass, 9799 uint32_t numClasses) 9800 { 9801 OSReturn result = kOSMetaClassNoInsKModSet; 9802 9803 if (!metaClasses) { 9804 metaClasses = OSSet::withCapacity(numClasses); 9805 if (!metaClasses) { 9806 goto finish; 9807 } 9808 } 9809 9810 if (metaClasses->containsObject(aClass)) { 9811 OSKextLog(this, 9812 kOSKextLogWarningLevel | 9813 kOSKextLogLoadFlag, 9814 "Notice - kext %s has already registered class %s.", 9815 getIdentifierCString(), 9816 aClass->getClassName()); 9817 result = kOSReturnSuccess; 9818 goto finish; 9819 } 9820 9821 if (!metaClasses->setObject(aClass)) { 9822 goto finish; 9823 } else { 9824 OSKextLog(this, 9825 kOSKextLogDetailLevel | 9826 kOSKextLogLoadFlag, 9827 "Kext %s registered class %s.", 9828 getIdentifierCString(), 9829 aClass->getClassName()); 9830 } 9831 9832 if (!flags.autounloadEnabled) { 9833 const OSMetaClass * metaScan = NULL; // do not release 9834 9835 for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) { 9836 if (metaScan == OSTypeID(IOService)) { 9837 OSKextLog(this, 9838 kOSKextLogProgressLevel | 9839 kOSKextLogLoadFlag, 9840 "Kext %s has IOService subclass %s; enabling autounload.", 9841 getIdentifierCString(), 9842 aClass->getClassName()); 9843 9844 flags.autounloadEnabled = (0 == flags.unloadUnsupported); 9845 break; 9846 } 9847 } 9848 } 9849 9850 notifyAddClassObservers(this, aClass, flags); 9851 9852 result = kOSReturnSuccess; 9853 9854 finish: 9855 if (result != kOSReturnSuccess) { 9856 OSKextLog(this, 9857 kOSKextLogErrorLevel | 9858 kOSKextLogLoadFlag, 9859 "Kext %s failed to register class %s.", 9860 getIdentifierCString(), 9861 aClass->getClassName()); 9862 } 9863 9864 return result; 9865 } 9866 9867 /********************************************************************* 9868 *********************************************************************/ 9869 OSReturn 9870 OSKext::removeClass( 9871 OSMetaClass * aClass) 9872 { 9873 OSReturn result = kOSMetaClassNoKModSet; 9874 9875 if (!metaClasses) { 9876 goto finish; 9877 } 9878 9879 if (!metaClasses->containsObject(aClass)) { 9880 OSKextLog(this, 9881 kOSKextLogWarningLevel | 9882 kOSKextLogLoadFlag, 9883 "Notice - kext %s asked to unregister unknown class %s.", 9884 getIdentifierCString(), 9885 aClass->getClassName()); 9886 result = kOSReturnSuccess; 9887 goto finish; 9888 } 9889 9890 OSKextLog(this, 9891 kOSKextLogDetailLevel | 9892 kOSKextLogLoadFlag, 9893 "Kext %s unregistering class %s.", 9894 getIdentifierCString(), 9895 aClass->getClassName()); 9896 9897 metaClasses->removeObject(aClass); 9898 9899 notifyRemoveClassObservers(this, aClass, flags); 9900 9901 result = kOSReturnSuccess; 9902 9903 finish: 9904 if (result != kOSReturnSuccess) { 9905 OSKextLog(this, 9906 kOSKextLogErrorLevel | 9907 kOSKextLogLoadFlag, 9908 "Failed to unregister kext %s class %s.", 9909 getIdentifierCString(), 9910 aClass->getClassName()); 9911 } 9912 return result; 9913 } 9914 9915 /********************************************************************* 9916 *********************************************************************/ 9917 OSSet * 9918 OSKext::getMetaClasses(void) 9919 { 9920 return metaClasses.get(); 9921 } 9922 9923 /********************************************************************* 9924 *********************************************************************/ 9925 bool 9926 OSKext::hasOSMetaClassInstances(void) 9927 { 9928 bool result = false; 9929 OSSharedPtr<OSCollectionIterator> classIterator; 9930 OSMetaClass * checkClass = NULL; // do not release 9931 9932 if (!metaClasses) { 9933 goto finish; 9934 } 9935 9936 classIterator = OSCollectionIterator::withCollection(metaClasses.get()); 9937 if (!classIterator) { 9938 // xxx - log alloc failure? 9939 goto finish; 9940 } 9941 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 9942 if (checkClass->getInstanceCount()) { 9943 result = true; 9944 goto finish; 9945 } 9946 } 9947 9948 finish: 9949 return result; 9950 } 9951 9952 /********************************************************************* 9953 *********************************************************************/ 9954 /* static */ 9955 void 9956 OSKext::reportOSMetaClassInstances( 9957 const char * kextIdentifier, 9958 OSKextLogSpec msgLogSpec) 9959 { 9960 OSSharedPtr<OSKext> theKext; 9961 9962 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 9963 if (!theKext) { 9964 goto finish; 9965 } 9966 9967 theKext->reportOSMetaClassInstances(msgLogSpec); 9968 finish: 9969 return; 9970 } 9971 9972 /********************************************************************* 9973 *********************************************************************/ 9974 void 9975 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec) 9976 { 9977 OSSharedPtr<OSCollectionIterator> classIterator; 9978 OSMetaClass * checkClass = NULL; // do not release 9979 9980 if (!metaClasses) { 9981 goto finish; 9982 } 9983 9984 classIterator = OSCollectionIterator::withCollection(metaClasses.get()); 9985 if (!classIterator) { 9986 goto finish; 9987 } 9988 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 9989 if (checkClass->getInstanceCount()) { 9990 OSKextLog(this, 9991 msgLogSpec, 9992 " Kext %s class %s has %d instance%s.", 9993 getIdentifierCString(), 9994 checkClass->getClassName(), 9995 checkClass->getInstanceCount(), 9996 checkClass->getInstanceCount() == 1 ? "" : "s"); 9997 } 9998 } 9999 10000 finish: 10001 return; 10002 } 10003 10004 #if PRAGMA_MARK 10005 #pragma mark User-Space Requests 10006 #endif 10007 10008 static kern_return_t 10009 patchDextLaunchRequests(task_t calling_task, OSArray *requests) 10010 { 10011 OSReturn result = kOSReturnSuccess; 10012 for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) { 10013 OSDictionary * request = NULL; //do not release 10014 IOUserServerCheckInToken * token = NULL; //do not release 10015 OSString * requestPredicate = NULL; //do not release 10016 OSSharedPtr<OSNumber> portNameNumber; 10017 mach_port_name_t portName = 0; 10018 request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex)); 10019 if (!request) { 10020 OSKextLog(/* kext */ NULL, 10021 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10022 "Elements of request should be of type OSDictionary"); 10023 result = kOSKextReturnInternalError; 10024 goto finish; 10025 } 10026 requestPredicate = _OSKextGetRequestPredicate(request); 10027 if (!requestPredicate) { 10028 OSKextLog(/* kext */ NULL, 10029 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10030 "Failed to get request predicate"); 10031 result = kOSKextReturnInternalError; 10032 goto finish; 10033 } 10034 // is this a dext launch? 10035 if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) { 10036 token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken)); 10037 if (!token) { 10038 OSKextLog(/* kext */ NULL, 10039 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10040 "Could not find a IOUserServerCheckInToken in daemon launch request."); 10041 result = kOSKextReturnInternalError; 10042 goto finish; 10043 } 10044 portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT); 10045 if (portName == 0 || portName == MACH_PORT_DEAD) { 10046 OSKextLog(/* kext */ NULL, 10047 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10048 "Could not create send right for object."); 10049 result = kOSKextReturnInternalError; 10050 goto finish; 10051 } 10052 // Store the mach port name as a OSNumber 10053 portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName)); 10054 if (!portNameNumber) { 10055 OSKextLog(/* kext */ NULL, 10056 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10057 "Could not create OSNumber object."); 10058 result = kOSKextReturnNoMemory; 10059 goto finish; 10060 } 10061 if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) { 10062 OSKextLog(/* kext */ NULL, 10063 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10064 "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken); 10065 result = kOSKextReturnNoMemory; 10066 goto finish; 10067 } 10068 } 10069 finish: 10070 if (result != kOSReturnSuccess) { 10071 break; 10072 } 10073 } 10074 return result; 10075 } 10076 10077 bool 10078 OSKext::iokitDaemonActive() 10079 { 10080 bool result; 10081 IORecursiveLockLock(sKextLock); 10082 result = sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot; 10083 IORecursiveLockUnlock(sKextLock); 10084 return result; 10085 } 10086 10087 /********************************************************************* 10088 * XXX - this function is a big ugly mess 10089 *********************************************************************/ 10090 /* static */ 10091 OSReturn 10092 OSKext::handleRequest( 10093 host_priv_t hostPriv, 10094 OSKextLogSpec clientLogFilter, 10095 char * requestBuffer, 10096 uint32_t requestLength, 10097 char ** responseOut, 10098 uint32_t * responseLengthOut, 10099 char ** logInfoOut, 10100 uint32_t * logInfoLengthOut) 10101 { 10102 OSReturn result = kOSReturnError; 10103 kern_return_t kmem_result = KERN_FAILURE; 10104 10105 char * response = NULL; // returned by reference 10106 uint32_t responseLength = 0; 10107 10108 bool taskCanManageAllKCs = false; 10109 bool taskOnlyManagesBootKC = false; 10110 10111 OSSharedPtr<OSObject> parsedXML; 10112 OSDictionary * requestDict = NULL; // do not release 10113 OSSharedPtr<OSString> errorString; 10114 10115 OSSharedPtr<OSObject> responseObject; 10116 10117 OSSharedPtr<OSSerialize> serializer; 10118 10119 OSSharedPtr<OSArray> logInfoArray; 10120 10121 OSString * predicate = NULL; // do not release 10122 OSString * kextIdentifier = NULL; // do not release 10123 OSArray * kextIdentifiers = NULL; // do not release 10124 OSKext * theKext = NULL; // do not release 10125 OSBoolean * boolArg = NULL; // do not release 10126 10127 10128 IORecursiveLockLock(sKextLock); 10129 10130 if (responseOut) { 10131 *responseOut = NULL; 10132 *responseLengthOut = 0; 10133 } 10134 if (logInfoOut) { 10135 *logInfoOut = NULL; 10136 *logInfoLengthOut = 0; 10137 } 10138 10139 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 10140 10141 /* XML must be nul-terminated. 10142 */ 10143 if (requestBuffer[requestLength - 1] != '\0') { 10144 OSKextLog(/* kext */ NULL, 10145 kOSKextLogErrorLevel | 10146 kOSKextLogIPCFlag, 10147 "Invalid request from user space (not nul-terminated)."); 10148 result = kOSKextReturnBadData; 10149 goto finish; 10150 } 10151 parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString); 10152 if (parsedXML) { 10153 requestDict = OSDynamicCast(OSDictionary, parsedXML.get()); 10154 } 10155 if (!requestDict) { 10156 const char * errorCString = "(unknown error)"; 10157 10158 if (errorString && errorString->getCStringNoCopy()) { 10159 errorCString = errorString->getCStringNoCopy(); 10160 } else if (parsedXML) { 10161 errorCString = "not a dictionary"; 10162 } 10163 OSKextLog(/* kext */ NULL, 10164 kOSKextLogErrorLevel | 10165 kOSKextLogIPCFlag, 10166 "Error unserializing request from user space: %s.", 10167 errorCString); 10168 result = kOSKextReturnSerialization; 10169 goto finish; 10170 } 10171 10172 predicate = _OSKextGetRequestPredicate(requestDict); 10173 if (!predicate) { 10174 OSKextLog(/* kext */ NULL, 10175 kOSKextLogErrorLevel | 10176 kOSKextLogIPCFlag, 10177 "Recieved kext request from user space with no predicate."); 10178 result = kOSKextReturnInvalidArgument; 10179 goto finish; 10180 } 10181 OSKextLog(/* kext */ NULL, 10182 kOSKextLogDebugLevel | 10183 kOSKextLogIPCFlag, 10184 "Received '%s' request from user space.", 10185 predicate->getCStringNoCopy()); 10186 10187 /* 10188 * All management of file sets requires an entitlement 10189 */ 10190 result = kOSKextReturnNotPrivileged; 10191 if (predicate->isEqualTo(kKextRequestPredicateUnload) || 10192 predicate->isEqualTo(kKextRequestPredicateStart) || 10193 predicate->isEqualTo(kKextRequestPredicateStop) || 10194 predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) || 10195 predicate->isEqualTo(kKextRequestPredicateSendResource) || 10196 predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) || 10197 predicate->isEqualTo(kKextRequestPredicateLoadCodeless) || 10198 predicate->isEqualTo(kKextRequestPredicateLoadFromKC) || 10199 predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) || 10200 predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) || 10201 predicate->isEqualTo(kKextRequestPredicateDaemonReady)) { 10202 if (!iokitDaemonAvailable()) { 10203 panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable"); 10204 } 10205 if (hostPriv == HOST_PRIV_NULL) { 10206 OSKextLog(/* kext */ NULL, 10207 kOSKextLogErrorLevel | 10208 kOSKextLogIPCFlag, 10209 "Access Failure - must be root user."); 10210 goto finish; 10211 } 10212 taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE; 10213 taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE; 10214 10215 if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) { 10216 OSKextLog(/* kext */ NULL, 10217 kOSKextLogErrorLevel | 10218 kOSKextLogIPCFlag, 10219 "Access Failure - client not entitled to manage file sets."); 10220 goto finish; 10221 } 10222 10223 /* 10224 * The OnlyBootKC entitlement restricts the 10225 * collection-management entitlement to only managing kexts in 10226 * the BootKC. All other predicates that alter global state or 10227 * add new KCs are disallowed. 10228 */ 10229 if (taskOnlyManagesBootKC && 10230 (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) || 10231 predicate->isEqualTo(kKextRequestPredicateSendResource) || 10232 predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) || 10233 predicate->isEqualTo(kKextRequestPredicateLoadCodeless) || 10234 predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) || 10235 predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) || 10236 predicate->isEqualTo(kKextRequestPredicateDaemonReady))) { 10237 OSKextLog(/* kext */ NULL, 10238 kOSKextLogErrorLevel | 10239 kOSKextLogIPCFlag, 10240 "Access Failure - client not entitled to manage non-primary KCs"); 10241 goto finish; 10242 } 10243 10244 /* 10245 * If we get here, then the process either has the full KC 10246 * management entitlement, or it has the BootKC-only 10247 * entitlement and the request is about the BootKC. 10248 */ 10249 } 10250 10251 /* Get common args in anticipation of use. 10252 */ 10253 kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument( 10254 requestDict, kKextRequestArgumentBundleIdentifierKey)); 10255 kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 10256 requestDict, kKextRequestArgumentBundleIdentifierKey)); 10257 if (kextIdentifier) { 10258 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 10259 } 10260 boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 10261 requestDict, kKextRequestArgumentValueKey)); 10262 10263 if (taskOnlyManagesBootKC && 10264 theKext && 10265 theKext->isInFileset() && 10266 theKext->kc_type != KCKindPrimary) { 10267 OSKextLog(/* kext */ NULL, 10268 kOSKextLogErrorLevel | 10269 kOSKextLogIPCFlag, 10270 "Access Failure - client not entitled to manage kext in non-primary KC"); 10271 result = kOSKextReturnNotPrivileged; 10272 goto finish; 10273 } 10274 result = kOSKextReturnInvalidArgument; 10275 10276 if (predicate->isEqualTo(kKextRequestPredicateStart)) { 10277 if (!kextIdentifier) { 10278 OSKextLog(/* kext */ NULL, 10279 kOSKextLogErrorLevel | 10280 kOSKextLogIPCFlag, 10281 "Invalid arguments to kext start request."); 10282 } else if (!theKext) { 10283 OSKextLog(/* kext */ NULL, 10284 kOSKextLogErrorLevel | 10285 kOSKextLogIPCFlag, 10286 "Kext %s not found for start request.", 10287 kextIdentifier->getCStringNoCopy()); 10288 result = kOSKextReturnNotFound; 10289 } else { 10290 result = theKext->start(); 10291 } 10292 } else if (predicate->isEqualTo(kKextRequestPredicateStop)) { 10293 if (!kextIdentifier) { 10294 OSKextLog(/* kext */ NULL, 10295 kOSKextLogErrorLevel | 10296 kOSKextLogIPCFlag, 10297 "Invalid arguments to kext stop request."); 10298 } else if (!theKext) { 10299 OSKextLog(/* kext */ NULL, 10300 kOSKextLogErrorLevel | 10301 kOSKextLogIPCFlag, 10302 "Kext %s not found for stop request.", 10303 kextIdentifier->getCStringNoCopy()); 10304 result = kOSKextReturnNotFound; 10305 } else { 10306 result = theKext->stop(); 10307 } 10308 } else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) { 10309 result = OSKext::setMissingAuxKCBundles(requestDict); 10310 } else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) { 10311 if (!kextIdentifier) { 10312 OSKextLog(/* kext */ NULL, 10313 kOSKextLogErrorLevel | 10314 kOSKextLogIPCFlag, 10315 "Invalid arguments to AuxKC Bundle Available request."); 10316 } else { 10317 result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict); 10318 } 10319 } else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) { 10320 if (!kextIdentifier) { 10321 OSKextLog(/* kext */ NULL, 10322 kOSKextLogErrorLevel | 10323 kOSKextLogIPCFlag, 10324 "Invalid arguments to kext load from KC request."); 10325 } else if (!theKext) { 10326 OSKextLog(/* kext */ NULL, 10327 kOSKextLogErrorLevel | 10328 kOSKextLogIPCFlag, 10329 "Kext %s not found for load from KC request.", 10330 kextIdentifier->getCStringNoCopy()); 10331 result = kOSKextReturnNotFound; 10332 } else if (!theKext->isInFileset()) { 10333 OSKextLog(/* kext */ NULL, 10334 kOSKextLogErrorLevel | 10335 kOSKextLogIPCFlag, 10336 "Kext %s does not exist in a KC: refusing to load.", 10337 kextIdentifier->getCStringNoCopy()); 10338 result = kOSKextReturnNotLoadable; 10339 } else { 10340 result = OSKext::loadKextFromKC(theKext, requestDict); 10341 } 10342 } else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) { 10343 if (!kextIdentifier) { 10344 OSKextLog(/* kext */ NULL, 10345 kOSKextLogErrorLevel | 10346 kOSKextLogIPCFlag, 10347 "Invalid arguments to codeless kext load interface (missing identifier)."); 10348 } else { 10349 result = OSKext::loadCodelessKext(kextIdentifier, requestDict); 10350 } 10351 } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) { 10352 if (!kextIdentifier) { 10353 OSKextLog(/* kext */ NULL, 10354 kOSKextLogErrorLevel | 10355 kOSKextLogIPCFlag, 10356 "Invalid arguments to kext unload request."); 10357 } else if (!theKext) { 10358 OSKextLog(/* kext */ NULL, 10359 kOSKextLogErrorLevel | 10360 kOSKextLogIPCFlag, 10361 "Kext %s not found for unload request.", 10362 kextIdentifier->getCStringNoCopy()); 10363 result = kOSKextReturnNotFound; 10364 } else { 10365 if (theKext->isDriverKit()) { 10366 result = OSKext::removeDext(theKext); 10367 } else { 10368 OSBoolean * terminateFlag = OSDynamicCast(OSBoolean, 10369 _OSKextGetRequestArgument(requestDict, 10370 kKextRequestArgumentTerminateIOServicesKey)); 10371 result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue); 10372 } 10373 } 10374 } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) { 10375 result = OSKext::dispatchResource(requestDict); 10376 } else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) { 10377 OSNumber *lookupNum = NULL; 10378 lookupNum = OSDynamicCast(OSNumber, 10379 _OSKextGetRequestArgument(requestDict, 10380 kKextRequestArgumentLookupAddressKey)); 10381 10382 responseObject = OSKext::copyKextUUIDForAddress(lookupNum); 10383 if (responseObject) { 10384 result = kOSReturnSuccess; 10385 } else { 10386 goto finish; 10387 } 10388 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) || 10389 predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) || 10390 predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection) || 10391 predicate->isEqualTo(kKextRequestPredicateGetDexts)) { 10392 OSBoolean * delayAutounloadBool = NULL; 10393 OSObject * infoKeysRaw = NULL; 10394 OSArray * infoKeys = NULL; 10395 uint32_t infoKeysCount = 0; 10396 10397 delayAutounloadBool = OSDynamicCast(OSBoolean, 10398 _OSKextGetRequestArgument(requestDict, 10399 kKextRequestArgumentDelayAutounloadKey)); 10400 10401 /* If asked to delay autounload, reset the timer if it's currently set. 10402 * (That is, don't schedule an unload if one isn't already pending. 10403 */ 10404 if (delayAutounloadBool == kOSBooleanTrue) { 10405 OSKext::considerUnloads(/* rescheduleOnly? */ true); 10406 } 10407 10408 infoKeysRaw = _OSKextGetRequestArgument(requestDict, 10409 kKextRequestArgumentInfoKeysKey); 10410 infoKeys = OSDynamicCast(OSArray, infoKeysRaw); 10411 if (infoKeysRaw && !infoKeys) { 10412 OSKextLog(/* kext */ NULL, 10413 kOSKextLogErrorLevel | 10414 kOSKextLogIPCFlag, 10415 "Invalid arguments to kext info request."); 10416 goto finish; 10417 } 10418 10419 if (infoKeys) { 10420 infoKeysCount = infoKeys->getCount(); 10421 for (uint32_t i = 0; i < infoKeysCount; i++) { 10422 if (!OSDynamicCast(OSString, infoKeys->getObject(i))) { 10423 OSKextLog(/* kext */ NULL, 10424 kOSKextLogErrorLevel | 10425 kOSKextLogIPCFlag, 10426 "Invalid arguments to kext info request."); 10427 goto finish; 10428 } 10429 } 10430 } 10431 10432 if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) { 10433 responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys); 10434 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) { 10435 responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys); 10436 } else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) { 10437 responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys); 10438 } else if (predicate->isEqualTo(kKextRequestPredicateGetDexts)) { 10439 responseObject = OSKext::copyDextsInfo(kextIdentifiers, infoKeys); 10440 } 10441 10442 if (!responseObject) { 10443 result = kOSKextReturnInternalError; 10444 } else { 10445 OSKextLog(/* kext */ NULL, 10446 kOSKextLogDebugLevel | 10447 kOSKextLogIPCFlag, 10448 "Returning loaded kext info."); 10449 result = kOSReturnSuccess; 10450 } 10451 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 10452 /* Hand the current sKernelRequests array to the caller 10453 * (who must release it), and make a new one. 10454 */ 10455 responseObject = os::move(sKernelRequests); 10456 sKernelRequests = OSArray::withCapacity(0); 10457 sPostedKextLoadIdentifiers->flushCollection(); 10458 OSKextLog(/* kext */ NULL, 10459 kOSKextLogDebugLevel | 10460 kOSKextLogIPCFlag, 10461 "Returning kernel requests."); 10462 result = kOSReturnSuccess; 10463 } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) { 10464 /* Return the set of all requested bundle identifiers */ 10465 responseObject = sAllKextLoadIdentifiers; 10466 OSKextLog(/* kext */ NULL, 10467 kOSKextLogDebugLevel | 10468 kOSKextLogIPCFlag, 10469 "Returning load requests."); 10470 result = kOSReturnSuccess; 10471 } else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) { 10472 printf("KextLog: Loading FileSet KC(s)\n"); 10473 result = OSKext::loadFileSetKexts(requestDict); 10474 } else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) { 10475 bool active = iokitDaemonActive(); 10476 printf("KextLog: " kIOKitDaemonName " is %s\n", active ? "active" : "not active"); 10477 if (sOSKextWasResetAfterUserspaceReboot) { 10478 printf("KextLog: was reset after userspace reboot\n"); 10479 } 10480 result = active ? kOSReturnSuccess : kIOReturnNotReady; 10481 } else { 10482 OSKextLog(/* kext */ NULL, 10483 kOSKextLogDebugLevel | 10484 kOSKextLogIPCFlag, 10485 "Received '%s' invalid request from user space.", 10486 predicate->getCStringNoCopy()); 10487 goto finish; 10488 } 10489 10490 /********** 10491 * Now we have handle the request, or not. Gather up the response & logging 10492 * info to ship to user space. 10493 *********/ 10494 10495 /* Note: Nothing in OSKext is supposed to retain requestDict, 10496 * but you never know.... 10497 */ 10498 if (requestDict->getRetainCount() > 1) { 10499 OSKextLog(/* kext */ NULL, 10500 kOSKextLogWarningLevel | 10501 kOSKextLogIPCFlag, 10502 "Request from user space still retained by a kext; " 10503 "probable memory leak."); 10504 } 10505 10506 if (responseOut && responseObject) { 10507 serializer = OSSerialize::withCapacity(0); 10508 if (!serializer) { 10509 result = kOSKextReturnNoMemory; 10510 goto finish; 10511 } 10512 /* 10513 * Before serializing the kernel requests, patch the dext launch requests so 10514 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the 10515 * IOUserServerCheckInToken kernel object. 10516 */ 10517 if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 10518 OSArray * requests = OSDynamicCast(OSArray, responseObject.get()); 10519 task_t calling_task = current_task(); 10520 if (!requests) { 10521 OSKextLog(/* kext */ NULL, 10522 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10523 "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests); 10524 result = kOSKextReturnInternalError; 10525 goto finish; 10526 } 10527 result = patchDextLaunchRequests(calling_task, requests); 10528 if (result != kOSReturnSuccess) { 10529 OSKextLog(/* kext */ NULL, 10530 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10531 "Failed to patch dext launch requests."); 10532 goto finish; 10533 } 10534 } 10535 10536 if (!responseObject->serialize(serializer.get())) { 10537 OSKextLog(/* kext */ NULL, 10538 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 10539 "Failed to serialize response to request from user space."); 10540 result = kOSKextReturnSerialization; 10541 goto finish; 10542 } 10543 10544 response = (char *)serializer->text(); 10545 responseLength = serializer->getLength(); 10546 } 10547 10548 if (responseOut && response) { 10549 char * buffer; 10550 10551 /* This kmem_alloc sets the return value of the function. 10552 */ 10553 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, 10554 round_page(responseLength), KMA_DATA, VM_KERN_MEMORY_OSKEXT); 10555 if (kmem_result != KERN_SUCCESS) { 10556 OSKextLog(/* kext */ NULL, 10557 kOSKextLogErrorLevel | 10558 kOSKextLogIPCFlag, 10559 "Failed to copy response to request from user space."); 10560 result = kmem_result; 10561 goto finish; 10562 } else { 10563 /* 11981737 - clear uninitialized data in last page */ 10564 bzero((void *)(buffer + responseLength), 10565 (round_page(responseLength) - responseLength)); 10566 memcpy(buffer, response, responseLength); 10567 *responseOut = buffer; 10568 *responseLengthOut = responseLength; 10569 } 10570 } 10571 10572 finish: 10573 10574 /* Gather up the collected log messages for user space. Any messages 10575 * messages past this call will not make it up as log messages but 10576 * will be in the system log. Note that we ignore the return of the 10577 * serialize; it has no bearing on the operation at hand even if we 10578 * fail to get the log messages. 10579 */ 10580 logInfoArray = OSKext::clearUserSpaceLogFilter(); 10581 10582 if (logInfoArray && logInfoOut && logInfoLengthOut) { 10583 (void)OSKext::serializeLogInfo(logInfoArray.get(), 10584 logInfoOut, logInfoLengthOut); 10585 } 10586 10587 IORecursiveLockUnlock(sKextLock); 10588 10589 return result; 10590 } 10591 10592 #if PRAGMA_MARK 10593 #pragma mark Linked Kext Collection Support 10594 #endif 10595 10596 static int 10597 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount) 10598 { 10599 for (int i = 0; i < segCount; i++) { 10600 vm_offset_t segStart = segAddrs[i]; 10601 vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i]; 10602 10603 if (theAddr >= segStart && theAddr < segEnd) { 10604 return i; 10605 } 10606 } 10607 return -1; 10608 } 10609 10610 static void 10611 __slideOldKaslrOffsets(kernel_mach_header_t *mh, 10612 kernel_segment_command_t *kextTextSeg, 10613 OSData *kaslrOffsets) 10614 { 10615 static const char *plk_segNames[] = { 10616 "__TEXT", 10617 "__TEXT_EXEC", 10618 "__DATA", 10619 "__DATA_CONST", 10620 "__LINKEDIT", 10621 "__PRELINK_TEXT", 10622 "__PLK_TEXT_EXEC", 10623 "__PRELINK_DATA", 10624 "__PLK_DATA_CONST", 10625 "__PLK_LLVM_COV", 10626 "__PLK_LINKEDIT", 10627 "__PRELINK_INFO" 10628 }; 10629 static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0])); 10630 10631 unsigned long plk_segSizes[num_plk_seg]; 10632 vm_offset_t plk_segAddrs[num_plk_seg]; 10633 10634 for (size_t i = 0; i < num_plk_seg; i++) { 10635 plk_segSizes[i] = 0; 10636 plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]); 10637 } 10638 10639 uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr; 10640 10641 int slidKextAddrCount = 0; 10642 int badSlideAddr = 0; 10643 int badSlideTarget = 0; 10644 10645 struct kaslrPackedOffsets { 10646 uint32_t count; /* number of offsets */ 10647 uint32_t offsetsArray[]; /* offsets to slide */ 10648 }; 10649 const struct kaslrPackedOffsets *myOffsets = NULL; 10650 myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy(); 10651 10652 for (uint32_t j = 0; j < myOffsets->count; j++) { 10653 uint64_t slideOffset = (uint64_t)myOffsets->offsetsArray[j]; 10654 vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset); 10655 int slideAddrSegIndex = -1; 10656 int addrToSlideSegIndex = -1; 10657 10658 slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg); 10659 if (slideAddrSegIndex >= 0) { 10660 addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg); 10661 if (addrToSlideSegIndex < 0) { 10662 badSlideTarget++; 10663 continue; 10664 } 10665 } else { 10666 badSlideAddr++; 10667 continue; 10668 } 10669 10670 slidKextAddrCount++; 10671 *slideAddr = ml_static_slide(*slideAddr); 10672 } // for ... 10673 } 10674 10675 10676 10677 /******************************************************************** 10678 * addKextsFromKextCollection 10679 * 10680 * Input: MachO header of kext collection. The MachO is assumed to 10681 * have a section named 'info_seg_name,info_sect_name' that 10682 * contains a serialized XML info dictionary. This dictionary 10683 * contains a UUID, possibly a set of relocations (for older 10684 * kxld-built binaries), and an array of kext personalities. 10685 * 10686 ********************************************************************/ 10687 bool 10688 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh, 10689 OSDictionary *infoDict, const char *text_seg_name, 10690 OSData **kcUUID, kc_kind_t type) 10691 { 10692 bool result = false; 10693 10694 OSArray *kextArray = NULL; // do not release 10695 OSData *infoDictKCUUID = NULL; // do not release 10696 OSData *kaslrOffsets = NULL; // do not release 10697 10698 IORegistryEntry *registryRoot = NULL; // do not release 10699 OSSharedPtr<OSNumber> kcKextCount; 10700 10701 /* extract the KC UUID from the dictionary */ 10702 infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 10703 if (infoDictKCUUID) { 10704 if (infoDictKCUUID->getLength() != sizeof(uuid_t)) { 10705 panic("kcUUID length is %d, expected %lu", 10706 infoDictKCUUID->getLength(), sizeof(uuid_t)); 10707 } 10708 } 10709 10710 /* locate the array of kext dictionaries */ 10711 kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey)); 10712 if (!kextArray) { 10713 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 10714 "The given KC has no kext info dictionaries"); 10715 goto finish; 10716 } 10717 10718 /* 10719 * old-style KASLR offsets may be present in the info dictionary. If 10720 * we find them, use them and eventually slide them. 10721 */ 10722 kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey)); 10723 10724 /* 10725 * Before processing any kexts, locate the special kext bundle which 10726 * contains a list of kexts that we are to prevent from loading. 10727 */ 10728 createExcludeListFromPrelinkInfo(kextArray); 10729 10730 /* 10731 * Create OSKext objects for each kext we find in the array of kext 10732 * info plist dictionaries. 10733 */ 10734 for (int i = 0; i < (int)kextArray->getCount(); ++i) { 10735 OSDictionary *kextDict = NULL; 10736 kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i)); 10737 if (!kextDict) { 10738 OSKextLog(/* kext */ NULL, 10739 kOSKextLogErrorLevel | 10740 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 10741 "Kext info dictionary for kext #%d isn't a dictionary?", i); 10742 continue; 10743 } 10744 10745 /* 10746 * Create the kext for the entry, then release it, because the 10747 * kext system keeps a reference around until the kext is 10748 * explicitly removed. Any creation/registration failures are 10749 * already logged for us. 10750 */ 10751 withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type); 10752 } 10753 10754 /* 10755 * slide old-style kxld relocations 10756 * NOTE: this is still used on embedded KCs built with kcgen 10757 * TODO: Remove this once we use the new kext linker everywhere! 10758 */ 10759 if (kaslrOffsets && vm_kernel_slide > 0) { 10760 kernel_segment_command_t *text_segment = NULL; 10761 text_segment = getsegbynamefromheader(mh, text_seg_name); 10762 if (!text_segment) { 10763 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 10764 "Can't find a TEXT segment named '%s' in macho header", text_seg_name); 10765 goto finish; 10766 } 10767 10768 __slideOldKaslrOffsets(mh, text_segment, kaslrOffsets); 10769 /* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */ 10770 setAllVMAttributes(); 10771 } 10772 10773 /* Store the number of prelinked kexts in the registry so we can tell 10774 * when the system has been started from a prelinked kernel. 10775 */ 10776 registryRoot = IORegistryEntry::getRegistryRoot(); 10777 assert(registryRoot); 10778 10779 kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t)); 10780 assert(kcKextCount); 10781 if (kcKextCount) { 10782 OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey); 10783 OSNumber *num; 10784 num = OSDynamicCast(OSNumber, prop.get()); 10785 if (num) { 10786 kcKextCount->addValue(num->unsigned64BitValue()); 10787 } 10788 registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get()); 10789 } 10790 10791 OSKextLog(/* kext */ NULL, 10792 kOSKextLogProgressLevel | 10793 kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag | 10794 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 10795 "%u prelinked kexts", infoDict->getCount()); 10796 10797 10798 if (kcUUID && infoDictKCUUID) { 10799 *kcUUID = OSData::withData(infoDictKCUUID).detach(); 10800 } 10801 10802 result = true; 10803 10804 finish: 10805 return result; 10806 } 10807 10808 bool 10809 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh, 10810 OSDictionary *infoDict, const char *text_seg_name, 10811 OSSharedPtr<OSData> &kcUUID, kc_kind_t type) 10812 { 10813 OSData *result = NULL; 10814 bool success = addKextsFromKextCollection(mh, 10815 infoDict, 10816 text_seg_name, 10817 &result, 10818 type); 10819 if (success) { 10820 kcUUID.reset(result, OSNoRetain); 10821 } 10822 return success; 10823 } 10824 10825 static OSSharedPtr<OSObject> deferredAuxKCXML; 10826 bool 10827 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh, 10828 OSSharedPtr<OSObject> &parsedXML, kc_kind_t type) 10829 { 10830 if (type != KCKindAuxiliary) { 10831 return false; 10832 } 10833 10834 kernel_mach_header_t *_mh; 10835 _mh = (kernel_mach_header_t*)PE_get_kc_header(type); 10836 if (!_mh || _mh != mh) { 10837 return false; 10838 } 10839 10840 if (deferredAuxKCXML) { 10841 /* only allow this to be called once */ 10842 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 10843 "An Aux KC has already been registered for deferred processing."); 10844 return false; 10845 } 10846 10847 OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 10848 if (!infoDict) { 10849 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 10850 "The Aux KC has info dictionary"); 10851 return false; 10852 } 10853 10854 OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 10855 if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) { 10856 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 10857 "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey); 10858 return false; 10859 } 10860 10861 /* 10862 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid 10863 * sysctl can return the UUID to user space which will check this 10864 * value for errors. 10865 */ 10866 memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(), 10867 kcUUID->getLength()); 10868 uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string); 10869 auxkc_uuid_valid = TRUE; 10870 10871 deferredAuxKCXML = parsedXML; 10872 10873 return true; 10874 } 10875 10876 OSSharedPtr<OSObject> 10877 OSKext::consumeDeferredKextCollection(kc_kind_t type) 10878 { 10879 if (type != KCKindAuxiliary || !deferredAuxKCXML) { 10880 return NULL; 10881 } 10882 10883 return os::move(deferredAuxKCXML); 10884 } 10885 10886 #if PRAGMA_MARK 10887 #pragma mark Profile-Guided-Optimization Support 10888 #endif 10889 10890 // #include <InstrProfiling.h> 10891 extern "C" { 10892 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin, 10893 const char *DataEnd, 10894 const char *CountersBegin, 10895 const char *CountersEnd, 10896 const char *NamesBegin, 10897 const char *NamesEnd); 10898 int __llvm_profile_write_buffer_internal(char *Buffer, 10899 const char *DataBegin, 10900 const char *DataEnd, 10901 const char *CountersBegin, 10902 const char *CountersEnd, 10903 const char *NamesBegin, 10904 const char *NamesEnd); 10905 } 10906 10907 10908 static 10909 void 10910 OSKextPgoMetadataPut(char *pBuffer, 10911 size_t *position, 10912 size_t bufferSize, 10913 uint32_t *num_pairs, 10914 const char *key, 10915 const char *value) 10916 { 10917 size_t strlen_key = strlen(key); 10918 size_t strlen_value = strlen(value); 10919 size_t len = strlen(key) + 1 + strlen(value) + 1; 10920 char *pos = pBuffer + *position; 10921 *position += len; 10922 if (pBuffer && bufferSize && *position <= bufferSize) { 10923 memcpy(pos, key, strlen_key); pos += strlen_key; 10924 *(pos++) = '='; 10925 memcpy(pos, value, strlen_value); pos += strlen_value; 10926 *(pos++) = 0; 10927 if (num_pairs) { 10928 (*num_pairs)++; 10929 } 10930 } 10931 } 10932 10933 10934 static 10935 void 10936 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max) 10937 { 10938 *position += strlen(key) + 1 + value_max + 1; 10939 } 10940 10941 10942 static 10943 void 10944 OSKextPgoMetadataPutAll(OSKext *kext, 10945 uuid_t instance_uuid, 10946 char *pBuffer, 10947 size_t *position, 10948 size_t bufferSize, 10949 uint32_t *num_pairs) 10950 { 10951 _static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0); 10952 //log_10 2^16 ≈ 4.82 10953 const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2; 10954 const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6; 10955 10956 if (!pBuffer) { 10957 OSKextPgoMetadataPutMax(position, "INSTANCE", 36); 10958 OSKextPgoMetadataPutMax(position, "UUID", 36); 10959 OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size); 10960 } else { 10961 uuid_string_t instance_uuid_string; 10962 uuid_unparse(instance_uuid, instance_uuid_string); 10963 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10964 "INSTANCE", instance_uuid_string); 10965 10966 OSSharedPtr<OSData> uuid_data; 10967 uuid_t uuid; 10968 uuid_string_t uuid_string; 10969 uuid_data = kext->copyUUID(); 10970 if (uuid_data) { 10971 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 10972 uuid_unparse(uuid, uuid_string); 10973 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10974 "UUID", uuid_string); 10975 } 10976 10977 clock_sec_t secs; 10978 clock_usec_t usecs; 10979 clock_get_calendar_microtime(&secs, &usecs); 10980 assert(usecs < 1000000); 10981 char timestamp[max_timestamp_string_size + 1]; 10982 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t)); 10983 snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs); 10984 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10985 "TIMESTAMP", timestamp); 10986 } 10987 10988 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10989 "NAME", kext->getIdentifierCString()); 10990 10991 char versionCString[kOSKextVersionMaxLength]; 10992 OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength); 10993 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10994 "VERSION", versionCString); 10995 } 10996 10997 static 10998 size_t 10999 OSKextPgoMetadataSize(OSKext *kext) 11000 { 11001 size_t position = 0; 11002 uuid_t fakeuuid = {}; 11003 OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL); 11004 return position; 11005 } 11006 11007 int 11008 OSKextGrabPgoDataLocked(OSKext *kext, 11009 bool metadata, 11010 uuid_t instance_uuid, 11011 uint64_t *pSize, 11012 char *pBuffer, 11013 uint64_t bufferSize) 11014 { 11015 int err = 0; 11016 11017 kernel_section_t *sect_prf_data = NULL; 11018 kernel_section_t *sect_prf_name = NULL; 11019 kernel_section_t *sect_prf_cnts = NULL; 11020 uint64_t size; 11021 size_t metadata_size = 0; 11022 size_t offset_to_pairs = 0; 11023 11024 sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data"); 11025 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names"); 11026 if (!sect_prf_name) { 11027 // kextcache sometimes truncates the section name to 15 chars 11028 // <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache 11029 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name"); 11030 } 11031 sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 11032 11033 if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) { 11034 err = ENOTSUP; 11035 goto out; 11036 } 11037 11038 size = __llvm_profile_get_size_for_buffer_internal( 11039 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 11040 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 11041 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 11042 11043 if (metadata) { 11044 metadata_size = OSKextPgoMetadataSize(kext); 11045 size += metadata_size; 11046 size += sizeof(pgo_metadata_footer); 11047 } 11048 11049 11050 if (pSize) { 11051 *pSize = size; 11052 } 11053 11054 if (pBuffer && bufferSize) { 11055 if (bufferSize < size) { 11056 err = ERANGE; 11057 goto out; 11058 } 11059 11060 err = __llvm_profile_write_buffer_internal( 11061 pBuffer, 11062 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 11063 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 11064 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 11065 11066 if (err) { 11067 err = EIO; 11068 goto out; 11069 } 11070 11071 if (metadata) { 11072 offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size; 11073 if (offset_to_pairs > UINT32_MAX) { 11074 err = E2BIG; 11075 goto out; 11076 } 11077 11078 char *end_of_buffer = pBuffer + size; 11079 struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer)); 11080 char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size); 11081 11082 size_t metadata_position = 0; 11083 uint32_t num_pairs = 0; 11084 OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs); 11085 while (metadata_position < metadata_size) { 11086 metadata_buffer[metadata_position++] = 0; 11087 } 11088 11089 struct pgo_metadata_footer footer; 11090 footer.magic = htonl(0x6d657461); 11091 footer.number_of_pairs = htonl( num_pairs ); 11092 footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs ); 11093 memcpy(footerp, &footer, sizeof(footer)); 11094 } 11095 } 11096 11097 out: 11098 return err; 11099 } 11100 11101 11102 int 11103 OSKextGrabPgoData(uuid_t uuid, 11104 uint64_t *pSize, 11105 char *pBuffer, 11106 uint64_t bufferSize, 11107 int wait_for_unload, 11108 int metadata) 11109 { 11110 int err = 0; 11111 OSSharedPtr<OSKext> kext; 11112 11113 11114 IORecursiveLockLock(sKextLock); 11115 11116 kext = OSKext::lookupKextWithUUID(uuid); 11117 if (!kext) { 11118 err = ENOENT; 11119 goto out; 11120 } 11121 11122 if (wait_for_unload) { 11123 OSKextGrabPgoStruct s; 11124 11125 s.metadata = metadata; 11126 s.pSize = pSize; 11127 s.pBuffer = pBuffer; 11128 s.bufferSize = bufferSize; 11129 s.err = EINTR; 11130 11131 struct list_head *prev = &kext->pendingPgoHead; 11132 struct list_head *next = kext->pendingPgoHead.next; 11133 11134 s.list_head.prev = prev; 11135 s.list_head.next = next; 11136 11137 prev->next = &s.list_head; 11138 next->prev = &s.list_head; 11139 11140 kext.reset(); 11141 11142 IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE); 11143 11144 prev = s.list_head.prev; 11145 next = s.list_head.next; 11146 11147 prev->next = next; 11148 next->prev = prev; 11149 11150 err = s.err; 11151 } else { 11152 err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize); 11153 } 11154 11155 out: 11156 11157 IORecursiveLockUnlock(sKextLock); 11158 11159 return err; 11160 } 11161 11162 void 11163 OSKextResetPgoCountersLock() 11164 { 11165 IORecursiveLockLock(sKextLock); 11166 } 11167 11168 void 11169 OSKextResetPgoCountersUnlock() 11170 { 11171 IORecursiveLockUnlock(sKextLock); 11172 } 11173 11174 11175 extern unsigned int not_in_kdp; 11176 11177 void 11178 OSKextResetPgoCounters() 11179 { 11180 assert(!not_in_kdp); 11181 uint32_t count = sLoadedKexts->getCount(); 11182 for (uint32_t i = 0; i < count; i++) { 11183 OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 11184 kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 11185 if (!sect_prf_cnts) { 11186 continue; 11187 } 11188 memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size); 11189 } 11190 } 11191 11192 OSSharedPtr<OSDictionary> 11193 OSKext::copyLoadedKextInfoByUUID( 11194 OSArray * kextIdentifiers, 11195 OSArray * infoKeys) 11196 { 11197 OSSharedPtr<OSDictionary> result; 11198 OSSharedPtr<OSDictionary> kextInfo; 11199 uint32_t max_count, i, j; 11200 uint32_t idCount = 0; 11201 uint32_t idIndex = 0; 11202 IORecursiveLockLock(sKextLock); 11203 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 11204 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 11205 11206 #if CONFIG_MACF 11207 /* Is the calling process allowed to query kext info? */ 11208 if (current_task() != kernel_task) { 11209 int macCheckResult = 0; 11210 kauth_cred_t cred = NULL; 11211 11212 cred = kauth_cred_get_with_ref(); 11213 macCheckResult = mac_kext_check_query(cred); 11214 kauth_cred_unref(&cred); 11215 11216 if (macCheckResult != 0) { 11217 OSKextLog(/* kext */ NULL, 11218 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 11219 "Failed to query kext info (MAC policy error 0x%x).", 11220 macCheckResult); 11221 goto finish; 11222 } 11223 } 11224 #endif 11225 11226 /* Empty list of UUIDs is equivalent to no list (get all). 11227 */ 11228 if (kextIdentifiers && !kextIdentifiers->getCount()) { 11229 kextIdentifiers = NULL; 11230 } else if (kextIdentifiers) { 11231 idCount = kextIdentifiers->getCount(); 11232 } 11233 11234 /* Same for keys. 11235 */ 11236 if (infoKeys && !infoKeys->getCount()) { 11237 infoKeys = NULL; 11238 } 11239 11240 max_count = count[0] + count[1]; 11241 result = OSDictionary::withCapacity(max_count); 11242 if (!result) { 11243 goto finish; 11244 } 11245 11246 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 11247 for (i = 0; i < count[j]; i++) { 11248 OSKext *thisKext = NULL; // do not release 11249 Boolean includeThis = true; 11250 uuid_t thisKextUUID; 11251 uuid_t thisKextTextUUID; 11252 OSSharedPtr<OSData> uuid_data; 11253 uuid_string_t uuid_key; 11254 11255 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 11256 if (!thisKext) { 11257 continue; 11258 } 11259 11260 uuid_data = thisKext->copyUUID(); 11261 if (!uuid_data) { 11262 continue; 11263 } 11264 11265 memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID)); 11266 11267 uuid_unparse(thisKextUUID, uuid_key); 11268 11269 uuid_data = thisKext->copyTextUUID(); 11270 if (!uuid_data) { 11271 continue; 11272 } 11273 memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID)); 11274 11275 /* Skip current kext if we have a list of UUIDs and 11276 * it isn't in the list. 11277 */ 11278 if (kextIdentifiers) { 11279 includeThis = false; 11280 11281 for (idIndex = 0; idIndex < idCount; idIndex++) { 11282 const OSString* wantedUUID = OSDynamicCast(OSString, 11283 kextIdentifiers->getObject(idIndex)); 11284 11285 uuid_t uuid; 11286 uuid_parse(wantedUUID->getCStringNoCopy(), uuid); 11287 11288 if ((0 == uuid_compare(uuid, thisKextUUID)) 11289 || (0 == uuid_compare(uuid, thisKextTextUUID))) { 11290 includeThis = true; 11291 /* Only need to find the first kext if multiple match, 11292 * ie. asking for the kernel uuid does not need to find 11293 * interface kexts or builtin static kexts. 11294 */ 11295 kextIdentifiers->removeObject(idIndex); 11296 uuid_unparse(uuid, uuid_key); 11297 break; 11298 } 11299 } 11300 } 11301 11302 if (!includeThis) { 11303 continue; 11304 } 11305 11306 kextInfo = thisKext->copyInfo(infoKeys); 11307 if (kextInfo) { 11308 result->setObject(uuid_key, kextInfo.get()); 11309 } 11310 11311 if (kextIdentifiers && !kextIdentifiers->getCount()) { 11312 goto finish; 11313 } 11314 } 11315 } 11316 11317 finish: 11318 IORecursiveLockUnlock(sKextLock); 11319 11320 return result; 11321 } 11322 11323 /********************************************************************* 11324 *********************************************************************/ 11325 /* static */ 11326 OSSharedPtr<OSDictionary> 11327 OSKext::copyKextCollectionInfo( 11328 OSDictionary *requestDict, 11329 OSArray *infoKeys) 11330 { 11331 OSSharedPtr<OSDictionary> result; 11332 OSString *collectionType = NULL; 11333 OSObject *rawLoadedState = NULL; 11334 OSString *loadedState = NULL; 11335 11336 kc_kind_t kc_request_kind = KCKindUnknown; 11337 bool onlyLoaded = false; 11338 bool onlyUnloaded = false; 11339 11340 #if CONFIG_MACF 11341 /* Is the calling process allowed to query kext info? */ 11342 if (current_task() != kernel_task) { 11343 int macCheckResult = 0; 11344 kauth_cred_t cred = NULL; 11345 11346 cred = kauth_cred_get_with_ref(); 11347 macCheckResult = mac_kext_check_query(cred); 11348 kauth_cred_unref(&cred); 11349 11350 if (macCheckResult != 0) { 11351 OSKextLog(/* kext */ NULL, 11352 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 11353 "Failed to query kext info (MAC policy error 0x%x).", 11354 macCheckResult); 11355 goto finish; 11356 } 11357 } 11358 #endif 11359 11360 if (infoKeys && !infoKeys->getCount()) { 11361 infoKeys = NULL; 11362 } 11363 11364 collectionType = OSDynamicCast(OSString, 11365 _OSKextGetRequestArgument(requestDict, 11366 kKextRequestArgumentCollectionTypeKey)); 11367 if (!collectionType) { 11368 OSKextLog(/* kext */ NULL, 11369 kOSKextLogErrorLevel | 11370 kOSKextLogIPCFlag, 11371 "Invalid '%s' argument to kext collection info request.", 11372 kKextRequestArgumentCollectionTypeKey); 11373 goto finish; 11374 } 11375 if (collectionType->isEqualTo(kKCTypePrimary)) { 11376 kc_request_kind = KCKindPrimary; 11377 } else if (collectionType->isEqualTo(kKCTypeSystem)) { 11378 kc_request_kind = KCKindPageable; 11379 } else if (collectionType->isEqualTo(kKCTypeAuxiliary)) { 11380 kc_request_kind = KCKindAuxiliary; 11381 } else if (collectionType->isEqualTo(kKCTypeCodeless)) { 11382 kc_request_kind = KCKindNone; 11383 } else if (!collectionType->isEqualTo(kKCTypeAny)) { 11384 OSKextLog(/* kext */ NULL, 11385 kOSKextLogErrorLevel | 11386 kOSKextLogIPCFlag, 11387 "Invalid '%s' argument value '%s' to kext collection info request.", 11388 kKextRequestArgumentCollectionTypeKey, 11389 collectionType->getCStringNoCopy()); 11390 goto finish; 11391 } 11392 11393 rawLoadedState = _OSKextGetRequestArgument(requestDict, 11394 kKextRequestArgumentLoadedStateKey); 11395 if (rawLoadedState) { 11396 loadedState = OSDynamicCast(OSString, rawLoadedState); 11397 if (!loadedState) { 11398 OSKextLog(/* kext */ NULL, 11399 kOSKextLogErrorLevel | 11400 kOSKextLogIPCFlag, 11401 "Invalid '%s' argument to kext collection info request.", 11402 kKextRequestArgumentLoadedStateKey); 11403 goto finish; 11404 } 11405 } 11406 if (loadedState) { 11407 if (loadedState->isEqualTo("Loaded")) { 11408 onlyLoaded = true; 11409 } else if (loadedState->isEqualTo("Unloaded")) { 11410 onlyUnloaded = true; 11411 } else if (!loadedState->isEqualTo("Any")) { 11412 OSKextLog(/* kext */ NULL, 11413 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 11414 "Invalid '%s' argument value '%s' for '%s' collection info", 11415 kKextRequestArgumentLoadedStateKey, 11416 loadedState->getCStringNoCopy(), 11417 collectionType->getCStringNoCopy()); 11418 goto finish; 11419 } 11420 } 11421 11422 result = OSDictionary::withCapacity(sKextsByID->getCount()); 11423 if (!result) { 11424 goto finish; 11425 } 11426 11427 IORecursiveLockLock(sKextLock); 11428 { // start block scope 11429 sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj) 11430 { 11431 OSKext *thisKext = NULL; // do not release 11432 OSSharedPtr<OSDictionary> kextInfo; 11433 11434 (void)thisKextID; 11435 11436 thisKext = OSDynamicCast(OSKext, obj); 11437 if (!thisKext) { 11438 return false; 11439 } 11440 11441 /* 11442 * skip the kext if it came from the wrong collection type 11443 * (and the caller requested a specific type) 11444 */ 11445 if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) { 11446 return false; 11447 } 11448 11449 /* 11450 * respect the caller's desire to find only loaded or 11451 * unloaded kexts 11452 */ 11453 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 11454 return false; 11455 } 11456 if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 11457 return false; 11458 } 11459 11460 kextInfo = thisKext->copyInfo(infoKeys); 11461 if (kextInfo) { 11462 result->setObject(thisKext->getIdentifier(), kextInfo.get()); 11463 } 11464 return false; 11465 }); 11466 } // end block scope 11467 IORecursiveLockUnlock(sKextLock); 11468 11469 finish: 11470 return result; 11471 } 11472 11473 /* static */ 11474 OSSharedPtr<OSArray> 11475 OSKext::copyDextsInfo( 11476 OSArray *kextIdentifiers, 11477 OSArray *infoKeys) 11478 { 11479 OSSharedPtr<OSArray> result = NULL; 11480 uint32_t idCount = 0; 11481 bool getActive = false; 11482 bool getLoaded = false; 11483 bool getUnloaded = false; 11484 bool getPendingUpgrade = false; 11485 unsigned int avgDextCount = 0; 11486 11487 #if CONFIG_MACF 11488 /* Is the calling process allowed to query dext info? */ 11489 if (current_task() != kernel_task) { 11490 int macCheckResult = 0; 11491 kauth_cred_t cred = NULL; 11492 11493 cred = kauth_cred_get_with_ref(); 11494 macCheckResult = mac_kext_check_query(cred); 11495 kauth_cred_unref(&cred); 11496 11497 if (macCheckResult != 0) { 11498 OSKextLog(/* kext */ NULL, 11499 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 11500 "Failed to query kext info (MAC policy error 0x%x).", 11501 macCheckResult); 11502 goto finish; 11503 } 11504 } 11505 #endif 11506 /* 11507 * No infoKeys means return everything we 11508 * know about the dexts. 11509 */ 11510 if (infoKeys && !infoKeys->getCount()) { 11511 infoKeys = NULL; 11512 } 11513 11514 /* 11515 * Empty list of bundle ids is equivalent to 11516 * no list (get all). 11517 */ 11518 if (kextIdentifiers && !kextIdentifiers->getCount()) { 11519 kextIdentifiers = NULL; 11520 } else if (kextIdentifiers) { 11521 idCount = kextIdentifiers->getCount(); 11522 } 11523 11524 /* 11525 * Caller can specify which state of dexts to query. 11526 */ 11527 if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveKey)) { 11528 getActive = true; 11529 } 11530 if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveLoadedKey)) { 11531 getLoaded = true; 11532 } 11533 if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveUnloadedKey)) { 11534 getUnloaded = true; 11535 } 11536 if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStatePendingUpgradeKey)) { 11537 getPendingUpgrade = true; 11538 } 11539 11540 /* 11541 * By default we are going to return all active and pendingUpgrade dexts 11542 * only. 11543 */ 11544 if (!(getActive || getLoaded || getUnloaded || getPendingUpgrade)) { 11545 getActive = true; 11546 getPendingUpgrade = true; 11547 } 11548 11549 /* 11550 * We return a dictionary of dexts 11551 * for every group requested. 11552 */ 11553 avgDextCount = sLoadedDriverKitKexts->getCount() + sDriverKitToUpgradeByID->getCount(); 11554 result = OSArray::withCapacity(avgDextCount); 11555 if (!result) { 11556 goto finish; 11557 } 11558 11559 IORecursiveLockLock(sKextLock); 11560 { // start block scope 11561 if (getActive || getLoaded || getUnloaded) { 11562 sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj) 11563 { 11564 OSKext *thisKext = NULL; // do not release 11565 OSSharedPtr<OSDictionary> kextInfo; 11566 Boolean includeThis = true; 11567 (void)thisKextID; 11568 11569 thisKext = OSDynamicCast(OSKext, obj); 11570 if (!thisKext || !thisKext->isDriverKit()) { 11571 return false; 11572 } 11573 11574 /* 11575 * Skip current dext if we have a list of bundle IDs and 11576 * it isn't in the list. 11577 */ 11578 if (kextIdentifiers) { 11579 includeThis = false; 11580 11581 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) { 11582 const OSString * thisRequestID = OSDynamicCast(OSString, 11583 kextIdentifiers->getObject(idIndex)); 11584 if (thisKextID->isEqualTo(thisRequestID)) { 11585 includeThis = true; 11586 break; 11587 } 11588 } 11589 } 11590 11591 if (!includeThis) { 11592 return false; 11593 } 11594 11595 OSSharedPtr<OSString> state; 11596 if (sLoadedDriverKitKexts->getNextIndexOfObject(thisKext, 0) == -1U) { 11597 if (!(getActive || getUnloaded)) { 11598 return false; 11599 } 11600 state = OSString::withCString(kOSBundleDextStateActiveUnloadedKey); 11601 } else { 11602 if (!(getActive || getLoaded)) { 11603 return false; 11604 } 11605 state = OSString::withCString(kOSBundleDextStateActiveLoadedKey); 11606 } 11607 11608 kextInfo = thisKext->copyInfo(infoKeys); 11609 if (kextInfo) { 11610 kextInfo->setObject(kOSBundleDextStateKey, state.get()); 11611 result->setObject(kextInfo.get()); 11612 } 11613 11614 return false; 11615 }); 11616 } 11617 11618 if (getPendingUpgrade) { 11619 sDriverKitToUpgradeByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj) 11620 { 11621 OSKext *thisKext = NULL; // do not release 11622 OSSharedPtr<OSDictionary> kextInfo; 11623 Boolean includeThis = true; 11624 (void)thisKextID; 11625 11626 thisKext = OSDynamicCast(OSKext, obj); 11627 if (!thisKext) { 11628 return false; 11629 } 11630 __assert_only bool isDext = thisKext->isDriverKit(); 11631 assert(isDext == true); 11632 11633 /* 11634 * Skip current dext if we have a list of bundle IDs and 11635 * it isn't in the list. 11636 */ 11637 if (kextIdentifiers) { 11638 includeThis = false; 11639 11640 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) { 11641 const OSString * thisRequestID = OSDynamicCast(OSString, 11642 kextIdentifiers->getObject(idIndex)); 11643 if (thisKextID->isEqualTo(thisRequestID)) { 11644 includeThis = true; 11645 break; 11646 } 11647 } 11648 } 11649 11650 if (!includeThis) { 11651 return false; 11652 } 11653 11654 kextInfo = thisKext->copyInfo(infoKeys); 11655 if (kextInfo) { 11656 OSSharedPtr<OSString> state = OSString::withCString(kOSBundleDextStatePendingUpgradeKey); 11657 kextInfo->setObject(kOSBundleDextStateKey, state.get()); 11658 result->setObject(kextInfo.get()); 11659 } 11660 return false; 11661 }); 11662 } 11663 } // end block scope 11664 IORecursiveLockUnlock(sKextLock); 11665 finish: 11666 return result; 11667 } 11668 11669 /********************************************************************* 11670 *********************************************************************/ 11671 /* static */ 11672 OSSharedPtr<OSDictionary> 11673 OSKext::copyLoadedKextInfo( 11674 OSArray * kextIdentifiers, 11675 OSArray * infoKeys) 11676 { 11677 OSSharedPtr<OSDictionary> result; 11678 uint32_t idCount = 0; 11679 bool onlyLoaded; 11680 11681 IORecursiveLockLock(sKextLock); 11682 11683 #if CONFIG_MACF 11684 /* Is the calling process allowed to query kext info? */ 11685 if (current_task() != kernel_task) { 11686 int macCheckResult = 0; 11687 kauth_cred_t cred = NULL; 11688 11689 cred = kauth_cred_get_with_ref(); 11690 macCheckResult = mac_kext_check_query(cred); 11691 kauth_cred_unref(&cred); 11692 11693 if (macCheckResult != 0) { 11694 OSKextLog(/* kext */ NULL, 11695 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 11696 "Failed to query kext info (MAC policy error 0x%x).", 11697 macCheckResult); 11698 goto finish; 11699 } 11700 } 11701 #endif 11702 11703 /* Empty list of bundle ids is equivalent to no list (get all). 11704 */ 11705 if (kextIdentifiers && !kextIdentifiers->getCount()) { 11706 kextIdentifiers = NULL; 11707 } else if (kextIdentifiers) { 11708 idCount = kextIdentifiers->getCount(); 11709 } 11710 11711 /* Same for keys. 11712 */ 11713 if (infoKeys && !infoKeys->getCount()) { 11714 infoKeys = NULL; 11715 } 11716 11717 onlyLoaded = (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey)); 11718 11719 result = OSDictionary::withCapacity(128); 11720 if (!result) { 11721 goto finish; 11722 } 11723 11724 #if 0 11725 OSKextLog(/* kext */ NULL, 11726 kOSKextLogErrorLevel | 11727 kOSKextLogGeneralFlag, 11728 "kaslr: vm_kernel_slide 0x%lx \n", 11729 vm_kernel_slide); 11730 OSKextLog(/* kext */ NULL, 11731 kOSKextLogErrorLevel | 11732 kOSKextLogGeneralFlag, 11733 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n", 11734 vm_kernel_stext, vm_kernel_etext); 11735 OSKextLog(/* kext */ NULL, 11736 kOSKextLogErrorLevel | 11737 kOSKextLogGeneralFlag, 11738 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n", 11739 vm_kernel_base, vm_kernel_top); 11740 OSKextLog(/* kext */ NULL, 11741 kOSKextLogErrorLevel | 11742 kOSKextLogGeneralFlag, 11743 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n", 11744 vm_kext_base, vm_kext_top); 11745 OSKextLog(/* kext */ NULL, 11746 kOSKextLogErrorLevel | 11747 kOSKextLogGeneralFlag, 11748 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n", 11749 vm_prelink_stext, vm_prelink_etext); 11750 OSKextLog(/* kext */ NULL, 11751 kOSKextLogErrorLevel | 11752 kOSKextLogGeneralFlag, 11753 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n", 11754 vm_prelink_sinfo, vm_prelink_einfo); 11755 OSKextLog(/* kext */ NULL, 11756 kOSKextLogErrorLevel | 11757 kOSKextLogGeneralFlag, 11758 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n", 11759 vm_slinkedit, vm_elinkedit); 11760 #endif 11761 { // start block scope 11762 sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj) 11763 { 11764 OSKext * thisKext = NULL; // do not release 11765 Boolean includeThis = true; 11766 OSSharedPtr<OSDictionary> kextInfo; 11767 11768 thisKext = OSDynamicCast(OSKext, obj); 11769 if (!thisKext) { 11770 return false; 11771 } 11772 11773 /* Skip current kext if not yet started and caller didn't request all. 11774 */ 11775 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 11776 return false; 11777 } 11778 11779 /* Skip current kext if we have a list of bundle IDs and 11780 * it isn't in the list. 11781 */ 11782 if (kextIdentifiers) { 11783 includeThis = false; 11784 11785 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) { 11786 const OSString * thisRequestID = OSDynamicCast(OSString, 11787 kextIdentifiers->getObject(idIndex)); 11788 if (thisKextID->isEqualTo(thisRequestID)) { 11789 includeThis = true; 11790 break; 11791 } 11792 } 11793 } 11794 11795 if (!includeThis) { 11796 return false; 11797 } 11798 11799 kextInfo = thisKext->copyInfo(infoKeys); 11800 if (kextInfo) { 11801 result->setObject(thisKext->getIdentifier(), kextInfo.get()); 11802 } 11803 return false; 11804 }); 11805 } // end block scope 11806 11807 finish: 11808 IORecursiveLockUnlock(sKextLock); 11809 11810 return result; 11811 } 11812 11813 /********************************************************************* 11814 * Any info that needs to do allocations must goto finish on alloc 11815 * failure. Info that is just a lookup should just not set the object 11816 * if the info does not exist. 11817 *********************************************************************/ 11818 #define _OSKextLoadInfoDictCapacity (12) 11819 11820 OSSharedPtr<OSDictionary> 11821 OSKext::copyInfo(OSArray * infoKeys) 11822 { 11823 OSSharedPtr<OSDictionary> result; 11824 bool success = false; 11825 OSSharedPtr<OSData> headerData; 11826 OSSharedPtr<OSData> logData; 11827 OSSharedPtr<OSNumber> cpuTypeNumber; 11828 OSSharedPtr<OSNumber> cpuSubtypeNumber; 11829 OSString * versionString = NULL; // do not release 11830 OSString * bundleType = NULL; // do not release 11831 uint32_t executablePathCStringSize = 0; 11832 char * executablePathCString = NULL; // must kfree 11833 OSSharedPtr<OSString> executablePathString; 11834 OSSharedPtr<OSData> uuid; 11835 OSSharedPtr<OSArray> dependencyLoadTags; 11836 OSSharedPtr<OSCollectionIterator> metaClassIterator; 11837 OSSharedPtr<OSArray> metaClassInfo; 11838 OSSharedPtr<OSDictionary> metaClassDict; 11839 OSMetaClass * thisMetaClass = NULL; // do not release 11840 OSSharedPtr<OSString> metaClassName; 11841 OSSharedPtr<OSString> superclassName; 11842 kc_format_t kcformat; 11843 uint32_t count, i; 11844 11845 result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity); 11846 if (!result) { 11847 goto finish; 11848 } 11849 11850 11851 /* Empty keys means no keys, but NULL is quicker to check. 11852 */ 11853 if (infoKeys && !infoKeys->getCount()) { 11854 infoKeys = NULL; 11855 } 11856 11857 if (!PE_get_primary_kc_format(&kcformat)) { 11858 goto finish; 11859 } 11860 11861 /* Headers, CPU type, and CPU subtype. 11862 */ 11863 if (!infoKeys || 11864 _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) || 11865 _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) || 11866 _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) || 11867 _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 11868 if (linkedExecutable && !isInterface()) { 11869 kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *) 11870 linkedExecutable->getBytesNoCopy(); 11871 11872 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX 11873 // do not return macho header info on shipping embedded - 19095897 11874 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) { 11875 kernel_mach_header_t * temp_kext_mach_hdr; 11876 struct load_command * lcp; 11877 11878 headerData = OSData::withBytes(kext_mach_hdr, 11879 (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds)); 11880 if (!headerData) { 11881 goto finish; 11882 } 11883 11884 // unslide any vmaddrs we return to userspace - 10726716 11885 temp_kext_mach_hdr = (kernel_mach_header_t *) 11886 headerData->getBytesNoCopy(); 11887 if (temp_kext_mach_hdr == NULL) { 11888 goto finish; 11889 } 11890 11891 lcp = (struct load_command *) (temp_kext_mach_hdr + 1); 11892 for (i = 0; (i < temp_kext_mach_hdr->ncmds) && !flags.unslidMachO; i++) { 11893 if (lcp->cmd == LC_SEGMENT_KERNEL) { 11894 kernel_segment_command_t * segp; 11895 kernel_section_t * secp; 11896 11897 segp = (kernel_segment_command_t *) lcp; 11898 // 10543468 - if we jettisoned __LINKEDIT clear size info 11899 if (flags.jettisonLinkeditSeg) { 11900 if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) { 11901 segp->vmsize = 0; 11902 segp->fileoff = 0; 11903 segp->filesize = 0; 11904 } 11905 } 11906 11907 #if __arm__ || __arm64__ 11908 // iBoot disregards zero-size segments, just set their addresses to gVirtBase 11909 // and unslide them to avoid vm assertion failures / kernel logging breakage. 11910 if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) { 11911 segp->vmaddr = gVirtBase; 11912 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { 11913 secp->size = 0; // paranoia :) 11914 secp->addr = gVirtBase; 11915 } 11916 } 11917 #endif 11918 11919 #if 0 11920 OSKextLog(/* kext */ NULL, 11921 kOSKextLogErrorLevel | 11922 kOSKextLogGeneralFlag, 11923 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u", 11924 __FUNCTION__, segp->segname, segp->vmaddr, 11925 VM_KERNEL_UNSLIDE(segp->vmaddr), 11926 segp->vmsize, segp->nsects); 11927 if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) && 11928 (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) && 11929 (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) && 11930 (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) && 11931 (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) { 11932 OSKextLog(/* kext */ NULL, 11933 kOSKextLogErrorLevel | 11934 kOSKextLogGeneralFlag, 11935 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX", 11936 __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top); 11937 } 11938 #endif 11939 segp->vmaddr = ml_static_unslide(segp->vmaddr); 11940 11941 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { 11942 secp->addr = ml_static_unslide(secp->addr); 11943 } 11944 } 11945 lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize); 11946 } 11947 result->setObject(kOSBundleMachOHeadersKey, headerData.get()); 11948 } 11949 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX 11950 11951 if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) { 11952 osLogDataHeaderRef *header; 11953 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])]; 11954 11955 void *os_log_data = NULL; 11956 void *cstring_data = NULL; 11957 void *asan_cstring_data = NULL; 11958 unsigned long os_log_size = 0; 11959 unsigned long cstring_size = 0; 11960 unsigned long asan_cstring_size = 0; 11961 uint32_t os_log_offset = 0; 11962 uint32_t cstring_offset = 0; 11963 uint32_t asan_cstring_offset = 0; 11964 bool res; 11965 11966 os_log_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size); 11967 cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size); 11968 asan_cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size); 11969 11970 /* 11971 * If the addresses in the Mach-O header are unslid, manually 11972 * slide them to allow for dereferencing. 11973 */ 11974 if (flags.unslidMachO) { 11975 os_log_data = (os_log_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)os_log_data) : nullptr; 11976 cstring_data = (cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)cstring_data) : nullptr; 11977 asan_cstring_data = (asan_cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)asan_cstring_data) : nullptr; 11978 } 11979 11980 os_log_offset = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr; 11981 cstring_offset = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr; 11982 asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr; 11983 11984 header = (osLogDataHeaderRef *) headerBytes; 11985 header->version = OS_LOG_HDR_VERSION; 11986 header->sect_count = NUM_OS_LOG_SECTIONS; 11987 header->sections[OS_LOG_SECT_IDX].sect_offset = os_log_offset; 11988 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) os_log_size; 11989 header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset; 11990 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) cstring_size; 11991 header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset; 11992 header->sections[ASAN_CSTRING_SECT_IDX].sect_size = (uint32_t) asan_cstring_size; 11993 11994 11995 logData = OSData::withValue(*header); 11996 if (!logData) { 11997 goto finish; 11998 } 11999 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0]))); 12000 if (!res) { 12001 goto finish; 12002 } 12003 if (os_log_data) { 12004 res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size); 12005 if (!res) { 12006 goto finish; 12007 } 12008 } 12009 if (cstring_data) { 12010 res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size); 12011 if (!res) { 12012 goto finish; 12013 } 12014 } 12015 if (asan_cstring_data) { 12016 res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size); 12017 if (!res) { 12018 goto finish; 12019 } 12020 } 12021 result->setObject(kOSBundleLogStringsKey, logData.get()); 12022 } 12023 12024 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) { 12025 cpuTypeNumber = OSNumber::withNumber( 12026 (uint64_t) kext_mach_hdr->cputype, 12027 8 * sizeof(kext_mach_hdr->cputype)); 12028 if (!cpuTypeNumber) { 12029 goto finish; 12030 } 12031 result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get()); 12032 } 12033 12034 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 12035 cpuSubtypeNumber = OSNumber::withNumber( 12036 (uint64_t) kext_mach_hdr->cpusubtype, 12037 8 * sizeof(kext_mach_hdr->cpusubtype)); 12038 if (!cpuSubtypeNumber) { 12039 goto finish; 12040 } 12041 result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get()); 12042 } 12043 } else { 12044 if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) { 12045 osLogDataHeaderRef *header; 12046 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])]; 12047 bool res; 12048 12049 header = (osLogDataHeaderRef *) headerBytes; 12050 header->version = OS_LOG_HDR_VERSION; 12051 header->sect_count = NUM_OS_LOG_SECTIONS; 12052 header->sections[OS_LOG_SECT_IDX].sect_offset = 0; 12053 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) 0; 12054 header->sections[CSTRING_SECT_IDX].sect_offset = 0; 12055 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) 0; 12056 header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0; 12057 header->sections[ASAN_CSTRING_SECT_IDX].sect_size = (uint32_t) 0; 12058 12059 logData = OSData::withValue(*header); 12060 if (!logData) { 12061 goto finish; 12062 } 12063 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0]))); 12064 if (!res) { 12065 goto finish; 12066 } 12067 result->setObject(kOSBundleLogStringsKey, logData.get()); 12068 } 12069 } 12070 } 12071 12072 /* CFBundleIdentifier. We set this regardless because it's just stupid not to. 12073 */ 12074 result->setObject(kCFBundleIdentifierKey, bundleID.get()); 12075 12076 /* kOSBundleDextUniqueIdentifierKey if present. 12077 */ 12078 if (isDriverKit() && dextUniqueID != NULL) { 12079 result->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID.get()); 12080 } 12081 12082 /* CFBundlePackageType 12083 */ 12084 bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL; 12085 if (bundleType) { 12086 result->setObject(kCFBundlePackageTypeKey, bundleType); 12087 } 12088 12089 /* CFBundleVersion. 12090 */ 12091 if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) { 12092 versionString = OSDynamicCast(OSString, 12093 getPropertyForHostArch(kCFBundleVersionKey)); 12094 if (versionString) { 12095 result->setObject(kCFBundleVersionKey, versionString); 12096 } 12097 } 12098 12099 /* OSBundleCompatibleVersion. 12100 */ 12101 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) { 12102 versionString = OSDynamicCast(OSString, 12103 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 12104 if (versionString) { 12105 result->setObject(kOSBundleCompatibleVersionKey, versionString); 12106 } 12107 } 12108 12109 /* Path. 12110 */ 12111 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) { 12112 if (path) { 12113 result->setObject(kOSBundlePathKey, path.get()); 12114 } 12115 } 12116 12117 12118 /* OSBundleExecutablePath. 12119 */ 12120 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) { 12121 if (path && executableRelPath) { 12122 uint32_t pathLength = path->getLength(); // gets incremented below 12123 12124 // +1 for slash, +1 for \0 12125 executablePathCStringSize = pathLength + executableRelPath->getLength() + 2; 12126 12127 executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize, 12128 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); // +1 for \0 12129 if (!executablePathCString) { 12130 goto finish; 12131 } 12132 strlcpy(executablePathCString, path->getCStringNoCopy(), 12133 executablePathCStringSize); 12134 executablePathCString[pathLength++] = '/'; 12135 executablePathCString[pathLength++] = '\0'; 12136 strlcat(executablePathCString, executableRelPath->getCStringNoCopy(), 12137 executablePathCStringSize); 12138 12139 executablePathString = OSString::withCString(executablePathCString); 12140 12141 if (!executablePathString) { 12142 goto finish; 12143 } 12144 12145 result->setObject(kOSBundleExecutablePathKey, executablePathString.get()); 12146 } else if (flags.builtin) { 12147 result->setObject(kOSBundleExecutablePathKey, bundleID.get()); 12148 } else if (isDriverKit()) { 12149 if (path) { 12150 // +1 for slash, +1 for \0 12151 uint32_t pathLength = path->getLength(); 12152 executablePathCStringSize = pathLength + 2; 12153 12154 executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize, 12155 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 12156 if (!executablePathCString) { 12157 goto finish; 12158 } 12159 strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize); 12160 executablePathCString[pathLength++] = '/'; 12161 executablePathCString[pathLength++] = '\0'; 12162 12163 executablePathString = OSString::withCString(executablePathCString); 12164 12165 if (!executablePathString) { 12166 goto finish; 12167 } 12168 12169 result->setObject(kOSBundleExecutablePathKey, executablePathString.get()); 12170 } 12171 } 12172 } 12173 12174 /* UUID, if the kext has one. 12175 */ 12176 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) { 12177 uuid = copyUUID(); 12178 if (uuid) { 12179 result->setObject(kOSBundleUUIDKey, uuid.get()); 12180 } 12181 } 12182 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) { 12183 uuid = copyTextUUID(); 12184 if (uuid) { 12185 result->setObject(kOSBundleTextUUIDKey, uuid.get()); 12186 } 12187 } 12188 12189 /* 12190 * Info.plist digest 12191 */ 12192 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) { 12193 OSData *digest; 12194 digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL; 12195 if (digest) { 12196 result->setObject(kOSKextInfoPlistDigestKey, digest); 12197 } 12198 } 12199 12200 /* 12201 * Collection type 12202 */ 12203 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) { 12204 result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString())); 12205 } 12206 12207 /* 12208 * Collection availability 12209 */ 12210 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) { 12211 result->setObject(kOSKextAuxKCAvailabilityKey, 12212 isLoadable() ? kOSBooleanTrue : kOSBooleanFalse); 12213 } 12214 12215 /* 12216 * Allows user load 12217 */ 12218 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) { 12219 OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey)); 12220 if (allowUserLoad) { 12221 result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad); 12222 } 12223 } 12224 12225 /* 12226 * Bundle Dependencies (OSBundleLibraries) 12227 */ 12228 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) { 12229 OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey)); 12230 if (libraries) { 12231 result->setObject(kOSBundleLibrariesKey, libraries); 12232 } 12233 } 12234 12235 /***** 12236 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted. 12237 */ 12238 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) { 12239 result->setObject(kOSKernelResourceKey, 12240 isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse); 12241 } 12242 12243 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) { 12244 result->setObject(kOSBundleIsInterfaceKey, 12245 isInterface() ? kOSBooleanTrue : kOSBooleanFalse); 12246 } 12247 12248 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) { 12249 result->setObject(kOSBundlePrelinkedKey, 12250 isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse); 12251 } 12252 12253 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) { 12254 result->setObject(kOSBundleStartedKey, 12255 isStarted() ? kOSBooleanTrue : kOSBooleanFalse); 12256 } 12257 12258 /* LoadTag (Index). 12259 */ 12260 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) { 12261 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag, 12262 /* numBits */ 8 * sizeof(loadTag)); 12263 if (!scratchNumber) { 12264 goto finish; 12265 } 12266 result->setObject(kOSBundleLoadTagKey, scratchNumber.get()); 12267 } 12268 12269 /* LoadAddress, LoadSize. 12270 */ 12271 if (!infoKeys || 12272 _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) || 12273 _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) || 12274 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) || 12275 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) || 12276 _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 12277 bool is_dext = isDriverKit(); 12278 if (isInterface() || flags.builtin || linkedExecutable || is_dext) { 12279 /* These go to userspace via serialization, so we don't want any doubts 12280 * about their size. 12281 */ 12282 uint64_t loadAddress = 0; 12283 uint32_t loadSize = 0; 12284 uint32_t wiredSize = 0; 12285 uint64_t execLoadAddress = 0; 12286 uint32_t execLoadSize = 0; 12287 12288 /* Interfaces always report 0 load address & size. 12289 * Just the way they roll. 12290 * 12291 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp 12292 * xxx - shouldn't have one! 12293 */ 12294 12295 if (flags.builtin || linkedExecutable) { 12296 kernel_mach_header_t *mh = NULL; 12297 kernel_segment_command_t *seg = NULL; 12298 12299 if (flags.builtin) { 12300 loadAddress = kmod_info->address; 12301 loadSize = (uint32_t)kmod_info->size; 12302 } else { 12303 loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy(); 12304 loadSize = linkedExecutable->getLength(); 12305 } 12306 mh = (kernel_mach_header_t *)loadAddress; 12307 loadAddress = ml_static_unslide(loadAddress); 12308 12309 /* Walk through the kext, looking for the first executable 12310 * segment in case we were asked for its size/address. 12311 */ 12312 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 12313 if (seg->initprot & VM_PROT_EXECUTE) { 12314 execLoadAddress = (flags.unslidMachO) ? seg->vmaddr : ml_static_unslide(seg->vmaddr); 12315 execLoadSize = (uint32_t)seg->vmsize; 12316 break; 12317 } 12318 } 12319 12320 /* If we have a kmod_info struct, calculated the wired size 12321 * from that. Otherwise it's the full load size. 12322 */ 12323 if (kmod_info) { 12324 wiredSize = loadSize - (uint32_t)kmod_info->hdr_size; 12325 } else { 12326 wiredSize = loadSize; 12327 } 12328 } else if (is_dext) { 12329 /* 12330 * DriverKit userspace executables do not have a kernel linkedExecutable, 12331 * so we "fake" their address range with the LoadTag. 12332 */ 12333 if (loadTag) { 12334 loadAddress = execLoadAddress = loadTag; 12335 loadSize = execLoadSize = 1; 12336 } 12337 } 12338 12339 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) { 12340 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12341 (unsigned long long)(loadAddress), 12342 /* numBits */ 8 * sizeof(loadAddress)); 12343 if (!scratchNumber) { 12344 goto finish; 12345 } 12346 result->setObject(kOSBundleLoadAddressKey, scratchNumber.get()); 12347 } 12348 if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) { 12349 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey)) 12350 && loadAddress && loadSize) { 12351 void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary); 12352 if (!baseAddress) { 12353 goto finish; 12354 } 12355 12356 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12357 (unsigned long long)ml_static_unslide((vm_offset_t)baseAddress), 12358 /* numBits */ 8 * sizeof(loadAddress)); 12359 if (!scratchNumber) { 12360 goto finish; 12361 } 12362 result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get()); 12363 } 12364 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey)) 12365 && (this == sKernelKext) && gBuiltinKmodsCount) { 12366 result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue); 12367 } 12368 } 12369 12370 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) { 12371 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12372 (unsigned long long)(execLoadAddress), 12373 /* numBits */ 8 * sizeof(execLoadAddress)); 12374 if (!scratchNumber) { 12375 goto finish; 12376 } 12377 result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get()); 12378 } 12379 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) { 12380 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12381 (unsigned long long)(loadSize), 12382 /* numBits */ 8 * sizeof(loadSize)); 12383 if (!scratchNumber) { 12384 goto finish; 12385 } 12386 result->setObject(kOSBundleLoadSizeKey, scratchNumber.get()); 12387 } 12388 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) { 12389 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12390 (unsigned long long)(execLoadSize), 12391 /* numBits */ 8 * sizeof(execLoadSize)); 12392 if (!scratchNumber) { 12393 goto finish; 12394 } 12395 result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get()); 12396 } 12397 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 12398 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12399 (unsigned long long)(wiredSize), 12400 /* numBits */ 8 * sizeof(wiredSize)); 12401 if (!scratchNumber) { 12402 goto finish; 12403 } 12404 result->setObject(kOSBundleWiredSizeKey, scratchNumber.get()); 12405 } 12406 } 12407 } 12408 12409 /* OSBundleDependencies. In descending order for 12410 * easy compatibility with kextstat(8). 12411 */ 12412 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) { 12413 if ((count = getNumDependencies())) { 12414 dependencyLoadTags = OSArray::withCapacity(count); 12415 result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get()); 12416 12417 i = count - 1; 12418 do { 12419 OSKext * dependency = OSDynamicCast(OSKext, 12420 dependencies->getObject(i)); 12421 12422 if (!dependency) { 12423 continue; 12424 } 12425 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12426 (unsigned long long)dependency->getLoadTag(), 12427 /* numBits*/ 8 * sizeof(loadTag)); 12428 if (!scratchNumber) { 12429 goto finish; 12430 } 12431 dependencyLoadTags->setObject(scratchNumber.get()); 12432 } while (i--); 12433 } 12434 } 12435 12436 /* OSBundleMetaClasses. 12437 */ 12438 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) { 12439 if (metaClasses && metaClasses->getCount()) { 12440 metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get()); 12441 metaClassInfo = OSArray::withCapacity(metaClasses->getCount()); 12442 if (!metaClassIterator || !metaClassInfo) { 12443 goto finish; 12444 } 12445 result->setObject(kOSBundleClassesKey, metaClassInfo.get()); 12446 12447 while ((thisMetaClass = OSDynamicCast(OSMetaClass, 12448 metaClassIterator->getNextObject()))) { 12449 metaClassDict = OSDictionary::withCapacity(3); 12450 if (!metaClassDict) { 12451 goto finish; 12452 } 12453 12454 metaClassName = OSString::withCString(thisMetaClass->getClassName()); 12455 if (thisMetaClass->getSuperClass()) { 12456 superclassName = OSString::withCString( 12457 thisMetaClass->getSuperClass()->getClassName()); 12458 } 12459 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(), 12460 8 * sizeof(unsigned int)); 12461 12462 /* Bail if any of the essentials is missing. The root class lacks a superclass, 12463 * of course. 12464 */ 12465 if (!metaClassDict || !metaClassName || !scratchNumber) { 12466 goto finish; 12467 } 12468 12469 metaClassInfo->setObject(metaClassDict.get()); 12470 metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get()); 12471 if (superclassName) { 12472 metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get()); 12473 } 12474 metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get()); 12475 } 12476 } 12477 } 12478 12479 /* OSBundleRetainCount. 12480 */ 12481 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) { 12482 { 12483 int kextRetainCount = getRetainCount() - 1; 12484 if (isLoaded()) { 12485 kextRetainCount--; 12486 } 12487 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 12488 (int)kextRetainCount, 12489 /* numBits*/ 8 * sizeof(int)); 12490 if (scratchNumber) { 12491 result->setObject(kOSBundleRetainCountKey, scratchNumber.get()); 12492 } 12493 } 12494 } 12495 12496 success = true; 12497 12498 finish: 12499 if (executablePathCString) { 12500 kfree_data(executablePathCString, executablePathCStringSize); 12501 } 12502 if (!success) { 12503 result.reset(); 12504 } 12505 return result; 12506 } 12507 12508 /********************************************************************* 12509 *********************************************************************/ 12510 /* static */ 12511 bool 12512 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize) 12513 { 12514 bool ok; 12515 OSSharedPtr<OSKext> kext; 12516 12517 IORecursiveLockLock(sKextLock); 12518 kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain); 12519 IORecursiveLockUnlock(sKextLock); 12520 12521 if (!kext || !kext->path || !kext->userExecutableRelPath) { 12522 return false; 12523 } 12524 snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s", 12525 kext->path->getCStringNoCopy(), 12526 kext->userExecutableRelPath->getCStringNoCopy()); 12527 ok = true; 12528 12529 return ok; 12530 } 12531 12532 /********************************************************************* 12533 *********************************************************************/ 12534 /* static */ 12535 OSReturn 12536 OSKext::requestResource( 12537 const char * kextIdentifierCString, 12538 const char * resourceNameCString, 12539 OSKextRequestResourceCallback callback, 12540 void * context, 12541 OSKextRequestTag * requestTagOut) 12542 { 12543 OSReturn result = kOSReturnError; 12544 OSSharedPtr<OSKext> callbackKext; // looked up 12545 12546 OSKextRequestTag requestTag = -1; 12547 OSSharedPtr<OSNumber> requestTagNum; 12548 OSSharedPtr<OSDictionary> requestDict; 12549 OSSharedPtr<OSString> kextIdentifier; 12550 OSSharedPtr<OSString> resourceName; 12551 12552 OSSharedPtr<OSDictionary> callbackRecord; 12553 OSSharedPtr<OSValueObject<OSKextRequestResourceCallback> > callbackWrapper; 12554 12555 OSSharedPtr<OSValueObject<void *> > contextWrapper; 12556 12557 IORecursiveLockLock(sKextLock); 12558 12559 if (requestTagOut) { 12560 *requestTagOut = kOSKextRequestTagInvalid; 12561 } 12562 12563 /* If requests to user space are disabled, don't go any further */ 12564 if (!sKernelRequestsEnabled) { 12565 OSKextLog(/* kext */ NULL, 12566 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12567 "Can't request resource %s for %s - requests to user space are disabled.", 12568 resourceNameCString, 12569 kextIdentifierCString); 12570 result = kOSKextReturnDisabled; 12571 goto finish; 12572 } 12573 12574 if (!kextIdentifierCString || !resourceNameCString || !callback) { 12575 result = kOSKextReturnInvalidArgument; 12576 goto finish; 12577 } 12578 12579 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 12580 if (!callbackKext) { 12581 OSKextLog(/* kext */ NULL, 12582 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12583 "Resource request has bad callback address."); 12584 result = kOSKextReturnInvalidArgument; 12585 goto finish; 12586 } 12587 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 12588 OSKextLog(/* kext */ NULL, 12589 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12590 "Resource request callback is in a kext that is not started."); 12591 result = kOSKextReturnInvalidArgument; 12592 goto finish; 12593 } 12594 12595 /* Do not allow any new requests to be made on a kext that is unloading. 12596 */ 12597 if (callbackKext->flags.stopping) { 12598 result = kOSKextReturnStopping; 12599 goto finish; 12600 } 12601 12602 /* If we're wrapped the next available request tag around to the negative 12603 * numbers, we can't service any more requests. 12604 */ 12605 if (sNextRequestTag == kOSKextRequestTagInvalid) { 12606 OSKextLog(/* kext */ NULL, 12607 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12608 "No more request tags available; restart required."); 12609 result = kOSKextReturnNoResources; 12610 goto finish; 12611 } 12612 requestTag = sNextRequestTag++; 12613 12614 result = _OSKextCreateRequest(kKextRequestPredicateRequestResource, 12615 requestDict); 12616 if (result != kOSReturnSuccess) { 12617 goto finish; 12618 } 12619 12620 kextIdentifier = OSString::withCString(kextIdentifierCString); 12621 resourceName = OSString::withCString(resourceNameCString); 12622 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 12623 8 * sizeof(requestTag)); 12624 if (!kextIdentifier || 12625 !resourceName || 12626 !requestTagNum || 12627 !_OSKextSetRequestArgument(requestDict.get(), 12628 kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) || 12629 !_OSKextSetRequestArgument(requestDict.get(), 12630 kKextRequestArgumentNameKey, resourceName.get()) || 12631 !_OSKextSetRequestArgument(requestDict.get(), 12632 kKextRequestArgumentRequestTagKey, requestTagNum.get())) { 12633 result = kOSKextReturnNoMemory; 12634 goto finish; 12635 } 12636 12637 callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection()); 12638 if (!callbackRecord) { 12639 result = kOSKextReturnNoMemory; 12640 goto finish; 12641 } 12642 // we validate callback address at call time 12643 callbackWrapper = OSValueObjectWithValue(callback); 12644 if (context) { 12645 contextWrapper = OSValueObjectWithValue(context); 12646 } 12647 if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(), 12648 kKextRequestArgumentCallbackKey, callbackWrapper.get())) { 12649 result = kOSKextReturnNoMemory; 12650 goto finish; 12651 } 12652 12653 if (context) { 12654 if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(), 12655 kKextRequestArgumentContextKey, contextWrapper.get())) { 12656 result = kOSKextReturnNoMemory; 12657 goto finish; 12658 } 12659 } 12660 12661 /* Only post the requests after all the other potential failure points 12662 * have been passed. 12663 */ 12664 if (!sKernelRequests->setObject(requestDict.get()) || 12665 !sRequestCallbackRecords->setObject(callbackRecord.get())) { 12666 result = kOSKextReturnNoMemory; 12667 goto finish; 12668 } 12669 12670 OSKext::pingIOKitDaemon(); 12671 12672 result = kOSReturnSuccess; 12673 if (requestTagOut) { 12674 *requestTagOut = requestTag; 12675 } 12676 12677 finish: 12678 12679 /* If we didn't succeed, yank the request & callback 12680 * from their holding arrays. 12681 */ 12682 if (result != kOSReturnSuccess) { 12683 unsigned int index; 12684 12685 index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0); 12686 if (index != (unsigned int)-1) { 12687 sKernelRequests->removeObject(index); 12688 } 12689 index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0); 12690 if (index != (unsigned int)-1) { 12691 sRequestCallbackRecords->removeObject(index); 12692 } 12693 } 12694 12695 OSKext::considerUnloads(/* rescheduleOnly? */ true); 12696 12697 IORecursiveLockUnlock(sKextLock); 12698 12699 return result; 12700 } 12701 12702 OSReturn 12703 OSKext::requestDaemonLaunch( 12704 OSString *kextIdentifier, 12705 OSString *serverName, 12706 OSNumber *serverTag, 12707 OSBoolean *reslide, 12708 IOUserServerCheckInToken * checkInToken, 12709 OSData *serverDUI) 12710 { 12711 OSReturn result = kOSReturnError; 12712 OSSharedPtr<OSDictionary> requestDict; 12713 unsigned int size = 0; 12714 const char *dextUniqueIDCString = NULL; 12715 12716 if (!kextIdentifier || !serverName || !serverTag || !checkInToken) { 12717 return kOSKextReturnInvalidArgument; 12718 } 12719 12720 if (serverDUI != NULL) { 12721 dextUniqueIDCString = getDextUniqueIDCString(serverDUI, &size); 12722 } 12723 12724 IORecursiveLockLock(sKextLock); 12725 12726 OSKextLog(/* kext */ NULL, 12727 kOSKextLogDebugLevel | 12728 kOSKextLogGeneralFlag, 12729 "Requesting daemon launch for %s %s with serverName %s and tag %llu%s", 12730 kextIdentifier->getCStringNoCopy(), 12731 (dextUniqueIDCString != NULL)?dextUniqueIDCString:"", 12732 serverName->getCStringNoCopy(), 12733 serverTag->unsigned64BitValue(), 12734 reslide == kOSBooleanTrue ? " with reslid shared cache" : "" 12735 ); 12736 12737 result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict); 12738 if (result != kOSReturnSuccess) { 12739 goto finish; 12740 } 12741 12742 if (!_OSKextSetRequestArgument(requestDict.get(), 12743 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) || 12744 !_OSKextSetRequestArgument(requestDict.get(), 12745 kKextRequestArgumentDriverExtensionServerName, serverName) || 12746 !_OSKextSetRequestArgument(requestDict.get(), 12747 kKextRequestArgumentDriverExtensionServerTag, serverTag) || 12748 !_OSKextSetRequestArgument(requestDict.get(), 12749 kKextRequestArgumentDriverExtensionReslideSharedCache, reslide) || 12750 !_OSKextSetRequestArgument(requestDict.get(), 12751 kKextRequestArgumentCheckInToken, checkInToken)) { 12752 result = kOSKextReturnNoMemory; 12753 goto finish; 12754 } 12755 12756 if (serverDUI) { 12757 if (!_OSKextSetRequestArgument(requestDict.get(), 12758 kOSBundleDextUniqueIdentifierKey, serverDUI)) { 12759 result = kOSKextReturnNoMemory; 12760 goto finish; 12761 } 12762 } 12763 12764 /* Only post the requests after all the other potential failure points 12765 * have been passed. 12766 */ 12767 if (!sKernelRequests->setObject(requestDict.get())) { 12768 result = kOSKextReturnNoMemory; 12769 goto finish; 12770 } 12771 OSKext::pingIOKitDaemon(); 12772 12773 result = kOSReturnSuccess; 12774 finish: 12775 IORecursiveLockUnlock(sKextLock); 12776 if (dextUniqueIDCString) { 12777 kfree_data(dextUniqueIDCString, size); 12778 } 12779 return result; 12780 } 12781 12782 OSReturn 12783 OSKext::notifyDextUpgrade( 12784 OSString *kextIdentifier, 12785 OSData *dextUniqueIdentifier) 12786 { 12787 OSReturn result = kOSReturnError; 12788 OSSharedPtr<OSDictionary> requestDict; 12789 unsigned int size = 0; 12790 const char *dextUniqueIDCString = getDextUniqueIDCString(dextUniqueIdentifier, &size); 12791 assert(dextUniqueIDCString != NULL); 12792 12793 IORecursiveLockLock(sKextLock); 12794 12795 OSKextLog(NULL, 12796 kOSKextLogDebugLevel | 12797 kOSKextLogGeneralFlag, 12798 "Notifying of dext upgrade for %s with UniqueID %s", 12799 kextIdentifier->getCStringNoCopy(), dextUniqueIDCString); 12800 12801 result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonUpgradeNotification, requestDict); 12802 if (result != kOSReturnSuccess) { 12803 goto finish; 12804 } 12805 12806 if (!_OSKextSetRequestArgument(requestDict.get(), 12807 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) || 12808 !_OSKextSetRequestArgument(requestDict.get(), 12809 kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) { 12810 result = kOSKextReturnNoMemory; 12811 goto finish; 12812 } 12813 12814 /* Only post the requests after all the other potential failure points 12815 * have been passed. 12816 */ 12817 if (!sKernelRequests->setObject(requestDict.get())) { 12818 result = kOSKextReturnNoMemory; 12819 goto finish; 12820 } 12821 OSKext::pingIOKitDaemon(); 12822 12823 result = kOSReturnSuccess; 12824 finish: 12825 IORecursiveLockUnlock(sKextLock); 12826 12827 if (dextUniqueIDCString != NULL) { 12828 kfree_data(dextUniqueIDCString, size); 12829 } 12830 return result; 12831 } 12832 12833 /********************************************************************* 12834 * Assumes sKextLock is held. 12835 *********************************************************************/ 12836 /* static */ 12837 OSReturn 12838 OSKext::dequeueCallbackForRequestTag( 12839 OSKextRequestTag requestTag, 12840 OSSharedPtr<OSDictionary> &callbackRecordOut) 12841 { 12842 OSDictionary * callbackRecordOutRaw = NULL; 12843 OSReturn result; 12844 12845 result = dequeueCallbackForRequestTag(requestTag, 12846 &callbackRecordOutRaw); 12847 12848 if (kOSReturnSuccess == result) { 12849 callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain); 12850 } 12851 12852 return result; 12853 } 12854 OSReturn 12855 OSKext::dequeueCallbackForRequestTag( 12856 OSKextRequestTag requestTag, 12857 OSDictionary ** callbackRecordOut) 12858 { 12859 OSReturn result = kOSReturnError; 12860 OSSharedPtr<OSNumber> requestTagNum; 12861 12862 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 12863 8 * sizeof(requestTag)); 12864 if (!requestTagNum) { 12865 goto finish; 12866 } 12867 12868 result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(), 12869 callbackRecordOut); 12870 12871 finish: 12872 return result; 12873 } 12874 12875 /********************************************************************* 12876 * Assumes sKextLock is held. 12877 *********************************************************************/ 12878 /* static */ 12879 OSReturn 12880 OSKext::dequeueCallbackForRequestTag( 12881 OSNumber * requestTagNum, 12882 OSSharedPtr<OSDictionary> &callbackRecordOut) 12883 { 12884 OSDictionary * callbackRecordOutRaw = NULL; 12885 OSReturn result; 12886 12887 result = dequeueCallbackForRequestTag(requestTagNum, 12888 &callbackRecordOutRaw); 12889 12890 if (kOSReturnSuccess == result) { 12891 callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain); 12892 } 12893 12894 return result; 12895 } 12896 OSReturn 12897 OSKext::dequeueCallbackForRequestTag( 12898 OSNumber * requestTagNum, 12899 OSDictionary ** callbackRecordOut) 12900 { 12901 OSReturn result = kOSKextReturnInvalidArgument; 12902 OSDictionary * callbackRecord = NULL; // retain if matched! 12903 OSNumber * callbackTagNum = NULL; // do not release 12904 unsigned int count, i; 12905 12906 result = kOSReturnError; 12907 count = sRequestCallbackRecords->getCount(); 12908 for (i = 0; i < count; i++) { 12909 callbackRecord = OSDynamicCast(OSDictionary, 12910 sRequestCallbackRecords->getObject(i)); 12911 if (!callbackRecord) { 12912 goto finish; 12913 } 12914 12915 /* If we don't find a tag, we basically have a leak here. Maybe 12916 * we should just remove it. 12917 */ 12918 callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument( 12919 callbackRecord, kKextRequestArgumentRequestTagKey)); 12920 if (!callbackTagNum) { 12921 goto finish; 12922 } 12923 12924 /* We could be even more paranoid and check that all the incoming 12925 * args match what's in the callback record. 12926 */ 12927 if (callbackTagNum->isEqualTo(requestTagNum)) { 12928 if (callbackRecordOut) { 12929 *callbackRecordOut = callbackRecord; 12930 callbackRecord->retain(); 12931 } 12932 sRequestCallbackRecords->removeObject(i); 12933 result = kOSReturnSuccess; 12934 goto finish; 12935 } 12936 } 12937 result = kOSKextReturnNotFound; 12938 12939 finish: 12940 return result; 12941 } 12942 12943 12944 /********************************************************************* 12945 * Busy timeout triage 12946 *********************************************************************/ 12947 /* static */ 12948 bool 12949 OSKext::pendingIOKitDaemonRequests(void) 12950 { 12951 return sRequestCallbackRecords && sRequestCallbackRecords->getCount(); 12952 } 12953 12954 /********************************************************************* 12955 * Acquires and releases sKextLock 12956 * 12957 * This function is designed to be called by kernelmanagerd and driverkitd 12958 * and it gathers all codeless kext and dext personalities, and then attempts 12959 * to map a System (pageable) KC and an Auxiliary (aux) KC. 12960 * 12961 * The pageable and aux KC can be loaded only once at boot time. 12962 * Even if the pageable or aux KC fail to load - this function will 12963 * not allow a new pageable or aux KC to be installed by subsequent calls. 12964 * This is done to avoid security issues where userspace has been compromised 12965 * or the pageable kc has been tampered with and the attacker 12966 * attempts to re-load a malicious variant. 12967 * However dexts can be dynamically loaded, so this function can be used 12968 * to request the installation of a new set of dexts even after boot time. 12969 * 12970 * 12971 * 12972 * Return: if a KC fails to load the return value will contain: 12973 * kOSKextReturnKCLoadFailure. If the pageable KC fails, 12974 * the return value will contain kOSKextReturnKCLoadFailureSystemKC. 12975 * Similarly, if the aux kc load fails, the return value will 12976 * contain kOSKextReturnKCLoadFailureAuxKC. The two values 12977 * compose with each other and with kOSKextReturnKCLoadFailure. 12978 *********************************************************************/ 12979 /* static */ 12980 OSReturn 12981 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused) 12982 { 12983 static bool daemon_ready = false; 12984 12985 OSReturn ret = kOSKextReturnInvalidArgument; 12986 OSReturn kcerr = 0; 12987 bool start_matching = false; 12988 12989 bool allow_fileset_load = !daemon_ready; 12990 #if !(defined(__x86_64__) || defined(__i386__)) 12991 /* never allow KCs full of kexts on non-x86 machines */ 12992 allow_fileset_load = false; 12993 #endif 12994 12995 /* 12996 * Change with 70582300 12997 */ 12998 #if 0 || !defined(VM_MAPPED_KEXTS) 12999 /* 13000 * On platforms that don't support the SystemKC or a file-backed 13001 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter 13002 * needs to be queried before we load any codeless kexts or release 13003 * any 3rd party kexts to run. On platforms that support a file-backed 13004 * AuxKC, this process is done via the kext audit mechanism. 13005 */ 13006 13007 printf("KextLog: waiting for kext receipt to be queried.\n"); 13008 while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) { 13009 IOSleep(30); 13010 } 13011 #endif /* !VM_MAPPED_KEXTS */ 13012 13013 /* 13014 * Get the args from the request. Right now we need the file 13015 * name for the pageable and the aux kext collection file sets. 13016 */ 13017 OSDictionary * requestArgs = NULL; // do not release 13018 OSString * pageable_filepath = NULL; // do not release 13019 OSString * aux_filepath = NULL; // do not release 13020 OSArray * codeless_kexts = NULL; // do not release 13021 13022 kernel_mach_header_t *akc_mh = NULL; 13023 13024 requestArgs = OSDynamicCast(OSDictionary, 13025 requestDict->getObject(kKextRequestArgumentsKey)); 13026 13027 if (requestArgs == NULL) { 13028 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13029 "KextLog: No arguments in plist for loading fileset kext\n"); 13030 printf("KextLog: No arguments in plist for loading fileset kext\n"); 13031 return ret; 13032 } 13033 13034 ret = kOSKextReturnDisabled; 13035 13036 IORecursiveLockLock(sKextLock); 13037 13038 if (!sLoadEnabled) { 13039 OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag, 13040 "KextLog: Kext loading is disabled (attempt to load KCs)."); 13041 IORecursiveLockUnlock(sKextLock); 13042 return ret; 13043 } 13044 13045 pageable_filepath = OSDynamicCast(OSString, 13046 requestArgs->getObject(kKextRequestArgumentPageableKCFilename)); 13047 13048 if (allow_fileset_load && pageable_filepath != NULL) { 13049 printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy()); 13050 13051 ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable); 13052 if (ret) { 13053 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13054 "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret); 13055 13056 printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret); 13057 ret = kOSKextReturnKCLoadFailure; 13058 kcerr |= kOSKextReturnKCLoadFailureSystemKC; 13059 goto try_auxkc; 13060 } 13061 /* 13062 * Even if the AuxKC fails to load, we still want to send 13063 * the System KC personalities to the catalog for matching 13064 */ 13065 start_matching = true; 13066 } else if (pageable_filepath != NULL) { 13067 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 13068 "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy()); 13069 ret = kOSKextReturnUnsupported; 13070 } 13071 13072 try_auxkc: 13073 akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary); 13074 if (akc_mh) { 13075 /* 13076 * If we try to load a deferred AuxKC, then don't ever attempt 13077 * a filesystem map of a file 13078 */ 13079 allow_fileset_load = false; 13080 13081 /* 13082 * This function is only called once per boot, so we haven't 13083 * yet loaded an AuxKC. If we have registered the AuxKC mach 13084 * header, that means that the kext collection has been placed 13085 * in memory for us by the booter, and is waiting for us to 13086 * process it. Grab the deferred XML plist of info 13087 * dictionaries and add all the kexts. 13088 */ 13089 OSSharedPtr<OSObject> parsedXML; 13090 OSSharedPtr<OSData> loaded_kcUUID; 13091 OSDictionary *infoDict; 13092 parsedXML = consumeDeferredKextCollection(KCKindAuxiliary); 13093 infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 13094 #if !defined(VM_MAPPED_KEXTS) 13095 /* 13096 * On platforms where we don't dynamically wire-down / page-in 13097 * kext memory, we need to maintain the invariant that if the 13098 * AuxKC in memory does not contain a kext receipt, then we 13099 * should not load any of the kexts. 13100 */ 13101 size_t receipt_sz = 0; 13102 if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) { 13103 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13104 "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt"); 13105 ret = kOSKextReturnKCLoadFailure; 13106 goto try_codeless; 13107 } 13108 #endif 13109 if (infoDict) { 13110 bool added; 13111 printf("KextLog: Adding kexts from in-memory AuxKC\n"); 13112 added = OSKext::addKextsFromKextCollection(akc_mh, infoDict, 13113 kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary); 13114 if (!loaded_kcUUID) { 13115 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13116 "KextLog: WARNING: did not find UUID in deferred Aux KC!"); 13117 } else if (!added) { 13118 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13119 "KextLog: WARNING: Failed to load AuxKC from memory."); 13120 } 13121 /* only return success if the pageable load (above) was successful */ 13122 if (ret != kOSKextReturnKCLoadFailure) { 13123 ret = kOSReturnSuccess; 13124 } 13125 /* the registration of the AuxKC parsed out the KC's UUID already */ 13126 } else { 13127 if (daemon_ready) { 13128 /* 13129 * Complain, but don't return an error if this isn't the first time the 13130 * IOKit daemon is checking in. If the daemon ever restarts, we will 13131 * hit this case because we've already consumed the deferred personalities. 13132 * We return success here so that a call to this function from a restarted 13133 * daemon with no codeless kexts will succeed. 13134 */ 13135 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 13136 "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart"); 13137 if (ret != kOSKextReturnKCLoadFailure) { 13138 ret = kOSReturnSuccess; 13139 } 13140 } else { 13141 /* this is a real error case */ 13142 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag, 13143 "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary"); 13144 printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n"); 13145 ret = kOSKextReturnKCLoadFailure; 13146 kcerr |= kOSKextReturnKCLoadFailureAuxKC; 13147 } 13148 } 13149 } 13150 13151 aux_filepath = OSDynamicCast(OSString, 13152 requestArgs->getObject(kKextRequestArgumentAuxKCFilename)); 13153 if (allow_fileset_load && aux_filepath != NULL) { 13154 printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy()); 13155 13156 ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary); 13157 if (ret) { 13158 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13159 "KextLog: loadKCFileSet for Aux KC returned %d\n", ret); 13160 13161 printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret); 13162 ret = kOSKextReturnKCLoadFailure; 13163 kcerr |= kOSKextReturnKCLoadFailureAuxKC; 13164 goto try_codeless; 13165 } 13166 start_matching = true; 13167 } else if (aux_filepath != NULL) { 13168 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 13169 "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy()); 13170 if (ret != kOSKextReturnKCLoadFailure) { 13171 ret = kOSKextReturnUnsupported; 13172 } 13173 } 13174 13175 try_codeless: 13176 /* 13177 * Load codeless kexts last so that there is no possibilty of a 13178 * codeless kext bundle ID preventing a kext in the system KC from 13179 * loading 13180 */ 13181 codeless_kexts = OSDynamicCast(OSArray, 13182 requestArgs->getObject(kKextRequestArgumentCodelessPersonalities)); 13183 if (codeless_kexts != NULL) { 13184 uint32_t count = codeless_kexts->getCount(); 13185 OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13186 "KextLog: loading %d codeless kexts/dexts", count); 13187 for (uint32_t i = 0; i < count; i++) { 13188 OSDictionary *infoDict; 13189 infoDict = OSDynamicCast(OSDictionary, 13190 codeless_kexts->getObject(i)); 13191 if (!infoDict) { 13192 continue; 13193 } 13194 // instantiate a new kext, and don't hold a reference 13195 // (the kext subsystem will hold one implicitly) 13196 OSKext::withCodelessInfo(infoDict, NULL); 13197 } 13198 /* ignore errors that are not KC load failures */ 13199 if (ret != kOSKextReturnKCLoadFailure) { 13200 ret = kOSReturnSuccess; 13201 } 13202 start_matching = true; 13203 } 13204 13205 /* send personalities to the IOCatalog once */ 13206 if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) { 13207 OSKext::sendAllKextPersonalitiesToCatalog(true); 13208 /* 13209 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark 13210 * things as active and start all the delayed matching: the 13211 * dext and codeless kext personalities should have all been 13212 * delivered via this one call. 13213 */ 13214 if (!daemon_ready) { 13215 OSKext::setIOKitDaemonActive(); 13216 OSKext::setDeferredLoadSucceeded(TRUE); 13217 IOService::iokitDaemonLaunched(); 13218 } 13219 if (sOSKextWasResetAfterUserspaceReboot) { 13220 sOSKextWasResetAfterUserspaceReboot = false; 13221 OSKext::setIOKitDaemonActive(); 13222 IOService::startDeferredMatches(); 13223 } 13224 } 13225 13226 if (ret == kOSKextReturnKCLoadFailure) { 13227 ret |= kcerr; 13228 } 13229 13230 /* 13231 * Only allow this function to attempt to load the pageable and 13232 * aux KCs once per boot. 13233 */ 13234 daemon_ready = true; 13235 13236 IORecursiveLockUnlock(sKextLock); 13237 13238 return ret; 13239 } 13240 13241 OSReturn 13242 OSKext::resetMutableSegments(void) 13243 { 13244 kernel_segment_command_t *seg = NULL; 13245 kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address; 13246 u_int index = 0; 13247 OSKextSavedMutableSegment *savedSegment = NULL; 13248 uintptr_t kext_slide = PE_get_kc_slide(kc_type); 13249 OSReturn err; 13250 13251 if (!savedMutableSegments) { 13252 OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag, 13253 "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString()); 13254 err = kOSKextReturnInternalError; 13255 goto finish; 13256 } 13257 13258 for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) { 13259 if (!segmentIsMutable(seg)) { 13260 continue; 13261 } 13262 uint64_t unslid_vmaddr = seg->vmaddr - kext_slide; 13263 uint64_t vmsize = seg->vmsize; 13264 err = kOSKextReturnInternalError; 13265 for (index = 0; index < savedMutableSegments->getCount(); index++) { 13266 savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index)); 13267 assert(savedSegment); 13268 if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) { 13269 OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag, 13270 "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1); 13271 err = savedSegment->restoreContents(seg); 13272 if (err != kOSReturnSuccess) { 13273 panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 13274 } 13275 } 13276 } 13277 if (err != kOSReturnSuccess) { 13278 panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 13279 } 13280 } 13281 err = kOSReturnSuccess; 13282 finish: 13283 return err; 13284 } 13285 13286 13287 /********************************************************************* 13288 * Assumes sKextLock is held. 13289 *********************************************************************/ 13290 /* static */ 13291 OSReturn 13292 OSKext::loadKCFileSet( 13293 const char *filepath, 13294 kc_kind_t type) 13295 { 13296 #if VM_MAPPED_KEXTS 13297 /* we only need to load filesets on systems that support VM_MAPPED kexts */ 13298 OSReturn err; 13299 struct vnode *vp = NULL; 13300 void *fileset_control; 13301 off_t fsize; 13302 bool pageable = (type == KCKindPageable); 13303 13304 if ((pageable && pageableKCloaded) || 13305 (!pageable && auxKCloaded)) { 13306 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13307 "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux")); 13308 13309 return kOSKextReturnInvalidArgument; 13310 } 13311 13312 /* Do not allow AuxKC to load if Pageable KC is not loaded */ 13313 if (!pageable && !pageableKCloaded) { 13314 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13315 "Trying to load the Aux KC without loading the Pageable KC"); 13316 return kOSKextReturnInvalidArgument; 13317 } 13318 13319 fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize); 13320 13321 if (fileset_control == NULL) { 13322 printf("Could not get memory control object for file %s", filepath); 13323 13324 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13325 "Could not get memory control object for file %s", filepath); 13326 return kOSKextReturnInvalidArgument; 13327 } 13328 if (vp == NULL) { 13329 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13330 "Could not find vnode for file %s", filepath); 13331 return kOSKextReturnInvalidArgument; 13332 } 13333 13334 kernel_mach_header_t *mh = NULL; 13335 uintptr_t slide = 0; 13336 13337 #if CONFIG_CSR 13338 /* 13339 * When SIP is enabled, the KC we map must be SIP-protected 13340 */ 13341 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) { 13342 struct vnode_attr va; 13343 int error; 13344 VATTR_INIT(&va); 13345 VATTR_WANTED(&va, va_flags); 13346 error = vnode_getattr(vp, &va, vfs_context_current()); 13347 if (error) { 13348 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13349 "vnode_getattr(%s) failed (error=%d)", filepath, error); 13350 err = kOSKextReturnInternalError; 13351 goto finish; 13352 } 13353 if (!(va.va_flags & SF_RESTRICTED)) { 13354 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13355 "Path to KC '%s' is not SIP-protected", filepath); 13356 err = kOSKextReturnInvalidArgument; 13357 goto finish; 13358 } 13359 } 13360 #endif 13361 13362 err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL); 13363 if (err) { 13364 printf("KextLog: mapKCFileSet returned %d\n", err); 13365 13366 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13367 "mapKCFileSet returned %d\n", err); 13368 13369 err = kOSKextReturnInvalidArgument; 13370 } 13371 13372 #if CONFIG_CSR 13373 finish: 13374 #endif 13375 /* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */ 13376 assert(vp != NULL); 13377 if (err == kOSReturnSuccess) { 13378 PE_set_kc_vp(type, vp); 13379 if (pageable) { 13380 pageableKCloaded = true; 13381 } else { 13382 auxKCloaded = true; 13383 } 13384 } else { 13385 vnode_put(vp); 13386 } 13387 13388 return err; 13389 #else 13390 (void)filepath; 13391 (void)type; 13392 return kOSKextReturnUnsupported; 13393 #endif // VM_MAPPED_KEXTS 13394 } 13395 13396 #if defined(__x86_64__) || defined(__i386__) 13397 /********************************************************************* 13398 * Assumes sKextLock is held. 13399 *********************************************************************/ 13400 /* static */ 13401 OSReturn 13402 OSKext::mapKCFileSet( 13403 void *control, 13404 vm_size_t fsize, 13405 kernel_mach_header_t **mhp, 13406 off_t file_offset, 13407 uintptr_t *slidep, 13408 bool pageable, 13409 void *map_entry_list) 13410 { 13411 bool fileset_load = false; 13412 kern_return_t ret; 13413 OSReturn err; 13414 kernel_section_t *infoPlistSection = NULL; 13415 OSDictionary *infoDict = NULL; 13416 13417 OSSharedPtr<OSObject> parsedXML; 13418 OSSharedPtr<OSString> errorString; 13419 OSSharedPtr<OSData> loaded_kcUUID; 13420 13421 /* Check if initial load for file set */ 13422 if (*mhp == NULL) { 13423 fileset_load = true; 13424 13425 /* Get a page aligned address from kext map to map the file */ 13426 vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize); 13427 if (pagealigned_addr == 0) { 13428 return kOSKextReturnNoMemory; 13429 } 13430 13431 *mhp = (kernel_mach_header_t *)pagealigned_addr; 13432 13433 /* Allocate memory for bailout mechanism */ 13434 map_entry_list = allocate_kcfileset_map_entry_list(); 13435 if (map_entry_list == NULL) { 13436 return kOSKextReturnNoMemory; 13437 } 13438 } 13439 13440 uintptr_t *slideptr = fileset_load ? slidep : NULL; 13441 err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list); 13442 /* mhp and slideptr are updated by mapKCTextSegment */ 13443 if (err) { 13444 if (fileset_load) { 13445 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13446 } 13447 return err; 13448 } 13449 13450 /* Initialize the kc header globals */ 13451 if (fileset_load) { 13452 if (pageable) { 13453 PE_set_kc_header(KCKindPageable, *mhp, *slidep); 13454 } else { 13455 PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep); 13456 } 13457 } 13458 13459 /* Iterate through all the segments and map necessary segments */ 13460 struct load_command *lcp = (struct load_command *) (*mhp + 1); 13461 for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) { 13462 vm_map_offset_t start; 13463 kernel_mach_header_t *k_mh = NULL; 13464 kernel_segment_command_t * seg = NULL; 13465 struct fileset_entry_command *fse = NULL; 13466 13467 if (lcp->cmd == LC_SEGMENT_KERNEL) { 13468 seg = (kernel_segment_command_t *)lcp; 13469 start = ((uintptr_t)(seg->vmaddr)) + *slidep; 13470 } else if (lcp->cmd == LC_FILESET_ENTRY) { 13471 fse = (struct fileset_entry_command *)lcp; 13472 k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep); 13473 13474 /* Map the segments of the mach-o binary */ 13475 err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list); 13476 if (err) { 13477 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13478 return kOSKextReturnInvalidArgument; 13479 } 13480 continue; 13481 } else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) { 13482 /* Check if the Aux KC is built pageable style */ 13483 if (!pageable && !fileset_load && !auxKCloaded) { 13484 resetAuxKCSegmentOnUnload = true; 13485 } 13486 continue; 13487 } else { 13488 continue; 13489 } 13490 13491 if (fileset_load) { 13492 if (seg->vmsize == 0) { 13493 continue; 13494 } 13495 13496 /* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */ 13497 if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 && 13498 strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 && 13499 strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 && 13500 strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) { 13501 continue; 13502 } 13503 } else { 13504 if (seg->vmsize == 0) { 13505 continue; 13506 } 13507 13508 /* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */ 13509 if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 || 13510 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 || 13511 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) { 13512 continue; 13513 } 13514 } 13515 13516 ret = vm_map_kcfileset_segment( 13517 &start, seg->vmsize, 13518 (memory_object_control_t)control, seg->fileoff, seg->maxprot); 13519 13520 if (ret != KERN_SUCCESS) { 13521 if (fileset_load) { 13522 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13523 } 13524 return kOSKextReturnInvalidArgument; 13525 } 13526 add_kcfileset_map_entry(map_entry_list, start, seg->vmsize); 13527 } 13528 13529 /* Return if regular mach-o */ 13530 if (!fileset_load) { 13531 return 0; 13532 } 13533 13534 /* 13535 * Fixup for the Pageable KC and the Aux KC is done by 13536 * i386_slide_kext_collection_mh_addrs, but it differs in 13537 * following ways: 13538 * 13539 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands. 13540 * The fixup of kext segments and kext load commands are done at kext 13541 * load time by calling i386_slide_individual_kext. 13542 * 13543 * AuxKC old style: Fixup all the segments and all the load commands. 13544 * 13545 * AuxKC pageable style: Same as the Pageable KC. 13546 */ 13547 bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false)); 13548 ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header); 13549 if (ret != KERN_SUCCESS) { 13550 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13551 return kOSKextReturnInvalidArgument; 13552 } 13553 13554 /* Get the prelink info dictionary */ 13555 infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection); 13556 parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString); 13557 if (parsedXML) { 13558 infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 13559 } 13560 13561 if (!infoDict) { 13562 const char *errorCString = "(unknown error)"; 13563 13564 if (errorString && errorString->getCStringNoCopy()) { 13565 errorCString = errorString->getCStringNoCopy(); 13566 } else if (parsedXML) { 13567 errorCString = "not a dictionary"; 13568 } 13569 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13570 "Error unserializing kext info plist section: %s.", errorCString); 13571 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13572 return kOSKextReturnInvalidArgument; 13573 } 13574 13575 /* Validate that the Kext Collection is prelinked to the loaded KC */ 13576 err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary); 13577 if (err) { 13578 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 13579 return kOSKextReturnInvalidArgument; 13580 } 13581 13582 /* Set Protection of Segments */ 13583 OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary); 13584 13585 OSKext::addKextsFromKextCollection(*mhp, 13586 infoDict, kPrelinkTextSegment, 13587 loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary); 13588 13589 /* Copy in the KC UUID */ 13590 if (!loaded_kcUUID) { 13591 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 13592 "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux"); 13593 } else if (pageable) { 13594 pageablekc_uuid_valid = TRUE; 13595 memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength()); 13596 uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string); 13597 } else { 13598 auxkc_uuid_valid = TRUE; 13599 memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength()); 13600 uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string); 13601 } 13602 13603 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable); 13604 13605 return 0; 13606 } 13607 13608 /********************************************************************* 13609 * Assumes sKextLock is held. 13610 *********************************************************************/ 13611 /* static */ 13612 OSReturn 13613 OSKext::mapKCTextSegment( 13614 void *control, 13615 kernel_mach_header_t **mhp, 13616 off_t file_offset, 13617 uintptr_t *slidep, 13618 void *map_entry_list) 13619 { 13620 kern_return_t ret; 13621 vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t), 13622 PAGE_MASK); 13623 vm_map_offset_t load_command_map_size = 0; 13624 kernel_mach_header_t *base_mh = *mhp; 13625 13626 /* Map the mach header at start of fileset for now (vmaddr = 0) */ 13627 ret = vm_map_kcfileset_segment( 13628 (vm_map_offset_t *)&base_mh, mach_header_map_size, 13629 (memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE)); 13630 13631 if (ret != KERN_SUCCESS) { 13632 printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret); 13633 13634 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13635 "Failed to map mach header of kc fileset with error %d", ret); 13636 return kOSKextReturnInvalidArgument; 13637 } 13638 13639 if (slidep) { 13640 /* Verify that it's an MH_FILESET */ 13641 if (base_mh->filetype != MH_FILESET) { 13642 printf("Kext Log: mapKCTextSegment mach header filetype" 13643 " is not an MH_FILESET, it is %x", base_mh->filetype); 13644 13645 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13646 "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype); 13647 13648 /* Unmap the mach header */ 13649 vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 13650 return kOSKextReturnInvalidArgument; 13651 } 13652 } 13653 13654 /* Map the remaining pages of load commands */ 13655 if (base_mh->sizeofcmds > mach_header_map_size) { 13656 vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size; 13657 load_command_map_size = base_mh->sizeofcmds - mach_header_map_size; 13658 13659 /* Map the load commands */ 13660 ret = vm_map_kcfileset_segment( 13661 &load_command_addr, load_command_map_size, 13662 (memory_object_control_t)control, file_offset + mach_header_map_size, 13663 (VM_PROT_READ | VM_PROT_WRITE)); 13664 13665 if (ret != KERN_SUCCESS) { 13666 printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret); 13667 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13668 "Failed to map load commands of kc fileset with error %d", ret); 13669 13670 /* Unmap the mach header */ 13671 vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 13672 return kOSKextReturnInvalidArgument; 13673 } 13674 } 13675 13676 kernel_segment_command_t *text_seg; 13677 text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT); 13678 13679 /* Calculate the slide and vm addr of mach header */ 13680 if (slidep) { 13681 *mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr); 13682 *slidep = ((uintptr_t)*mhp) - text_seg->vmaddr; 13683 } 13684 13685 /* Cache the text segment size and file offset before unmapping */ 13686 vm_map_offset_t text_segment_size = text_seg->vmsize; 13687 vm_object_offset_t text_segment_fileoff = text_seg->fileoff; 13688 vm_prot_t text_maxprot = text_seg->maxprot; 13689 13690 /* Unmap the first page and loadcommands and map the text segment */ 13691 ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 13692 assert(ret == KERN_SUCCESS); 13693 13694 if (load_command_map_size) { 13695 vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size; 13696 ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size); 13697 assert(ret == KERN_SUCCESS); 13698 } 13699 13700 /* Map the text segment at actual vm addr specified in fileset */ 13701 ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size, 13702 (memory_object_control_t)control, text_segment_fileoff, text_maxprot); 13703 if (ret != KERN_SUCCESS) { 13704 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 13705 "Failed to map Text segment of kc fileset with error %d", ret); 13706 return kOSKextReturnInvalidArgument; 13707 } 13708 13709 add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size); 13710 return 0; 13711 } 13712 13713 /********************************************************************* 13714 * Assumes sKextLock is held. 13715 *********************************************************************/ 13716 /* static */ 13717 OSReturn 13718 OSKext::protectKCFileSet( 13719 kernel_mach_header_t *mh, 13720 kc_kind_t type) 13721 { 13722 vm_map_t kext_map = g_kext_map; 13723 kernel_segment_command_t * seg = NULL; 13724 vm_map_offset_t start = 0; 13725 vm_map_offset_t end = 0; 13726 OSReturn ret = 0; 13727 13728 /* Set VM permissions */ 13729 seg = firstsegfromheader((kernel_mach_header_t *)mh); 13730 while (seg) { 13731 start = round_page(seg->vmaddr); 13732 end = trunc_page(seg->vmaddr + seg->vmsize); 13733 13734 /* 13735 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS 13736 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT 13737 * for the Aux KC as well. 13738 */ 13739 if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 || 13740 strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 || 13741 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 || 13742 (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload && 13743 strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) { 13744 ret = OSKext_protect((kernel_mach_header_t *)mh, 13745 kext_map, start, end, seg->maxprot, TRUE, type); 13746 if (ret != KERN_SUCCESS) { 13747 printf("OSKext protect failed with error %d", ret); 13748 return kOSKextReturnInvalidArgument; 13749 } 13750 13751 ret = OSKext_protect((kernel_mach_header_t *)mh, 13752 kext_map, start, end, seg->initprot, FALSE, type); 13753 if (ret != KERN_SUCCESS) { 13754 printf("OSKext protect failed with error %d", ret); 13755 return kOSKextReturnInvalidArgument; 13756 } 13757 13758 ret = OSKext_wire((kernel_mach_header_t *)mh, 13759 kext_map, start, end, seg->initprot, FALSE, type); 13760 if (ret != KERN_SUCCESS) { 13761 printf("OSKext wire failed with error %d", ret); 13762 return kOSKextReturnInvalidArgument; 13763 } 13764 } 13765 13766 seg = nextsegfromheader((kernel_mach_header_t *) mh, seg); 13767 } 13768 13769 return 0; 13770 } 13771 13772 /********************************************************************* 13773 * Assumes sKextLock is held. 13774 *********************************************************************/ 13775 /* static */ 13776 void 13777 OSKext::freeKCFileSetcontrol(void) 13778 { 13779 PE_reset_all_kc_vp(); 13780 } 13781 13782 /********************************************************************* 13783 * Assumes sKextLock is held. 13784 * 13785 * resetKCFileSetSegments: Kext start function expects data segment to 13786 * be pristine on every load, unmap the dirty segments on unload and 13787 * remap them from FileSet on disk. Remap all segments of kext since 13788 * fixups are done per kext and not per segment. 13789 *********************************************************************/ 13790 OSReturn 13791 OSKext::resetKCFileSetSegments(void) 13792 { 13793 kernel_segment_command_t *seg = NULL; 13794 kernel_segment_command_t *text_seg; 13795 uint32_t text_fileoff; 13796 kernel_mach_header_t *k_mh = NULL; 13797 uintptr_t slide; 13798 struct vnode *vp = NULL; 13799 void *fileset_control = NULL; 13800 bool pageable = (kc_type == KCKindPageable); 13801 OSReturn err; 13802 kern_return_t kr; 13803 13804 /* Check the vnode reference is still available */ 13805 vp = (struct vnode *)PE_get_kc_vp(kc_type); 13806 if (vp == NULL) { 13807 OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag, 13808 "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString()); 13809 return kOSKextReturnInternalError; 13810 } 13811 13812 fileset_control = ubc_getobject(vp, 0); 13813 assert(fileset_control != NULL); 13814 13815 OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag, 13816 "Kext %s resetting all segments", getIdentifierCString()); 13817 13818 k_mh = (kernel_mach_header_t *)kmod_info->address; 13819 text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT); 13820 text_fileoff = text_seg->fileoff; 13821 slide = PE_get_kc_slide(kc_type); 13822 13823 seg = firstsegfromheader((kernel_mach_header_t *)k_mh); 13824 while (seg) { 13825 if (seg->vmsize == 0) { 13826 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 13827 continue; 13828 } 13829 13830 /* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */ 13831 if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 || 13832 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 || 13833 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) { 13834 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 13835 continue; 13836 } 13837 13838 kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize); 13839 assert(kr == KERN_SUCCESS); 13840 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 13841 } 13842 13843 /* Unmap the text segment */ 13844 kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize); 13845 assert(kr == KERN_SUCCESS); 13846 13847 /* Map all the segments of the kext */ 13848 err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL); 13849 if (err) { 13850 panic("Could not reset segments of a mapped kext, error %x", err); 13851 } 13852 13853 /* Update address in kmod_info, since it has been reset */ 13854 if (kmod_info->address) { 13855 kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide); 13856 } 13857 13858 return 0; 13859 } 13860 13861 /********************************************************************* 13862 * Mechanism to track all segment mapping while mapping KC fileset. 13863 *********************************************************************/ 13864 13865 struct kcfileset_map_entry { 13866 vm_map_offset_t me_start; 13867 vm_map_offset_t me_size; 13868 }; 13869 13870 struct kcfileset_map_entry_list { 13871 int kme_list_count; 13872 int kme_list_index; 13873 struct kcfileset_map_entry kme_list[]; 13874 }; 13875 13876 #define KCFILESET_MAP_ENTRY_MAX (16380) 13877 13878 static void * 13879 allocate_kcfileset_map_entry_list(void) 13880 { 13881 struct kcfileset_map_entry_list *entry_list; 13882 13883 entry_list = kalloc_type(struct kcfileset_map_entry_list, 13884 struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO); 13885 13886 entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX; 13887 entry_list->kme_list_index = 0; 13888 return entry_list; 13889 } 13890 13891 static void 13892 add_kcfileset_map_entry( 13893 void *map_entry_list, 13894 vm_map_offset_t start, 13895 vm_map_offset_t size) 13896 { 13897 if (map_entry_list == NULL) { 13898 return; 13899 } 13900 13901 struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list; 13902 13903 if (entry_list->kme_list_index >= entry_list->kme_list_count) { 13904 panic("Ran out of map kc fileset list"); 13905 } 13906 13907 entry_list->kme_list[entry_list->kme_list_index].me_start = start; 13908 entry_list->kme_list[entry_list->kme_list_index].me_size = size; 13909 13910 entry_list->kme_list_index++; 13911 } 13912 13913 static void 13914 deallocate_kcfileset_map_entry_list_and_unmap_entries( 13915 void *map_entry_list, 13916 boolean_t unmap_entries, 13917 bool pageable) 13918 { 13919 struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list; 13920 13921 if (unmap_entries) { 13922 for (int i = 0; i < entry_list->kme_list_index; i++) { 13923 kern_return_t ret; 13924 ret = vm_unmap_kcfileset_segment( 13925 &(entry_list->kme_list[i].me_start), 13926 entry_list->kme_list[i].me_size); 13927 assert(ret == KERN_SUCCESS); 13928 } 13929 13930 PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary); 13931 } 13932 13933 kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry, 13934 KCFILESET_MAP_ENTRY_MAX, entry_list); 13935 } 13936 13937 /********************************************************************* 13938 * Mechanism to map kext segment. 13939 *********************************************************************/ 13940 13941 kern_return_t 13942 vm_map_kcfileset_segment( 13943 vm_map_offset_t *start, 13944 vm_map_offset_t size, 13945 void *control, 13946 vm_object_offset_t fileoffset, 13947 vm_prot_t max_prot) 13948 { 13949 vm_map_kernel_flags_t vmk_flags = { 13950 .vmf_fixed = true, 13951 .vmkf_no_copy_on_read = true, 13952 .vmkf_cs_enforcement_override = true, 13953 .vm_tag = VM_KERN_MEMORY_OSKEXT, 13954 }; 13955 kern_return_t ret; 13956 13957 /* Add Write to max prot to allow fixups */ 13958 max_prot = max_prot | VM_PROT_WRITE; 13959 13960 /* 13961 * Map the segments from file as COPY mappings to 13962 * make sure changes on disk to the file does not affect 13963 * mapped segments. 13964 */ 13965 ret = vm_map_enter_mem_object_control( 13966 g_kext_map, 13967 start, 13968 size, 13969 (mach_vm_offset_t)0, 13970 vmk_flags, 13971 (memory_object_control_t)control, 13972 fileoffset, 13973 TRUE, /* copy */ 13974 (VM_PROT_READ | VM_PROT_WRITE), max_prot, 13975 VM_INHERIT_NONE); 13976 13977 return ret; 13978 } 13979 13980 kern_return_t 13981 vm_unmap_kcfileset_segment( 13982 vm_map_offset_t *start, 13983 vm_map_offset_t size) 13984 { 13985 return mach_vm_deallocate(g_kext_map, *start, size); 13986 } 13987 13988 #endif //(__x86_64__) || defined(__i386__) 13989 13990 /********************************************************************* 13991 * Assumes sKextLock is held. 13992 *********************************************************************/ 13993 /* static */ 13994 OSReturn 13995 OSKext::validateKCFileSetUUID( 13996 OSDictionary *infoDict, 13997 kc_kind_t type) 13998 { 13999 OSReturn ret = kOSReturnSuccess; 14000 14001 if (!kernelcache_uuid_valid) { 14002 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 14003 "validateKCFileSetUUID Boot KC UUID was not set at boot."); 14004 ret = kOSKextReturnInvalidArgument; 14005 goto finish; 14006 } 14007 ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey); 14008 if (ret != 0) { 14009 goto finish; 14010 } 14011 14012 #if defined(__x86_64__) || defined(__i386__) 14013 /* Check if the Aux KC is prelinked to correct Pageable KC */ 14014 if (type == KCKindAuxiliary) { 14015 if (!pageablekc_uuid_valid) { 14016 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 14017 "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC."); 14018 ret = kOSKextReturnInvalidArgument; 14019 goto finish; 14020 } 14021 ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey); 14022 if (ret != 0) { 14023 goto finish; 14024 } 14025 } 14026 #endif //(__x86_64__) || defined(__i386__) 14027 14028 printf("KextLog: Collection UUID matches with loaded KCs.\n"); 14029 finish: 14030 return ret; 14031 } 14032 14033 /********************************************************************* 14034 * Assumes sKextLock is held. 14035 *********************************************************************/ 14036 /* static */ 14037 OSReturn 14038 OSKext::validateKCUUIDfromPrelinkInfo( 14039 uuid_t *loaded_kcuuid, 14040 kc_kind_t type, 14041 OSDictionary *infoDict, 14042 const char *uuid_key) 14043 { 14044 /* extract the UUID from the dictionary */ 14045 OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key)); 14046 if (!prelinkinfoKCUUID) { 14047 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 14048 "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key); 14049 return kOSKextReturnInvalidArgument; 14050 } 14051 14052 if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) { 14053 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 14054 "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength()); 14055 return kOSKextReturnInvalidArgument; 14056 } 14057 14058 if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), 14059 prelinkinfoKCUUID->getLength())) { 14060 OSData *info_dict_uuid; 14061 uuid_string_t info_dict_uuid_str = {}; 14062 uuid_string_t expected_uuid_str = {}; 14063 uuid_string_t given_uuid_str = {}; 14064 uuid_t given_uuid; 14065 14066 /* extract the KC UUID from the dictionary */ 14067 info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 14068 if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) { 14069 uuid_t tmp_uuid; 14070 memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid)); 14071 uuid_unparse(tmp_uuid, info_dict_uuid_str); 14072 } 14073 14074 uuid_unparse(*loaded_kcuuid, expected_uuid_str); 14075 memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid)); 14076 uuid_unparse(given_uuid, given_uuid_str); 14077 14078 printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key, 14079 given_uuid_str, expected_uuid_str, info_dict_uuid_str); 14080 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 14081 "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key, 14082 given_uuid_str, expected_uuid_str, info_dict_uuid_str); 14083 if (type == KCKindPageable && sPanicOnKCMismatch) { 14084 panic("System KC UUID %s linked against %s, but %s is loaded", 14085 info_dict_uuid_str, given_uuid_str, expected_uuid_str); 14086 } 14087 return kOSKextReturnInvalidArgument; 14088 } 14089 14090 return 0; 14091 } 14092 14093 /********************************************************************* 14094 * Assumes sKextLock is held. 14095 *********************************************************************/ 14096 /* static */ 14097 OSReturn 14098 OSKext::dispatchResource(OSDictionary * requestDict) 14099 { 14100 OSReturn result = kOSReturnError; 14101 OSSharedPtr<OSDictionary> callbackRecord; 14102 OSNumber * requestTag = NULL; // do not release 14103 OSNumber * requestResult = NULL; // do not release 14104 OSData * dataObj = NULL; // do not release 14105 uint32_t dataLength = 0; 14106 const void * dataPtr = NULL; // do not free 14107 OSValueObject<OSKextRequestResourceCallback> * callbackWrapper = nullptr; // do not release 14108 OSKextRequestResourceCallback callback = NULL; 14109 OSValueObject<void *> * contextWrapper = nullptr; // do not release 14110 void * context = NULL; // do not free 14111 OSSharedPtr<OSKext> callbackKext; 14112 14113 /* Get the args from the request. Right now we need the tag 14114 * to look up the callback record, and the result for invoking the callback. 14115 */ 14116 requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 14117 kKextRequestArgumentRequestTagKey)); 14118 requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 14119 kKextRequestArgumentResultKey)); 14120 if (!requestTag || !requestResult) { 14121 result = kOSKextReturnInvalidArgument; 14122 goto finish; 14123 } 14124 14125 /* Look for a callback record matching this request's tag. 14126 */ 14127 result = dequeueCallbackForRequestTag(requestTag, callbackRecord); 14128 if (result != kOSReturnSuccess) { 14129 goto finish; 14130 } 14131 14132 /***** 14133 * Get the context pointer of the callback record (if there is one). 14134 */ 14135 contextWrapper = OSDynamicCast(OSValueObject<void *>, _OSKextGetRequestArgument( 14136 callbackRecord.get(), kKextRequestArgumentContextKey)); 14137 context = _OSKextExtractPointer(contextWrapper); 14138 if (contextWrapper && !context) { 14139 goto finish; 14140 } 14141 14142 callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>, 14143 _OSKextGetRequestArgument(callbackRecord.get(), 14144 kKextRequestArgumentCallbackKey)); 14145 callback = _OSKextExtractCallbackPointer(callbackWrapper); 14146 if (!callback) { 14147 goto finish; 14148 } 14149 14150 /* Check for a data obj. We might not have one and that's ok, that means 14151 * we didn't find the requested resource, and we still have to tell the 14152 * caller that via the callback. 14153 */ 14154 dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict, 14155 kKextRequestArgumentValueKey)); 14156 if (dataObj) { 14157 dataPtr = dataObj->getBytesNoCopy(); 14158 dataLength = dataObj->getLength(); 14159 } 14160 14161 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 14162 if (!callbackKext) { 14163 OSKextLog(/* kext */ NULL, 14164 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 14165 "Can't invoke callback for resource request; "); 14166 goto finish; 14167 } 14168 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 14169 OSKextLog(/* kext */ NULL, 14170 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 14171 "Can't invoke kext resource callback; "); 14172 goto finish; 14173 } 14174 14175 (void)callback(requestTag->unsigned32BitValue(), 14176 (OSReturn)requestResult->unsigned32BitValue(), 14177 dataPtr, dataLength, context); 14178 14179 result = kOSReturnSuccess; 14180 14181 finish: 14182 return result; 14183 } 14184 14185 /********************************************************************* 14186 * Assumes sKextLock is held. 14187 *********************************************************************/ 14188 /* static */ 14189 OSReturn 14190 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict) 14191 { 14192 OSSharedPtr<OSDictionary> missingIDs; 14193 OSArray *bundleIDList = NULL; // do not release 14194 14195 bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 14196 requestDict, kKextRequestArgumentMissingBundleIDs)); 14197 if (!bundleIDList) { 14198 return kOSKextReturnInvalidArgument; 14199 } 14200 14201 missingIDs = OSDictionary::withCapacity(bundleIDList->getCount()); 14202 if (!missingIDs) { 14203 return kOSKextReturnNoMemory; 14204 } 14205 14206 uint32_t count, i; 14207 count = bundleIDList->getCount(); 14208 for (i = 0; i < count; i++) { 14209 OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i)); 14210 if (thisID) { 14211 missingIDs->setObject(thisID, kOSBooleanFalse); 14212 } 14213 } 14214 14215 sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain); 14216 14217 return kOSReturnSuccess; 14218 } 14219 14220 /********************************************************************* 14221 * Assumes sKextLock is held. 14222 *********************************************************************/ 14223 /* static */ 14224 OSReturn 14225 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict) 14226 { 14227 bool loadable = true; 14228 if (!kextIdentifier) { 14229 return kOSKextReturnInvalidArgument; 14230 } 14231 14232 if (requestDict) { 14233 OSBoolean *loadableArg; 14234 loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 14235 requestDict, kKextRequestArgumentBundleAvailability)); 14236 /* If we find the "Bundle Available" arg, and it's false, then 14237 * mark the bundle ID as _not_ loadable 14238 */ 14239 if (loadableArg && !loadableArg->getValue()) { 14240 loadable = false; 14241 } 14242 } 14243 14244 if (!sNonLoadableKextsByID) { 14245 sNonLoadableKextsByID = OSDictionary::withCapacity(1); 14246 } 14247 14248 sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable)); 14249 14250 OSKextLog(/* kext */ NULL, 14251 kOSKextLogBasicLevel | kOSKextLogIPCFlag, 14252 "KextLog: AuxKC bundle %s marked as %s", 14253 kextIdentifier->getCStringNoCopy(), 14254 (loadable ? "loadable" : "NOT loadable")); 14255 14256 return kOSReturnSuccess; 14257 } 14258 14259 /********************************************************************* 14260 *********************************************************************/ 14261 /* static */ 14262 void 14263 OSKext::invokeRequestCallback( 14264 OSDictionary * callbackRecord, 14265 OSReturn callbackResult) 14266 { 14267 OSString * predicate = _OSKextGetRequestPredicate(callbackRecord); 14268 OSSharedPtr<OSNumber> resultNum; 14269 14270 if (!predicate) { 14271 goto finish; 14272 } 14273 14274 resultNum = OSNumber::withNumber((long long unsigned int)callbackResult, 14275 8 * sizeof(callbackResult)); 14276 if (!resultNum) { 14277 goto finish; 14278 } 14279 14280 /* Insert the result into the callback record and dispatch it as if it 14281 * were the reply coming down from user space. 14282 */ 14283 _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey, 14284 resultNum.get()); 14285 14286 if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) { 14287 /* This removes the pending callback record. 14288 */ 14289 OSKext::dispatchResource(callbackRecord); 14290 } 14291 14292 finish: 14293 return; 14294 } 14295 14296 /********************************************************************* 14297 * Assumes sKextLock is held. 14298 *********************************************************************/ 14299 /* static */ 14300 OSReturn 14301 OSKext::cancelRequest( 14302 OSKextRequestTag requestTag, 14303 void ** contextOut) 14304 { 14305 OSReturn result = kOSKextReturnNoMemory; 14306 OSSharedPtr<OSDictionary> callbackRecord; 14307 OSValueObject<void *> * contextWrapper = nullptr; // do not release 14308 14309 IORecursiveLockLock(sKextLock); 14310 result = OSKext::dequeueCallbackForRequestTag(requestTag, 14311 callbackRecord); 14312 IORecursiveLockUnlock(sKextLock); 14313 14314 if (result == kOSReturnSuccess && contextOut) { 14315 contextWrapper = OSDynamicCast(OSValueObject<void *>, 14316 _OSKextGetRequestArgument(callbackRecord.get(), 14317 kKextRequestArgumentContextKey)); 14318 *contextOut = _OSKextExtractPointer(contextWrapper); 14319 } 14320 14321 return result; 14322 } 14323 14324 /********************************************************************* 14325 * Assumes sKextLock is held. 14326 *********************************************************************/ 14327 void 14328 OSKext::invokeOrCancelRequestCallbacks( 14329 OSReturn callbackResult, 14330 bool invokeFlag) 14331 { 14332 unsigned int count, i; 14333 14334 count = sRequestCallbackRecords->getCount(); 14335 if (!count) { 14336 goto finish; 14337 } 14338 14339 i = count - 1; 14340 do { 14341 OSDictionary * request = OSDynamicCast(OSDictionary, 14342 sRequestCallbackRecords->getObject(i)); 14343 14344 if (!request) { 14345 continue; 14346 } 14347 auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>, 14348 _OSKextGetRequestArgument(request, 14349 kKextRequestArgumentCallbackKey)); 14350 14351 if (!callbackWrapper) { 14352 sRequestCallbackRecords->removeObject(i); 14353 continue; 14354 } 14355 14356 vm_address_t callbackAddress = (vm_address_t) 14357 ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer); 14358 14359 if ((kmod_info->address <= callbackAddress) && 14360 (callbackAddress < (kmod_info->address + kmod_info->size))) { 14361 if (invokeFlag) { 14362 /* This removes the callback record. 14363 */ 14364 invokeRequestCallback(request, callbackResult); 14365 } else { 14366 sRequestCallbackRecords->removeObject(i); 14367 } 14368 } 14369 } while (i--); 14370 14371 finish: 14372 return; 14373 } 14374 14375 /********************************************************************* 14376 * Assumes sKextLock is held. 14377 *********************************************************************/ 14378 uint32_t 14379 OSKext::countRequestCallbacks(void) 14380 { 14381 uint32_t result = 0; 14382 unsigned int count, i; 14383 14384 count = sRequestCallbackRecords->getCount(); 14385 if (!count) { 14386 goto finish; 14387 } 14388 14389 i = count - 1; 14390 do { 14391 OSDictionary * request = OSDynamicCast(OSDictionary, 14392 sRequestCallbackRecords->getObject(i)); 14393 14394 if (!request) { 14395 continue; 14396 } 14397 auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>, 14398 _OSKextGetRequestArgument(request, 14399 kKextRequestArgumentCallbackKey)); 14400 14401 if (!callbackWrapper) { 14402 continue; 14403 } 14404 14405 vm_address_t callbackAddress = (vm_address_t) 14406 ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer); 14407 14408 if ((kmod_info->address <= callbackAddress) && 14409 (callbackAddress < (kmod_info->address + kmod_info->size))) { 14410 result++; 14411 } 14412 } while (i--); 14413 14414 finish: 14415 return result; 14416 } 14417 14418 /********************************************************************* 14419 *********************************************************************/ 14420 static OSReturn 14421 _OSKextCreateRequest( 14422 const char * predicate, 14423 OSSharedPtr<OSDictionary> & requestR) 14424 { 14425 OSReturn result = kOSKextReturnNoMemory; 14426 OSSharedPtr<OSDictionary> request; 14427 14428 request = OSDictionary::withCapacity(2); 14429 if (!request) { 14430 goto finish; 14431 } 14432 result = _OSDictionarySetCStringValue(request.get(), 14433 kKextRequestPredicateKey, predicate); 14434 if (result != kOSReturnSuccess) { 14435 goto finish; 14436 } 14437 result = kOSReturnSuccess; 14438 14439 finish: 14440 if (result == kOSReturnSuccess) { 14441 requestR = os::move(request); 14442 } 14443 14444 return result; 14445 } 14446 14447 /********************************************************************* 14448 *********************************************************************/ 14449 static OSString * 14450 _OSKextGetRequestPredicate(OSDictionary * requestDict) 14451 { 14452 return OSDynamicCast(OSString, 14453 requestDict->getObject(kKextRequestPredicateKey)); 14454 } 14455 14456 /********************************************************************* 14457 *********************************************************************/ 14458 static OSObject * 14459 _OSKextGetRequestArgument( 14460 OSDictionary * requestDict, 14461 const char * argName) 14462 { 14463 OSDictionary * args = OSDynamicCast(OSDictionary, 14464 requestDict->getObject(kKextRequestArgumentsKey)); 14465 if (args) { 14466 return args->getObject(argName); 14467 } 14468 return NULL; 14469 } 14470 14471 /********************************************************************* 14472 *********************************************************************/ 14473 static bool 14474 _OSKextSetRequestArgument( 14475 OSDictionary * requestDict, 14476 const char * argName, 14477 OSMetaClassBase * value) 14478 { 14479 OSDictionary * args = OSDynamicCast(OSDictionary, 14480 requestDict->getObject(kKextRequestArgumentsKey)); 14481 OSSharedPtr<OSDictionary> newArgs; 14482 if (!args) { 14483 newArgs = OSDictionary::withCapacity(2); 14484 args = newArgs.get(); 14485 if (!args) { 14486 goto finish; 14487 } 14488 requestDict->setObject(kKextRequestArgumentsKey, args); 14489 } 14490 if (args) { 14491 return args->setObject(argName, value); 14492 } 14493 finish: 14494 return false; 14495 } 14496 14497 /********************************************************************* 14498 *********************************************************************/ 14499 template <typename T> 14500 static T * 14501 _OSKextExtractPointer(OSValueObject<T *> * wrapper) 14502 { 14503 if (!wrapper) { 14504 return nullptr; 14505 } 14506 return wrapper->getRef(); 14507 } 14508 14509 /********************************************************************* 14510 *********************************************************************/ 14511 static OSKextRequestResourceCallback 14512 _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper) 14513 { 14514 if (!wrapper) { 14515 return nullptr; 14516 } 14517 return wrapper->getRef(); 14518 } 14519 14520 14521 /********************************************************************* 14522 *********************************************************************/ 14523 static OSReturn 14524 _OSDictionarySetCStringValue( 14525 OSDictionary * dict, 14526 const char * cKey, 14527 const char * cValue) 14528 { 14529 OSReturn result = kOSKextReturnNoMemory; 14530 OSSharedPtr<const OSSymbol> key; 14531 OSSharedPtr<OSString> value; 14532 14533 key = OSSymbol::withCString(cKey); 14534 value = OSString::withCString(cValue); 14535 if (!key || !value) { 14536 goto finish; 14537 } 14538 if (dict->setObject(key.get(), value.get())) { 14539 result = kOSReturnSuccess; 14540 } 14541 14542 finish: 14543 return result; 14544 } 14545 14546 /********************************************************************* 14547 *********************************************************************/ 14548 static bool 14549 _OSArrayContainsCString( 14550 OSArray * array, 14551 const char * cString) 14552 { 14553 bool result = false; 14554 OSSharedPtr<const OSSymbol> symbol; 14555 uint32_t count, i; 14556 14557 if (!array || !cString) { 14558 goto finish; 14559 } 14560 14561 symbol = OSSymbol::withCStringNoCopy(cString); 14562 if (!symbol) { 14563 goto finish; 14564 } 14565 14566 count = array->getCount(); 14567 for (i = 0; i < count; i++) { 14568 OSObject * thisObject = array->getObject(i); 14569 if (symbol->isEqualTo(thisObject)) { 14570 result = true; 14571 goto finish; 14572 } 14573 } 14574 14575 finish: 14576 return result; 14577 } 14578 14579 #if CONFIG_KXLD 14580 /********************************************************************* 14581 * We really only care about boot / system start up related kexts. 14582 * We return true if we're less than REBUILD_MAX_TIME since start up, 14583 * otherwise return false. 14584 *********************************************************************/ 14585 bool 14586 _OSKextInPrelinkRebuildWindow(void) 14587 { 14588 static bool outside_the_window = false; 14589 AbsoluteTime my_abstime; 14590 UInt64 my_ns; 14591 SInt32 my_secs; 14592 14593 if (outside_the_window) { 14594 return false; 14595 } 14596 clock_get_uptime(&my_abstime); 14597 absolutetime_to_nanoseconds(my_abstime, &my_ns); 14598 my_secs = (SInt32)(my_ns / NSEC_PER_SEC); 14599 if (my_secs > REBUILD_MAX_TIME) { 14600 outside_the_window = true; 14601 return false; 14602 } 14603 return true; 14604 } 14605 #endif /* CONFIG_KXLD */ 14606 14607 /********************************************************************* 14608 *********************************************************************/ 14609 bool 14610 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID ) 14611 { 14612 int unLoadedCount, i; 14613 bool result = false; 14614 14615 IORecursiveLockLock(sKextLock); 14616 14617 if (sUnloadedPrelinkedKexts == NULL) { 14618 goto finish; 14619 } 14620 unLoadedCount = sUnloadedPrelinkedKexts->getCount(); 14621 if (unLoadedCount == 0) { 14622 goto finish; 14623 } 14624 14625 for (i = 0; i < unLoadedCount; i++) { 14626 const OSSymbol * myBundleID; // do not release 14627 14628 myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i)); 14629 if (!myBundleID) { 14630 continue; 14631 } 14632 if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) { 14633 result = true; 14634 break; 14635 } 14636 } 14637 finish: 14638 IORecursiveLockUnlock(sKextLock); 14639 return result; 14640 } 14641 14642 #if PRAGMA_MARK 14643 #pragma mark Personalities (IOKit Drivers) 14644 #endif 14645 /********************************************************************* 14646 *********************************************************************/ 14647 /* static */ 14648 OSSharedPtr<OSArray> 14649 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag) 14650 { 14651 OSSharedPtr<OSArray> result; 14652 OSSharedPtr<OSCollectionIterator> kextIterator; 14653 OSSharedPtr<OSArray> personalities; 14654 14655 OSString * kextID = NULL; // do not release 14656 OSKext * theKext = NULL; // do not release 14657 14658 IORecursiveLockLock(sKextLock); 14659 14660 /* Let's conservatively guess that any given kext has around 3 14661 * personalities for now. 14662 */ 14663 result = OSArray::withCapacity(sKextsByID->getCount() * 3); 14664 if (!result) { 14665 goto finish; 14666 } 14667 14668 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 14669 if (!kextIterator) { 14670 goto finish; 14671 } 14672 14673 while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) { 14674 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID)); 14675 if (theKext->flags.requireExplicitLoad) { 14676 OSKextLog(theKext, 14677 kOSKextLogDebugLevel | 14678 kOSKextLogLoadFlag, 14679 "Kext %s requires an explicit kextload; " 14680 "omitting its personalities.", 14681 theKext->getIdentifierCString()); 14682 } else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) { 14683 personalities = theKext->copyPersonalitiesArray(); 14684 if (!personalities) { 14685 continue; 14686 } 14687 result->merge(personalities.get()); 14688 } else { 14689 // xxx - check for better place to put this log msg 14690 OSKextLog(theKext, 14691 kOSKextLogWarningLevel | 14692 kOSKextLogLoadFlag, 14693 "Kext %s is not loadable during safe boot; " 14694 "omitting its personalities.", 14695 theKext->getIdentifierCString()); 14696 } 14697 } 14698 14699 finish: 14700 IORecursiveLockUnlock(sKextLock); 14701 14702 return result; 14703 } 14704 14705 /********************************************************************* 14706 *********************************************************************/ 14707 /* static */ 14708 void 14709 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching) 14710 { 14711 int numPersonalities = 0; 14712 14713 OSKextLog(/* kext */ NULL, 14714 kOSKextLogStepLevel | 14715 kOSKextLogLoadFlag, 14716 "Sending all eligible registered kexts' personalities " 14717 "to the IOCatalogue %s.", 14718 startMatching ? "and starting matching" : "but not starting matching"); 14719 14720 OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities( 14721 /* filterSafeBootFlag */ true); 14722 14723 if (personalities) { 14724 gIOCatalogue->addDrivers(personalities.get(), startMatching); 14725 numPersonalities = personalities->getCount(); 14726 } 14727 14728 OSKextLog(/* kext */ NULL, 14729 kOSKextLogStepLevel | 14730 kOSKextLogLoadFlag, 14731 "%d kext personalit%s sent to the IOCatalogue; %s.", 14732 numPersonalities, numPersonalities > 0 ? "ies" : "y", 14733 startMatching ? "matching started" : "matching not started"); 14734 return; 14735 } 14736 14737 /********************************************************************* 14738 * Do not make a deep copy, just convert the IOKitPersonalities dict 14739 * to an array for sending to the IOCatalogue. 14740 *********************************************************************/ 14741 OSSharedPtr<OSArray> 14742 OSKext::copyPersonalitiesArray(void) 14743 { 14744 OSSharedPtr<OSArray> result; 14745 OSDictionary * personalities = NULL; // do not release 14746 OSSharedPtr<OSCollectionIterator> personalitiesIterator; 14747 14748 OSString * personalityName = NULL; // do not release 14749 OSString * personalityBundleIdentifier = NULL; // do not release 14750 14751 personalities = OSDynamicCast(OSDictionary, 14752 getPropertyForHostArch(kIOKitPersonalitiesKey)); 14753 if (!personalities) { 14754 goto finish; 14755 } 14756 14757 result = OSArray::withCapacity(personalities->getCount()); 14758 if (!result) { 14759 goto finish; 14760 } 14761 14762 personalitiesIterator = 14763 OSCollectionIterator::withCollection(personalities); 14764 if (!personalitiesIterator) { 14765 goto finish; 14766 } 14767 while ((personalityName = OSDynamicCast(OSString, 14768 personalitiesIterator->getNextObject()))) { 14769 OSDictionary * personality = OSDynamicCast(OSDictionary, 14770 personalities->getObject(personalityName)); 14771 14772 if (personality) { 14773 /****** 14774 * If the personality doesn't have a CFBundleIdentifier, or if it 14775 * differs from the kext's, insert the kext's ID so we can find it. 14776 * The publisher ID is used to remove personalities from bundles 14777 * correctly. 14778 */ 14779 personalityBundleIdentifier = OSDynamicCast(OSString, 14780 personality->getObject(kCFBundleIdentifierKey)); 14781 14782 if (!personalityBundleIdentifier) { 14783 personality->setObject(kCFBundleIdentifierKey, bundleID.get()); 14784 } else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) { 14785 personality->setObject(kIOPersonalityPublisherKey, bundleID.get()); 14786 } 14787 } 14788 14789 result->setObject(personality); 14790 } 14791 14792 finish: 14793 return result; 14794 } 14795 14796 /********************************************************************* 14797 * Might want to change this to a bool return? 14798 *********************************************************************/ 14799 OSReturn 14800 OSKext::sendPersonalitiesToCatalog( 14801 bool startMatching, 14802 OSArray * personalityNames) 14803 { 14804 OSReturn result = kOSReturnSuccess; 14805 OSSharedPtr<OSArray> personalitiesToSend; 14806 OSDictionary * kextPersonalities = NULL; // do not release 14807 int count, i; 14808 14809 if (!sLoadEnabled) { 14810 OSKextLog(this, 14811 kOSKextLogErrorLevel | 14812 kOSKextLogLoadFlag, 14813 "Kext loading is disabled (attempt to start matching for kext %s).", 14814 getIdentifierCString()); 14815 result = kOSKextReturnDisabled; 14816 goto finish; 14817 } 14818 14819 if (sSafeBoot && !isLoadableInSafeBoot()) { 14820 OSKextLog(this, 14821 kOSKextLogErrorLevel | 14822 kOSKextLogLoadFlag, 14823 "Kext %s is not loadable during safe boot; " 14824 "not sending personalities to the IOCatalogue.", 14825 getIdentifierCString()); 14826 result = kOSKextReturnNotLoadable; 14827 goto finish; 14828 } 14829 14830 if (!personalityNames || !personalityNames->getCount()) { 14831 personalitiesToSend = copyPersonalitiesArray(); 14832 } else { 14833 kextPersonalities = OSDynamicCast(OSDictionary, 14834 getPropertyForHostArch(kIOKitPersonalitiesKey)); 14835 if (!kextPersonalities || !kextPersonalities->getCount()) { 14836 // not an error 14837 goto finish; 14838 } 14839 personalitiesToSend = OSArray::withCapacity(0); 14840 if (!personalitiesToSend) { 14841 result = kOSKextReturnNoMemory; 14842 goto finish; 14843 } 14844 count = personalityNames->getCount(); 14845 for (i = 0; i < count; i++) { 14846 OSString * name = OSDynamicCast(OSString, 14847 personalityNames->getObject(i)); 14848 if (!name) { 14849 continue; 14850 } 14851 OSDictionary * personality = OSDynamicCast(OSDictionary, 14852 kextPersonalities->getObject(name)); 14853 if (personality) { 14854 personalitiesToSend->setObject(personality); 14855 } 14856 } 14857 } 14858 if (personalitiesToSend) { 14859 unsigned numPersonalities = personalitiesToSend->getCount(); 14860 OSKextLog(this, 14861 kOSKextLogStepLevel | 14862 kOSKextLogLoadFlag, 14863 "Kext %s sending %d personalit%s to the IOCatalogue%s.", 14864 getIdentifierCString(), 14865 numPersonalities, 14866 numPersonalities > 1 ? "ies" : "y", 14867 startMatching ? " and starting matching" : " but not starting matching"); 14868 gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching); 14869 } 14870 finish: 14871 return result; 14872 } 14873 14874 /********************************************************************* 14875 * xxx - We should allow removing the kext's declared personalities, 14876 * xxx - even with other bundle identifiers. 14877 *********************************************************************/ 14878 void 14879 OSKext::removePersonalitiesFromCatalog(void) 14880 { 14881 OSSharedPtr<OSDictionary> personality; 14882 14883 personality = OSDictionary::withCapacity(1); 14884 if (!personality) { 14885 goto finish; 14886 } 14887 personality->setObject(kCFBundleIdentifierKey, getIdentifier()); 14888 14889 OSKextLog(this, 14890 kOSKextLogStepLevel | 14891 kOSKextLogLoadFlag, 14892 "Kext %s removing all personalities naming it from the IOCatalogue.", 14893 getIdentifierCString()); 14894 14895 /* Have the IOCatalog remove all personalities matching this kext's 14896 * bundle ID and trigger matching anew. 14897 */ 14898 gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true); 14899 14900 finish: 14901 return; 14902 } 14903 14904 void 14905 OSKext::updatePersonalitiesInCatalog(OSArray *upgradedPersonalities) 14906 { 14907 if (!upgradedPersonalities || upgradedPersonalities->getCount() == 0) { 14908 return; 14909 } 14910 14911 OSSharedPtr<OSDictionary> personalityToRemove = OSDictionary::withCapacity(1); 14912 if (!personalityToRemove) { 14913 return; 14914 } 14915 14916 /* 14917 * Create a personality dictionary with just the bundleID. 14918 * We will remove any personality that has a matching bundleID, 14919 * irrespective of which other keys are present on the dictionary. 14920 */ 14921 personalityToRemove->setObject(kCFBundleIdentifierKey, getIdentifier()); 14922 gIOCatalogue->exchangeDrivers(personalityToRemove.get(), upgradedPersonalities, true); 14923 } 14924 14925 #if PRAGMA_MARK 14926 #pragma mark Logging 14927 #endif 14928 /********************************************************************* 14929 * Do not call any function that takes sKextLock here! 14930 *********************************************************************/ 14931 /* static */ 14932 OSKextLogSpec 14933 OSKext::setUserSpaceLogFilter( 14934 OSKextLogSpec newUserLogFilter, 14935 bool captureFlag) 14936 { 14937 OSKextLogSpec result; 14938 bool allocError = false; 14939 14940 /* Do not call any function that takes sKextLoggingLock during 14941 * this critical block. That means do logging after. 14942 */ 14943 IOLockLock(sKextLoggingLock); 14944 14945 result = sUserSpaceKextLogFilter; 14946 sUserSpaceKextLogFilter = newUserLogFilter; 14947 14948 if (newUserLogFilter && captureFlag && 14949 !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) { 14950 // xxx - do some measurements for a good initial capacity? 14951 sUserSpaceLogSpecArray = OSArray::withCapacity(0); 14952 sUserSpaceLogMessageArray = OSArray::withCapacity(0); 14953 14954 if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) { 14955 allocError = true; 14956 } 14957 } 14958 14959 IOLockUnlock(sKextLoggingLock); 14960 14961 /* If the config flag itself is changing, log the state change 14962 * going both ways, before setting up the user-space log arrays, 14963 * so that this is only logged in the kernel. 14964 */ 14965 if (result != newUserLogFilter) { 14966 OSKextLog(/* kext */ NULL, 14967 kOSKextLogDebugLevel | 14968 kOSKextLogGeneralFlag, 14969 "User-space log flags changed from 0x%x to 0x%x.", 14970 result, newUserLogFilter); 14971 } 14972 if (allocError) { 14973 OSKextLog(/* kext */ NULL, 14974 kOSKextLogErrorLevel | 14975 kOSKextLogGeneralFlag, 14976 "Failed to allocate user-space log message arrays."); 14977 } 14978 14979 return result; 14980 } 14981 14982 /********************************************************************* 14983 * Do not call any function that takes sKextLock here! 14984 *********************************************************************/ 14985 /* static */ 14986 OSSharedPtr<OSArray> 14987 OSKext::clearUserSpaceLogFilter(void) 14988 { 14989 OSSharedPtr<OSArray> result; 14990 OSKextLogSpec oldLogFilter; 14991 OSKextLogSpec newLogFilter = kOSKextLogSilentFilter; 14992 14993 /* Do not call any function that takes sKextLoggingLock during 14994 * this critical block. That means do logging after. 14995 */ 14996 IOLockLock(sKextLoggingLock); 14997 14998 result = OSArray::withCapacity(2); 14999 if (result) { 15000 result->setObject(sUserSpaceLogSpecArray.get()); 15001 result->setObject(sUserSpaceLogMessageArray.get()); 15002 } 15003 sUserSpaceLogSpecArray.reset(); 15004 sUserSpaceLogMessageArray.reset(); 15005 15006 oldLogFilter = sUserSpaceKextLogFilter; 15007 sUserSpaceKextLogFilter = newLogFilter; 15008 15009 IOLockUnlock(sKextLoggingLock); 15010 15011 /* If the config flag itself is changing, log the state change 15012 * going both ways, after tearing down the user-space log 15013 * arrays, so this is only logged within the kernel. 15014 */ 15015 if (oldLogFilter != newLogFilter) { 15016 OSKextLog(/* kext */ NULL, 15017 kOSKextLogDebugLevel | 15018 kOSKextLogGeneralFlag, 15019 "User-space log flags changed from 0x%x to 0x%x.", 15020 oldLogFilter, newLogFilter); 15021 } 15022 15023 return result; 15024 } 15025 15026 15027 /********************************************************************* 15028 * Do not call any function that takes sKextLock here! 15029 *********************************************************************/ 15030 /* static */ 15031 OSKextLogSpec 15032 OSKext::getUserSpaceLogFilter(void) 15033 { 15034 OSKextLogSpec result; 15035 15036 IOLockLock(sKextLoggingLock); 15037 result = sUserSpaceKextLogFilter; 15038 IOLockUnlock(sKextLoggingLock); 15039 15040 return result; 15041 } 15042 15043 /********************************************************************* 15044 * This function is called by OSMetaClass during kernel C++ setup. 15045 * Be careful what you access here; assume only OSKext::initialize() 15046 * has been called. 15047 * 15048 * Do not call any function that takes sKextLock here! 15049 *********************************************************************/ 15050 #define VTRESET "\033[0m" 15051 15052 #define VTBOLD "\033[1m" 15053 #define VTUNDER "\033[4m" 15054 15055 #define VTRED "\033[31m" 15056 #define VTGREEN "\033[32m" 15057 #define VTYELLOW "\033[33m" 15058 #define VTBLUE "\033[34m" 15059 #define VTMAGENTA "\033[35m" 15060 #define VTCYAN "\033[36m" 15061 15062 inline const char * 15063 colorForFlags(OSKextLogSpec flags) 15064 { 15065 OSKextLogSpec logLevel = flags & kOSKextLogLevelMask; 15066 15067 switch (logLevel) { 15068 case kOSKextLogErrorLevel: 15069 return VTRED VTBOLD; 15070 case kOSKextLogWarningLevel: 15071 return VTRED; 15072 case kOSKextLogBasicLevel: 15073 return VTYELLOW VTUNDER; 15074 case kOSKextLogProgressLevel: 15075 return VTYELLOW; 15076 case kOSKextLogStepLevel: 15077 return VTGREEN; 15078 case kOSKextLogDetailLevel: 15079 return VTCYAN; 15080 case kOSKextLogDebugLevel: 15081 return VTMAGENTA; 15082 default: 15083 return ""; // white 15084 } 15085 } 15086 15087 inline bool 15088 logSpecMatch( 15089 OSKextLogSpec msgLogSpec, 15090 OSKextLogSpec logFilter) 15091 { 15092 OSKextLogSpec filterKextGlobal = logFilter & kOSKextLogKextOrGlobalMask; 15093 OSKextLogSpec filterLevel = logFilter & kOSKextLogLevelMask; 15094 OSKextLogSpec filterFlags = logFilter & kOSKextLogFlagsMask; 15095 15096 OSKextLogSpec msgKextGlobal = msgLogSpec & kOSKextLogKextOrGlobalMask; 15097 OSKextLogSpec msgLevel = msgLogSpec & kOSKextLogLevelMask; 15098 OSKextLogSpec msgFlags = msgLogSpec & kOSKextLogFlagsMask; 15099 15100 /* Explicit messages always get logged. 15101 */ 15102 if (msgLevel == kOSKextLogExplicitLevel) { 15103 return true; 15104 } 15105 15106 /* Warnings and errors are logged regardless of the flags. 15107 */ 15108 if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) { 15109 return true; 15110 } 15111 15112 /* A verbose message that isn't for a logging-enabled kext and isn't global 15113 * does *not* get logged. 15114 */ 15115 if (!msgKextGlobal && !filterKextGlobal) { 15116 return false; 15117 } 15118 15119 /* Warnings and errors are logged regardless of the flags. 15120 * All other messages must fit the flags and 15121 * have a level at or below the filter. 15122 * 15123 */ 15124 if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) { 15125 return true; 15126 } 15127 return false; 15128 } 15129 15130 extern "C" { 15131 void 15132 OSKextLog( 15133 OSKext * aKext, 15134 OSKextLogSpec msgLogSpec, 15135 const char * format, ...) 15136 { 15137 va_list argList; 15138 15139 va_start(argList, format); 15140 OSKextVLog(aKext, msgLogSpec, format, argList); 15141 va_end(argList); 15142 } 15143 15144 void 15145 OSKextVLog( 15146 OSKext * aKext, 15147 OSKextLogSpec msgLogSpec, 15148 const char * format, 15149 va_list srcArgList) 15150 { 15151 extern int disableConsoleOutput; 15152 15153 bool logForKernel = false; 15154 bool logForUser = false; 15155 va_list argList; 15156 char stackBuffer[120]; 15157 uint32_t length = 0; 15158 char * allocBuffer = NULL; // must kfree 15159 OSSharedPtr<OSNumber> logSpecNum; 15160 OSSharedPtr<OSString> logString; 15161 char * buffer = stackBuffer; // do not free 15162 15163 IOLockLock(sKextLoggingLock); 15164 15165 /* Set the kext/global bit in the message spec if we have no 15166 * kext or if the kext requests logging. 15167 */ 15168 if (!aKext || aKext->flags.loggingEnabled) { 15169 msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask; 15170 } 15171 15172 logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter); 15173 if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 15174 logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter); 15175 } 15176 15177 if (!(logForKernel || logForUser)) { 15178 goto finish; 15179 } 15180 15181 /* No goto from here until past va_end()! 15182 */ 15183 va_copy(argList, srcArgList); 15184 length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList); 15185 va_end(argList); 15186 15187 if (length + 1 >= sizeof(stackBuffer)) { 15188 allocBuffer = (char *)kalloc_data_tag(length + 1, 15189 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 15190 if (!allocBuffer) { 15191 goto finish; 15192 } 15193 15194 /* No goto from here until past va_end()! 15195 */ 15196 va_copy(argList, srcArgList); 15197 vsnprintf(allocBuffer, length + 1, format, argList); 15198 va_end(argList); 15199 15200 buffer = allocBuffer; 15201 } 15202 15203 /* If user space wants the log message, queue it up. 15204 */ 15205 if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 15206 logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec)); 15207 logString = OSString::withCString(buffer); 15208 if (logSpecNum && logString) { 15209 sUserSpaceLogSpecArray->setObject(logSpecNum.get()); 15210 sUserSpaceLogMessageArray->setObject(logString.get()); 15211 } 15212 } 15213 15214 /* Always log messages from the kernel according to the kernel's 15215 * log flags. 15216 */ 15217 if (logForKernel) { 15218 /* If we are in console mode and have a custom log filter, 15219 * colorize the log message. 15220 */ 15221 if (!disableConsoleOutput && sBootArgLogFilterFound) { 15222 const char * color = ""; // do not free 15223 color = colorForFlags(msgLogSpec); 15224 printf("%s%s%s\n", colorForFlags(msgLogSpec), 15225 buffer, color[0] ? VTRESET : ""); 15226 } else { 15227 printf("%s\n", buffer); 15228 } 15229 } 15230 15231 finish: 15232 IOLockUnlock(sKextLoggingLock); 15233 15234 if (allocBuffer) { 15235 kfree_data(allocBuffer, length + 1); 15236 } 15237 return; 15238 } 15239 15240 #if KASLR_IOREG_DEBUG 15241 15242 #define IOLOG_INDENT( the_indention ) \ 15243 { \ 15244 int i; \ 15245 for ( i = 0; i < (the_indention); i++ ) { \ 15246 IOLog(" "); \ 15247 } \ 15248 } 15249 15250 extern vm_offset_t vm_kernel_stext; 15251 extern vm_offset_t vm_kernel_etext; 15252 extern mach_vm_offset_t kext_alloc_base; 15253 extern mach_vm_offset_t kext_alloc_max; 15254 15255 bool ScanForAddrInObject(OSObject * theObject, 15256 int indent ); 15257 15258 bool 15259 ScanForAddrInObject(OSObject * theObject, 15260 int indent) 15261 { 15262 const OSMetaClass * myTypeID; 15263 OSSharedPtr<OSCollectionIterator> myIter; 15264 OSSymbol * myKey; 15265 OSObject * myValue; 15266 bool myResult = false; 15267 15268 if (theObject == NULL) { 15269 IOLog("%s: theObject is NULL \n", 15270 __FUNCTION__); 15271 return myResult; 15272 } 15273 15274 myTypeID = OSTypeIDInst(theObject); 15275 15276 if (myTypeID == OSTypeID(OSDictionary)) { 15277 OSDictionary * myDictionary; 15278 15279 myDictionary = OSDynamicCast(OSDictionary, theObject); 15280 myIter = OSCollectionIterator::withCollection( myDictionary ); 15281 if (myIter == NULL) { 15282 return myResult; 15283 } 15284 15285 // !! reset the iterator 15286 myIter->reset(); 15287 15288 while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) { 15289 bool myTempResult; 15290 15291 myValue = myDictionary->getObject(myKey); 15292 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 15293 if (myTempResult) { 15294 // if we ever get a true result return true 15295 myResult = true; 15296 IOLOG_INDENT(indent); 15297 IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy()); 15298 } 15299 } 15300 15301 // !! release the iterator 15302 myIter.reset(); 15303 } else if (myTypeID == OSTypeID(OSArray)) { 15304 OSArray * myArray; 15305 15306 myArray = OSDynamicCast(OSArray, theObject); 15307 myIter = OSCollectionIterator::withCollection(myArray); 15308 if (myIter == NULL) { 15309 return myResult; 15310 } 15311 // !! reset the iterator 15312 myIter->reset(); 15313 15314 while ((myValue = myIter->getNextObject())) { 15315 bool myTempResult; 15316 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 15317 if (myTempResult) { 15318 // if we ever get a true result return true 15319 myResult = true; 15320 IOLOG_INDENT(indent); 15321 IOLog("OSArray: \n"); 15322 } 15323 } 15324 // !! release the iterator 15325 myIter.reset(); 15326 } else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) { 15327 // should we look for addresses in strings? 15328 } else if (myTypeID == OSTypeID(OSData)) { 15329 void * * myPtrPtr; 15330 unsigned int myLen; 15331 OSData * myDataObj; 15332 15333 myDataObj = OSDynamicCast(OSData, theObject); 15334 myPtrPtr = (void * *) myDataObj->getBytesNoCopy(); 15335 myLen = myDataObj->getLength(); 15336 15337 if (myPtrPtr && myLen && myLen > 7) { 15338 int i; 15339 int myPtrCount = (myLen / sizeof(void *)); 15340 15341 for (i = 0; i < myPtrCount; i++) { 15342 UInt64 numberValue = (UInt64) * (myPtrPtr); 15343 15344 if (kext_alloc_max != 0 && 15345 numberValue >= kext_alloc_base && 15346 numberValue < kext_alloc_max) { 15347 OSSharedPtr<OSKext> myKext; 15348 // IOLog("found OSData %p in kext map %p to %p \n", 15349 // *(myPtrPtr), 15350 // (void *) kext_alloc_base, 15351 // (void *) kext_alloc_max); 15352 15353 myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr)); 15354 if (myKext) { 15355 IOLog("found addr %p from an OSData obj within kext \"%s\" \n", 15356 *(myPtrPtr), 15357 myKext->getIdentifierCString()); 15358 } 15359 myResult = true; 15360 } 15361 if (vm_kernel_etext != 0 && 15362 numberValue >= vm_kernel_stext && 15363 numberValue < vm_kernel_etext) { 15364 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n", 15365 *(myPtrPtr), 15366 (void *) vm_kernel_stext, 15367 (void *) vm_kernel_etext); 15368 myResult = true; 15369 } 15370 myPtrPtr++; 15371 } 15372 } 15373 } else if (myTypeID == OSTypeID(OSBoolean)) { 15374 // do nothing here... 15375 } else if (myTypeID == OSTypeID(OSNumber)) { 15376 OSNumber * number = OSDynamicCast(OSNumber, theObject); 15377 15378 UInt64 numberValue = number->unsigned64BitValue(); 15379 15380 if (kext_alloc_max != 0 && 15381 numberValue >= kext_alloc_base && 15382 numberValue < kext_alloc_max) { 15383 OSSharedPtr<OSKext> myKext; 15384 IOLog("found OSNumber in kext map %p to %p \n", 15385 (void *) kext_alloc_base, 15386 (void *) kext_alloc_max); 15387 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 15388 15389 myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue ); 15390 if (myKext) { 15391 IOLog("found in kext \"%s\" \n", 15392 myKext->getIdentifierCString()); 15393 } 15394 15395 myResult = true; 15396 } 15397 if (vm_kernel_etext != 0 && 15398 numberValue >= vm_kernel_stext && 15399 numberValue < vm_kernel_etext) { 15400 IOLog("found OSNumber in kernel text segment %p to %p \n", 15401 (void *) vm_kernel_stext, 15402 (void *) vm_kernel_etext); 15403 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 15404 myResult = true; 15405 } 15406 } 15407 #if 0 15408 else { 15409 const OSMetaClass* myMetaClass = NULL; 15410 15411 myMetaClass = theObject->getMetaClass(); 15412 if (myMetaClass) { 15413 IOLog("class %s \n", myMetaClass->getClassName()); 15414 } else { 15415 IOLog("Unknown object \n" ); 15416 } 15417 } 15418 #endif 15419 15420 return myResult; 15421 } 15422 #endif // KASLR_KEXT_DEBUG 15423 }; /* extern "C" */ 15424 15425 #if PRAGMA_MARK 15426 #pragma mark Backtrace Dump & kmod_get_info() support 15427 #endif 15428 /********************************************************************* 15429 * This function must be safe to call in panic context. 15430 *********************************************************************/ 15431 /* static */ 15432 void 15433 OSKext::printKextsInBacktrace( 15434 vm_offset_t * addr __unused, 15435 unsigned int cnt __unused, 15436 int (* printf_func)(const char *fmt, ...) __unused, 15437 uint32_t flags __unused) 15438 { 15439 addr64_t summary_page = 0; 15440 addr64_t last_summary_page = 0; 15441 bool found_kmod = false; 15442 u_int i = 0; 15443 15444 if (kPrintKextsLock & flags) { 15445 if (!sKextSummariesLock) { 15446 return; 15447 } 15448 IOLockLock(sKextSummariesLock); 15449 } 15450 15451 if (!gLoadedKextSummaries) { 15452 (*printf_func)(" can't perform kext scan: no kext summary"); 15453 goto finish; 15454 } 15455 15456 summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries); 15457 last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize); 15458 for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) { 15459 if (pmap_find_phys(kernel_pmap, summary_page) == 0) { 15460 (*printf_func)(" can't perform kext scan: " 15461 "missing kext summary page %p", summary_page); 15462 goto finish; 15463 } 15464 } 15465 15466 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 15467 OSKextLoadedKextSummary * summary; 15468 15469 summary = gLoadedKextSummaries->summaries + i; 15470 if (!summary->address) { 15471 continue; 15472 } 15473 15474 if (!summaryIsInBacktrace(summary, addr, cnt)) { 15475 continue; 15476 } 15477 15478 if (!found_kmod) { 15479 if (!(kPrintKextsTerse & flags)) { 15480 (*printf_func)(" Kernel Extensions in backtrace:\n"); 15481 } 15482 found_kmod = true; 15483 } 15484 15485 printSummary(summary, printf_func, flags); 15486 } 15487 15488 finish: 15489 if (kPrintKextsLock & flags) { 15490 IOLockUnlock(sKextSummariesLock); 15491 } 15492 15493 return; 15494 } 15495 15496 /********************************************************************* 15497 * This function must be safe to call in panic context. 15498 *********************************************************************/ 15499 /* static */ 15500 boolean_t 15501 OSKext::summaryIsInBacktrace( 15502 OSKextLoadedKextSummary * summary, 15503 vm_offset_t * addr, 15504 unsigned int cnt) 15505 { 15506 u_int i = 0; 15507 15508 for (i = 0; i < cnt; i++) { 15509 vm_offset_t kscan_addr = addr[i]; 15510 #if __has_feature(ptrauth_calls) 15511 kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr); 15512 #endif /* __has_feature(ptrauth_calls) */ 15513 if ((kscan_addr >= summary->text_exec_address) && 15514 (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) { 15515 return TRUE; 15516 } 15517 } 15518 15519 return FALSE; 15520 } 15521 15522 /* 15523 * Get the kext summary object for the kext where 'addr' lies. Must be called with 15524 * sKextSummariesLock held. 15525 */ 15526 OSKextLoadedKextSummary * 15527 OSKext::summaryForAddress(uintptr_t addr) 15528 { 15529 #if __has_feature(ptrauth_calls) 15530 addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr); 15531 #endif /* __has_feature(ptrauth_calls) */ 15532 for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 15533 OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i]; 15534 if (!summary->address) { 15535 continue; 15536 } 15537 15538 #if VM_MAPPED_KEXTS 15539 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not 15540 * support split kexts, but we also may unmap the kexts, which can 15541 * race with the above codepath (see OSKext::unload). As such, 15542 * use a simple range lookup if we are using VM_MAPPED_KEXTS. 15543 */ 15544 if ((addr >= summary->address) && (addr < (summary->address + summary->size))) { 15545 return summary; 15546 } 15547 #else 15548 kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address; 15549 kernel_segment_command_t *seg; 15550 15551 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 15552 if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) { 15553 return summary; 15554 } 15555 } 15556 #endif 15557 } 15558 15559 /* addr did not map to any kext */ 15560 return NULL; 15561 } 15562 15563 /* static */ 15564 void * 15565 OSKext::kextForAddress(const void *address) 15566 { 15567 OSKextActiveAccount * active; 15568 OSKext * kext = NULL; 15569 uint32_t baseIdx; 15570 uint32_t lim; 15571 uintptr_t addr = (uintptr_t) address; 15572 size_t i; 15573 15574 if (!addr) { 15575 return NULL; 15576 } 15577 #if __has_feature(ptrauth_calls) 15578 addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr); 15579 #endif /* __has_feature(ptrauth_calls) */ 15580 15581 if (sKextAccountsCount) { 15582 lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp); 15583 // bsearch sKextAccounts list 15584 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 15585 active = &sKextAccounts[baseIdx + (lim >> 1)]; 15586 if ((addr >= active->address) && (addr < active->address_end)) { 15587 kext = active->account->kext; 15588 if (kext && kext->kmod_info) { 15589 lck_ticket_unlock(sKextAccountsLock); 15590 return (void *)kext->kmod_info->address; 15591 } 15592 break; 15593 } else if (addr > active->address) { 15594 // move right 15595 baseIdx += (lim >> 1) + 1; 15596 lim--; 15597 } 15598 // else move left 15599 } 15600 lck_ticket_unlock(sKextAccountsLock); 15601 } 15602 if (kernel_text_contains(addr)) { 15603 return (void *)&_mh_execute_header; 15604 } 15605 if (gLoadedKextSummaries) { 15606 IOLockLock(sKextSummariesLock); 15607 for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) { 15608 OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i; 15609 if (addr >= summary->address && addr < summary->address + summary->size) { 15610 void *kextAddress = (void *)summary->address; 15611 IOLockUnlock(sKextSummariesLock); 15612 return kextAddress; 15613 } 15614 } 15615 IOLockUnlock(sKextSummariesLock); 15616 } 15617 15618 return NULL; 15619 } 15620 15621 /* 15622 * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t * 15623 * Safe to call in panic context. 15624 */ 15625 static OSKextLoadedKextSummary * 15626 findSummary(uint32_t tagID) 15627 { 15628 OSKextLoadedKextSummary * summary; 15629 for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 15630 summary = gLoadedKextSummaries->summaries + i; 15631 if (summary->loadTag == tagID) { 15632 return summary; 15633 } 15634 } 15635 return NULL; 15636 } 15637 15638 /********************************************************************* 15639 * This function must be safe to call in panic context. 15640 *********************************************************************/ 15641 void 15642 OSKext::printSummary( 15643 OSKextLoadedKextSummary * summary, 15644 int (* printf_func)(const char *fmt, ...), 15645 uint32_t flags) 15646 { 15647 kmod_reference_t * kmod_ref = NULL; 15648 uuid_string_t uuid; 15649 char version[kOSKextVersionMaxLength]; 15650 uint64_t tmpAddr; 15651 uint64_t tmpSize; 15652 OSKextLoadedKextSummary *dependencySummary; 15653 15654 if (!OSKextVersionGetString(summary->version, version, sizeof(version))) { 15655 strlcpy(version, "unknown version", sizeof(version)); 15656 } 15657 (void) uuid_unparse(summary->uuid, uuid); 15658 15659 #if defined(__arm__) || defined(__arm64__) 15660 tmpAddr = summary->text_exec_address; 15661 tmpSize = summary->text_exec_size; 15662 #else 15663 tmpAddr = summary->address; 15664 tmpSize = summary->size; 15665 #endif 15666 if (kPrintKextsUnslide & flags) { 15667 tmpAddr = ml_static_unslide(tmpAddr); 15668 } 15669 (*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n", 15670 (kPrintKextsTerse & flags) ? "" : " ", 15671 summary->name, version, uuid, 15672 tmpAddr, tmpAddr + tmpSize - 1); 15673 15674 if (kPrintKextsTerse & flags) { 15675 return; 15676 } 15677 15678 /* print dependency info */ 15679 for (kmod_ref = (kmod_reference_t *) summary->reference_list; 15680 kmod_ref; 15681 kmod_ref = kmod_ref->next) { 15682 kmod_info_t * rinfo; 15683 15684 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) { 15685 (*printf_func)(" kmod dependency scan stopped " 15686 "due to missing dependency page: %p\n", 15687 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref); 15688 break; 15689 } 15690 rinfo = kmod_ref->info; 15691 15692 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) { 15693 (*printf_func)(" kmod dependency scan stopped " 15694 "due to missing kmod page: %p\n", 15695 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo); 15696 break; 15697 } 15698 15699 if (!rinfo->address) { 15700 continue; // skip fake entries for built-ins 15701 } 15702 15703 dependencySummary = findSummary(rinfo->id); 15704 uuid[0] = 0x00; 15705 tmpAddr = rinfo->address; 15706 tmpSize = rinfo->size; 15707 if (dependencySummary) { 15708 (void) uuid_unparse(dependencySummary->uuid, uuid); 15709 #if defined(__arm__) || defined(__arm64__) 15710 tmpAddr = dependencySummary->text_exec_address; 15711 tmpSize = dependencySummary->text_exec_size; 15712 #endif 15713 } 15714 15715 if (kPrintKextsUnslide & flags) { 15716 tmpAddr = ml_static_unslide(tmpAddr); 15717 } 15718 (*printf_func)(" dependency: %s(%s)[%s]@%p->%p\n", 15719 rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1); 15720 } 15721 return; 15722 } 15723 15724 15725 #if !defined(__arm__) && !defined(__arm64__) 15726 /******************************************************************************* 15727 * substitute() looks at an input string (a pointer within a larger buffer) 15728 * for a match to a substring, and on match it writes the marker & substitution 15729 * character to an output string, updating the scan (from) and 15730 * output (to) indexes as appropriate. 15731 *******************************************************************************/ 15732 static int substitute( 15733 const char * scan_string, 15734 char * string_out, 15735 uint32_t * to_index, 15736 uint32_t * from_index, 15737 const char * substring, 15738 char marker, 15739 char substitution); 15740 15741 /* string_out must be at least KMOD_MAX_NAME bytes. 15742 */ 15743 static int 15744 substitute( 15745 const char * scan_string, 15746 char * string_out, 15747 uint32_t * to_index, 15748 uint32_t * from_index, 15749 const char * substring, 15750 char marker, 15751 char substitution) 15752 { 15753 size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1); 15754 15755 /* On a substring match, append the marker (if there is one) and then 15756 * the substitution character, updating the output (to) index accordingly. 15757 * Then update the input (from) length by the length of the substring 15758 * that got replaced. 15759 */ 15760 if (!strncmp(scan_string, substring, substring_length)) { 15761 if (marker) { 15762 string_out[(*to_index)++] = marker; 15763 } 15764 string_out[(*to_index)++] = substitution; 15765 (*from_index) += substring_length; 15766 return 1; 15767 } 15768 return 0; 15769 } 15770 15771 /******************************************************************************* 15772 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least 15773 * KMOD_MAX_NAME characters and performs various substitutions of common 15774 * prefixes & substrings as defined by tables in kext_panic_report.h. 15775 *******************************************************************************/ 15776 static void compactIdentifier( 15777 const char * identifier, 15778 char * identifier_out, 15779 char ** identifier_out_end); 15780 15781 static void 15782 compactIdentifier( 15783 const char * identifier, 15784 char * identifier_out, 15785 char ** identifier_out_end) 15786 { 15787 uint32_t from_index, to_index; 15788 uint32_t scan_from_index = 0; 15789 uint32_t scan_to_index = 0; 15790 subs_entry_t * subs_entry = NULL; 15791 int did_sub = 0; 15792 15793 from_index = to_index = 0; 15794 identifier_out[0] = '\0'; 15795 15796 /* Replace certain identifier prefixes with shorter @+character sequences. 15797 * Check the return value of substitute() so we only replace the prefix. 15798 */ 15799 for (subs_entry = &kext_identifier_prefix_subs[0]; 15800 subs_entry->substring && !did_sub; 15801 subs_entry++) { 15802 did_sub = substitute(identifier, identifier_out, 15803 &scan_to_index, &scan_from_index, 15804 subs_entry->substring, /* marker */ '\0', subs_entry->substitute); 15805 } 15806 did_sub = 0; 15807 15808 /* Now scan through the identifier looking for the common substrings 15809 * and replacing them with shorter !+character sequences via substitute(). 15810 */ 15811 for (/* see above */; 15812 scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index]; 15813 /* see loop */) { 15814 const char * scan_string = &identifier[scan_from_index]; 15815 15816 did_sub = 0; 15817 15818 if (scan_from_index) { 15819 for (subs_entry = &kext_identifier_substring_subs[0]; 15820 subs_entry->substring && !did_sub; 15821 subs_entry++) { 15822 did_sub = substitute(scan_string, identifier_out, 15823 &scan_to_index, &scan_from_index, 15824 subs_entry->substring, '!', subs_entry->substitute); 15825 } 15826 } 15827 15828 /* If we didn't substitute, copy the input character to the output. 15829 */ 15830 if (!did_sub) { 15831 identifier_out[scan_to_index++] = identifier[scan_from_index++]; 15832 } 15833 } 15834 15835 identifier_out[scan_to_index] = '\0'; 15836 if (identifier_out_end) { 15837 *identifier_out_end = &identifier_out[scan_to_index]; 15838 } 15839 15840 return; 15841 } 15842 #endif /* !defined(__arm__) && !defined(__arm64__) */ 15843 15844 /******************************************************************************* 15845 * assemble_identifier_and_version() adds to a string buffer a compacted 15846 * bundle identifier followed by a version string. 15847 *******************************************************************************/ 15848 15849 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length. 15850 */ 15851 static size_t assemble_identifier_and_version( 15852 kmod_info_t * kmod_info, 15853 char * identPlusVers, 15854 size_t bufSize); 15855 15856 static size_t 15857 assemble_identifier_and_version( 15858 kmod_info_t * kmod_info, 15859 char * identPlusVers, 15860 size_t bufSize) 15861 { 15862 size_t result = 0; 15863 15864 #if defined(__arm__) || defined(__arm64__) 15865 result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME); 15866 #else 15867 compactIdentifier(kmod_info->name, identPlusVers, NULL); 15868 result = strnlen(identPlusVers, KMOD_MAX_NAME - 1); 15869 #endif 15870 identPlusVers[result++] = '\t'; // increment for real char 15871 identPlusVers[result] = '\0'; // don't increment for nul char 15872 result = strlcat(identPlusVers, kmod_info->version, bufSize); 15873 if (result >= bufSize) { 15874 identPlusVers[bufSize - 1] = '\0'; 15875 result = bufSize - 1; 15876 } 15877 15878 return result; 15879 } 15880 15881 /******************************************************************************* 15882 * Assumes sKextLock is held. 15883 *******************************************************************************/ 15884 /* static */ 15885 int 15886 OSKext::saveLoadedKextPanicListTyped( 15887 const char * prefix, 15888 int invertFlag, 15889 int libsFlag, 15890 char * paniclist, 15891 uint32_t list_size) 15892 { 15893 int result = -1; 15894 unsigned int count, i; 15895 15896 count = sLoadedKexts->getCount(); 15897 if (!count) { 15898 goto finish; 15899 } 15900 15901 i = count - 1; 15902 do { 15903 OSObject * rawKext = sLoadedKexts->getObject(i); 15904 OSKext * theKext = OSDynamicCast(OSKext, rawKext); 15905 int match; 15906 size_t identPlusVersLength; 15907 size_t tempLen; 15908 char identPlusVers[2 * KMOD_MAX_NAME]; 15909 15910 if (!rawKext) { 15911 printf("OSKext::saveLoadedKextPanicListTyped - " 15912 "NULL kext in loaded kext list; continuing\n"); 15913 continue; 15914 } 15915 15916 if (!theKext) { 15917 printf("OSKext::saveLoadedKextPanicListTyped - " 15918 "Kext type cast failed in loaded kext list; continuing\n"); 15919 continue; 15920 } 15921 15922 /* Skip all built-in kexts. 15923 */ 15924 if (theKext->isKernelComponent()) { 15925 continue; 15926 } 15927 15928 kmod_info_t * kmod_info = theKext->kmod_info; 15929 15930 /* Filter for kmod name (bundle identifier). 15931 */ 15932 match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME)); 15933 if ((match && invertFlag) || (!match && !invertFlag)) { 15934 continue; 15935 } 15936 15937 /* Filter for libraries (kexts that have a compatible version). 15938 */ 15939 if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) || 15940 (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) { 15941 continue; 15942 } 15943 15944 if (!kmod_info || 15945 !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) { 15946 printf("kext scan stopped due to missing kmod_info page: %p\n", 15947 kmod_info); 15948 goto finish; 15949 } 15950 15951 identPlusVersLength = assemble_identifier_and_version(kmod_info, 15952 identPlusVers, 15953 sizeof(identPlusVers)); 15954 if (!identPlusVersLength) { 15955 printf("error saving loaded kext info\n"); 15956 goto finish; 15957 } 15958 15959 /* make sure everything fits and we null terminate. 15960 */ 15961 tempLen = strlcat(paniclist, identPlusVers, list_size); 15962 if (tempLen >= list_size) { 15963 // panic list is full, keep it and null terminate 15964 paniclist[list_size - 1] = 0x00; 15965 result = 0; 15966 goto finish; 15967 } 15968 tempLen = strlcat(paniclist, "\n", list_size); 15969 if (tempLen >= list_size) { 15970 // panic list is full, keep it and null terminate 15971 paniclist[list_size - 1] = 0x00; 15972 result = 0; 15973 goto finish; 15974 } 15975 } while (i--); 15976 15977 result = 0; 15978 finish: 15979 15980 return result; 15981 } 15982 15983 /********************************************************************* 15984 *********************************************************************/ 15985 /* static */ 15986 void 15987 OSKext::saveLoadedKextPanicList(void) 15988 { 15989 char * newlist = NULL; 15990 uint32_t newlist_size = 0; 15991 15992 newlist_size = KEXT_PANICLIST_SIZE; 15993 newlist = (char *)kalloc_data_tag(newlist_size, 15994 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 15995 15996 if (!newlist) { 15997 OSKextLog(/* kext */ NULL, 15998 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 15999 "Couldn't allocate kext panic log buffer."); 16000 goto finish; 16001 } 16002 16003 newlist[0] = '\0'; 16004 16005 // non-"com.apple." kexts 16006 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1, 16007 /* libs? */ -1, newlist, newlist_size) != 0) { 16008 goto finish; 16009 } 16010 // "com.apple." nonlibrary kexts 16011 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 16012 /* libs? */ 0, newlist, newlist_size) != 0) { 16013 goto finish; 16014 } 16015 // "com.apple." library kexts 16016 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 16017 /* libs? */ 1, newlist, newlist_size) != 0) { 16018 goto finish; 16019 } 16020 16021 if (loaded_kext_paniclist) { 16022 kfree_data(loaded_kext_paniclist, loaded_kext_paniclist_size); 16023 } 16024 loaded_kext_paniclist = newlist; 16025 newlist = NULL; 16026 loaded_kext_paniclist_size = newlist_size; 16027 16028 finish: 16029 if (newlist) { 16030 kfree_data(newlist, newlist_size); 16031 } 16032 return; 16033 } 16034 16035 /********************************************************************* 16036 * Assumes sKextLock is held. 16037 *********************************************************************/ 16038 void 16039 OSKext::savePanicString(bool isLoading) 16040 { 16041 u_long len; 16042 16043 if (!kmod_info) { 16044 return; // do not goto finish here b/c of lock 16045 } 16046 16047 len = assemble_identifier_and_version( kmod_info, 16048 (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf, 16049 (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf)); 16050 if (!len) { 16051 printf("error saving unloaded kext info\n"); 16052 goto finish; 16053 } 16054 16055 if (isLoading) { 16056 last_loaded_strlen = len; 16057 last_loaded_address = (void *)kmod_info->address; 16058 last_loaded_size = kmod_info->size; 16059 clock_get_uptime(&last_loaded_timestamp); 16060 } else { 16061 last_unloaded_strlen = len; 16062 last_unloaded_address = (void *)kmod_info->address; 16063 last_unloaded_size = kmod_info->size; 16064 clock_get_uptime(&last_unloaded_timestamp); 16065 } 16066 16067 finish: 16068 return; 16069 } 16070 16071 /********************************************************************* 16072 *********************************************************************/ 16073 /* static */ 16074 void 16075 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...)) 16076 { 16077 if (last_loaded_strlen) { 16078 printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n", 16079 AbsoluteTime_to_scalar(&last_loaded_timestamp), 16080 last_loaded_strlen, last_loaded_str_buf, 16081 last_loaded_address, last_loaded_size); 16082 } 16083 16084 if (last_unloaded_strlen) { 16085 printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n", 16086 AbsoluteTime_to_scalar(&last_unloaded_timestamp), 16087 last_unloaded_strlen, last_unloaded_str_buf, 16088 last_unloaded_address, last_unloaded_size); 16089 } 16090 16091 printf_func("loaded kexts:\n"); 16092 if (loaded_kext_paniclist && 16093 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) && 16094 loaded_kext_paniclist[0]) { 16095 printf_func("%.*s", 16096 strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size), 16097 loaded_kext_paniclist); 16098 } else { 16099 printf_func("(none)\n"); 16100 } 16101 return; 16102 } 16103 16104 /********************************************************************* 16105 * Assumes sKextLock is held. 16106 *********************************************************************/ 16107 /* static */ 16108 void 16109 OSKext::updateLoadedKextSummaries(void) 16110 { 16111 kern_return_t result = KERN_FAILURE; 16112 OSKextLoadedKextSummaryHeader *summaryHeader = NULL; 16113 OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL; 16114 OSKext *aKext; 16115 vm_map_offset_t start, end; 16116 size_t summarySize = 0; 16117 size_t size; 16118 u_int count; 16119 u_int maxKexts; 16120 u_int i, j; 16121 OSKextActiveAccount * accountingList; 16122 OSKextActiveAccount * prevAccountingList; 16123 uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount; 16124 16125 prevAccountingList = NULL; 16126 prevAccountingListCount = 0; 16127 16128 #if DEVELOPMENT || DEBUG 16129 if (IORecursiveLockHaveLock(sKextLock) == false) { 16130 panic("sKextLock must be held"); 16131 } 16132 #endif 16133 16134 IOLockLock(sKextSummariesLock); 16135 16136 count = sLoadedKexts->getCount(); 16137 for (i = 0, maxKexts = 0; i < count; ++i) { 16138 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 16139 maxKexts += (aKext && aKext->isExecutable()); 16140 } 16141 16142 if (!maxKexts) { 16143 goto finish; 16144 } 16145 if (maxKexts < kOSKextTypicalLoadCount) { 16146 maxKexts = kOSKextTypicalLoadCount; 16147 } 16148 16149 /* Calculate the size needed for the new summary headers. 16150 */ 16151 16152 size = sizeof(*gLoadedKextSummaries); 16153 size += maxKexts * sizeof(*gLoadedKextSummaries->summaries); 16154 size = round_page(size); 16155 16156 if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) { 16157 if (gLoadedKextSummaries) { 16158 kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize); 16159 gLoadedKextSummaries = NULL; 16160 gLoadedKextSummariesTimestamp = mach_absolute_time(); 16161 sLoadedKextSummariesAllocSize = 0; 16162 } 16163 result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, 16164 KMA_DATA, VM_KERN_MEMORY_OSKEXT); 16165 if (result != KERN_SUCCESS) { 16166 goto finish; 16167 } 16168 summaryHeader = summaryHeaderAlloc; 16169 summarySize = size; 16170 } else { 16171 summaryHeader = gLoadedKextSummaries; 16172 summarySize = sLoadedKextSummariesAllocSize; 16173 16174 start = (vm_map_offset_t) summaryHeader; 16175 end = start + summarySize; 16176 result = vm_map_protect(kernel_map, 16177 start, 16178 end, 16179 VM_PROT_DEFAULT, 16180 FALSE); 16181 if (result != KERN_SUCCESS) { 16182 goto finish; 16183 } 16184 } 16185 16186 /* Populate the summary header. 16187 */ 16188 16189 bzero(summaryHeader, summarySize); 16190 summaryHeader->version = kOSKextLoadedKextSummaryVersion; 16191 summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary); 16192 16193 /* Populate each kext summary. 16194 */ 16195 16196 count = sLoadedKexts->getCount(); 16197 accountingListAlloc = 0; 16198 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 16199 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 16200 if (!aKext || !aKext->isExecutable()) { 16201 continue; 16202 } 16203 16204 aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]); 16205 summaryHeader->numSummaries++; 16206 accountingListAlloc++; 16207 } 16208 16209 accountingList = IONew(typeof(accountingList[0]), accountingListAlloc); 16210 accountingListCount = 0; 16211 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 16212 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 16213 if (!aKext || !aKext->isExecutable()) { 16214 continue; 16215 } 16216 16217 OSKextActiveAccount activeAccount; 16218 aKext->updateActiveAccount(&activeAccount); 16219 // order by address 16220 for (idx = 0; idx < accountingListCount; idx++) { 16221 if (activeAccount.address < accountingList[idx].address) { 16222 break; 16223 } 16224 } 16225 bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0])); 16226 accountingList[idx] = activeAccount; 16227 accountingListCount++; 16228 } 16229 assert(accountingListCount == accountingListAlloc); 16230 /* Write protect the buffer and move it into place. 16231 */ 16232 16233 start = (vm_map_offset_t) summaryHeader; 16234 end = start + summarySize; 16235 16236 result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE); 16237 if (result != KERN_SUCCESS) { 16238 goto finish; 16239 } 16240 16241 gLoadedKextSummaries = summaryHeader; 16242 gLoadedKextSummariesTimestamp = mach_absolute_time(); 16243 sLoadedKextSummariesAllocSize = summarySize; 16244 summaryHeaderAlloc = NULL; 16245 16246 /* Call the magic breakpoint function through a static function pointer so 16247 * the compiler can't optimize the function away. 16248 */ 16249 if (sLoadedKextSummariesUpdated) { 16250 (*sLoadedKextSummariesUpdated)(); 16251 } 16252 16253 lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp); 16254 prevAccountingList = sKextAccounts; 16255 prevAccountingListCount = sKextAccountsCount; 16256 sKextAccounts = accountingList; 16257 sKextAccountsCount = accountingListCount; 16258 lck_ticket_unlock(sKextAccountsLock); 16259 16260 finish: 16261 IOLockUnlock(sKextSummariesLock); 16262 16263 /* If we had to allocate a new buffer but failed to generate the summaries, 16264 * free that now. 16265 */ 16266 if (summaryHeaderAlloc) { 16267 kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize); 16268 } 16269 if (prevAccountingList) { 16270 IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount); 16271 } 16272 16273 return; 16274 } 16275 16276 /********************************************************************* 16277 *********************************************************************/ 16278 void 16279 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary) 16280 { 16281 OSSharedPtr<OSData> uuid; 16282 16283 strlcpy(summary->name, getIdentifierCString(), 16284 sizeof(summary->name)); 16285 16286 uuid = copyUUID(); 16287 if (uuid) { 16288 memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid)); 16289 } 16290 16291 if (flags.builtin) { 16292 // this value will stop lldb from parsing the mach-o header 16293 // summary->address = UINT64_MAX; 16294 // summary->size = 0; 16295 summary->address = kmod_info->address; 16296 summary->size = kmod_info->size; 16297 } else { 16298 summary->address = kmod_info->address; 16299 summary->size = kmod_info->size; 16300 } 16301 summary->version = getVersion(); 16302 summary->loadTag = kmod_info->id; 16303 summary->flags = 0; 16304 summary->reference_list = (uint64_t) kmod_info->reference_list; 16305 16306 summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size); 16307 if (summary->text_exec_address == 0) { 16308 // Fallback to __TEXT 16309 summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size); 16310 } 16311 return; 16312 } 16313 16314 /********************************************************************* 16315 *********************************************************************/ 16316 16317 void 16318 OSKext::updateActiveAccount(OSKextActiveAccount *accountp) 16319 { 16320 kernel_mach_header_t *hdr = NULL; 16321 kernel_segment_command_t *seg = NULL; 16322 16323 bzero(accountp, sizeof(*accountp)); 16324 16325 hdr = (kernel_mach_header_t *)kmod_info->address; 16326 if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) { 16327 /* 16328 * If this kext supports split segments (or is in a new 16329 * MH_FILESET kext collection), use the first 16330 * executable segment as the range for instructions 16331 * (and thus for backtracing. 16332 */ 16333 for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) { 16334 if (seg->initprot & VM_PROT_EXECUTE) { 16335 break; 16336 } 16337 } 16338 } 16339 if (seg) { 16340 accountp->address = seg->vmaddr; 16341 if (accountp->address) { 16342 accountp->address_end = seg->vmaddr + seg->vmsize; 16343 } 16344 } else { 16345 /* For non-split kexts and for kexts without executable 16346 * segments, just use the kmod_info range (as the kext 16347 * is either all in one range or should not show up in 16348 * instruction backtraces). 16349 */ 16350 accountp->address = kmod_info->address; 16351 if (accountp->address) { 16352 accountp->address_end = kmod_info->address + kmod_info->size; 16353 } 16354 } 16355 16356 accountp->account = this->account; 16357 } 16358 16359 bool 16360 OSKext::isDriverKit(void) 16361 { 16362 OSString *bundleType; 16363 16364 if (infoDict) { 16365 bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)); 16366 if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) { 16367 return TRUE; 16368 } 16369 } 16370 return FALSE; 16371 } 16372 16373 bool 16374 OSKext::isInFileset(void) 16375 { 16376 if (!kmod_info) { 16377 goto check_prelinked; 16378 } 16379 16380 if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) { 16381 return true; 16382 } 16383 16384 check_prelinked: 16385 if (isPrelinked()) { 16386 /* 16387 * If we haven't setup kmod_info yet, but we know 16388 * we're loading a prelinked kext in an MH_FILESET KC, 16389 * then return true 16390 */ 16391 kc_format_t kc_format; 16392 if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) { 16393 return true; 16394 } 16395 } 16396 return false; 16397 } 16398 16399 OSSharedPtr<OSDextStatistics> 16400 OSKext::copyDextStatistics(void) 16401 { 16402 return dextStatistics; 16403 } 16404 16405 bool 16406 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg) 16407 { 16408 kern_return_t result; 16409 if (!super::init()) { 16410 return false; 16411 } 16412 if (seg == nullptr) { 16413 return false; 16414 } 16415 result = kmem_alloc(kernel_map, (vm_offset_t *)&data, seg->vmsize, 16416 KMA_PAGEABLE, VM_KERN_MEMORY_KEXT); 16417 if (result != KERN_SUCCESS) { 16418 return false; 16419 } 16420 memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize); 16421 savedSegment = seg; 16422 vmsize = seg->vmsize; 16423 vmaddr = seg->vmaddr; 16424 return true; 16425 } 16426 16427 OSSharedPtr<OSKextSavedMutableSegment> 16428 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg) 16429 { 16430 OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>(); 16431 if (me && !me->initWithSegment(seg)) { 16432 return nullptr; 16433 } 16434 return me; 16435 } 16436 16437 void 16438 OSKextSavedMutableSegment::free(void) 16439 { 16440 if (data) { 16441 kmem_free(kernel_map, (vm_offset_t)data, vmsize); 16442 } 16443 } 16444 16445 vm_offset_t 16446 OSKextSavedMutableSegment::getVMAddr() const 16447 { 16448 return vmaddr; 16449 } 16450 16451 vm_offset_t 16452 OSKextSavedMutableSegment::getVMSize() const 16453 { 16454 return vmsize; 16455 } 16456 16457 OSReturn 16458 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg) 16459 { 16460 if (seg != savedSegment) { 16461 return kOSKextReturnInvalidArgument; 16462 } 16463 if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) { 16464 return kOSKextReturnInvalidArgument; 16465 } 16466 memcpy((void *)seg->vmaddr, data, vmsize); 16467 return kOSReturnSuccess; 16468 } 16469 16470 extern "C" kern_return_t 16471 OSKextSetReceiptQueried(void) 16472 { 16473 OSKextLog(/* kext */ NULL, 16474 kOSKextLogStepLevel | kOSKextLogGeneralFlag, 16475 "Setting kext receipt as queried"); 16476 16477 IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue); 16478 return KERN_SUCCESS; 16479 } 16480 16481 extern "C" const vm_allocation_site_t * 16482 OSKextGetAllocationSiteForCaller(uintptr_t address) 16483 { 16484 OSKextActiveAccount * active; 16485 vm_allocation_site_t * site; 16486 vm_allocation_site_t * releasesite; 16487 16488 uint32_t baseIdx; 16489 uint32_t lim; 16490 #if __has_feature(ptrauth_calls) 16491 address = (uintptr_t)VM_KERNEL_STRIP_PTR(address); 16492 #endif /* __has_feature(ptrauth_calls) */ 16493 16494 lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp); 16495 site = releasesite = NULL; 16496 16497 // bsearch sKextAccounts list 16498 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 16499 active = &sKextAccounts[baseIdx + (lim >> 1)]; 16500 if ((address >= active->address) && (address < active->address_end)) { 16501 site = &active->account->site; 16502 if (!site->tag) { 16503 vm_tag_alloc_locked(site, &releasesite); 16504 } 16505 break; 16506 } else if (address > active->address) { 16507 // move right 16508 baseIdx += (lim >> 1) + 1; 16509 lim--; 16510 } 16511 // else move left 16512 } 16513 lck_ticket_unlock(sKextAccountsLock); 16514 if (releasesite) { 16515 kern_allocation_name_release(releasesite); 16516 } 16517 16518 return site; 16519 } 16520 16521 #if DEVELOPMENT || DEBUG 16522 extern "C" void 16523 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *)) 16524 { 16525 OSKextActiveAccount * active; 16526 16527 uint32_t baseIdx; 16528 uint32_t lim; 16529 #if __has_feature(ptrauth_calls) 16530 address = (uintptr_t)VM_KERNEL_STRIP_PTR(address); 16531 #endif /* __has_feature(ptrauth_calls) */ 16532 16533 lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp); 16534 16535 // bsearch sKextAccounts list 16536 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 16537 active = &sKextAccounts[baseIdx + (lim >> 1)]; 16538 if ((address >= active->address) && (address < active->address_end)) { 16539 cb(&active->account->task_refgrp); 16540 break; 16541 } else if (address > active->address) { 16542 // move right 16543 baseIdx += (lim >> 1) + 1; 16544 lim--; 16545 } 16546 // else move left 16547 } 16548 lck_ticket_unlock(sKextAccountsLock); 16549 } 16550 #endif /* DEVELOPMENT || DEBUG */ 16551 16552 extern "C" uint32_t 16553 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen) 16554 { 16555 OSKextAccount * account = (typeof(account))site; 16556 const char * kname; 16557 16558 if (name) { 16559 if (account->kext) { 16560 kname = account->kext->getIdentifierCString(); 16561 } else { 16562 kname = "<>"; 16563 } 16564 strlcpy(name, kname, namelen); 16565 } 16566 16567 return account->loadTag; 16568 } 16569 16570 extern "C" void 16571 OSKextFreeSite(vm_allocation_site_t * site) 16572 { 16573 OSKextAccount * freeAccount = (typeof(freeAccount))site; 16574 IOFreeType(freeAccount, OSKextAccount); 16575 } 16576 16577 /********************************************************************* 16578 *********************************************************************/ 16579 16580 #if CONFIG_IMAGEBOOT 16581 int 16582 OSKextGetUUIDForName(const char *name, uuid_t uuid) 16583 { 16584 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name); 16585 if (!kext) { 16586 return 1; 16587 } 16588 16589 OSSharedPtr<OSData> uuid_data = kext->copyUUID(); 16590 if (uuid_data) { 16591 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t)); 16592 return 0; 16593 } 16594 16595 return 1; 16596 } 16597 #endif 16598 16599 16600 16601 class OSDextCrash : public OSObject { 16602 OSDeclareDefaultStructors(OSDextCrash); 16603 public: 16604 static OSPtr<OSDextCrash> withTimestamp(uint64_t timestamp); 16605 uint64_t getTimestamp(); 16606 16607 private: 16608 virtual bool initWithTimestamp(uint64_t timestamp); 16609 uint64_t fTimestamp; 16610 }; 16611 16612 OSDefineMetaClassAndStructors(OSDextCrash, OSObject); 16613 16614 OSSharedPtr<OSDextCrash> 16615 OSDextCrash::withTimestamp(uint64_t timestamp) 16616 { 16617 OSSharedPtr<OSDextCrash> result = OSMakeShared<OSDextCrash>(); 16618 if (!result->initWithTimestamp(timestamp)) { 16619 return NULL; 16620 } 16621 return result; 16622 } 16623 16624 bool 16625 OSDextCrash::initWithTimestamp(uint64_t timestamp) 16626 { 16627 if (!OSObject::init()) { 16628 return false; 16629 } 16630 fTimestamp = timestamp; 16631 return true; 16632 } 16633 16634 uint64_t 16635 OSDextCrash::getTimestamp() 16636 { 16637 return fTimestamp; 16638 } 16639 16640 OSSharedPtr<OSDextStatistics> 16641 OSDextStatistics::create() 16642 { 16643 OSSharedPtr<OSDextStatistics> result = OSMakeShared<OSDextStatistics>(); 16644 if (!result->init()) { 16645 return NULL; 16646 } 16647 return result; 16648 } 16649 16650 bool 16651 OSDextStatistics::init() 16652 { 16653 if (!OSObject::init()) { 16654 return false; 16655 } 16656 16657 lock = IOLockAlloc(); 16658 crashes = OSArray::withCapacity(kMaxDextCrashesInOneDay); 16659 return true; 16660 } 16661 16662 void 16663 OSDextStatistics::free() 16664 { 16665 if (lock) { 16666 IOLockFree(lock); 16667 } 16668 crashes.reset(); 16669 OSObject::free(); 16670 } 16671 16672 OSDextCrashPolicy 16673 OSDextStatistics::recordCrash() 16674 { 16675 size_t i = 0; 16676 uint64_t timestamp = mach_continuous_time(); 16677 uint64_t interval; 16678 nanoseconds_to_absolutetime(86400 * NSEC_PER_SEC /* 1 day */, &interval); 16679 uint64_t lastTimestamp = timestamp > interval ? timestamp - interval : 0; 16680 OSDextCrashPolicy policy; 16681 16682 IOLockLock(lock); 16683 OSSharedPtr<OSDextCrash> crash = OSDextCrash::withTimestamp(timestamp); 16684 for (i = 0; i < crashes->getCount();) { 16685 OSDextCrash * current = OSDynamicCast(OSDextCrash, crashes->getObject(i)); 16686 assert(current != NULL); 16687 if (current->getTimestamp() < lastTimestamp) { 16688 crashes->removeObject(i); 16689 } else { 16690 i++; 16691 } 16692 } 16693 16694 crashes->setObject(crash); 16695 16696 if (crashes->getCount() > kMaxDextCrashesInOneDay) { 16697 policy = kOSDextCrashPolicyReboot; 16698 } else { 16699 policy = kOSDextCrashPolicyNone; 16700 } 16701 16702 IOLockUnlock(lock); 16703 16704 return policy; 16705 } 16706 16707 size_t 16708 OSDextStatistics::getCrashCount() 16709 { 16710 size_t result = 0; 16711 IOLockLock(lock); 16712 result = crashes->getCount(); 16713 IOLockUnlock(lock); 16714 return result; 16715 } 16716 16717 static int 16718 sysctl_willuserspacereboot 16719 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 16720 { 16721 int new_value = 0, old_value = 0, changed = 0; 16722 int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed); 16723 if (error) { 16724 return error; 16725 } 16726 if (changed) { 16727 OSKext::willUserspaceReboot(); 16728 } 16729 return 0; 16730 } 16731 16732 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot, 16733 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 16734 NULL, 0, sysctl_willuserspacereboot, "I", ""); 16735