1 /* 2 * Copyright (c) 2008-2016 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_kern.h> 40 #include <vm/vm_map.h> 41 #include <kextd/kextd_mach.h> 42 #include <libkern/kernel_mach_header.h> 43 #include <libkern/kext_panic_report.h> 44 #include <libkern/kext_request_keys.h> 45 #include <libkern/mkext.h> 46 #include <libkern/prelink.h> 47 #include <libkern/version.h> 48 #include <libkern/zlib.h> 49 #include <mach/host_special_ports.h> 50 #include <mach/mach_vm.h> 51 #include <mach/mach_time.h> 52 #include <sys/sysctl.h> 53 #include <uuid/uuid.h> 54 #include <sys/random.h> 55 #include <pexpert/pexpert.h> 56 57 #include <sys/pgo.h> 58 59 #if CONFIG_MACF 60 #include <sys/kauth.h> 61 #include <security/mac_framework.h> 62 #endif 63 64 #if CONFIG_CSR 65 #include <sys/csr.h> 66 #include <sys/stat.h> 67 #include <sys/vnode.h> 68 #endif /* CONFIG_CSR */ 69 }; 70 71 #include <os/cpp_util.h> 72 73 #include <libkern/OSKextLibPrivate.h> 74 #include <libkern/c++/OSKext.h> 75 #include <libkern/c++/OSLib.h> 76 77 #include <IOKit/IOLib.h> 78 #include <IOKit/IOCatalogue.h> 79 #include <IOKit/IORegistryEntry.h> 80 #include <IOKit/IOService.h> 81 #include <IOKit/IOUserServer.h> 82 83 #include <IOKit/IOStatisticsPrivate.h> 84 #include <IOKit/IOBSD.h> 85 #include <IOKit/IOPlatformExpert.h> 86 87 #include <san/kasan.h> 88 89 #if PRAGMA_MARK 90 #pragma mark External & Internal Function Protos 91 #endif 92 /********************************************************************* 93 *********************************************************************/ 94 extern "C" { 95 extern int IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize); 96 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize); 97 98 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */ 99 extern int dtrace_keep_kernel_symbols(void); 100 101 #if defined(__x86_64__) || defined(__i386__) 102 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide); 103 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers); 104 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size); 105 static void *allocate_kcfileset_map_entry_list(void); 106 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size); 107 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable); 108 int vnode_put(struct vnode *vp); 109 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size, 110 void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot); 111 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size); 112 void * ubc_getobject(struct vnode *vp, __unused int flags); 113 #endif //(__x86_64__) || defined(__i386__) 114 } 115 116 extern unsigned long gVirtBase; 117 extern unsigned long gPhysBase; 118 extern vm_map_t g_kext_map; 119 120 bool pageableKCloaded = false; 121 bool auxKCloaded = false; 122 bool resetAuxKCSegmentOnUnload = false; 123 124 extern boolean_t pageablekc_uuid_valid; 125 extern uuid_t pageablekc_uuid; 126 extern uuid_string_t pageablekc_uuid_string; 127 128 extern boolean_t auxkc_uuid_valid; 129 extern uuid_t auxkc_uuid; 130 extern uuid_string_t auxkc_uuid_string; 131 132 static OSReturn _OSKextCreateRequest( 133 const char * predicate, 134 OSSharedPtr<OSDictionary> & requestP); 135 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict); 136 static OSObject * _OSKextGetRequestArgument( 137 OSDictionary * requestDict, 138 const char * argName); 139 static bool _OSKextSetRequestArgument( 140 OSDictionary * requestDict, 141 const char * argName, 142 OSObject * value); 143 static void * _OSKextExtractPointer(OSData * wrapper); 144 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSData * wrapper); 145 static OSReturn _OSDictionarySetCStringValue( 146 OSDictionary * dict, 147 const char * key, 148 const char * value); 149 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID); 150 #if CONFIG_KXLD 151 static bool _OSKextInPrelinkRebuildWindow(void); 152 #endif 153 154 // We really should add containsObject() & containsCString to OSCollection & subclasses. 155 // So few pad slots, though.... 156 static bool _OSArrayContainsCString(OSArray * array, const char * cString); 157 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code); 158 159 /* Prelinked arm kexts do not have VM entries because the method we use to 160 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does 161 * not work on ARM. To get around that, we must free prelinked kext 162 * executables with ml_static_mfree() instead of kext_free(). 163 */ 164 #if __i386__ || __x86_64__ 165 #define VM_MAPPED_KEXTS 1 166 #define KASLR_KEXT_DEBUG 0 167 #define KASLR_IOREG_DEBUG 0 168 #elif __arm__ || __arm64__ 169 #define VM_MAPPED_KEXTS 0 170 #define KASLR_KEXT_DEBUG 0 171 #else 172 #error Unsupported architecture 173 #endif 174 175 #if PRAGMA_MARK 176 #pragma mark Constants & Macros 177 #endif 178 /********************************************************************* 179 * Constants & Macros 180 *********************************************************************/ 181 182 /* Use this number to create containers. 183 */ 184 #define kOSKextTypicalLoadCount (150) 185 186 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict. 187 * A loaded kext will no dependents or external retains will have 2 retains. 188 */ 189 #define kOSKextMinRetainCount (1) 190 #define kOSKextMinLoadedRetainCount (2) 191 192 /********** 193 * Strings and substrings used in dependency resolution. 194 */ 195 #define APPLE_KEXT_PREFIX "com.apple." 196 #define KERNEL_LIB "com.apple.kernel" 197 198 #define PRIVATE_KPI "com.apple.kpi.private" 199 200 /* Version for compatbility pseudokexts (com.apple.kernel.*), 201 * compatible back to v6.0. 202 */ 203 #define KERNEL6_LIB "com.apple.kernel.6.0" 204 #define KERNEL6_VERSION "7.9.9" 205 206 #define KERNEL_LIB_PREFIX "com.apple.kernel." 207 #define KPI_LIB_PREFIX "com.apple.kpi." 208 209 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0) 210 211 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes 212 #define MINIMUM_WAKEUP_SECONDS (30) 213 214 /********************************************************************* 215 * infoDict keys for internally-stored data. Saves on ivar slots for 216 * objects we don't keep around past boot time or during active load. 217 *********************************************************************/ 218 219 /* A usable, uncompressed file is stored under this key. 220 */ 221 #define _kOSKextExecutableKey "_OSKextExecutable" 222 223 /* An indirect reference to the executable file from an mkext 224 * is stored under this key. 225 */ 226 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference" 227 228 /* If the file is contained in a larger buffer laid down by the booter or 229 * sent from user space, the OSKext stores that OSData under this key so that 230 * references are properly tracked. This is always an mkext, right now. 231 */ 232 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData" 233 234 #define OS_LOG_HDR_VERSION 1 235 #define NUM_OS_LOG_SECTIONS 2 236 237 #define OS_LOG_SECT_IDX 0 238 #define CSTRING_SECT_IDX 1 239 240 #if PRAGMA_MARK 241 #pragma mark Typedefs 242 #endif 243 /********************************************************************* 244 * Typedefs 245 *********************************************************************/ 246 247 /********************************************************************* 248 * osLogDataHeaderRef describes the header information of an OSData 249 * object that is returned when querying for kOSBundleLogStringsKey. 250 * We currently return information regarding 2 sections - os_log and 251 * cstring. In the case that the os_log section doesn't exist, we just 252 * return an offset and length of 0 for that section. 253 *********************************************************************/ 254 typedef struct osLogDataHeader { 255 uint32_t version; 256 uint32_t sect_count; 257 struct { 258 uint32_t sect_offset; 259 uint32_t sect_size; 260 } sections[0]; 261 } osLogDataHeaderRef; 262 263 /********************************************************************* 264 * MkextEntryRef describes the contents of an OSData object 265 * referencing a file entry from an mkext so that we can uncompress 266 * (if necessary) and extract it on demand. 267 * 268 * It contains the mkextVersion in case we ever wind up supporting 269 * multiple mkext formats. Mkext format 1 is officially retired as of 270 * Snow Leopard. 271 *********************************************************************/ 272 typedef struct MkextEntryRef { 273 mkext_basic_header * mkext; // beginning of whole mkext file 274 void * fileinfo;// mkext2_file_entry or equiv; see mkext.h 275 } MkextEntryRef; 276 277 #if PRAGMA_MARK 278 #pragma mark Global and static Module Variables 279 #endif 280 /********************************************************************* 281 * Global & static variables, used to keep track of kexts. 282 *********************************************************************/ 283 284 static bool sPrelinkBoot = false; 285 static bool sSafeBoot = false; 286 static bool sKeepSymbols = false; 287 static bool sPanicOnKCMismatch = false; 288 static bool sOSKextWasResetAfterUserspaceReboot = false; 289 290 /********************************************************************* 291 * sKextLock is the principal lock for OSKext, and guards all static 292 * and global variables not owned by other locks (declared further 293 * below). It must be taken by any entry-point method or function, 294 * including internal functions called on scheduled threads. 295 * 296 * sKextLock and sKextInnerLock are recursive due to multiple functions 297 * that are called both externally and internally. The other locks are 298 * nonrecursive. 299 * 300 * Which locks are taken depends on what they protect, but if more than 301 * one must be taken, they must always be locked in this order 302 * (and unlocked in reverse order) to prevent deadlocks: 303 * 304 * 1. sKextLock 305 * 2. sKextInnerLock 306 * 3. sKextSummariesLock 307 * 4. sKextLoggingLock 308 */ 309 static IORecursiveLock * sKextLock = NULL; 310 311 static OSSharedPtr<OSDictionary> sKextsByID; 312 static OSSharedPtr<OSDictionary> sExcludeListByID; 313 static OSKextVersion sExcludeListVersion = 0; 314 static OSSharedPtr<OSArray> sLoadedKexts; 315 static OSSharedPtr<OSDictionary> sNonLoadableKextsByID; 316 static OSSharedPtr<OSArray> sUnloadedPrelinkedKexts; 317 static OSSharedPtr<OSArray> sLoadedDriverKitKexts; 318 319 // Requests to the IOKit daemon waiting to be picked up. 320 static OSSharedPtr<OSArray> sKernelRequests; 321 // Identifier of kext load requests in sKernelRequests 322 static OSSharedPtr<OSSet> sPostedKextLoadIdentifiers; 323 static OSSharedPtr<OSArray> sRequestCallbackRecords; 324 325 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel 326 static OSSharedPtr<OSSet> sAllKextLoadIdentifiers; 327 #if CONFIG_KXLD 328 static KXLDContext * sKxldContext = NULL; 329 #endif 330 static uint32_t sNextLoadTag = 0; 331 static uint32_t sNextRequestTag = 0; 332 333 static bool sUserLoadsActive = false; 334 static bool sIOKitDaemonActive = false; 335 static bool sDeferredLoadSucceeded = false; 336 static bool sConsiderUnloadsExecuted = false; 337 338 #if NO_KEXTD 339 static bool sKernelRequestsEnabled = false; 340 #else 341 static bool sKernelRequestsEnabled = true; 342 #endif 343 static bool sLoadEnabled = true; 344 static bool sUnloadEnabled = true; 345 346 /********************************************************************* 347 * Stuff for the OSKext representing the kernel itself. 348 **********/ 349 static OSKext * sKernelKext = NULL; 350 351 /* Set up a fake kmod_info struct for the kernel. 352 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP() 353 * before OSKext is initialized; that call only needs the name 354 * and address to be set correctly. 355 * 356 * We don't do much else with the kerne's kmod_info; we never 357 * put it into the kmod list, never adjust the reference count, 358 * and never have kernel components reference it. 359 * For that matter, we don't do much with kmod_info structs 360 * at all anymore! We just keep them filled in for gdb and 361 * binary compability. 362 */ 363 kmod_info_t g_kernel_kmod_info = { 364 .next = NULL, 365 .info_version = KMOD_INFO_VERSION, 366 .id = 0, // loadTag: kernel is always 0 367 .name = kOSKextKernelIdentifier,// bundle identifier 368 .version = "0", // filled in in OSKext::initialize() 369 .reference_count = -1, // never adjusted; kernel never unloads 370 .reference_list = NULL, 371 .address = 0, 372 .size = 0, // filled in in OSKext::initialize() 373 .hdr_size = 0, 374 .start = NULL, 375 .stop = NULL 376 }; 377 378 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */ 379 380 kmod_info_t invalid_kmod_info = { 381 .next = NULL, 382 .info_version = KMOD_INFO_VERSION, 383 .id = UINT32_MAX, 384 .name = "invalid", 385 .version = "0", 386 .reference_count = -1, 387 .reference_list = NULL, 388 .address = 0, 389 .size = 0, 390 .hdr_size = 0, 391 .start = NULL, 392 .stop = NULL 393 }; 394 395 extern "C" { 396 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c, 397 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s, 398 // misc_protos.h, db_low_trace.c, kgmacros 399 // 'kmod' is a holdover from the old kmod system, we can't rename it. 400 kmod_info_t * kmod = NULL; 401 402 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE) 403 404 405 static char * loaded_kext_paniclist = NULL; 406 static uint32_t loaded_kext_paniclist_size = 0; 407 408 AbsoluteTime last_loaded_timestamp; 409 static char last_loaded_str_buf[2 * KMOD_MAX_NAME]; 410 static u_long last_loaded_strlen = 0; 411 static void * last_loaded_address = NULL; 412 static u_long last_loaded_size = 0; 413 414 AbsoluteTime last_unloaded_timestamp; 415 static char last_unloaded_str_buf[2 * KMOD_MAX_NAME]; 416 static u_long last_unloaded_strlen = 0; 417 static void * last_unloaded_address = NULL; 418 static u_long last_unloaded_size = 0; 419 420 // Statically linked kmods described by several mach-o sections: 421 // 422 // kPrelinkInfoSegment:kBuiltinInfoSection 423 // Array of pointers to kmod_info_t structs. 424 // 425 // kPrelinkInfoSegment:kBuiltinInfoSection 426 // Array of pointers to an embedded mach-o header. 427 // 428 // __DATA:kBuiltinInitSection, kBuiltinTermSection 429 // Structors for all kmods. Has to be filtered by proc address. 430 // 431 432 static uint32_t gBuiltinKmodsCount; 433 static kernel_section_t * gBuiltinKmodsSectionInfo; 434 static kernel_section_t * gBuiltinKmodsSectionStart; 435 436 const OSSymbol * gIOSurfaceIdentifier; 437 vm_tag_t gIOSurfaceTag; 438 439 /********************************************************************* 440 * sKextInnerLock protects against cross-calls with IOService and 441 * IOCatalogue, and owns the variables declared immediately below. 442 * 443 * Note that sConsiderUnloadsExecuted above belongs to sKextLock! 444 * 445 * When both sKextLock and sKextInnerLock need to be taken, 446 * always lock sKextLock first and unlock it second. Never take both 447 * locks in an entry point to OSKext; if you need to do so, you must 448 * spawn an independent thread to avoid potential deadlocks for threads 449 * calling into OSKext. 450 **********/ 451 static IORecursiveLock * sKextInnerLock = NULL; 452 453 static bool sAutounloadEnabled = true; 454 static bool sConsiderUnloadsCalled = false; 455 static bool sConsiderUnloadsPending = false; 456 457 static unsigned int sConsiderUnloadDelay = 60; // seconds 458 static thread_call_t sUnloadCallout = NULL; 459 #if CONFIG_KXLD 460 static thread_call_t sDestroyLinkContextThread = NULL; // one-shot, one-at-a-time thread 461 #endif // CONFIG_KXLD 462 static bool sSystemSleep = false; // true when system going to sleep 463 static AbsoluteTime sLastWakeTime; // last time we woke up 464 465 /********************************************************************* 466 * Backtraces can be printed at various times so we need a tight lock 467 * on data used for that. sKextSummariesLock protects the variables 468 * declared immediately below. 469 * 470 * gLoadedKextSummaries is accessed by other modules, but only during 471 * a panic so the lock isn't needed then. 472 * 473 * gLoadedKextSummaries has the "used" attribute in order to ensure 474 * that it remains visible even when we are performing extremely 475 * aggressive optimizations, as it is needed to allow the debugger 476 * to automatically parse the list of loaded kexts. 477 **********/ 478 static IOLock * sKextSummariesLock = NULL; 479 extern "C" lck_spin_t vm_allocation_sites_lock; 480 static IOSimpleLock * sKextAccountsLock = &vm_allocation_sites_lock; 481 482 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated; 483 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL; 484 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0; 485 static size_t sLoadedKextSummariesAllocSize = 0; 486 487 static OSKextActiveAccount * sKextAccounts; 488 static uint32_t sKextAccountsCount; 489 }; 490 491 /********************************************************************* 492 * sKextLoggingLock protects the logging variables declared immediately below. 493 **********/ 494 static IOLock * sKextLoggingLock = NULL; 495 496 static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel | 497 kOSKextLogVerboseFlagsMask; 498 static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter; 499 static bool sBootArgLogFilterFound = false; 500 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter, 501 0, "kernel kext logging"); 502 503 static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter; 504 static OSSharedPtr<OSArray> sUserSpaceLogSpecArray; 505 static OSSharedPtr<OSArray> sUserSpaceLogMessageArray; 506 507 /********* 508 * End scope for sKextInnerLock-protected variables. 509 *********************************************************************/ 510 511 512 /********************************************************************* 513 * helper function used for collecting PGO data upon unload of a kext 514 */ 515 516 static int OSKextGrabPgoDataLocked(OSKext *kext, 517 bool metadata, 518 uuid_t instance_uuid, 519 uint64_t *pSize, 520 char *pBuffer, 521 uint64_t bufferSize); 522 523 /**********************************************************************/ 524 525 526 527 #if PRAGMA_MARK 528 #pragma mark OSData callbacks (need to move to OSData) 529 #endif 530 /********************************************************************* 531 * C functions used for callbacks. 532 *********************************************************************/ 533 extern "C" { 534 void 535 osdata_kmem_free(void * ptr, unsigned int length) 536 { 537 kmem_free(kernel_map, (vm_address_t)ptr, length); 538 return; 539 } 540 541 void 542 osdata_phys_free(void * ptr, unsigned int length) 543 { 544 ml_static_mfree((vm_offset_t)ptr, length); 545 return; 546 } 547 548 void 549 osdata_vm_deallocate(void * ptr, unsigned int length) 550 { 551 (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length); 552 return; 553 } 554 555 void 556 osdata_kext_free(void * ptr, unsigned int length) 557 { 558 (void)kext_free((vm_offset_t)ptr, length); 559 } 560 }; 561 562 #if PRAGMA_MARK 563 #pragma mark KXLD Allocation Callback 564 #endif 565 #if CONFIG_KXLD 566 /********************************************************************* 567 * KXLD Allocation Callback 568 *********************************************************************/ 569 kxld_addr_t 570 kern_allocate( 571 u_long size, 572 KXLDAllocateFlags * flags, 573 void * user_data) 574 { 575 vm_address_t result = 0; // returned 576 kern_return_t mach_result = KERN_FAILURE; 577 bool success = false; 578 OSKext * theKext = (OSKext *)user_data; 579 unsigned int roundSize = 0; 580 OSSharedPtr<OSData> linkBuffer; 581 582 if (round_page(size) > UINT_MAX) { 583 OSKextLog(theKext, 584 kOSKextLogErrorLevel | 585 kOSKextLogGeneralFlag, 586 "%s: Requested memory size is greater than UINT_MAX.", 587 theKext->getIdentifierCString()); 588 goto finish; 589 } 590 591 roundSize = (unsigned int)round_page(size); 592 593 mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE); 594 if (mach_result != KERN_SUCCESS) { 595 OSKextLog(theKext, 596 kOSKextLogErrorLevel | 597 kOSKextLogGeneralFlag, 598 "Can't allocate kernel memory to link %s.", 599 theKext->getIdentifierCString()); 600 goto finish; 601 } 602 603 /* Create an OSData wrapper for the allocated buffer. 604 */ 605 linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize); 606 if (!linkBuffer) { 607 OSKextLog(theKext, 608 kOSKextLogErrorLevel | 609 kOSKextLogGeneralFlag, 610 "Can't allocate linked executable wrapper for %s.", 611 theKext->getIdentifierCString()); 612 goto finish; 613 } 614 linkBuffer->setDeallocFunction(osdata_kext_free); 615 OSKextLog(theKext, 616 kOSKextLogProgressLevel | 617 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 618 "Allocated link buffer for kext %s at %p (%lu bytes).", 619 theKext->getIdentifierCString(), 620 (void *)result, (unsigned long)roundSize); 621 622 theKext->setLinkedExecutable(linkBuffer.get()); 623 624 *flags = kKxldAllocateWritable; 625 success = true; 626 627 finish: 628 if (!success && result) { 629 kext_free(result, roundSize); 630 result = 0; 631 } 632 633 return (kxld_addr_t)result; 634 } 635 636 /********************************************************************* 637 *********************************************************************/ 638 void 639 kxld_log_callback( 640 KXLDLogSubsystem subsystem, 641 KXLDLogLevel level, 642 const char * format, 643 va_list argList, 644 void * user_data) 645 { 646 OSKext *theKext = (OSKext *) user_data; 647 OSKextLogSpec logSpec = 0; 648 649 switch (subsystem) { 650 case kKxldLogLinking: 651 logSpec |= kOSKextLogLinkFlag; 652 break; 653 case kKxldLogPatching: 654 logSpec |= kOSKextLogPatchFlag; 655 break; 656 } 657 658 switch (level) { 659 case kKxldLogExplicit: 660 logSpec |= kOSKextLogExplicitLevel; 661 break; 662 case kKxldLogErr: 663 logSpec |= kOSKextLogErrorLevel; 664 break; 665 case kKxldLogWarn: 666 logSpec |= kOSKextLogWarningLevel; 667 break; 668 case kKxldLogBasic: 669 logSpec |= kOSKextLogProgressLevel; 670 break; 671 case kKxldLogDetail: 672 logSpec |= kOSKextLogDetailLevel; 673 break; 674 case kKxldLogDebug: 675 logSpec |= kOSKextLogDebugLevel; 676 break; 677 } 678 679 OSKextVLog(theKext, logSpec, format, argList); 680 } 681 #endif // CONFIG_KXLD 682 683 #if PRAGMA_MARK 684 #pragma mark IOStatistics defines 685 #endif 686 687 #if IOKITSTATS 688 689 #define notifyKextLoadObservers(kext, kmod_info) \ 690 do { \ 691 IOStatistics::onKextLoad(kext, kmod_info); \ 692 } while (0) 693 694 #define notifyKextUnloadObservers(kext) \ 695 do { \ 696 IOStatistics::onKextUnload(kext); \ 697 } while (0) 698 699 #define notifyAddClassObservers(kext, addedClass, flags) \ 700 do { \ 701 IOStatistics::onClassAdded(kext, addedClass); \ 702 } while (0) 703 704 #define notifyRemoveClassObservers(kext, removedClass, flags) \ 705 do { \ 706 IOStatistics::onClassRemoved(kext, removedClass); \ 707 } while (0) 708 709 #else 710 711 #define notifyKextLoadObservers(kext, kmod_info) 712 #define notifyKextUnloadObservers(kext) 713 #define notifyAddClassObservers(kext, addedClass, flags) 714 #define notifyRemoveClassObservers(kext, removedClass, flags) 715 716 #endif /* IOKITSTATS */ 717 718 #if PRAGMA_MARK 719 #pragma mark Module Config (Startup & Shutdown) 720 #endif 721 /********************************************************************* 722 * Module Config (Class Definition & Class Methods) 723 *********************************************************************/ 724 #define super OSObject 725 OSDefineMetaClassAndStructors(OSKext, OSObject) 726 727 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject); 728 729 /********************************************************************* 730 *********************************************************************/ 731 /* static */ 732 void 733 OSKext::initialize(void) 734 { 735 OSSharedPtr<OSData> kernelExecutable = NULL;// do not release 736 u_char * kernelStart = NULL;// do not free 737 size_t kernelLength = 0; 738 IORegistryEntry * registryRoot = NULL;// do not release 739 OSSharedPtr<OSNumber> kernelCPUType; 740 OSSharedPtr<OSNumber> kernelCPUSubtype; 741 OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter; 742 bool setResult = false; 743 uint64_t * timestamp = NULL; 744 __unused char bootArgBuffer[16];// for PE_parse_boot_argn w/strings 745 746 /* This must be the first thing allocated. Everything else grabs this lock. 747 */ 748 sKextLock = IORecursiveLockAlloc(); 749 sKextInnerLock = IORecursiveLockAlloc(); 750 sKextSummariesLock = IOLockAlloc(); 751 sKextLoggingLock = IOLockAlloc(); 752 assert(sKextLock); 753 assert(sKextInnerLock); 754 assert(sKextSummariesLock); 755 assert(sKextLoggingLock); 756 757 sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount); 758 sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 759 sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount); 760 sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10); 761 sKernelRequests = OSArray::withCapacity(0); 762 sPostedKextLoadIdentifiers = OSSet::withCapacity(0); 763 sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount); 764 sRequestCallbackRecords = OSArray::withCapacity(0); 765 assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests && 766 sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers && 767 sRequestCallbackRecords && sUnloadedPrelinkedKexts); 768 769 /* Read the log flag boot-args and set the log flags. 770 */ 771 if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) { 772 sBootArgLogFilterFound = true; 773 sKernelLogFilter = bootLogFilter; 774 // log this if any flags are set 775 OSKextLog(/* kext */ NULL, 776 kOSKextLogBasicLevel | 777 kOSKextLogFlagsMask, 778 "Kernel kext log filter 0x%x per kextlog boot arg.", 779 (unsigned)sKernelLogFilter); 780 } 781 782 #if !defined(__arm__) && !defined(__arm64__) 783 /* 784 * On our ARM targets, the kernelcache/boot kernel collection contains 785 * the set of kexts required to boot, as specified by KCB. Safeboot is 786 * either unsupported, or is supported by the bootloader only loading 787 * the boot kernel collection; as a result OSKext has no role to play 788 * in safeboot policy on ARM. 789 */ 790 sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer, 791 sizeof(bootArgBuffer)) ? true : false; 792 #endif /* defined(__arm__) && defined(__arm64__) */ 793 794 if (sSafeBoot) { 795 OSKextLog(/* kext */ NULL, 796 kOSKextLogWarningLevel | 797 kOSKextLogGeneralFlag, 798 "SAFE BOOT DETECTED - " 799 "only valid OSBundleRequired kexts will be loaded."); 800 } 801 802 PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols)); 803 #if CONFIG_DTRACE 804 if (dtrace_keep_kernel_symbols()) { 805 sKeepSymbols = true; 806 } 807 #endif /* CONFIG_DTRACE */ 808 #if KASAN_DYNAMIC_BLACKLIST 809 /* needed for function lookup */ 810 sKeepSymbols = true; 811 #endif 812 813 /* 814 * Should we panic when the SystemKC is not linked against the 815 * BootKC that was loaded by the booter? By default: yes, if the 816 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic 817 * on mis-match and instead just print an error and continue. 818 */ 819 sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer, 820 sizeof(bootArgBuffer)) ? false : true; 821 822 /* Set up an OSKext instance to represent the kernel itself. 823 */ 824 sKernelKext = new OSKext; 825 assert(sKernelKext); 826 827 kernelStart = (u_char *)&_mh_execute_header; 828 kernelLength = getlastaddr() - (vm_offset_t)kernelStart; 829 assert(kernelLength <= UINT_MAX); 830 kernelExecutable = OSData::withBytesNoCopy( 831 kernelStart, (unsigned int)kernelLength); 832 assert(kernelExecutable); 833 834 #if KASLR_KEXT_DEBUG 835 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %lu (0x%016lx) \n", 836 (unsigned long)kernelStart, 837 (unsigned long)getlastaddr(), 838 kernelLength, 839 (unsigned long)vm_kernel_slide, 840 (unsigned long)vm_kernel_slide); 841 #endif 842 843 sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0 844 sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier); 845 846 sKernelKext->version = OSKextParseVersionString(osrelease); 847 sKernelKext->compatibleVersion = sKernelKext->version; 848 sKernelKext->linkedExecutable = os::move(kernelExecutable); 849 sKernelKext->interfaceUUID = sKernelKext->copyUUID(); 850 851 sKernelKext->flags.hasAllDependencies = 1; 852 sKernelKext->flags.kernelComponent = 1; 853 sKernelKext->flags.prelinked = 0; 854 sKernelKext->flags.loaded = 1; 855 sKernelKext->flags.started = 1; 856 sKernelKext->flags.CPPInitialized = 0; 857 sKernelKext->flags.jettisonLinkeditSeg = 0; 858 859 sKernelKext->kmod_info = &g_kernel_kmod_info; 860 strlcpy(g_kernel_kmod_info.version, osrelease, 861 sizeof(g_kernel_kmod_info.version)); 862 g_kernel_kmod_info.size = kernelLength; 863 g_kernel_kmod_info.id = sKernelKext->loadTag; 864 865 /* Cons up an info dict, so we don't have to have special-case 866 * checking all over. 867 */ 868 sKernelKext->infoDict = OSDictionary::withCapacity(5); 869 assert(sKernelKext->infoDict); 870 setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey, 871 sKernelKext->bundleID.get()); 872 assert(setResult); 873 setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey, 874 kOSBooleanTrue); 875 assert(setResult); 876 877 { 878 OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease)); 879 assert(scratchString); 880 setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey, 881 scratchString.get()); 882 assert(setResult); 883 } 884 885 { 886 OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy("mach_kernel")); 887 assert(scratchString); 888 setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey, 889 scratchString.get()); 890 assert(setResult); 891 } 892 893 /* Add the kernel kext to the bookkeeping dictionaries. Note that 894 * the kernel kext doesn't have a kmod_info struct. copyInfo() 895 * gathers info from other places anyhow. 896 */ 897 setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext); 898 assert(setResult); 899 setResult = sLoadedKexts->setObject(sKernelKext); 900 assert(setResult); 901 902 // XXX: better way with OSSharedPtr? 903 // sKernelKext remains a valid pointer even after the decref 904 sKernelKext->release(); 905 906 registryRoot = IORegistryEntry::getRegistryRoot(); 907 kernelCPUType = OSNumber::withNumber( 908 (long long unsigned int)_mh_execute_header.cputype, 909 8 * sizeof(_mh_execute_header.cputype)); 910 kernelCPUSubtype = OSNumber::withNumber( 911 (long long unsigned int)_mh_execute_header.cpusubtype, 912 8 * sizeof(_mh_execute_header.cpusubtype)); 913 assert(registryRoot && kernelCPUSubtype && kernelCPUType); 914 915 registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get()); 916 registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get()); 917 918 gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection); 919 if (gBuiltinKmodsSectionInfo) { 920 uint32_t count; 921 922 assert(gBuiltinKmodsSectionInfo->addr); 923 assert(gBuiltinKmodsSectionInfo->size); 924 assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX); 925 gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *)); 926 927 gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection); 928 assert(gBuiltinKmodsSectionStart); 929 assert(gBuiltinKmodsSectionStart->addr); 930 assert(gBuiltinKmodsSectionStart->size); 931 assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX); 932 count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t)); 933 // one extra pointer for the end of last kmod 934 assert(count == (gBuiltinKmodsCount + 1)); 935 936 vm_kernel_builtinkmod_text = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0]; 937 vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1]; 938 } 939 940 // Don't track this object -- it's never released 941 gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach(); 942 943 timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp); 944 *timestamp = 0; 945 timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp); 946 *timestamp = 0; 947 timestamp = __OSAbsoluteTimePtr(&sLastWakeTime); 948 *timestamp = 0; 949 950 OSKextLog(/* kext */ NULL, 951 kOSKextLogProgressLevel | 952 kOSKextLogGeneralFlag, 953 "Kext system initialized."); 954 955 notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info); 956 957 return; 958 } 959 960 /********************************************************************* 961 * This is expected to be called exactly once, from exactly one thread 962 * context, during kernel bootstrap. 963 *********************************************************************/ 964 /* static */ 965 OSReturn 966 OSKext::removeKextBootstrap(void) 967 { 968 OSReturn result = kOSReturnError; 969 970 const char * dt_kernel_header_name = "Kernel-__HEADER"; 971 const char * dt_kernel_symtab_name = "Kernel-__SYMTAB"; 972 kernel_mach_header_t * dt_mach_header = NULL; 973 int dt_mach_header_size = 0; 974 struct symtab_command * dt_symtab = NULL; 975 int dt_symtab_size = 0; 976 int dt_result = 0; 977 978 kernel_segment_command_t * seg_to_remove = NULL; 979 980 const char __unused * dt_segment_name = NULL; 981 void __unused * segment_paddress = NULL; 982 int __unused segment_size = 0; 983 984 OSKextLog(/* kext */ NULL, 985 kOSKextLogProgressLevel | 986 kOSKextLogGeneralFlag, 987 "Jettisoning kext bootstrap segments."); 988 989 /* 990 * keep the linkedit segment around when booted from a new MH_FILESET 991 * KC because all the kexts shared a linkedit segment. 992 */ 993 kc_format_t kc_format; 994 if (!PE_get_primary_kc_format(&kc_format)) { 995 OSKextLog(/* kext */ NULL, 996 kOSKextLogErrorLevel | 997 kOSKextLogGeneralFlag, 998 "Unable to determine primary KC format"); 999 } 1000 1001 /***** 1002 * Dispose of unnecessary stuff that the booter didn't need to load. 1003 */ 1004 dt_result = IODTGetLoaderInfo(dt_kernel_header_name, 1005 (void **)&dt_mach_header, &dt_mach_header_size); 1006 if (dt_result == 0 && dt_mach_header) { 1007 IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header, 1008 round_page_32(dt_mach_header_size)); 1009 } 1010 dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name, 1011 (void **)&dt_symtab, &dt_symtab_size); 1012 if (dt_result == 0 && dt_symtab) { 1013 IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab, 1014 round_page_32(dt_symtab_size)); 1015 } 1016 1017 /***** 1018 * KLD bootstrap segment. 1019 */ 1020 // xxx - should rename KLD segment 1021 seg_to_remove = getsegbyname("__KLD"); 1022 if (seg_to_remove) { 1023 OSRuntimeUnloadCPPForSegment(seg_to_remove); 1024 } 1025 1026 #if __arm__ || __arm64__ 1027 /* Free the memory that was set up by bootx. 1028 */ 1029 dt_segment_name = "Kernel-__KLD"; 1030 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) { 1031 /* We cannot free this with KTRR enabled, as we cannot 1032 * update the permissions on the KLD range this late 1033 * in the boot process. 1034 */ 1035 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1036 (int)segment_size); 1037 } 1038 #elif __i386__ || __x86_64__ 1039 /* On x86, use the mapping data from the segment load command to 1040 * unload KLD directly. 1041 * This may invalidate any assumptions about "avail_start" 1042 * defining the lower bound for valid physical addresses. 1043 */ 1044 if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) { 1045 bzero((void *)seg_to_remove->vmaddr, seg_to_remove->vmsize); 1046 ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize); 1047 } 1048 #else 1049 #error arch 1050 #endif 1051 1052 seg_to_remove = NULL; 1053 1054 /***** 1055 * Prelinked kernel's symtab (if there is one). 1056 */ 1057 if (kc_format != KCFormatFileset) { 1058 kernel_section_t * sect; 1059 sect = getsectbyname("__PRELINK", "__symtab"); 1060 if (sect && sect->addr && sect->size) { 1061 ml_static_mfree(sect->addr, sect->size); 1062 } 1063 } 1064 1065 seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT"); 1066 1067 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it 1068 * pageable, unless keepsyms is set. To do that, we have to copy it from 1069 * its booter-allocated memory, free the booter memory, reallocate proper 1070 * managed memory, then copy the segment back in. 1071 * 1072 * NOTE: This optimization is not valid for fileset KCs because each 1073 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment 1074 * that points to one fileset-global LINKEDIT segment. This 1075 * optimization is also only valid for platforms that support vm 1076 * mapped kexts or mapped kext collections (pageable KCs) 1077 */ 1078 #if VM_MAPPED_KEXTS 1079 if (!sKeepSymbols && kc_format != KCFormatFileset) { 1080 kern_return_t mem_result; 1081 void *seg_copy = NULL; 1082 void *seg_data = NULL; 1083 vm_map_offset_t seg_offset = 0; 1084 vm_map_offset_t seg_copy_offset = 0; 1085 vm_map_size_t seg_length = 0; 1086 1087 seg_data = (void *) seg_to_remove->vmaddr; 1088 seg_offset = (vm_map_offset_t) seg_to_remove->vmaddr; 1089 seg_length = (vm_map_size_t) seg_to_remove->vmsize; 1090 1091 /* Allocate space for the LINKEDIT copy. 1092 */ 1093 mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy, 1094 seg_length, VM_KERN_MEMORY_KEXT); 1095 if (mem_result != KERN_SUCCESS) { 1096 OSKextLog(/* kext */ NULL, 1097 kOSKextLogErrorLevel | 1098 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1099 "Can't copy __LINKEDIT segment for VM reassign."); 1100 return result; 1101 } 1102 seg_copy_offset = (vm_map_offset_t) seg_copy; 1103 1104 /* Copy it out. 1105 */ 1106 memcpy(seg_copy, seg_data, seg_length); 1107 1108 /* Dump the booter memory. 1109 */ 1110 ml_static_mfree(seg_offset, seg_length); 1111 1112 /* Set up the VM region. 1113 */ 1114 mem_result = vm_map_enter_mem_object( 1115 kernel_map, 1116 &seg_offset, 1117 seg_length, /* mask */ 0, 1118 VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, 1119 VM_MAP_KERNEL_FLAGS_NONE, 1120 VM_KERN_MEMORY_NONE, 1121 (ipc_port_t)NULL, 1122 (vm_object_offset_t) 0, 1123 /* copy */ FALSE, 1124 /* cur_protection */ VM_PROT_READ | VM_PROT_WRITE, 1125 /* max_protection */ VM_PROT_ALL, 1126 /* inheritance */ VM_INHERIT_DEFAULT); 1127 if ((mem_result != KERN_SUCCESS) || 1128 (seg_offset != (vm_map_offset_t) seg_data)) { 1129 OSKextLog(/* kext */ NULL, 1130 kOSKextLogErrorLevel | 1131 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1132 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).", 1133 seg_data, seg_length, mem_result); 1134 return result; 1135 } 1136 1137 /* And copy it back. 1138 */ 1139 memcpy(seg_data, seg_copy, seg_length); 1140 1141 /* Free the copy. 1142 */ 1143 kmem_free(kernel_map, seg_copy_offset, seg_length); 1144 } else if (!sKeepSymbols && kc_format == KCFormatFileset) { 1145 /* Remove the linkedit segment of the Boot KC */ 1146 kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary); 1147 OSKext::jettisonFileSetLinkeditSegment(mh); 1148 } 1149 #else // !VM_MAPPED_KEXTS 1150 /***** 1151 * Dump the LINKEDIT segment, unless keepsyms is set. 1152 */ 1153 if (!sKeepSymbols && kc_format != KCFormatFileset) { 1154 dt_segment_name = "Kernel-__LINKEDIT"; 1155 if (0 == IODTGetLoaderInfo(dt_segment_name, 1156 &segment_paddress, &segment_size)) { 1157 #ifdef SECURE_KERNEL 1158 vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress); 1159 bzero((void*)vmaddr, segment_size); 1160 #endif 1161 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress, 1162 (int)segment_size); 1163 } 1164 } else { 1165 OSKextLog(/* kext */ NULL, 1166 kOSKextLogBasicLevel | 1167 kOSKextLogGeneralFlag, 1168 "keepsyms boot arg specified; keeping linkedit segment for symbols."); 1169 } 1170 #endif // VM_MAPPED_KEXTS 1171 1172 seg_to_remove = NULL; 1173 1174 result = kOSReturnSuccess; 1175 1176 return result; 1177 } 1178 1179 #if CONFIG_KXLD 1180 /********************************************************************* 1181 *********************************************************************/ 1182 void 1183 OSKext::flushNonloadedKexts( 1184 Boolean flushPrelinkedKexts) 1185 { 1186 OSSharedPtr<OSSet> keepKexts; 1187 1188 /* TODO: make this more efficient with MH_FILESET kexts */ 1189 1190 // Do not unload prelinked kexts on arm because the kernelcache is not 1191 // structured in a way that allows them to be unmapped 1192 #if !defined(__x86_64__) 1193 flushPrelinkedKexts = false; 1194 #endif /* defined(__x86_64__) */ 1195 1196 IORecursiveLockLock(sKextLock); 1197 1198 OSKextLog(/* kext */ NULL, 1199 kOSKextLogProgressLevel | 1200 kOSKextLogKextBookkeepingFlag, 1201 "Flushing nonloaded kexts and other unused data."); 1202 1203 OSKext::considerDestroyingLinkContext(); 1204 1205 /* If we aren't flushing unused prelinked kexts, we have to put them 1206 * aside while we flush everything else so make a container for them. 1207 */ 1208 keepKexts = OSSet::withCapacity(16); 1209 if (!keepKexts) { 1210 goto finish; 1211 } 1212 1213 /* Set aside prelinked kexts (in-use or not) and break 1214 * any lingering inter-kext references for nonloaded kexts 1215 * so they have min. retain counts. 1216 */ 1217 { 1218 sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) { 1219 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1220 if (!thisKext) { 1221 return false; 1222 } 1223 if (!flushPrelinkedKexts && thisKext->isPrelinked()) { 1224 keepKexts->setObject(thisKext); 1225 } else if (!thisKext->declaresExecutable()) { 1226 /* 1227 * Don't unload codeless kexts, because they never appear in the loadedKexts array. 1228 * Requesting one from the IOKit daemon will load it and then immediately remove it by calling 1229 * flushNonloadedKexts(). 1230 * And adding one to loadedKexts breaks code assuming they have kmod_info etc. 1231 */ 1232 keepKexts->setObject(thisKext); 1233 } else if (thisKext->isInFileset()) { 1234 /* keep all kexts in the new MH_FILESET KC */ 1235 keepKexts->setObject(thisKext); 1236 } 1237 1238 thisKext->flushDependencies(/* forceIfLoaded */ false); 1239 return false; 1240 }); 1241 } 1242 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly. 1243 */ 1244 sKextsByID->flushCollection(); 1245 1246 /* Now put the loaded kexts back into the ID dictionary. 1247 */ 1248 sLoadedKexts->iterateObjects(^bool (OSObject * obj) { 1249 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1250 if (!thisKext) { 1251 return false; 1252 } 1253 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1254 return false; 1255 }); 1256 1257 /* Finally, put back the kept kexts if we saved any. 1258 */ 1259 keepKexts->iterateObjects(^bool (OSObject * obj) { 1260 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1261 if (!thisKext) { 1262 return false; 1263 } 1264 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext); 1265 return false; 1266 }); 1267 1268 finish: 1269 IORecursiveLockUnlock(sKextLock); 1270 return; 1271 } 1272 #else /* !CONFIG_KXLD */ 1273 1274 void 1275 OSKext::flushNonloadedKexts( 1276 Boolean flushPrelinkedKexts __unused) 1277 { 1278 IORecursiveLockLock(sKextLock); 1279 1280 OSKextLog(/* kext */ NULL, 1281 kOSKextLogProgressLevel | 1282 kOSKextLogKextBookkeepingFlag, 1283 "Flushing dependency info for non-loaded kexts."); 1284 1285 /* 1286 * In a world where we don't dynamically link kexts, they all come 1287 * from a kext collection that's either in wired memory, or 1288 * wire-on-demand. We don't need to mess around with moving kexts in 1289 * and out of the sKextsByID array - they can all just stay there. 1290 * Here we just flush the dependency list for kexts that are not 1291 * loaded. 1292 */ 1293 sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) { 1294 OSKext * thisKext = OSDynamicCast(OSKext, obj); 1295 if (!thisKext) { 1296 return false; 1297 } 1298 thisKext->flushDependencies(/* forceIfLoaded */ false); 1299 return false; 1300 }); 1301 1302 IORecursiveLockUnlock(sKextLock); 1303 return; 1304 } 1305 1306 #endif /* CONFIG_KXLD */ 1307 1308 /********************************************************************* 1309 *********************************************************************/ 1310 /* static */ 1311 void 1312 OSKext::setIOKitDaemonActive(bool active) 1313 { 1314 IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0); 1315 IORecursiveLockLock(sKextLock); 1316 sIOKitDaemonActive = active; 1317 if (sKernelRequests->getCount()) { 1318 OSKext::pingIOKitDaemon(); 1319 } 1320 IORecursiveLockUnlock(sKextLock); 1321 1322 return; 1323 } 1324 1325 /********************************************************************* 1326 * OSKextLib.cpp might need access to this someday but for now it's 1327 * private. 1328 *********************************************************************/ 1329 extern "C" { 1330 extern void ipc_port_release_send(ipc_port_t); 1331 }; 1332 1333 /* static */ 1334 OSReturn 1335 OSKext::pingIOKitDaemon(void) 1336 { 1337 OSReturn result = kOSReturnError; 1338 #if !NO_KEXTD 1339 mach_port_t kextd_port = IPC_PORT_NULL; 1340 1341 if (!sIOKitDaemonActive) { 1342 result = kOSKextReturnDisabled; // basically unavailable 1343 goto finish; 1344 } 1345 1346 result = host_get_kextd_port(host_priv_self(), &kextd_port); 1347 if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) { 1348 OSKextLog(/* kext */ NULL, 1349 kOSKextLogErrorLevel | 1350 kOSKextLogIPCFlag, 1351 "Can't get " kIOKitDaemonName " port."); 1352 goto finish; 1353 } 1354 1355 result = kextd_ping(kextd_port); 1356 if (result != KERN_SUCCESS) { 1357 OSKextLog(/* kext */ NULL, 1358 kOSKextLogErrorLevel | 1359 kOSKextLogIPCFlag, 1360 kIOKitDaemonName " ping failed (0x%x).", (int)result); 1361 goto finish; 1362 } 1363 1364 finish: 1365 if (IPC_PORT_VALID(kextd_port)) { 1366 ipc_port_release_send(kextd_port); 1367 } 1368 #endif 1369 1370 return result; 1371 } 1372 1373 /********************************************************************* 1374 *********************************************************************/ 1375 /* static */ 1376 void 1377 OSKext::setDeferredLoadSucceeded(Boolean succeeded) 1378 { 1379 IORecursiveLockLock(sKextLock); 1380 sDeferredLoadSucceeded = succeeded; 1381 IORecursiveLockUnlock(sKextLock); 1382 1383 return; 1384 } 1385 1386 /********************************************************************* 1387 * Called from IOSystemShutdownNotification. 1388 *********************************************************************/ 1389 /* static */ 1390 void 1391 OSKext::willShutdown(void) 1392 { 1393 #if !NO_KEXTD 1394 OSReturn checkResult = kOSReturnError; 1395 #endif 1396 OSSharedPtr<OSDictionary> exitRequest; 1397 1398 IORecursiveLockLock(sKextLock); 1399 1400 OSKext::setLoadEnabled(false); 1401 OSKext::setUnloadEnabled(false); 1402 OSKext::setAutounloadsEnabled(false); 1403 OSKext::setKernelRequestsEnabled(false); 1404 1405 #if defined(__x86_64__) || defined(__i386__) 1406 if (IOPMRootDomainGetWillShutdown()) { 1407 OSKext::freeKCFileSetcontrol(); 1408 } 1409 #endif // (__x86_64__) || defined(__i386__) 1410 1411 #if !NO_KEXTD 1412 OSKextLog(/* kext */ NULL, 1413 kOSKextLogProgressLevel | 1414 kOSKextLogGeneralFlag, 1415 "System shutdown; requesting immediate " kIOKitDaemonName " exit."); 1416 1417 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit, 1418 exitRequest); 1419 if (checkResult != kOSReturnSuccess) { 1420 goto finish; 1421 } 1422 if (!sKernelRequests->setObject(exitRequest.get())) { 1423 goto finish; 1424 } 1425 1426 OSKext::pingIOKitDaemon(); 1427 1428 finish: 1429 #endif 1430 1431 IORecursiveLockUnlock(sKextLock); 1432 return; 1433 } 1434 1435 void 1436 OSKext::willUserspaceReboot(void) 1437 { 1438 OSKext::willShutdown(); 1439 IOService::userSpaceWillReboot(); 1440 gIOCatalogue->terminateDriversForUserspaceReboot(); 1441 } 1442 1443 void 1444 OSKext::resetAfterUserspaceReboot(void) 1445 { 1446 OSSharedPtr<OSArray> arr = OSArray::withCapacity(1); 1447 IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */); 1448 1449 IORecursiveLockLock(sKextLock); 1450 gIOCatalogue->resetAfterUserspaceReboot(); 1451 IOService::userSpaceDidReboot(); 1452 OSKext::setLoadEnabled(true); 1453 OSKext::setUnloadEnabled(true); 1454 OSKext::setAutounloadsEnabled(true); 1455 OSKext::setKernelRequestsEnabled(true); 1456 sOSKextWasResetAfterUserspaceReboot = true; 1457 IORecursiveLockUnlock(sKextLock); 1458 } 1459 1460 extern "C" void 1461 OSKextResetAfterUserspaceReboot(void) 1462 { 1463 OSKext::resetAfterUserspaceReboot(); 1464 } 1465 1466 /********************************************************************* 1467 *********************************************************************/ 1468 /* static */ 1469 bool 1470 OSKext::getLoadEnabled(void) 1471 { 1472 bool result; 1473 1474 IORecursiveLockLock(sKextLock); 1475 result = sLoadEnabled; 1476 IORecursiveLockUnlock(sKextLock); 1477 return result; 1478 } 1479 1480 /********************************************************************* 1481 *********************************************************************/ 1482 /* static */ 1483 bool 1484 OSKext::setLoadEnabled(bool flag) 1485 { 1486 bool result; 1487 1488 IORecursiveLockLock(sKextLock); 1489 result = sLoadEnabled; 1490 sLoadEnabled = (flag ? true : false); 1491 1492 if (sLoadEnabled != result) { 1493 OSKextLog(/* kext */ NULL, 1494 kOSKextLogBasicLevel | 1495 kOSKextLogLoadFlag, 1496 "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis"); 1497 } 1498 1499 IORecursiveLockUnlock(sKextLock); 1500 1501 return result; 1502 } 1503 1504 /********************************************************************* 1505 *********************************************************************/ 1506 /* static */ 1507 bool 1508 OSKext::getUnloadEnabled(void) 1509 { 1510 bool result; 1511 1512 IORecursiveLockLock(sKextLock); 1513 result = sUnloadEnabled; 1514 IORecursiveLockUnlock(sKextLock); 1515 return result; 1516 } 1517 1518 /********************************************************************* 1519 *********************************************************************/ 1520 /* static */ 1521 bool 1522 OSKext::setUnloadEnabled(bool flag) 1523 { 1524 bool result; 1525 1526 IORecursiveLockLock(sKextLock); 1527 result = sUnloadEnabled; 1528 sUnloadEnabled = (flag ? true : false); 1529 IORecursiveLockUnlock(sKextLock); 1530 1531 if (sUnloadEnabled != result) { 1532 OSKextLog(/* kext */ NULL, 1533 kOSKextLogBasicLevel | 1534 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1535 "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis"); 1536 } 1537 1538 return result; 1539 } 1540 1541 /********************************************************************* 1542 * Do not call any function that takes sKextLock here! 1543 *********************************************************************/ 1544 /* static */ 1545 bool 1546 OSKext::getAutounloadEnabled(void) 1547 { 1548 bool result; 1549 1550 IORecursiveLockLock(sKextInnerLock); 1551 result = sAutounloadEnabled ? true : false; 1552 IORecursiveLockUnlock(sKextInnerLock); 1553 return result; 1554 } 1555 1556 /********************************************************************* 1557 * Do not call any function that takes sKextLock here! 1558 *********************************************************************/ 1559 /* static */ 1560 bool 1561 OSKext::setAutounloadsEnabled(bool flag) 1562 { 1563 bool result; 1564 1565 IORecursiveLockLock(sKextInnerLock); 1566 1567 result = sAutounloadEnabled; 1568 sAutounloadEnabled = (flag ? true : false); 1569 if (!sAutounloadEnabled && sUnloadCallout) { 1570 thread_call_cancel(sUnloadCallout); 1571 } 1572 1573 if (sAutounloadEnabled != result) { 1574 OSKextLog(/* kext */ NULL, 1575 kOSKextLogBasicLevel | 1576 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 1577 "Kext autounloading now %sabled.", 1578 sAutounloadEnabled ? "en" : "dis"); 1579 } 1580 1581 IORecursiveLockUnlock(sKextInnerLock); 1582 1583 return result; 1584 } 1585 1586 /********************************************************************* 1587 *********************************************************************/ 1588 /* instance method operating on OSKext field */ 1589 bool 1590 OSKext::setAutounloadEnabled(bool flag) 1591 { 1592 bool result = flags.autounloadEnabled ? true : false; 1593 flags.autounloadEnabled = flag ? 1 : 0; 1594 1595 if (result != (flag ? true : false)) { 1596 OSKextLog(this, 1597 kOSKextLogProgressLevel | 1598 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 1599 "Autounloading for kext %s now %sabled.", 1600 getIdentifierCString(), 1601 flags.autounloadEnabled ? "en" : "dis"); 1602 } 1603 return result; 1604 } 1605 1606 /********************************************************************* 1607 *********************************************************************/ 1608 /* static */ 1609 bool 1610 OSKext::setKernelRequestsEnabled(bool flag) 1611 { 1612 bool result; 1613 1614 IORecursiveLockLock(sKextLock); 1615 result = sKernelRequestsEnabled; 1616 sKernelRequestsEnabled = flag ? true : false; 1617 1618 if (sKernelRequestsEnabled != result) { 1619 OSKextLog(/* kext */ NULL, 1620 kOSKextLogBasicLevel | 1621 kOSKextLogGeneralFlag, 1622 "Kernel requests now %sabled.", 1623 sKernelRequestsEnabled ? "en" : "dis"); 1624 } 1625 IORecursiveLockUnlock(sKextLock); 1626 return result; 1627 } 1628 1629 /********************************************************************* 1630 *********************************************************************/ 1631 /* static */ 1632 bool 1633 OSKext::getKernelRequestsEnabled(void) 1634 { 1635 bool result; 1636 1637 IORecursiveLockLock(sKextLock); 1638 result = sKernelRequestsEnabled; 1639 IORecursiveLockUnlock(sKextLock); 1640 return result; 1641 } 1642 1643 static bool 1644 segmentIsMutable(kernel_segment_command_t *seg) 1645 { 1646 /* Mutable segments have to have VM_PROT_WRITE */ 1647 if ((seg->maxprot & VM_PROT_WRITE) == 0) { 1648 return false; 1649 } 1650 /* Exclude the __DATA_CONST segment */ 1651 if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) { 1652 return false; 1653 } 1654 /* Exclude __LINKEDIT */ 1655 if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) { 1656 return false; 1657 } 1658 return true; 1659 } 1660 1661 #if PRAGMA_MARK 1662 #pragma mark Kext Life Cycle 1663 #endif 1664 /********************************************************************* 1665 *********************************************************************/ 1666 OSSharedPtr<OSKext> 1667 OSKext::withPrelinkedInfoDict( 1668 OSDictionary * anInfoDict, 1669 bool doCoalescedSlides, 1670 kc_kind_t type) 1671 { 1672 OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>()); 1673 1674 if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) { 1675 return NULL; 1676 } 1677 1678 return newKext; 1679 } 1680 1681 /********************************************************************* 1682 *********************************************************************/ 1683 bool 1684 OSKext::initWithPrelinkedInfoDict( 1685 OSDictionary * anInfoDict, 1686 bool doCoalescedSlides, 1687 kc_kind_t type) 1688 { 1689 bool result = false; 1690 OSString * kextPath = NULL; // do not release 1691 OSNumber * addressNum = NULL; // reused; do not release 1692 OSNumber * lengthNum = NULL; // reused; do not release 1693 OSBoolean * scratchBool = NULL; // do not release 1694 void * data = NULL; // do not free 1695 void * srcData = NULL; // do not free 1696 OSSharedPtr<OSData> prelinkedExecutable; 1697 uint32_t length = 0; // reused 1698 uintptr_t kext_slide = PE_get_kc_slide(type); 1699 bool shouldSaveSegments = false; 1700 1701 if (!super::init()) { 1702 goto finish; 1703 } 1704 1705 /* Get the path. Don't look for an arch-specific path property. 1706 */ 1707 kextPath = OSDynamicCast(OSString, 1708 anInfoDict->getObject(kPrelinkBundlePathKey)); 1709 1710 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 1711 goto finish; 1712 } 1713 1714 #if KASLR_KEXT_DEBUG 1715 IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString()); 1716 #endif 1717 1718 /* Also get the executable's bundle-relative path if present. 1719 * Don't look for an arch-specific path property. 1720 */ 1721 executableRelPath.reset(OSDynamicCast(OSString, 1722 anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain); 1723 userExecutableRelPath.reset(OSDynamicCast(OSString, 1724 anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain); 1725 1726 /* Don't need the paths to be in the info dictionary any more. 1727 */ 1728 anInfoDict->removeObject(kPrelinkBundlePathKey); 1729 anInfoDict->removeObject(kPrelinkExecutableRelativePathKey); 1730 1731 scratchBool = OSDynamicCast(OSBoolean, 1732 getPropertyForHostArch(kOSBundleRequireExplicitLoadKey)); 1733 if (scratchBool == kOSBooleanTrue) { 1734 flags.requireExplicitLoad = 1; 1735 } 1736 1737 /* Create an OSData wrapper around the linked executable. 1738 */ 1739 addressNum = OSDynamicCast(OSNumber, 1740 anInfoDict->getObject(kPrelinkExecutableLoadKey)); 1741 if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) { 1742 lengthNum = OSDynamicCast(OSNumber, 1743 anInfoDict->getObject(kPrelinkExecutableSizeKey)); 1744 if (!lengthNum) { 1745 OSKextLog(this, 1746 kOSKextLogErrorLevel | 1747 kOSKextLogArchiveFlag, 1748 "Kext %s can't find prelinked kext executable size.", 1749 getIdentifierCString()); 1750 return result; 1751 } 1752 1753 data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 1754 length = (uint32_t) (lengthNum->unsigned32BitValue()); 1755 1756 #if KASLR_KEXT_DEBUG 1757 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n", 1758 (unsigned long)ml_static_unslide((vm_offset_t)data), 1759 (unsigned long)data, 1760 length); 1761 #endif 1762 1763 anInfoDict->removeObject(kPrelinkExecutableLoadKey); 1764 anInfoDict->removeObject(kPrelinkExecutableSizeKey); 1765 1766 /* If the kext's load address differs from its source address, allocate 1767 * space in the kext map at the load address and copy the kext over. 1768 */ 1769 addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey)); 1770 if (addressNum) { 1771 srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 1772 1773 #if KASLR_KEXT_DEBUG 1774 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n", 1775 (unsigned long)ml_static_unslide((vm_offset_t)srcData), 1776 (unsigned long)srcData); 1777 #endif 1778 1779 if (data != srcData) { 1780 #if __LP64__ 1781 kern_return_t alloc_result; 1782 1783 alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE); 1784 if (alloc_result != KERN_SUCCESS) { 1785 OSKextLog(this, 1786 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 1787 "Failed to allocate space for prelinked kext %s.", 1788 getIdentifierCString()); 1789 goto finish; 1790 } 1791 memcpy(data, srcData, length); 1792 #else 1793 OSKextLog(this, 1794 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 1795 "Error: prelinked kext %s - source and load addresses " 1796 "differ on ILP32 architecture.", 1797 getIdentifierCString()); 1798 goto finish; 1799 #endif /* __LP64__ */ 1800 } 1801 1802 anInfoDict->removeObject(kPrelinkExecutableSourceKey); 1803 } 1804 1805 prelinkedExecutable = OSData::withBytesNoCopy(data, length); 1806 if (!prelinkedExecutable) { 1807 OSKextLog(this, 1808 kOSKextLogErrorLevel | 1809 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, 1810 "Kext %s failed to create executable wrapper.", 1811 getIdentifierCString()); 1812 goto finish; 1813 } 1814 1815 #if VM_MAPPED_KEXTS 1816 prelinkedExecutable->setDeallocFunction(osdata_kext_free); 1817 #else 1818 prelinkedExecutable->setDeallocFunction(osdata_phys_free); 1819 #endif 1820 setLinkedExecutable(prelinkedExecutable.get()); 1821 addressNum = OSDynamicCast(OSNumber, 1822 anInfoDict->getObject(kPrelinkKmodInfoKey)); 1823 if (!addressNum) { 1824 OSKextLog(this, 1825 kOSKextLogErrorLevel | 1826 kOSKextLogArchiveFlag, 1827 "Kext %s can't find prelinked kext kmod_info address.", 1828 getIdentifierCString()); 1829 goto finish; 1830 } 1831 1832 if (addressNum->unsigned64BitValue() != 0) { 1833 kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide); 1834 if (kmod_info->address) { 1835 kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide); 1836 } else { 1837 kmod_info->address = (uintptr_t)data; 1838 kmod_info->size = length; 1839 } 1840 #if KASLR_KEXT_DEBUG 1841 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n", 1842 (unsigned long)((vm_offset_t)kmod_info) - kext_slide, 1843 (unsigned long)kmod_info); 1844 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n", 1845 (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide, 1846 (unsigned long)kmod_info->address); 1847 #endif 1848 } 1849 1850 anInfoDict->removeObject(kPrelinkKmodInfoKey); 1851 } 1852 1853 if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) { 1854 uintptr_t builtinTextStart; 1855 uintptr_t builtinTextEnd; 1856 1857 flags.builtin = true; 1858 builtinKmodIdx = addressNum->unsigned32BitValue(); 1859 assert(builtinKmodIdx < gBuiltinKmodsCount); 1860 1861 builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx]; 1862 builtinTextEnd = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1]; 1863 1864 kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx]; 1865 kmod_info->address = builtinTextStart; 1866 kmod_info->size = builtinTextEnd - builtinTextStart; 1867 } 1868 1869 /* If the plist has a UUID for an interface, save that off. 1870 */ 1871 if (isInterface()) { 1872 interfaceUUID.reset(OSDynamicCast(OSData, 1873 anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain); 1874 if (interfaceUUID) { 1875 anInfoDict->removeObject(kPrelinkInterfaceUUIDKey); 1876 } 1877 } 1878 1879 result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides)); 1880 if (!result) { 1881 goto finish; 1882 } 1883 1884 kc_type = type; 1885 /* Exclude builtin and codeless kexts */ 1886 if (prelinkedExecutable && kmod_info) { 1887 switch (kc_type) { 1888 case KCKindPrimary: 1889 shouldSaveSegments = ( 1890 getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue || 1891 getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue); 1892 if (shouldSaveSegments) { 1893 flags.resetSegmentsFromImmutableCopy = 1; 1894 } 1895 break; 1896 case KCKindPageable: 1897 flags.resetSegmentsFromVnode = 1; 1898 break; 1899 case KCKindAuxiliary: 1900 if (!pageableKCloaded) { 1901 flags.resetSegmentsFromImmutableCopy = 1; 1902 } else if (resetAuxKCSegmentOnUnload) { 1903 flags.resetSegmentsFromVnode = 1; 1904 } 1905 break; 1906 default: 1907 break; 1908 } 1909 } 1910 1911 if (flags.resetSegmentsFromImmutableCopy) { 1912 /* Save a pristine copy of the mutable segments */ 1913 kernel_segment_command_t *seg = NULL; 1914 kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address; 1915 1916 savedMutableSegments = OSArray::withCapacity(0); 1917 1918 for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) { 1919 if (!segmentIsMutable(seg)) { 1920 continue; 1921 } 1922 uint64_t unslid_vmaddr = seg->vmaddr - kext_slide; 1923 uint64_t vmsize = seg->vmsize; 1924 OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag, 1925 "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1); 1926 OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg); 1927 if (!savedSegment) { 1928 OSKextLog(this, 1929 kOSKextLogErrorLevel | 1930 kOSKextLogGeneralFlag, 1931 "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 1932 result = kOSKextReturnInternalError; 1933 goto finish; 1934 } 1935 savedMutableSegments->setObject(savedSegment); 1936 } 1937 } 1938 1939 if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) { 1940 /* 1941 * set VM protections now, wire pages for the old style Aux KC now, 1942 * wire pages for the rest of the KC types at load time. 1943 */ 1944 result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false)); 1945 if (!result) { 1946 goto finish; 1947 } 1948 } 1949 1950 flags.prelinked = true; 1951 1952 /* If we created a kext from prelink info, 1953 * we must be booting from a prelinked kernel. 1954 */ 1955 sPrelinkBoot = true; 1956 1957 result = registerIdentifier(); 1958 1959 finish: 1960 return result; 1961 } 1962 1963 /********************************************************************* 1964 *********************************************************************/ 1965 /* static */ 1966 OSSharedPtr<OSKext> 1967 OSKext::withCodelessInfo(OSDictionary * anInfoDict) 1968 { 1969 OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>(); 1970 1971 if (newKext && !newKext->initWithCodelessInfo(anInfoDict)) { 1972 return NULL; 1973 } 1974 1975 return newKext; 1976 } 1977 1978 /********************************************************************* 1979 *********************************************************************/ 1980 bool 1981 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict) 1982 { 1983 bool result = false; 1984 OSString * kextPath = NULL; // do not release 1985 OSBoolean * scratchBool = NULL; // do not release 1986 1987 if (anInfoDict == NULL || !super::init()) { 1988 goto finish; 1989 } 1990 1991 /* 1992 * Get the path. Don't look for an arch-specific path property. 1993 */ 1994 kextPath = OSDynamicCast(OSString, 1995 anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey)); 1996 if (!kextPath) { 1997 OSKextLog(NULL, 1998 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 1999 "Requested codeless kext dictionary does not contain the '%s' key", 2000 kKextRequestArgumentCodelessInfoBundlePathKey); 2001 goto finish; 2002 } 2003 2004 uniquePersonalityProperties(anInfoDict); 2005 2006 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 2007 goto finish; 2008 } 2009 2010 /* 2011 * This path is meant to initialize codeless kexts only. Refuse 2012 * anything that looks like it has an executable and/or declares 2013 * itself as a kernel component. 2014 */ 2015 if (declaresExecutable() || isKernelComponent()) { 2016 OSKextLog(NULL, 2017 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 2018 "Refusing to register codeless kext that declares an executable/kernel component: %s", 2019 getIdentifierCString()); 2020 goto finish; 2021 } 2022 2023 if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) { 2024 boolean_t updated = updateExcludeList(infoDict.get()); 2025 if (updated) { 2026 OSKextLog(this, 2027 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 2028 "KextExcludeList was updated to version: %lld", sExcludeListVersion); 2029 } 2030 } 2031 2032 kc_type = KCKindNone; 2033 2034 scratchBool = OSDynamicCast(OSBoolean, 2035 getPropertyForHostArch(kOSBundleRequireExplicitLoadKey)); 2036 if (scratchBool == kOSBooleanTrue) { 2037 flags.requireExplicitLoad = 1; 2038 } 2039 2040 /* Also get the executable's bundle-relative path if present. 2041 * Don't look for an arch-specific path property. 2042 */ 2043 userExecutableRelPath.reset(OSDynamicCast(OSString, 2044 anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain); 2045 2046 /* remove unnecessary paths from the info dict */ 2047 anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey); 2048 2049 result = registerIdentifier(); 2050 2051 finish: 2052 return result; 2053 } 2054 2055 /********************************************************************* 2056 *********************************************************************/ 2057 /* static */ 2058 void 2059 OSKext::setAllVMAttributes(void) 2060 { 2061 OSSharedPtr<OSCollectionIterator> kextIterator; 2062 const OSSymbol * thisID = NULL; // do not release 2063 2064 IORecursiveLockLock(sKextLock); 2065 2066 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 2067 if (!kextIterator) { 2068 goto finish; 2069 } 2070 2071 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 2072 OSKext * thisKext; // do not release 2073 2074 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 2075 if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) { 2076 continue; 2077 } 2078 2079 if (!thisKext->flags.resetSegmentsFromVnode) { 2080 /* 2081 * set VM protections now, wire pages for the old style Aux KC now, 2082 * wire pages for the rest of the KC types at load time. 2083 */ 2084 thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false); 2085 } 2086 } 2087 2088 finish: 2089 IORecursiveLockUnlock(sKextLock); 2090 2091 return; 2092 } 2093 2094 /********************************************************************* 2095 *********************************************************************/ 2096 OSSharedPtr<OSKext> 2097 OSKext::withBooterData( 2098 OSString * deviceTreeName, 2099 OSData * booterData) 2100 { 2101 OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>()); 2102 2103 if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) { 2104 return NULL; 2105 } 2106 2107 return newKext; 2108 } 2109 2110 /********************************************************************* 2111 *********************************************************************/ 2112 typedef struct _BooterKextFileInfo { 2113 uint32_t infoDictPhysAddr; 2114 uint32_t infoDictLength; 2115 uint32_t executablePhysAddr; 2116 uint32_t executableLength; 2117 uint32_t bundlePathPhysAddr; 2118 uint32_t bundlePathLength; 2119 } _BooterKextFileInfo; 2120 2121 bool 2122 OSKext::initWithBooterData( 2123 OSString * deviceTreeName, 2124 OSData * booterData) 2125 { 2126 bool result = false; 2127 _BooterKextFileInfo * kextFileInfo = NULL; // do not free 2128 char * infoDictAddr = NULL; // do not free 2129 void * executableAddr = NULL; // do not free 2130 char * bundlePathAddr = NULL; // do not free 2131 2132 OSDictionary * theInfoDict = NULL; // do not release 2133 OSSharedPtr<OSObject> parsedXML; 2134 OSSharedPtr<OSString> kextPath; 2135 2136 OSSharedPtr<OSString> errorString; 2137 OSSharedPtr<OSData> executable; 2138 2139 if (!super::init()) { 2140 goto finish; 2141 } 2142 2143 kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy(); 2144 if (!kextFileInfo) { 2145 OSKextLog(this, 2146 kOSKextLogErrorLevel | 2147 kOSKextLogGeneralFlag, 2148 "No booter-provided data for kext device tree entry %s.", 2149 deviceTreeName->getCStringNoCopy()); 2150 goto finish; 2151 } 2152 2153 /* The info plist must exist or we can't read the kext. 2154 */ 2155 if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) { 2156 OSKextLog(this, 2157 kOSKextLogErrorLevel | 2158 kOSKextLogGeneralFlag, 2159 "No kext info dictionary for booter device tree entry %s.", 2160 deviceTreeName->getCStringNoCopy()); 2161 goto finish; 2162 } 2163 2164 infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 2165 if (!infoDictAddr) { 2166 OSKextLog(this, 2167 kOSKextLogErrorLevel | 2168 kOSKextLogGeneralFlag, 2169 "Can't translate physical address 0x%x of kext info dictionary " 2170 "for device tree entry %s.", 2171 (int)kextFileInfo->infoDictPhysAddr, 2172 deviceTreeName->getCStringNoCopy()); 2173 goto finish; 2174 } 2175 2176 parsedXML = OSUnserializeXML(infoDictAddr, errorString); 2177 if (parsedXML) { 2178 theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 2179 } 2180 if (!theInfoDict) { 2181 const char * errorCString = "(unknown error)"; 2182 2183 if (errorString && errorString->getCStringNoCopy()) { 2184 errorCString = errorString->getCStringNoCopy(); 2185 } else if (parsedXML) { 2186 errorCString = "not a dictionary"; 2187 } 2188 OSKextLog(this, 2189 kOSKextLogErrorLevel | 2190 kOSKextLogGeneralFlag, 2191 "Error unserializing info dictionary for device tree entry %s: %s.", 2192 deviceTreeName->getCStringNoCopy(), errorCString); 2193 goto finish; 2194 } 2195 2196 /* A bundle path is not mandatory. 2197 */ 2198 if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) { 2199 bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr); 2200 if (!bundlePathAddr) { 2201 OSKextLog(this, 2202 kOSKextLogErrorLevel | 2203 kOSKextLogGeneralFlag, 2204 "Can't translate physical address 0x%x of kext bundle path " 2205 "for device tree entry %s.", 2206 (int)kextFileInfo->bundlePathPhysAddr, 2207 deviceTreeName->getCStringNoCopy()); 2208 goto finish; 2209 } 2210 bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0'; // just in case! 2211 2212 kextPath = OSString::withCString(bundlePathAddr); 2213 if (!kextPath) { 2214 OSKextLog(this, 2215 kOSKextLogErrorLevel | 2216 kOSKextLogGeneralFlag, 2217 "Failed to create wrapper for device tree entry %s kext path %s.", 2218 deviceTreeName->getCStringNoCopy(), bundlePathAddr); 2219 goto finish; 2220 } 2221 } 2222 2223 if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) { 2224 goto finish; 2225 } 2226 2227 /* An executable is not mandatory. 2228 */ 2229 if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) { 2230 executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr); 2231 if (!executableAddr) { 2232 OSKextLog(this, 2233 kOSKextLogErrorLevel | 2234 kOSKextLogGeneralFlag, 2235 "Can't translate physical address 0x%x of kext executable " 2236 "for device tree entry %s.", 2237 (int)kextFileInfo->executablePhysAddr, 2238 deviceTreeName->getCStringNoCopy()); 2239 goto finish; 2240 } 2241 2242 executable = OSData::withBytesNoCopy(executableAddr, 2243 kextFileInfo->executableLength); 2244 if (!executable) { 2245 OSKextLog(this, 2246 kOSKextLogErrorLevel | 2247 kOSKextLogGeneralFlag, 2248 "Failed to create executable wrapper for device tree entry %s.", 2249 deviceTreeName->getCStringNoCopy()); 2250 goto finish; 2251 } 2252 2253 /* A kext with an executable needs to retain the whole booterData 2254 * object to keep the executable in memory. 2255 */ 2256 if (!setExecutable(executable.get(), booterData)) { 2257 OSKextLog(this, 2258 kOSKextLogErrorLevel | 2259 kOSKextLogGeneralFlag, 2260 "Failed to set kext executable for device tree entry %s.", 2261 deviceTreeName->getCStringNoCopy()); 2262 goto finish; 2263 } 2264 } 2265 2266 result = registerIdentifier(); 2267 2268 finish: 2269 return result; 2270 } 2271 2272 /********************************************************************* 2273 *********************************************************************/ 2274 bool 2275 OSKext::registerIdentifier(void) 2276 { 2277 bool result = false; 2278 OSKext * existingKext = NULL; // do not release 2279 bool existingIsLoaded = false; 2280 bool existingIsPrelinked = false; 2281 bool existingIsCodeless = false; 2282 bool existingIsDext = false; 2283 OSKextVersion newVersion = -1; 2284 OSKextVersion existingVersion = -1; 2285 char newVersionCString[kOSKextVersionMaxLength]; 2286 char existingVersionCString[kOSKextVersionMaxLength]; 2287 OSSharedPtr<OSData> newUUID; 2288 OSSharedPtr<OSData> existingUUID; 2289 2290 IORecursiveLockLock(sKextLock); 2291 2292 /* Get the new kext's version for checks & log messages. 2293 */ 2294 newVersion = getVersion(); 2295 OSKextVersionGetString(newVersion, newVersionCString, 2296 kOSKextVersionMaxLength); 2297 2298 /* If we don't have an existing kext with this identifier, 2299 * just record the new kext and we're done! 2300 */ 2301 existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get())); 2302 if (!existingKext) { 2303 sKextsByID->setObject(bundleID.get(), this); 2304 result = true; 2305 goto finish; 2306 } 2307 2308 /* Get the existing kext's version for checks & log messages. 2309 */ 2310 existingVersion = existingKext->getVersion(); 2311 OSKextVersionGetString(existingVersion, 2312 existingVersionCString, kOSKextVersionMaxLength); 2313 2314 existingIsLoaded = existingKext->isLoaded(); 2315 existingIsPrelinked = existingKext->isPrelinked(); 2316 existingIsDext = existingKext->isDriverKit(); 2317 existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext; 2318 2319 /* If we have a non-codeless kext with this identifier that's already 2320 * loaded/prelinked, we can't use the new one, but let's be really 2321 * thorough and check how the two are related for a precise diagnostic 2322 * log message. 2323 * 2324 * This check is valid for kexts that declare an executable and for 2325 * dexts, but not for codeless kexts - we can just replace those. 2326 */ 2327 if ((!existingIsCodeless || existingIsDext) && 2328 (existingIsLoaded || existingIsPrelinked)) { 2329 bool sameVersion = (newVersion == existingVersion); 2330 bool sameExecutable = true; // assume true unless we have UUIDs 2331 2332 /* Only get the UUID if the existing kext is loaded. Doing so 2333 * might have to uncompress an mkext executable and we shouldn't 2334 * take that hit when neither kext is loaded. 2335 * 2336 * Note: there is no decompression that happens when all kexts 2337 * are loaded from kext collecitons. 2338 */ 2339 newUUID = copyUUID(); 2340 existingUUID = existingKext->copyUUID(); 2341 2342 if (existingIsDext && !isDriverKit()) { 2343 OSKextLog(this, 2344 kOSKextLogWarningLevel | 2345 kOSKextLogKextBookkeepingFlag, 2346 "Notice - new kext %s, v%s matches a %s dext" 2347 "with the same bundle ID, v%s.", 2348 getIdentifierCString(), newVersionCString, 2349 (existingIsLoaded ? "loaded" : "prelinked"), 2350 existingVersionCString); 2351 goto finish; 2352 } 2353 2354 /* I'm entirely too paranoid about checking equivalence of executables, 2355 * but I remember nasty problems with it in the past. 2356 * 2357 * - If we have UUIDs for both kexts, compare them. 2358 * - If only one kext has a UUID, they're definitely different. 2359 */ 2360 if (newUUID && existingUUID) { 2361 sameExecutable = newUUID->isEqualTo(existingUUID.get()); 2362 } else if (newUUID || existingUUID) { 2363 sameExecutable = false; 2364 } 2365 2366 if (!newUUID && !existingUUID) { 2367 /* If there are no UUIDs, we can't really tell that the executables 2368 * are *different* without a lot of work; the loaded kext's 2369 * unrelocated executable is no longer around (and we never had it 2370 * in-kernel for a prelinked kext). We certainly don't want to do 2371 * a whole fake link for the new kext just to compare, either. 2372 */ 2373 OSKextLog(this, 2374 kOSKextLogWarningLevel | 2375 kOSKextLogKextBookkeepingFlag, 2376 "Notice - new kext %s, v%s matches %s kext " 2377 "but can't determine if executables are the same (no UUIDs).", 2378 getIdentifierCString(), 2379 newVersionCString, 2380 (existingIsLoaded ? "loaded" : "prelinked")); 2381 } 2382 2383 if (sameVersion && sameExecutable) { 2384 OSKextLog(this, 2385 (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) | 2386 kOSKextLogKextBookkeepingFlag, 2387 "Refusing new kext %s, v%s: a %s copy is already present " 2388 "(same version and executable).", 2389 getIdentifierCString(), newVersionCString, 2390 (existingIsLoaded ? "loaded" : "prelinked")); 2391 } else { 2392 if (!sameVersion) { 2393 /* This condition is significant so log it under warnings. 2394 */ 2395 OSKextLog(this, 2396 kOSKextLogWarningLevel | 2397 kOSKextLogKextBookkeepingFlag, 2398 "Refusing new kext %s, v%s: already have %s v%s.", 2399 getIdentifierCString(), 2400 newVersionCString, 2401 (existingIsLoaded ? "loaded" : "prelinked"), 2402 existingVersionCString); 2403 } else { 2404 /* This condition is significant so log it under warnings. 2405 */ 2406 OSKextLog(this, 2407 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 2408 "Refusing new kext %s, v%s: a %s copy with a different " 2409 "executable UUID is already present.", 2410 getIdentifierCString(), newVersionCString, 2411 (existingIsLoaded ? "loaded" : "prelinked")); 2412 } 2413 } 2414 goto finish; 2415 } /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */ 2416 2417 /* Refuse to allow an existing loaded codeless kext be replaced by a 2418 * normal kext with the same bundle ID. 2419 */ 2420 if (existingIsCodeless && declaresExecutable()) { 2421 OSKextLog(this, 2422 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag, 2423 "Refusing new kext %s, v%s: a codeless copy is already %s", 2424 getIdentifierCString(), newVersionCString, 2425 (existingIsLoaded ? "loaded" : "prelinked")); 2426 goto finish; 2427 } 2428 2429 /* Dexts packaged in the BootKC will be protected against replacement 2430 * by non-dexts by the logic above which checks if they are prelinked. 2431 * Dexts which are prelinked into the System KC will be registered 2432 * before any other kexts in the AuxKC are registered, and we never 2433 * put dexts in the AuxKC. Therefore, there is no need to check if an 2434 * existing object is a dext and is being replaced by a non-dext. 2435 * The scenario cannot happen by construction. 2436 * 2437 * See: OSKext::loadFileSetKexts() 2438 */ 2439 2440 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether 2441 * user loads are happening or if we're still in early boot. User agents are 2442 * supposed to resolve dependencies topside and include only the exact 2443 * kexts needed; so we always accept the new kext (in fact we should never 2444 * see an older unloaded copy hanging around). 2445 */ 2446 if (sUserLoadsActive) { 2447 sKextsByID->setObject(bundleID.get(), this); 2448 result = true; 2449 2450 OSKextLog(this, 2451 kOSKextLogStepLevel | 2452 kOSKextLogKextBookkeepingFlag, 2453 "Dropping old copy of kext %s (v%s) for newly-added (v%s).", 2454 getIdentifierCString(), 2455 existingVersionCString, 2456 newVersionCString); 2457 2458 goto finish; 2459 } 2460 2461 /* During early boot, the kext with the highest version always wins out. 2462 * Prelinked kernels will never hit this, but mkexts and booter-read 2463 * kexts might have duplicates. 2464 */ 2465 if (newVersion > existingVersion) { 2466 sKextsByID->setObject(bundleID.get(), this); 2467 result = true; 2468 2469 OSKextLog(this, 2470 kOSKextLogStepLevel | 2471 kOSKextLogKextBookkeepingFlag, 2472 "Dropping lower version (v%s) of registered kext %s for higher (v%s).", 2473 existingVersionCString, 2474 getIdentifierCString(), 2475 newVersionCString); 2476 } else { 2477 OSKextLog(this, 2478 kOSKextLogStepLevel | 2479 kOSKextLogKextBookkeepingFlag, 2480 "Kext %s is already registered with a higher/same version (v%s); " 2481 "dropping newly-added (v%s).", 2482 getIdentifierCString(), 2483 existingVersionCString, 2484 newVersionCString); 2485 } 2486 2487 /* result has been set appropriately by now. */ 2488 2489 finish: 2490 2491 IORecursiveLockUnlock(sKextLock); 2492 2493 if (result) { 2494 OSKextLog(this, 2495 kOSKextLogStepLevel | 2496 kOSKextLogKextBookkeepingFlag, 2497 "Kext %s, v%s registered and available for loading.", 2498 getIdentifierCString(), newVersionCString); 2499 } 2500 2501 return result; 2502 } 2503 2504 /********************************************************************* 2505 * Does the bare minimum validation to look up a kext. 2506 * All other validation is done on the spot as needed. 2507 **********************************************************************/ 2508 bool 2509 OSKext::setInfoDictionaryAndPath( 2510 OSDictionary * aDictionary, 2511 OSString * aPath) 2512 { 2513 bool result = false; 2514 OSString * bundleIDString = NULL; // do not release 2515 OSString * versionString = NULL; // do not release 2516 OSString * compatibleVersionString = NULL; // do not release 2517 const char * versionCString = NULL; // do not free 2518 const char * compatibleVersionCString = NULL; // do not free 2519 OSBoolean * scratchBool = NULL; // do not release 2520 OSDictionary * scratchDict = NULL; // do not release 2521 2522 if (infoDict) { 2523 panic("Attempt to set info dictionary on a kext " 2524 "that already has one (%s).", 2525 getIdentifierCString()); 2526 } 2527 2528 if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) { 2529 goto finish; 2530 } 2531 2532 infoDict.reset(aDictionary, OSRetain); 2533 2534 /* Check right away if the info dictionary has any log flags. 2535 */ 2536 scratchBool = OSDynamicCast(OSBoolean, 2537 getPropertyForHostArch(kOSBundleEnableKextLoggingKey)); 2538 if (scratchBool == kOSBooleanTrue) { 2539 flags.loggingEnabled = 1; 2540 } 2541 2542 /* The very next thing to get is the bundle identifier. Unlike 2543 * in user space, a kext with no bundle identifier gets axed 2544 * immediately. 2545 */ 2546 bundleIDString = OSDynamicCast(OSString, 2547 getPropertyForHostArch(kCFBundleIdentifierKey)); 2548 if (!bundleIDString) { 2549 OSKextLog(this, 2550 kOSKextLogErrorLevel | 2551 kOSKextLogValidationFlag, 2552 "CFBundleIdentifier missing/invalid type in kext %s.", 2553 aPath ? aPath->getCStringNoCopy() : "(unknown)"); 2554 goto finish; 2555 } 2556 bundleID = OSSymbol::withString(bundleIDString); 2557 if (!bundleID) { 2558 OSKextLog(this, 2559 kOSKextLogErrorLevel | 2560 kOSKextLogValidationFlag, 2561 "Can't copy bundle identifier as symbol for kext %s.", 2562 bundleIDString->getCStringNoCopy()); 2563 goto finish; 2564 } 2565 2566 /* Save the path if we got one (it should always be available but it's 2567 * just something nice to have for bookkeeping). 2568 */ 2569 if (aPath) { 2570 path.reset(aPath, OSRetain); 2571 } 2572 2573 /***** 2574 * Minimal validation to initialize. We'll do other validation on the spot. 2575 */ 2576 if (bundleID->getLength() >= KMOD_MAX_NAME) { 2577 OSKextLog(this, 2578 kOSKextLogErrorLevel | 2579 kOSKextLogValidationFlag, 2580 "Kext %s error - CFBundleIdentifier over max length %d.", 2581 getIdentifierCString(), KMOD_MAX_NAME - 1); 2582 goto finish; 2583 } 2584 2585 version = compatibleVersion = -1; 2586 2587 versionString = OSDynamicCast(OSString, 2588 getPropertyForHostArch(kCFBundleVersionKey)); 2589 if (!versionString) { 2590 OSKextLog(this, 2591 kOSKextLogErrorLevel | 2592 kOSKextLogValidationFlag, 2593 "Kext %s error - CFBundleVersion missing/invalid type.", 2594 getIdentifierCString()); 2595 goto finish; 2596 } 2597 versionCString = versionString->getCStringNoCopy(); 2598 version = OSKextParseVersionString(versionCString); 2599 if (version < 0) { 2600 OSKextLog(this, 2601 kOSKextLogErrorLevel | 2602 kOSKextLogValidationFlag, 2603 "Kext %s error - CFBundleVersion bad value '%s'.", 2604 getIdentifierCString(), versionCString); 2605 goto finish; 2606 } 2607 2608 compatibleVersion = -1; // set to illegal value for kexts that don't have 2609 2610 compatibleVersionString = OSDynamicCast(OSString, 2611 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 2612 if (compatibleVersionString) { 2613 compatibleVersionCString = compatibleVersionString->getCStringNoCopy(); 2614 compatibleVersion = OSKextParseVersionString(compatibleVersionCString); 2615 if (compatibleVersion < 0) { 2616 OSKextLog(this, 2617 kOSKextLogErrorLevel | 2618 kOSKextLogValidationFlag, 2619 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.", 2620 getIdentifierCString(), compatibleVersionCString); 2621 goto finish; 2622 } 2623 2624 if (compatibleVersion > version) { 2625 OSKextLog(this, 2626 kOSKextLogErrorLevel | 2627 kOSKextLogValidationFlag, 2628 "Kext %s error - %s %s > %s %s (must be <=).", 2629 getIdentifierCString(), 2630 kOSBundleCompatibleVersionKey, compatibleVersionCString, 2631 kCFBundleVersionKey, versionCString); 2632 goto finish; 2633 } 2634 } 2635 2636 /* Check to see if this kext is in exclude list */ 2637 if (isInExcludeList()) { 2638 OSKextLog(this, 2639 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 2640 "Kext %s is in exclude list, not loadable", 2641 getIdentifierCString()); 2642 goto finish; 2643 } 2644 2645 /* Set flags for later use if the infoDict gets flushed. We only 2646 * check for true values, not false ones(!) 2647 */ 2648 scratchBool = OSDynamicCast(OSBoolean, 2649 getPropertyForHostArch(kOSBundleIsInterfaceKey)); 2650 if (scratchBool == kOSBooleanTrue) { 2651 flags.interface = 1; 2652 } 2653 2654 scratchBool = OSDynamicCast(OSBoolean, 2655 getPropertyForHostArch(kOSKernelResourceKey)); 2656 if (scratchBool == kOSBooleanTrue) { 2657 flags.kernelComponent = 1; 2658 flags.interface = 1; // xxx - hm. the kernel itself isn't an interface... 2659 flags.started = 1; 2660 2661 /* A kernel component has one implicit dependency on the kernel. 2662 */ 2663 flags.hasAllDependencies = 1; 2664 } 2665 2666 /* Make sure common string values in personalities are uniqued to OSSymbols. 2667 */ 2668 scratchDict = OSDynamicCast(OSDictionary, 2669 getPropertyForHostArch(kIOKitPersonalitiesKey)); 2670 if (scratchDict) { 2671 uniquePersonalityProperties(scratchDict); 2672 } 2673 2674 result = true; 2675 2676 finish: 2677 2678 return result; 2679 } 2680 2681 /********************************************************************* 2682 * Not used for prelinked kernel boot as there is no unrelocated 2683 * executable. 2684 *********************************************************************/ 2685 bool 2686 OSKext::setExecutable( 2687 OSData * anExecutable, 2688 OSData * externalData, 2689 bool externalDataIsMkext) 2690 { 2691 bool result = false; 2692 const char * executableKey = NULL; // do not free 2693 2694 if (!anExecutable) { 2695 infoDict->removeObject(_kOSKextExecutableKey); 2696 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 2697 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 2698 result = true; 2699 goto finish; 2700 } 2701 2702 if (infoDict->getObject(_kOSKextExecutableKey) || 2703 infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) { 2704 panic("Attempt to set an executable on a kext " 2705 "that already has one (%s).", 2706 getIdentifierCString()); 2707 goto finish; 2708 } 2709 2710 if (externalDataIsMkext) { 2711 executableKey = _kOSKextMkextExecutableReferenceKey; 2712 } else { 2713 executableKey = _kOSKextExecutableKey; 2714 } 2715 2716 if (anExecutable) { 2717 infoDict->setObject(executableKey, anExecutable); 2718 if (externalData) { 2719 infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData); 2720 } 2721 } 2722 2723 result = true; 2724 2725 finish: 2726 return result; 2727 } 2728 2729 /********************************************************************* 2730 *********************************************************************/ 2731 static void 2732 uniqueStringPlistProperty(OSDictionary * dict, const char * key) 2733 { 2734 OSObject * value = NULL; // do not release 2735 OSString * stringValue = NULL; // do not release 2736 OSSharedPtr<const OSSymbol> symbolValue; 2737 2738 value = dict->getObject(key); 2739 if (!value) { 2740 goto finish; 2741 } 2742 if (OSDynamicCast(OSSymbol, value)) { 2743 /* this is already an OSSymbol: we're good */ 2744 goto finish; 2745 } 2746 2747 stringValue = OSDynamicCast(OSString, value); 2748 if (!stringValue) { 2749 goto finish; 2750 } 2751 2752 symbolValue = OSSymbol::withString(stringValue); 2753 if (!symbolValue) { 2754 goto finish; 2755 } 2756 2757 dict->setObject(key, symbolValue.get()); 2758 2759 finish: 2760 return; 2761 } 2762 2763 /********************************************************************* 2764 *********************************************************************/ 2765 static void 2766 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key) 2767 { 2768 OSObject * value = NULL; // do not release 2769 OSString * stringValue = NULL; // do not release 2770 OSSharedPtr<const OSSymbol> symbolValue; 2771 2772 value = dict->getObject(key); 2773 if (!value) { 2774 goto finish; 2775 } 2776 if (OSDynamicCast(OSSymbol, value)) { 2777 /* this is already an OSSymbol: we're good */ 2778 goto finish; 2779 } 2780 2781 stringValue = OSDynamicCast(OSString, value); 2782 if (!stringValue) { 2783 goto finish; 2784 } 2785 2786 symbolValue = OSSymbol::withString(stringValue); 2787 if (!symbolValue) { 2788 goto finish; 2789 } 2790 2791 dict->setObject(key, symbolValue.get()); 2792 2793 finish: 2794 return; 2795 } 2796 2797 void 2798 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict) 2799 { 2800 OSKext::uniquePersonalityProperties(personalityDict, true); 2801 } 2802 2803 /********************************************************************* 2804 * Replace common personality property values with uniqued instances 2805 * to save on wired memory. 2806 *********************************************************************/ 2807 /* static */ 2808 void 2809 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier) 2810 { 2811 /* Properties every personality has. 2812 */ 2813 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey); 2814 uniqueStringPlistProperty(personalityDict, kIOProviderClassKey); 2815 uniqueStringPlistProperty(personalityDict, gIOClassKey.get()); 2816 if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) { 2817 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey); 2818 } else if (defaultAddKernelBundleIdentifier) { 2819 personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey)); 2820 } 2821 2822 /* Other commonly used properties. 2823 */ 2824 uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey); 2825 uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey); 2826 uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey); 2827 2828 uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior"); 2829 uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType"); 2830 uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType"); 2831 uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType"); 2832 uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher"); 2833 uniqueStringPlistProperty(personalityDict, "Physical Interconnect"); 2834 uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location"); 2835 uniqueStringPlistProperty(personalityDict, "Vendor"); 2836 uniqueStringPlistProperty(personalityDict, "Vendor Identification"); 2837 uniqueStringPlistProperty(personalityDict, "Vendor Name"); 2838 uniqueStringPlistProperty(personalityDict, "bConfigurationValue"); 2839 uniqueStringPlistProperty(personalityDict, "bInterfaceNumber"); 2840 uniqueStringPlistProperty(personalityDict, "idProduct"); 2841 2842 return; 2843 } 2844 2845 /********************************************************************* 2846 *********************************************************************/ 2847 void 2848 OSKext::free(void) 2849 { 2850 if (isLoaded()) { 2851 panic("Attempt to free loaded kext %s.", getIdentifierCString()); 2852 } 2853 2854 infoDict.reset(); 2855 bundleID.reset(); 2856 path.reset(); 2857 executableRelPath.reset(); 2858 userExecutableRelPath.reset(); 2859 dependencies.reset(); 2860 linkedExecutable.reset(); 2861 metaClasses.reset(); 2862 interfaceUUID.reset(); 2863 driverKitUUID.reset(); 2864 2865 if (isInterface() && kmod_info) { 2866 kfree(kmod_info, sizeof(kmod_info_t)); 2867 } 2868 2869 super::free(); 2870 return; 2871 } 2872 2873 #if PRAGMA_MARK 2874 #pragma mark Mkext files 2875 #endif 2876 2877 #if CONFIG_KXLD 2878 /* 2879 * mkext archives are really only relevant on kxld-enabled kernels. 2880 * Without a dynamic kernel linker, we don't need to support any mkexts. 2881 */ 2882 2883 /********************************************************************* 2884 *********************************************************************/ 2885 OSReturn 2886 OSKext::readMkextArchive(OSData * mkextData, 2887 uint32_t * checksumPtr) 2888 { 2889 OSReturn result = kOSKextReturnBadData; 2890 uint32_t mkextLength = 0; 2891 mkext_header * mkextHeader = NULL; // do not free 2892 uint32_t mkextVersion = 0; 2893 2894 /* Note default return of kOSKextReturnBadData above. 2895 */ 2896 mkextLength = mkextData->getLength(); 2897 if (mkextLength < sizeof(mkext_basic_header)) { 2898 OSKextLog(/* kext */ NULL, 2899 kOSKextLogErrorLevel | 2900 kOSKextLogArchiveFlag, 2901 "Mkext archive too small to be valid."); 2902 goto finish; 2903 } 2904 2905 mkextHeader = (mkext_header *)mkextData->getBytesNoCopy(); 2906 2907 if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC || 2908 MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) { 2909 OSKextLog(/* kext */ NULL, 2910 kOSKextLogErrorLevel | 2911 kOSKextLogArchiveFlag, 2912 "Mkext archive has invalid magic or signature."); 2913 goto finish; 2914 } 2915 2916 if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) { 2917 OSKextLog(/* kext */ NULL, 2918 kOSKextLogErrorLevel | 2919 kOSKextLogArchiveFlag, 2920 "Mkext archive recorded length doesn't match actual file length."); 2921 goto finish; 2922 } 2923 2924 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 2925 2926 if (mkextVersion == MKEXT_VERS_2) { 2927 result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr); 2928 } else { 2929 OSKextLog(/* kext */ NULL, 2930 kOSKextLogErrorLevel | 2931 kOSKextLogArchiveFlag, 2932 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion); 2933 result = kOSKextReturnUnsupported; 2934 } 2935 2936 finish: 2937 return result; 2938 } 2939 2940 /********************************************************************* 2941 * Assumes magic, signature, version, length have been checked. 2942 * xxx - need to add further bounds checking for each file entry 2943 * 2944 * Should keep track of all kexts created so far, and if we hit a 2945 * fatal error halfway through, remove those kexts. If we've dropped 2946 * an older version that had already been read, whoops! Might want to 2947 * add a level of buffering? 2948 *********************************************************************/ 2949 /* static */ 2950 OSReturn 2951 OSKext::readMkext2Archive( 2952 OSData * mkextData, 2953 OSDictionary ** mkextPlistOut, 2954 uint32_t * checksumPtr) 2955 { 2956 OSReturn result = kOSReturnError; 2957 uint32_t mkextLength; 2958 mkext2_header * mkextHeader = NULL; // do not free 2959 void * mkextEnd = NULL; // do not free 2960 uint32_t mkextVersion; 2961 uint8_t * crc_address = NULL; 2962 size_t crc_buffer_size = 0; 2963 uint32_t checksum; 2964 uint32_t mkextPlistOffset; 2965 uint32_t mkextPlistCompressedSize; 2966 char * mkextPlistEnd = NULL; // do not free 2967 uint32_t mkextPlistFullSize; 2968 OSSharedPtr<OSString> errorString; 2969 OSSharedPtr<OSData> mkextPlistUncompressedData; 2970 const char * mkextPlistDataBuffer = NULL; // do not free 2971 OSSharedPtr<OSObject> parsedXML; 2972 OSDictionary * mkextPlist = NULL; // do not release 2973 OSArray * mkextInfoDictArray = NULL; // do not release 2974 uint32_t count, i; 2975 kc_format_t kc_format; 2976 2977 if (!PE_get_primary_kc_format(&kc_format)) { 2978 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 2979 "Unable to determine primary KC format"); 2980 goto finish; 2981 } 2982 2983 mkextLength = mkextData->getLength(); 2984 mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy(); 2985 mkextEnd = (char *)mkextHeader + mkextLength; 2986 mkextVersion = MKEXT_GET_VERSION(mkextHeader); 2987 2988 crc_address = (u_int8_t *)&mkextHeader->version; 2989 crc_buffer_size = (uintptr_t)mkextHeader + 2990 MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address; 2991 if (crc_buffer_size > INT32_MAX) { 2992 OSKextLog(/* kext */ NULL, 2993 kOSKextLogErrorLevel | 2994 kOSKextLogArchiveFlag, 2995 "Mkext archive size is too large (%lu > INT32_MAX).", 2996 crc_buffer_size); 2997 result = kOSKextReturnBadData; 2998 goto finish; 2999 } 3000 checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size); 3001 3002 if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) { 3003 OSKextLog(/* kext */ NULL, 3004 kOSKextLogErrorLevel | 3005 kOSKextLogArchiveFlag, 3006 "Mkext archive has bad checksum."); 3007 result = kOSKextReturnBadData; 3008 goto finish; 3009 } 3010 3011 if (checksumPtr) { 3012 *checksumPtr = checksum; 3013 } 3014 3015 /* Check that the CPU type & subtype match that of the running kernel. */ 3016 if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) { 3017 OSKextLog(/* kext */ NULL, 3018 kOSKextLogErrorLevel | 3019 kOSKextLogArchiveFlag, 3020 "Mkext archive must have a specific CPU type."); 3021 result = kOSKextReturnBadData; 3022 goto finish; 3023 } else { 3024 if ((UInt32)_mh_execute_header.cputype != 3025 MKEXT_GET_CPUTYPE(mkextHeader)) { 3026 OSKextLog(/* kext */ NULL, 3027 kOSKextLogErrorLevel | 3028 kOSKextLogArchiveFlag, 3029 "Mkext archive does not match the running kernel's CPU type."); 3030 result = kOSKextReturnArchNotFound; 3031 goto finish; 3032 } 3033 } 3034 3035 mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader); 3036 mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader); 3037 mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset + 3038 mkextPlistCompressedSize; 3039 if (mkextPlistEnd > mkextEnd) { 3040 OSKextLog(/* kext */ NULL, 3041 kOSKextLogErrorLevel | 3042 kOSKextLogArchiveFlag, 3043 "Mkext archive file overrun."); 3044 result = kOSKextReturnBadData; 3045 } 3046 3047 mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader); 3048 if (mkextPlistCompressedSize) { 3049 mkextPlistUncompressedData = sKernelKext->extractMkext2FileData( 3050 (UInt8 *)mkextHeader + mkextPlistOffset, 3051 "plist", 3052 mkextPlistCompressedSize, mkextPlistFullSize); 3053 if (!mkextPlistUncompressedData) { 3054 goto finish; 3055 } 3056 mkextPlistDataBuffer = (const char *) 3057 mkextPlistUncompressedData->getBytesNoCopy(); 3058 } else { 3059 mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset; 3060 } 3061 3062 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it. 3063 */ 3064 parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString); 3065 if (parsedXML) { 3066 mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get()); 3067 } 3068 if (!mkextPlist) { 3069 const char * errorCString = "(unknown error)"; 3070 3071 if (errorString && errorString->getCStringNoCopy()) { 3072 errorCString = errorString->getCStringNoCopy(); 3073 } else if (parsedXML) { 3074 errorCString = "not a dictionary"; 3075 } 3076 OSKextLog(/* kext */ NULL, 3077 kOSKextLogErrorLevel | 3078 kOSKextLogArchiveFlag, 3079 "Error unserializing mkext plist: %s.", errorCString); 3080 goto finish; 3081 } 3082 3083 mkextInfoDictArray = OSDynamicCast(OSArray, 3084 mkextPlist->getObject(kMKEXTInfoDictionariesKey)); 3085 if (!mkextInfoDictArray) { 3086 OSKextLog(/* kext */ NULL, 3087 kOSKextLogErrorLevel | 3088 kOSKextLogArchiveFlag, 3089 "Mkext archive contains no kext info dictionaries."); 3090 goto finish; 3091 } 3092 3093 count = mkextInfoDictArray->getCount(); 3094 for (i = 0; i < count; i++) { 3095 OSDictionary * infoDict; 3096 3097 3098 infoDict = OSDynamicCast(OSDictionary, 3099 mkextInfoDictArray->getObject(i)); 3100 3101 /* Create the kext for the entry, then release it, because the 3102 * kext system keeps them around until explicitly removed. 3103 * Any creation/registration failures are already logged for us. 3104 */ 3105 if (infoDict) { 3106 OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData); 3107 3108 /* Fail dynamic loading of a kext when booted from MH_FILESET */ 3109 if (kc_format == KCFormatFileset && 3110 newKext && 3111 !(newKext->isPrelinked()) && 3112 newKext->declaresExecutable()) { 3113 result = kOSReturnError; 3114 printf("Kext LOG: Dynamic loading of kext denied for kext %s\n", 3115 newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext"); 3116 3117 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 3118 "Dynamic loading of kext denied for kext %s\n", 3119 newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext"); 3120 goto finish; 3121 } 3122 } 3123 } 3124 3125 /* If the caller needs the plist, hand them back our copy 3126 */ 3127 if (mkextPlistOut) { 3128 *mkextPlistOut = mkextPlist; 3129 parsedXML.detach(); 3130 } 3131 3132 /* Even if we didn't keep any kexts from the mkext, we may have a load 3133 * request to process, so we are successful (no errors occurred). 3134 */ 3135 result = kOSReturnSuccess; 3136 3137 finish: 3138 return result; 3139 } 3140 3141 /* static */ 3142 OSReturn 3143 OSKext::readMkext2Archive( 3144 OSData * mkextData, 3145 OSSharedPtr<OSDictionary> &mkextPlistOut, 3146 uint32_t * checksumPtr) 3147 { 3148 OSDictionary * mkextPlist = NULL; 3149 OSReturn ret; 3150 3151 if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData, 3152 &mkextPlist, 3153 checksumPtr))) { 3154 mkextPlistOut.reset(mkextPlist, OSNoRetain); 3155 } 3156 return ret; 3157 } 3158 3159 /********************************************************************* 3160 *********************************************************************/ 3161 /* static */ 3162 OSSharedPtr<OSKext> 3163 OSKext::withMkext2Info( 3164 OSDictionary * anInfoDict, 3165 OSData * mkextData) 3166 { 3167 OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>(); 3168 3169 if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) { 3170 return NULL; 3171 } 3172 3173 return newKext; 3174 } 3175 3176 /********************************************************************* 3177 *********************************************************************/ 3178 bool 3179 OSKext::initWithMkext2Info( 3180 OSDictionary * anInfoDict, 3181 OSData * mkextData) 3182 { 3183 bool result = false; 3184 OSString * kextPath = NULL; // do not release 3185 OSNumber * executableOffsetNum = NULL; // do not release 3186 OSSharedPtr<OSData> executable; 3187 3188 if (anInfoDict == NULL || !super::init()) { 3189 goto finish; 3190 } 3191 3192 /* Get the path. Don't look for an arch-specific path property. 3193 */ 3194 kextPath = OSDynamicCast(OSString, 3195 anInfoDict->getObject(kMKEXTBundlePathKey)); 3196 3197 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) { 3198 goto finish; 3199 } 3200 3201 /* If we have a path to the executable, save it. 3202 */ 3203 executableRelPath.reset(OSDynamicCast(OSString, 3204 anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain); 3205 3206 /* Don't need the paths to be in the info dictionary any more. 3207 */ 3208 anInfoDict->removeObject(kMKEXTBundlePathKey); 3209 anInfoDict->removeObject(kMKEXTExecutableRelativePathKey); 3210 3211 executableOffsetNum = OSDynamicCast(OSNumber, 3212 infoDict->getObject(kMKEXTExecutableKey)); 3213 if (executableOffsetNum) { 3214 executable = createMkext2FileEntry(mkextData, 3215 executableOffsetNum, "executable"); 3216 infoDict->removeObject(kMKEXTExecutableKey); 3217 if (!executable) { 3218 goto finish; 3219 } 3220 if (!setExecutable(executable.get(), mkextData, true)) { 3221 goto finish; 3222 } 3223 } 3224 3225 result = registerIdentifier(); 3226 3227 finish: 3228 return result; 3229 } 3230 3231 /********************************************************************* 3232 *********************************************************************/ 3233 OSSharedPtr<OSData> 3234 OSKext::createMkext2FileEntry( 3235 OSData * mkextData, 3236 OSNumber * offsetNum, 3237 const char * name) 3238 { 3239 OSSharedPtr<OSData> result; 3240 MkextEntryRef entryRef; 3241 uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy(); 3242 uint32_t entryOffset = offsetNum->unsigned32BitValue(); 3243 3244 result = OSData::withCapacity(sizeof(entryRef)); 3245 if (!result) { 3246 goto finish; 3247 } 3248 3249 entryRef.mkext = (mkext_basic_header *)mkextBuffer; 3250 entryRef.fileinfo = mkextBuffer + entryOffset; 3251 if (!result->appendBytes(&entryRef, sizeof(entryRef))) { 3252 result.reset(); 3253 goto finish; 3254 } 3255 3256 finish: 3257 if (!result) { 3258 OSKextLog(this, 3259 kOSKextLogErrorLevel | 3260 kOSKextLogArchiveFlag, 3261 "Can't create wrapper for mkext file entry '%s' of kext %s.", 3262 name, getIdentifierCString()); 3263 } 3264 return result; 3265 } 3266 3267 /********************************************************************* 3268 *********************************************************************/ 3269 extern "C" { 3270 static void * z_alloc(void *, u_int items, u_int size); 3271 static void z_free(void *, void *ptr); 3272 3273 typedef struct z_mem { 3274 uint32_t alloc_size; 3275 uint8_t data[0]; 3276 } z_mem; 3277 3278 /* 3279 * Space allocation and freeing routines for use by zlib routines. 3280 */ 3281 void * 3282 z_alloc(void * notused __unused, u_int num_items, u_int size) 3283 { 3284 void * result = NULL; 3285 z_mem * zmem = NULL; 3286 3287 uint64_t total = ((uint64_t)num_items) * ((uint64_t)size); 3288 //Check for overflow due to multiplication 3289 if (total > UINT32_MAX) { 3290 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n", 3291 notused, num_items, size, num_items, size); 3292 } 3293 3294 uint64_t allocSize64 = total + ((uint64_t)sizeof(zmem)); 3295 //Check for overflow due to addition 3296 if (allocSize64 > UINT32_MAX) { 3297 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n", 3298 notused, num_items, size, (uint32_t)total, sizeof(zmem)); 3299 } 3300 uint32_t allocSize = (uint32_t)allocSize64; 3301 3302 zmem = (z_mem *)kheap_alloc_tag(KHEAP_DATA_BUFFERS, allocSize, 3303 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 3304 if (!zmem) { 3305 goto finish; 3306 } 3307 zmem->alloc_size = allocSize; 3308 result = (void *)&(zmem->data); 3309 finish: 3310 return result; 3311 } 3312 3313 void 3314 z_free(void * notused __unused, void * ptr) 3315 { 3316 uint32_t * skipper = (uint32_t *)ptr - 1; 3317 z_mem * zmem = (z_mem *)skipper; 3318 kheap_free(KHEAP_DATA_BUFFERS, zmem, zmem->alloc_size); 3319 return; 3320 } 3321 }; 3322 3323 OSSharedPtr<OSData> 3324 OSKext::extractMkext2FileData( 3325 UInt8 * data, 3326 const char * name, 3327 uint32_t compressedSize, 3328 uint32_t fullSize) 3329 { 3330 OSSharedPtr<OSData> result; 3331 OSSharedPtr<OSData> uncompressedData; // release on error 3332 3333 uint8_t * uncompressedDataBuffer = NULL; // do not free 3334 unsigned long uncompressedSize; 3335 z_stream zstream; 3336 bool zstream_inited = false; 3337 int zlib_result; 3338 3339 /* If the file isn't compressed, we want to make a copy 3340 * so that we don't have the tie to the larger mkext file buffer any more. 3341 */ 3342 if (!compressedSize) { 3343 uncompressedData = OSData::withBytes(data, fullSize); 3344 // xxx - no check for failure? 3345 result = uncompressedData; 3346 goto finish; 3347 } 3348 3349 if (KERN_SUCCESS != kmem_alloc(kernel_map, 3350 (vm_offset_t*)&uncompressedDataBuffer, fullSize, VM_KERN_MEMORY_OSKEXT)) { 3351 /* How's this for cheesy? The kernel is only asked to extract 3352 * kext plists so we tailor the log messages. 3353 */ 3354 if (isKernel()) { 3355 OSKextLog(this, 3356 kOSKextLogErrorLevel | 3357 kOSKextLogArchiveFlag, 3358 "Allocation failure extracting %s from mkext.", name); 3359 } else { 3360 OSKextLog(this, 3361 kOSKextLogErrorLevel | 3362 kOSKextLogArchiveFlag, 3363 "Allocation failure extracting %s from mkext for kext %s.", 3364 name, getIdentifierCString()); 3365 } 3366 3367 goto finish; 3368 } 3369 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize); 3370 if (!uncompressedData) { 3371 if (isKernel()) { 3372 OSKextLog(this, 3373 kOSKextLogErrorLevel | 3374 kOSKextLogArchiveFlag, 3375 "Allocation failure extracting %s from mkext.", name); 3376 } else { 3377 OSKextLog(this, 3378 kOSKextLogErrorLevel | 3379 kOSKextLogArchiveFlag, 3380 "Allocation failure extracting %s from mkext for kext %s.", 3381 name, getIdentifierCString()); 3382 } 3383 goto finish; 3384 } 3385 uncompressedData->setDeallocFunction(&osdata_kmem_free); 3386 3387 if (isKernel()) { 3388 OSKextLog(this, 3389 kOSKextLogDetailLevel | 3390 kOSKextLogArchiveFlag, 3391 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.", 3392 name, compressedSize, fullSize); 3393 } else { 3394 OSKextLog(this, 3395 kOSKextLogDetailLevel | 3396 kOSKextLogArchiveFlag, 3397 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.", 3398 getIdentifierCString(), name, compressedSize, fullSize); 3399 } 3400 3401 bzero(&zstream, sizeof(zstream)); 3402 zstream.next_in = (UInt8 *)data; 3403 zstream.avail_in = compressedSize; 3404 3405 zstream.next_out = uncompressedDataBuffer; 3406 zstream.avail_out = fullSize; 3407 3408 zstream.zalloc = z_alloc; 3409 zstream.zfree = z_free; 3410 3411 zlib_result = inflateInit(&zstream); 3412 if (Z_OK != zlib_result) { 3413 if (isKernel()) { 3414 OSKextLog(this, 3415 kOSKextLogErrorLevel | 3416 kOSKextLogArchiveFlag, 3417 "Mkext error; zlib inflateInit failed (%d) for %s.", 3418 zlib_result, name); 3419 } else { 3420 OSKextLog(this, 3421 kOSKextLogErrorLevel | 3422 kOSKextLogArchiveFlag, 3423 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .", 3424 getIdentifierCString(), zlib_result, name); 3425 } 3426 goto finish; 3427 } else { 3428 zstream_inited = true; 3429 } 3430 3431 zlib_result = inflate(&zstream, Z_FINISH); 3432 3433 if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) { 3434 uncompressedSize = zstream.total_out; 3435 } else { 3436 if (isKernel()) { 3437 OSKextLog(this, 3438 kOSKextLogErrorLevel | 3439 kOSKextLogArchiveFlag, 3440 "Mkext error; zlib inflate failed (%d) for %s.", 3441 zlib_result, name); 3442 } else { 3443 OSKextLog(this, 3444 kOSKextLogErrorLevel | 3445 kOSKextLogArchiveFlag, 3446 "Kext %s - mkext error; zlib inflate failed (%d) for %s .", 3447 getIdentifierCString(), zlib_result, name); 3448 } 3449 if (zstream.msg) { 3450 OSKextLog(this, 3451 kOSKextLogErrorLevel | 3452 kOSKextLogArchiveFlag, 3453 "zlib error: %s.", zstream.msg); 3454 } 3455 goto finish; 3456 } 3457 3458 if (uncompressedSize != fullSize) { 3459 if (isKernel()) { 3460 OSKextLog(this, 3461 kOSKextLogErrorLevel | 3462 kOSKextLogArchiveFlag, 3463 "Mkext error; zlib inflate discrepancy for %s, " 3464 "uncompressed size != original size.", name); 3465 } else { 3466 OSKextLog(this, 3467 kOSKextLogErrorLevel | 3468 kOSKextLogArchiveFlag, 3469 "Kext %s - mkext error; zlib inflate discrepancy for %s, " 3470 "uncompressed size != original size.", 3471 getIdentifierCString(), name); 3472 } 3473 goto finish; 3474 } 3475 3476 result = os::move(uncompressedData); 3477 3478 finish: 3479 /* Don't bother checking return, nothing we can do on fail. 3480 */ 3481 if (zstream_inited) { 3482 inflateEnd(&zstream); 3483 } 3484 3485 return result; 3486 } 3487 3488 /********************************************************************* 3489 *********************************************************************/ 3490 /* static */ 3491 OSReturn 3492 OSKext::loadFromMkext( 3493 OSKextLogSpec clientLogFilter, 3494 char * mkextBuffer, 3495 uint32_t mkextBufferLength, 3496 char ** logInfoOut, 3497 uint32_t * logInfoLengthOut) 3498 { 3499 OSReturn result = kOSReturnError; 3500 OSReturn tempResult = kOSReturnError; 3501 3502 OSSharedPtr<OSData> mkextData; 3503 OSSharedPtr<OSDictionary> mkextPlist; 3504 3505 OSSharedPtr<OSArray> logInfoArray; 3506 OSSharedPtr<OSSerialize> serializer; 3507 3508 OSString * predicate = NULL; // do not release 3509 OSDictionary * requestArgs = NULL; // do not release 3510 3511 OSString * kextIdentifier = NULL; // do not release 3512 OSNumber * startKextExcludeNum = NULL; // do not release 3513 OSNumber * startMatchingExcludeNum = NULL; // do not release 3514 OSBoolean * delayAutounloadBool = NULL; // do not release 3515 OSArray * personalityNames = NULL; // do not release 3516 3517 /* Default values for these two options: regular autounload behavior, 3518 * load all kexts, send no personalities. 3519 */ 3520 Boolean delayAutounload = false; 3521 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 3522 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll; 3523 3524 IORecursiveLockLock(sKextLock); 3525 3526 if (logInfoOut) { 3527 *logInfoOut = NULL; 3528 *logInfoLengthOut = 0; 3529 } 3530 3531 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 3532 3533 OSKextLog(/* kext */ NULL, 3534 kOSKextLogDebugLevel | 3535 kOSKextLogIPCFlag, 3536 "Received kext load request from user space."); 3537 3538 /* Regardless of processing, the fact that we have gotten here means some 3539 * user-space program is up and talking to us, so we'll switch our kext 3540 * registration to reflect that. 3541 */ 3542 if (!sUserLoadsActive) { 3543 OSKextLog(/* kext */ NULL, 3544 kOSKextLogProgressLevel | 3545 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 3546 "Switching to late startup (user-space) kext loading policy."); 3547 3548 sUserLoadsActive = true; 3549 } 3550 3551 if (!sLoadEnabled) { 3552 OSKextLog(/* kext */ NULL, 3553 kOSKextLogErrorLevel | 3554 kOSKextLogLoadFlag, 3555 "Kext loading is disabled."); 3556 result = kOSKextReturnDisabled; 3557 goto finish; 3558 } 3559 3560 /* Note that we do not set a dealloc function on this OSData 3561 * object! No references to it can remain after the loadFromMkext() 3562 * call since we are in a MIG function, and will vm_deallocate() 3563 * the buffer. 3564 */ 3565 mkextData = OSData::withBytesNoCopy(mkextBuffer, 3566 mkextBufferLength); 3567 if (!mkextData) { 3568 OSKextLog(/* kext */ NULL, 3569 kOSKextLogErrorLevel | 3570 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 3571 "Failed to create wrapper for kext load request."); 3572 result = kOSKextReturnNoMemory; 3573 goto finish; 3574 } 3575 3576 result = readMkext2Archive(mkextData.get(), mkextPlist, NULL); 3577 if (result != kOSReturnSuccess) { 3578 OSKextLog(/* kext */ NULL, 3579 kOSKextLogErrorLevel | 3580 kOSKextLogLoadFlag, 3581 "Failed to read kext load request."); 3582 goto finish; 3583 } 3584 3585 predicate = _OSKextGetRequestPredicate(mkextPlist.get()); 3586 if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) { 3587 OSKextLog(/* kext */ NULL, 3588 kOSKextLogErrorLevel | 3589 kOSKextLogLoadFlag, 3590 "Received kext load request with no predicate; skipping."); 3591 result = kOSKextReturnInvalidArgument; 3592 goto finish; 3593 } 3594 3595 requestArgs = OSDynamicCast(OSDictionary, 3596 mkextPlist->getObject(kKextRequestArgumentsKey)); 3597 if (!requestArgs || !requestArgs->getCount()) { 3598 OSKextLog(/* kext */ NULL, 3599 kOSKextLogErrorLevel | 3600 kOSKextLogLoadFlag, 3601 "Received kext load request with no arguments."); 3602 result = kOSKextReturnInvalidArgument; 3603 goto finish; 3604 } 3605 3606 kextIdentifier = OSDynamicCast(OSString, 3607 requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey)); 3608 3609 if (!kextIdentifier) { 3610 OSKextLog(/* kext */ NULL, 3611 kOSKextLogErrorLevel | 3612 kOSKextLogLoadFlag, 3613 "Received kext load request with no kext identifier."); 3614 result = kOSKextReturnInvalidArgument; 3615 goto finish; 3616 } 3617 3618 startKextExcludeNum = OSDynamicCast(OSNumber, 3619 requestArgs->getObject(kKextRequestArgumentStartExcludeKey)); 3620 startMatchingExcludeNum = OSDynamicCast(OSNumber, 3621 requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey)); 3622 delayAutounloadBool = OSDynamicCast(OSBoolean, 3623 requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey)); 3624 personalityNames = OSDynamicCast(OSArray, 3625 requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey)); 3626 3627 if (delayAutounloadBool) { 3628 delayAutounload = delayAutounloadBool->getValue(); 3629 } 3630 if (startKextExcludeNum) { 3631 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 3632 } 3633 if (startMatchingExcludeNum) { 3634 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 3635 } 3636 3637 OSKextLog(/* kext */ NULL, 3638 kOSKextLogProgressLevel | 3639 kOSKextLogIPCFlag, 3640 "Received request from user space to load kext %s.", 3641 kextIdentifier->getCStringNoCopy()); 3642 3643 /* Load the kext, with no deferral, since this is a load from outside 3644 * the kernel. 3645 * xxx - Would like a better way to handle the default values for the 3646 * xxx - start/match opt args. 3647 */ 3648 result = OSKext::loadKextWithIdentifier( 3649 kextIdentifier, 3650 /* kextRef */ NULL, 3651 /* allowDefer */ false, 3652 delayAutounload, 3653 startKextExcludeLevel, 3654 startMatchingExcludeLevel, 3655 personalityNames); 3656 if (result != kOSReturnSuccess) { 3657 goto finish; 3658 } 3659 /* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue 3660 * for matching via a separate IOKit calldown. 3661 */ 3662 3663 finish: 3664 3665 /* Gather up the collected log messages for user space. Any 3666 * error messages past this call will not make it up as log messages 3667 * but will be in the system log. 3668 */ 3669 logInfoArray = OSKext::clearUserSpaceLogFilter(); 3670 3671 if (logInfoArray && logInfoOut && logInfoLengthOut) { 3672 tempResult = OSKext::serializeLogInfo(logInfoArray.get(), 3673 logInfoOut, logInfoLengthOut); 3674 if (tempResult != kOSReturnSuccess) { 3675 result = tempResult; 3676 } 3677 } 3678 3679 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false); 3680 3681 IORecursiveLockUnlock(sKextLock); 3682 3683 /* Note: mkextDataObject will have been retained by every kext w/an 3684 * executable in it. That should all have been flushed out at the 3685 * and of the load operation, but you never know.... 3686 */ 3687 if (mkextData && mkextData->getRetainCount() > 1) { 3688 OSKextLog(/* kext */ NULL, 3689 kOSKextLogErrorLevel | 3690 kOSKextLogLoadFlag | kOSKextLogIPCFlag, 3691 "Kext load request buffer from user space still retained by a kext; " 3692 "probable memory leak."); 3693 } 3694 3695 return result; 3696 } 3697 3698 #endif // CONFIG_KXLD 3699 3700 /********************************************************************* 3701 *********************************************************************/ 3702 /* static */ 3703 OSReturn 3704 OSKext::serializeLogInfo( 3705 OSArray * logInfoArray, 3706 char ** logInfoOut, 3707 uint32_t * logInfoLengthOut) 3708 { 3709 OSReturn result = kOSReturnError; 3710 char * buffer = NULL; 3711 kern_return_t kmem_result = KERN_FAILURE; 3712 OSSharedPtr<OSSerialize> serializer; 3713 char * logInfo = NULL; // returned by reference 3714 uint32_t logInfoLength = 0; 3715 3716 if (!logInfoArray || !logInfoOut || !logInfoLengthOut) { 3717 OSKextLog(/* kext */ NULL, 3718 kOSKextLogErrorLevel | 3719 kOSKextLogIPCFlag, 3720 "Internal error; invalid arguments to OSKext::serializeLogInfo()."); 3721 /* Bad programmer. */ 3722 result = kOSKextReturnInvalidArgument; 3723 goto finish; 3724 } 3725 3726 serializer = OSSerialize::withCapacity(0); 3727 if (!serializer) { 3728 OSKextLog(/* kext */ NULL, 3729 kOSKextLogErrorLevel | 3730 kOSKextLogIPCFlag, 3731 "Failed to create serializer on log info for request from user space."); 3732 /* Incidental error; we're going to (try to) allow the request 3733 * itself to succeed. */ 3734 } 3735 3736 if (!logInfoArray->serialize(serializer.get())) { 3737 OSKextLog(/* kext */ NULL, 3738 kOSKextLogErrorLevel | 3739 kOSKextLogIPCFlag, 3740 "Failed to serialize log info for request from user space."); 3741 /* Incidental error; we're going to (try to) allow the request 3742 * itself to succeed. */ 3743 } else { 3744 logInfo = serializer->text(); 3745 logInfoLength = serializer->getLength(); 3746 3747 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT); 3748 if (kmem_result != KERN_SUCCESS) { 3749 OSKextLog(/* kext */ NULL, 3750 kOSKextLogErrorLevel | 3751 kOSKextLogIPCFlag, 3752 "Failed to copy log info for request from user space."); 3753 /* Incidental error; we're going to (try to) allow the request 3754 * to succeed. */ 3755 } else { 3756 /* 11981737 - clear uninitialized data in last page */ 3757 bzero((void *)(buffer + logInfoLength), 3758 (round_page(logInfoLength) - logInfoLength)); 3759 memcpy(buffer, logInfo, logInfoLength); 3760 *logInfoOut = buffer; 3761 *logInfoLengthOut = logInfoLength; 3762 } 3763 } 3764 3765 result = kOSReturnSuccess; 3766 finish: 3767 return result; 3768 } 3769 3770 #if PRAGMA_MARK 3771 #pragma mark Instance Management Methods 3772 #endif 3773 /********************************************************************* 3774 *********************************************************************/ 3775 OSSharedPtr<OSKext> 3776 OSKext::lookupKextWithIdentifier(const char * kextIdentifier) 3777 { 3778 OSSharedPtr<OSKext> foundKext; 3779 3780 IORecursiveLockLock(sKextLock); 3781 foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain); 3782 IORecursiveLockUnlock(sKextLock); 3783 3784 return foundKext; 3785 } 3786 3787 /********************************************************************* 3788 *********************************************************************/ 3789 OSSharedPtr<OSKext> 3790 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier) 3791 { 3792 return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy()); 3793 } 3794 3795 /********************************************************************* 3796 *********************************************************************/ 3797 OSSharedPtr<OSKext> 3798 OSKext::lookupKextWithLoadTag(uint32_t aTag) 3799 { 3800 OSSharedPtr<OSKext> foundKext; // returned 3801 uint32_t i, j; 3802 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 3803 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 3804 3805 IORecursiveLockLock(sKextLock); 3806 3807 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 3808 for (i = 0; i < count[j]; i++) { 3809 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 3810 if (thisKext->getLoadTag() == aTag) { 3811 foundKext.reset(thisKext, OSRetain); 3812 goto finish; 3813 } 3814 } 3815 } 3816 3817 finish: 3818 IORecursiveLockUnlock(sKextLock); 3819 3820 return foundKext; 3821 } 3822 3823 /********************************************************************* 3824 *********************************************************************/ 3825 OSSharedPtr<OSKext> 3826 OSKext::lookupKextWithAddress(vm_address_t address) 3827 { 3828 OSSharedPtr<OSKext> foundKext; // returned 3829 uint32_t count, i; 3830 kmod_info_t *kmod_info; 3831 #if defined(__arm64__) 3832 uint64_t textExecBase; 3833 size_t textExecSize; 3834 #endif /* defined(__arm64__) */ 3835 3836 #if __has_feature(ptrauth_calls) 3837 address = (vm_address_t)VM_KERNEL_STRIP_PTR(address); 3838 #endif /* __has_feature(ptrauth_calls) */ 3839 3840 IORecursiveLockLock(sKextLock); 3841 3842 count = sLoadedKexts->getCount(); 3843 for (i = 0; i < count; i++) { 3844 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 3845 if (thisKext == sKernelKext) { 3846 continue; 3847 } 3848 if (thisKext->kmod_info && thisKext->kmod_info->address) { 3849 kmod_info = thisKext->kmod_info; 3850 vm_address_t kext_start = kmod_info->address; 3851 vm_address_t kext_end = kext_start + kmod_info->size; 3852 if ((kext_start <= address) && (address < kext_end)) { 3853 foundKext.reset(thisKext, OSRetain); 3854 goto finish; 3855 } 3856 #if defined(__arm64__) 3857 textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize); 3858 if ((textExecBase <= address) && (address < textExecBase + textExecSize)) { 3859 foundKext.reset(thisKext, OSRetain); 3860 goto finish; 3861 } 3862 #endif /* defined (__arm64__) */ 3863 } 3864 } 3865 if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) { 3866 foundKext.reset(sKernelKext, OSRetain); 3867 goto finish; 3868 } 3869 /* 3870 * DriverKit userspace executables do not have a kernel linkedExecutable, 3871 * so we "fake" their address range with the LoadTag. 3872 * 3873 * This is supposed to be used for logging reasons only. When logd 3874 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we 3875 * remove it here before checking it against the LoadTag. 3876 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line. 3877 */ 3878 3879 address = address & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT); 3880 count = sLoadedDriverKitKexts->getCount(); 3881 for (i = 0; i < count; i++) { 3882 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i)); 3883 if (thisKext->getLoadTag() == address) { 3884 foundKext.reset(thisKext, OSRetain); 3885 } 3886 } 3887 3888 finish: 3889 IORecursiveLockUnlock(sKextLock); 3890 3891 return foundKext; 3892 } 3893 3894 OSSharedPtr<OSData> 3895 OSKext::copyKextUUIDForAddress(OSNumber *address) 3896 { 3897 OSSharedPtr<OSData> uuid; 3898 OSSharedPtr<OSKext> kext; 3899 3900 if (!address) { 3901 return NULL; 3902 } 3903 3904 uintptr_t addr = ml_static_slide((uintptr_t)address->unsigned64BitValue()); 3905 if (addr == 0) { 3906 return NULL; 3907 } 3908 #if __has_feature(ptrauth_calls) 3909 addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr); 3910 #endif /* __has_feature(ptrauth_calls) */ 3911 3912 #if CONFIG_MACF 3913 /* Is the calling process allowed to query kext info? */ 3914 if (current_task() != kernel_task) { 3915 int macCheckResult = 0; 3916 kauth_cred_t cred = NULL; 3917 3918 cred = kauth_cred_get_with_ref(); 3919 macCheckResult = mac_kext_check_query(cred); 3920 kauth_cred_unref(&cred); 3921 3922 if (macCheckResult != 0) { 3923 OSKextLog(/* kext */ NULL, 3924 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 3925 "Failed to query kext UUID (MAC policy error 0x%x).", 3926 macCheckResult); 3927 return NULL; 3928 } 3929 } 3930 #endif 3931 kext = lookupKextWithAddress(addr); 3932 if (kext) { 3933 uuid = kext->copyTextUUID(); 3934 } 3935 return uuid; 3936 } 3937 3938 /********************************************************************* 3939 *********************************************************************/ 3940 OSSharedPtr<OSKext> 3941 OSKext::lookupKextWithUUID(uuid_t wanted) 3942 { 3943 OSSharedPtr<OSKext> foundKext; // returned 3944 uint32_t j, i; 3945 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 3946 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 3947 3948 3949 IORecursiveLockLock(sKextLock); 3950 3951 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 3952 for (i = 0; i < count[j]; i++) { 3953 OSKext * thisKext = NULL; 3954 3955 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 3956 if (!thisKext) { 3957 continue; 3958 } 3959 3960 OSSharedPtr<OSData> uuid_data = thisKext->copyUUID(); 3961 if (!uuid_data) { 3962 continue; 3963 } 3964 3965 uuid_t uuid; 3966 memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 3967 3968 if (0 == uuid_compare(wanted, uuid)) { 3969 foundKext.reset(thisKext, OSRetain); 3970 goto finish; 3971 } 3972 } 3973 } 3974 finish: 3975 IORecursiveLockUnlock(sKextLock); 3976 3977 return foundKext; 3978 } 3979 3980 3981 3982 3983 /********************************************************************* 3984 *********************************************************************/ 3985 /* static */ 3986 bool 3987 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier) 3988 { 3989 bool result = false; 3990 OSKext * foundKext = NULL; // returned 3991 3992 IORecursiveLockLock(sKextLock); 3993 3994 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 3995 if (foundKext && foundKext->isLoaded()) { 3996 result = true; 3997 } 3998 3999 IORecursiveLockUnlock(sKextLock); 4000 4001 return result; 4002 } 4003 4004 /********************************************************************* 4005 * xxx - should spawn a separate thread so a kext can safely have 4006 * xxx - itself unloaded. 4007 *********************************************************************/ 4008 /* static */ 4009 OSReturn 4010 OSKext::removeKext( 4011 OSKext * aKext, 4012 #if CONFIG_EMBEDDED 4013 __unused 4014 #endif 4015 bool terminateServicesAndRemovePersonalitiesFlag) 4016 { 4017 #if CONFIG_EMBEDDED 4018 OSKextLog(aKext, 4019 kOSKextLogErrorLevel | 4020 kOSKextLogKextBookkeepingFlag, 4021 "removeKext() called for %s, not supported on embedded", 4022 aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext"); 4023 4024 return kOSReturnSuccess; 4025 #else /* CONFIG_EMBEDDED */ 4026 4027 OSReturn result = kOSKextReturnInUse; 4028 OSKext * checkKext = NULL; // do not release 4029 #if CONFIG_MACF 4030 int macCheckResult = 0; 4031 kauth_cred_t cred = NULL; 4032 #endif 4033 4034 IORecursiveLockLock(sKextLock); 4035 4036 /* If the kext has no identifier, it failed to init 4037 * so isn't in sKextsByID and it isn't loaded. 4038 */ 4039 if (!aKext->getIdentifier()) { 4040 result = kOSReturnSuccess; 4041 goto finish; 4042 } 4043 4044 checkKext = OSDynamicCast(OSKext, 4045 sKextsByID->getObject(aKext->getIdentifier())); 4046 if (checkKext != aKext) { 4047 result = kOSKextReturnNotFound; 4048 goto finish; 4049 } 4050 4051 if (aKext->isLoaded()) { 4052 #if CONFIG_MACF 4053 if (current_task() != kernel_task) { 4054 cred = kauth_cred_get_with_ref(); 4055 macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString()); 4056 kauth_cred_unref(&cred); 4057 } 4058 4059 if (macCheckResult != 0) { 4060 result = kOSReturnError; 4061 OSKextLog(aKext, 4062 kOSKextLogErrorLevel | 4063 kOSKextLogKextBookkeepingFlag, 4064 "Failed to remove kext %s (MAC policy error 0x%x).", 4065 aKext->getIdentifierCString(), macCheckResult); 4066 goto finish; 4067 } 4068 #endif 4069 4070 /* make sure there are no resource requests in flight - 17187548 */ 4071 if (aKext->countRequestCallbacks()) { 4072 goto finish; 4073 } 4074 4075 /* If we are terminating, send the request to the IOCatalogue 4076 * (which will actually call us right back but that's ok we have 4077 * a recursive lock don't you know) but do not ask the IOCatalogue 4078 * to call back with an unload, we'll do that right here. 4079 */ 4080 if (terminateServicesAndRemovePersonalitiesFlag) { 4081 result = gIOCatalogue->terminateDriversForModule( 4082 aKext->getIdentifierCString(), /* unload */ false); 4083 if (result != kOSReturnSuccess) { 4084 OSKextLog(aKext, 4085 kOSKextLogErrorLevel | 4086 kOSKextLogKextBookkeepingFlag, 4087 "Can't remove kext %s; services failed to terminate - 0x%x.", 4088 aKext->getIdentifierCString(), result); 4089 goto finish; 4090 } 4091 } 4092 4093 result = aKext->unload(); 4094 if (result != kOSReturnSuccess) { 4095 goto finish; 4096 } 4097 } 4098 4099 /* Remove personalities as requested. This is a bit redundant for a loaded 4100 * kext as IOCatalogue::terminateDriversForModule() removes driver 4101 * personalities, but it doesn't restart matching, which we always want 4102 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures 4103 * that happens. 4104 */ 4105 if (terminateServicesAndRemovePersonalitiesFlag) { 4106 aKext->removePersonalitiesFromCatalog(); 4107 } 4108 4109 if (aKext->isInFileset()) { 4110 OSKextLog(aKext, 4111 kOSKextLogProgressLevel | 4112 kOSKextLogKextBookkeepingFlag, 4113 "Fileset kext %s unloaded.", 4114 aKext->getIdentifierCString()); 4115 } else { 4116 OSKextLog(aKext, 4117 kOSKextLogProgressLevel | 4118 kOSKextLogKextBookkeepingFlag, 4119 "Removing kext %s.", 4120 aKext->getIdentifierCString()); 4121 4122 sKextsByID->removeObject(aKext->getIdentifier()); 4123 } 4124 result = kOSReturnSuccess; 4125 4126 finish: 4127 IORecursiveLockUnlock(sKextLock); 4128 return result; 4129 #endif /* CONFIG_EMBEDDED */ 4130 } 4131 4132 /********************************************************************* 4133 *********************************************************************/ 4134 /* static */ 4135 OSReturn 4136 OSKext::removeKextWithIdentifier( 4137 const char * kextIdentifier, 4138 bool terminateServicesAndRemovePersonalitiesFlag) 4139 { 4140 OSReturn result = kOSReturnError; 4141 4142 IORecursiveLockLock(sKextLock); 4143 4144 OSKext * aKext = OSDynamicCast(OSKext, 4145 sKextsByID->getObject(kextIdentifier)); 4146 if (!aKext) { 4147 result = kOSKextReturnNotFound; 4148 OSKextLog(/* kext */ NULL, 4149 kOSKextLogErrorLevel | 4150 kOSKextLogKextBookkeepingFlag, 4151 "Can't remove kext %s - not found.", 4152 kextIdentifier); 4153 goto finish; 4154 } 4155 4156 result = OSKext::removeKext(aKext, 4157 terminateServicesAndRemovePersonalitiesFlag); 4158 4159 finish: 4160 IORecursiveLockUnlock(sKextLock); 4161 4162 return result; 4163 } 4164 4165 /********************************************************************* 4166 *********************************************************************/ 4167 /* static */ 4168 OSReturn 4169 OSKext::removeKextWithLoadTag( 4170 OSKextLoadTag loadTag, 4171 bool terminateServicesAndRemovePersonalitiesFlag) 4172 { 4173 OSReturn result = kOSReturnError; 4174 OSKext * foundKext = NULL; 4175 uint32_t i, j; 4176 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 4177 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 4178 4179 4180 IORecursiveLockLock(sKextLock); 4181 4182 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 4183 for (i = 0; i < count[j]; i++) { 4184 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 4185 if (thisKext->loadTag == loadTag) { 4186 foundKext = thisKext; 4187 break; 4188 } 4189 } 4190 } 4191 4192 if (!foundKext) { 4193 result = kOSKextReturnNotFound; 4194 OSKextLog(/* kext */ NULL, 4195 kOSKextLogErrorLevel | 4196 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 4197 "Can't remove kext with load tag %d - not found.", 4198 loadTag); 4199 goto finish; 4200 } 4201 4202 result = OSKext::removeKext(foundKext, 4203 terminateServicesAndRemovePersonalitiesFlag); 4204 4205 finish: 4206 IORecursiveLockUnlock(sKextLock); 4207 4208 return result; 4209 } 4210 4211 /********************************************************************* 4212 *********************************************************************/ 4213 OSSharedPtr<OSDictionary> 4214 OSKext::copyKexts(void) 4215 { 4216 OSSharedPtr<OSDictionary> result; 4217 4218 IORecursiveLockLock(sKextLock); 4219 result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection()); 4220 IORecursiveLockUnlock(sKextLock); 4221 4222 return result; 4223 } 4224 4225 /********************************************************************* 4226 *********************************************************************/ 4227 #define BOOTER_KEXT_PREFIX "Driver-" 4228 4229 typedef struct _DeviceTreeBuffer { 4230 uint32_t paddr; 4231 uint32_t length; 4232 } _DeviceTreeBuffer; 4233 4234 /********************************************************************* 4235 * Create a dictionary of excluded kexts from the given booter data. 4236 *********************************************************************/ 4237 /* static */ 4238 void 4239 OSKext::createExcludeListFromBooterData( 4240 OSDictionary * theDictionary, 4241 OSCollectionIterator * theIterator ) 4242 { 4243 OSString * deviceTreeName = NULL; // do not release 4244 const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not release 4245 char * booterDataPtr = NULL; // do not release 4246 _BooterKextFileInfo * kextFileInfo = NULL; // do not release 4247 char * infoDictAddr = NULL; // do not release 4248 OSSharedPtr<OSObject> parsedXML; 4249 OSDictionary * theInfoDict = NULL; // do not release 4250 4251 theIterator->reset(); 4252 4253 /* look for AppleKextExcludeList.kext */ 4254 while ((deviceTreeName = 4255 OSDynamicCast(OSString, theIterator->getNextObject()))) { 4256 const char * devTreeNameCString; 4257 OSData * deviceTreeEntry; // do not release 4258 OSString * myBundleID; // do not release 4259 4260 deviceTreeEntry = 4261 OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName)); 4262 if (!deviceTreeEntry) { 4263 continue; 4264 } 4265 4266 /* Make sure it is a kext */ 4267 devTreeNameCString = deviceTreeName->getCStringNoCopy(); 4268 if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX, 4269 (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) { 4270 OSKextLog(NULL, 4271 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4272 "\"%s\" not a kext", 4273 devTreeNameCString); 4274 continue; 4275 } 4276 4277 deviceTreeBuffer = (const _DeviceTreeBuffer *) 4278 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer)); 4279 if (!deviceTreeBuffer) { 4280 continue; 4281 } 4282 4283 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr); 4284 if (!booterDataPtr) { 4285 continue; 4286 } 4287 4288 kextFileInfo = (_BooterKextFileInfo *) booterDataPtr; 4289 if (!kextFileInfo->infoDictPhysAddr || 4290 !kextFileInfo->infoDictLength) { 4291 continue; 4292 } 4293 4294 infoDictAddr = (char *) 4295 ml_static_ptovirt(kextFileInfo->infoDictPhysAddr); 4296 if (!infoDictAddr) { 4297 continue; 4298 } 4299 4300 parsedXML = OSUnserializeXML(infoDictAddr); 4301 if (!parsedXML) { 4302 continue; 4303 } 4304 4305 theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 4306 if (!theInfoDict) { 4307 continue; 4308 } 4309 4310 myBundleID = 4311 OSDynamicCast(OSString, 4312 theInfoDict->getObject(kCFBundleIdentifierKey)); 4313 if (myBundleID && 4314 strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) { 4315 boolean_t updated = updateExcludeList(theInfoDict); 4316 if (!updated) { 4317 /* 25322874 */ 4318 panic("Missing OSKextExcludeList dictionary\n"); 4319 } 4320 break; 4321 } 4322 } // while ( (deviceTreeName = ...) ) 4323 4324 return; 4325 } 4326 4327 /********************************************************************* 4328 * Create a dictionary of excluded kexts from the given prelink 4329 * info (kernelcache). 4330 *********************************************************************/ 4331 /* static */ 4332 void 4333 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray ) 4334 { 4335 OSDictionary * myInfoDict = NULL; // do not release 4336 OSString * myBundleID; // do not release 4337 u_int i; 4338 4339 /* Find the Apple Kext Exclude List. */ 4340 for (i = 0; i < theInfoArray->getCount(); i++) { 4341 myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i)); 4342 if (!myInfoDict) { 4343 continue; 4344 } 4345 myBundleID = 4346 OSDynamicCast(OSString, 4347 myInfoDict->getObject(kCFBundleIdentifierKey)); 4348 if (myBundleID && 4349 strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) { 4350 boolean_t updated = updateExcludeList(myInfoDict); 4351 if (!updated) { 4352 /* 25322874 */ 4353 panic("Missing OSKextExcludeList dictionary\n"); 4354 } 4355 break; 4356 } 4357 } // for (i = 0; i < theInfoArray->getCount()... 4358 4359 return; 4360 } 4361 4362 /* static */ 4363 boolean_t 4364 OSKext::updateExcludeList(OSDictionary *infoDict) 4365 { 4366 OSDictionary *myTempDict = NULL; // do not free 4367 OSString *myTempString = NULL; // do not free 4368 OSKextVersion newVersion = 0; 4369 boolean_t updated = false; 4370 4371 if (!infoDict) { 4372 return false; 4373 } 4374 4375 myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList")); 4376 if (!myTempDict) { 4377 return false; 4378 } 4379 4380 myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey)); 4381 if (!myTempString) { 4382 return false; 4383 } 4384 4385 newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy()); 4386 if (newVersion == 0) { 4387 return false; 4388 } 4389 4390 IORecursiveLockLock(sKextLock); 4391 4392 if (newVersion > sExcludeListVersion) { 4393 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0); 4394 sExcludeListVersion = newVersion; 4395 updated = true; 4396 } 4397 4398 IORecursiveLockUnlock(sKextLock); 4399 return updated; 4400 } 4401 4402 #if PRAGMA_MARK 4403 #pragma mark Accessors 4404 #endif 4405 /********************************************************************* 4406 *********************************************************************/ 4407 const OSSymbol * 4408 OSKext::getIdentifier(void) 4409 { 4410 return bundleID.get(); 4411 } 4412 4413 /********************************************************************* 4414 * A kext must have a bundle identifier to even survive initialization; 4415 * this is guaranteed to exist past then. 4416 *********************************************************************/ 4417 const char * 4418 OSKext::getIdentifierCString(void) 4419 { 4420 return bundleID->getCStringNoCopy(); 4421 } 4422 4423 /********************************************************************* 4424 *********************************************************************/ 4425 OSKextVersion 4426 OSKext::getVersion(void) 4427 { 4428 return version; 4429 } 4430 4431 /********************************************************************* 4432 *********************************************************************/ 4433 OSKextVersion 4434 OSKext::getCompatibleVersion(void) 4435 { 4436 return compatibleVersion; 4437 } 4438 4439 /********************************************************************* 4440 *********************************************************************/ 4441 bool 4442 OSKext::isLibrary(void) 4443 { 4444 return getCompatibleVersion() > 0; 4445 } 4446 4447 /********************************************************************* 4448 *********************************************************************/ 4449 bool 4450 OSKext::isCompatibleWithVersion(OSKextVersion aVersion) 4451 { 4452 if ((compatibleVersion > -1 && version > -1) && 4453 (compatibleVersion <= version && aVersion <= version)) { 4454 return true; 4455 } 4456 return false; 4457 } 4458 4459 /********************************************************************* 4460 *********************************************************************/ 4461 bool 4462 OSKext::declaresExecutable(void) 4463 { 4464 if (isDriverKit()) { 4465 return false; 4466 } 4467 return getPropertyForHostArch(kCFBundleExecutableKey) != NULL; 4468 } 4469 4470 /********************************************************************* 4471 *********************************************************************/ 4472 OSData * 4473 OSKext::getExecutable(void) 4474 { 4475 OSData * result = NULL; 4476 OSSharedPtr<OSData> extractedExecutable; 4477 4478 if (flags.builtin) { 4479 return sKernelKext->linkedExecutable.get(); 4480 } 4481 4482 result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey)); 4483 if (result) { 4484 return result; 4485 } 4486 4487 #if CONFIG_KXLD 4488 OSData * mkextExecutableRef = NULL; // do not release 4489 mkextExecutableRef = OSDynamicCast(OSData, 4490 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey)); 4491 4492 if (mkextExecutableRef) { 4493 MkextEntryRef * mkextEntryRef = (MkextEntryRef *) 4494 mkextExecutableRef->getBytesNoCopy(); 4495 uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext); 4496 if (mkextVersion == MKEXT_VERS_2) { 4497 mkext2_file_entry * fileinfo = 4498 (mkext2_file_entry *)mkextEntryRef->fileinfo; 4499 uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo); 4500 uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo); 4501 extractedExecutable = extractMkext2FileData( 4502 MKEXT2_GET_ENTRY_DATA(fileinfo), "executable", 4503 compressedSize, fullSize); 4504 } else { 4505 OSKextLog(this, kOSKextLogErrorLevel | 4506 kOSKextLogArchiveFlag, 4507 "Kext %s - unknown mkext version 0x%x for executable.", 4508 getIdentifierCString(), mkextVersion); 4509 } 4510 4511 /* Regardless of success, remove the mkext executable, 4512 * and drop one reference on the mkext. (setExecutable() does not 4513 * replace, it removes, or panics if asked to replace.) 4514 */ 4515 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey); 4516 infoDict->removeObject(_kOSKextExecutableExternalDataKey); 4517 4518 if (extractedExecutable && extractedExecutable->getLength()) { 4519 if (!setExecutable(extractedExecutable.get())) { 4520 goto finish; 4521 } 4522 result = extractedExecutable.get(); 4523 } else { 4524 goto finish; 4525 } 4526 } 4527 4528 finish: 4529 #endif // CONFIG_KXLD 4530 return result; 4531 } 4532 4533 /********************************************************************* 4534 *********************************************************************/ 4535 bool 4536 OSKext::isInterface(void) 4537 { 4538 return flags.interface; 4539 } 4540 4541 /********************************************************************* 4542 *********************************************************************/ 4543 bool 4544 OSKext::isKernel(void) 4545 { 4546 return this == sKernelKext; 4547 } 4548 4549 /********************************************************************* 4550 *********************************************************************/ 4551 bool 4552 OSKext::isKernelComponent(void) 4553 { 4554 return flags.kernelComponent ? true : false; 4555 } 4556 4557 /********************************************************************* 4558 *********************************************************************/ 4559 bool 4560 OSKext::isExecutable(void) 4561 { 4562 return !isKernel() && !isInterface() && declaresExecutable(); 4563 } 4564 4565 /********************************************************************* 4566 * We might want to check this recursively for all dependencies, 4567 * since a subtree of dependencies could get loaded before we hit 4568 * a dependency that isn't safe-boot-loadable. 4569 * 4570 * xxx - Might want to return false if OSBundleEnableKextLogging or 4571 * OSBundleDebugLevel 4572 * or IOKitDebug is nonzero too (we used to do that, but I don't see 4573 * the point except it's usually development drivers, which might 4574 * cause panics on startup, that have those properties). Heh; could 4575 * use a "kx" boot-arg! 4576 *********************************************************************/ 4577 bool 4578 OSKext::isLoadableInSafeBoot(void) 4579 { 4580 bool result = false; 4581 OSString * required = NULL; // do not release 4582 4583 if (isKernel()) { 4584 result = true; 4585 goto finish; 4586 } 4587 4588 if (isDriverKit()) { 4589 result = true; 4590 goto finish; 4591 } 4592 4593 required = OSDynamicCast(OSString, 4594 getPropertyForHostArch(kOSBundleRequiredKey)); 4595 if (!required) { 4596 goto finish; 4597 } 4598 if (required->isEqualTo(kOSBundleRequiredRoot) || 4599 required->isEqualTo(kOSBundleRequiredLocalRoot) || 4600 required->isEqualTo(kOSBundleRequiredNetworkRoot) || 4601 required->isEqualTo(kOSBundleRequiredSafeBoot) || 4602 required->isEqualTo(kOSBundleRequiredConsole)) { 4603 result = true; 4604 } 4605 4606 finish: 4607 return result; 4608 } 4609 4610 /********************************************************************* 4611 *********************************************************************/ 4612 bool 4613 OSKext::isPrelinked(void) 4614 { 4615 return flags.prelinked ? true : false; 4616 } 4617 4618 /********************************************************************* 4619 *********************************************************************/ 4620 bool 4621 OSKext::isLoaded(void) 4622 { 4623 return flags.loaded ? true : false; 4624 } 4625 4626 /********************************************************************* 4627 *********************************************************************/ 4628 bool 4629 OSKext::isStarted(void) 4630 { 4631 return flags.started ? true : false; 4632 } 4633 4634 /********************************************************************* 4635 *********************************************************************/ 4636 bool 4637 OSKext::isCPPInitialized(void) 4638 { 4639 return flags.CPPInitialized; 4640 } 4641 4642 /********************************************************************* 4643 *********************************************************************/ 4644 void 4645 OSKext::setCPPInitialized(bool initialized) 4646 { 4647 flags.CPPInitialized = initialized; 4648 } 4649 4650 /********************************************************************* 4651 *********************************************************************/ 4652 uint32_t 4653 OSKext::getLoadTag(void) 4654 { 4655 return loadTag; 4656 } 4657 4658 /********************************************************************* 4659 *********************************************************************/ 4660 void 4661 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize) 4662 { 4663 if (linkedExecutable) { 4664 *loadSize = linkedExecutable->getLength(); 4665 4666 /* If we have a kmod_info struct, calculated the wired size 4667 * from that. Otherwise it's the full load size. 4668 */ 4669 if (kmod_info) { 4670 *wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size; 4671 } else { 4672 *wiredSize = *loadSize; 4673 } 4674 } else { 4675 *wiredSize = 0; 4676 *loadSize = 0; 4677 } 4678 } 4679 4680 /********************************************************************* 4681 *********************************************************************/ 4682 OSSharedPtr<OSData> 4683 OSKext::copyUUID(void) 4684 { 4685 OSSharedPtr<OSData> result; 4686 OSData * theExecutable = NULL; // do not release 4687 const kernel_mach_header_t * header; 4688 4689 /* An interface kext doesn't have a linked executable with an LC_UUID, 4690 * we create one when it's linked. 4691 */ 4692 if (interfaceUUID) { 4693 result = interfaceUUID; 4694 goto finish; 4695 } 4696 4697 if (flags.builtin || isInterface()) { 4698 return sKernelKext->copyUUID(); 4699 } 4700 4701 if (isDriverKit() && infoDict) { 4702 return driverKitUUID; 4703 } 4704 4705 /* For real kexts, try to get the UUID from the linked executable, 4706 * or if is hasn't been linked yet, the unrelocated executable. 4707 */ 4708 theExecutable = linkedExecutable.get(); 4709 if (!theExecutable) { 4710 theExecutable = getExecutable(); 4711 } 4712 4713 if (!theExecutable) { 4714 goto finish; 4715 } 4716 4717 header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy(); 4718 result = copyMachoUUID(header); 4719 4720 finish: 4721 return result; 4722 } 4723 4724 /********************************************************************* 4725 *********************************************************************/ 4726 OSSharedPtr<OSData> 4727 OSKext::copyTextUUID(void) 4728 { 4729 if (flags.builtin) { 4730 return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address); 4731 } 4732 return copyUUID(); 4733 } 4734 4735 /********************************************************************* 4736 *********************************************************************/ 4737 OSSharedPtr<OSData> 4738 OSKext::copyMachoUUID(const kernel_mach_header_t * header) 4739 { 4740 OSSharedPtr<OSData> result; 4741 const struct load_command * load_cmd = NULL; 4742 const struct uuid_command * uuid_cmd = NULL; 4743 uint32_t i; 4744 4745 load_cmd = (const struct load_command *)&header[1]; 4746 4747 if (header->magic != MH_MAGIC_KERNEL) { 4748 OSKextLog(NULL, 4749 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4750 "%s: bad header %p", 4751 __func__, 4752 header); 4753 goto finish; 4754 } 4755 4756 for (i = 0; i < header->ncmds; i++) { 4757 if (load_cmd->cmd == LC_UUID) { 4758 uuid_cmd = (struct uuid_command *)load_cmd; 4759 result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid)); 4760 goto finish; 4761 } 4762 load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize); 4763 } 4764 4765 finish: 4766 return result; 4767 } 4768 4769 void 4770 OSKext::setDriverKitUUID(OSData *uuid) 4771 { 4772 if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) { 4773 OSSafeReleaseNULL(uuid); 4774 } 4775 } 4776 4777 /********************************************************************* 4778 *********************************************************************/ 4779 #if defined (__arm__) 4780 #include <arm/arch.h> 4781 #endif 4782 4783 #if defined (__x86_64__) 4784 #define ARCHNAME "x86_64" 4785 #elif defined (__arm64__) 4786 #define ARCHNAME "arm64" 4787 #elif defined (__arm__) 4788 4789 #if defined (__ARM_ARCH_7S__) 4790 #define ARCHNAME "armv7s" 4791 #elif defined (__ARM_ARCH_7F__) 4792 #define ARCHNAME "armv7f" 4793 #elif defined (__ARM_ARCH_7K__) 4794 #define ARCHNAME "armv7k" 4795 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */ 4796 #define ARCHNAME "armv7" 4797 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */ 4798 #define ARCHNAME "armv6" 4799 #endif 4800 4801 #elif defined (__arm64__) 4802 #define ARCHNAME "arm64" 4803 #else 4804 #error architecture not supported 4805 #endif 4806 4807 #define ARCH_SEPARATOR_CHAR '_' 4808 4809 static char * 4810 makeHostArchKey(const char * key, size_t * keySizeOut) 4811 { 4812 char * result = NULL; 4813 size_t keyLength = strlen(key); 4814 size_t keySize; 4815 4816 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'. 4817 */ 4818 keySize = 1 + 1 + keyLength + strlen(ARCHNAME); 4819 result = (char *)kheap_alloc_tag(KHEAP_TEMP, keySize, 4820 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 4821 4822 if (!result) { 4823 goto finish; 4824 } 4825 strlcpy(result, key, keySize); 4826 result[keyLength++] = ARCH_SEPARATOR_CHAR; 4827 result[keyLength] = '\0'; 4828 strlcat(result, ARCHNAME, keySize); 4829 *keySizeOut = keySize; 4830 4831 finish: 4832 return result; 4833 } 4834 4835 /********************************************************************* 4836 *********************************************************************/ 4837 OSObject * 4838 OSKext::getPropertyForHostArch(const char * key) 4839 { 4840 OSObject * result = NULL;// do not release 4841 size_t hostArchKeySize = 0; 4842 char * hostArchKey = NULL;// must kfree 4843 4844 if (!key || !infoDict) { 4845 goto finish; 4846 } 4847 4848 /* Some properties are not allowed to be arch-variant: 4849 * - Any CFBundle... property. 4850 * - OSBundleIsInterface. 4851 * - OSKernelResource. 4852 */ 4853 if (STRING_HAS_PREFIX(key, "OS") || 4854 STRING_HAS_PREFIX(key, "IO")) { 4855 hostArchKey = makeHostArchKey(key, &hostArchKeySize); 4856 if (!hostArchKey) { 4857 OSKextLog(/* kext (this isn't about a kext) */ NULL, 4858 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 4859 "Allocation failure."); 4860 goto finish; 4861 } 4862 result = infoDict->getObject(hostArchKey); 4863 } 4864 4865 if (!result) { 4866 result = infoDict->getObject(key); 4867 } 4868 4869 finish: 4870 if (hostArchKey) { 4871 kheap_free(KHEAP_TEMP, hostArchKey, hostArchKeySize); 4872 } 4873 return result; 4874 } 4875 4876 #if PRAGMA_MARK 4877 #pragma mark Load/Start/Stop/Unload 4878 #endif 4879 4880 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n') 4881 4882 /********************************************************************* 4883 * sExcludeListByID is a dictionary with keys / values of: 4884 * key = bundleID string of kext we will not allow to load 4885 * value = version string(s) of the kext that is to be denied loading. 4886 * The version strings can be comma delimited. For example if kext 4887 * com.foocompany.fookext has two versions that we want to deny 4888 * loading then the version strings might look like: 4889 * 1.0.0, 1.0.1 4890 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will 4891 * not load the kext. 4892 * 4893 * Value may also be in the form of "LE 2.0.0" (version numbers 4894 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version 4895 * number less than 2.0.0 will not load) 4896 * 4897 * NOTE - we cannot use the characters "<=" or "<" because we have code 4898 * that serializes plists and treats '<' as a special character. 4899 *********************************************************************/ 4900 bool 4901 OSKext::isInExcludeList(void) 4902 { 4903 OSString * versionString = NULL; // do not release 4904 char * versionCString = NULL; // do not free 4905 size_t i; 4906 boolean_t wantLessThan = false; 4907 boolean_t wantLessThanEqualTo = false; 4908 boolean_t isInExcludeList = true; 4909 char myBuffer[32]; 4910 4911 IORecursiveLockLock(sKextLock); 4912 4913 if (!sExcludeListByID) { 4914 isInExcludeList = false; 4915 } else { 4916 /* look up by bundleID in our exclude list and if found get version 4917 * string (or strings) that we will not allow to load 4918 */ 4919 versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get())); 4920 if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) { 4921 isInExcludeList = false; 4922 } 4923 } 4924 4925 IORecursiveLockUnlock(sKextLock); 4926 4927 if (!isInExcludeList) { 4928 return false; 4929 } 4930 4931 /* parse version strings */ 4932 versionCString = (char *) versionString->getCStringNoCopy(); 4933 4934 /* look for "LT" or "LE" form of version string, must be in first two 4935 * positions. 4936 */ 4937 if (*versionCString == 'L' && *(versionCString + 1) == 'T') { 4938 wantLessThan = true; 4939 versionCString += 2; 4940 } else if (*versionCString == 'L' && *(versionCString + 1) == 'E') { 4941 wantLessThanEqualTo = true; 4942 versionCString += 2; 4943 } 4944 4945 for (i = 0; *versionCString != 0x00; versionCString++) { 4946 /* skip whitespace */ 4947 if (isWhiteSpace(*versionCString)) { 4948 continue; 4949 } 4950 4951 /* peek ahead for version string separator or null terminator */ 4952 if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) { 4953 /* OK, we have a version string */ 4954 myBuffer[i++] = *versionCString; 4955 myBuffer[i] = 0x00; 4956 4957 OSKextVersion excludeVers; 4958 excludeVers = OSKextParseVersionString(myBuffer); 4959 4960 if (wantLessThanEqualTo) { 4961 if (version <= excludeVers) { 4962 return true; 4963 } 4964 } else if (wantLessThan) { 4965 if (version < excludeVers) { 4966 return true; 4967 } 4968 } else if (version == excludeVers) { 4969 return true; 4970 } 4971 4972 /* reset for the next (if any) version string */ 4973 i = 0; 4974 wantLessThan = false; 4975 wantLessThanEqualTo = false; 4976 } else { 4977 /* save valid version character */ 4978 myBuffer[i++] = *versionCString; 4979 4980 /* make sure bogus version string doesn't overrun local buffer */ 4981 if (i >= sizeof(myBuffer)) { 4982 break; 4983 } 4984 } 4985 } 4986 4987 return false; 4988 } 4989 4990 /********************************************************************* 4991 * sNonLoadableKextsByID is a dictionary with keys / values of: 4992 * key = bundleID string of kext we will not allow to load 4993 * value = boolean (true == loadable, false == not loadable) 4994 * 4995 * Only kexts which are in the AuxKC will be marked as "not loadble," 4996 * i.e., the value for the kext's bundleID will be false. All kexts in 4997 * the primary and system KCs will always be marked as "loadable." 4998 * 4999 * This list ultimately comes from kexts which have been uninstalled 5000 * in user space by deleting the kext from disk, but which have not 5001 * yet been removed from the AuxKC. Because the user could choose to 5002 * re-install the exact same version of the kext, we need to keep 5003 * a dictionary of boolean values so that user space only needs to 5004 * keep a simple list of "uninstalled" or "missing" bundles. When 5005 * a bundle is re-installed, the iokit daemon can use the 5006 * AucKCBundleAvailable predicate to set the individual kext's 5007 * availability to true. 5008 *********************************************************************/ 5009 bool 5010 OSKext::isLoadable(void) 5011 { 5012 bool isLoadable = true; 5013 5014 if (kc_type != KCKindAuxiliary) { 5015 /* this filtering only applies to kexts in the auxkc */ 5016 return true; 5017 } 5018 5019 IORecursiveLockLock(sKextLock); 5020 5021 if (sNonLoadableKextsByID) { 5022 /* look up by bundleID in our exclude list and if found get version 5023 * string (or strings) that we will not allow to load 5024 */ 5025 OSBoolean *loadableVal; 5026 loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get())); 5027 if (loadableVal && !loadableVal->getValue()) { 5028 isLoadable = false; 5029 } 5030 } 5031 IORecursiveLockUnlock(sKextLock); 5032 5033 return isLoadable; 5034 } 5035 5036 /********************************************************************* 5037 *********************************************************************/ 5038 /* static */ 5039 OSReturn 5040 OSKext::loadKextWithIdentifier( 5041 const char * kextIdentifierCString, 5042 Boolean allowDeferFlag, 5043 Boolean delayAutounloadFlag, 5044 OSKextExcludeLevel startOpt, 5045 OSKextExcludeLevel startMatchingOpt, 5046 OSArray * personalityNames) 5047 { 5048 OSReturn result = kOSReturnError; 5049 OSSharedPtr<OSString> kextIdentifier; 5050 5051 kextIdentifier = OSString::withCString(kextIdentifierCString); 5052 if (!kextIdentifier) { 5053 result = kOSKextReturnNoMemory; 5054 goto finish; 5055 } 5056 result = OSKext::loadKextWithIdentifier(kextIdentifier.get(), 5057 NULL /* kextRef */, 5058 allowDeferFlag, delayAutounloadFlag, 5059 startOpt, startMatchingOpt, personalityNames); 5060 5061 finish: 5062 return result; 5063 } 5064 5065 OSReturn 5066 OSKext::loadKextWithIdentifier( 5067 OSString * kextIdentifier, 5068 OSSharedPtr<OSObject> &kextRef, 5069 Boolean allowDeferFlag, 5070 Boolean delayAutounloadFlag, 5071 OSKextExcludeLevel startOpt, 5072 OSKextExcludeLevel startMatchingOpt, 5073 OSArray * personalityNames) 5074 { 5075 OSObject * kextRefRaw = NULL; 5076 OSReturn result; 5077 5078 result = loadKextWithIdentifier(kextIdentifier, 5079 &kextRefRaw, 5080 allowDeferFlag, 5081 delayAutounloadFlag, 5082 startOpt, 5083 startMatchingOpt, 5084 personalityNames); 5085 if ((kOSReturnSuccess == result) && kextRefRaw) { 5086 kextRef.reset(kextRefRaw, OSNoRetain); 5087 } 5088 return result; 5089 } 5090 5091 /********************************************************************* 5092 *********************************************************************/ 5093 OSReturn 5094 OSKext::loadKextWithIdentifier( 5095 OSString * kextIdentifier, 5096 OSObject ** kextRef, 5097 Boolean allowDeferFlag, 5098 Boolean delayAutounloadFlag, 5099 OSKextExcludeLevel startOpt, 5100 OSKextExcludeLevel startMatchingOpt, 5101 OSArray * personalityNames) 5102 { 5103 OSReturn result = kOSReturnError; 5104 OSReturn pingResult = kOSReturnError; 5105 OSKext * theKext = NULL; // do not release 5106 OSSharedPtr<OSDictionary> loadRequest; 5107 OSSharedPtr<const OSSymbol> kextIdentifierSymbol; 5108 5109 if (kextRef) { 5110 *kextRef = NULL; 5111 } 5112 5113 IORecursiveLockLock(sKextLock); 5114 5115 if (!kextIdentifier) { 5116 result = kOSKextReturnInvalidArgument; 5117 goto finish; 5118 } 5119 5120 OSKext::recordIdentifierRequest(kextIdentifier); 5121 5122 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 5123 if (!theKext) { 5124 if (!allowDeferFlag) { 5125 OSKextLog(/* kext */ NULL, 5126 kOSKextLogErrorLevel | 5127 kOSKextLogLoadFlag, 5128 "Can't load kext %s - not found.", 5129 kextIdentifier->getCStringNoCopy()); 5130 goto finish; 5131 } 5132 5133 if (!sKernelRequestsEnabled) { 5134 OSKextLog(theKext, 5135 kOSKextLogErrorLevel | 5136 kOSKextLogLoadFlag, 5137 "Can't load kext %s - requests to user space are disabled.", 5138 kextIdentifier->getCStringNoCopy()); 5139 result = kOSKextReturnDisabled; 5140 goto finish; 5141 } 5142 5143 /* Create a new request unless one is already sitting 5144 * in sKernelRequests for this bundle identifier 5145 */ 5146 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 5147 if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) { 5148 result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad, 5149 loadRequest); 5150 if (result != kOSReturnSuccess) { 5151 goto finish; 5152 } 5153 if (!_OSKextSetRequestArgument(loadRequest.get(), 5154 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 5155 result = kOSKextReturnNoMemory; 5156 goto finish; 5157 } 5158 if (!sKernelRequests->setObject(loadRequest.get())) { 5159 result = kOSKextReturnNoMemory; 5160 goto finish; 5161 } 5162 5163 if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) { 5164 result = kOSKextReturnNoMemory; 5165 goto finish; 5166 } 5167 5168 OSKextLog(theKext, 5169 kOSKextLogDebugLevel | 5170 kOSKextLogLoadFlag, 5171 "Kext %s not found; queued load request to user space.", 5172 kextIdentifier->getCStringNoCopy()); 5173 } 5174 5175 pingResult = OSKext::pingIOKitDaemon(); 5176 if (pingResult == kOSKextReturnDisabled) { 5177 OSKextLog(/* kext */ NULL, 5178 ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) | 5179 kOSKextLogLoadFlag, 5180 "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.", 5181 kextIdentifier->getCStringNoCopy()); 5182 } 5183 5184 result = kOSKextReturnDeferred; 5185 goto finish; 5186 } 5187 5188 result = theKext->load(startOpt, startMatchingOpt, personalityNames); 5189 5190 if (result != kOSReturnSuccess) { 5191 OSKextLog(theKext, 5192 kOSKextLogErrorLevel | 5193 kOSKextLogLoadFlag, 5194 "Failed to load kext %s (error 0x%x).", 5195 kextIdentifier->getCStringNoCopy(), (int)result); 5196 5197 if (theKext->kc_type == KCKindUnknown) { 5198 OSKext::removeKext(theKext, 5199 /* terminateService/removePersonalities */ true); 5200 } 5201 goto finish; 5202 } 5203 5204 if (delayAutounloadFlag) { 5205 OSKextLog(theKext, 5206 kOSKextLogProgressLevel | 5207 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 5208 "Setting delayed autounload for %s.", 5209 kextIdentifier->getCStringNoCopy()); 5210 theKext->flags.delayAutounload = 1; 5211 } 5212 5213 finish: 5214 if ((kOSReturnSuccess == result) && kextRef) { 5215 *kextRef = theKext; 5216 theKext->matchingRefCount++; 5217 theKext->retain(); 5218 } 5219 5220 IORecursiveLockUnlock(sKextLock); 5221 5222 return result; 5223 } 5224 5225 /********************************************************************* 5226 *********************************************************************/ 5227 /* static */ 5228 OSReturn 5229 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict) 5230 { 5231 OSReturn result = kOSReturnError; 5232 5233 OSBoolean *delayAutounloadBool = NULL; // do not release 5234 OSNumber *startKextExcludeNum = NULL; // do not release 5235 OSNumber *startMatchingExcludeNum = NULL; // do not release 5236 OSArray *personalityNames = NULL; // do not release 5237 5238 /* 5239 * Default values for these options: 5240 * regular autounload behavior 5241 * start the kext 5242 * send all personalities to the catalog 5243 */ 5244 Boolean delayAutounload = false; 5245 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone; 5246 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone; 5247 5248 IORecursiveLockLock(sKextLock); 5249 5250 OSKextLog(/* kext */ NULL, 5251 kOSKextLogDebugLevel | 5252 kOSKextLogIPCFlag, 5253 "Received kext KC load request from user space."); 5254 5255 /* Regardless of processing, the fact that we have gotten here means some 5256 * user-space program is up and talking to us, so we'll switch our kext 5257 * registration to reflect that. 5258 */ 5259 if (!sUserLoadsActive) { 5260 OSKextLog(/* kext */ NULL, 5261 kOSKextLogProgressLevel | 5262 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 5263 "Switching to late startup (user-space) kext loading policy."); 5264 sUserLoadsActive = true; 5265 } 5266 5267 delayAutounloadBool = OSDynamicCast(OSBoolean, 5268 _OSKextGetRequestArgument(requestDict, 5269 kKextRequestArgumentDelayAutounloadKey)); 5270 startKextExcludeNum = OSDynamicCast(OSNumber, 5271 _OSKextGetRequestArgument(requestDict, 5272 kKextRequestArgumentStartExcludeKey)); 5273 startMatchingExcludeNum = OSDynamicCast(OSNumber, 5274 _OSKextGetRequestArgument(requestDict, 5275 kKextRequestArgumentStartMatchingExcludeKey)); 5276 personalityNames = OSDynamicCast(OSArray, 5277 _OSKextGetRequestArgument(requestDict, 5278 kKextRequestArgumentPersonalityNamesKey)); 5279 5280 if (delayAutounloadBool) { 5281 delayAutounload = delayAutounloadBool->getValue(); 5282 } 5283 if (startKextExcludeNum) { 5284 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue(); 5285 } 5286 if (startMatchingExcludeNum) { 5287 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue(); 5288 } 5289 5290 OSKextLog(/* kext */ NULL, 5291 kOSKextLogProgressLevel | 5292 kOSKextLogIPCFlag, 5293 "Received request from user space to load KC kext %s.", 5294 theKext->getIdentifierCString()); 5295 5296 /* this could be in the Auxiliary KC, so record the load request */ 5297 OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier())); 5298 5299 /* 5300 * Load the kext 5301 */ 5302 result = theKext->load(startKextExcludeLevel, 5303 startMatchingExcludeLevel, personalityNames); 5304 5305 if (result != kOSReturnSuccess) { 5306 OSKextLog(theKext, 5307 kOSKextLogErrorLevel | 5308 kOSKextLogLoadFlag, 5309 "Failed to load kext %s (error 0x%x).", 5310 theKext->getIdentifierCString(), (int)result); 5311 5312 OSKext::removeKext(theKext, 5313 /* terminateService/removePersonalities */ true); 5314 goto finish; 5315 } else { 5316 OSKextLog(theKext, 5317 kOSKextLogProgressLevel | 5318 kOSKextLogLoadFlag, 5319 "Kext %s Loaded successfully from %s KC", 5320 theKext->getIdentifierCString(), theKext->getKCTypeString()); 5321 } 5322 5323 if (delayAutounload) { 5324 OSKextLog(theKext, 5325 kOSKextLogProgressLevel | 5326 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 5327 "Setting delayed autounload for %s.", 5328 theKext->getIdentifierCString()); 5329 theKext->flags.delayAutounload = 1; 5330 } 5331 5332 finish: 5333 IORecursiveLockUnlock(sKextLock); 5334 5335 return result; 5336 } 5337 5338 /********************************************************************* 5339 *********************************************************************/ 5340 /* static */ 5341 OSReturn 5342 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict) 5343 { 5344 OSReturn result = kOSReturnError; 5345 OSDictionary *anInfoDict = NULL; // do not release 5346 5347 anInfoDict = OSDynamicCast(OSDictionary, 5348 _OSKextGetRequestArgument(requestDict, 5349 kKextRequestArgumentCodelessInfoKey)); 5350 if (anInfoDict == NULL) { 5351 OSKextLog(/* kext */ NULL, 5352 kOSKextLogErrorLevel | 5353 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 5354 "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.", 5355 kextIdentifier->getCStringNoCopy()); 5356 return kOSKextReturnInvalidArgument; 5357 } 5358 5359 IORecursiveLockLock(sKextLock); 5360 5361 OSKextLog(/* kext */ NULL, 5362 kOSKextLogProgressLevel | 5363 kOSKextLogIPCFlag, 5364 "Received request from user space to load codeless kext %s.", 5365 kextIdentifier->getCStringNoCopy()); 5366 5367 { 5368 // instantiate a new kext, and don't hold a reference 5369 // (the kext subsystem will hold one implicitly) 5370 OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict); 5371 if (!newKext) { 5372 OSKextLog(/* kext */ NULL, 5373 kOSKextLogErrorLevel | 5374 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 5375 "Could not instantiate codeless kext."); 5376 result = kOSKextReturnNotLoadable; 5377 goto finish; 5378 } 5379 if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) { 5380 OSKextLog(/* kext */ NULL, 5381 kOSKextLogErrorLevel | 5382 kOSKextLogGeneralFlag | kOSKextLogLoadFlag, 5383 "Codeless kext identifiers don't match '%s' != '%s'", 5384 kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString()); 5385 5386 OSKext::removeKext(newKext.get(), false); 5387 result = kOSKextReturnInvalidArgument; 5388 goto finish; 5389 } 5390 5391 /* Record the request for the codeless kext */ 5392 OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier())); 5393 5394 result = kOSReturnSuccess; 5395 /* send the kext's personalities to the IOCatalog */ 5396 if (!newKext->flags.requireExplicitLoad) { 5397 result = newKext->sendPersonalitiesToCatalog(true, NULL); 5398 } 5399 } 5400 5401 finish: 5402 IORecursiveLockUnlock(sKextLock); 5403 5404 return result; 5405 } 5406 5407 /********************************************************************* 5408 *********************************************************************/ 5409 /* static */ 5410 void 5411 OSKext::dropMatchingReferences( 5412 OSSet * kexts) 5413 { 5414 IORecursiveLockLock(sKextLock); 5415 kexts->iterateObjects(^bool (OSObject * obj) { 5416 OSKext * thisKext = OSDynamicCast(OSKext, obj); 5417 if (!thisKext) { 5418 return false; 5419 } 5420 thisKext->matchingRefCount--; 5421 return false; 5422 }); 5423 IORecursiveLockUnlock(sKextLock); 5424 } 5425 5426 /********************************************************************* 5427 *********************************************************************/ 5428 /* static */ 5429 void 5430 OSKext::recordIdentifierRequest( 5431 OSString * kextIdentifier) 5432 { 5433 OSSharedPtr<const OSSymbol> kextIdentifierSymbol; 5434 bool fail = false; 5435 5436 if (!sAllKextLoadIdentifiers || !kextIdentifier) { 5437 goto finish; 5438 } 5439 5440 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier); 5441 if (!kextIdentifierSymbol) { 5442 // xxx - this is really a basic alloc failure 5443 fail = true; 5444 goto finish; 5445 } 5446 5447 IORecursiveLockLock(sKextLock); 5448 if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) { 5449 if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) { 5450 fail = true; 5451 } else { 5452 // xxx - need to find a way to associate this whole func w/the kext 5453 OSKextLog(/* kext */ NULL, 5454 // xxx - check level 5455 kOSKextLogStepLevel | 5456 kOSKextLogArchiveFlag, 5457 "Recorded kext %s as a candidate for inclusion in prelinked kernel.", 5458 kextIdentifier->getCStringNoCopy()); 5459 } 5460 } 5461 IORecursiveLockUnlock(sKextLock); 5462 5463 finish: 5464 5465 if (fail) { 5466 OSKextLog(/* kext */ NULL, 5467 kOSKextLogErrorLevel | 5468 kOSKextLogArchiveFlag, 5469 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.", 5470 kextIdentifier->getCStringNoCopy()); 5471 } 5472 return; 5473 } 5474 5475 /********************************************************************* 5476 *********************************************************************/ 5477 OSReturn 5478 OSKext::load( 5479 OSKextExcludeLevel startOpt, 5480 OSKextExcludeLevel startMatchingOpt, 5481 OSArray * personalityNames) 5482 { 5483 OSReturn result = kOSReturnError; 5484 OSKextExcludeLevel dependenciesStartOpt = startOpt; 5485 OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt; 5486 unsigned int i, count; 5487 Boolean alreadyLoaded = false; 5488 OSKext * lastLoadedKext = NULL; // do not release 5489 5490 if (isInExcludeList()) { 5491 OSKextLog(this, 5492 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | 5493 kOSKextLogLoadFlag, 5494 "Kext %s is in exclude list, not loadable", 5495 getIdentifierCString()); 5496 5497 result = kOSKextReturnNotLoadable; 5498 goto finish; 5499 } 5500 if (!isLoadable()) { 5501 OSKextLog(this, 5502 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | 5503 kOSKextLogLoadFlag, 5504 "Kext %s is not loadable", 5505 getIdentifierCString()); 5506 5507 result = kOSKextReturnNotLoadable; 5508 goto finish; 5509 } 5510 5511 if (isLoaded()) { 5512 alreadyLoaded = true; 5513 result = kOSReturnSuccess; 5514 5515 OSKextLog(this, 5516 kOSKextLogDebugLevel | 5517 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 5518 "Kext %s is already loaded.", 5519 getIdentifierCString()); 5520 goto loaded; 5521 } 5522 5523 #if CONFIG_MACF && XNU_TARGET_OS_OSX 5524 #if CONFIG_KXLD 5525 if (current_task() != kernel_task) { 5526 #else 5527 /* 5528 * On non-kxld systems, only check the mac-hook for kexts in the 5529 * Pageable and Aux KCs. This means on Apple silicon devices that 5530 * the mac hook will only be useful to block 3rd party kexts. 5531 * 5532 * Note that this should _not_ be called on kexts loaded from the 5533 * kernel bootstrap thread as the kernel proc's cred struct is not 5534 * yet initialized! This won't happen on macOS because all the kexts 5535 * in the BootKC are self-contained and their kc_type = KCKindPrimary. 5536 */ 5537 if (kc_type != KCKindPrimary && kc_type != KCKindUnknown) { 5538 #endif /* CONFIG_KXLD */ 5539 int macCheckResult = 0; 5540 kauth_cred_t cred = NULL; 5541 5542 cred = kauth_cred_get_with_ref(); 5543 macCheckResult = mac_kext_check_load(cred, getIdentifierCString()); 5544 kauth_cred_unref(&cred); 5545 5546 if (macCheckResult != 0) { 5547 result = kOSReturnError; 5548 OSKextLog(this, 5549 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5550 "Failed to load kext %s (MAC policy error 0x%x).", 5551 getIdentifierCString(), macCheckResult); 5552 goto finish; 5553 } 5554 } 5555 #endif 5556 5557 if (!sLoadEnabled) { 5558 OSKextLog(this, 5559 kOSKextLogErrorLevel | 5560 kOSKextLogLoadFlag, 5561 "Kext loading is disabled (attempt to load kext %s).", 5562 getIdentifierCString()); 5563 result = kOSKextReturnDisabled; 5564 goto finish; 5565 } 5566 5567 /* If we've pushed the next available load tag to the invalid value, 5568 * we can't load any more kexts. 5569 */ 5570 if (sNextLoadTag == kOSKextInvalidLoadTag) { 5571 OSKextLog(this, 5572 kOSKextLogErrorLevel | 5573 kOSKextLogLoadFlag, 5574 "Can't load kext %s - no more load tags to assign.", 5575 getIdentifierCString()); 5576 result = kOSKextReturnNoResources; 5577 goto finish; 5578 } 5579 5580 /* This is a bit of a hack, because we shouldn't be handling 5581 * personalities within the load function. 5582 */ 5583 if (!declaresExecutable()) { 5584 /* There is a special case where a non-executable kext can be loaded: the 5585 * AppleKextExcludeList. Detect that special kext by bundle identifier and 5586 * load its metadata into the global data structures, if appropriate 5587 */ 5588 if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) { 5589 boolean_t updated = updateExcludeList(infoDict.get()); 5590 if (updated) { 5591 OSKextLog(this, 5592 kOSKextLogDebugLevel | kOSKextLogLoadFlag, 5593 "KextExcludeList was updated to version: %lld", sExcludeListVersion); 5594 } 5595 } 5596 5597 if (isDriverKit()) { 5598 if (loadTag == 0) { 5599 sLoadedDriverKitKexts->setObject(this); 5600 loadTag = sNextLoadTag++; 5601 } 5602 } 5603 result = kOSReturnSuccess; 5604 goto loaded; 5605 } 5606 5607 /* Are we in safe boot? 5608 */ 5609 if (sSafeBoot && !isLoadableInSafeBoot()) { 5610 OSKextLog(this, 5611 kOSKextLogErrorLevel | 5612 kOSKextLogLoadFlag, 5613 "Can't load kext %s - not loadable during safe boot.", 5614 getIdentifierCString()); 5615 result = kOSKextReturnBootLevel; 5616 goto finish; 5617 } 5618 5619 OSKextLog(this, 5620 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 5621 "Loading kext %s.", 5622 getIdentifierCString()); 5623 5624 #if !VM_MAPPED_KEXTS 5625 if (isPrelinked() == false) { 5626 OSKextLog(this, 5627 kOSKextLogErrorLevel | 5628 kOSKextLogLoadFlag, 5629 "Can't load kext %s - not in a kext collection.", 5630 getIdentifierCString()); 5631 result = kOSKextReturnDisabled; 5632 goto finish; 5633 } 5634 #endif /* defined(__x86_64__) */ 5635 5636 #if CONFIG_KXLD 5637 if (!sKxldContext) { 5638 kern_return_t kxldResult; 5639 kxldResult = kxld_create_context(&sKxldContext, &kern_allocate, 5640 &kxld_log_callback, /* Flags */ (KXLDFlags) 0, 5641 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0); 5642 if (kxldResult) { 5643 OSKextLog(this, 5644 kOSKextLogErrorLevel | 5645 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 5646 "Can't load kext %s - failed to create link context.", 5647 getIdentifierCString()); 5648 result = kOSKextReturnNoMemory; 5649 goto finish; 5650 } 5651 } 5652 #endif // CONFIG_KXLD 5653 5654 /* We only need to resolve dependencies once for the whole graph, but 5655 * resolveDependencies will just return if there's no work to do, so it's 5656 * safe to call it more than once. 5657 */ 5658 if (!resolveDependencies()) { 5659 // xxx - check resolveDependencies() for log msg 5660 OSKextLog(this, 5661 kOSKextLogErrorLevel | 5662 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 5663 "Can't load kext %s - failed to resolve library dependencies.", 5664 getIdentifierCString()); 5665 result = kOSKextReturnDependencies; 5666 goto finish; 5667 } 5668 5669 /* If we are excluding just the kext being loaded now (and not its 5670 * dependencies), drop the exclusion level to none so dependencies 5671 * start and/or add their personalities. 5672 */ 5673 if (dependenciesStartOpt == kOSKextExcludeKext) { 5674 dependenciesStartOpt = kOSKextExcludeNone; 5675 } 5676 5677 if (dependenciesStartMatchingOpt == kOSKextExcludeKext) { 5678 dependenciesStartMatchingOpt = kOSKextExcludeNone; 5679 } 5680 5681 /* Load the dependencies, recursively. 5682 */ 5683 count = getNumDependencies(); 5684 for (i = 0; i < count; i++) { 5685 OSKext * dependency = OSDynamicCast(OSKext, 5686 dependencies->getObject(i)); 5687 if (dependency == NULL) { 5688 OSKextLog(this, 5689 kOSKextLogErrorLevel | 5690 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 5691 "Internal error loading kext %s; dependency disappeared.", 5692 getIdentifierCString()); 5693 result = kOSKextReturnInternalError; 5694 goto finish; 5695 } 5696 5697 /* Dependencies must be started accorting to the opt, 5698 * but not given the personality names of the main kext. 5699 */ 5700 result = dependency->load(dependenciesStartOpt, 5701 dependenciesStartMatchingOpt, 5702 /* personalityNames */ NULL); 5703 if (result != KERN_SUCCESS) { 5704 OSKextLog(this, 5705 kOSKextLogErrorLevel | 5706 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 5707 "Dependency %s of kext %s failed to load.", 5708 dependency->getIdentifierCString(), 5709 getIdentifierCString()); 5710 5711 OSKext::removeKext(dependency, 5712 /* terminateService/removePersonalities */ true); 5713 result = kOSKextReturnDependencyLoadError; 5714 5715 goto finish; 5716 } 5717 } 5718 5719 result = loadExecutable(); 5720 if (result != KERN_SUCCESS) { 5721 goto finish; 5722 } 5723 5724 pendingPgoHead.next = &pendingPgoHead; 5725 pendingPgoHead.prev = &pendingPgoHead; 5726 5727 // The kernel PRNG is not initialized when the first kext is 5728 // loaded, so use early random 5729 uuid_generate_early_random(instance_uuid); 5730 account = IONew(OSKextAccount, 1); 5731 if (!account) { 5732 result = KERN_MEMORY_ERROR; 5733 goto finish; 5734 } 5735 bzero(account, sizeof(*account)); 5736 account->loadTag = kmod_info->id; 5737 account->site.refcount = 0; 5738 account->site.flags = VM_TAG_KMOD; 5739 account->kext = this; 5740 if (gIOSurfaceIdentifier == bundleID) { 5741 vm_tag_alloc(&account->site); 5742 gIOSurfaceTag = account->site.tag; 5743 } 5744 5745 flags.loaded = true; 5746 5747 /* Add the kext to the list of loaded kexts and update the kmod_info 5748 * struct to point to that of the last loaded kext (which is the way 5749 * it's always been done, though I'd rather do them in order now). 5750 */ 5751 lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 5752 sLoadedKexts->setObject(this); 5753 5754 /* Keep the kernel itself out of the kmod list. 5755 */ 5756 if (lastLoadedKext->isKernel()) { 5757 lastLoadedKext = NULL; 5758 } 5759 5760 if (lastLoadedKext) { 5761 kmod_info->next = lastLoadedKext->kmod_info; 5762 } 5763 5764 notifyKextLoadObservers(this, kmod_info); 5765 5766 /* Make the global kmod list point at the just-loaded kext. Note that the 5767 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard, 5768 * although we do report it in kextstat these days by using the newer 5769 * OSArray of loaded kexts, which does contain it. 5770 * 5771 * (The OSKext object representing the kernel doesn't even have a kmod_info 5772 * struct, though I suppose we could stick a pointer to it from the 5773 * static struct in OSRuntime.cpp.) 5774 */ 5775 kmod = kmod_info; 5776 5777 /* Save the list of loaded kexts in case we panic. 5778 */ 5779 OSKext::saveLoadedKextPanicList(); 5780 5781 if (isExecutable()) { 5782 OSKext::updateLoadedKextSummaries(); 5783 savePanicString(/* isLoading */ true); 5784 5785 #if CONFIG_DTRACE 5786 registerWithDTrace(); 5787 #else 5788 jettisonLinkeditSegment(); 5789 #endif /* CONFIG_DTRACE */ 5790 5791 #if !VM_MAPPED_KEXTS 5792 /* If there is a page (or more) worth of padding after the end 5793 * of the last data section but before the end of the data segment 5794 * then free it in the same manner the LinkeditSegment is freed 5795 */ 5796 jettisonDATASegmentPadding(); 5797 #endif 5798 } 5799 5800 loaded: 5801 if (isExecutable() && !flags.started) { 5802 if (startOpt == kOSKextExcludeNone) { 5803 result = start(); 5804 if (result != kOSReturnSuccess) { 5805 OSKextLog(this, 5806 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 5807 "Kext %s start failed (result 0x%x).", 5808 getIdentifierCString(), result); 5809 result = kOSKextReturnStartStopError; 5810 } 5811 } 5812 } 5813 5814 /* If not excluding matching, send the personalities to the kernel. 5815 * This never affects the result of the load operation. 5816 * This is a bit of a hack, because we shouldn't be handling 5817 * personalities within the load function. 5818 */ 5819 if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) { 5820 result = sendPersonalitiesToCatalog(true, personalityNames); 5821 } 5822 5823 finish: 5824 5825 if (result != kOSReturnSuccess) { 5826 OSKextLog(this, 5827 kOSKextLogErrorLevel | 5828 kOSKextLogLoadFlag, 5829 "Kext %s failed to load (0x%x).", 5830 getIdentifierCString(), (int)result); 5831 } else if (!alreadyLoaded) { 5832 OSKextLog(this, 5833 kOSKextLogProgressLevel | 5834 kOSKextLogLoadFlag, 5835 "Kext %s loaded.", 5836 getIdentifierCString()); 5837 5838 queueKextNotification(kKextRequestPredicateLoadNotification, 5839 OSDynamicCast(OSString, bundleID.get())); 5840 } 5841 return result; 5842 } 5843 5844 #if CONFIG_KXLD 5845 /********************************************************************* 5846 * 5847 *********************************************************************/ 5848 static char * 5849 strdup(const char * string) 5850 { 5851 char * result = NULL; 5852 size_t size; 5853 5854 if (!string) { 5855 goto finish; 5856 } 5857 5858 size = 1 + strlen(string); 5859 result = (char *)kheap_alloc_tag(KHEAP_DATA_BUFFERS, size, 5860 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 5861 if (!result) { 5862 goto finish; 5863 } 5864 5865 memcpy(result, string, size); 5866 5867 finish: 5868 return result; 5869 } 5870 #endif // CONFIG_KXLD 5871 5872 /********************************************************************* 5873 * 5874 *********************************************************************/ 5875 5876 kernel_section_t * 5877 OSKext::lookupSection(const char *segname, const char *secname) 5878 { 5879 kernel_section_t * found_section = NULL; 5880 kernel_mach_header_t * mh = NULL; 5881 kernel_segment_command_t * seg = NULL; 5882 kernel_section_t * sec = NULL; 5883 5884 if (!linkedExecutable) { 5885 return NULL; 5886 } 5887 5888 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 5889 5890 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 5891 if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) { 5892 continue; 5893 } 5894 5895 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 5896 if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) { 5897 found_section = sec; 5898 goto out; 5899 } 5900 } 5901 } 5902 5903 out: 5904 return found_section; 5905 } 5906 5907 /********************************************************************* 5908 * 5909 *********************************************************************/ 5910 5911 OSReturn 5912 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides) 5913 { 5914 OSReturn result = kOSKextReturnBadData; 5915 kernel_mach_header_t * mh = NULL; 5916 kernel_segment_command_t * seg = NULL; 5917 kernel_segment_command_t * linkeditSeg = NULL; 5918 kernel_section_t * sec = NULL; 5919 char * linkeditBase = NULL; 5920 bool haveLinkeditBase = false; 5921 char * relocBase = NULL; 5922 bool haveRelocBase = false; 5923 struct dysymtab_command * dysymtab = NULL; 5924 struct linkedit_data_command * segmentSplitInfo = NULL; 5925 struct symtab_command * symtab = NULL; 5926 kernel_nlist_t * sym = NULL; 5927 struct relocation_info * reloc = NULL; 5928 uint32_t i = 0; 5929 int reloc_size; 5930 vm_offset_t new_kextsize; 5931 5932 if (linkedExecutable == NULL || flags.builtin) { 5933 result = kOSReturnSuccess; 5934 goto finish; 5935 } 5936 5937 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy(); 5938 if (kernel_mach_header_is_in_fileset(mh)) { 5939 // kexts in filesets are slid as part of collection sliding 5940 result = kOSReturnSuccess; 5941 goto finish; 5942 } 5943 5944 segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO); 5945 5946 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 5947 if (!seg->vmaddr) { 5948 continue; 5949 } 5950 5951 seg->vmaddr = ml_static_slide(seg->vmaddr); 5952 5953 #if KASLR_KEXT_DEBUG 5954 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n", 5955 seg->segname, 5956 (unsigned long)ml_static_unslide(seg->vmaddr), 5957 (unsigned long)seg->vmaddr); 5958 #endif 5959 5960 if (!haveRelocBase) { 5961 relocBase = (char *) seg->vmaddr; 5962 haveRelocBase = true; 5963 } 5964 if (!strcmp(seg->segname, "__LINKEDIT")) { 5965 linkeditBase = (char *) seg->vmaddr - seg->fileoff; 5966 haveLinkeditBase = true; 5967 linkeditSeg = seg; 5968 } 5969 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) { 5970 sec->addr = ml_static_slide(sec->addr); 5971 5972 #if KASLR_KEXT_DEBUG 5973 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n", 5974 sec->sectname, 5975 (unsigned long)ml_static_unslide(sec->addr), 5976 (unsigned long)sec->addr); 5977 #endif 5978 } 5979 } 5980 5981 dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB); 5982 5983 symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB); 5984 5985 if (symtab != NULL && doCoalescedSlides == false) { 5986 /* Some pseudo-kexts have symbol tables without segments. 5987 * Ignore them. */ 5988 if (symtab->nsyms > 0 && haveLinkeditBase) { 5989 sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff); 5990 for (i = 0; i < symtab->nsyms; i++) { 5991 if (sym[i].n_type & N_STAB) { 5992 continue; 5993 } 5994 sym[i].n_value = ml_static_slide(sym[i].n_value); 5995 5996 #if KASLR_KEXT_DEBUG 5997 #define MAX_SYMS_TO_LOG 5 5998 if (i < MAX_SYMS_TO_LOG) { 5999 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n", 6000 (unsigned long)ml_static_unslide(sym[i].n_value), 6001 (unsigned long)sym[i].n_value); 6002 } 6003 #endif 6004 } 6005 } 6006 } 6007 6008 if (dysymtab != NULL && doCoalescedSlides == false) { 6009 if (dysymtab->nextrel > 0) { 6010 OSKextLog(this, 6011 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6012 kOSKextLogLinkFlag, 6013 "Sliding kext %s: External relocations found.", 6014 getIdentifierCString()); 6015 goto finish; 6016 } 6017 6018 if (dysymtab->nlocrel > 0) { 6019 if (!haveLinkeditBase) { 6020 OSKextLog(this, 6021 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6022 kOSKextLogLinkFlag, 6023 "Sliding kext %s: No linkedit segment.", 6024 getIdentifierCString()); 6025 goto finish; 6026 } 6027 6028 if (!haveRelocBase) { 6029 OSKextLog(this, 6030 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6031 kOSKextLogLinkFlag, 6032 #if __x86_64__ 6033 "Sliding kext %s: No writable segments.", 6034 #else 6035 "Sliding kext %s: No segments.", 6036 #endif 6037 getIdentifierCString()); 6038 goto finish; 6039 } 6040 6041 reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff); 6042 reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info); 6043 6044 for (i = 0; i < dysymtab->nlocrel; i++) { 6045 if (reloc[i].r_extern != 0 6046 || reloc[i].r_type != 0 6047 || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2) 6048 ) { 6049 OSKextLog(this, 6050 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6051 kOSKextLogLinkFlag, 6052 "Sliding kext %s: Unexpected relocation found.", 6053 getIdentifierCString()); 6054 goto finish; 6055 } 6056 if (reloc[i].r_pcrel != 0) { 6057 continue; 6058 } 6059 uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address); 6060 *relocAddr = ml_static_slide(*relocAddr); 6061 6062 #if KASLR_KEXT_DEBUG 6063 #define MAX_DYSYMS_TO_LOG 5 6064 if (i < MAX_DYSYMS_TO_LOG) { 6065 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n", 6066 (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))), 6067 (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address))); 6068 } 6069 #endif 6070 } 6071 6072 /* We should free these relocations, not just delete the reference to them. 6073 * <rdar://problem/10535549> Free relocations from PIE kexts. 6074 * 6075 * For now, we do not free LINKEDIT for kexts with split segments. 6076 */ 6077 new_kextsize = round_page(kmod_info->size - reloc_size); 6078 if (new_kextsize > UINT_MAX) { 6079 OSKextLog(this, 6080 kOSKextLogErrorLevel | kOSKextLogLoadFlag | 6081 kOSKextLogLinkFlag, 6082 "Kext %s: new kext size is too large.", 6083 getIdentifierCString()); 6084 goto finish; 6085 } 6086 if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) { 6087 vm_offset_t endofkext = kmod_info->address + kmod_info->size; 6088 vm_offset_t new_endofkext = kmod_info->address + new_kextsize; 6089 vm_offset_t endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size); 6090 size_t bytes_remaining = endofkext - endofrelocInfo; 6091 OSSharedPtr<OSData> new_osdata; 6092 6093 /* fix up symbol offsets if they are after the dsymtab local relocs */ 6094 if (symtab) { 6095 if (dysymtab->locreloff < symtab->symoff) { 6096 symtab->symoff -= reloc_size; 6097 } 6098 if (dysymtab->locreloff < symtab->stroff) { 6099 symtab->stroff -= reloc_size; 6100 } 6101 } 6102 if (dysymtab->locreloff < dysymtab->extreloff) { 6103 dysymtab->extreloff -= reloc_size; 6104 } 6105 6106 /* move data behind reloc info down to new offset */ 6107 if (endofrelocInfo < endofkext) { 6108 memcpy(reloc, (void *)endofrelocInfo, bytes_remaining); 6109 } 6110 6111 /* Create a new OSData for the smaller kext object and reflect 6112 * new linkedit segment size. 6113 */ 6114 linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size); 6115 linkeditSeg->filesize = linkeditSeg->vmsize; 6116 6117 new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize); 6118 if (new_osdata) { 6119 /* Fix up kmod info and linkedExecutable. 6120 */ 6121 kmod_info->size = new_kextsize; 6122 #if VM_MAPPED_KEXTS 6123 new_osdata->setDeallocFunction(osdata_kext_free); 6124 #else 6125 new_osdata->setDeallocFunction(osdata_phys_free); 6126 #endif 6127 linkedExecutable->setDeallocFunction(NULL); 6128 linkedExecutable = os::move(new_osdata); 6129 6130 #if VM_MAPPED_KEXTS 6131 kext_free(new_endofkext, (endofkext - new_endofkext)); 6132 #else 6133 ml_static_mfree(new_endofkext, (endofkext - new_endofkext)); 6134 #endif 6135 } 6136 } 6137 dysymtab->nlocrel = 0; 6138 dysymtab->locreloff = 0; 6139 } 6140 } 6141 6142 result = kOSReturnSuccess; 6143 finish: 6144 return result; 6145 } 6146 6147 /********************************************************************* 6148 * called only by load() 6149 *********************************************************************/ 6150 OSReturn 6151 OSKext::loadExecutable() 6152 { 6153 OSReturn result = kOSReturnError; 6154 OSSharedPtr<OSArray> linkDependencies; 6155 uint32_t num_kmod_refs = 0; 6156 OSData * theExecutable = NULL; // do not release 6157 OSString * versString = NULL; // do not release 6158 const char * versCString = NULL; // do not free 6159 const char * string = NULL; // do not free 6160 6161 #if CONFIG_KXLD 6162 unsigned int i; 6163 uint32_t numDirectDependencies = 0; 6164 kern_return_t kxldResult; 6165 KXLDDependency * kxlddeps = NULL; // must kfree 6166 uint32_t num_kxlddeps = 0; 6167 struct mach_header ** kxldHeaderPtr = NULL; // do not free 6168 struct mach_header * kxld_header = NULL; // xxx - need to free here? 6169 #endif // CONFIG_KXLD 6170 6171 /* We need the version string for a variety of bits below. 6172 */ 6173 versString = OSDynamicCast(OSString, 6174 getPropertyForHostArch(kCFBundleVersionKey)); 6175 if (!versString) { 6176 goto finish; 6177 } 6178 versCString = versString->getCStringNoCopy(); 6179 6180 if (isKernelComponent()) { 6181 if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) { 6182 if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) { 6183 OSKextLog(this, 6184 kOSKextLogErrorLevel | 6185 kOSKextLogLoadFlag, 6186 "Kernel component %s has incorrect version %s; " 6187 "expected %s.", 6188 getIdentifierCString(), 6189 versCString, KERNEL6_VERSION); 6190 result = kOSKextReturnInternalError; 6191 goto finish; 6192 } else if (strcmp(versCString, osrelease)) { 6193 OSKextLog(this, 6194 kOSKextLogErrorLevel | 6195 kOSKextLogLoadFlag, 6196 "Kernel component %s has incorrect version %s; " 6197 "expected %s.", 6198 getIdentifierCString(), 6199 versCString, osrelease); 6200 result = kOSKextReturnInternalError; 6201 goto finish; 6202 } 6203 } 6204 } 6205 6206 #if defined(__x86_64__) || defined(__i386__) 6207 if (flags.resetSegmentsFromVnode) { 6208 /* Fixup the chains and slide the mach headers */ 6209 kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address; 6210 6211 if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) { 6212 result = kOSKextReturnValidation; 6213 goto finish; 6214 } 6215 } 6216 #endif //(__x86_64__) || defined(__i386__) 6217 6218 if (isPrelinked()) { 6219 goto register_kmod; 6220 } 6221 6222 /* <rdar://problem/21444003> all callers must be entitled */ 6223 if (FALSE == IOTaskHasEntitlement(current_task(), kOSKextCollectionManagementEntitlement)) { 6224 OSKextLog(this, 6225 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 6226 "Not entitled to link kext '%s'", 6227 getIdentifierCString()); 6228 result = kOSKextReturnNotPrivileged; 6229 goto finish; 6230 } 6231 6232 theExecutable = getExecutable(); 6233 if (!theExecutable) { 6234 if (declaresExecutable()) { 6235 OSKextLog(this, 6236 kOSKextLogErrorLevel | 6237 kOSKextLogLoadFlag, 6238 "Can't load kext %s - executable is missing.", 6239 getIdentifierCString()); 6240 result = kOSKextReturnValidation; 6241 goto finish; 6242 } 6243 goto register_kmod; 6244 } 6245 6246 if (isInterface()) { 6247 OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable); 6248 if (executableCopy) { 6249 setLinkedExecutable(executableCopy.get()); 6250 } 6251 goto register_kmod; 6252 } 6253 6254 #if CONFIG_KXLD 6255 numDirectDependencies = getNumDependencies(); 6256 6257 if (flags.hasBleedthrough) { 6258 linkDependencies = dependencies; 6259 } else { 6260 linkDependencies = OSArray::withArray(dependencies.get()); 6261 if (!linkDependencies) { 6262 OSKextLog(this, 6263 kOSKextLogErrorLevel | 6264 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 6265 "Can't allocate link dependencies to load kext %s.", 6266 getIdentifierCString()); 6267 goto finish; 6268 } 6269 6270 for (i = 0; i < numDirectDependencies; ++i) { 6271 OSKext * dependencyKext = OSDynamicCast(OSKext, 6272 dependencies->getObject(i)); 6273 dependencyKext->addBleedthroughDependencies(linkDependencies.get()); 6274 } 6275 } 6276 6277 num_kxlddeps = linkDependencies->getCount(); 6278 if (!num_kxlddeps) { 6279 OSKextLog(this, 6280 kOSKextLogErrorLevel | 6281 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag, 6282 "Can't load kext %s - it has no library dependencies.", 6283 getIdentifierCString()); 6284 goto finish; 6285 } 6286 6287 kxlddeps = (KXLDDependency *)kalloc_tag(num_kxlddeps * sizeof(*kxlddeps), VM_KERN_MEMORY_OSKEXT); 6288 if (!kxlddeps) { 6289 OSKextLog(this, 6290 kOSKextLogErrorLevel | 6291 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 6292 "Can't allocate link context to load kext %s.", 6293 getIdentifierCString()); 6294 goto finish; 6295 } 6296 bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps)); 6297 6298 for (i = 0; i < num_kxlddeps; ++i) { 6299 OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i)); 6300 6301 if (dependency->isInterface()) { 6302 OSKext *interfaceTargetKext = NULL; //do not release 6303 OSData * interfaceTarget = NULL; //do not release 6304 6305 if (dependency->isKernelComponent()) { 6306 interfaceTargetKext = sKernelKext; 6307 interfaceTarget = sKernelKext->linkedExecutable.get(); 6308 } else { 6309 interfaceTargetKext = OSDynamicCast(OSKext, 6310 dependency->dependencies->getObject(0)); 6311 6312 interfaceTarget = interfaceTargetKext->linkedExecutable.get(); 6313 } 6314 6315 if (!interfaceTarget) { 6316 // panic? 6317 goto finish; 6318 } 6319 6320 /* The names set here aren't actually logged yet <rdar://problem/7941514>, 6321 * it will be useful to have them in the debugger. 6322 * strdup() failing isn't critical right here so we don't check that. 6323 */ 6324 kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy(); 6325 kxlddeps[i].kext_size = interfaceTarget->getLength(); 6326 kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString()); 6327 6328 if (dependency->linkedExecutable != NULL) { 6329 kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 6330 kxlddeps[i].interface_size = dependency->linkedExecutable->getLength(); 6331 } else { 6332 kxlddeps[i].interface = (u_char *) NULL; 6333 kxlddeps[i].interface_size = 0; 6334 } 6335 kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString()); 6336 } else { 6337 kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy(); 6338 kxlddeps[i].kext_size = dependency->linkedExecutable->getLength(); 6339 kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString()); 6340 } 6341 6342 kxlddeps[i].is_direct_dependency = (i < numDirectDependencies); 6343 } 6344 6345 kxldHeaderPtr = &kxld_header; 6346 6347 #if DEBUG 6348 OSKextLog(this, 6349 kOSKextLogExplicitLevel | 6350 kOSKextLogLoadFlag | kOSKextLogLinkFlag, 6351 "Kext %s - calling kxld_link_file:\n" 6352 " kxld_context: %p\n" 6353 " executable: %p executable_length: %d\n" 6354 " user_data: %p\n" 6355 " kxld_dependencies: %p num_dependencies: %d\n" 6356 " kxld_header_ptr: %p kmod_info_ptr: %p\n", 6357 getIdentifierCString(), sKxldContext, 6358 theExecutable->getBytesNoCopy(), theExecutable->getLength(), 6359 this, kxlddeps, num_kxlddeps, 6360 kxldHeaderPtr, &kmod_info); 6361 #endif 6362 6363 /* After this call, the linkedExecutable instance variable 6364 * should exist. 6365 */ 6366 kxldResult = kxld_link_file(sKxldContext, 6367 (u_char *)theExecutable->getBytesNoCopy(), 6368 theExecutable->getLength(), 6369 getIdentifierCString(), this, kxlddeps, num_kxlddeps, 6370 (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info); 6371 6372 if (kxldResult != KERN_SUCCESS) { 6373 // xxx - add kxldResult here? 6374 OSKextLog(this, 6375 kOSKextLogErrorLevel | 6376 kOSKextLogLoadFlag, 6377 "Can't load kext %s - link failed.", 6378 getIdentifierCString()); 6379 result = kOSKextReturnLinkError; 6380 goto finish; 6381 } 6382 6383 /* We've written data & instructions into kernel memory, so flush the data 6384 * cache and invalidate the instruction cache. 6385 * I/D caches are coherent on x86 6386 */ 6387 #if !defined(__i386__) && !defined(__x86_64__) 6388 flush_dcache(kmod_info->address, kmod_info->size, false); 6389 invalidate_icache(kmod_info->address, kmod_info->size, false); 6390 #endif 6391 6392 #else // !CONFIG_KXLD 6393 OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag, 6394 "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString()); 6395 result = kOSKextReturnLinkError; 6396 goto finish; 6397 #endif // CONFIG_KXLD 6398 6399 register_kmod: 6400 6401 if (isInterface()) { 6402 /* Whip up a fake kmod_info entry for the interface kext. 6403 */ 6404 kmod_info = (kmod_info_t *)kalloc_tag(sizeof(kmod_info_t), VM_KERN_MEMORY_OSKEXT); 6405 if (!kmod_info) { 6406 result = KERN_MEMORY_ERROR; 6407 goto finish; 6408 } 6409 6410 /* A pseudokext has almost nothing in its kmod_info struct. 6411 */ 6412 bzero(kmod_info, sizeof(kmod_info_t)); 6413 6414 kmod_info->info_version = KMOD_INFO_VERSION; 6415 6416 /* An interface kext doesn't have a linkedExecutable, so save a 6417 * copy of the UUID out of the original executable via copyUUID() 6418 * while we still have the original executable. 6419 */ 6420 interfaceUUID = copyUUID(); 6421 } 6422 6423 kmod_info->id = loadTag = sNextLoadTag++; 6424 kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid). 6425 6426 /* Stamp the bundle ID and version from the OSKext over anything 6427 * resident inside the kmod_info. 6428 */ 6429 string = getIdentifierCString(); 6430 strlcpy(kmod_info->name, string, sizeof(kmod_info->name)); 6431 6432 string = versCString; 6433 strlcpy(kmod_info->version, string, sizeof(kmod_info->version)); 6434 6435 /* Add the dependencies' kmod_info structs as kmod_references. 6436 */ 6437 num_kmod_refs = getNumDependencies(); 6438 if (num_kmod_refs) { 6439 kmod_info->reference_list = (kmod_reference_t *)kalloc_tag( 6440 num_kmod_refs * sizeof(kmod_reference_t), VM_KERN_MEMORY_OSKEXT); 6441 if (!kmod_info->reference_list) { 6442 result = KERN_MEMORY_ERROR; 6443 goto finish; 6444 } 6445 bzero(kmod_info->reference_list, 6446 num_kmod_refs * sizeof(kmod_reference_t)); 6447 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 6448 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 6449 OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex)); 6450 ref->info = refKext->kmod_info; 6451 ref->info->reference_count++; 6452 6453 if (refIndex + 1 < num_kmod_refs) { 6454 ref->next = kmod_info->reference_list + refIndex + 1; 6455 } 6456 } 6457 } 6458 6459 if (kmod_info->hdr_size > UINT32_MAX) { 6460 OSKextLog(this, 6461 kOSKextLogErrorLevel | 6462 kOSKextLogLoadFlag, 6463 #if __LP64__ 6464 "Kext %s header size is too large (%lu > UINT32_MAX).", 6465 #else 6466 "Kext %s header size is too large (%u > UINT32_MAX).", 6467 #endif 6468 kmod_info->name, 6469 kmod_info->hdr_size); 6470 result = KERN_FAILURE; 6471 goto finish; 6472 } 6473 6474 if (kmod_info->size > UINT32_MAX) { 6475 OSKextLog(this, 6476 kOSKextLogErrorLevel | 6477 kOSKextLogLoadFlag, 6478 #if __LP64__ 6479 "Kext %s size is too large (%lu > UINT32_MAX).", 6480 #else 6481 "Kext %s size is too large (%u > UINT32_MAX).", 6482 #endif 6483 kmod_info->name, 6484 kmod_info->size); 6485 result = KERN_FAILURE; 6486 goto finish; 6487 } 6488 6489 if (!isInterface() && linkedExecutable) { 6490 OSKextLog(this, 6491 kOSKextLogProgressLevel | 6492 kOSKextLogLoadFlag, 6493 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).", 6494 kmod_info->name, 6495 (unsigned)kmod_info->size / PAGE_SIZE, 6496 (unsigned long)ml_static_unslide(kmod_info->address), 6497 (unsigned)kmod_info->id); 6498 } 6499 6500 /* VM protections and wiring for the Aux KC are done at collection loading time */ 6501 if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) { 6502 /* if prelinked and primary KC, VM protections are already set */ 6503 result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true); 6504 if (result != KERN_SUCCESS) { 6505 goto finish; 6506 } 6507 } 6508 6509 #if KASAN 6510 if (linkedExecutable) { 6511 kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), 6512 linkedExecutable->getLength(), getIdentifierCString()); 6513 } 6514 #else 6515 if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) { 6516 OSKextLog(this, 6517 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 6518 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n", 6519 getIdentifierCString() 6520 ); 6521 result = KERN_FAILURE; 6522 goto finish; 6523 } 6524 #endif 6525 6526 result = kOSReturnSuccess; 6527 6528 finish: 6529 6530 #if CONFIG_KXLD 6531 /* Clear up locally allocated dependency info. 6532 */ 6533 for (i = 0; i < num_kxlddeps; ++i) { 6534 size_t size; 6535 6536 if (kxlddeps[i].kext_name) { 6537 size = 1 + strlen(kxlddeps[i].kext_name); 6538 kheap_free(KHEAP_DATA_BUFFERS, kxlddeps[i].kext_name, size); 6539 } 6540 if (kxlddeps[i].interface_name) { 6541 size = 1 + strlen(kxlddeps[i].interface_name); 6542 kheap_free(KHEAP_DATA_BUFFERS, kxlddeps[i].interface_name, size); 6543 } 6544 } 6545 if (kxlddeps) { 6546 kfree(kxlddeps, (num_kxlddeps * sizeof(*kxlddeps))); 6547 } 6548 #endif // CONFIG_KXLD 6549 6550 /* We no longer need the unrelocated executable (which the linker 6551 * has altered anyhow). 6552 */ 6553 setExecutable(NULL); 6554 6555 if (result != kOSReturnSuccess) { 6556 OSKextLog(this, 6557 kOSKextLogErrorLevel | 6558 kOSKextLogLoadFlag, 6559 "Failed to load executable for kext %s.", 6560 getIdentifierCString()); 6561 6562 if (kmod_info && kmod_info->reference_list) { 6563 kfree(kmod_info->reference_list, 6564 num_kmod_refs * sizeof(kmod_reference_t)); 6565 } 6566 if (isInterface()) { 6567 kfree(kmod_info, sizeof(kmod_info_t)); 6568 kmod_info = NULL; 6569 } 6570 if (kc_type == KCKindUnknown) { 6571 kmod_info = NULL; 6572 if (linkedExecutable) { 6573 linkedExecutable.reset(); 6574 } 6575 } 6576 } 6577 6578 return result; 6579 } 6580 6581 #if VM_MAPPED_KEXTS 6582 /* static */ 6583 void 6584 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh) 6585 { 6586 kernel_segment_command_t *linkeditseg = NULL; 6587 6588 linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT); 6589 assert(linkeditseg != NULL); 6590 6591 /* BootKC on x86_64 is not vm mapped */ 6592 ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize); 6593 6594 OSKextLog(/* kext */ NULL, 6595 kOSKextLogProgressLevel | 6596 kOSKextLogGeneralFlag, 6597 "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu", 6598 linkeditseg->vmaddr, linkeditseg->vmsize); 6599 } 6600 #endif /* VM_MAPPED_KEXTS */ 6601 6602 /********************************************************************* 6603 * The linkedit segment is used by the kext linker for dependency 6604 * resolution, and by dtrace for probe initialization. We can free it 6605 * for non-library kexts, since no kexts depend on non-library kexts 6606 * by definition, once dtrace has been initialized. 6607 *********************************************************************/ 6608 void 6609 OSKext::jettisonLinkeditSegment(void) 6610 { 6611 kernel_mach_header_t * machhdr = (kernel_mach_header_t *)kmod_info->address; 6612 kernel_segment_command_t * linkedit = NULL; 6613 vm_offset_t start; 6614 vm_size_t linkeditsize, kextsize; 6615 OSSharedPtr<OSData> data; 6616 6617 if (isInFileset()) { 6618 return; 6619 } 6620 6621 #if NO_KEXTD 6622 /* We can free symbol tables for all embedded kexts because we don't 6623 * support runtime kext linking. 6624 */ 6625 if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 6626 #else 6627 if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) { 6628 #endif 6629 goto finish; 6630 } 6631 6632 /* Find the linkedit segment. If it's not the last segment, then freeing 6633 * it will fragment the kext into multiple VM regions, which OSKext is not 6634 * designed to handle, so we'll have to skip it. 6635 */ 6636 linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT); 6637 if (!linkedit) { 6638 goto finish; 6639 } 6640 6641 if (round_page(kmod_info->address + kmod_info->size) != 6642 round_page(linkedit->vmaddr + linkedit->vmsize)) { 6643 goto finish; 6644 } 6645 6646 /* Create a new OSData for the smaller kext object. 6647 */ 6648 linkeditsize = round_page(linkedit->vmsize); 6649 kextsize = kmod_info->size - linkeditsize; 6650 start = linkedit->vmaddr; 6651 6652 if (kextsize > UINT_MAX) { 6653 goto finish; 6654 } 6655 data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize); 6656 if (!data) { 6657 goto finish; 6658 } 6659 6660 /* Fix the kmod info and linkedExecutable. 6661 */ 6662 kmod_info->size = kextsize; 6663 6664 #if VM_MAPPED_KEXTS 6665 data->setDeallocFunction(osdata_kext_free); 6666 #else 6667 data->setDeallocFunction(osdata_phys_free); 6668 #endif 6669 linkedExecutable->setDeallocFunction(NULL); 6670 linkedExecutable = os::move(data); 6671 flags.jettisonLinkeditSeg = 1; 6672 6673 /* Free the linkedit segment. 6674 */ 6675 #if VM_MAPPED_KEXTS 6676 kext_free(start, linkeditsize); 6677 #else 6678 ml_static_mfree(start, linkeditsize); 6679 #endif 6680 6681 finish: 6682 return; 6683 } 6684 6685 /********************************************************************* 6686 * If there are whole pages that are unused betweem the last section 6687 * of the DATA segment and the end of the DATA segment then we can free 6688 * them 6689 *********************************************************************/ 6690 void 6691 OSKext::jettisonDATASegmentPadding(void) 6692 { 6693 kernel_mach_header_t * mh; 6694 kernel_segment_command_t * dataSeg; 6695 kernel_section_t * sec, * lastSec; 6696 vm_offset_t dataSegEnd, lastSecEnd; 6697 vm_size_t padSize; 6698 6699 if (flags.builtin) { 6700 return; 6701 } 6702 mh = (kernel_mach_header_t *)kmod_info->address; 6703 6704 if (isInFileset()) { 6705 return; 6706 } 6707 6708 dataSeg = getsegbynamefromheader(mh, SEG_DATA); 6709 if (dataSeg == NULL) { 6710 return; 6711 } 6712 6713 lastSec = NULL; 6714 sec = firstsect(dataSeg); 6715 while (sec != NULL) { 6716 lastSec = sec; 6717 sec = nextsect(dataSeg, sec); 6718 } 6719 6720 if (lastSec == NULL) { 6721 return; 6722 } 6723 6724 if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) || 6725 (dataSeg->vmsize != round_page(dataSeg->vmsize))) { 6726 return; 6727 } 6728 6729 dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize; 6730 lastSecEnd = round_page(lastSec->addr + lastSec->size); 6731 6732 if (dataSegEnd <= lastSecEnd) { 6733 return; 6734 } 6735 6736 padSize = dataSegEnd - lastSecEnd; 6737 6738 if (padSize >= PAGE_SIZE) { 6739 #if VM_MAPPED_KEXTS 6740 kext_free(lastSecEnd, padSize); 6741 #else 6742 ml_static_mfree(lastSecEnd, padSize); 6743 #endif 6744 } 6745 } 6746 6747 /********************************************************************* 6748 *********************************************************************/ 6749 void 6750 OSKext::setLinkedExecutable(OSData * anExecutable) 6751 { 6752 if (linkedExecutable) { 6753 panic("Attempt to set linked executable on kext " 6754 "that already has one (%s).\n", 6755 getIdentifierCString()); 6756 } 6757 linkedExecutable.reset(anExecutable, OSRetain); 6758 return; 6759 } 6760 6761 #if CONFIG_DTRACE 6762 /********************************************************************* 6763 * Go through all loaded kexts and tell them to register with dtrace. 6764 * The instance method only registers if necessary. 6765 *********************************************************************/ 6766 /* static */ 6767 void 6768 OSKext::registerKextsWithDTrace(void) 6769 { 6770 uint32_t count = sLoadedKexts->getCount(); 6771 uint32_t i; 6772 6773 IORecursiveLockLock(sKextLock); 6774 6775 for (i = 0; i < count; i++) { 6776 OSKext * thisKext = NULL; // do not release 6777 6778 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 6779 if (!thisKext || !thisKext->isExecutable()) { 6780 continue; 6781 } 6782 6783 thisKext->registerWithDTrace(); 6784 } 6785 6786 IORecursiveLockUnlock(sKextLock); 6787 6788 return; 6789 } 6790 6791 extern "C" { 6792 extern int (*dtrace_modload)(struct kmod_info *, uint32_t); 6793 extern int (*dtrace_modunload)(struct kmod_info *); 6794 }; 6795 6796 /********************************************************************* 6797 *********************************************************************/ 6798 void 6799 OSKext::registerWithDTrace(void) 6800 { 6801 /* Register kext with dtrace. A dtrace_modload failure should not 6802 * prevent a kext from loading, so we ignore the return code. 6803 */ 6804 if (!flags.dtraceInitialized && (dtrace_modload != NULL)) { 6805 uint32_t modflag = 0; 6806 OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit"); 6807 6808 #if VM_MAPPED_KEXTS 6809 if (!sKeepSymbols && kc_type == KCKindPrimary) { 6810 if (forceInit == kOSBooleanTrue) { 6811 /* Make sure the kext is not from the Boot KC */ 6812 panic("OSBundleForceDTraceInit key specified for the Boot KC kext : %s", getIdentifierCString()); 6813 } else { 6814 /* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */ 6815 modflag |= KMOD_DTRACE_NO_KERNEL_SYMS; 6816 } 6817 } 6818 #endif /* VM_MAPPED_KEXTS */ 6819 if (forceInit == kOSBooleanTrue) { 6820 modflag |= KMOD_DTRACE_FORCE_INIT; 6821 } 6822 if (flags.builtin) { 6823 modflag |= KMOD_DTRACE_STATIC_KEXT; 6824 } 6825 6826 (void)(*dtrace_modload)(kmod_info, modflag); 6827 flags.dtraceInitialized = true; 6828 jettisonLinkeditSegment(); 6829 } 6830 return; 6831 } 6832 /********************************************************************* 6833 *********************************************************************/ 6834 void 6835 OSKext::unregisterWithDTrace(void) 6836 { 6837 /* Unregister kext with dtrace. A dtrace_modunload failure should not 6838 * prevent a kext from loading, so we ignore the return code. 6839 */ 6840 if (flags.dtraceInitialized && (dtrace_modunload != NULL)) { 6841 (void)(*dtrace_modunload)(kmod_info); 6842 flags.dtraceInitialized = false; 6843 } 6844 return; 6845 } 6846 #endif /* CONFIG_DTRACE */ 6847 6848 6849 /********************************************************************* 6850 * called only by loadExecutable() 6851 *********************************************************************/ 6852 #if !VM_MAPPED_KEXTS 6853 #if defined(__arm__) || defined(__arm64__) 6854 static inline kern_return_t 6855 OSKext_protect( 6856 kernel_mach_header_t *kext_mh, 6857 vm_map_t map, 6858 vm_map_offset_t start, 6859 vm_map_offset_t end, 6860 vm_prot_t new_prot, 6861 boolean_t set_max, 6862 kc_kind_t kc_type) 6863 { 6864 #pragma unused(kext_mh,map,kc_type) 6865 assert(map == kernel_map); // we can handle KEXTs arising from the PRELINK segment and no others 6866 assert(start <= end); 6867 if (start >= end) { 6868 return KERN_SUCCESS; // Punt segments of length zero (e.g., headers) or less (i.e., blunders) 6869 } else if (set_max) { 6870 return KERN_SUCCESS; // Punt set_max, as there's no mechanism to record that state 6871 } else { 6872 return ml_static_protect(start, end - start, new_prot); 6873 } 6874 } 6875 6876 static inline kern_return_t 6877 OSKext_wire( 6878 kernel_mach_header_t *kext_mh, 6879 vm_map_t map, 6880 vm_map_offset_t start, 6881 vm_map_offset_t end, 6882 vm_prot_t access_type, 6883 boolean_t user_wire, 6884 kc_kind_t kc_type) 6885 { 6886 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type) 6887 return KERN_SUCCESS; // No-op as PRELINK kexts are cemented into physical memory at boot 6888 } 6889 #else 6890 #error Unrecognized architecture 6891 #endif 6892 #else 6893 static inline kern_return_t 6894 OSKext_protect( 6895 kernel_mach_header_t *kext_mh, 6896 vm_map_t map, 6897 vm_map_offset_t start, 6898 vm_map_offset_t end, 6899 vm_prot_t new_prot, 6900 boolean_t set_max, 6901 kc_kind_t kc_type) 6902 { 6903 if (start == end) { // 10538581 6904 return KERN_SUCCESS; 6905 } 6906 if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) { 6907 /* 6908 * XXX: This will probably need to be different for AuxKC and 6909 * pageableKC! 6910 */ 6911 return ml_static_protect(start, end - start, new_prot); 6912 } 6913 return vm_map_protect(map, start, end, new_prot, set_max); 6914 } 6915 6916 static inline kern_return_t 6917 OSKext_wire( 6918 kernel_mach_header_t *kext_mh, 6919 vm_map_t map, 6920 vm_map_offset_t start, 6921 vm_map_offset_t end, 6922 vm_prot_t access_type, 6923 boolean_t user_wire, 6924 kc_kind_t kc_type) 6925 { 6926 if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) { 6927 /* TODO: we may need to hook this for the pageableKC */ 6928 return KERN_SUCCESS; 6929 } 6930 return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire); 6931 } 6932 #endif 6933 6934 OSReturn 6935 OSKext::setVMAttributes(bool protect, bool wire) 6936 { 6937 vm_map_t kext_map = NULL; 6938 kernel_segment_command_t * seg = NULL; 6939 vm_map_offset_t start_protect = 0; 6940 vm_map_offset_t start_wire = 0; 6941 vm_map_offset_t end_protect = 0; 6942 vm_map_offset_t end_wire = 0; 6943 OSReturn result = kOSReturnError; 6944 6945 if (isInterface() || !declaresExecutable() || flags.builtin) { 6946 result = kOSReturnSuccess; 6947 goto finish; 6948 } 6949 6950 /* Get the kext's vm map */ 6951 kext_map = kext_get_vm_map(kmod_info); 6952 if (!kext_map) { 6953 result = KERN_MEMORY_ERROR; 6954 goto finish; 6955 } 6956 6957 #if !VM_MAPPED_KEXTS 6958 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) { 6959 /* This is a split kext in a prelinked kernelcache; we'll let the 6960 * platform code take care of protecting it. It is already wired. 6961 */ 6962 /* TODO: Should this still allow protections for the first segment 6963 * to go through, in the event that we have a mix of split and 6964 * unsplit kexts? 6965 */ 6966 result = KERN_SUCCESS; 6967 goto finish; 6968 } 6969 6970 if (isInFileset() && kc_type != KCKindPageable) { 6971 // kexts in filesets have protections setup as part of collection loading 6972 result = KERN_SUCCESS; 6973 goto finish; 6974 } 6975 #endif 6976 6977 /* Protect the headers as read-only; they do not need to be wired */ 6978 result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address, 6979 kext_map, kmod_info->address, 6980 kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type) 6981 : KERN_SUCCESS; 6982 if (result != KERN_SUCCESS) { 6983 goto finish; 6984 } 6985 6986 /* Set the VM protections and wire down each of the segments */ 6987 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 6988 while (seg) { 6989 #if __arm__ 6990 /* We build all ARM kexts, so we can ensure they are aligned */ 6991 assert((seg->vmaddr & PAGE_MASK) == 0); 6992 assert((seg->vmsize & PAGE_MASK) == 0); 6993 #endif 6994 6995 /* 6996 * For the non page aligned segments, the range calculation for protection 6997 * and wiring differ as follows: 6998 * 6999 * Protection: The non page aligned data at the start or at the end of the 7000 * segment is excluded from the protection. This exclusion is needed to make 7001 * sure OSKext_protect is not called twice on same page, if the page is shared 7002 * between two segments. 7003 * 7004 * Wiring: The non page aligned data at the start or at the end of the 7005 * segment is included in the wiring range, this inclusion is needed to make sure 7006 * all the data of the segment is wired. 7007 */ 7008 start_protect = round_page(seg->vmaddr); 7009 end_protect = trunc_page(seg->vmaddr + seg->vmsize); 7010 7011 start_wire = trunc_page(seg->vmaddr); 7012 end_wire = round_page(seg->vmaddr + seg->vmsize); 7013 7014 /* 7015 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared 7016 * across kexts and data from kexts is not page aligned 7017 */ 7018 if (protect && (end_protect > start_protect) && 7019 ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 && 7020 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) || 7021 (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) { 7022 result = OSKext_protect((kernel_mach_header_t *)kmod_info->address, 7023 kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type); 7024 if (result != KERN_SUCCESS) { 7025 OSKextLog(this, 7026 kOSKextLogErrorLevel | 7027 kOSKextLogLoadFlag, 7028 "Kext %s failed to set maximum VM protections " 7029 "for segment %s - 0x%x.", 7030 getIdentifierCString(), seg->segname, (int)result); 7031 goto finish; 7032 } 7033 7034 result = OSKext_protect((kernel_mach_header_t *)kmod_info->address, 7035 kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type); 7036 if (result != KERN_SUCCESS) { 7037 OSKextLog(this, 7038 kOSKextLogErrorLevel | 7039 kOSKextLogLoadFlag, 7040 "Kext %s failed to set initial VM protections " 7041 "for segment %s - 0x%x.", 7042 getIdentifierCString(), seg->segname, (int)result); 7043 goto finish; 7044 } 7045 } 7046 7047 if (segmentShouldBeWired(seg) && wire) { 7048 result = OSKext_wire((kernel_mach_header_t *)kmod_info->address, 7049 kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type); 7050 if (result != KERN_SUCCESS) { 7051 goto finish; 7052 } 7053 } 7054 7055 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 7056 } 7057 7058 finish: 7059 return result; 7060 } 7061 7062 /********************************************************************* 7063 *********************************************************************/ 7064 boolean_t 7065 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg) 7066 { 7067 return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) && 7068 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname))); 7069 } 7070 7071 /********************************************************************* 7072 *********************************************************************/ 7073 OSReturn 7074 OSKext::validateKextMapping(bool startFlag) 7075 { 7076 OSReturn result = kOSReturnError; 7077 const char * whichOp = startFlag ? "start" : "stop"; 7078 kern_return_t kern_result = 0; 7079 vm_map_t kext_map = NULL; 7080 kernel_segment_command_t * seg = NULL; 7081 mach_vm_address_t address = 0; 7082 mach_vm_size_t size = 0; 7083 uint32_t depth = 0; 7084 uint64_t kext_segbase = 0; 7085 uint64_t kext_segsize = 0; 7086 mach_msg_type_number_t count; 7087 vm_region_submap_short_info_data_64_t info; 7088 uintptr_t kext_slide = PE_get_kc_slide(kc_type); 7089 7090 if (flags.builtin) { 7091 return kOSReturnSuccess; 7092 } 7093 7094 count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 7095 bzero(&info, sizeof(info)); 7096 7097 // xxx - do we need a distinct OSReturn value for these or is "bad data" 7098 // xxx - sufficient? 7099 7100 /* Verify that the kmod_info and start/stop pointers are non-NULL. 7101 */ 7102 if (!kmod_info) { 7103 OSKextLog(this, 7104 kOSKextLogErrorLevel | 7105 kOSKextLogLoadFlag, 7106 "Kext %s - NULL kmod_info pointer.", 7107 getIdentifierCString()); 7108 result = kOSKextReturnBadData; 7109 goto finish; 7110 } 7111 7112 if (startFlag) { 7113 address = (mach_vm_address_t)kmod_info->start; 7114 } else { 7115 address = (mach_vm_address_t)kmod_info->stop; 7116 } 7117 7118 if (!address) { 7119 OSKextLog(this, 7120 kOSKextLogErrorLevel | 7121 kOSKextLogLoadFlag, 7122 "Kext %s - NULL module %s pointer.", 7123 getIdentifierCString(), whichOp); 7124 result = kOSKextReturnBadData; 7125 goto finish; 7126 } 7127 7128 kext_map = kext_get_vm_map(kmod_info); 7129 depth = (kernel_map == kext_map) ? 1 : 2; 7130 if (isInFileset()) { 7131 #if defined(HAS_APPLE_PAC) 7132 address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0); 7133 #endif /* defined(HAS_APPLE_PAC) */ 7134 } 7135 7136 /* Verify that the start/stop function lies within the kext's address range. 7137 */ 7138 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) || 7139 isInFileset()) { 7140 /* This will likely be how we deal with split kexts; walk the segments to 7141 * check that the function lies inside one of the segments of this kext. 7142 */ 7143 for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 7144 seg != NULL; 7145 seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) { 7146 if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) { 7147 kext_segbase = seg->vmaddr; 7148 kext_segsize = seg->vmsize; 7149 break; 7150 } 7151 } 7152 7153 if (!seg) { 7154 OSKextLog(this, 7155 kOSKextLogErrorLevel | 7156 kOSKextLogLoadFlag, 7157 "Kext %s module %s pointer is outside of kext range " 7158 "(%s %p - kext starts at %p).", 7159 getIdentifierCString(), 7160 whichOp, 7161 whichOp, 7162 (void *)(((uintptr_t)address) - kext_slide), 7163 (void *)(((uintptr_t)kmod_info->address) - kext_slide)); 7164 result = kOSKextReturnBadData; 7165 goto finish; 7166 } 7167 7168 seg = NULL; 7169 } else { 7170 if (address < kmod_info->address + kmod_info->hdr_size || 7171 kmod_info->address + kmod_info->size <= address) { 7172 OSKextLog(this, 7173 kOSKextLogErrorLevel | 7174 kOSKextLogLoadFlag, 7175 "Kext %s module %s pointer is outside of kext range " 7176 "(%s %p - kext at %p-%p).", 7177 getIdentifierCString(), 7178 whichOp, 7179 whichOp, 7180 (void *)(((uintptr_t)address) - kext_slide), 7181 (void *)(((uintptr_t)kmod_info->address) - kext_slide), 7182 (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size)); 7183 result = kOSKextReturnBadData; 7184 goto finish; 7185 } 7186 } 7187 7188 /* Only do these checks before calling the start function; 7189 * If anything goes wrong with the mapping while the kext is running, 7190 * we'll likely have panicked well before any attempt to stop the kext. 7191 */ 7192 if (startFlag) { 7193 if (!isInFileset() || kc_type != KCKindPrimary) { 7194 /* 7195 * Verify that the start/stop function is executable. 7196 */ 7197 kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth, 7198 (vm_region_recurse_info_t)&info, &count); 7199 if (kern_result != KERN_SUCCESS) { 7200 OSKextLog(this, 7201 kOSKextLogErrorLevel | 7202 kOSKextLogLoadFlag, 7203 "Kext %s - bad %s pointer %p.", 7204 getIdentifierCString(), 7205 whichOp, (void *)ml_static_unslide(address)); 7206 result = kOSKextReturnBadData; 7207 goto finish; 7208 } 7209 } else { 7210 /* 7211 * Since kexts loaded from the primary KC are held in memory 7212 * allocated by efiboot, we cannot use mach_vm_region_recurse() to 7213 * discover that memory's protection flags. Instead, we need to 7214 * get that information from the kernel pmap itself. Above, we 7215 * (potentially) saved the size of the segment in which the address 7216 * in question was located. If we have a non-zero size, verify 7217 * that all pages in the (address, address + kext_segsize) range 7218 * are marked executable. If we somehow did not record the size 7219 * (or the base) just verify the single page that includes the address. 7220 */ 7221 if (kext_segbase == 0 || kext_segsize == 0) { 7222 kext_segbase = address & ~(uint64_t)PAGE_MASK; 7223 kext_segsize = PAGE_SIZE; 7224 } 7225 } 7226 7227 #if VM_MAPPED_KEXTS 7228 if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) || 7229 ((isInFileset() && kc_type == KCKindPrimary) && 7230 ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) { 7231 OSKextLog(this, 7232 kOSKextLogErrorLevel | 7233 kOSKextLogLoadFlag, 7234 "Kext %s - memory region containing module %s function " 7235 "is not executable.", 7236 getIdentifierCString(), whichOp); 7237 result = kOSKextReturnBadData; 7238 goto finish; 7239 } 7240 #endif 7241 7242 /* Verify that the kext's segments are backed by physical memory. 7243 */ 7244 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 7245 while (seg) { 7246 if (!verifySegmentMapping(seg)) { 7247 result = kOSKextReturnBadData; 7248 goto finish; 7249 } 7250 7251 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 7252 } 7253 } 7254 7255 result = kOSReturnSuccess; 7256 finish: 7257 return result; 7258 } 7259 7260 /********************************************************************* 7261 *********************************************************************/ 7262 boolean_t 7263 OSKext::verifySegmentMapping(kernel_segment_command_t *seg) 7264 { 7265 mach_vm_address_t address = 0; 7266 7267 if (seg->vmsize > UINT32_MAX) { 7268 return false; 7269 } 7270 7271 if (!segmentShouldBeWired(seg)) { 7272 return true; 7273 } 7274 7275 for (address = seg->vmaddr; 7276 address < round_page(seg->vmaddr + seg->vmsize); 7277 address += PAGE_SIZE) { 7278 if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) { 7279 OSKextLog(this, 7280 kOSKextLogErrorLevel | 7281 kOSKextLogLoadFlag, 7282 "Kext %s - page %p is not backed by physical memory.", 7283 getIdentifierCString(), 7284 (void *)address); 7285 return false; 7286 } 7287 } 7288 7289 return true; 7290 } 7291 7292 /********************************************************************* 7293 *********************************************************************/ 7294 static void 7295 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code) 7296 { 7297 uint64_t stamp = 0; 7298 firehose_tracepoint_id_u trace_id; 7299 struct firehose_trace_uuid_info_s uuid_info_s; 7300 firehose_trace_uuid_info_t uuid_info = &uuid_info_s; 7301 size_t uuid_info_len = sizeof(struct firehose_trace_uuid_info_s); 7302 OSSharedPtr<OSData> uuid_data; 7303 7304 stamp = firehose_tracepoint_time(firehose_activity_flags_default); 7305 trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code); 7306 7307 uuid_data = aKext->copyTextUUID(); 7308 if (uuid_data) { 7309 memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid)); 7310 } 7311 7312 uuid_info->ftui_size = size; 7313 if (aKext->isDriverKit()) { 7314 uuid_info->ftui_address = address; 7315 } else { 7316 uuid_info->ftui_address = ml_static_unslide(address); 7317 } 7318 firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len); 7319 return; 7320 } 7321 7322 void 7323 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext) 7324 { 7325 OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load); 7326 } 7327 7328 /********************************************************************* 7329 *********************************************************************/ 7330 OSReturn 7331 OSKext::start(bool startDependenciesFlag) 7332 { 7333 OSReturn result = kOSReturnError; 7334 kern_return_t (* startfunc)(kmod_info_t *, void *); 7335 unsigned int i, count; 7336 void * kmodStartData = NULL; 7337 7338 if (isStarted() || isInterface() || isKernelComponent()) { 7339 result = kOSReturnSuccess; 7340 goto finish; 7341 } 7342 7343 if (!isLoaded()) { 7344 OSKextLog(this, 7345 kOSKextLogErrorLevel | 7346 kOSKextLogLoadFlag, 7347 "Attempt to start nonloaded kext %s.", 7348 getIdentifierCString()); 7349 result = kOSKextReturnInvalidArgument; 7350 goto finish; 7351 } 7352 7353 if (!sLoadEnabled) { 7354 OSKextLog(this, 7355 kOSKextLogErrorLevel | 7356 kOSKextLogLoadFlag, 7357 "Kext loading is disabled (attempt to start kext %s).", 7358 getIdentifierCString()); 7359 result = kOSKextReturnDisabled; 7360 goto finish; 7361 } 7362 7363 result = validateKextMapping(/* start? */ true); 7364 if (result != kOSReturnSuccess) { 7365 goto finish; 7366 } 7367 7368 startfunc = kmod_info->start; 7369 7370 count = getNumDependencies(); 7371 for (i = 0; i < count; i++) { 7372 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i)); 7373 if (dependency == NULL) { 7374 OSKextLog(this, 7375 kOSKextLogErrorLevel | 7376 kOSKextLogLoadFlag, 7377 "Kext %s start - internal error, dependency disappeared.", 7378 getIdentifierCString()); 7379 goto finish; 7380 } 7381 if (!dependency->isStarted()) { 7382 if (startDependenciesFlag) { 7383 OSReturn dependencyResult = 7384 dependency->start(startDependenciesFlag); 7385 if (dependencyResult != KERN_SUCCESS) { 7386 OSKextLog(this, 7387 kOSKextLogErrorLevel | 7388 kOSKextLogLoadFlag, 7389 "Kext %s start - dependency %s failed to start (error 0x%x).", 7390 getIdentifierCString(), 7391 dependency->getIdentifierCString(), 7392 dependencyResult); 7393 goto finish; 7394 } 7395 } else { 7396 OSKextLog(this, 7397 kOSKextLogErrorLevel | 7398 kOSKextLogLoadFlag, 7399 "Not starting %s - dependency %s not started yet.", 7400 getIdentifierCString(), 7401 dependency->getIdentifierCString()); 7402 result = kOSKextReturnStartStopError; // xxx - make new return? 7403 goto finish; 7404 } 7405 } 7406 } 7407 7408 OSKextLog(this, 7409 kOSKextLogDetailLevel | 7410 kOSKextLogLoadFlag, 7411 "Kext %s calling module start function.", 7412 getIdentifierCString()); 7413 7414 flags.starting = 1; 7415 7416 // Drop a log message so logd can grab the needed information to decode this kext 7417 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load); 7418 result = OSRuntimeInitializeCPP(this); 7419 if (result == KERN_SUCCESS) { 7420 result = startfunc(kmod_info, kmodStartData); 7421 } 7422 7423 flags.starting = 0; 7424 7425 /* On success overlap the setting of started/starting. On failure just 7426 * clear starting. 7427 */ 7428 if (result == KERN_SUCCESS) { 7429 flags.started = 1; 7430 7431 // xxx - log start error from kernel? 7432 OSKextLog(this, 7433 kOSKextLogProgressLevel | 7434 kOSKextLogLoadFlag, 7435 "Kext %s is now started.", 7436 getIdentifierCString()); 7437 } else { 7438 invokeOrCancelRequestCallbacks( 7439 /* result not actually used */ kOSKextReturnStartStopError, 7440 /* invokeFlag */ false); 7441 OSKextLog(this, 7442 kOSKextLogWarningLevel | 7443 kOSKextLogLoadFlag, 7444 "Kext %s did not start (return code 0x%x).", 7445 getIdentifierCString(), result); 7446 } 7447 7448 finish: 7449 return result; 7450 } 7451 7452 /********************************************************************* 7453 *********************************************************************/ 7454 /* static */ 7455 bool 7456 OSKext::canUnloadKextWithIdentifier( 7457 OSString * kextIdentifier, 7458 bool checkClassesFlag) 7459 { 7460 bool result = false; 7461 OSKext * aKext = NULL; // do not release 7462 7463 IORecursiveLockLock(sKextLock); 7464 7465 aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 7466 7467 if (!aKext) { 7468 goto finish; // can't unload what's not loaded 7469 } 7470 7471 if (aKext->isLoaded()) { 7472 if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) { 7473 goto finish; 7474 } 7475 if (checkClassesFlag && aKext->hasOSMetaClassInstances()) { 7476 goto finish; 7477 } 7478 } 7479 7480 result = true; 7481 7482 finish: 7483 IORecursiveLockUnlock(sKextLock); 7484 return result; 7485 } 7486 7487 /********************************************************************* 7488 *********************************************************************/ 7489 OSReturn 7490 OSKext::stop(void) 7491 { 7492 OSReturn result = kOSReturnError; 7493 kern_return_t (*stopfunc)(kmod_info_t *, void *); 7494 7495 if (!isStarted() || isInterface()) { 7496 result = kOSReturnSuccess; 7497 goto finish; 7498 } 7499 7500 if (!isLoaded()) { 7501 OSKextLog(this, 7502 kOSKextLogErrorLevel | 7503 kOSKextLogLoadFlag, 7504 "Attempt to stop nonloaded kext %s.", 7505 getIdentifierCString()); 7506 result = kOSKextReturnInvalidArgument; 7507 goto finish; 7508 } 7509 7510 /* Refuse to stop if we have clients or instances. It is up to 7511 * the caller to make sure those aren't true. 7512 */ 7513 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 7514 OSKextLog(this, 7515 kOSKextLogErrorLevel | 7516 kOSKextLogLoadFlag, 7517 "Kext %s - C++ instances; can't stop.", 7518 getIdentifierCString()); 7519 result = kOSKextReturnInUse; 7520 goto finish; 7521 } 7522 7523 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 7524 OSKextLog(this, 7525 kOSKextLogErrorLevel | 7526 kOSKextLogLoadFlag, 7527 "Kext %s - has references (linkage or tracking object); " 7528 "can't stop.", 7529 getIdentifierCString()); 7530 result = kOSKextReturnInUse; 7531 goto finish; 7532 } 7533 7534 /* Note: If validateKextMapping fails on the stop & unload path, 7535 * we are in serious trouble and a kernel panic is likely whether 7536 * we stop & unload the kext or not. 7537 */ 7538 result = validateKextMapping(/* start? */ false); 7539 if (result != kOSReturnSuccess) { 7540 goto finish; 7541 } 7542 7543 stopfunc = kmod_info->stop; 7544 if (stopfunc) { 7545 OSKextLog(this, 7546 kOSKextLogDetailLevel | 7547 kOSKextLogLoadFlag, 7548 "Kext %s calling module stop function.", 7549 getIdentifierCString()); 7550 7551 flags.stopping = 1; 7552 7553 result = stopfunc(kmod_info, /* userData */ NULL); 7554 if (result == KERN_SUCCESS) { 7555 result = OSRuntimeFinalizeCPP(this); 7556 } 7557 7558 flags.stopping = 0; 7559 7560 if (result == KERN_SUCCESS) { 7561 flags.started = 0; 7562 7563 OSKextLog(this, 7564 kOSKextLogDetailLevel | 7565 kOSKextLogLoadFlag, 7566 "Kext %s is now stopped and ready to unload.", 7567 getIdentifierCString()); 7568 } else { 7569 OSKextLog(this, 7570 kOSKextLogErrorLevel | 7571 kOSKextLogLoadFlag, 7572 "Kext %s did not stop (return code 0x%x).", 7573 getIdentifierCString(), result); 7574 result = kOSKextReturnStartStopError; 7575 } 7576 } 7577 7578 finish: 7579 // Drop a log message so logd can update this kext's metadata 7580 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload); 7581 return result; 7582 } 7583 7584 /********************************************************************* 7585 *********************************************************************/ 7586 OSReturn 7587 OSKext::unload(void) 7588 { 7589 OSReturn result = kOSReturnError; 7590 unsigned int index; 7591 uint32_t num_kmod_refs = 0; 7592 OSKextAccount * freeAccount; 7593 bool in_fileset = false; 7594 7595 if (!sUnloadEnabled) { 7596 OSKextLog(this, 7597 kOSKextLogErrorLevel | 7598 kOSKextLogLoadFlag, 7599 "Kext unloading is disabled (%s).", 7600 this->getIdentifierCString()); 7601 7602 result = kOSKextReturnDisabled; 7603 goto finish; 7604 } 7605 7606 // cache this result so we don't need to access the kmod_info after 7607 // it's been potentially free'd 7608 in_fileset = isInFileset(); 7609 7610 /* Refuse to unload if we have clients or instances. It is up to 7611 * the caller to make sure those aren't true. 7612 */ 7613 if (getRetainCount() > kOSKextMinLoadedRetainCount) { 7614 // xxx - Don't log under errors? this is more of an info thing 7615 OSKextLog(this, 7616 kOSKextLogErrorLevel | 7617 kOSKextLogKextBookkeepingFlag, 7618 "Can't unload kext %s; outstanding references (linkage or tracking object).", 7619 getIdentifierCString()); 7620 result = kOSKextReturnInUse; 7621 goto finish; 7622 } 7623 7624 if (isDriverKit()) { 7625 index = sLoadedKexts->getNextIndexOfObject(this, 0); 7626 if (index != (unsigned int)-1) { 7627 sLoadedDriverKitKexts->removeObject(index); 7628 OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload); 7629 loadTag = 0; 7630 } 7631 } 7632 7633 if (!isLoaded()) { 7634 result = kOSReturnSuccess; 7635 goto finish; 7636 } 7637 7638 if (isKernelComponent()) { 7639 result = kOSKextReturnInvalidArgument; 7640 goto finish; 7641 } 7642 7643 if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) { 7644 OSKextLog(this, 7645 kOSKextLogErrorLevel | 7646 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 7647 "Can't unload kext %s; classes have instances:", 7648 getIdentifierCString()); 7649 reportOSMetaClassInstances(kOSKextLogErrorLevel | 7650 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag); 7651 result = kOSKextReturnInUse; 7652 goto finish; 7653 } 7654 7655 /* Note that the kext is unloading before running any code that 7656 * might be in the kext (request callbacks, module stop function). 7657 * We will deny certain requests made against a kext in the process 7658 * of unloading. 7659 */ 7660 flags.unloading = 1; 7661 7662 /* Update the string describing the last kext to unload in case we panic. 7663 */ 7664 savePanicString(/* isLoading */ false); 7665 7666 if (isStarted()) { 7667 result = stop(); 7668 if (result != KERN_SUCCESS) { 7669 OSKextLog(this, 7670 kOSKextLogErrorLevel | 7671 kOSKextLogLoadFlag, 7672 "Kext %s can't unload - module stop returned 0x%x.", 7673 getIdentifierCString(), (unsigned)result); 7674 result = kOSKextReturnStartStopError; 7675 goto finish; 7676 } 7677 } 7678 7679 OSKextLog(this, 7680 kOSKextLogProgressLevel | 7681 kOSKextLogLoadFlag, 7682 "Kext %s unloading.", 7683 getIdentifierCString()); 7684 7685 { 7686 struct list_head *p; 7687 struct list_head *prev; 7688 struct list_head *next; 7689 for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) { 7690 OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head); 7691 s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize); 7692 prev = p->prev; 7693 next = p->next; 7694 prev->next = next; 7695 next->prev = prev; 7696 p->prev = p; 7697 p->next = p; 7698 IORecursiveLockWakeup(sKextLock, s, false); 7699 } 7700 } 7701 7702 7703 /* Even if we don't call the stop function, we want to be sure we 7704 * have no OSMetaClass references before unloading the kext executable 7705 * from memory. OSMetaClasses may have pointers into the kext executable 7706 * and that would cause a panic on OSKext::free() when metaClasses is freed. 7707 */ 7708 if (metaClasses) { 7709 metaClasses->flushCollection(); 7710 } 7711 (void) OSRuntimeFinalizeCPP(this); 7712 7713 /* Remove the kext from the list of loaded kexts, patch the gap 7714 * in the kmod_info_t linked list, and reset "kmod" to point to the 7715 * last loaded kext that isn't the fake kernel kext (sKernelKext). 7716 */ 7717 index = sLoadedKexts->getNextIndexOfObject(this, 0); 7718 if (index != (unsigned int)-1) { 7719 sLoadedKexts->removeObject(index); 7720 7721 OSKext * nextKext = OSDynamicCast(OSKext, 7722 sLoadedKexts->getObject(index)); 7723 7724 if (nextKext) { 7725 if (index > 0) { 7726 OSKext * gapKext = OSDynamicCast(OSKext, 7727 sLoadedKexts->getObject(index - 1)); 7728 7729 nextKext->kmod_info->next = gapKext->kmod_info; 7730 } else { /* index == 0 */ 7731 nextKext->kmod_info->next = NULL; 7732 } 7733 } 7734 7735 OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject()); 7736 if (lastKext && !lastKext->isKernel()) { 7737 kmod = lastKext->kmod_info; 7738 } else { 7739 kmod = NULL; // clear the global kmod variable 7740 } 7741 } 7742 7743 /* Clear out the kmod references that we're keeping for compatibility 7744 * with current panic backtrace code & kgmacros. 7745 * xxx - will want to update those bits sometime and remove this. 7746 */ 7747 num_kmod_refs = getNumDependencies(); 7748 if (num_kmod_refs && kmod_info && kmod_info->reference_list) { 7749 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) { 7750 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]); 7751 ref->info->reference_count--; 7752 } 7753 kfree(kmod_info->reference_list, 7754 num_kmod_refs * sizeof(kmod_reference_t)); 7755 } 7756 7757 #if CONFIG_DTRACE 7758 unregisterWithDTrace(); 7759 #endif /* CONFIG_DTRACE */ 7760 7761 notifyKextUnloadObservers(this); 7762 7763 freeAccount = NULL; 7764 IOSimpleLockLock(sKextAccountsLock); 7765 account->kext = NULL; 7766 if (account->site.tag) { 7767 account->site.flags |= VM_TAG_UNLOAD; 7768 } else { 7769 freeAccount = account; 7770 } 7771 IOSimpleLockUnlock(sKextAccountsLock); 7772 if (freeAccount) { 7773 IODelete(freeAccount, OSKextAccount, 1); 7774 } 7775 7776 /* Unwire and free the linked executable. 7777 */ 7778 if (linkedExecutable) { 7779 #if KASAN 7780 kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength()); 7781 #endif 7782 7783 #if VM_MAPPED_KEXTS 7784 if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) { 7785 kernel_segment_command_t *seg = NULL; 7786 vm_map_t kext_map = kext_get_vm_map(kmod_info); 7787 7788 if (!kext_map) { 7789 OSKextLog(this, 7790 kOSKextLogErrorLevel | 7791 kOSKextLogLoadFlag, 7792 "Failed to free kext %s; couldn't find the kext map.", 7793 getIdentifierCString()); 7794 result = kOSKextReturnInternalError; 7795 goto finish; 7796 } 7797 7798 OSKextLog(this, 7799 kOSKextLogProgressLevel | 7800 kOSKextLogLoadFlag, 7801 "Kext %s unwiring and unmapping linked executable.", 7802 getIdentifierCString()); 7803 7804 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address); 7805 while (seg) { 7806 if (segmentShouldBeWired(seg)) { 7807 vm_map_offset_t start_wire = trunc_page(seg->vmaddr); 7808 vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize); 7809 7810 result = vm_map_unwire(kext_map, start_wire, 7811 end_wire, FALSE); 7812 if (result != KERN_SUCCESS) { 7813 OSKextLog(this, 7814 kOSKextLogErrorLevel | 7815 kOSKextLogLoadFlag, 7816 "Failed to unwire kext %s.", 7817 getIdentifierCString()); 7818 result = kOSKextReturnInternalError; 7819 goto finish; 7820 } 7821 } 7822 7823 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg); 7824 } 7825 #if defined(__x86_64__) || defined(__i386__) 7826 if (in_fileset && flags.resetSegmentsFromVnode) { 7827 IORecursiveLockLock(sKextLock); 7828 resetKCFileSetSegments(); 7829 IORecursiveLockUnlock(sKextLock); 7830 } 7831 #endif // (__x86_64__) || defined(__i386__) 7832 } 7833 #endif /* VM_MAPPED_KEXTS */ 7834 if (flags.resetSegmentsFromImmutableCopy) { 7835 result = resetMutableSegments(); 7836 if (result != kOSReturnSuccess) { 7837 OSKextLog(this, 7838 kOSKextLogErrorLevel | 7839 kOSKextLogLoadFlag, 7840 "Failed to reset kext %s.", 7841 getIdentifierCString()); 7842 result = kOSKextReturnInternalError; 7843 goto finish; 7844 } 7845 } 7846 if (kc_type == KCKindUnknown) { 7847 linkedExecutable.reset(); 7848 } 7849 } 7850 7851 /* An interface kext has a fake kmod_info that was allocated, 7852 * so we have to free it. 7853 */ 7854 if (isInterface()) { 7855 kfree(kmod_info, sizeof(kmod_info_t)); 7856 kmod_info = NULL; 7857 } 7858 7859 if (!in_fileset) { 7860 kmod_info = NULL; 7861 } 7862 7863 flags.loaded = false; 7864 flushDependencies(); 7865 7866 /* save a copy of the bundle ID for us to check when deciding to 7867 * rebuild the kernel cache file. If a kext was already in the kernel 7868 * cache and unloaded then later loaded we do not need to rebuild the 7869 * kernel cache. 9055303 7870 */ 7871 if (isPrelinked()) { 7872 if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) { 7873 IORecursiveLockLock(sKextLock); 7874 if (sUnloadedPrelinkedKexts) { 7875 sUnloadedPrelinkedKexts->setObject(bundleID.get()); 7876 } 7877 IORecursiveLockUnlock(sKextLock); 7878 } 7879 } 7880 7881 OSKextLog(this, 7882 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 7883 "Kext %s unloaded.", getIdentifierCString()); 7884 7885 queueKextNotification(kKextRequestPredicateUnloadNotification, 7886 OSDynamicCast(OSString, bundleID.get())); 7887 7888 finish: 7889 OSKext::saveLoadedKextPanicList(); 7890 OSKext::updateLoadedKextSummaries(); 7891 7892 flags.unloading = 0; 7893 return result; 7894 } 7895 7896 /********************************************************************* 7897 * Assumes sKextLock is held. 7898 *********************************************************************/ 7899 /* static */ 7900 OSReturn 7901 OSKext::queueKextNotification( 7902 const char * notificationName, 7903 OSString * kextIdentifier) 7904 { 7905 OSReturn result = kOSReturnError; 7906 OSSharedPtr<OSDictionary> loadRequest; 7907 7908 if (!kextIdentifier) { 7909 result = kOSKextReturnInvalidArgument; 7910 goto finish; 7911 } 7912 7913 /* Create a new request unless one is already sitting 7914 * in sKernelRequests for this bundle identifier 7915 */ 7916 result = _OSKextCreateRequest(notificationName, loadRequest); 7917 if (result != kOSReturnSuccess) { 7918 goto finish; 7919 } 7920 if (!_OSKextSetRequestArgument(loadRequest.get(), 7921 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) { 7922 result = kOSKextReturnNoMemory; 7923 goto finish; 7924 } 7925 if (!sKernelRequests->setObject(loadRequest.get())) { 7926 result = kOSKextReturnNoMemory; 7927 goto finish; 7928 } 7929 7930 /* We might want to only queue the notification if the IOKit daemon is active, 7931 * but that wouldn't work for embedded. Note that we don't care if 7932 * the ping immediately succeeds here so don't do anything with the 7933 * result of this call. 7934 */ 7935 OSKext::pingIOKitDaemon(); 7936 7937 result = kOSReturnSuccess; 7938 7939 finish: 7940 return result; 7941 } 7942 7943 7944 #if CONFIG_KXLD 7945 /********************************************************************* 7946 *********************************************************************/ 7947 static void 7948 _OSKextConsiderDestroyingLinkContext( 7949 __unused thread_call_param_t p0, 7950 __unused thread_call_param_t p1) 7951 { 7952 /* Take multiple locks in the correct order. 7953 */ 7954 IORecursiveLockLock(sKextLock); 7955 IORecursiveLockLock(sKextInnerLock); 7956 7957 /* The first time we destroy the kxldContext is in the first 7958 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled 7959 * before calling this function. Thereafter any call to this function 7960 * will actually destroy the context. 7961 */ 7962 if (sConsiderUnloadsCalled && sKxldContext) { 7963 kxld_destroy_context(sKxldContext); 7964 sKxldContext = NULL; 7965 } 7966 7967 /* Free the thread_call that was allocated to execute this function. 7968 */ 7969 if (sDestroyLinkContextThread) { 7970 if (!thread_call_free(sDestroyLinkContextThread)) { 7971 OSKextLog(/* kext */ NULL, 7972 kOSKextLogErrorLevel | 7973 kOSKextLogGeneralFlag, 7974 "thread_call_free() failed for kext link context."); 7975 } 7976 sDestroyLinkContextThread = NULL; 7977 } 7978 7979 IORecursiveLockUnlock(sKextInnerLock); 7980 IORecursiveLockUnlock(sKextLock); 7981 7982 return; 7983 } 7984 7985 /********************************************************************* 7986 * Destroying the kxldContext requires checking variables under both 7987 * sKextInnerLock and sKextLock, so we do it on a separate thread 7988 * to avoid deadlocks with IOService, with which OSKext has a reciprocal 7989 * call relationship. 7990 * 7991 * This function must be invoked with sKextInnerLock held. 7992 * Do not call any function that takes sKextLock here! 7993 *********************************************************************/ 7994 /* static */ 7995 void 7996 OSKext::considerDestroyingLinkContext(void) 7997 { 7998 IORecursiveLockLock(sKextInnerLock); 7999 8000 /* If we have already queued a thread to destroy the link context, 8001 * don't bother resetting; that thread will take care of it. 8002 */ 8003 if (sDestroyLinkContextThread) { 8004 goto finish; 8005 } 8006 8007 /* The function to be invoked in the thread will deallocate 8008 * this thread_call, so don't share it around. 8009 */ 8010 sDestroyLinkContextThread = thread_call_allocate( 8011 &_OSKextConsiderDestroyingLinkContext, NULL); 8012 if (!sDestroyLinkContextThread) { 8013 OSKextLog(/* kext */ NULL, 8014 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag, 8015 "Can't create thread to destroy kext link context."); 8016 goto finish; 8017 } 8018 8019 thread_call_enter(sDestroyLinkContextThread); 8020 8021 finish: 8022 IORecursiveLockUnlock(sKextInnerLock); 8023 return; 8024 } 8025 8026 #else // !CONFIG_KXLD 8027 8028 /* static */ 8029 void 8030 OSKext::considerDestroyingLinkContext(void) 8031 { 8032 return; 8033 } 8034 8035 #endif // CONFIG_KXLD 8036 8037 #if PRAGMA_MARK 8038 #pragma mark Autounload 8039 #endif 8040 /********************************************************************* 8041 * This is a static method because the kext will be deallocated if it 8042 * does unload! 8043 *********************************************************************/ 8044 /* static */ 8045 OSReturn 8046 OSKext::autounloadKext(OSKext * aKext) 8047 { 8048 OSReturn result = kOSKextReturnInUse; 8049 8050 #if NO_KEXTD 8051 /* 8052 * Do not unload prelinked kexts on platforms that do not have an 8053 * IOKit daemon as there is no way to reload the kext or restart 8054 * matching. 8055 */ 8056 if (aKext->isPrelinked()) { 8057 goto finish; 8058 } 8059 #endif /* defined(__x86_64__) */ 8060 8061 /* Check for external references to this kext (usu. dependents), 8062 * instances of defined classes (or classes derived from them), 8063 * outstanding requests. 8064 */ 8065 if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) || 8066 !aKext->flags.autounloadEnabled || 8067 aKext->isKernelComponent()) { 8068 goto finish; 8069 } 8070 8071 /* Skip a delay-autounload kext, once. 8072 */ 8073 if (aKext->flags.delayAutounload) { 8074 OSKextLog(aKext, 8075 kOSKextLogProgressLevel | 8076 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag, 8077 "Kext %s has delayed autounload set; skipping and clearing flag.", 8078 aKext->getIdentifierCString()); 8079 aKext->flags.delayAutounload = 0; 8080 goto finish; 8081 } 8082 8083 if (aKext->hasOSMetaClassInstances() || 8084 aKext->countRequestCallbacks()) { 8085 goto finish; 8086 } 8087 8088 result = OSKext::removeKext(aKext); 8089 8090 finish: 8091 return result; 8092 } 8093 8094 /********************************************************************* 8095 *********************************************************************/ 8096 void 8097 _OSKextConsiderUnloads( 8098 __unused thread_call_param_t p0, 8099 __unused thread_call_param_t p1) 8100 { 8101 bool didUnload = false; 8102 unsigned int count, i; 8103 8104 /* Take multiple locks in the correct order 8105 * (note also sKextSummaries lock further down). 8106 */ 8107 IORecursiveLockLock(sKextLock); 8108 IORecursiveLockLock(sKextInnerLock); 8109 8110 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true); 8111 8112 /* If the system is powering down, don't try to unload anything. 8113 */ 8114 if (sSystemSleep) { 8115 goto finish; 8116 } 8117 8118 OSKextLog(/* kext */ NULL, 8119 kOSKextLogProgressLevel | kOSKextLogLoadFlag, 8120 "Checking for unused kexts to autounload."); 8121 8122 /***** 8123 * Remove any request callbacks marked as stale, 8124 * and mark as stale any currently in flight. 8125 */ 8126 count = sRequestCallbackRecords->getCount(); 8127 if (count) { 8128 i = count - 1; 8129 do { 8130 OSDictionary * callbackRecord = OSDynamicCast(OSDictionary, 8131 sRequestCallbackRecords->getObject(i)); 8132 OSBoolean * stale = OSDynamicCast(OSBoolean, 8133 callbackRecord->getObject(kKextRequestStaleKey)); 8134 8135 if (stale == kOSBooleanTrue) { 8136 OSKext::invokeRequestCallback(callbackRecord, 8137 kOSKextReturnTimeout); 8138 } else { 8139 callbackRecord->setObject(kKextRequestStaleKey, 8140 kOSBooleanTrue); 8141 } 8142 } while (i--); 8143 } 8144 8145 /***** 8146 * Make multiple passes through the array of loaded kexts until 8147 * we don't unload any. This handles unwinding of dependency 8148 * chains. We have to go *backwards* through the array because 8149 * kexts are removed from it when unloaded, and we cannot make 8150 * a copy or we'll mess up the retain counts we rely on to 8151 * check whether a kext will unload. If only we could have 8152 * nonretaining collections like CF has.... 8153 */ 8154 do { 8155 didUnload = false; 8156 8157 count = sLoadedKexts->getCount(); 8158 if (count) { 8159 i = count - 1; 8160 do { 8161 OSKext * thisKext = OSDynamicCast(OSKext, 8162 sLoadedKexts->getObject(i)); 8163 didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext)); 8164 } while (i--); 8165 } 8166 } while (didUnload); 8167 8168 finish: 8169 sConsiderUnloadsPending = false; 8170 sConsiderUnloadsExecuted = true; 8171 8172 (void) OSKext::considerRebuildOfPrelinkedKernel(); 8173 8174 IORecursiveLockUnlock(sKextInnerLock); 8175 IORecursiveLockUnlock(sKextLock); 8176 8177 return; 8178 } 8179 8180 /********************************************************************* 8181 * Do not call any function that takes sKextLock here! 8182 *********************************************************************/ 8183 void 8184 OSKext::considerUnloads(Boolean rescheduleOnlyFlag) 8185 { 8186 AbsoluteTime when; 8187 8188 IORecursiveLockLock(sKextInnerLock); 8189 8190 if (!sUnloadCallout) { 8191 sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL); 8192 } 8193 8194 /* we only reset delay value for unloading if we already have something 8195 * pending. rescheduleOnlyFlag should not start the count down. 8196 */ 8197 if (rescheduleOnlyFlag && !sConsiderUnloadsPending) { 8198 goto finish; 8199 } 8200 8201 thread_call_cancel(sUnloadCallout); 8202 if (OSKext::getAutounloadEnabled() && !sSystemSleep 8203 #if !NO_KEXTD 8204 && sIOKitDaemonActive 8205 #endif 8206 ) { 8207 clock_interval_to_deadline(sConsiderUnloadDelay, 8208 1000 * 1000 * 1000, &when); 8209 8210 OSKextLog(/* kext */ NULL, 8211 kOSKextLogProgressLevel | 8212 kOSKextLogLoadFlag, 8213 "%scheduling %sscan for unused kexts in %lu seconds.", 8214 sConsiderUnloadsPending ? "Res" : "S", 8215 sConsiderUnloadsCalled ? "" : "initial ", 8216 (unsigned long)sConsiderUnloadDelay); 8217 8218 sConsiderUnloadsPending = true; 8219 thread_call_enter_delayed(sUnloadCallout, when); 8220 } 8221 8222 finish: 8223 /* The kxld context should be reused throughout boot. We mark the end of 8224 * period as the first time considerUnloads() is called, and we destroy 8225 * the first kxld context in that function. Afterwards, it will be 8226 * destroyed in flushNonloadedKexts. 8227 */ 8228 if (!sConsiderUnloadsCalled) { 8229 sConsiderUnloadsCalled = true; 8230 OSKext::considerDestroyingLinkContext(); 8231 } 8232 8233 IORecursiveLockUnlock(sKextInnerLock); 8234 return; 8235 } 8236 8237 /********************************************************************* 8238 * Do not call any function that takes sKextLock here! 8239 *********************************************************************/ 8240 extern "C" { 8241 IOReturn OSKextSystemSleepOrWake(UInt32 messageType); 8242 IOReturn 8243 OSKextSystemSleepOrWake(UInt32 messageType) 8244 { 8245 IORecursiveLockLock(sKextInnerLock); 8246 8247 /* If the system is going to sleep, cancel the reaper thread timer, 8248 * and note that we're in a sleep state in case it just fired but hasn't 8249 * taken the lock yet. If we are coming back from sleep, just 8250 * clear the sleep flag; IOService's normal operation will cause 8251 * unloads to be considered soon enough. 8252 */ 8253 if (messageType == kIOMessageSystemWillSleep) { 8254 if (sUnloadCallout) { 8255 thread_call_cancel(sUnloadCallout); 8256 } 8257 sSystemSleep = true; 8258 AbsoluteTime_to_scalar(&sLastWakeTime) = 0; 8259 } else if (messageType == kIOMessageSystemHasPoweredOn) { 8260 sSystemSleep = false; 8261 clock_get_uptime(&sLastWakeTime); 8262 } 8263 IORecursiveLockUnlock(sKextInnerLock); 8264 8265 return kIOReturnSuccess; 8266 } 8267 }; 8268 8269 8270 #if PRAGMA_MARK 8271 #pragma mark Prelinked Kernel 8272 #endif 8273 8274 #ifdef CONFIG_KXLD 8275 /********************************************************************* 8276 * Do not access sConsiderUnloads... variables other than 8277 * sConsiderUnloadsExecuted in this function. They are guarded by a 8278 * different lock. 8279 *********************************************************************/ 8280 /* static */ 8281 void 8282 OSKext::considerRebuildOfPrelinkedKernel(void) 8283 { 8284 static bool requestedPrelink = false; 8285 OSReturn checkResult = kOSReturnError; 8286 OSSharedPtr<OSDictionary> prelinkRequest; 8287 OSSharedPtr<OSCollectionIterator> kextIterator; 8288 const OSSymbol * thisID = NULL; // do not release 8289 bool doRebuild = false; 8290 AbsoluteTime my_abstime; 8291 UInt64 my_ns; 8292 SInt32 delta_secs; 8293 8294 /* Only one auto rebuild per boot and only on boot from prelinked kernel */ 8295 if (requestedPrelink || !sPrelinkBoot) { 8296 return; 8297 } 8298 8299 /* no direct return from this point */ 8300 IORecursiveLockLock(sKextLock); 8301 8302 /* We need to wait for the IOKit daemon to get up and running with unloads already done 8303 * and any new startup kexts loaded. 8304 */ 8305 if (!sConsiderUnloadsExecuted || 8306 !sDeferredLoadSucceeded) { 8307 goto finish; 8308 } 8309 8310 /* we really only care about boot / system start up related kexts so bail 8311 * if we're here after REBUILD_MAX_TIME. 8312 */ 8313 if (!_OSKextInPrelinkRebuildWindow()) { 8314 OSKextLog(/* kext */ NULL, 8315 kOSKextLogArchiveFlag, 8316 "%s prebuild rebuild has expired", 8317 __FUNCTION__); 8318 requestedPrelink = true; 8319 goto finish; 8320 } 8321 8322 /* we do not want to trigger a rebuild if we get here too close to waking 8323 * up. (see radar 10233768) 8324 */ 8325 IORecursiveLockLock(sKextInnerLock); 8326 8327 clock_get_uptime(&my_abstime); 8328 delta_secs = MINIMUM_WAKEUP_SECONDS + 1; 8329 if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) { 8330 SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime); 8331 absolutetime_to_nanoseconds(my_abstime, &my_ns); 8332 delta_secs = (SInt32)(my_ns / NSEC_PER_SEC); 8333 } 8334 IORecursiveLockUnlock(sKextInnerLock); 8335 8336 if (delta_secs < MINIMUM_WAKEUP_SECONDS) { 8337 /* too close to time of last wake from sleep */ 8338 goto finish; 8339 } 8340 requestedPrelink = true; 8341 8342 /* Now it's time to see if we have a reason to rebuild. We may have done 8343 * some loads and unloads but the kernel cache didn't actually change. 8344 * We will rebuild if any kext is not marked prelinked AND is not in our 8345 * list of prelinked kexts that got unloaded. (see radar 9055303) 8346 */ 8347 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 8348 if (!kextIterator) { 8349 goto finish; 8350 } 8351 8352 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) { 8353 OSKext * thisKext; // do not release 8354 8355 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID)); 8356 if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) { 8357 continue; 8358 } 8359 8360 if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) { 8361 continue; 8362 } 8363 /* kext is loaded and was not in current kernel cache so let's rebuild 8364 */ 8365 doRebuild = true; 8366 OSKextLog(/* kext */ NULL, 8367 kOSKextLogArchiveFlag, 8368 "considerRebuildOfPrelinkedKernel %s triggered rebuild", 8369 thisKext->bundleID->getCStringNoCopy()); 8370 break; 8371 } 8372 sUnloadedPrelinkedKexts->flushCollection(); 8373 8374 if (!doRebuild) { 8375 goto finish; 8376 } 8377 8378 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink, 8379 prelinkRequest); 8380 if (checkResult != kOSReturnSuccess) { 8381 goto finish; 8382 } 8383 8384 if (!sKernelRequests->setObject(prelinkRequest.get())) { 8385 goto finish; 8386 } 8387 8388 OSKext::pingIOKitDaemon(); 8389 8390 finish: 8391 IORecursiveLockUnlock(sKextLock); 8392 8393 return; 8394 } 8395 8396 #else /* !CONFIG_KXLD */ 8397 8398 void 8399 OSKext::considerRebuildOfPrelinkedKernel(void) 8400 { 8401 /* in a non-dynamic kext loading world, there is never a reason to rebuild */ 8402 return; 8403 } 8404 8405 #endif /* CONFIG_KXLD */ 8406 8407 #if PRAGMA_MARK 8408 #pragma mark Dependencies 8409 #endif 8410 /********************************************************************* 8411 *********************************************************************/ 8412 bool 8413 OSKext::resolveDependencies( 8414 OSArray * loopStack) 8415 { 8416 bool result = false; 8417 OSSharedPtr<OSArray> localLoopStack; 8418 bool addedToLoopStack = false; 8419 OSDictionary * libraries = NULL; // do not release 8420 OSSharedPtr<OSCollectionIterator> libraryIterator; 8421 OSString * libraryID = NULL; // do not release 8422 OSKext * libraryKext = NULL; // do not release 8423 bool hasRawKernelDependency = false; 8424 bool hasKernelDependency = false; 8425 bool hasKPIDependency = false; 8426 bool hasPrivateKPIDependency = false; 8427 unsigned int count; 8428 8429 #if CONFIG_KXLD 8430 OSString * infoString = NULL; // do not release 8431 OSString * readableString = NULL; // do not release 8432 #endif // CONFIG_KXLD 8433 8434 /* A kernel component will automatically have this flag set, 8435 * and a loaded kext should also have it set (as should all its 8436 * loaded dependencies). 8437 */ 8438 if (flags.hasAllDependencies) { 8439 result = true; 8440 goto finish; 8441 } 8442 8443 /* Check for loops in the dependency graph. 8444 */ 8445 if (loopStack) { 8446 if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) { 8447 OSKextLog(this, 8448 kOSKextLogErrorLevel | 8449 kOSKextLogDependenciesFlag, 8450 "Kext %s has a dependency loop; can't resolve dependencies.", 8451 getIdentifierCString()); 8452 goto finish; 8453 } 8454 } else { 8455 OSKextLog(this, 8456 kOSKextLogStepLevel | 8457 kOSKextLogDependenciesFlag, 8458 "Kext %s resolving dependencies.", 8459 getIdentifierCString()); 8460 8461 localLoopStack = OSArray::withCapacity(6); // any small capacity will do 8462 if (!localLoopStack) { 8463 OSKextLog(this, 8464 kOSKextLogErrorLevel | 8465 kOSKextLogDependenciesFlag, 8466 "Kext %s can't create bookkeeping stack to resolve dependencies.", 8467 getIdentifierCString()); 8468 goto finish; 8469 } 8470 loopStack = localLoopStack.get(); 8471 } 8472 if (!loopStack->setObject(this)) { 8473 OSKextLog(this, 8474 kOSKextLogErrorLevel | 8475 kOSKextLogDependenciesFlag, 8476 "Kext %s - internal error resolving dependencies.", 8477 getIdentifierCString()); 8478 goto finish; 8479 } 8480 addedToLoopStack = true; 8481 8482 /* Purge any existing kexts in the dependency list and start over. 8483 */ 8484 flushDependencies(); 8485 if (dependencies) { 8486 OSKextLog(this, 8487 kOSKextLogErrorLevel | 8488 kOSKextLogDependenciesFlag, 8489 "Kext %s - internal error resolving dependencies.", 8490 getIdentifierCString()); 8491 } 8492 8493 libraries = OSDynamicCast(OSDictionary, 8494 getPropertyForHostArch(kOSBundleLibrariesKey)); 8495 if (libraries == NULL || libraries->getCount() == 0) { 8496 OSKextLog(this, 8497 kOSKextLogErrorLevel | 8498 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 8499 "Kext %s - can't resolve dependencies; %s missing/invalid type.", 8500 getIdentifierCString(), kOSBundleLibrariesKey); 8501 goto finish; 8502 } 8503 8504 /* Make a new array to hold the dependencies (flush freed the old one). 8505 */ 8506 dependencies = OSArray::withCapacity(libraries->getCount()); 8507 if (!dependencies) { 8508 OSKextLog(this, 8509 kOSKextLogErrorLevel | 8510 kOSKextLogDependenciesFlag, 8511 "Kext %s - can't allocate dependencies array.", 8512 getIdentifierCString()); 8513 goto finish; 8514 } 8515 8516 // xxx - compat: We used to add an implicit dependency on kernel 6.0 8517 // xxx - compat: if none were declared. 8518 8519 libraryIterator = OSCollectionIterator::withCollection(libraries); 8520 if (!libraryIterator) { 8521 OSKextLog(this, 8522 kOSKextLogErrorLevel | 8523 kOSKextLogDependenciesFlag, 8524 "Kext %s - can't allocate dependencies iterator.", 8525 getIdentifierCString()); 8526 goto finish; 8527 } 8528 8529 while ((libraryID = OSDynamicCast(OSString, 8530 libraryIterator->getNextObject()))) { 8531 const char * library_id = libraryID->getCStringNoCopy(); 8532 8533 OSString * libraryVersion = OSDynamicCast(OSString, 8534 libraries->getObject(libraryID)); 8535 if (libraryVersion == NULL) { 8536 OSKextLog(this, 8537 kOSKextLogErrorLevel | 8538 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 8539 "Kext %s - illegal type in OSBundleLibraries.", 8540 getIdentifierCString()); 8541 goto finish; 8542 } 8543 8544 OSKextVersion libraryVers = 8545 OSKextParseVersionString(libraryVersion->getCStringNoCopy()); 8546 if (libraryVers == -1) { 8547 OSKextLog(this, 8548 kOSKextLogErrorLevel | 8549 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 8550 "Kext %s - invalid library version %s.", 8551 getIdentifierCString(), 8552 libraryVersion->getCStringNoCopy()); 8553 goto finish; 8554 } 8555 8556 libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID)); 8557 if (libraryKext == NULL) { 8558 OSKextLog(this, 8559 kOSKextLogErrorLevel | 8560 kOSKextLogDependenciesFlag, 8561 "Kext %s - library kext %s not found.", 8562 getIdentifierCString(), library_id); 8563 goto finish; 8564 } 8565 8566 if (!libraryKext->isCompatibleWithVersion(libraryVers)) { 8567 OSKextLog(this, 8568 kOSKextLogErrorLevel | 8569 kOSKextLogDependenciesFlag, 8570 "Kext %s - library kext %s not compatible " 8571 "with requested version %s.", 8572 getIdentifierCString(), library_id, 8573 libraryVersion->getCStringNoCopy()); 8574 goto finish; 8575 } 8576 8577 /* If a nonprelinked library somehow got into the mix for a 8578 * prelinked kext, at any point in the chain, we must fail 8579 * because the prelinked relocs for the library will be all wrong. 8580 */ 8581 if (this->isPrelinked() && 8582 libraryKext->declaresExecutable() && 8583 !libraryKext->isPrelinked()) { 8584 OSKextLog(this, 8585 kOSKextLogErrorLevel | 8586 kOSKextLogDependenciesFlag, 8587 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.", 8588 getIdentifierCString(), library_id, 8589 libraryVersion->getCStringNoCopy()); 8590 goto finish; 8591 } 8592 8593 if (!libraryKext->resolveDependencies(loopStack)) { 8594 goto finish; 8595 } 8596 8597 /* Add the library directly only if it has an executable to link. 8598 * Otherwise it's just used to collect other dependencies, so put 8599 * *its* dependencies on the list for this kext. 8600 */ 8601 // xxx - We are losing info here; would like to make fake entries or 8602 // xxx - keep these in the dependency graph for loaded kexts. 8603 // xxx - I really want to make kernel components not a special case! 8604 if (libraryKext->declaresExecutable() || 8605 libraryKext->isInterface()) { 8606 if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) { 8607 dependencies->setObject(libraryKext); 8608 8609 OSKextLog(this, 8610 kOSKextLogDetailLevel | 8611 kOSKextLogDependenciesFlag, 8612 "Kext %s added dependency %s.", 8613 getIdentifierCString(), 8614 libraryKext->getIdentifierCString()); 8615 } 8616 } else { 8617 int numLibDependencies = libraryKext->getNumDependencies(); 8618 OSArray * libraryDependencies = libraryKext->getDependencies(); 8619 int index; 8620 8621 if (numLibDependencies) { 8622 // xxx - this msg level should be 1 lower than the per-kext one 8623 OSKextLog(this, 8624 kOSKextLogDetailLevel | 8625 kOSKextLogDependenciesFlag, 8626 "Kext %s pulling %d dependencies from codeless library %s.", 8627 getIdentifierCString(), 8628 numLibDependencies, 8629 libraryKext->getIdentifierCString()); 8630 } 8631 for (index = 0; index < numLibDependencies; index++) { 8632 OSKext * thisLibDependency = OSDynamicCast(OSKext, 8633 libraryDependencies->getObject(index)); 8634 if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) { 8635 dependencies->setObject(thisLibDependency); 8636 OSKextLog(this, 8637 kOSKextLogDetailLevel | 8638 kOSKextLogDependenciesFlag, 8639 "Kext %s added dependency %s from codeless library %s.", 8640 getIdentifierCString(), 8641 thisLibDependency->getIdentifierCString(), 8642 libraryKext->getIdentifierCString()); 8643 } 8644 } 8645 } 8646 8647 if ((strlen(library_id) == strlen(KERNEL_LIB)) && 8648 0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) { 8649 hasRawKernelDependency = true; 8650 } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) { 8651 hasKernelDependency = true; 8652 } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) { 8653 hasKPIDependency = true; 8654 if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) { 8655 hasPrivateKPIDependency = true; 8656 } 8657 } 8658 } 8659 8660 if (hasRawKernelDependency) { 8661 OSKextLog(this, 8662 kOSKextLogErrorLevel | 8663 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 8664 "Error - kext %s declares a dependency on %s, which is not permitted.", 8665 getIdentifierCString(), KERNEL_LIB); 8666 goto finish; 8667 } 8668 #if __LP64__ 8669 if (hasKernelDependency) { 8670 OSKextLog(this, 8671 kOSKextLogErrorLevel | 8672 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag, 8673 "Error - kext %s declares %s dependencies. " 8674 "Only %s* dependencies are supported for 64-bit kexts.", 8675 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 8676 goto finish; 8677 } 8678 if (!hasKPIDependency) { 8679 OSKextLog(this, 8680 kOSKextLogWarningLevel | 8681 kOSKextLogDependenciesFlag, 8682 "Warning - kext %s declares no %s* dependencies. " 8683 "If it uses any KPIs, the link may fail with undefined symbols.", 8684 getIdentifierCString(), KPI_LIB_PREFIX); 8685 } 8686 #else /* __LP64__ */ 8687 // xxx - will change to flatly disallow "kernel" dependencies at some point 8688 // xxx - is it invalid to do both "com.apple.kernel" and any 8689 // xxx - "com.apple.kernel.*"? 8690 8691 if (hasKernelDependency && hasKPIDependency) { 8692 OSKextLog(this, 8693 kOSKextLogWarningLevel | 8694 kOSKextLogDependenciesFlag, 8695 "Warning - kext %s has immediate dependencies on both " 8696 "%s* and %s* components; use only one style.", 8697 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX); 8698 } 8699 8700 if (!hasKernelDependency && !hasKPIDependency) { 8701 // xxx - do we want to use validation flag for these too? 8702 OSKextLog(this, 8703 kOSKextLogWarningLevel | 8704 kOSKextLogDependenciesFlag, 8705 "Warning - %s declares no kernel dependencies; using %s.", 8706 getIdentifierCString(), KERNEL6_LIB); 8707 OSKext * kernelKext = OSDynamicCast(OSKext, 8708 sKextsByID->getObject(KERNEL6_LIB)); 8709 if (kernelKext) { 8710 dependencies->setObject(kernelKext); 8711 } else { 8712 OSKextLog(this, 8713 kOSKextLogErrorLevel | 8714 kOSKextLogDependenciesFlag, 8715 "Error - Library %s not found for %s.", 8716 KERNEL6_LIB, getIdentifierCString()); 8717 } 8718 } 8719 8720 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of 8721 * its indirect dependencies to simulate old-style linking. XXX - Should 8722 * check for duplicates. 8723 */ 8724 if (!hasKPIDependency) { 8725 unsigned int i; 8726 8727 flags.hasBleedthrough = true; 8728 8729 count = getNumDependencies(); 8730 8731 /* We add to the dependencies array in this loop, but do not iterate 8732 * past its original count. 8733 */ 8734 for (i = 0; i < count; i++) { 8735 OSKext * dependencyKext = OSDynamicCast(OSKext, 8736 dependencies->getObject(i)); 8737 dependencyKext->addBleedthroughDependencies(dependencies.get()); 8738 } 8739 } 8740 #endif /* __LP64__ */ 8741 8742 #if CONFIG_KXLD 8743 /* 8744 * If we're not dynamically linking kexts, then we don't need to check 8745 * copyright strings. The linker in user space has already done this. 8746 */ 8747 if (hasPrivateKPIDependency) { 8748 bool hasApplePrefix = false; 8749 bool infoCopyrightIsValid = false; 8750 bool readableCopyrightIsValid = false; 8751 8752 hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(), 8753 APPLE_KEXT_PREFIX); 8754 8755 infoString = OSDynamicCast(OSString, 8756 getPropertyForHostArch("CFBundleGetInfoString")); 8757 if (infoString) { 8758 infoCopyrightIsValid = 8759 kxld_validate_copyright_string(infoString->getCStringNoCopy()); 8760 } 8761 8762 readableString = OSDynamicCast(OSString, 8763 getPropertyForHostArch("NSHumanReadableCopyright")); 8764 if (readableString) { 8765 readableCopyrightIsValid = 8766 kxld_validate_copyright_string(readableString->getCStringNoCopy()); 8767 } 8768 8769 if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) { 8770 OSKextLog(this, 8771 kOSKextLogErrorLevel | 8772 kOSKextLogDependenciesFlag, 8773 "Error - kext %s declares a dependency on %s. " 8774 "Only Apple kexts may declare a dependency on %s.", 8775 getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI); 8776 goto finish; 8777 } 8778 } 8779 #endif // CONFIG_KXLD 8780 8781 result = true; 8782 flags.hasAllDependencies = 1; 8783 8784 finish: 8785 8786 if (addedToLoopStack) { 8787 count = loopStack->getCount(); 8788 if (count > 0 && (this == loopStack->getObject(count - 1))) { 8789 loopStack->removeObject(count - 1); 8790 } else { 8791 OSKextLog(this, 8792 kOSKextLogErrorLevel | 8793 kOSKextLogDependenciesFlag, 8794 "Kext %s - internal error resolving dependencies.", 8795 getIdentifierCString()); 8796 } 8797 } 8798 8799 if (result && localLoopStack) { 8800 OSKextLog(this, 8801 kOSKextLogStepLevel | 8802 kOSKextLogDependenciesFlag, 8803 "Kext %s successfully resolved dependencies.", 8804 getIdentifierCString()); 8805 } 8806 8807 return result; 8808 } 8809 8810 /********************************************************************* 8811 *********************************************************************/ 8812 bool 8813 OSKext::addBleedthroughDependencies(OSArray * anArray) 8814 { 8815 bool result = false; 8816 unsigned int dependencyIndex, dependencyCount; 8817 8818 dependencyCount = getNumDependencies(); 8819 8820 for (dependencyIndex = 0; 8821 dependencyIndex < dependencyCount; 8822 dependencyIndex++) { 8823 OSKext * dependency = OSDynamicCast(OSKext, 8824 dependencies->getObject(dependencyIndex)); 8825 if (!dependency) { 8826 OSKextLog(this, 8827 kOSKextLogErrorLevel | 8828 kOSKextLogDependenciesFlag, 8829 "Kext %s - internal error propagating compatibility dependencies.", 8830 getIdentifierCString()); 8831 goto finish; 8832 } 8833 if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) { 8834 anArray->setObject(dependency); 8835 } 8836 dependency->addBleedthroughDependencies(anArray); 8837 } 8838 8839 result = true; 8840 8841 finish: 8842 return result; 8843 } 8844 8845 /********************************************************************* 8846 *********************************************************************/ 8847 bool 8848 OSKext::flushDependencies(bool forceFlag) 8849 { 8850 bool result = false; 8851 8852 /* Only clear the dependencies if the kext isn't loaded; 8853 * we need the info for loaded kexts to track references. 8854 */ 8855 if (!isLoaded() || forceFlag) { 8856 if (dependencies) { 8857 // xxx - check level 8858 OSKextLog(this, 8859 kOSKextLogProgressLevel | 8860 kOSKextLogDependenciesFlag, 8861 "Kext %s flushing dependencies.", 8862 getIdentifierCString()); 8863 dependencies.reset(); 8864 } 8865 if (!isKernelComponent()) { 8866 flags.hasAllDependencies = 0; 8867 } 8868 result = true; 8869 } 8870 8871 return result; 8872 } 8873 8874 /********************************************************************* 8875 *********************************************************************/ 8876 uint32_t 8877 OSKext::getNumDependencies(void) 8878 { 8879 if (!dependencies) { 8880 return 0; 8881 } 8882 return dependencies->getCount(); 8883 } 8884 8885 /********************************************************************* 8886 *********************************************************************/ 8887 OSArray * 8888 OSKext::getDependencies(void) 8889 { 8890 return dependencies.get(); 8891 } 8892 8893 bool 8894 OSKext::hasDependency(const OSSymbol * depID) 8895 { 8896 bool result __block; 8897 8898 if (depID == getIdentifier()) { 8899 return true; 8900 } 8901 if (!dependencies) { 8902 return false; 8903 } 8904 result = false; 8905 dependencies->iterateObjects(^bool (OSObject * obj) { 8906 OSKext * kext; 8907 kext = OSDynamicCast(OSKext, obj); 8908 if (!kext) { 8909 return false; 8910 } 8911 result = (depID == kext->getIdentifier()); 8912 return result; 8913 }); 8914 return result; 8915 } 8916 8917 #if PRAGMA_MARK 8918 #pragma mark OSMetaClass Support 8919 #endif 8920 /********************************************************************* 8921 *********************************************************************/ 8922 OSReturn 8923 OSKext::addClass( 8924 OSMetaClass * aClass, 8925 uint32_t numClasses) 8926 { 8927 OSReturn result = kOSMetaClassNoInsKModSet; 8928 8929 if (!metaClasses) { 8930 metaClasses = OSSet::withCapacity(numClasses); 8931 if (!metaClasses) { 8932 goto finish; 8933 } 8934 } 8935 8936 if (metaClasses->containsObject(aClass)) { 8937 OSKextLog(this, 8938 kOSKextLogWarningLevel | 8939 kOSKextLogLoadFlag, 8940 "Notice - kext %s has already registered class %s.", 8941 getIdentifierCString(), 8942 aClass->getClassName()); 8943 result = kOSReturnSuccess; 8944 goto finish; 8945 } 8946 8947 if (!metaClasses->setObject(aClass)) { 8948 goto finish; 8949 } else { 8950 OSKextLog(this, 8951 kOSKextLogDetailLevel | 8952 kOSKextLogLoadFlag, 8953 "Kext %s registered class %s.", 8954 getIdentifierCString(), 8955 aClass->getClassName()); 8956 } 8957 8958 if (!flags.autounloadEnabled) { 8959 const OSMetaClass * metaScan = NULL; // do not release 8960 8961 for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) { 8962 if (metaScan == OSTypeID(IOService)) { 8963 OSKextLog(this, 8964 kOSKextLogProgressLevel | 8965 kOSKextLogLoadFlag, 8966 "Kext %s has IOService subclass %s; enabling autounload.", 8967 getIdentifierCString(), 8968 aClass->getClassName()); 8969 8970 flags.autounloadEnabled = 1; 8971 break; 8972 } 8973 } 8974 } 8975 8976 notifyAddClassObservers(this, aClass, flags); 8977 8978 result = kOSReturnSuccess; 8979 8980 finish: 8981 if (result != kOSReturnSuccess) { 8982 OSKextLog(this, 8983 kOSKextLogErrorLevel | 8984 kOSKextLogLoadFlag, 8985 "Kext %s failed to register class %s.", 8986 getIdentifierCString(), 8987 aClass->getClassName()); 8988 } 8989 8990 return result; 8991 } 8992 8993 /********************************************************************* 8994 *********************************************************************/ 8995 OSReturn 8996 OSKext::removeClass( 8997 OSMetaClass * aClass) 8998 { 8999 OSReturn result = kOSMetaClassNoKModSet; 9000 9001 if (!metaClasses) { 9002 goto finish; 9003 } 9004 9005 if (!metaClasses->containsObject(aClass)) { 9006 OSKextLog(this, 9007 kOSKextLogWarningLevel | 9008 kOSKextLogLoadFlag, 9009 "Notice - kext %s asked to unregister unknown class %s.", 9010 getIdentifierCString(), 9011 aClass->getClassName()); 9012 result = kOSReturnSuccess; 9013 goto finish; 9014 } 9015 9016 OSKextLog(this, 9017 kOSKextLogDetailLevel | 9018 kOSKextLogLoadFlag, 9019 "Kext %s unregistering class %s.", 9020 getIdentifierCString(), 9021 aClass->getClassName()); 9022 9023 metaClasses->removeObject(aClass); 9024 9025 notifyRemoveClassObservers(this, aClass, flags); 9026 9027 result = kOSReturnSuccess; 9028 9029 finish: 9030 if (result != kOSReturnSuccess) { 9031 OSKextLog(this, 9032 kOSKextLogErrorLevel | 9033 kOSKextLogLoadFlag, 9034 "Failed to unregister kext %s class %s.", 9035 getIdentifierCString(), 9036 aClass->getClassName()); 9037 } 9038 return result; 9039 } 9040 9041 /********************************************************************* 9042 *********************************************************************/ 9043 OSSet * 9044 OSKext::getMetaClasses(void) 9045 { 9046 return metaClasses.get(); 9047 } 9048 9049 /********************************************************************* 9050 *********************************************************************/ 9051 bool 9052 OSKext::hasOSMetaClassInstances(void) 9053 { 9054 bool result = false; 9055 OSSharedPtr<OSCollectionIterator> classIterator; 9056 OSMetaClass * checkClass = NULL; // do not release 9057 9058 if (!metaClasses) { 9059 goto finish; 9060 } 9061 9062 classIterator = OSCollectionIterator::withCollection(metaClasses.get()); 9063 if (!classIterator) { 9064 // xxx - log alloc failure? 9065 goto finish; 9066 } 9067 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 9068 if (checkClass->getInstanceCount()) { 9069 result = true; 9070 goto finish; 9071 } 9072 } 9073 9074 finish: 9075 return result; 9076 } 9077 9078 /********************************************************************* 9079 *********************************************************************/ 9080 /* static */ 9081 void 9082 OSKext::reportOSMetaClassInstances( 9083 const char * kextIdentifier, 9084 OSKextLogSpec msgLogSpec) 9085 { 9086 OSSharedPtr<OSKext> theKext; 9087 9088 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 9089 if (!theKext) { 9090 goto finish; 9091 } 9092 9093 theKext->reportOSMetaClassInstances(msgLogSpec); 9094 finish: 9095 return; 9096 } 9097 9098 /********************************************************************* 9099 *********************************************************************/ 9100 void 9101 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec) 9102 { 9103 OSSharedPtr<OSCollectionIterator> classIterator; 9104 OSMetaClass * checkClass = NULL; // do not release 9105 9106 if (!metaClasses) { 9107 goto finish; 9108 } 9109 9110 classIterator = OSCollectionIterator::withCollection(metaClasses.get()); 9111 if (!classIterator) { 9112 goto finish; 9113 } 9114 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 9115 if (checkClass->getInstanceCount()) { 9116 OSKextLog(this, 9117 msgLogSpec, 9118 " Kext %s class %s has %d instance%s.", 9119 getIdentifierCString(), 9120 checkClass->getClassName(), 9121 checkClass->getInstanceCount(), 9122 checkClass->getInstanceCount() == 1 ? "" : "s"); 9123 } 9124 } 9125 9126 finish: 9127 return; 9128 } 9129 9130 #if PRAGMA_MARK 9131 #pragma mark User-Space Requests 9132 #endif 9133 9134 static kern_return_t 9135 patchDextLaunchRequests(task_t calling_task, OSArray *requests) 9136 { 9137 OSReturn result = kOSReturnSuccess; 9138 for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) { 9139 OSDictionary * request = NULL; //do not release 9140 IOUserServerCheckInToken * token = NULL; //do not release 9141 OSString * requestPredicate = NULL; //do not release 9142 OSSharedPtr<OSNumber> portNameNumber; 9143 mach_port_name_t portName = 0; 9144 request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex)); 9145 if (!request) { 9146 OSKextLog(/* kext */ NULL, 9147 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9148 "Elements of request should be of type OSDictionary"); 9149 result = kOSKextReturnInternalError; 9150 goto finish; 9151 } 9152 requestPredicate = _OSKextGetRequestPredicate(request); 9153 if (!requestPredicate) { 9154 OSKextLog(/* kext */ NULL, 9155 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9156 "Failed to get request predicate"); 9157 result = kOSKextReturnInternalError; 9158 goto finish; 9159 } 9160 // is this a dext launch? 9161 if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) { 9162 token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken)); 9163 if (!token) { 9164 OSKextLog(/* kext */ NULL, 9165 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9166 "Could not find a IOUserServerCheckInToken in daemon launch request."); 9167 result = kOSKextReturnInternalError; 9168 goto finish; 9169 } 9170 portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT); 9171 if (portName == 0 || portName == MACH_PORT_DEAD) { 9172 OSKextLog(/* kext */ NULL, 9173 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9174 "Could not create send right for object."); 9175 result = kOSKextReturnInternalError; 9176 goto finish; 9177 } 9178 // Store the mach port name as a OSNumber 9179 portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName)); 9180 if (!portNameNumber) { 9181 OSKextLog(/* kext */ NULL, 9182 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9183 "Could not create OSNumber object."); 9184 result = kOSKextReturnNoMemory; 9185 goto finish; 9186 } 9187 if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) { 9188 OSKextLog(/* kext */ NULL, 9189 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9190 "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken); 9191 result = kOSKextReturnNoMemory; 9192 goto finish; 9193 } 9194 } 9195 finish: 9196 if (result != kOSReturnSuccess) { 9197 break; 9198 } 9199 } 9200 return result; 9201 } 9202 9203 /********************************************************************* 9204 * XXX - this function is a big ugly mess 9205 *********************************************************************/ 9206 /* static */ 9207 OSReturn 9208 OSKext::handleRequest( 9209 host_priv_t hostPriv, 9210 OSKextLogSpec clientLogFilter, 9211 char * requestBuffer, 9212 uint32_t requestLength, 9213 char ** responseOut, 9214 uint32_t * responseLengthOut, 9215 char ** logInfoOut, 9216 uint32_t * logInfoLengthOut) 9217 { 9218 OSReturn result = kOSReturnError; 9219 kern_return_t kmem_result = KERN_FAILURE; 9220 9221 char * response = NULL; // returned by reference 9222 uint32_t responseLength = 0; 9223 9224 bool taskCanManageAllKCs = false; 9225 bool taskOnlyManagesBootKC = false; 9226 9227 OSSharedPtr<OSObject> parsedXML; 9228 OSDictionary * requestDict = NULL; // do not release 9229 OSSharedPtr<OSString> errorString; 9230 9231 OSSharedPtr<OSObject> responseObject; 9232 9233 OSSharedPtr<OSSerialize> serializer; 9234 9235 OSSharedPtr<OSArray> logInfoArray; 9236 9237 OSString * predicate = NULL; // do not release 9238 OSString * kextIdentifier = NULL; // do not release 9239 OSArray * kextIdentifiers = NULL; // do not release 9240 OSKext * theKext = NULL; // do not release 9241 OSBoolean * boolArg = NULL; // do not release 9242 9243 IORecursiveLockLock(sKextLock); 9244 9245 if (responseOut) { 9246 *responseOut = NULL; 9247 *responseLengthOut = 0; 9248 } 9249 if (logInfoOut) { 9250 *logInfoOut = NULL; 9251 *logInfoLengthOut = 0; 9252 } 9253 9254 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false); 9255 9256 /* XML must be nul-terminated. 9257 */ 9258 if (requestBuffer[requestLength - 1] != '\0') { 9259 OSKextLog(/* kext */ NULL, 9260 kOSKextLogErrorLevel | 9261 kOSKextLogIPCFlag, 9262 "Invalid request from user space (not nul-terminated)."); 9263 result = kOSKextReturnBadData; 9264 goto finish; 9265 } 9266 parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString); 9267 if (parsedXML) { 9268 requestDict = OSDynamicCast(OSDictionary, parsedXML.get()); 9269 } 9270 if (!requestDict) { 9271 const char * errorCString = "(unknown error)"; 9272 9273 if (errorString && errorString->getCStringNoCopy()) { 9274 errorCString = errorString->getCStringNoCopy(); 9275 } else if (parsedXML) { 9276 errorCString = "not a dictionary"; 9277 } 9278 OSKextLog(/* kext */ NULL, 9279 kOSKextLogErrorLevel | 9280 kOSKextLogIPCFlag, 9281 "Error unserializing request from user space: %s.", 9282 errorCString); 9283 result = kOSKextReturnSerialization; 9284 goto finish; 9285 } 9286 9287 predicate = _OSKextGetRequestPredicate(requestDict); 9288 if (!predicate) { 9289 OSKextLog(/* kext */ NULL, 9290 kOSKextLogErrorLevel | 9291 kOSKextLogIPCFlag, 9292 "Recieved kext request from user space with no predicate."); 9293 result = kOSKextReturnInvalidArgument; 9294 goto finish; 9295 } 9296 9297 OSKextLog(/* kext */ NULL, 9298 kOSKextLogDebugLevel | 9299 kOSKextLogIPCFlag, 9300 "Received '%s' request from user space.", 9301 predicate->getCStringNoCopy()); 9302 9303 /* 9304 * All management of file sets requires an entitlement 9305 */ 9306 result = kOSKextReturnNotPrivileged; 9307 if (predicate->isEqualTo(kKextRequestPredicateUnload) || 9308 predicate->isEqualTo(kKextRequestPredicateStart) || 9309 predicate->isEqualTo(kKextRequestPredicateStop) || 9310 predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) || 9311 predicate->isEqualTo(kKextRequestPredicateSendResource) || 9312 predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) || 9313 predicate->isEqualTo(kKextRequestPredicateLoadCodeless) || 9314 predicate->isEqualTo(kKextRequestPredicateLoadFromKC) || 9315 predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) || 9316 predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) || 9317 predicate->isEqualTo(kKextRequestPredicateDaemonReady)) { 9318 if (hostPriv == HOST_PRIV_NULL) { 9319 OSKextLog(/* kext */ NULL, 9320 kOSKextLogErrorLevel | 9321 kOSKextLogIPCFlag, 9322 "Access Failure - must be root user."); 9323 goto finish; 9324 } 9325 taskCanManageAllKCs = IOTaskHasEntitlement(current_task(), kOSKextCollectionManagementEntitlement) == TRUE; 9326 taskOnlyManagesBootKC = IOTaskHasEntitlement(current_task(), kOSKextOnlyBootKCManagementEntitlement) == TRUE; 9327 9328 if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) { 9329 OSKextLog(/* kext */ NULL, 9330 kOSKextLogErrorLevel | 9331 kOSKextLogIPCFlag, 9332 "Access Failure - client not entitled to manage file sets."); 9333 goto finish; 9334 } 9335 9336 /* 9337 * The OnlyBootKC entitlement restricts the 9338 * collection-management entitlement to only managing kexts in 9339 * the BootKC. All other predicates that alter global state or 9340 * add new KCs are disallowed. 9341 */ 9342 if (taskOnlyManagesBootKC && 9343 (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) || 9344 predicate->isEqualTo(kKextRequestPredicateSendResource) || 9345 predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) || 9346 predicate->isEqualTo(kKextRequestPredicateLoadCodeless) || 9347 predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) || 9348 predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) || 9349 predicate->isEqualTo(kKextRequestPredicateDaemonReady))) { 9350 OSKextLog(/* kext */ NULL, 9351 kOSKextLogErrorLevel | 9352 kOSKextLogIPCFlag, 9353 "Access Failure - client not entitled to manage non-primary KCs"); 9354 goto finish; 9355 } 9356 9357 /* 9358 * If we get here, then the process either has the full KC 9359 * management entitlement, or it has the BootKC-only 9360 * entitlement and the request is about the BootKC. 9361 */ 9362 } 9363 9364 /* Get common args in anticipation of use. 9365 */ 9366 kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument( 9367 requestDict, kKextRequestArgumentBundleIdentifierKey)); 9368 kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 9369 requestDict, kKextRequestArgumentBundleIdentifierKey)); 9370 if (kextIdentifier) { 9371 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)); 9372 } 9373 boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 9374 requestDict, kKextRequestArgumentValueKey)); 9375 9376 if (taskOnlyManagesBootKC && 9377 theKext && 9378 theKext->isInFileset() && 9379 theKext->kc_type != KCKindPrimary) { 9380 OSKextLog(/* kext */ NULL, 9381 kOSKextLogErrorLevel | 9382 kOSKextLogIPCFlag, 9383 "Access Failure - client not entitled to manage kext in non-primary KC"); 9384 result = kOSKextReturnNotPrivileged; 9385 goto finish; 9386 } 9387 9388 result = kOSKextReturnInvalidArgument; 9389 9390 if (predicate->isEqualTo(kKextRequestPredicateStart)) { 9391 if (!kextIdentifier) { 9392 OSKextLog(/* kext */ NULL, 9393 kOSKextLogErrorLevel | 9394 kOSKextLogIPCFlag, 9395 "Invalid arguments to kext start request."); 9396 } else if (!theKext) { 9397 OSKextLog(/* kext */ NULL, 9398 kOSKextLogErrorLevel | 9399 kOSKextLogIPCFlag, 9400 "Kext %s not found for start request.", 9401 kextIdentifier->getCStringNoCopy()); 9402 result = kOSKextReturnNotFound; 9403 } else { 9404 result = theKext->start(); 9405 } 9406 } else if (predicate->isEqualTo(kKextRequestPredicateStop)) { 9407 if (!kextIdentifier) { 9408 OSKextLog(/* kext */ NULL, 9409 kOSKextLogErrorLevel | 9410 kOSKextLogIPCFlag, 9411 "Invalid arguments to kext stop request."); 9412 } else if (!theKext) { 9413 OSKextLog(/* kext */ NULL, 9414 kOSKextLogErrorLevel | 9415 kOSKextLogIPCFlag, 9416 "Kext %s not found for stop request.", 9417 kextIdentifier->getCStringNoCopy()); 9418 result = kOSKextReturnNotFound; 9419 } else { 9420 result = theKext->stop(); 9421 } 9422 } else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) { 9423 result = OSKext::setMissingAuxKCBundles(requestDict); 9424 } else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) { 9425 if (!kextIdentifier) { 9426 OSKextLog(/* kext */ NULL, 9427 kOSKextLogErrorLevel | 9428 kOSKextLogIPCFlag, 9429 "Invalid arguments to AuxKC Bundle Available request."); 9430 } else { 9431 result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict); 9432 } 9433 } else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) { 9434 if (!kextIdentifier) { 9435 OSKextLog(/* kext */ NULL, 9436 kOSKextLogErrorLevel | 9437 kOSKextLogIPCFlag, 9438 "Invalid arguments to kext load from KC request."); 9439 } else if (!theKext) { 9440 OSKextLog(/* kext */ NULL, 9441 kOSKextLogErrorLevel | 9442 kOSKextLogIPCFlag, 9443 "Kext %s not found for load from KC request.", 9444 kextIdentifier->getCStringNoCopy()); 9445 result = kOSKextReturnNotFound; 9446 } else if (!theKext->isInFileset()) { 9447 OSKextLog(/* kext */ NULL, 9448 kOSKextLogErrorLevel | 9449 kOSKextLogIPCFlag, 9450 "Kext %s does not exist in a KC: refusing to load.", 9451 kextIdentifier->getCStringNoCopy()); 9452 result = kOSKextReturnNotLoadable; 9453 } else { 9454 result = OSKext::loadKextFromKC(theKext, requestDict); 9455 } 9456 } else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) { 9457 if (!kextIdentifier) { 9458 OSKextLog(/* kext */ NULL, 9459 kOSKextLogErrorLevel | 9460 kOSKextLogIPCFlag, 9461 "Invalid arguments to codeless kext load interface (missing identifier)."); 9462 } else { 9463 result = OSKext::loadCodelessKext(kextIdentifier, requestDict); 9464 } 9465 } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) { 9466 if (!kextIdentifier) { 9467 OSKextLog(/* kext */ NULL, 9468 kOSKextLogErrorLevel | 9469 kOSKextLogIPCFlag, 9470 "Invalid arguments to kext unload request."); 9471 } else if (!theKext) { 9472 OSKextLog(/* kext */ NULL, 9473 kOSKextLogErrorLevel | 9474 kOSKextLogIPCFlag, 9475 "Kext %s not found for unload request.", 9476 kextIdentifier->getCStringNoCopy()); 9477 result = kOSKextReturnNotFound; 9478 } else { 9479 OSBoolean * terminateFlag = OSDynamicCast(OSBoolean, 9480 _OSKextGetRequestArgument(requestDict, 9481 kKextRequestArgumentTerminateIOServicesKey)); 9482 result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue); 9483 } 9484 } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) { 9485 result = OSKext::dispatchResource(requestDict); 9486 } else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) { 9487 OSNumber *lookupNum = NULL; 9488 lookupNum = OSDynamicCast(OSNumber, 9489 _OSKextGetRequestArgument(requestDict, 9490 kKextRequestArgumentLookupAddressKey)); 9491 9492 responseObject = OSKext::copyKextUUIDForAddress(lookupNum); 9493 if (responseObject) { 9494 result = kOSReturnSuccess; 9495 } else { 9496 goto finish; 9497 } 9498 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) || 9499 predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) || 9500 predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) { 9501 OSBoolean * delayAutounloadBool = NULL; 9502 OSObject * infoKeysRaw = NULL; 9503 OSArray * infoKeys = NULL; 9504 uint32_t infoKeysCount = 0; 9505 9506 delayAutounloadBool = OSDynamicCast(OSBoolean, 9507 _OSKextGetRequestArgument(requestDict, 9508 kKextRequestArgumentDelayAutounloadKey)); 9509 9510 /* If asked to delay autounload, reset the timer if it's currently set. 9511 * (That is, don't schedule an unload if one isn't already pending. 9512 */ 9513 if (delayAutounloadBool == kOSBooleanTrue) { 9514 OSKext::considerUnloads(/* rescheduleOnly? */ true); 9515 } 9516 9517 infoKeysRaw = _OSKextGetRequestArgument(requestDict, 9518 kKextRequestArgumentInfoKeysKey); 9519 infoKeys = OSDynamicCast(OSArray, infoKeysRaw); 9520 if (infoKeysRaw && !infoKeys) { 9521 OSKextLog(/* kext */ NULL, 9522 kOSKextLogErrorLevel | 9523 kOSKextLogIPCFlag, 9524 "Invalid arguments to kext info request."); 9525 goto finish; 9526 } 9527 9528 if (infoKeys) { 9529 infoKeysCount = infoKeys->getCount(); 9530 for (uint32_t i = 0; i < infoKeysCount; i++) { 9531 if (!OSDynamicCast(OSString, infoKeys->getObject(i))) { 9532 OSKextLog(/* kext */ NULL, 9533 kOSKextLogErrorLevel | 9534 kOSKextLogIPCFlag, 9535 "Invalid arguments to kext info request."); 9536 goto finish; 9537 } 9538 } 9539 } 9540 9541 if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) { 9542 responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys); 9543 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) { 9544 responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys); 9545 } else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) { 9546 responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys); 9547 } 9548 9549 if (!responseObject) { 9550 result = kOSKextReturnInternalError; 9551 } else { 9552 OSKextLog(/* kext */ NULL, 9553 kOSKextLogDebugLevel | 9554 kOSKextLogIPCFlag, 9555 "Returning loaded kext info."); 9556 result = kOSReturnSuccess; 9557 } 9558 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 9559 /* Hand the current sKernelRequests array to the caller 9560 * (who must release it), and make a new one. 9561 */ 9562 responseObject = os::move(sKernelRequests); 9563 sKernelRequests = OSArray::withCapacity(0); 9564 sPostedKextLoadIdentifiers->flushCollection(); 9565 OSKextLog(/* kext */ NULL, 9566 kOSKextLogDebugLevel | 9567 kOSKextLogIPCFlag, 9568 "Returning kernel requests."); 9569 result = kOSReturnSuccess; 9570 } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) { 9571 /* Return the set of all requested bundle identifiers */ 9572 responseObject = sAllKextLoadIdentifiers; 9573 OSKextLog(/* kext */ NULL, 9574 kOSKextLogDebugLevel | 9575 kOSKextLogIPCFlag, 9576 "Returning load requests."); 9577 result = kOSReturnSuccess; 9578 } else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) { 9579 printf("KextLog: Loading FileSet KC(s)\n"); 9580 result = OSKext::loadFileSetKexts(requestDict); 9581 } else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) { 9582 printf("KextLog: " kIOKitDaemonName " is %s\n", sIOKitDaemonActive ? "active" : "not active"); 9583 result = (sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot) ? kOSReturnSuccess : kIOReturnNotReady; 9584 } else { 9585 OSKextLog(/* kext */ NULL, 9586 kOSKextLogDebugLevel | 9587 kOSKextLogIPCFlag, 9588 "Received '%s' invalid request from user space.", 9589 predicate->getCStringNoCopy()); 9590 goto finish; 9591 } 9592 9593 /********** 9594 * Now we have handle the request, or not. Gather up the response & logging 9595 * info to ship to user space. 9596 *********/ 9597 9598 /* Note: Nothing in OSKext is supposed to retain requestDict, 9599 * but you never know.... 9600 */ 9601 if (requestDict->getRetainCount() > 1) { 9602 OSKextLog(/* kext */ NULL, 9603 kOSKextLogWarningLevel | 9604 kOSKextLogIPCFlag, 9605 "Request from user space still retained by a kext; " 9606 "probable memory leak."); 9607 } 9608 9609 if (responseOut && responseObject) { 9610 serializer = OSSerialize::withCapacity(0); 9611 if (!serializer) { 9612 result = kOSKextReturnNoMemory; 9613 goto finish; 9614 } 9615 /* 9616 * Before serializing the kernel requests, patch the dext launch requests so 9617 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the 9618 * IOUserServerCheckInToken kernel object. 9619 */ 9620 if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) { 9621 OSArray * requests = OSDynamicCast(OSArray, responseObject.get()); 9622 task_t calling_task = current_task(); 9623 if (!requests) { 9624 OSKextLog(/* kext */ NULL, 9625 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9626 "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests); 9627 result = kOSKextReturnInternalError; 9628 goto finish; 9629 } 9630 result = patchDextLaunchRequests(calling_task, requests); 9631 if (result != kOSReturnSuccess) { 9632 OSKextLog(/* kext */ NULL, 9633 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9634 "Failed to patch dext launch requests."); 9635 goto finish; 9636 } 9637 } 9638 9639 if (!responseObject->serialize(serializer.get())) { 9640 OSKextLog(/* kext */ NULL, 9641 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 9642 "Failed to serialize response to request from user space."); 9643 result = kOSKextReturnSerialization; 9644 goto finish; 9645 } 9646 9647 response = (char *)serializer->text(); 9648 responseLength = serializer->getLength(); 9649 } 9650 9651 if (responseOut && response) { 9652 char * buffer; 9653 9654 /* This kmem_alloc sets the return value of the function. 9655 */ 9656 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, 9657 round_page(responseLength), VM_KERN_MEMORY_OSKEXT); 9658 if (kmem_result != KERN_SUCCESS) { 9659 OSKextLog(/* kext */ NULL, 9660 kOSKextLogErrorLevel | 9661 kOSKextLogIPCFlag, 9662 "Failed to copy response to request from user space."); 9663 result = kmem_result; 9664 goto finish; 9665 } else { 9666 /* 11981737 - clear uninitialized data in last page */ 9667 bzero((void *)(buffer + responseLength), 9668 (round_page(responseLength) - responseLength)); 9669 memcpy(buffer, response, responseLength); 9670 *responseOut = buffer; 9671 *responseLengthOut = responseLength; 9672 } 9673 } 9674 9675 finish: 9676 9677 /* Gather up the collected log messages for user space. Any messages 9678 * messages past this call will not make it up as log messages but 9679 * will be in the system log. Note that we ignore the return of the 9680 * serialize; it has no bearing on the operation at hand even if we 9681 * fail to get the log messages. 9682 */ 9683 logInfoArray = OSKext::clearUserSpaceLogFilter(); 9684 9685 if (logInfoArray && logInfoOut && logInfoLengthOut) { 9686 (void)OSKext::serializeLogInfo(logInfoArray.get(), 9687 logInfoOut, logInfoLengthOut); 9688 } 9689 9690 IORecursiveLockUnlock(sKextLock); 9691 9692 return result; 9693 } 9694 9695 #if PRAGMA_MARK 9696 #pragma mark Linked Kext Collection Support 9697 #endif 9698 9699 static int 9700 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount) 9701 { 9702 for (int i = 0; i < segCount; i++) { 9703 vm_offset_t segStart = segAddrs[i]; 9704 vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i]; 9705 9706 if (theAddr >= segStart && theAddr < segEnd) { 9707 return i; 9708 } 9709 } 9710 return -1; 9711 } 9712 9713 static void 9714 __slideOldKaslrOffsets(kernel_mach_header_t *mh, 9715 kernel_segment_command_t *kextTextSeg, 9716 OSData *kaslrOffsets) 9717 { 9718 static const char *plk_segNames[] = { 9719 "__TEXT", 9720 "__TEXT_EXEC", 9721 "__DATA", 9722 "__DATA_CONST", 9723 "__LINKEDIT", 9724 "__PRELINK_TEXT", 9725 "__PLK_TEXT_EXEC", 9726 "__PRELINK_DATA", 9727 "__PLK_DATA_CONST", 9728 "__PLK_LLVM_COV", 9729 "__PLK_LINKEDIT", 9730 "__PRELINK_INFO" 9731 }; 9732 static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0])); 9733 9734 unsigned long plk_segSizes[num_plk_seg]; 9735 vm_offset_t plk_segAddrs[num_plk_seg]; 9736 9737 for (size_t i = 0; i < num_plk_seg; i++) { 9738 plk_segSizes[i] = 0; 9739 plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]); 9740 } 9741 9742 uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr; 9743 9744 int slidKextAddrCount = 0; 9745 int badSlideAddr = 0; 9746 int badSlideTarget = 0; 9747 9748 struct kaslrPackedOffsets { 9749 uint32_t count; /* number of offsets */ 9750 uint32_t offsetsArray[]; /* offsets to slide */ 9751 }; 9752 const struct kaslrPackedOffsets *myOffsets = NULL; 9753 myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy(); 9754 9755 for (uint32_t j = 0; j < myOffsets->count; j++) { 9756 uint64_t slideOffset = (uint64_t)myOffsets->offsetsArray[j]; 9757 vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset); 9758 int slideAddrSegIndex = -1; 9759 int addrToSlideSegIndex = -1; 9760 9761 slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg); 9762 if (slideAddrSegIndex >= 0) { 9763 addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg); 9764 if (addrToSlideSegIndex < 0) { 9765 badSlideTarget++; 9766 continue; 9767 } 9768 } else { 9769 badSlideAddr++; 9770 continue; 9771 } 9772 9773 slidKextAddrCount++; 9774 *slideAddr = ml_static_slide(*slideAddr); 9775 } // for ... 9776 } 9777 9778 9779 9780 /******************************************************************** 9781 * addKextsFromKextCollection 9782 * 9783 * Input: MachO header of kext collection. The MachO is assumed to 9784 * have a section named 'info_seg_name,info_sect_name' that 9785 * contains a serialized XML info dictionary. This dictionary 9786 * contains a UUID, possibly a set of relocations (for older 9787 * kxld-built binaries), and an array of kext personalities. 9788 * 9789 ********************************************************************/ 9790 bool 9791 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh, 9792 OSDictionary *infoDict, const char *text_seg_name, 9793 OSData **kcUUID, kc_kind_t type) 9794 { 9795 bool result = false; 9796 9797 OSArray *kextArray = NULL; // do not release 9798 OSData *infoDictKCUUID = NULL; // do not release 9799 OSData *kaslrOffsets = NULL; // do not release 9800 9801 IORegistryEntry *registryRoot = NULL; // do not release 9802 OSSharedPtr<OSNumber> kcKextCount; 9803 9804 /* extract the KC UUID from the dictionary */ 9805 infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 9806 if (infoDictKCUUID) { 9807 if (infoDictKCUUID->getLength() != sizeof(uuid_t)) { 9808 panic("kcUUID length is %d, expected %lu", 9809 infoDictKCUUID->getLength(), sizeof(uuid_t)); 9810 } 9811 } 9812 9813 /* locate the array of kext dictionaries */ 9814 kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey)); 9815 if (!kextArray) { 9816 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 9817 "The given KC has no kext info dictionaries"); 9818 goto finish; 9819 } 9820 9821 /* 9822 * old-style KASLR offsets may be present in the info dictionary. If 9823 * we find them, use them and eventually slide them. 9824 */ 9825 kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey)); 9826 9827 /* 9828 * Before processing any kexts, locate the special kext bundle which 9829 * contains a list of kexts that we are to prevent from loading. 9830 */ 9831 createExcludeListFromPrelinkInfo(kextArray); 9832 9833 /* 9834 * Create OSKext objects for each kext we find in the array of kext 9835 * info plist dictionaries. 9836 */ 9837 for (int i = 0; i < (int)kextArray->getCount(); ++i) { 9838 OSDictionary *kextDict = NULL; 9839 kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i)); 9840 if (!kextDict) { 9841 OSKextLog(/* kext */ NULL, 9842 kOSKextLogErrorLevel | 9843 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 9844 "Kext info dictionary for kext #%d isn't a dictionary?", i); 9845 continue; 9846 } 9847 9848 /* 9849 * Create the kext for the entry, then release it, because the 9850 * kext system keeps a reference around until the kext is 9851 * explicitly removed. Any creation/registration failures are 9852 * already logged for us. 9853 */ 9854 withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type); 9855 } 9856 9857 /* 9858 * slide old-style kxld relocations 9859 * NOTE: this is still used on embedded KCs built with kcgen 9860 * TODO: Remove this once we use the new kext linker everywhere! 9861 */ 9862 if (kaslrOffsets && vm_kernel_slide > 0) { 9863 kernel_segment_command_t *text_segment = NULL; 9864 text_segment = getsegbynamefromheader(mh, text_seg_name); 9865 if (!text_segment) { 9866 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 9867 "Can't find a TEXT segment named '%s' in macho header", text_seg_name); 9868 goto finish; 9869 } 9870 9871 __slideOldKaslrOffsets(mh, text_segment, kaslrOffsets); 9872 /* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */ 9873 setAllVMAttributes(); 9874 } 9875 9876 /* Store the number of prelinked kexts in the registry so we can tell 9877 * when the system has been started from a prelinked kernel. 9878 */ 9879 registryRoot = IORegistryEntry::getRegistryRoot(); 9880 assert(registryRoot); 9881 9882 kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t)); 9883 assert(kcKextCount); 9884 if (kcKextCount) { 9885 OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey); 9886 OSNumber *num; 9887 num = OSDynamicCast(OSNumber, prop.get()); 9888 if (num) { 9889 kcKextCount->addValue(num->unsigned64BitValue()); 9890 } 9891 registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get()); 9892 } 9893 9894 OSKextLog(/* kext */ NULL, 9895 kOSKextLogProgressLevel | 9896 kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag | 9897 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 9898 "%u prelinked kexts", infoDict->getCount()); 9899 9900 9901 if (kcUUID && infoDictKCUUID) { 9902 *kcUUID = OSData::withData(infoDictKCUUID).detach(); 9903 } 9904 9905 result = true; 9906 9907 finish: 9908 return result; 9909 } 9910 9911 bool 9912 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh, 9913 OSDictionary *infoDict, const char *text_seg_name, 9914 OSSharedPtr<OSData> &kcUUID, kc_kind_t type) 9915 { 9916 OSData *result = NULL; 9917 bool success = addKextsFromKextCollection(mh, 9918 infoDict, 9919 text_seg_name, 9920 &result, 9921 type); 9922 if (success) { 9923 kcUUID.reset(result, OSNoRetain); 9924 } 9925 return success; 9926 } 9927 9928 static OSSharedPtr<OSObject> deferredAuxKCXML; 9929 bool 9930 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh, 9931 OSSharedPtr<OSObject> &parsedXML, kc_kind_t type) 9932 { 9933 if (type != KCKindAuxiliary) { 9934 return false; 9935 } 9936 9937 kernel_mach_header_t *_mh; 9938 _mh = (kernel_mach_header_t*)PE_get_kc_header(type); 9939 if (!_mh || _mh != mh) { 9940 return false; 9941 } 9942 9943 if (deferredAuxKCXML) { 9944 /* only allow this to be called once */ 9945 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 9946 "An Aux KC has already been registered for deferred processing."); 9947 return false; 9948 } 9949 9950 OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 9951 if (!infoDict) { 9952 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 9953 "The Aux KC has info dictionary"); 9954 return false; 9955 } 9956 9957 OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 9958 if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) { 9959 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 9960 "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey); 9961 return false; 9962 } 9963 9964 /* 9965 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid 9966 * sysctl can return the UUID to user space which will check this 9967 * value for errors. 9968 */ 9969 memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(), 9970 kcUUID->getLength()); 9971 uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string); 9972 auxkc_uuid_valid = TRUE; 9973 9974 deferredAuxKCXML = parsedXML; 9975 9976 return true; 9977 } 9978 9979 OSSharedPtr<OSObject> 9980 OSKext::consumeDeferredKextCollection(kc_kind_t type) 9981 { 9982 if (type != KCKindAuxiliary || !deferredAuxKCXML) { 9983 return NULL; 9984 } 9985 9986 return os::move(deferredAuxKCXML); 9987 } 9988 9989 #if PRAGMA_MARK 9990 #pragma mark Profile-Guided-Optimization Support 9991 #endif 9992 9993 // #include <InstrProfiling.h> 9994 extern "C" { 9995 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin, 9996 const char *DataEnd, 9997 const char *CountersBegin, 9998 const char *CountersEnd, 9999 const char *NamesBegin, 10000 const char *NamesEnd); 10001 int __llvm_profile_write_buffer_internal(char *Buffer, 10002 const char *DataBegin, 10003 const char *DataEnd, 10004 const char *CountersBegin, 10005 const char *CountersEnd, 10006 const char *NamesBegin, 10007 const char *NamesEnd); 10008 } 10009 10010 10011 static 10012 void 10013 OSKextPgoMetadataPut(char *pBuffer, 10014 size_t *position, 10015 size_t bufferSize, 10016 uint32_t *num_pairs, 10017 const char *key, 10018 const char *value) 10019 { 10020 size_t strlen_key = strlen(key); 10021 size_t strlen_value = strlen(value); 10022 size_t len = strlen(key) + 1 + strlen(value) + 1; 10023 char *pos = pBuffer + *position; 10024 *position += len; 10025 if (pBuffer && bufferSize && *position <= bufferSize) { 10026 memcpy(pos, key, strlen_key); pos += strlen_key; 10027 *(pos++) = '='; 10028 memcpy(pos, value, strlen_value); pos += strlen_value; 10029 *(pos++) = 0; 10030 if (num_pairs) { 10031 (*num_pairs)++; 10032 } 10033 } 10034 } 10035 10036 10037 static 10038 void 10039 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max) 10040 { 10041 *position += strlen(key) + 1 + value_max + 1; 10042 } 10043 10044 10045 static 10046 void 10047 OSKextPgoMetadataPutAll(OSKext *kext, 10048 uuid_t instance_uuid, 10049 char *pBuffer, 10050 size_t *position, 10051 size_t bufferSize, 10052 uint32_t *num_pairs) 10053 { 10054 _static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0); 10055 //log_10 2^16 ≈ 4.82 10056 const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2; 10057 const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6; 10058 10059 if (!pBuffer) { 10060 OSKextPgoMetadataPutMax(position, "INSTANCE", 36); 10061 OSKextPgoMetadataPutMax(position, "UUID", 36); 10062 OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size); 10063 } else { 10064 uuid_string_t instance_uuid_string; 10065 uuid_unparse(instance_uuid, instance_uuid_string); 10066 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10067 "INSTANCE", instance_uuid_string); 10068 10069 OSSharedPtr<OSData> uuid_data; 10070 uuid_t uuid; 10071 uuid_string_t uuid_string; 10072 uuid_data = kext->copyUUID(); 10073 if (uuid_data) { 10074 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid)); 10075 uuid_unparse(uuid, uuid_string); 10076 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10077 "UUID", uuid_string); 10078 } 10079 10080 clock_sec_t secs; 10081 clock_usec_t usecs; 10082 clock_get_calendar_microtime(&secs, &usecs); 10083 assert(usecs < 1000000); 10084 char timestamp[max_timestamp_string_size + 1]; 10085 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t)); 10086 snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs); 10087 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10088 "TIMESTAMP", timestamp); 10089 } 10090 10091 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10092 "NAME", kext->getIdentifierCString()); 10093 10094 char versionCString[kOSKextVersionMaxLength]; 10095 OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength); 10096 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs, 10097 "VERSION", versionCString); 10098 } 10099 10100 static 10101 size_t 10102 OSKextPgoMetadataSize(OSKext *kext) 10103 { 10104 size_t position = 0; 10105 uuid_t fakeuuid = {}; 10106 OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL); 10107 return position; 10108 } 10109 10110 int 10111 OSKextGrabPgoDataLocked(OSKext *kext, 10112 bool metadata, 10113 uuid_t instance_uuid, 10114 uint64_t *pSize, 10115 char *pBuffer, 10116 uint64_t bufferSize) 10117 { 10118 int err = 0; 10119 10120 kernel_section_t *sect_prf_data = NULL; 10121 kernel_section_t *sect_prf_name = NULL; 10122 kernel_section_t *sect_prf_cnts = NULL; 10123 uint64_t size; 10124 size_t metadata_size = 0; 10125 size_t offset_to_pairs = 0; 10126 10127 sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data"); 10128 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names"); 10129 if (!sect_prf_name) { 10130 // kextcache sometimes truncates the section name to 15 chars 10131 // <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache 10132 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name"); 10133 } 10134 sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 10135 10136 if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) { 10137 err = ENOTSUP; 10138 goto out; 10139 } 10140 10141 size = __llvm_profile_get_size_for_buffer_internal( 10142 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 10143 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 10144 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 10145 10146 if (metadata) { 10147 metadata_size = OSKextPgoMetadataSize(kext); 10148 size += metadata_size; 10149 size += sizeof(pgo_metadata_footer); 10150 } 10151 10152 10153 if (pSize) { 10154 *pSize = size; 10155 } 10156 10157 if (pBuffer && bufferSize) { 10158 if (bufferSize < size) { 10159 err = ERANGE; 10160 goto out; 10161 } 10162 10163 err = __llvm_profile_write_buffer_internal( 10164 pBuffer, 10165 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size, 10166 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size, 10167 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size); 10168 10169 if (err) { 10170 err = EIO; 10171 goto out; 10172 } 10173 10174 if (metadata) { 10175 offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size; 10176 if (offset_to_pairs > UINT32_MAX) { 10177 err = E2BIG; 10178 goto out; 10179 } 10180 10181 char *end_of_buffer = pBuffer + size; 10182 struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer)); 10183 char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size); 10184 10185 size_t metadata_position = 0; 10186 uint32_t num_pairs = 0; 10187 OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs); 10188 while (metadata_position < metadata_size) { 10189 metadata_buffer[metadata_position++] = 0; 10190 } 10191 10192 struct pgo_metadata_footer footer; 10193 footer.magic = htonl(0x6d657461); 10194 footer.number_of_pairs = htonl( num_pairs ); 10195 footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs ); 10196 memcpy(footerp, &footer, sizeof(footer)); 10197 } 10198 } 10199 10200 out: 10201 return err; 10202 } 10203 10204 10205 int 10206 OSKextGrabPgoData(uuid_t uuid, 10207 uint64_t *pSize, 10208 char *pBuffer, 10209 uint64_t bufferSize, 10210 int wait_for_unload, 10211 int metadata) 10212 { 10213 int err = 0; 10214 OSSharedPtr<OSKext> kext; 10215 10216 10217 IORecursiveLockLock(sKextLock); 10218 10219 kext = OSKext::lookupKextWithUUID(uuid); 10220 if (!kext) { 10221 err = ENOENT; 10222 goto out; 10223 } 10224 10225 if (wait_for_unload) { 10226 OSKextGrabPgoStruct s; 10227 10228 s.metadata = metadata; 10229 s.pSize = pSize; 10230 s.pBuffer = pBuffer; 10231 s.bufferSize = bufferSize; 10232 s.err = EINTR; 10233 10234 struct list_head *prev = &kext->pendingPgoHead; 10235 struct list_head *next = kext->pendingPgoHead.next; 10236 10237 s.list_head.prev = prev; 10238 s.list_head.next = next; 10239 10240 prev->next = &s.list_head; 10241 next->prev = &s.list_head; 10242 10243 kext.reset(); 10244 10245 IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE); 10246 10247 prev = s.list_head.prev; 10248 next = s.list_head.next; 10249 10250 prev->next = next; 10251 next->prev = prev; 10252 10253 err = s.err; 10254 } else { 10255 err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize); 10256 } 10257 10258 out: 10259 10260 IORecursiveLockUnlock(sKextLock); 10261 10262 return err; 10263 } 10264 10265 void 10266 OSKextResetPgoCountersLock() 10267 { 10268 IORecursiveLockLock(sKextLock); 10269 } 10270 10271 void 10272 OSKextResetPgoCountersUnlock() 10273 { 10274 IORecursiveLockUnlock(sKextLock); 10275 } 10276 10277 10278 extern unsigned int not_in_kdp; 10279 10280 void 10281 OSKextResetPgoCounters() 10282 { 10283 assert(!not_in_kdp); 10284 uint32_t count = sLoadedKexts->getCount(); 10285 for (uint32_t i = 0; i < count; i++) { 10286 OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 10287 kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts"); 10288 if (!sect_prf_cnts) { 10289 continue; 10290 } 10291 memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size); 10292 } 10293 } 10294 10295 OSSharedPtr<OSDictionary> 10296 OSKext::copyLoadedKextInfoByUUID( 10297 OSArray * kextIdentifiers, 10298 OSArray * infoKeys) 10299 { 10300 OSSharedPtr<OSDictionary> result; 10301 OSSharedPtr<OSDictionary> kextInfo; 10302 uint32_t max_count, i, j; 10303 uint32_t idCount = 0; 10304 uint32_t idIndex = 0; 10305 IORecursiveLockLock(sKextLock); 10306 OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()}; 10307 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()}; 10308 10309 #if CONFIG_MACF 10310 /* Is the calling process allowed to query kext info? */ 10311 if (current_task() != kernel_task) { 10312 int macCheckResult = 0; 10313 kauth_cred_t cred = NULL; 10314 10315 cred = kauth_cred_get_with_ref(); 10316 macCheckResult = mac_kext_check_query(cred); 10317 kauth_cred_unref(&cred); 10318 10319 if (macCheckResult != 0) { 10320 OSKextLog(/* kext */ NULL, 10321 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 10322 "Failed to query kext info (MAC policy error 0x%x).", 10323 macCheckResult); 10324 goto finish; 10325 } 10326 } 10327 #endif 10328 10329 /* Empty list of UUIDs is equivalent to no list (get all). 10330 */ 10331 if (kextIdentifiers && !kextIdentifiers->getCount()) { 10332 kextIdentifiers = NULL; 10333 } else if (kextIdentifiers) { 10334 idCount = kextIdentifiers->getCount(); 10335 } 10336 10337 /* Same for keys. 10338 */ 10339 if (infoKeys && !infoKeys->getCount()) { 10340 infoKeys = NULL; 10341 } 10342 10343 max_count = count[0] + count[1]; 10344 result = OSDictionary::withCapacity(max_count); 10345 if (!result) { 10346 goto finish; 10347 } 10348 10349 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) { 10350 for (i = 0; i < count[j]; i++) { 10351 OSKext *thisKext = NULL; // do not release 10352 Boolean includeThis = true; 10353 uuid_t thisKextUUID; 10354 uuid_t thisKextTextUUID; 10355 OSSharedPtr<OSData> uuid_data; 10356 uuid_string_t uuid_key; 10357 10358 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i)); 10359 if (!thisKext) { 10360 continue; 10361 } 10362 10363 uuid_data = thisKext->copyUUID(); 10364 if (!uuid_data) { 10365 continue; 10366 } 10367 10368 memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID)); 10369 10370 uuid_unparse(thisKextUUID, uuid_key); 10371 10372 uuid_data = thisKext->copyTextUUID(); 10373 if (!uuid_data) { 10374 continue; 10375 } 10376 memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID)); 10377 10378 /* Skip current kext if we have a list of UUIDs and 10379 * it isn't in the list. 10380 */ 10381 if (kextIdentifiers) { 10382 includeThis = false; 10383 10384 for (idIndex = 0; idIndex < idCount; idIndex++) { 10385 const OSString* wantedUUID = OSDynamicCast(OSString, 10386 kextIdentifiers->getObject(idIndex)); 10387 10388 uuid_t uuid; 10389 uuid_parse(wantedUUID->getCStringNoCopy(), uuid); 10390 10391 if ((0 == uuid_compare(uuid, thisKextUUID)) 10392 || (0 == uuid_compare(uuid, thisKextTextUUID))) { 10393 includeThis = true; 10394 /* Only need to find the first kext if multiple match, 10395 * ie. asking for the kernel uuid does not need to find 10396 * interface kexts or builtin static kexts. 10397 */ 10398 kextIdentifiers->removeObject(idIndex); 10399 uuid_unparse(uuid, uuid_key); 10400 break; 10401 } 10402 } 10403 } 10404 10405 if (!includeThis) { 10406 continue; 10407 } 10408 10409 kextInfo = thisKext->copyInfo(infoKeys); 10410 if (kextInfo) { 10411 result->setObject(uuid_key, kextInfo.get()); 10412 } 10413 10414 if (kextIdentifiers && !kextIdentifiers->getCount()) { 10415 goto finish; 10416 } 10417 } 10418 } 10419 10420 finish: 10421 IORecursiveLockUnlock(sKextLock); 10422 10423 return result; 10424 } 10425 10426 /********************************************************************* 10427 *********************************************************************/ 10428 /* static */ 10429 OSSharedPtr<OSDictionary> 10430 OSKext::copyKextCollectionInfo( 10431 OSDictionary *requestDict, 10432 OSArray *infoKeys) 10433 { 10434 OSSharedPtr<OSDictionary> result; 10435 OSString *collectionType = NULL; 10436 OSObject *rawLoadedState = NULL; 10437 OSString *loadedState = NULL; 10438 10439 kc_kind_t kc_request_kind = KCKindUnknown; 10440 bool onlyLoaded = false; 10441 bool onlyUnloaded = false; 10442 10443 #if CONFIG_MACF 10444 /* Is the calling process allowed to query kext info? */ 10445 if (current_task() != kernel_task) { 10446 int macCheckResult = 0; 10447 kauth_cred_t cred = NULL; 10448 10449 cred = kauth_cred_get_with_ref(); 10450 macCheckResult = mac_kext_check_query(cred); 10451 kauth_cred_unref(&cred); 10452 10453 if (macCheckResult != 0) { 10454 OSKextLog(/* kext */ NULL, 10455 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 10456 "Failed to query kext info (MAC policy error 0x%x).", 10457 macCheckResult); 10458 goto finish; 10459 } 10460 } 10461 #endif 10462 10463 if (infoKeys && !infoKeys->getCount()) { 10464 infoKeys = NULL; 10465 } 10466 10467 collectionType = OSDynamicCast(OSString, 10468 _OSKextGetRequestArgument(requestDict, 10469 kKextRequestArgumentCollectionTypeKey)); 10470 if (!collectionType) { 10471 OSKextLog(/* kext */ NULL, 10472 kOSKextLogErrorLevel | 10473 kOSKextLogIPCFlag, 10474 "Invalid '%s' argument to kext collection info request.", 10475 kKextRequestArgumentCollectionTypeKey); 10476 goto finish; 10477 } 10478 if (collectionType->isEqualTo(kKCTypePrimary)) { 10479 kc_request_kind = KCKindPrimary; 10480 } else if (collectionType->isEqualTo(kKCTypeSystem)) { 10481 kc_request_kind = KCKindPageable; 10482 } else if (collectionType->isEqualTo(kKCTypeAuxiliary)) { 10483 kc_request_kind = KCKindAuxiliary; 10484 } else if (collectionType->isEqualTo(kKCTypeCodeless)) { 10485 kc_request_kind = KCKindNone; 10486 } else if (!collectionType->isEqualTo(kKCTypeAny)) { 10487 OSKextLog(/* kext */ NULL, 10488 kOSKextLogErrorLevel | 10489 kOSKextLogIPCFlag, 10490 "Invalid '%s' argument value '%s' to kext collection info request.", 10491 kKextRequestArgumentCollectionTypeKey, 10492 collectionType->getCStringNoCopy()); 10493 goto finish; 10494 } 10495 10496 rawLoadedState = _OSKextGetRequestArgument(requestDict, 10497 kKextRequestArgumentLoadedStateKey); 10498 if (rawLoadedState) { 10499 loadedState = OSDynamicCast(OSString, rawLoadedState); 10500 if (!loadedState) { 10501 OSKextLog(/* kext */ NULL, 10502 kOSKextLogErrorLevel | 10503 kOSKextLogIPCFlag, 10504 "Invalid '%s' argument to kext collection info request.", 10505 kKextRequestArgumentLoadedStateKey); 10506 goto finish; 10507 } 10508 } 10509 if (loadedState) { 10510 if (loadedState->isEqualTo("Loaded")) { 10511 onlyLoaded = true; 10512 } else if (loadedState->isEqualTo("Unloaded")) { 10513 onlyUnloaded = true; 10514 } else if (!loadedState->isEqualTo("Any")) { 10515 OSKextLog(/* kext */ NULL, 10516 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 10517 "Invalid '%s' argument value '%s' for '%s' collection info", 10518 kKextRequestArgumentLoadedStateKey, 10519 loadedState->getCStringNoCopy(), 10520 collectionType->getCStringNoCopy()); 10521 goto finish; 10522 } 10523 } 10524 10525 result = OSDictionary::withCapacity(sKextsByID->getCount()); 10526 if (!result) { 10527 goto finish; 10528 } 10529 10530 IORecursiveLockLock(sKextLock); 10531 { // start block scope 10532 sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj) 10533 { 10534 OSKext *thisKext = NULL; // do not release 10535 OSSharedPtr<OSDictionary> kextInfo; 10536 10537 (void)thisKextID; 10538 10539 thisKext = OSDynamicCast(OSKext, obj); 10540 if (!thisKext) { 10541 return false;; 10542 } 10543 10544 /* 10545 * skip the kext if it came from the wrong collection type 10546 * (and the caller requested a specific type) 10547 */ 10548 if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) { 10549 return false; 10550 } 10551 10552 /* 10553 * respect the caller's desire to find only loaded or 10554 * unloaded kexts 10555 */ 10556 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 10557 return false; 10558 } 10559 if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 10560 return false; 10561 } 10562 10563 kextInfo = thisKext->copyInfo(infoKeys); 10564 if (kextInfo) { 10565 result->setObject(thisKext->getIdentifier(), kextInfo.get()); 10566 } 10567 return false; 10568 }); 10569 } // end block scope 10570 IORecursiveLockUnlock(sKextLock); 10571 10572 finish: 10573 return result; 10574 } 10575 10576 /********************************************************************* 10577 *********************************************************************/ 10578 /* static */ 10579 OSSharedPtr<OSDictionary> 10580 OSKext::copyLoadedKextInfo( 10581 OSArray * kextIdentifiers, 10582 OSArray * infoKeys) 10583 { 10584 OSSharedPtr<OSDictionary> result; 10585 uint32_t idCount = 0; 10586 bool onlyLoaded; 10587 10588 IORecursiveLockLock(sKextLock); 10589 10590 #if CONFIG_MACF 10591 /* Is the calling process allowed to query kext info? */ 10592 if (current_task() != kernel_task) { 10593 int macCheckResult = 0; 10594 kauth_cred_t cred = NULL; 10595 10596 cred = kauth_cred_get_with_ref(); 10597 macCheckResult = mac_kext_check_query(cred); 10598 kauth_cred_unref(&cred); 10599 10600 if (macCheckResult != 0) { 10601 OSKextLog(/* kext */ NULL, 10602 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 10603 "Failed to query kext info (MAC policy error 0x%x).", 10604 macCheckResult); 10605 goto finish; 10606 } 10607 } 10608 #endif 10609 10610 /* Empty list of bundle ids is equivalent to no list (get all). 10611 */ 10612 if (kextIdentifiers && !kextIdentifiers->getCount()) { 10613 kextIdentifiers = NULL; 10614 } else if (kextIdentifiers) { 10615 idCount = kextIdentifiers->getCount(); 10616 } 10617 10618 /* Same for keys. 10619 */ 10620 if (infoKeys && !infoKeys->getCount()) { 10621 infoKeys = NULL; 10622 } 10623 10624 onlyLoaded = (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey)); 10625 10626 result = OSDictionary::withCapacity(128); 10627 if (!result) { 10628 goto finish; 10629 } 10630 10631 #if 0 10632 OSKextLog(/* kext */ NULL, 10633 kOSKextLogErrorLevel | 10634 kOSKextLogGeneralFlag, 10635 "kaslr: vm_kernel_slide 0x%lx \n", 10636 vm_kernel_slide); 10637 OSKextLog(/* kext */ NULL, 10638 kOSKextLogErrorLevel | 10639 kOSKextLogGeneralFlag, 10640 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n", 10641 vm_kernel_stext, vm_kernel_etext); 10642 OSKextLog(/* kext */ NULL, 10643 kOSKextLogErrorLevel | 10644 kOSKextLogGeneralFlag, 10645 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n", 10646 vm_kernel_base, vm_kernel_top); 10647 OSKextLog(/* kext */ NULL, 10648 kOSKextLogErrorLevel | 10649 kOSKextLogGeneralFlag, 10650 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n", 10651 vm_kext_base, vm_kext_top); 10652 OSKextLog(/* kext */ NULL, 10653 kOSKextLogErrorLevel | 10654 kOSKextLogGeneralFlag, 10655 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n", 10656 vm_prelink_stext, vm_prelink_etext); 10657 OSKextLog(/* kext */ NULL, 10658 kOSKextLogErrorLevel | 10659 kOSKextLogGeneralFlag, 10660 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n", 10661 vm_prelink_sinfo, vm_prelink_einfo); 10662 OSKextLog(/* kext */ NULL, 10663 kOSKextLogErrorLevel | 10664 kOSKextLogGeneralFlag, 10665 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n", 10666 vm_slinkedit, vm_elinkedit); 10667 #endif 10668 { // start block scope 10669 sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj) 10670 { 10671 OSKext * thisKext = NULL; // do not release 10672 Boolean includeThis = true; 10673 OSSharedPtr<OSDictionary> kextInfo; 10674 10675 thisKext = OSDynamicCast(OSKext, obj); 10676 if (!thisKext) { 10677 return false;; 10678 } 10679 10680 /* Skip current kext if not yet started and caller didn't request all. 10681 */ 10682 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) { 10683 return false;; 10684 } 10685 10686 /* Skip current kext if we have a list of bundle IDs and 10687 * it isn't in the list. 10688 */ 10689 if (kextIdentifiers) { 10690 includeThis = false; 10691 10692 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) { 10693 const OSString * thisRequestID = OSDynamicCast(OSString, 10694 kextIdentifiers->getObject(idIndex)); 10695 if (thisKextID->isEqualTo(thisRequestID)) { 10696 includeThis = true; 10697 break; 10698 } 10699 } 10700 } 10701 10702 if (!includeThis) { 10703 return false; 10704 } 10705 10706 kextInfo = thisKext->copyInfo(infoKeys); 10707 if (kextInfo) { 10708 result->setObject(thisKext->getIdentifier(), kextInfo.get()); 10709 } 10710 return false; 10711 }); 10712 } // end block scope 10713 10714 finish: 10715 IORecursiveLockUnlock(sKextLock); 10716 10717 return result; 10718 } 10719 10720 /********************************************************************* 10721 * Any info that needs to do allocations must goto finish on alloc 10722 * failure. Info that is just a lookup should just not set the object 10723 * if the info does not exist. 10724 *********************************************************************/ 10725 #define _OSKextLoadInfoDictCapacity (12) 10726 10727 OSSharedPtr<OSDictionary> 10728 OSKext::copyInfo(OSArray * infoKeys) 10729 { 10730 OSSharedPtr<OSDictionary> result; 10731 bool success = false; 10732 OSSharedPtr<OSData> headerData; 10733 OSSharedPtr<OSData> logData; 10734 OSSharedPtr<OSNumber> cpuTypeNumber; 10735 OSSharedPtr<OSNumber> cpuSubtypeNumber; 10736 OSString * versionString = NULL; // do not release 10737 OSString * bundleType = NULL; // do not release 10738 uint32_t executablePathCStringSize = 0; 10739 char * executablePathCString = NULL; // must kfree 10740 OSSharedPtr<OSString> executablePathString; 10741 OSSharedPtr<OSData> uuid; 10742 OSSharedPtr<OSArray> dependencyLoadTags; 10743 OSSharedPtr<OSCollectionIterator> metaClassIterator; 10744 OSSharedPtr<OSArray> metaClassInfo; 10745 OSSharedPtr<OSDictionary> metaClassDict; 10746 OSMetaClass * thisMetaClass = NULL; // do not release 10747 OSSharedPtr<OSString> metaClassName; 10748 OSSharedPtr<OSString> superclassName; 10749 kc_format_t kcformat; 10750 uint32_t count, i; 10751 10752 result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity); 10753 if (!result) { 10754 goto finish; 10755 } 10756 10757 10758 /* Empty keys means no keys, but NULL is quicker to check. 10759 */ 10760 if (infoKeys && !infoKeys->getCount()) { 10761 infoKeys = NULL; 10762 } 10763 10764 if (!PE_get_primary_kc_format(&kcformat)) { 10765 goto finish; 10766 } 10767 10768 /* Headers, CPU type, and CPU subtype. 10769 */ 10770 if (!infoKeys || 10771 _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) || 10772 _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) || 10773 _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) || 10774 _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 10775 if (linkedExecutable && !isInterface()) { 10776 kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *) 10777 linkedExecutable->getBytesNoCopy(); 10778 10779 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX 10780 // do not return macho header info on shipping embedded - 19095897 10781 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) { 10782 kernel_mach_header_t * temp_kext_mach_hdr; 10783 struct load_command * lcp; 10784 10785 headerData = OSData::withBytes(kext_mach_hdr, 10786 (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds)); 10787 if (!headerData) { 10788 goto finish; 10789 } 10790 10791 // unslide any vmaddrs we return to userspace - 10726716 10792 temp_kext_mach_hdr = (kernel_mach_header_t *) 10793 headerData->getBytesNoCopy(); 10794 if (temp_kext_mach_hdr == NULL) { 10795 goto finish; 10796 } 10797 10798 lcp = (struct load_command *) (temp_kext_mach_hdr + 1); 10799 for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) { 10800 if (lcp->cmd == LC_SEGMENT_KERNEL) { 10801 kernel_segment_command_t * segp; 10802 kernel_section_t * secp; 10803 10804 segp = (kernel_segment_command_t *) lcp; 10805 // 10543468 - if we jettisoned __LINKEDIT clear size info 10806 if (flags.jettisonLinkeditSeg) { 10807 if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) { 10808 segp->vmsize = 0; 10809 segp->fileoff = 0; 10810 segp->filesize = 0; 10811 } 10812 } 10813 10814 #if __arm__ || __arm64__ 10815 // iBoot disregards zero-size segments, just set their addresses to gVirtBase 10816 // and unslide them to avoid vm assertion failures / kernel logging breakage. 10817 if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) { 10818 segp->vmaddr = gVirtBase; 10819 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { 10820 secp->size = 0; // paranoia :) 10821 secp->addr = gVirtBase; 10822 } 10823 } 10824 #endif 10825 10826 #if 0 10827 OSKextLog(/* kext */ NULL, 10828 kOSKextLogErrorLevel | 10829 kOSKextLogGeneralFlag, 10830 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u", 10831 __FUNCTION__, segp->segname, segp->vmaddr, 10832 VM_KERNEL_UNSLIDE(segp->vmaddr), 10833 segp->vmsize, segp->nsects); 10834 if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) && 10835 (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) && 10836 (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) && 10837 (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) && 10838 (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) { 10839 OSKextLog(/* kext */ NULL, 10840 kOSKextLogErrorLevel | 10841 kOSKextLogGeneralFlag, 10842 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX", 10843 __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top); 10844 } 10845 #endif 10846 segp->vmaddr = ml_static_unslide(segp->vmaddr); 10847 10848 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { 10849 secp->addr = ml_static_unslide(secp->addr); 10850 } 10851 } 10852 lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize); 10853 } 10854 result->setObject(kOSBundleMachOHeadersKey, headerData.get()); 10855 } 10856 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX 10857 10858 if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) { 10859 osLogDataHeaderRef *header; 10860 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])]; 10861 10862 void *os_log_data = NULL; 10863 void *cstring_data = NULL; 10864 unsigned long os_log_size = 0; 10865 unsigned long cstring_size = 0; 10866 uint32_t os_log_offset = 0; 10867 uint32_t cstring_offset = 0; 10868 bool res; 10869 10870 os_log_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size); 10871 os_log_offset = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr; 10872 cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size); 10873 cstring_offset = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr; 10874 10875 header = (osLogDataHeaderRef *) headerBytes; 10876 header->version = OS_LOG_HDR_VERSION; 10877 header->sect_count = NUM_OS_LOG_SECTIONS; 10878 header->sections[OS_LOG_SECT_IDX].sect_offset = os_log_offset; 10879 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) os_log_size; 10880 header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset; 10881 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) cstring_size; 10882 10883 10884 logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef))); 10885 if (!logData) { 10886 goto finish; 10887 } 10888 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0]))); 10889 if (!res) { 10890 goto finish; 10891 } 10892 if (os_log_data) { 10893 res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size); 10894 if (!res) { 10895 goto finish; 10896 } 10897 } 10898 if (cstring_data) { 10899 res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size); 10900 if (!res) { 10901 goto finish; 10902 } 10903 } 10904 result->setObject(kOSBundleLogStringsKey, logData.get()); 10905 } 10906 10907 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) { 10908 cpuTypeNumber = OSNumber::withNumber( 10909 (uint64_t) kext_mach_hdr->cputype, 10910 8 * sizeof(kext_mach_hdr->cputype)); 10911 if (!cpuTypeNumber) { 10912 goto finish; 10913 } 10914 result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get()); 10915 } 10916 10917 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) { 10918 cpuSubtypeNumber = OSNumber::withNumber( 10919 (uint64_t) kext_mach_hdr->cpusubtype, 10920 8 * sizeof(kext_mach_hdr->cpusubtype)); 10921 if (!cpuSubtypeNumber) { 10922 goto finish; 10923 } 10924 result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get()); 10925 } 10926 } else { 10927 if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) { 10928 osLogDataHeaderRef *header; 10929 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])]; 10930 bool res; 10931 10932 header = (osLogDataHeaderRef *) headerBytes; 10933 header->version = OS_LOG_HDR_VERSION; 10934 header->sect_count = NUM_OS_LOG_SECTIONS; 10935 header->sections[OS_LOG_SECT_IDX].sect_offset = 0; 10936 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) 0; 10937 header->sections[CSTRING_SECT_IDX].sect_offset = 0; 10938 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) 0; 10939 10940 logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef))); 10941 if (!logData) { 10942 goto finish; 10943 } 10944 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0]))); 10945 if (!res) { 10946 goto finish; 10947 } 10948 result->setObject(kOSBundleLogStringsKey, logData.get()); 10949 } 10950 } 10951 } 10952 10953 /* CFBundleIdentifier. We set this regardless because it's just stupid not to. 10954 */ 10955 result->setObject(kCFBundleIdentifierKey, bundleID.get()); 10956 10957 /* CFBundlePackageType 10958 */ 10959 bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL; 10960 if (bundleType) { 10961 result->setObject(kCFBundlePackageTypeKey, bundleType); 10962 } 10963 10964 /* CFBundleVersion. 10965 */ 10966 if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) { 10967 versionString = OSDynamicCast(OSString, 10968 getPropertyForHostArch(kCFBundleVersionKey)); 10969 if (versionString) { 10970 result->setObject(kCFBundleVersionKey, versionString); 10971 } 10972 } 10973 10974 /* OSBundleCompatibleVersion. 10975 */ 10976 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) { 10977 versionString = OSDynamicCast(OSString, 10978 getPropertyForHostArch(kOSBundleCompatibleVersionKey)); 10979 if (versionString) { 10980 result->setObject(kOSBundleCompatibleVersionKey, versionString); 10981 } 10982 } 10983 10984 /* Path. 10985 */ 10986 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) { 10987 if (path) { 10988 result->setObject(kOSBundlePathKey, path.get()); 10989 } 10990 } 10991 10992 10993 /* OSBundleExecutablePath. 10994 */ 10995 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) { 10996 if (path && executableRelPath) { 10997 uint32_t pathLength = path->getLength(); // gets incremented below 10998 10999 // +1 for slash, +1 for \0 11000 executablePathCStringSize = pathLength + executableRelPath->getLength() + 2; 11001 11002 executablePathCString = (char *)kheap_alloc_tag(KHEAP_TEMP, 11003 executablePathCStringSize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); // +1 for \0 11004 if (!executablePathCString) { 11005 goto finish; 11006 } 11007 strlcpy(executablePathCString, path->getCStringNoCopy(), 11008 executablePathCStringSize); 11009 executablePathCString[pathLength++] = '/'; 11010 executablePathCString[pathLength++] = '\0'; 11011 strlcat(executablePathCString, executableRelPath->getCStringNoCopy(), 11012 executablePathCStringSize); 11013 11014 executablePathString = OSString::withCString(executablePathCString); 11015 11016 if (!executablePathString) { 11017 goto finish; 11018 } 11019 11020 result->setObject(kOSBundleExecutablePathKey, executablePathString.get()); 11021 } else if (flags.builtin) { 11022 result->setObject(kOSBundleExecutablePathKey, bundleID.get()); 11023 } else if (isDriverKit()) { 11024 if (path) { 11025 // +1 for slash, +1 for \0 11026 uint32_t pathLength = path->getLength(); 11027 executablePathCStringSize = pathLength + 2; 11028 11029 executablePathCString = (char *)kheap_alloc_tag(KHEAP_TEMP, 11030 executablePathCStringSize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 11031 if (!executablePathCString) { 11032 goto finish; 11033 } 11034 strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize); 11035 executablePathCString[pathLength++] = '/'; 11036 executablePathCString[pathLength++] = '\0'; 11037 11038 executablePathString = OSString::withCString(executablePathCString); 11039 11040 if (!executablePathString) { 11041 goto finish; 11042 } 11043 11044 result->setObject(kOSBundleExecutablePathKey, executablePathString.get()); 11045 } 11046 } 11047 } 11048 11049 /* UUID, if the kext has one. 11050 */ 11051 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) { 11052 uuid = copyUUID(); 11053 if (uuid) { 11054 result->setObject(kOSBundleUUIDKey, uuid.get()); 11055 } 11056 } 11057 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) { 11058 uuid = copyTextUUID(); 11059 if (uuid) { 11060 result->setObject(kOSBundleTextUUIDKey, uuid.get()); 11061 } 11062 } 11063 11064 /* 11065 * Info.plist digest 11066 */ 11067 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) { 11068 OSData *digest; 11069 digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL; 11070 if (digest) { 11071 result->setObject(kOSKextInfoPlistDigestKey, digest); 11072 } 11073 } 11074 11075 /* 11076 * Collection type 11077 */ 11078 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) { 11079 result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString())); 11080 } 11081 11082 /* 11083 * Collection availability 11084 */ 11085 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) { 11086 result->setObject(kOSKextAuxKCAvailabilityKey, 11087 isLoadable() ? kOSBooleanTrue : kOSBooleanFalse); 11088 } 11089 11090 /* 11091 * Allows user load 11092 */ 11093 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) { 11094 OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey)); 11095 if (allowUserLoad) { 11096 result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad); 11097 } 11098 } 11099 11100 /* 11101 * Bundle Dependencies (OSBundleLibraries) 11102 */ 11103 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) { 11104 OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey)); 11105 if (libraries) { 11106 result->setObject(kOSBundleLibrariesKey, libraries); 11107 } 11108 } 11109 11110 /***** 11111 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted. 11112 */ 11113 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) { 11114 result->setObject(kOSKernelResourceKey, 11115 isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse); 11116 } 11117 11118 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) { 11119 result->setObject(kOSBundleIsInterfaceKey, 11120 isInterface() ? kOSBooleanTrue : kOSBooleanFalse); 11121 } 11122 11123 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) { 11124 result->setObject(kOSBundlePrelinkedKey, 11125 isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse); 11126 } 11127 11128 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) { 11129 result->setObject(kOSBundleStartedKey, 11130 isStarted() ? kOSBooleanTrue : kOSBooleanFalse); 11131 } 11132 11133 /* LoadTag (Index). 11134 */ 11135 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) { 11136 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag, 11137 /* numBits */ 8 * sizeof(loadTag)); 11138 if (!scratchNumber) { 11139 goto finish; 11140 } 11141 result->setObject(kOSBundleLoadTagKey, scratchNumber.get()); 11142 } 11143 11144 /* LoadAddress, LoadSize. 11145 */ 11146 if (!infoKeys || 11147 _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) || 11148 _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) || 11149 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) || 11150 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) || 11151 _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 11152 bool is_dext = isDriverKit(); 11153 if (isInterface() || flags.builtin || linkedExecutable || is_dext) { 11154 /* These go to userspace via serialization, so we don't want any doubts 11155 * about their size. 11156 */ 11157 uint64_t loadAddress = 0; 11158 uint32_t loadSize = 0; 11159 uint32_t wiredSize = 0; 11160 uint64_t execLoadAddress = 0; 11161 uint32_t execLoadSize = 0; 11162 11163 /* Interfaces always report 0 load address & size. 11164 * Just the way they roll. 11165 * 11166 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp 11167 * xxx - shouldn't have one! 11168 */ 11169 11170 if (flags.builtin || linkedExecutable) { 11171 kernel_mach_header_t *mh = NULL; 11172 kernel_segment_command_t *seg = NULL; 11173 11174 if (flags.builtin) { 11175 loadAddress = kmod_info->address; 11176 loadSize = (uint32_t)kmod_info->size; 11177 } else { 11178 loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy(); 11179 loadSize = linkedExecutable->getLength(); 11180 } 11181 mh = (kernel_mach_header_t *)loadAddress; 11182 loadAddress = ml_static_unslide(loadAddress); 11183 11184 /* Walk through the kext, looking for the first executable 11185 * segment in case we were asked for its size/address. 11186 */ 11187 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 11188 if (seg->initprot & VM_PROT_EXECUTE) { 11189 execLoadAddress = ml_static_unslide(seg->vmaddr); 11190 execLoadSize = (uint32_t)seg->vmsize; 11191 break; 11192 } 11193 } 11194 11195 /* If we have a kmod_info struct, calculated the wired size 11196 * from that. Otherwise it's the full load size. 11197 */ 11198 if (kmod_info) { 11199 wiredSize = loadSize - (uint32_t)kmod_info->hdr_size; 11200 } else { 11201 wiredSize = loadSize; 11202 } 11203 } else if (is_dext) { 11204 /* 11205 * DriverKit userspace executables do not have a kernel linkedExecutable, 11206 * so we "fake" their address range with the LoadTag. 11207 */ 11208 if (loadTag) { 11209 loadAddress = execLoadAddress = loadTag; 11210 loadSize = execLoadSize = 1; 11211 } 11212 } 11213 11214 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) { 11215 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11216 (unsigned long long)(loadAddress), 11217 /* numBits */ 8 * sizeof(loadAddress)); 11218 if (!scratchNumber) { 11219 goto finish; 11220 } 11221 result->setObject(kOSBundleLoadAddressKey, scratchNumber.get()); 11222 } 11223 if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) { 11224 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey)) 11225 && loadAddress && loadSize) { 11226 void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary); 11227 if (!baseAddress) { 11228 goto finish; 11229 } 11230 11231 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11232 (unsigned long long)ml_static_unslide((vm_offset_t)baseAddress), 11233 /* numBits */ 8 * sizeof(loadAddress)); 11234 if (!scratchNumber) { 11235 goto finish; 11236 } 11237 result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get()); 11238 } 11239 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey)) 11240 && (this == sKernelKext) && gBuiltinKmodsCount) { 11241 result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue); 11242 } 11243 } 11244 11245 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) { 11246 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11247 (unsigned long long)(execLoadAddress), 11248 /* numBits */ 8 * sizeof(execLoadAddress)); 11249 if (!scratchNumber) { 11250 goto finish; 11251 } 11252 result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get()); 11253 } 11254 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) { 11255 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11256 (unsigned long long)(loadSize), 11257 /* numBits */ 8 * sizeof(loadSize)); 11258 if (!scratchNumber) { 11259 goto finish; 11260 } 11261 result->setObject(kOSBundleLoadSizeKey, scratchNumber.get()); 11262 } 11263 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) { 11264 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11265 (unsigned long long)(execLoadSize), 11266 /* numBits */ 8 * sizeof(execLoadSize)); 11267 if (!scratchNumber) { 11268 goto finish; 11269 } 11270 result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get()); 11271 } 11272 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) { 11273 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11274 (unsigned long long)(wiredSize), 11275 /* numBits */ 8 * sizeof(wiredSize)); 11276 if (!scratchNumber) { 11277 goto finish; 11278 } 11279 result->setObject(kOSBundleWiredSizeKey, scratchNumber.get()); 11280 } 11281 } 11282 } 11283 11284 /* OSBundleDependencies. In descending order for 11285 * easy compatibility with kextstat(8). 11286 */ 11287 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) { 11288 if ((count = getNumDependencies())) { 11289 dependencyLoadTags = OSArray::withCapacity(count); 11290 result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get()); 11291 11292 i = count - 1; 11293 do { 11294 OSKext * dependency = OSDynamicCast(OSKext, 11295 dependencies->getObject(i)); 11296 11297 if (!dependency) { 11298 continue; 11299 } 11300 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11301 (unsigned long long)dependency->getLoadTag(), 11302 /* numBits*/ 8 * sizeof(loadTag)); 11303 if (!scratchNumber) { 11304 goto finish; 11305 } 11306 dependencyLoadTags->setObject(scratchNumber.get()); 11307 } while (i--); 11308 } 11309 } 11310 11311 /* OSBundleMetaClasses. 11312 */ 11313 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) { 11314 if (metaClasses && metaClasses->getCount()) { 11315 metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get()); 11316 metaClassInfo = OSArray::withCapacity(metaClasses->getCount()); 11317 if (!metaClassIterator || !metaClassInfo) { 11318 goto finish; 11319 } 11320 result->setObject(kOSBundleClassesKey, metaClassInfo.get()); 11321 11322 while ((thisMetaClass = OSDynamicCast(OSMetaClass, 11323 metaClassIterator->getNextObject()))) { 11324 metaClassDict = OSDictionary::withCapacity(3); 11325 if (!metaClassDict) { 11326 goto finish; 11327 } 11328 11329 metaClassName = OSString::withCString(thisMetaClass->getClassName()); 11330 if (thisMetaClass->getSuperClass()) { 11331 superclassName = OSString::withCString( 11332 thisMetaClass->getSuperClass()->getClassName()); 11333 } 11334 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(), 11335 8 * sizeof(unsigned int)); 11336 11337 /* Bail if any of the essentials is missing. The root class lacks a superclass, 11338 * of course. 11339 */ 11340 if (!metaClassDict || !metaClassName || !scratchNumber) { 11341 goto finish; 11342 } 11343 11344 metaClassInfo->setObject(metaClassDict.get()); 11345 metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get()); 11346 if (superclassName) { 11347 metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get()); 11348 } 11349 metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get()); 11350 } 11351 } 11352 } 11353 11354 /* OSBundleRetainCount. 11355 */ 11356 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) { 11357 { 11358 int kextRetainCount = getRetainCount() - 1; 11359 if (isLoaded()) { 11360 kextRetainCount--; 11361 } 11362 OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber( 11363 (int)kextRetainCount, 11364 /* numBits*/ 8 * sizeof(int)); 11365 if (scratchNumber) { 11366 result->setObject(kOSBundleRetainCountKey, scratchNumber.get()); 11367 } 11368 } 11369 } 11370 11371 success = true; 11372 11373 finish: 11374 if (executablePathCString) { 11375 kheap_free(KHEAP_TEMP, executablePathCString, executablePathCStringSize); 11376 } 11377 if (!success) { 11378 result.reset(); 11379 } 11380 return result; 11381 } 11382 11383 /********************************************************************* 11384 *********************************************************************/ 11385 /* static */ 11386 bool 11387 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize) 11388 { 11389 bool ok; 11390 OSSharedPtr<OSKext> kext; 11391 11392 IORecursiveLockLock(sKextLock); 11393 kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain); 11394 IORecursiveLockUnlock(sKextLock); 11395 11396 if (!kext || !kext->path || !kext->userExecutableRelPath) { 11397 return false; 11398 } 11399 snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s", 11400 kext->path->getCStringNoCopy(), 11401 kext->userExecutableRelPath->getCStringNoCopy()); 11402 ok = true; 11403 11404 return ok; 11405 } 11406 11407 /********************************************************************* 11408 *********************************************************************/ 11409 /* static */ 11410 OSReturn 11411 OSKext::requestResource( 11412 const char * kextIdentifierCString, 11413 const char * resourceNameCString, 11414 OSKextRequestResourceCallback callback, 11415 void * context, 11416 OSKextRequestTag * requestTagOut) 11417 { 11418 OSReturn result = kOSReturnError; 11419 OSSharedPtr<OSKext> callbackKext; // looked up 11420 11421 OSKextRequestTag requestTag = -1; 11422 OSSharedPtr<OSNumber> requestTagNum; 11423 OSSharedPtr<OSDictionary> requestDict; 11424 OSSharedPtr<OSString> kextIdentifier; 11425 OSSharedPtr<OSString> resourceName; 11426 11427 OSSharedPtr<OSDictionary> callbackRecord; 11428 OSSharedPtr<OSData> callbackWrapper; 11429 11430 OSSharedPtr<OSData> contextWrapper; 11431 11432 IORecursiveLockLock(sKextLock); 11433 11434 if (requestTagOut) { 11435 *requestTagOut = kOSKextRequestTagInvalid; 11436 } 11437 11438 /* If requests to user space are disabled, don't go any further */ 11439 if (!sKernelRequestsEnabled) { 11440 OSKextLog(/* kext */ NULL, 11441 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 11442 "Can't request resource %s for %s - requests to user space are disabled.", 11443 resourceNameCString, 11444 kextIdentifierCString); 11445 result = kOSKextReturnDisabled; 11446 goto finish; 11447 } 11448 11449 if (!kextIdentifierCString || !resourceNameCString || !callback) { 11450 result = kOSKextReturnInvalidArgument; 11451 goto finish; 11452 } 11453 11454 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 11455 if (!callbackKext) { 11456 OSKextLog(/* kext */ NULL, 11457 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 11458 "Resource request has bad callback address."); 11459 result = kOSKextReturnInvalidArgument; 11460 goto finish; 11461 } 11462 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 11463 OSKextLog(/* kext */ NULL, 11464 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 11465 "Resource request callback is in a kext that is not started."); 11466 result = kOSKextReturnInvalidArgument; 11467 goto finish; 11468 } 11469 11470 /* Do not allow any new requests to be made on a kext that is unloading. 11471 */ 11472 if (callbackKext->flags.stopping) { 11473 result = kOSKextReturnStopping; 11474 goto finish; 11475 } 11476 11477 /* If we're wrapped the next available request tag around to the negative 11478 * numbers, we can't service any more requests. 11479 */ 11480 if (sNextRequestTag == kOSKextRequestTagInvalid) { 11481 OSKextLog(/* kext */ NULL, 11482 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 11483 "No more request tags available; restart required."); 11484 result = kOSKextReturnNoResources; 11485 goto finish; 11486 } 11487 requestTag = sNextRequestTag++; 11488 11489 result = _OSKextCreateRequest(kKextRequestPredicateRequestResource, 11490 requestDict); 11491 if (result != kOSReturnSuccess) { 11492 goto finish; 11493 } 11494 11495 kextIdentifier = OSString::withCString(kextIdentifierCString); 11496 resourceName = OSString::withCString(resourceNameCString); 11497 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 11498 8 * sizeof(requestTag)); 11499 if (!kextIdentifier || 11500 !resourceName || 11501 !requestTagNum || 11502 !_OSKextSetRequestArgument(requestDict.get(), 11503 kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) || 11504 !_OSKextSetRequestArgument(requestDict.get(), 11505 kKextRequestArgumentNameKey, resourceName.get()) || 11506 !_OSKextSetRequestArgument(requestDict.get(), 11507 kKextRequestArgumentRequestTagKey, requestTagNum.get())) { 11508 result = kOSKextReturnNoMemory; 11509 goto finish; 11510 } 11511 11512 callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection()); 11513 if (!callbackRecord) { 11514 result = kOSKextReturnNoMemory; 11515 goto finish; 11516 } 11517 // we validate callback address at call time 11518 callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *)); 11519 if (context) { 11520 contextWrapper = OSData::withBytes((void *)&context, sizeof(void *)); 11521 } 11522 if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(), 11523 kKextRequestArgumentCallbackKey, callbackWrapper.get())) { 11524 result = kOSKextReturnNoMemory; 11525 goto finish; 11526 } 11527 11528 if (context) { 11529 if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(), 11530 kKextRequestArgumentContextKey, contextWrapper.get())) { 11531 result = kOSKextReturnNoMemory; 11532 goto finish; 11533 } 11534 } 11535 11536 /* Only post the requests after all the other potential failure points 11537 * have been passed. 11538 */ 11539 if (!sKernelRequests->setObject(requestDict.get()) || 11540 !sRequestCallbackRecords->setObject(callbackRecord.get())) { 11541 result = kOSKextReturnNoMemory; 11542 goto finish; 11543 } 11544 11545 OSKext::pingIOKitDaemon(); 11546 11547 result = kOSReturnSuccess; 11548 if (requestTagOut) { 11549 *requestTagOut = requestTag; 11550 } 11551 11552 finish: 11553 11554 /* If we didn't succeed, yank the request & callback 11555 * from their holding arrays. 11556 */ 11557 if (result != kOSReturnSuccess) { 11558 unsigned int index; 11559 11560 index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0); 11561 if (index != (unsigned int)-1) { 11562 sKernelRequests->removeObject(index); 11563 } 11564 index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0); 11565 if (index != (unsigned int)-1) { 11566 sRequestCallbackRecords->removeObject(index); 11567 } 11568 } 11569 11570 OSKext::considerUnloads(/* rescheduleOnly? */ true); 11571 11572 IORecursiveLockUnlock(sKextLock); 11573 11574 return result; 11575 } 11576 11577 OSReturn 11578 OSKext::requestDaemonLaunch( 11579 OSString *kextIdentifier, 11580 OSString *serverName, 11581 OSNumber *serverTag, 11582 OSSharedPtr<IOUserServerCheckInToken> &checkInToken) 11583 { 11584 OSReturn result; 11585 IOUserServerCheckInToken * checkInTokenRaw = NULL; 11586 11587 result = requestDaemonLaunch(kextIdentifier, serverName, 11588 serverTag, &checkInTokenRaw); 11589 11590 if (kOSReturnSuccess == result) { 11591 checkInToken.reset(checkInTokenRaw, OSNoRetain); 11592 } 11593 11594 return result; 11595 } 11596 11597 OSReturn 11598 OSKext::requestDaemonLaunch( 11599 OSString *kextIdentifier, 11600 OSString *serverName, 11601 OSNumber *serverTag, 11602 IOUserServerCheckInToken ** checkInToken) 11603 { 11604 OSReturn result = kOSReturnError; 11605 OSSharedPtr<OSDictionary> requestDict; 11606 OSSharedPtr<IOUserServerCheckInToken> token; 11607 11608 if (!kextIdentifier || !serverName || !serverTag) { 11609 result = kOSKextReturnInvalidArgument; 11610 goto finish; 11611 } 11612 11613 IORecursiveLockLock(sKextLock); 11614 11615 OSKextLog(/* kext */ NULL, 11616 kOSKextLogDebugLevel | 11617 kOSKextLogGeneralFlag, 11618 "Requesting daemon launch for %s with serverName %s and tag %llu", 11619 kextIdentifier->getCStringNoCopy(), 11620 serverName->getCStringNoCopy(), 11621 serverTag->unsigned64BitValue() 11622 ); 11623 11624 result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict); 11625 if (result != kOSReturnSuccess) { 11626 goto finish; 11627 } 11628 11629 token.reset(IOUserServerCheckInToken::create(), OSNoRetain); 11630 if (!token) { 11631 result = kOSKextReturnNoMemory; 11632 goto finish; 11633 } 11634 11635 if (!_OSKextSetRequestArgument(requestDict.get(), 11636 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) || 11637 !_OSKextSetRequestArgument(requestDict.get(), 11638 kKextRequestArgumentDriverExtensionServerName, serverName) || 11639 !_OSKextSetRequestArgument(requestDict.get(), 11640 kKextRequestArgumentDriverExtensionServerTag, serverTag) || 11641 !_OSKextSetRequestArgument(requestDict.get(), 11642 kKextRequestArgumentCheckInToken, token.get())) { 11643 result = kOSKextReturnNoMemory; 11644 goto finish; 11645 } 11646 11647 /* Only post the requests after all the other potential failure points 11648 * have been passed. 11649 */ 11650 if (!sKernelRequests->setObject(requestDict.get())) { 11651 result = kOSKextReturnNoMemory; 11652 goto finish; 11653 } 11654 *checkInToken = token.detach(); 11655 OSKext::pingIOKitDaemon(); 11656 11657 result = kOSReturnSuccess; 11658 finish: 11659 IORecursiveLockUnlock(sKextLock); 11660 return result; 11661 } 11662 11663 /********************************************************************* 11664 * Assumes sKextLock is held. 11665 *********************************************************************/ 11666 /* static */ 11667 OSReturn 11668 OSKext::dequeueCallbackForRequestTag( 11669 OSKextRequestTag requestTag, 11670 OSSharedPtr<OSDictionary> &callbackRecordOut) 11671 { 11672 OSDictionary * callbackRecordOutRaw = NULL; 11673 OSReturn result; 11674 11675 result = dequeueCallbackForRequestTag(requestTag, 11676 &callbackRecordOutRaw); 11677 11678 if (kOSReturnSuccess == result) { 11679 callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain); 11680 } 11681 11682 return result; 11683 } 11684 OSReturn 11685 OSKext::dequeueCallbackForRequestTag( 11686 OSKextRequestTag requestTag, 11687 OSDictionary ** callbackRecordOut) 11688 { 11689 OSReturn result = kOSReturnError; 11690 OSSharedPtr<OSNumber> requestTagNum; 11691 11692 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag, 11693 8 * sizeof(requestTag)); 11694 if (!requestTagNum) { 11695 goto finish; 11696 } 11697 11698 result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(), 11699 callbackRecordOut); 11700 11701 finish: 11702 return result; 11703 } 11704 11705 /********************************************************************* 11706 * Assumes sKextLock is held. 11707 *********************************************************************/ 11708 /* static */ 11709 OSReturn 11710 OSKext::dequeueCallbackForRequestTag( 11711 OSNumber * requestTagNum, 11712 OSSharedPtr<OSDictionary> &callbackRecordOut) 11713 { 11714 OSDictionary * callbackRecordOutRaw = NULL; 11715 OSReturn result; 11716 11717 result = dequeueCallbackForRequestTag(requestTagNum, 11718 &callbackRecordOutRaw); 11719 11720 if (kOSReturnSuccess == result) { 11721 callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain); 11722 } 11723 11724 return result; 11725 } 11726 OSReturn 11727 OSKext::dequeueCallbackForRequestTag( 11728 OSNumber * requestTagNum, 11729 OSDictionary ** callbackRecordOut) 11730 { 11731 OSReturn result = kOSKextReturnInvalidArgument; 11732 OSDictionary * callbackRecord = NULL; // retain if matched! 11733 OSNumber * callbackTagNum = NULL; // do not release 11734 unsigned int count, i; 11735 11736 result = kOSReturnError; 11737 count = sRequestCallbackRecords->getCount(); 11738 for (i = 0; i < count; i++) { 11739 callbackRecord = OSDynamicCast(OSDictionary, 11740 sRequestCallbackRecords->getObject(i)); 11741 if (!callbackRecord) { 11742 goto finish; 11743 } 11744 11745 /* If we don't find a tag, we basically have a leak here. Maybe 11746 * we should just remove it. 11747 */ 11748 callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument( 11749 callbackRecord, kKextRequestArgumentRequestTagKey)); 11750 if (!callbackTagNum) { 11751 goto finish; 11752 } 11753 11754 /* We could be even more paranoid and check that all the incoming 11755 * args match what's in the callback record. 11756 */ 11757 if (callbackTagNum->isEqualTo(requestTagNum)) { 11758 if (callbackRecordOut) { 11759 *callbackRecordOut = callbackRecord; 11760 callbackRecord->retain(); 11761 } 11762 sRequestCallbackRecords->removeObject(i); 11763 result = kOSReturnSuccess; 11764 goto finish; 11765 } 11766 } 11767 result = kOSKextReturnNotFound; 11768 11769 finish: 11770 return result; 11771 } 11772 11773 11774 /********************************************************************* 11775 * Busy timeout triage 11776 *********************************************************************/ 11777 /* static */ 11778 bool 11779 OSKext::pendingIOKitDaemonRequests(void) 11780 { 11781 return sRequestCallbackRecords && sRequestCallbackRecords->getCount(); 11782 } 11783 11784 /********************************************************************* 11785 * Acquires and releases sKextLock 11786 * 11787 * This function is designed to be called exactly once on boot by 11788 * the IOKit management daemon, kernelmanagerd. It gathers all codeless 11789 * kext and dext personalities, and then attempts to map a System 11790 * (pageable) KC and an Auxiliary (aux) KC. 11791 * 11792 * Even if the pageable or aux KC fail to load - this function will 11793 * not allow a second call. This avoids security issues where 11794 * kernelmanagerd has been compromised or the pageable kc has been 11795 * tampered with and the attacker attempts to re-load a malicious 11796 * variant. 11797 * 11798 * Return: if a KC fails to load the return value will contain: 11799 * kOSKextReturnKCLoadFailure. If the pageable KC fails, 11800 * the return value will contain kOSKextReturnKCLoadFailureSystemKC. 11801 * Similarly, if the aux kc load fails, the return value will 11802 * contain kOSKextReturnKCLoadFailureAuxKC. The two values 11803 * compose with each other and with kOSKextReturnKCLoadFailure. 11804 *********************************************************************/ 11805 /* static */ 11806 OSReturn 11807 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused) 11808 { 11809 static bool daemon_ready = false; 11810 11811 OSReturn ret = kOSKextReturnInvalidArgument; 11812 OSReturn kcerr = 0; 11813 bool start_matching = false; 11814 11815 bool allow_fileset_load = !daemon_ready; 11816 #if !(defined(__x86_64__) || defined(__i386__)) 11817 /* never allow KCs full of kexts on non-x86 machines */ 11818 allow_fileset_load = false; 11819 #endif 11820 11821 /* 11822 * Get the args from the request. Right now we need the file 11823 * name for the pageable and the aux kext collection file sets. 11824 */ 11825 OSDictionary * requestArgs = NULL; // do not release 11826 OSString * pageable_filepath = NULL; // do not release 11827 OSString * aux_filepath = NULL; // do not release 11828 OSArray * codeless_kexts = NULL; // do not release 11829 11830 kernel_mach_header_t *akc_mh = NULL; 11831 11832 requestArgs = OSDynamicCast(OSDictionary, 11833 requestDict->getObject(kKextRequestArgumentsKey)); 11834 11835 if (requestArgs == NULL) { 11836 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 11837 "KextLog: No arguments in plist for loading fileset kext\n"); 11838 printf("KextLog: No arguments in plist for loading fileset kext\n"); 11839 return ret; 11840 } 11841 11842 ret = kOSKextReturnDisabled; 11843 11844 IORecursiveLockLock(sKextLock); 11845 11846 pageable_filepath = OSDynamicCast(OSString, 11847 requestArgs->getObject(kKextRequestArgumentPageableKCFilename)); 11848 11849 if (allow_fileset_load && pageable_filepath != NULL) { 11850 printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy()); 11851 11852 ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable); 11853 if (ret) { 11854 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 11855 "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret); 11856 11857 printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret); 11858 ret = kOSKextReturnKCLoadFailure; 11859 kcerr |= kOSKextReturnKCLoadFailureSystemKC; 11860 goto try_auxkc; 11861 } 11862 /* 11863 * Even if the AuxKC fails to load, we still want to send 11864 * the System KC personalities to the catalog for matching 11865 */ 11866 start_matching = true; 11867 } else if (pageable_filepath != NULL) { 11868 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 11869 "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy()); 11870 ret = kOSKextReturnUnsupported; 11871 } 11872 11873 try_auxkc: 11874 akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary); 11875 if (akc_mh) { 11876 /* 11877 * If we try to load a deferred AuxKC, then don't ever attempt 11878 * a filesystem map of a file 11879 */ 11880 allow_fileset_load = false; 11881 11882 /* 11883 * This function is only called once per boot, so we haven't 11884 * yet loaded an AuxKC. If we have registered the AuxKC mach 11885 * header, that means that the kext collection has been placed 11886 * in memory for us by the booter, and is waiting for us to 11887 * process it. Grab the deferred XML plist of info 11888 * dictionaries and add all the kexts. 11889 */ 11890 OSSharedPtr<OSObject> parsedXML; 11891 OSSharedPtr<OSData> loaded_kcUUID; 11892 OSDictionary *infoDict; 11893 parsedXML = consumeDeferredKextCollection(KCKindAuxiliary); 11894 infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 11895 if (infoDict) { 11896 bool added; 11897 printf("KextLog: Adding kexts from in-memory AuxKC\n"); 11898 added = OSKext::addKextsFromKextCollection(akc_mh, infoDict, 11899 kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary); 11900 if (!loaded_kcUUID) { 11901 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 11902 "KextLog: WARNING: did not find UUID in deferred Aux KC!"); 11903 } else if (!added) { 11904 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 11905 "KextLog: WARNING: Failed to load AuxKC from memory."); 11906 } 11907 /* only return success if the pageable load (above) was successful */ 11908 if (ret != kOSKextReturnKCLoadFailure) { 11909 ret = kOSReturnSuccess; 11910 } 11911 /* the registration of the AuxKC parsed out the KC's UUID already */ 11912 } else { 11913 if (daemon_ready) { 11914 /* 11915 * Complain, but don't return an error if this isn't the first time the 11916 * IOKit daemon is checking in. If the daemon ever restarts, we will 11917 * hit this case because we've already consumed the deferred personalities. 11918 * We return success here so that a call to this function from a restarted 11919 * daemon with no codeless kexts will succeed. 11920 */ 11921 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 11922 "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart"); 11923 if (ret != kOSKextReturnKCLoadFailure) { 11924 ret = kOSReturnSuccess; 11925 } 11926 } else { 11927 /* this is a real error case */ 11928 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag, 11929 "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary"); 11930 printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n"); 11931 ret = kOSKextReturnKCLoadFailure; 11932 kcerr |= kOSKextReturnKCLoadFailureAuxKC; 11933 } 11934 } 11935 } 11936 11937 aux_filepath = OSDynamicCast(OSString, 11938 requestArgs->getObject(kKextRequestArgumentAuxKCFilename)); 11939 if (allow_fileset_load && aux_filepath != NULL) { 11940 printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy()); 11941 11942 ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary); 11943 if (ret) { 11944 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 11945 "KextLog: loadKCFileSet for Aux KC returned %d\n", ret); 11946 11947 printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret); 11948 ret = kOSKextReturnKCLoadFailure; 11949 kcerr |= kOSKextReturnKCLoadFailureAuxKC; 11950 goto try_codeless; 11951 } 11952 start_matching = true; 11953 } else if (aux_filepath != NULL) { 11954 OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag, 11955 "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy()); 11956 if (ret != kOSKextReturnKCLoadFailure) { 11957 ret = kOSKextReturnUnsupported; 11958 } 11959 } 11960 11961 try_codeless: 11962 /* 11963 * Load codeless kexts last so that there is no possibilty of a 11964 * codeless kext bundle ID preventing a kext in the system KC from 11965 * loading 11966 */ 11967 codeless_kexts = OSDynamicCast(OSArray, 11968 requestArgs->getObject(kKextRequestArgumentCodelessPersonalities)); 11969 if (codeless_kexts != NULL) { 11970 uint32_t count = codeless_kexts->getCount(); 11971 OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 11972 "KextLog: loading %d codeless kexts/dexts", count); 11973 for (uint32_t i = 0; i < count; i++) { 11974 OSDictionary *infoDict; 11975 infoDict = OSDynamicCast(OSDictionary, 11976 codeless_kexts->getObject(i)); 11977 if (!infoDict) { 11978 continue; 11979 } 11980 // instantiate a new kext, and don't hold a reference 11981 // (the kext subsystem will hold one implicitly) 11982 OSKext::withCodelessInfo(infoDict); 11983 } 11984 /* ignore errors that are not KC load failures */ 11985 if (ret != kOSKextReturnKCLoadFailure) { 11986 ret = kOSReturnSuccess; 11987 } 11988 start_matching = true; 11989 } 11990 11991 /* send personalities to the IOCatalog once */ 11992 if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) { 11993 OSKext::sendAllKextPersonalitiesToCatalog(true); 11994 /* 11995 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark 11996 * things as active and start all the delayed matching: the 11997 * dext and codeless kext personalities should have all been 11998 * delivered via this one call. 11999 */ 12000 if (!daemon_ready) { 12001 OSKext::setIOKitDaemonActive(); 12002 OSKext::setDeferredLoadSucceeded(TRUE); 12003 IOService::iokitDaemonLaunched(); 12004 } 12005 if (sOSKextWasResetAfterUserspaceReboot) { 12006 sOSKextWasResetAfterUserspaceReboot = false; 12007 OSKext::setIOKitDaemonActive(); 12008 IOService::startDeferredMatches(); 12009 } 12010 } 12011 12012 if (ret == kOSKextReturnKCLoadFailure) { 12013 ret |= kcerr; 12014 } 12015 12016 /* 12017 * Only allow this function to attempt to load the pageable and 12018 * aux KCs once per boot. 12019 */ 12020 daemon_ready = true; 12021 12022 IORecursiveLockUnlock(sKextLock); 12023 12024 return ret; 12025 } 12026 12027 OSReturn 12028 OSKext::resetMutableSegments(void) 12029 { 12030 kernel_segment_command_t *seg = NULL; 12031 kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address; 12032 u_int index = 0; 12033 OSKextSavedMutableSegment *savedSegment = NULL; 12034 uintptr_t kext_slide = PE_get_kc_slide(kc_type); 12035 OSReturn err; 12036 12037 if (!savedMutableSegments) { 12038 OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag, 12039 "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString()); 12040 err = kOSKextReturnInternalError; 12041 goto finish; 12042 } 12043 12044 for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) { 12045 if (!segmentIsMutable(seg)) { 12046 continue; 12047 } 12048 uint64_t unslid_vmaddr = seg->vmaddr - kext_slide; 12049 uint64_t vmsize = seg->vmsize; 12050 err = kOSKextReturnInternalError; 12051 for (index = 0; index < savedMutableSegments->getCount(); index++) { 12052 savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index)); 12053 assert(savedSegment); 12054 if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) { 12055 OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag, 12056 "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1); 12057 err = savedSegment->restoreContents(seg); 12058 if (err != kOSReturnSuccess) { 12059 panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 12060 } 12061 } 12062 } 12063 if (err != kOSReturnSuccess) { 12064 panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1); 12065 } 12066 } 12067 err = kOSReturnSuccess; 12068 finish: 12069 return err; 12070 } 12071 12072 12073 /********************************************************************* 12074 * Assumes sKextLock is held. 12075 *********************************************************************/ 12076 /* static */ 12077 OSReturn 12078 OSKext::loadKCFileSet( 12079 const char *filepath, 12080 kc_kind_t type) 12081 { 12082 #if VM_MAPPED_KEXTS 12083 /* we only need to load filesets on systems that support VM_MAPPED kexts */ 12084 OSReturn err; 12085 struct vnode *vp = NULL; 12086 void *fileset_control; 12087 off_t fsize; 12088 bool pageable = (type == KCKindPageable); 12089 12090 if ((pageable && pageableKCloaded) || 12091 (!pageable && auxKCloaded)) { 12092 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12093 "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux")); 12094 12095 return kOSKextReturnInvalidArgument; 12096 } 12097 12098 /* Do not allow AuxKC to load if Pageable KC is not loaded */ 12099 if (!pageable && !pageableKCloaded) { 12100 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12101 "Trying to load the Aux KC without loading the Pageable KC"); 12102 return kOSKextReturnInvalidArgument; 12103 } 12104 12105 fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize); 12106 12107 if (fileset_control == NULL) { 12108 printf("Could not get memory control object for file %s", filepath); 12109 12110 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12111 "Could not get memory control object for file %s", filepath); 12112 return kOSKextReturnInvalidArgument; 12113 } 12114 if (vp == NULL) { 12115 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12116 "Could not find vnode for file %s", filepath); 12117 return kOSKextReturnInvalidArgument; 12118 } 12119 12120 kernel_mach_header_t *mh = NULL; 12121 uintptr_t slide = 0; 12122 12123 #if CONFIG_CSR 12124 /* 12125 * When SIP is enabled, the KC we map must be SIP-protected 12126 */ 12127 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) { 12128 struct vnode_attr va; 12129 int error; 12130 VATTR_INIT(&va); 12131 VATTR_WANTED(&va, va_flags); 12132 error = vnode_getattr(vp, &va, vfs_context_current()); 12133 if (error) { 12134 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12135 "vnode_getattr(%s) failed (error=%d)", filepath, error); 12136 err = kOSKextReturnInternalError; 12137 goto finish; 12138 } 12139 if (!(va.va_flags & SF_RESTRICTED)) { 12140 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12141 "Path to KC '%s' is not SIP-protected", filepath); 12142 err = kOSKextReturnInvalidArgument; 12143 goto finish; 12144 } 12145 } 12146 #endif 12147 12148 err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL); 12149 if (err) { 12150 printf("KextLog: mapKCFileSet returned %d\n", err); 12151 12152 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12153 "mapKCFileSet returned %d\n", err); 12154 12155 err = kOSKextReturnInvalidArgument; 12156 } 12157 12158 #if CONFIG_CSR 12159 finish: 12160 #endif 12161 /* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */ 12162 assert(vp != NULL); 12163 if (err == kOSReturnSuccess) { 12164 PE_set_kc_vp(type, vp); 12165 if (pageable) { 12166 pageableKCloaded = true; 12167 } else { 12168 auxKCloaded = true; 12169 } 12170 } else { 12171 vnode_put(vp); 12172 } 12173 12174 return err; 12175 #else 12176 (void)filepath; 12177 (void)type; 12178 return kOSKextReturnUnsupported; 12179 #endif // VM_MAPPED_KEXTS 12180 } 12181 12182 #if defined(__x86_64__) || defined(__i386__) 12183 /********************************************************************* 12184 * Assumes sKextLock is held. 12185 *********************************************************************/ 12186 /* static */ 12187 OSReturn 12188 OSKext::mapKCFileSet( 12189 void *control, 12190 vm_size_t fsize, 12191 kernel_mach_header_t **mhp, 12192 off_t file_offset, 12193 uintptr_t *slidep, 12194 bool pageable, 12195 void *map_entry_list) 12196 { 12197 bool fileset_load = false; 12198 kern_return_t ret; 12199 OSReturn err; 12200 kernel_section_t *infoPlistSection = NULL; 12201 OSDictionary *infoDict = NULL; 12202 12203 OSSharedPtr<OSObject> parsedXML; 12204 OSSharedPtr<OSString> errorString; 12205 OSSharedPtr<OSData> loaded_kcUUID; 12206 12207 /* Check if initial load for file set */ 12208 if (*mhp == NULL) { 12209 fileset_load = true; 12210 12211 /* Get a page aligned address from kext map to map the file */ 12212 vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize); 12213 if (pagealigned_addr == 0) { 12214 return kOSKextReturnNoMemory; 12215 } 12216 12217 *mhp = (kernel_mach_header_t *)pagealigned_addr; 12218 12219 /* Allocate memory for bailout mechanism */ 12220 map_entry_list = allocate_kcfileset_map_entry_list(); 12221 if (map_entry_list == NULL) { 12222 return kOSKextReturnNoMemory; 12223 } 12224 } 12225 12226 uintptr_t *slideptr = fileset_load ? slidep : NULL; 12227 err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list); 12228 /* mhp and slideptr are updated by mapKCTextSegment */ 12229 if (err) { 12230 if (fileset_load) { 12231 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12232 } 12233 return err; 12234 } 12235 12236 /* Initialize the kc header globals */ 12237 if (fileset_load) { 12238 if (pageable) { 12239 PE_set_kc_header(KCKindPageable, *mhp, *slidep); 12240 } else { 12241 PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep); 12242 } 12243 } 12244 12245 /* Iterate through all the segments and map necessary segments */ 12246 struct load_command *lcp = (struct load_command *) (*mhp + 1); 12247 for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) { 12248 vm_map_offset_t start; 12249 kernel_mach_header_t *k_mh = NULL; 12250 kernel_segment_command_t * seg = NULL; 12251 struct fileset_entry_command *fse = NULL; 12252 12253 if (lcp->cmd == LC_SEGMENT_KERNEL) { 12254 seg = (kernel_segment_command_t *)lcp; 12255 start = ((uintptr_t)(seg->vmaddr)) + *slidep; 12256 } else if (lcp->cmd == LC_FILESET_ENTRY) { 12257 fse = (struct fileset_entry_command *)lcp; 12258 k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep); 12259 12260 /* Map the segments of the mach-o binary */ 12261 err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list); 12262 if (err) { 12263 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12264 return kOSKextReturnInvalidArgument; 12265 } 12266 continue; 12267 } else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) { 12268 /* Check if the Aux KC is built pageable style */ 12269 if (!pageable && !fileset_load && !auxKCloaded) { 12270 resetAuxKCSegmentOnUnload = true; 12271 } 12272 continue; 12273 } else { 12274 continue; 12275 } 12276 12277 if (fileset_load) { 12278 if (seg->vmsize == 0) { 12279 continue; 12280 } 12281 12282 /* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */ 12283 if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 && 12284 strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 && 12285 strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 && 12286 strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) { 12287 continue; 12288 } 12289 } else { 12290 if (seg->vmsize == 0) { 12291 continue; 12292 } 12293 12294 /* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */ 12295 if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 || 12296 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 || 12297 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) { 12298 continue; 12299 } 12300 } 12301 12302 ret = vm_map_kcfileset_segment( 12303 &start, seg->vmsize, 12304 (memory_object_control_t)control, seg->fileoff, seg->maxprot); 12305 12306 if (ret != KERN_SUCCESS) { 12307 if (fileset_load) { 12308 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12309 } 12310 return kOSKextReturnInvalidArgument; 12311 } 12312 add_kcfileset_map_entry(map_entry_list, start, seg->vmsize); 12313 } 12314 12315 /* Return if regular mach-o */ 12316 if (!fileset_load) { 12317 return 0; 12318 } 12319 12320 /* 12321 * Fixup for the Pageable KC and the Aux KC is done by 12322 * i386_slide_kext_collection_mh_addrs, but it differs in 12323 * following ways: 12324 * 12325 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands. 12326 * The fixup of kext segments and kext load commands are done at kext 12327 * load time by calling i386_slide_individual_kext. 12328 * 12329 * AuxKC old style: Fixup all the segments and all the load commands. 12330 * 12331 * AuxKC pageable style: Same as the Pageable KC. 12332 */ 12333 bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false)); 12334 ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header); 12335 if (ret != KERN_SUCCESS) { 12336 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12337 return kOSKextReturnInvalidArgument; 12338 } 12339 12340 /* Get the prelink info dictionary */ 12341 infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection); 12342 parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString); 12343 if (parsedXML) { 12344 infoDict = OSDynamicCast(OSDictionary, parsedXML.get()); 12345 } 12346 12347 if (!infoDict) { 12348 const char *errorCString = "(unknown error)"; 12349 12350 if (errorString && errorString->getCStringNoCopy()) { 12351 errorCString = errorString->getCStringNoCopy(); 12352 } else if (parsedXML) { 12353 errorCString = "not a dictionary"; 12354 } 12355 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12356 "Error unserializing kext info plist section: %s.", errorCString); 12357 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12358 return kOSKextReturnInvalidArgument; 12359 } 12360 12361 /* Validate that the Kext Collection is prelinked to the loaded KC */ 12362 err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary); 12363 if (err) { 12364 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable); 12365 return kOSKextReturnInvalidArgument; 12366 } 12367 12368 /* Set Protection of Segments */ 12369 OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary); 12370 12371 OSKext::addKextsFromKextCollection(*mhp, 12372 infoDict, kPrelinkTextSegment, 12373 loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary); 12374 12375 /* Copy in the KC UUID */ 12376 if (!loaded_kcUUID) { 12377 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12378 "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux"); 12379 } else if (pageable) { 12380 pageablekc_uuid_valid = TRUE; 12381 memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength()); 12382 uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string); 12383 } else { 12384 auxkc_uuid_valid = TRUE; 12385 memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength()); 12386 uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string); 12387 } 12388 12389 deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable); 12390 12391 return 0; 12392 } 12393 12394 /********************************************************************* 12395 * Assumes sKextLock is held. 12396 *********************************************************************/ 12397 /* static */ 12398 OSReturn 12399 OSKext::mapKCTextSegment( 12400 void *control, 12401 kernel_mach_header_t **mhp, 12402 off_t file_offset, 12403 uintptr_t *slidep, 12404 void *map_entry_list) 12405 { 12406 kern_return_t ret; 12407 vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t), 12408 PAGE_MASK); 12409 vm_map_offset_t load_command_map_size = 0; 12410 kernel_mach_header_t *base_mh = *mhp; 12411 12412 /* Map the mach header at start of fileset for now (vmaddr = 0) */ 12413 ret = vm_map_kcfileset_segment( 12414 (vm_map_offset_t *)&base_mh, mach_header_map_size, 12415 (memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE)); 12416 12417 if (ret != KERN_SUCCESS) { 12418 printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret); 12419 12420 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12421 "Failed to map mach header of kc fileset with error %d", ret); 12422 return kOSKextReturnInvalidArgument; 12423 } 12424 12425 if (slidep) { 12426 /* Verify that it's an MH_FILESET */ 12427 if (base_mh->filetype != MH_FILESET) { 12428 printf("Kext Log: mapKCTextSegment mach header filetype" 12429 " is not an MH_FILESET, it is %x", base_mh->filetype); 12430 12431 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12432 "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype); 12433 12434 /* Unmap the mach header */ 12435 vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 12436 return kOSKextReturnInvalidArgument; 12437 } 12438 } 12439 12440 /* Map the remaining pages of load commands */ 12441 if (base_mh->sizeofcmds > mach_header_map_size) { 12442 vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size; 12443 load_command_map_size = base_mh->sizeofcmds - mach_header_map_size; 12444 12445 /* Map the load commands */ 12446 ret = vm_map_kcfileset_segment( 12447 &load_command_addr, load_command_map_size, 12448 (memory_object_control_t)control, file_offset + mach_header_map_size, 12449 (VM_PROT_READ | VM_PROT_WRITE)); 12450 12451 if (ret != KERN_SUCCESS) { 12452 printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret); 12453 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12454 "Failed to map load commands of kc fileset with error %d", ret); 12455 12456 /* Unmap the mach header */ 12457 vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 12458 return kOSKextReturnInvalidArgument; 12459 } 12460 } 12461 12462 kernel_segment_command_t *text_seg; 12463 text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT); 12464 12465 /* Calculate the slide and vm addr of mach header */ 12466 if (slidep) { 12467 *mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr); 12468 *slidep = ((uintptr_t)*mhp) - text_seg->vmaddr; 12469 } 12470 12471 /* Cache the text segment size and file offset before unmapping */ 12472 vm_map_offset_t text_segment_size = text_seg->vmsize; 12473 vm_object_offset_t text_segment_fileoff = text_seg->fileoff; 12474 vm_prot_t text_maxprot = text_seg->maxprot; 12475 12476 /* Unmap the first page and loadcommands and map the text segment */ 12477 ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size); 12478 assert(ret == KERN_SUCCESS); 12479 12480 if (load_command_map_size) { 12481 vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size; 12482 ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size); 12483 assert(ret == KERN_SUCCESS); 12484 } 12485 12486 /* Map the text segment at actual vm addr specified in fileset */ 12487 ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size, 12488 (memory_object_control_t)control, text_segment_fileoff, text_maxprot); 12489 if (ret != KERN_SUCCESS) { 12490 OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag, 12491 "Failed to map Text segment of kc fileset with error %d", ret); 12492 return kOSKextReturnInvalidArgument; 12493 } 12494 12495 add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size); 12496 return 0; 12497 } 12498 12499 /********************************************************************* 12500 * Assumes sKextLock is held. 12501 *********************************************************************/ 12502 /* static */ 12503 OSReturn 12504 OSKext::protectKCFileSet( 12505 kernel_mach_header_t *mh, 12506 kc_kind_t type) 12507 { 12508 vm_map_t kext_map = g_kext_map; 12509 kernel_segment_command_t * seg = NULL; 12510 vm_map_offset_t start = 0; 12511 vm_map_offset_t end = 0; 12512 OSReturn ret = 0; 12513 12514 /* Set VM permissions */ 12515 seg = firstsegfromheader((kernel_mach_header_t *)mh); 12516 while (seg) { 12517 start = round_page(seg->vmaddr); 12518 end = trunc_page(seg->vmaddr + seg->vmsize); 12519 12520 /* 12521 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS 12522 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT 12523 * for the Aux KC as well. 12524 */ 12525 if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 || 12526 strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 || 12527 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 || 12528 (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload && 12529 strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) { 12530 ret = OSKext_protect((kernel_mach_header_t *)mh, 12531 kext_map, start, end, seg->maxprot, TRUE, type); 12532 if (ret != KERN_SUCCESS) { 12533 printf("OSKext protect failed with error %d", ret); 12534 return kOSKextReturnInvalidArgument; 12535 } 12536 12537 ret = OSKext_protect((kernel_mach_header_t *)mh, 12538 kext_map, start, end, seg->initprot, FALSE, type); 12539 if (ret != KERN_SUCCESS) { 12540 printf("OSKext protect failed with error %d", ret); 12541 return kOSKextReturnInvalidArgument; 12542 } 12543 12544 ret = OSKext_wire((kernel_mach_header_t *)mh, 12545 kext_map, start, end, seg->initprot, FALSE, type); 12546 if (ret != KERN_SUCCESS) { 12547 printf("OSKext wire failed with error %d", ret); 12548 return kOSKextReturnInvalidArgument; 12549 } 12550 } 12551 12552 seg = nextsegfromheader((kernel_mach_header_t *) mh, seg); 12553 } 12554 12555 return 0; 12556 } 12557 12558 /********************************************************************* 12559 * Assumes sKextLock is held. 12560 *********************************************************************/ 12561 /* static */ 12562 void 12563 OSKext::freeKCFileSetcontrol(void) 12564 { 12565 PE_reset_all_kc_vp(); 12566 } 12567 12568 /********************************************************************* 12569 * Assumes sKextLock is held. 12570 * 12571 * resetKCFileSetSegments: Kext start function expects data segment to 12572 * be pristine on every load, unmap the dirty segments on unload and 12573 * remap them from FileSet on disk. Remap all segments of kext since 12574 * fixups are done per kext and not per segment. 12575 *********************************************************************/ 12576 OSReturn 12577 OSKext::resetKCFileSetSegments(void) 12578 { 12579 kernel_segment_command_t *seg = NULL; 12580 kernel_segment_command_t *text_seg; 12581 uint32_t text_fileoff; 12582 kernel_mach_header_t *k_mh = NULL; 12583 uintptr_t slide; 12584 struct vnode *vp = NULL; 12585 void *fileset_control = NULL; 12586 bool pageable = (kc_type == KCKindPageable); 12587 OSReturn err; 12588 kern_return_t kr; 12589 12590 /* Check the vnode reference is still available */ 12591 vp = (struct vnode *)PE_get_kc_vp(kc_type); 12592 if (vp == NULL) { 12593 OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag, 12594 "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString()); 12595 return kOSKextReturnInternalError; 12596 } 12597 12598 fileset_control = ubc_getobject(vp, 0); 12599 assert(fileset_control != NULL); 12600 12601 OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag, 12602 "Kext %s resetting all segments", getIdentifierCString()); 12603 12604 k_mh = (kernel_mach_header_t *)kmod_info->address; 12605 text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT); 12606 text_fileoff = text_seg->fileoff; 12607 slide = PE_get_kc_slide(kc_type); 12608 12609 seg = firstsegfromheader((kernel_mach_header_t *)k_mh); 12610 while (seg) { 12611 if (seg->vmsize == 0) { 12612 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 12613 continue; 12614 } 12615 12616 /* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */ 12617 if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 || 12618 strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 || 12619 strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) { 12620 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 12621 continue; 12622 } 12623 12624 kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize); 12625 assert(kr == KERN_SUCCESS); 12626 seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg); 12627 } 12628 12629 /* Unmap the text segment */ 12630 kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize); 12631 assert(kr == KERN_SUCCESS); 12632 12633 /* Map all the segments of the kext */ 12634 err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL); 12635 if (err) { 12636 panic("Could not reset segments of a mapped kext, error %x", err); 12637 } 12638 12639 /* Update address in kmod_info, since it has been reset */ 12640 if (kmod_info->address) { 12641 kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide); 12642 } 12643 12644 return 0; 12645 } 12646 12647 /********************************************************************* 12648 * Mechanism to track all segment mapping while mapping KC fileset. 12649 *********************************************************************/ 12650 12651 struct kcfileset_map_entry { 12652 vm_map_offset_t me_start; 12653 vm_map_offset_t me_size; 12654 }; 12655 12656 struct kcfileset_map_entry_list { 12657 int kme_list_count; 12658 int kme_list_index; 12659 struct kcfileset_map_entry kme_list[]; 12660 }; 12661 12662 #define KCFILESET_MAP_ENTRY_MAX (16380) 12663 12664 static void * 12665 allocate_kcfileset_map_entry_list(void) 12666 { 12667 struct kcfileset_map_entry_list *entry_list; 12668 12669 entry_list = (struct kcfileset_map_entry_list *)kalloc(sizeof(struct kcfileset_map_entry_list) + 12670 (sizeof(struct kcfileset_map_entry) * KCFILESET_MAP_ENTRY_MAX)); 12671 12672 entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX; 12673 entry_list->kme_list_index = 0; 12674 return entry_list; 12675 } 12676 12677 static void 12678 add_kcfileset_map_entry( 12679 void *map_entry_list, 12680 vm_map_offset_t start, 12681 vm_map_offset_t size) 12682 { 12683 if (map_entry_list == NULL) { 12684 return; 12685 } 12686 12687 struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list; 12688 12689 if (entry_list->kme_list_index >= entry_list->kme_list_count) { 12690 panic("Ran out of map kc fileset list\n"); 12691 } 12692 12693 entry_list->kme_list[entry_list->kme_list_index].me_start = start; 12694 entry_list->kme_list[entry_list->kme_list_index].me_size = size; 12695 12696 entry_list->kme_list_index++; 12697 } 12698 12699 static void 12700 deallocate_kcfileset_map_entry_list_and_unmap_entries( 12701 void *map_entry_list, 12702 boolean_t unmap_entries, 12703 bool pageable) 12704 { 12705 struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list; 12706 12707 if (unmap_entries) { 12708 for (int i = 0; i < entry_list->kme_list_index; i++) { 12709 kern_return_t ret; 12710 ret = vm_unmap_kcfileset_segment( 12711 &(entry_list->kme_list[i].me_start), 12712 entry_list->kme_list[i].me_size); 12713 assert(ret == KERN_SUCCESS); 12714 } 12715 12716 PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary); 12717 } 12718 12719 kfree(entry_list, sizeof(struct kcfileset_map_entry_list) + 12720 (sizeof(struct kcfileset_map_entry) * KCFILESET_MAP_ENTRY_MAX)); 12721 } 12722 12723 /********************************************************************* 12724 * Mechanism to map kext segment. 12725 *********************************************************************/ 12726 12727 kern_return_t 12728 vm_map_kcfileset_segment( 12729 vm_map_offset_t *start, 12730 vm_map_offset_t size, 12731 void *control, 12732 vm_object_offset_t fileoffset, 12733 vm_prot_t max_prot) 12734 { 12735 vm_map_kernel_flags_t vmk_flags; 12736 vmk_flags.vmkf_no_copy_on_read = 1; 12737 vmk_flags.vmkf_cs_enforcement = 0; 12738 vmk_flags.vmkf_cs_enforcement_override = 1; 12739 kern_return_t ret; 12740 12741 /* Add Write to max prot to allow fixups */ 12742 max_prot = max_prot | VM_PROT_WRITE; 12743 12744 /* 12745 * Map the segments from file as COPY mappings to 12746 * make sure changes on disk to the file does not affect 12747 * mapped segments. 12748 */ 12749 ret = vm_map_enter_mem_object_control( 12750 g_kext_map, 12751 start, 12752 size, 12753 (mach_vm_offset_t)0, 12754 VM_FLAGS_FIXED, 12755 vmk_flags, 12756 VM_KERN_MEMORY_OSKEXT, 12757 (memory_object_control_t)control, 12758 fileoffset, 12759 TRUE, /* copy */ 12760 (VM_PROT_READ | VM_PROT_WRITE), max_prot, 12761 VM_INHERIT_NONE); 12762 12763 return ret; 12764 } 12765 12766 kern_return_t 12767 vm_unmap_kcfileset_segment( 12768 vm_map_offset_t *start, 12769 vm_map_offset_t size) 12770 { 12771 return mach_vm_deallocate(g_kext_map, *start, size); 12772 } 12773 12774 #endif //(__x86_64__) || defined(__i386__) 12775 12776 /********************************************************************* 12777 * Assumes sKextLock is held. 12778 *********************************************************************/ 12779 /* static */ 12780 OSReturn 12781 OSKext::validateKCFileSetUUID( 12782 OSDictionary *infoDict, 12783 kc_kind_t type) 12784 { 12785 OSReturn ret = kOSReturnSuccess; 12786 12787 if (!kernelcache_uuid_valid) { 12788 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12789 "validateKCFileSetUUID Boot KC UUID was not set at boot."); 12790 ret = kOSKextReturnInvalidArgument; 12791 goto finish; 12792 } 12793 ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey); 12794 if (ret != 0) { 12795 goto finish; 12796 } 12797 12798 #if defined(__x86_64__) || defined(__i386__) 12799 /* Check if the Aux KC is prelinked to correct Pageable KC */ 12800 if (type == KCKindAuxiliary) { 12801 if (!pageablekc_uuid_valid) { 12802 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12803 "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC."); 12804 ret = kOSKextReturnInvalidArgument; 12805 goto finish; 12806 } 12807 ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey); 12808 if (ret != 0) { 12809 goto finish; 12810 } 12811 } 12812 #endif //(__x86_64__) || defined(__i386__) 12813 12814 printf("KextLog: Collection UUID matches with loaded KCs.\n"); 12815 finish: 12816 return ret; 12817 } 12818 12819 /********************************************************************* 12820 * Assumes sKextLock is held. 12821 *********************************************************************/ 12822 /* static */ 12823 OSReturn 12824 OSKext::validateKCUUIDfromPrelinkInfo( 12825 uuid_t *loaded_kcuuid, 12826 kc_kind_t type, 12827 OSDictionary *infoDict, 12828 const char *uuid_key) 12829 { 12830 /* extract the UUID from the dictionary */ 12831 OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key)); 12832 if (!prelinkinfoKCUUID) { 12833 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12834 "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key); 12835 return kOSKextReturnInvalidArgument; 12836 } 12837 12838 if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) { 12839 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12840 "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength()); 12841 return kOSKextReturnInvalidArgument; 12842 } 12843 12844 if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), 12845 prelinkinfoKCUUID->getLength())) { 12846 OSData *info_dict_uuid; 12847 uuid_string_t info_dict_uuid_str = {}; 12848 uuid_string_t expected_uuid_str = {}; 12849 uuid_string_t given_uuid_str = {}; 12850 uuid_t given_uuid; 12851 12852 /* extract the KC UUID from the dictionary */ 12853 info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey)); 12854 if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) { 12855 uuid_t tmp_uuid; 12856 memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid)); 12857 uuid_unparse(tmp_uuid, info_dict_uuid_str); 12858 } 12859 12860 uuid_unparse(*loaded_kcuuid, expected_uuid_str); 12861 memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid)); 12862 uuid_unparse(given_uuid, given_uuid_str); 12863 12864 printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key, 12865 given_uuid_str, expected_uuid_str, info_dict_uuid_str); 12866 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 12867 "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key, 12868 given_uuid_str, expected_uuid_str, info_dict_uuid_str); 12869 if (type == KCKindPageable && sPanicOnKCMismatch) { 12870 panic("System KC UUID %s linked against %s, but %s is loaded", 12871 info_dict_uuid_str, given_uuid_str, expected_uuid_str); 12872 } 12873 return kOSKextReturnInvalidArgument; 12874 } 12875 12876 return 0; 12877 } 12878 12879 /********************************************************************* 12880 * Assumes sKextLock is held. 12881 *********************************************************************/ 12882 /* static */ 12883 OSReturn 12884 OSKext::dispatchResource(OSDictionary * requestDict) 12885 { 12886 OSReturn result = kOSReturnError; 12887 OSSharedPtr<OSDictionary> callbackRecord; 12888 OSNumber * requestTag = NULL; // do not release 12889 OSNumber * requestResult = NULL; // do not release 12890 OSData * dataObj = NULL; // do not release 12891 uint32_t dataLength = 0; 12892 const void * dataPtr = NULL; // do not free 12893 OSData * callbackWrapper = NULL; // do not release 12894 OSKextRequestResourceCallback callback = NULL; 12895 OSData * contextWrapper = NULL; // do not release 12896 void * context = NULL; // do not free 12897 OSSharedPtr<OSKext> callbackKext; 12898 12899 /* Get the args from the request. Right now we need the tag 12900 * to look up the callback record, and the result for invoking the callback. 12901 */ 12902 requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 12903 kKextRequestArgumentRequestTagKey)); 12904 requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict, 12905 kKextRequestArgumentResultKey)); 12906 if (!requestTag || !requestResult) { 12907 result = kOSKextReturnInvalidArgument; 12908 goto finish; 12909 } 12910 12911 /* Look for a callback record matching this request's tag. 12912 */ 12913 result = dequeueCallbackForRequestTag(requestTag, callbackRecord); 12914 if (result != kOSReturnSuccess) { 12915 goto finish; 12916 } 12917 12918 /***** 12919 * Get the context pointer of the callback record (if there is one). 12920 */ 12921 contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord.get(), 12922 kKextRequestArgumentContextKey)); 12923 context = _OSKextExtractPointer(contextWrapper); 12924 if (contextWrapper && !context) { 12925 goto finish; 12926 } 12927 12928 callbackWrapper = OSDynamicCast(OSData, 12929 _OSKextGetRequestArgument(callbackRecord.get(), 12930 kKextRequestArgumentCallbackKey)); 12931 callback = _OSKextExtractCallbackPointer(callbackWrapper); 12932 if (!callback) { 12933 goto finish; 12934 } 12935 12936 /* Check for a data obj. We might not have one and that's ok, that means 12937 * we didn't find the requested resource, and we still have to tell the 12938 * caller that via the callback. 12939 */ 12940 dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict, 12941 kKextRequestArgumentValueKey)); 12942 if (dataObj) { 12943 dataPtr = dataObj->getBytesNoCopy(); 12944 dataLength = dataObj->getLength(); 12945 } 12946 12947 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback); 12948 if (!callbackKext) { 12949 OSKextLog(/* kext */ NULL, 12950 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12951 "Can't invoke callback for resource request; "); 12952 goto finish; 12953 } 12954 if (!callbackKext->flags.starting && !callbackKext->flags.started) { 12955 OSKextLog(/* kext */ NULL, 12956 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 12957 "Can't invoke kext resource callback; "); 12958 goto finish; 12959 } 12960 12961 (void)callback(requestTag->unsigned32BitValue(), 12962 (OSReturn)requestResult->unsigned32BitValue(), 12963 dataPtr, dataLength, context); 12964 12965 result = kOSReturnSuccess; 12966 12967 finish: 12968 return result; 12969 } 12970 12971 /********************************************************************* 12972 * Assumes sKextLock is held. 12973 *********************************************************************/ 12974 /* static */ 12975 OSReturn 12976 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict) 12977 { 12978 OSSharedPtr<OSDictionary> missingIDs; 12979 OSArray *bundleIDList = NULL; // do not release 12980 12981 bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument( 12982 requestDict, kKextRequestArgumentMissingBundleIDs)); 12983 if (!bundleIDList) { 12984 return kOSKextReturnInvalidArgument; 12985 } 12986 12987 missingIDs = OSDictionary::withCapacity(bundleIDList->getCount()); 12988 if (!missingIDs) { 12989 return kOSKextReturnNoMemory; 12990 } 12991 12992 uint32_t count, i; 12993 count = bundleIDList->getCount(); 12994 for (i = 0; i < count; i++) { 12995 OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i)); 12996 if (thisID) { 12997 missingIDs->setObject(thisID, kOSBooleanFalse); 12998 } 12999 } 13000 13001 sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain); 13002 13003 return kOSReturnSuccess; 13004 } 13005 13006 /********************************************************************* 13007 * Assumes sKextLock is held. 13008 *********************************************************************/ 13009 /* static */ 13010 OSReturn 13011 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict) 13012 { 13013 bool loadable = true; 13014 if (!kextIdentifier) { 13015 return kOSKextReturnInvalidArgument; 13016 } 13017 13018 if (requestDict) { 13019 OSBoolean *loadableArg; 13020 loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument( 13021 requestDict, kKextRequestArgumentBundleAvailability)); 13022 /* If we find the "Bundle Available" arg, and it's false, then 13023 * mark the bundle ID as _not_ loadable 13024 */ 13025 if (loadableArg && !loadableArg->getValue()) { 13026 loadable = false; 13027 } 13028 } 13029 13030 if (!sNonLoadableKextsByID) { 13031 sNonLoadableKextsByID = OSDictionary::withCapacity(1); 13032 } 13033 13034 sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable)); 13035 13036 OSKextLog(/* kext */ NULL, 13037 kOSKextLogBasicLevel | kOSKextLogIPCFlag, 13038 "KextLog: AuxKC bundle %s marked as %s", 13039 kextIdentifier->getCStringNoCopy(), 13040 (loadable ? "loadable" : "NOT loadable")); 13041 13042 return kOSReturnSuccess; 13043 } 13044 13045 /********************************************************************* 13046 *********************************************************************/ 13047 /* static */ 13048 void 13049 OSKext::invokeRequestCallback( 13050 OSDictionary * callbackRecord, 13051 OSReturn callbackResult) 13052 { 13053 OSString * predicate = _OSKextGetRequestPredicate(callbackRecord); 13054 OSSharedPtr<OSNumber> resultNum; 13055 13056 if (!predicate) { 13057 goto finish; 13058 } 13059 13060 resultNum = OSNumber::withNumber((long long unsigned int)callbackResult, 13061 8 * sizeof(callbackResult)); 13062 if (!resultNum) { 13063 goto finish; 13064 } 13065 13066 /* Insert the result into the callback record and dispatch it as if it 13067 * were the reply coming down from user space. 13068 */ 13069 _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey, 13070 resultNum.get()); 13071 13072 if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) { 13073 /* This removes the pending callback record. 13074 */ 13075 OSKext::dispatchResource(callbackRecord); 13076 } 13077 13078 finish: 13079 return; 13080 } 13081 13082 /********************************************************************* 13083 * Assumes sKextLock is held. 13084 *********************************************************************/ 13085 /* static */ 13086 OSReturn 13087 OSKext::cancelRequest( 13088 OSKextRequestTag requestTag, 13089 void ** contextOut) 13090 { 13091 OSReturn result = kOSKextReturnNoMemory; 13092 OSSharedPtr<OSDictionary> callbackRecord; 13093 OSData * contextWrapper = NULL; // do not release 13094 13095 IORecursiveLockLock(sKextLock); 13096 result = OSKext::dequeueCallbackForRequestTag(requestTag, 13097 callbackRecord); 13098 IORecursiveLockUnlock(sKextLock); 13099 13100 if (result == kOSReturnSuccess && contextOut) { 13101 contextWrapper = OSDynamicCast(OSData, 13102 _OSKextGetRequestArgument(callbackRecord.get(), 13103 kKextRequestArgumentContextKey)); 13104 *contextOut = _OSKextExtractPointer(contextWrapper); 13105 } 13106 13107 return result; 13108 } 13109 13110 /********************************************************************* 13111 * Assumes sKextLock is held. 13112 *********************************************************************/ 13113 void 13114 OSKext::invokeOrCancelRequestCallbacks( 13115 OSReturn callbackResult, 13116 bool invokeFlag) 13117 { 13118 unsigned int count, i; 13119 13120 count = sRequestCallbackRecords->getCount(); 13121 if (!count) { 13122 goto finish; 13123 } 13124 13125 i = count - 1; 13126 do { 13127 OSDictionary * request = OSDynamicCast(OSDictionary, 13128 sRequestCallbackRecords->getObject(i)); 13129 13130 if (!request) { 13131 continue; 13132 } 13133 OSData * callbackWrapper = OSDynamicCast(OSData, 13134 _OSKextGetRequestArgument(request, 13135 kKextRequestArgumentCallbackKey)); 13136 13137 if (!callbackWrapper) { 13138 sRequestCallbackRecords->removeObject(i); 13139 continue; 13140 } 13141 13142 vm_address_t callbackAddress = (vm_address_t) 13143 ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer); 13144 13145 if ((kmod_info->address <= callbackAddress) && 13146 (callbackAddress < (kmod_info->address + kmod_info->size))) { 13147 if (invokeFlag) { 13148 /* This removes the callback record. 13149 */ 13150 invokeRequestCallback(request, callbackResult); 13151 } else { 13152 sRequestCallbackRecords->removeObject(i); 13153 } 13154 } 13155 } while (i--); 13156 13157 finish: 13158 return; 13159 } 13160 13161 /********************************************************************* 13162 * Assumes sKextLock is held. 13163 *********************************************************************/ 13164 uint32_t 13165 OSKext::countRequestCallbacks(void) 13166 { 13167 uint32_t result = 0; 13168 unsigned int count, i; 13169 13170 count = sRequestCallbackRecords->getCount(); 13171 if (!count) { 13172 goto finish; 13173 } 13174 13175 i = count - 1; 13176 do { 13177 OSDictionary * request = OSDynamicCast(OSDictionary, 13178 sRequestCallbackRecords->getObject(i)); 13179 13180 if (!request) { 13181 continue; 13182 } 13183 OSData * callbackWrapper = OSDynamicCast(OSData, 13184 _OSKextGetRequestArgument(request, 13185 kKextRequestArgumentCallbackKey)); 13186 13187 if (!callbackWrapper) { 13188 continue; 13189 } 13190 13191 vm_address_t callbackAddress = (vm_address_t) 13192 ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer); 13193 13194 if ((kmod_info->address <= callbackAddress) && 13195 (callbackAddress < (kmod_info->address + kmod_info->size))) { 13196 result++; 13197 } 13198 } while (i--); 13199 13200 finish: 13201 return result; 13202 } 13203 13204 /********************************************************************* 13205 *********************************************************************/ 13206 static OSReturn 13207 _OSKextCreateRequest( 13208 const char * predicate, 13209 OSSharedPtr<OSDictionary> & requestR) 13210 { 13211 OSReturn result = kOSKextReturnNoMemory; 13212 OSSharedPtr<OSDictionary> request; 13213 13214 request = OSDictionary::withCapacity(2); 13215 if (!request) { 13216 goto finish; 13217 } 13218 result = _OSDictionarySetCStringValue(request.get(), 13219 kKextRequestPredicateKey, predicate); 13220 if (result != kOSReturnSuccess) { 13221 goto finish; 13222 } 13223 result = kOSReturnSuccess; 13224 13225 finish: 13226 if (result == kOSReturnSuccess) { 13227 requestR = os::move(request); 13228 } 13229 13230 return result; 13231 } 13232 13233 /********************************************************************* 13234 *********************************************************************/ 13235 static OSString * 13236 _OSKextGetRequestPredicate(OSDictionary * requestDict) 13237 { 13238 return OSDynamicCast(OSString, 13239 requestDict->getObject(kKextRequestPredicateKey)); 13240 } 13241 13242 /********************************************************************* 13243 *********************************************************************/ 13244 static OSObject * 13245 _OSKextGetRequestArgument( 13246 OSDictionary * requestDict, 13247 const char * argName) 13248 { 13249 OSDictionary * args = OSDynamicCast(OSDictionary, 13250 requestDict->getObject(kKextRequestArgumentsKey)); 13251 if (args) { 13252 return args->getObject(argName); 13253 } 13254 return NULL; 13255 } 13256 13257 /********************************************************************* 13258 *********************************************************************/ 13259 static bool 13260 _OSKextSetRequestArgument( 13261 OSDictionary * requestDict, 13262 const char * argName, 13263 OSObject * value) 13264 { 13265 OSDictionary * args = OSDynamicCast(OSDictionary, 13266 requestDict->getObject(kKextRequestArgumentsKey)); 13267 OSSharedPtr<OSDictionary> newArgs; 13268 if (!args) { 13269 newArgs = OSDictionary::withCapacity(2); 13270 args = newArgs.get(); 13271 if (!args) { 13272 goto finish; 13273 } 13274 requestDict->setObject(kKextRequestArgumentsKey, args); 13275 } 13276 if (args) { 13277 return args->setObject(argName, value); 13278 } 13279 finish: 13280 return false; 13281 } 13282 13283 /********************************************************************* 13284 *********************************************************************/ 13285 static void * 13286 _OSKextExtractPointer(OSData * wrapper) 13287 { 13288 void * result = NULL; 13289 const void * resultPtr = NULL; 13290 13291 if (!wrapper) { 13292 goto finish; 13293 } 13294 resultPtr = wrapper->getBytesNoCopy(); 13295 result = *(void **)resultPtr; 13296 finish: 13297 return result; 13298 } 13299 13300 /********************************************************************* 13301 *********************************************************************/ 13302 static OSKextRequestResourceCallback 13303 _OSKextExtractCallbackPointer(OSData * wrapper) 13304 { 13305 OSKextRequestResourceCallback result = NULL; 13306 const void * resultPtr = NULL; 13307 13308 if (!wrapper) { 13309 goto finish; 13310 } 13311 resultPtr = wrapper->getBytesNoCopy(); 13312 result = *(OSKextRequestResourceCallback *)resultPtr; 13313 finish: 13314 return result; 13315 } 13316 13317 13318 /********************************************************************* 13319 *********************************************************************/ 13320 static OSReturn 13321 _OSDictionarySetCStringValue( 13322 OSDictionary * dict, 13323 const char * cKey, 13324 const char * cValue) 13325 { 13326 OSReturn result = kOSKextReturnNoMemory; 13327 OSSharedPtr<const OSSymbol> key; 13328 OSSharedPtr<OSString> value; 13329 13330 key = OSSymbol::withCString(cKey); 13331 value = OSString::withCString(cValue); 13332 if (!key || !value) { 13333 goto finish; 13334 } 13335 if (dict->setObject(key.get(), value.get())) { 13336 result = kOSReturnSuccess; 13337 } 13338 13339 finish: 13340 return result; 13341 } 13342 13343 /********************************************************************* 13344 *********************************************************************/ 13345 static bool 13346 _OSArrayContainsCString( 13347 OSArray * array, 13348 const char * cString) 13349 { 13350 bool result = false; 13351 OSSharedPtr<const OSSymbol> symbol; 13352 uint32_t count, i; 13353 13354 if (!array || !cString) { 13355 goto finish; 13356 } 13357 13358 symbol = OSSymbol::withCStringNoCopy(cString); 13359 if (!symbol) { 13360 goto finish; 13361 } 13362 13363 count = array->getCount(); 13364 for (i = 0; i < count; i++) { 13365 OSObject * thisObject = array->getObject(i); 13366 if (symbol->isEqualTo(thisObject)) { 13367 result = true; 13368 goto finish; 13369 } 13370 } 13371 13372 finish: 13373 return result; 13374 } 13375 13376 #if CONFIG_KXLD 13377 /********************************************************************* 13378 * We really only care about boot / system start up related kexts. 13379 * We return true if we're less than REBUILD_MAX_TIME since start up, 13380 * otherwise return false. 13381 *********************************************************************/ 13382 bool 13383 _OSKextInPrelinkRebuildWindow(void) 13384 { 13385 static bool outside_the_window = false; 13386 AbsoluteTime my_abstime; 13387 UInt64 my_ns; 13388 SInt32 my_secs; 13389 13390 if (outside_the_window) { 13391 return false; 13392 } 13393 clock_get_uptime(&my_abstime); 13394 absolutetime_to_nanoseconds(my_abstime, &my_ns); 13395 my_secs = (SInt32)(my_ns / NSEC_PER_SEC); 13396 if (my_secs > REBUILD_MAX_TIME) { 13397 outside_the_window = true; 13398 return false; 13399 } 13400 return true; 13401 } 13402 #endif /* CONFIG_KXLD */ 13403 13404 /********************************************************************* 13405 *********************************************************************/ 13406 bool 13407 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID ) 13408 { 13409 int unLoadedCount, i; 13410 bool result = false; 13411 13412 IORecursiveLockLock(sKextLock); 13413 13414 if (sUnloadedPrelinkedKexts == NULL) { 13415 goto finish; 13416 } 13417 unLoadedCount = sUnloadedPrelinkedKexts->getCount(); 13418 if (unLoadedCount == 0) { 13419 goto finish; 13420 } 13421 13422 for (i = 0; i < unLoadedCount; i++) { 13423 const OSSymbol * myBundleID; // do not release 13424 13425 myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i)); 13426 if (!myBundleID) { 13427 continue; 13428 } 13429 if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) { 13430 result = true; 13431 break; 13432 } 13433 } 13434 finish: 13435 IORecursiveLockUnlock(sKextLock); 13436 return result; 13437 } 13438 13439 #if PRAGMA_MARK 13440 #pragma mark Personalities (IOKit Drivers) 13441 #endif 13442 /********************************************************************* 13443 *********************************************************************/ 13444 /* static */ 13445 OSSharedPtr<OSArray> 13446 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag) 13447 { 13448 OSSharedPtr<OSArray> result; 13449 OSSharedPtr<OSCollectionIterator> kextIterator; 13450 OSSharedPtr<OSArray> personalities; 13451 13452 OSString * kextID = NULL; // do not release 13453 OSKext * theKext = NULL; // do not release 13454 13455 IORecursiveLockLock(sKextLock); 13456 13457 /* Let's conservatively guess that any given kext has around 3 13458 * personalities for now. 13459 */ 13460 result = OSArray::withCapacity(sKextsByID->getCount() * 3); 13461 if (!result) { 13462 goto finish; 13463 } 13464 13465 kextIterator = OSCollectionIterator::withCollection(sKextsByID.get()); 13466 if (!kextIterator) { 13467 goto finish; 13468 } 13469 13470 while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) { 13471 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID)); 13472 if (theKext->flags.requireExplicitLoad) { 13473 OSKextLog(theKext, 13474 kOSKextLogDebugLevel | 13475 kOSKextLogLoadFlag, 13476 "Kext %s requires an explicit kextload; " 13477 "omitting its personalities.", 13478 theKext->getIdentifierCString()); 13479 } else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) { 13480 personalities = theKext->copyPersonalitiesArray(); 13481 if (!personalities) { 13482 continue; 13483 } 13484 result->merge(personalities.get()); 13485 } else { 13486 // xxx - check for better place to put this log msg 13487 OSKextLog(theKext, 13488 kOSKextLogWarningLevel | 13489 kOSKextLogLoadFlag, 13490 "Kext %s is not loadable during safe boot; " 13491 "omitting its personalities.", 13492 theKext->getIdentifierCString()); 13493 } 13494 } 13495 13496 finish: 13497 IORecursiveLockUnlock(sKextLock); 13498 13499 return result; 13500 } 13501 13502 /********************************************************************* 13503 *********************************************************************/ 13504 /* static */ 13505 void 13506 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching) 13507 { 13508 int numPersonalities = 0; 13509 13510 OSKextLog(/* kext */ NULL, 13511 kOSKextLogStepLevel | 13512 kOSKextLogLoadFlag, 13513 "Sending all eligible registered kexts' personalities " 13514 "to the IOCatalogue %s.", 13515 startMatching ? "and starting matching" : "but not starting matching"); 13516 13517 OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities( 13518 /* filterSafeBootFlag */ true); 13519 13520 if (personalities) { 13521 gIOCatalogue->addDrivers(personalities.get(), startMatching); 13522 numPersonalities = personalities->getCount(); 13523 } 13524 13525 OSKextLog(/* kext */ NULL, 13526 kOSKextLogStepLevel | 13527 kOSKextLogLoadFlag, 13528 "%d kext personalit%s sent to the IOCatalogue; %s.", 13529 numPersonalities, numPersonalities > 0 ? "ies" : "y", 13530 startMatching ? "matching started" : "matching not started"); 13531 return; 13532 } 13533 13534 /********************************************************************* 13535 * Do not make a deep copy, just convert the IOKitPersonalities dict 13536 * to an array for sending to the IOCatalogue. 13537 *********************************************************************/ 13538 OSSharedPtr<OSArray> 13539 OSKext::copyPersonalitiesArray(void) 13540 { 13541 OSSharedPtr<OSArray> result; 13542 OSDictionary * personalities = NULL; // do not release 13543 OSSharedPtr<OSCollectionIterator> personalitiesIterator; 13544 13545 OSString * personalityName = NULL; // do not release 13546 OSString * personalityBundleIdentifier = NULL; // do not release 13547 13548 personalities = OSDynamicCast(OSDictionary, 13549 getPropertyForHostArch(kIOKitPersonalitiesKey)); 13550 if (!personalities) { 13551 goto finish; 13552 } 13553 13554 result = OSArray::withCapacity(personalities->getCount()); 13555 if (!result) { 13556 goto finish; 13557 } 13558 13559 personalitiesIterator = 13560 OSCollectionIterator::withCollection(personalities); 13561 if (!personalitiesIterator) { 13562 goto finish; 13563 } 13564 while ((personalityName = OSDynamicCast(OSString, 13565 personalitiesIterator->getNextObject()))) { 13566 OSDictionary * personality = OSDynamicCast(OSDictionary, 13567 personalities->getObject(personalityName)); 13568 13569 /****** 13570 * If the personality doesn't have a CFBundleIdentifier, or if it 13571 * differs from the kext's, insert the kext's ID so we can find it. 13572 * The publisher ID is used to remove personalities from bundles 13573 * correctly. 13574 */ 13575 personalityBundleIdentifier = OSDynamicCast(OSString, 13576 personality->getObject(kCFBundleIdentifierKey)); 13577 13578 if (!personalityBundleIdentifier) { 13579 personality->setObject(kCFBundleIdentifierKey, bundleID.get()); 13580 } else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) { 13581 personality->setObject(kIOPersonalityPublisherKey, bundleID.get()); 13582 } 13583 13584 result->setObject(personality); 13585 } 13586 13587 finish: 13588 return result; 13589 } 13590 13591 /********************************************************************* 13592 * Might want to change this to a bool return? 13593 *********************************************************************/ 13594 OSReturn 13595 OSKext::sendPersonalitiesToCatalog( 13596 bool startMatching, 13597 OSArray * personalityNames) 13598 { 13599 OSReturn result = kOSReturnSuccess; 13600 OSSharedPtr<OSArray> personalitiesToSend; 13601 OSDictionary * kextPersonalities = NULL; // do not release 13602 int count, i; 13603 13604 if (!sLoadEnabled) { 13605 OSKextLog(this, 13606 kOSKextLogErrorLevel | 13607 kOSKextLogLoadFlag, 13608 "Kext loading is disabled (attempt to start matching for kext %s).", 13609 getIdentifierCString()); 13610 result = kOSKextReturnDisabled; 13611 goto finish; 13612 } 13613 13614 if (sSafeBoot && !isLoadableInSafeBoot()) { 13615 OSKextLog(this, 13616 kOSKextLogErrorLevel | 13617 kOSKextLogLoadFlag, 13618 "Kext %s is not loadable during safe boot; " 13619 "not sending personalities to the IOCatalogue.", 13620 getIdentifierCString()); 13621 result = kOSKextReturnNotLoadable; 13622 goto finish; 13623 } 13624 13625 if (!personalityNames || !personalityNames->getCount()) { 13626 personalitiesToSend = copyPersonalitiesArray(); 13627 } else { 13628 kextPersonalities = OSDynamicCast(OSDictionary, 13629 getPropertyForHostArch(kIOKitPersonalitiesKey)); 13630 if (!kextPersonalities || !kextPersonalities->getCount()) { 13631 // not an error 13632 goto finish; 13633 } 13634 personalitiesToSend = OSArray::withCapacity(0); 13635 if (!personalitiesToSend) { 13636 result = kOSKextReturnNoMemory; 13637 goto finish; 13638 } 13639 count = personalityNames->getCount(); 13640 for (i = 0; i < count; i++) { 13641 OSString * name = OSDynamicCast(OSString, 13642 personalityNames->getObject(i)); 13643 if (!name) { 13644 continue; 13645 } 13646 OSDictionary * personality = OSDynamicCast(OSDictionary, 13647 kextPersonalities->getObject(name)); 13648 if (personality) { 13649 personalitiesToSend->setObject(personality); 13650 } 13651 } 13652 } 13653 if (personalitiesToSend) { 13654 unsigned numPersonalities = personalitiesToSend->getCount(); 13655 OSKextLog(this, 13656 kOSKextLogStepLevel | 13657 kOSKextLogLoadFlag, 13658 "Kext %s sending %d personalit%s to the IOCatalogue%s.", 13659 getIdentifierCString(), 13660 numPersonalities, 13661 numPersonalities > 1 ? "ies" : "y", 13662 startMatching ? " and starting matching" : " but not starting matching"); 13663 gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching); 13664 } 13665 finish: 13666 return result; 13667 } 13668 13669 /********************************************************************* 13670 * xxx - We should allow removing the kext's declared personalities, 13671 * xxx - even with other bundle identifiers. 13672 *********************************************************************/ 13673 void 13674 OSKext::removePersonalitiesFromCatalog(void) 13675 { 13676 OSSharedPtr<OSDictionary> personality; 13677 13678 personality = OSDictionary::withCapacity(1); 13679 if (!personality) { 13680 goto finish; 13681 } 13682 personality->setObject(kCFBundleIdentifierKey, getIdentifier()); 13683 13684 OSKextLog(this, 13685 kOSKextLogStepLevel | 13686 kOSKextLogLoadFlag, 13687 "Kext %s removing all personalities naming it from the IOCatalogue.", 13688 getIdentifierCString()); 13689 13690 /* Have the IOCatalog remove all personalities matching this kext's 13691 * bundle ID and trigger matching anew. 13692 */ 13693 gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true); 13694 13695 finish: 13696 return; 13697 } 13698 13699 13700 #if PRAGMA_MARK 13701 #pragma mark Logging 13702 #endif 13703 /********************************************************************* 13704 * Do not call any function that takes sKextLock here! 13705 *********************************************************************/ 13706 /* static */ 13707 OSKextLogSpec 13708 OSKext::setUserSpaceLogFilter( 13709 OSKextLogSpec newUserLogFilter, 13710 bool captureFlag) 13711 { 13712 OSKextLogSpec result; 13713 bool allocError = false; 13714 13715 /* Do not call any function that takes sKextLoggingLock during 13716 * this critical block. That means do logging after. 13717 */ 13718 IOLockLock(sKextLoggingLock); 13719 13720 result = sUserSpaceKextLogFilter; 13721 sUserSpaceKextLogFilter = newUserLogFilter; 13722 13723 if (newUserLogFilter && captureFlag && 13724 !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) { 13725 // xxx - do some measurements for a good initial capacity? 13726 sUserSpaceLogSpecArray = OSArray::withCapacity(0); 13727 sUserSpaceLogMessageArray = OSArray::withCapacity(0); 13728 13729 if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) { 13730 allocError = true; 13731 } 13732 } 13733 13734 IOLockUnlock(sKextLoggingLock); 13735 13736 /* If the config flag itself is changing, log the state change 13737 * going both ways, before setting up the user-space log arrays, 13738 * so that this is only logged in the kernel. 13739 */ 13740 if (result != newUserLogFilter) { 13741 OSKextLog(/* kext */ NULL, 13742 kOSKextLogDebugLevel | 13743 kOSKextLogGeneralFlag, 13744 "User-space log flags changed from 0x%x to 0x%x.", 13745 result, newUserLogFilter); 13746 } 13747 if (allocError) { 13748 OSKextLog(/* kext */ NULL, 13749 kOSKextLogErrorLevel | 13750 kOSKextLogGeneralFlag, 13751 "Failed to allocate user-space log message arrays."); 13752 } 13753 13754 return result; 13755 } 13756 13757 /********************************************************************* 13758 * Do not call any function that takes sKextLock here! 13759 *********************************************************************/ 13760 /* static */ 13761 OSSharedPtr<OSArray> 13762 OSKext::clearUserSpaceLogFilter(void) 13763 { 13764 OSSharedPtr<OSArray> result; 13765 OSKextLogSpec oldLogFilter; 13766 OSKextLogSpec newLogFilter = kOSKextLogSilentFilter; 13767 13768 /* Do not call any function that takes sKextLoggingLock during 13769 * this critical block. That means do logging after. 13770 */ 13771 IOLockLock(sKextLoggingLock); 13772 13773 result = OSArray::withCapacity(2); 13774 if (result) { 13775 result->setObject(sUserSpaceLogSpecArray.get()); 13776 result->setObject(sUserSpaceLogMessageArray.get()); 13777 } 13778 sUserSpaceLogSpecArray.reset(); 13779 sUserSpaceLogMessageArray.reset(); 13780 13781 oldLogFilter = sUserSpaceKextLogFilter; 13782 sUserSpaceKextLogFilter = newLogFilter; 13783 13784 IOLockUnlock(sKextLoggingLock); 13785 13786 /* If the config flag itself is changing, log the state change 13787 * going both ways, after tearing down the user-space log 13788 * arrays, so this is only logged within the kernel. 13789 */ 13790 if (oldLogFilter != newLogFilter) { 13791 OSKextLog(/* kext */ NULL, 13792 kOSKextLogDebugLevel | 13793 kOSKextLogGeneralFlag, 13794 "User-space log flags changed from 0x%x to 0x%x.", 13795 oldLogFilter, newLogFilter); 13796 } 13797 13798 return result; 13799 } 13800 13801 13802 /********************************************************************* 13803 * Do not call any function that takes sKextLock here! 13804 *********************************************************************/ 13805 /* static */ 13806 OSKextLogSpec 13807 OSKext::getUserSpaceLogFilter(void) 13808 { 13809 OSKextLogSpec result; 13810 13811 IOLockLock(sKextLoggingLock); 13812 result = sUserSpaceKextLogFilter; 13813 IOLockUnlock(sKextLoggingLock); 13814 13815 return result; 13816 } 13817 13818 /********************************************************************* 13819 * This function is called by OSMetaClass during kernel C++ setup. 13820 * Be careful what you access here; assume only OSKext::initialize() 13821 * has been called. 13822 * 13823 * Do not call any function that takes sKextLock here! 13824 *********************************************************************/ 13825 #define VTRESET "\033[0m" 13826 13827 #define VTBOLD "\033[1m" 13828 #define VTUNDER "\033[4m" 13829 13830 #define VTRED "\033[31m" 13831 #define VTGREEN "\033[32m" 13832 #define VTYELLOW "\033[33m" 13833 #define VTBLUE "\033[34m" 13834 #define VTMAGENTA "\033[35m" 13835 #define VTCYAN "\033[36m" 13836 13837 inline const char * 13838 colorForFlags(OSKextLogSpec flags) 13839 { 13840 OSKextLogSpec logLevel = flags & kOSKextLogLevelMask; 13841 13842 switch (logLevel) { 13843 case kOSKextLogErrorLevel: 13844 return VTRED VTBOLD; 13845 case kOSKextLogWarningLevel: 13846 return VTRED; 13847 case kOSKextLogBasicLevel: 13848 return VTYELLOW VTUNDER; 13849 case kOSKextLogProgressLevel: 13850 return VTYELLOW; 13851 case kOSKextLogStepLevel: 13852 return VTGREEN; 13853 case kOSKextLogDetailLevel: 13854 return VTCYAN; 13855 case kOSKextLogDebugLevel: 13856 return VTMAGENTA; 13857 default: 13858 return ""; // white 13859 } 13860 } 13861 13862 inline bool 13863 logSpecMatch( 13864 OSKextLogSpec msgLogSpec, 13865 OSKextLogSpec logFilter) 13866 { 13867 OSKextLogSpec filterKextGlobal = logFilter & kOSKextLogKextOrGlobalMask; 13868 OSKextLogSpec filterLevel = logFilter & kOSKextLogLevelMask; 13869 OSKextLogSpec filterFlags = logFilter & kOSKextLogFlagsMask; 13870 13871 OSKextLogSpec msgKextGlobal = msgLogSpec & kOSKextLogKextOrGlobalMask; 13872 OSKextLogSpec msgLevel = msgLogSpec & kOSKextLogLevelMask; 13873 OSKextLogSpec msgFlags = msgLogSpec & kOSKextLogFlagsMask; 13874 13875 /* Explicit messages always get logged. 13876 */ 13877 if (msgLevel == kOSKextLogExplicitLevel) { 13878 return true; 13879 } 13880 13881 /* Warnings and errors are logged regardless of the flags. 13882 */ 13883 if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) { 13884 return true; 13885 } 13886 13887 /* A verbose message that isn't for a logging-enabled kext and isn't global 13888 * does *not* get logged. 13889 */ 13890 if (!msgKextGlobal && !filterKextGlobal) { 13891 return false; 13892 } 13893 13894 /* Warnings and errors are logged regardless of the flags. 13895 * All other messages must fit the flags and 13896 * have a level at or below the filter. 13897 * 13898 */ 13899 if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) { 13900 return true; 13901 } 13902 return false; 13903 } 13904 13905 extern "C" { 13906 void 13907 OSKextLog( 13908 OSKext * aKext, 13909 OSKextLogSpec msgLogSpec, 13910 const char * format, ...) 13911 { 13912 va_list argList; 13913 13914 va_start(argList, format); 13915 OSKextVLog(aKext, msgLogSpec, format, argList); 13916 va_end(argList); 13917 } 13918 13919 void 13920 OSKextVLog( 13921 OSKext * aKext, 13922 OSKextLogSpec msgLogSpec, 13923 const char * format, 13924 va_list srcArgList) 13925 { 13926 extern int disableConsoleOutput; 13927 13928 bool logForKernel = false; 13929 bool logForUser = false; 13930 va_list argList; 13931 char stackBuffer[120]; 13932 uint32_t length = 0; 13933 char * allocBuffer = NULL; // must kfree 13934 OSSharedPtr<OSNumber> logSpecNum; 13935 OSSharedPtr<OSString> logString; 13936 char * buffer = stackBuffer; // do not free 13937 13938 IOLockLock(sKextLoggingLock); 13939 13940 /* Set the kext/global bit in the message spec if we have no 13941 * kext or if the kext requests logging. 13942 */ 13943 if (!aKext || aKext->flags.loggingEnabled) { 13944 msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask; 13945 } 13946 13947 logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter); 13948 if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 13949 logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter); 13950 } 13951 13952 if (!(logForKernel || logForUser)) { 13953 goto finish; 13954 } 13955 13956 /* No goto from here until past va_end()! 13957 */ 13958 va_copy(argList, srcArgList); 13959 length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList); 13960 va_end(argList); 13961 13962 if (length + 1 >= sizeof(stackBuffer)) { 13963 allocBuffer = (char *)kheap_alloc_tag(KHEAP_TEMP, 13964 length + 1, Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 13965 if (!allocBuffer) { 13966 goto finish; 13967 } 13968 13969 /* No goto from here until past va_end()! 13970 */ 13971 va_copy(argList, srcArgList); 13972 vsnprintf(allocBuffer, length + 1, format, argList); 13973 va_end(argList); 13974 13975 buffer = allocBuffer; 13976 } 13977 13978 /* If user space wants the log message, queue it up. 13979 */ 13980 if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) { 13981 logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec)); 13982 logString = OSString::withCString(buffer); 13983 if (logSpecNum && logString) { 13984 sUserSpaceLogSpecArray->setObject(logSpecNum.get()); 13985 sUserSpaceLogMessageArray->setObject(logString.get()); 13986 } 13987 } 13988 13989 /* Always log messages from the kernel according to the kernel's 13990 * log flags. 13991 */ 13992 if (logForKernel) { 13993 /* If we are in console mode and have a custom log filter, 13994 * colorize the log message. 13995 */ 13996 if (!disableConsoleOutput && sBootArgLogFilterFound) { 13997 const char * color = ""; // do not free 13998 color = colorForFlags(msgLogSpec); 13999 printf("%s%s%s\n", colorForFlags(msgLogSpec), 14000 buffer, color[0] ? VTRESET : ""); 14001 } else { 14002 printf("%s\n", buffer); 14003 } 14004 } 14005 14006 finish: 14007 IOLockUnlock(sKextLoggingLock); 14008 14009 if (allocBuffer) { 14010 kheap_free(KHEAP_TEMP, allocBuffer, (length + 1) * sizeof(char)); 14011 } 14012 return; 14013 } 14014 14015 #if KASLR_IOREG_DEBUG 14016 14017 #define IOLOG_INDENT( the_indention ) \ 14018 { \ 14019 int i; \ 14020 for ( i = 0; i < (the_indention); i++ ) { \ 14021 IOLog(" "); \ 14022 } \ 14023 } 14024 14025 extern vm_offset_t vm_kernel_stext; 14026 extern vm_offset_t vm_kernel_etext; 14027 extern mach_vm_offset_t kext_alloc_base; 14028 extern mach_vm_offset_t kext_alloc_max; 14029 14030 bool ScanForAddrInObject(OSObject * theObject, 14031 int indent ); 14032 14033 bool 14034 ScanForAddrInObject(OSObject * theObject, 14035 int indent) 14036 { 14037 const OSMetaClass * myTypeID; 14038 OSSharedPtr<OSCollectionIterator> myIter; 14039 OSSymbol * myKey; 14040 OSObject * myValue; 14041 bool myResult = false; 14042 14043 if (theObject == NULL) { 14044 IOLog("%s: theObject is NULL \n", 14045 __FUNCTION__); 14046 return myResult; 14047 } 14048 14049 myTypeID = OSTypeIDInst(theObject); 14050 14051 if (myTypeID == OSTypeID(OSDictionary)) { 14052 OSDictionary * myDictionary; 14053 14054 myDictionary = OSDynamicCast(OSDictionary, theObject); 14055 myIter = OSCollectionIterator::withCollection( myDictionary ); 14056 if (myIter == NULL) { 14057 return myResult; 14058 } 14059 14060 // !! reset the iterator 14061 myIter->reset(); 14062 14063 while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) { 14064 bool myTempResult; 14065 14066 myValue = myDictionary->getObject(myKey); 14067 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 14068 if (myTempResult) { 14069 // if we ever get a true result return true 14070 myResult = true; 14071 IOLOG_INDENT(indent); 14072 IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy()); 14073 } 14074 } 14075 14076 // !! release the iterator 14077 myIter.reset(); 14078 } else if (myTypeID == OSTypeID(OSArray)) { 14079 OSArray * myArray; 14080 14081 myArray = OSDynamicCast(OSArray, theObject); 14082 myIter = OSCollectionIterator::withCollection(myArray); 14083 if (myIter == NULL) { 14084 return myResult; 14085 } 14086 // !! reset the iterator 14087 myIter->reset(); 14088 14089 while ((myValue = myIter->getNextObject())) { 14090 bool myTempResult; 14091 myTempResult = ScanForAddrInObject(myValue, (indent + 4)); 14092 if (myTempResult) { 14093 // if we ever get a true result return true 14094 myResult = true; 14095 IOLOG_INDENT(indent); 14096 IOLog("OSArray: \n"); 14097 } 14098 } 14099 // !! release the iterator 14100 myIter.reset(); 14101 } else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) { 14102 // should we look for addresses in strings? 14103 } else if (myTypeID == OSTypeID(OSData)) { 14104 void * * myPtrPtr; 14105 unsigned int myLen; 14106 OSData * myDataObj; 14107 14108 myDataObj = OSDynamicCast(OSData, theObject); 14109 myPtrPtr = (void * *) myDataObj->getBytesNoCopy(); 14110 myLen = myDataObj->getLength(); 14111 14112 if (myPtrPtr && myLen && myLen > 7) { 14113 int i; 14114 int myPtrCount = (myLen / sizeof(void *)); 14115 14116 for (i = 0; i < myPtrCount; i++) { 14117 UInt64 numberValue = (UInt64) * (myPtrPtr); 14118 14119 if (kext_alloc_max != 0 && 14120 numberValue >= kext_alloc_base && 14121 numberValue < kext_alloc_max) { 14122 OSSharedPtr<OSKext> myKext; 14123 // IOLog("found OSData %p in kext map %p to %p \n", 14124 // *(myPtrPtr), 14125 // (void *) kext_alloc_base, 14126 // (void *) kext_alloc_max); 14127 14128 myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr)); 14129 if (myKext) { 14130 IOLog("found addr %p from an OSData obj within kext \"%s\" \n", 14131 *(myPtrPtr), 14132 myKext->getIdentifierCString()); 14133 } 14134 myResult = true; 14135 } 14136 if (vm_kernel_etext != 0 && 14137 numberValue >= vm_kernel_stext && 14138 numberValue < vm_kernel_etext) { 14139 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n", 14140 *(myPtrPtr), 14141 (void *) vm_kernel_stext, 14142 (void *) vm_kernel_etext); 14143 myResult = true; 14144 } 14145 myPtrPtr++; 14146 } 14147 } 14148 } else if (myTypeID == OSTypeID(OSBoolean)) { 14149 // do nothing here... 14150 } else if (myTypeID == OSTypeID(OSNumber)) { 14151 OSNumber * number = OSDynamicCast(OSNumber, theObject); 14152 14153 UInt64 numberValue = number->unsigned64BitValue(); 14154 14155 if (kext_alloc_max != 0 && 14156 numberValue >= kext_alloc_base && 14157 numberValue < kext_alloc_max) { 14158 OSSharedPtr<OSKext> myKext; 14159 IOLog("found OSNumber in kext map %p to %p \n", 14160 (void *) kext_alloc_base, 14161 (void *) kext_alloc_max); 14162 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 14163 14164 myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue ); 14165 if (myKext) { 14166 IOLog("found in kext \"%s\" \n", 14167 myKext->getIdentifierCString()); 14168 } 14169 14170 myResult = true; 14171 } 14172 if (vm_kernel_etext != 0 && 14173 numberValue >= vm_kernel_stext && 14174 numberValue < vm_kernel_etext) { 14175 IOLog("found OSNumber in kernel text segment %p to %p \n", 14176 (void *) vm_kernel_stext, 14177 (void *) vm_kernel_etext); 14178 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue); 14179 myResult = true; 14180 } 14181 } 14182 #if 0 14183 else { 14184 const OSMetaClass* myMetaClass = NULL; 14185 14186 myMetaClass = theObject->getMetaClass(); 14187 if (myMetaClass) { 14188 IOLog("class %s \n", myMetaClass->getClassName()); 14189 } else { 14190 IOLog("Unknown object \n" ); 14191 } 14192 } 14193 #endif 14194 14195 return myResult; 14196 } 14197 #endif // KASLR_KEXT_DEBUG 14198 }; /* extern "C" */ 14199 14200 #if PRAGMA_MARK 14201 #pragma mark Backtrace Dump & kmod_get_info() support 14202 #endif 14203 /********************************************************************* 14204 * This function must be safe to call in panic context. 14205 *********************************************************************/ 14206 /* static */ 14207 void 14208 OSKext::printKextsInBacktrace( 14209 vm_offset_t * addr __unused, 14210 unsigned int cnt __unused, 14211 int (* printf_func)(const char *fmt, ...) __unused, 14212 uint32_t flags __unused) 14213 { 14214 addr64_t summary_page = 0; 14215 addr64_t last_summary_page = 0; 14216 bool found_kmod = false; 14217 u_int i = 0; 14218 14219 if (kPrintKextsLock & flags) { 14220 if (!sKextSummariesLock) { 14221 return; 14222 } 14223 IOLockLock(sKextSummariesLock); 14224 } 14225 14226 if (!gLoadedKextSummaries) { 14227 (*printf_func)(" can't perform kext scan: no kext summary"); 14228 goto finish; 14229 } 14230 14231 summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries); 14232 last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize); 14233 for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) { 14234 if (pmap_find_phys(kernel_pmap, summary_page) == 0) { 14235 (*printf_func)(" can't perform kext scan: " 14236 "missing kext summary page %p", summary_page); 14237 goto finish; 14238 } 14239 } 14240 14241 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 14242 OSKextLoadedKextSummary * summary; 14243 14244 summary = gLoadedKextSummaries->summaries + i; 14245 if (!summary->address) { 14246 continue; 14247 } 14248 14249 if (!summaryIsInBacktrace(summary, addr, cnt)) { 14250 continue; 14251 } 14252 14253 if (!found_kmod) { 14254 if (!(kPrintKextsTerse & flags)) { 14255 (*printf_func)(" Kernel Extensions in backtrace:\n"); 14256 } 14257 found_kmod = true; 14258 } 14259 14260 printSummary(summary, printf_func, flags); 14261 } 14262 14263 finish: 14264 if (kPrintKextsLock & flags) { 14265 IOLockUnlock(sKextSummariesLock); 14266 } 14267 14268 return; 14269 } 14270 14271 /********************************************************************* 14272 * This function must be safe to call in panic context. 14273 *********************************************************************/ 14274 /* static */ 14275 boolean_t 14276 OSKext::summaryIsInBacktrace( 14277 OSKextLoadedKextSummary * summary, 14278 vm_offset_t * addr, 14279 unsigned int cnt) 14280 { 14281 u_int i = 0; 14282 14283 for (i = 0; i < cnt; i++) { 14284 vm_offset_t kscan_addr = addr[i]; 14285 #if __has_feature(ptrauth_calls) 14286 kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr); 14287 #endif /* __has_feature(ptrauth_calls) */ 14288 if ((kscan_addr >= summary->text_exec_address) && 14289 (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) { 14290 return TRUE; 14291 } 14292 } 14293 14294 return FALSE; 14295 } 14296 14297 /* 14298 * Get the kext summary object for the kext where 'addr' lies. Must be called with 14299 * sKextSummariesLock held. 14300 */ 14301 OSKextLoadedKextSummary * 14302 OSKext::summaryForAddress(uintptr_t addr) 14303 { 14304 #if __has_feature(ptrauth_calls) 14305 addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr); 14306 #endif /* __has_feature(ptrauth_calls) */ 14307 for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 14308 OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i]; 14309 if (!summary->address) { 14310 continue; 14311 } 14312 14313 #if VM_MAPPED_KEXTS 14314 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not 14315 * support split kexts, but we also may unmap the kexts, which can 14316 * race with the above codepath (see OSKext::unload). As such, 14317 * use a simple range lookup if we are using VM_MAPPED_KEXTS. 14318 */ 14319 if ((addr >= summary->address) && (addr < (summary->address + summary->size))) { 14320 return summary; 14321 } 14322 #else 14323 kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address; 14324 kernel_segment_command_t *seg; 14325 14326 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) { 14327 if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) { 14328 return summary; 14329 } 14330 } 14331 #endif 14332 } 14333 14334 /* addr did not map to any kext */ 14335 return NULL; 14336 } 14337 14338 /* static */ 14339 void * 14340 OSKext::kextForAddress(const void *address) 14341 { 14342 void * image = NULL; 14343 OSKextActiveAccount * active; 14344 OSKext * kext = NULL; 14345 uint32_t baseIdx; 14346 uint32_t lim; 14347 uintptr_t addr = (uintptr_t) address; 14348 size_t i; 14349 14350 if (!addr) { 14351 return NULL; 14352 } 14353 #if __has_feature(ptrauth_calls) 14354 addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr); 14355 #endif /* __has_feature(ptrauth_calls) */ 14356 14357 if (sKextAccountsCount) { 14358 IOSimpleLockLock(sKextAccountsLock); 14359 // bsearch sKextAccounts list 14360 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 14361 active = &sKextAccounts[baseIdx + (lim >> 1)]; 14362 if ((addr >= active->address) && (addr < active->address_end)) { 14363 kext = active->account->kext; 14364 if (kext && kext->kmod_info) { 14365 image = (void *) kext->kmod_info->address; 14366 } 14367 break; 14368 } else if (addr > active->address) { 14369 // move right 14370 baseIdx += (lim >> 1) + 1; 14371 lim--; 14372 } 14373 // else move left 14374 } 14375 IOSimpleLockUnlock(sKextAccountsLock); 14376 } 14377 if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) { 14378 image = (void *) &_mh_execute_header; 14379 } 14380 if (!image && gLoadedKextSummaries) { 14381 IOLockLock(sKextSummariesLock); 14382 for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) { 14383 OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i; 14384 if (addr >= summary->address && addr < summary->address + summary->size) { 14385 image = (void *)summary->address; 14386 } 14387 } 14388 IOLockUnlock(sKextSummariesLock); 14389 } 14390 14391 return image; 14392 } 14393 14394 /* 14395 * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t * 14396 * Safe to call in panic context. 14397 */ 14398 static OSKextLoadedKextSummary * 14399 findSummary(uint32_t tagID) 14400 { 14401 OSKextLoadedKextSummary * summary; 14402 for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) { 14403 summary = gLoadedKextSummaries->summaries + i; 14404 if (summary->loadTag == tagID) { 14405 return summary; 14406 } 14407 } 14408 return NULL; 14409 } 14410 14411 /********************************************************************* 14412 * This function must be safe to call in panic context. 14413 *********************************************************************/ 14414 void 14415 OSKext::printSummary( 14416 OSKextLoadedKextSummary * summary, 14417 int (* printf_func)(const char *fmt, ...), 14418 uint32_t flags) 14419 { 14420 kmod_reference_t * kmod_ref = NULL; 14421 uuid_string_t uuid; 14422 char version[kOSKextVersionMaxLength]; 14423 uint64_t tmpAddr; 14424 uint64_t tmpSize; 14425 OSKextLoadedKextSummary *dependencySummary; 14426 14427 if (!OSKextVersionGetString(summary->version, version, sizeof(version))) { 14428 strlcpy(version, "unknown version", sizeof(version)); 14429 } 14430 (void) uuid_unparse(summary->uuid, uuid); 14431 14432 #if defined(__arm__) || defined(__arm64__) 14433 tmpAddr = summary->text_exec_address; 14434 tmpSize = summary->text_exec_size; 14435 #else 14436 tmpAddr = summary->address; 14437 tmpSize = summary->size; 14438 #endif 14439 if (kPrintKextsUnslide & flags) { 14440 tmpAddr = ml_static_unslide(tmpAddr); 14441 } 14442 (*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n", 14443 (kPrintKextsTerse & flags) ? "" : " ", 14444 summary->name, version, uuid, 14445 tmpAddr, tmpAddr + tmpSize - 1); 14446 14447 if (kPrintKextsTerse & flags) { 14448 return; 14449 } 14450 14451 /* print dependency info */ 14452 for (kmod_ref = (kmod_reference_t *) summary->reference_list; 14453 kmod_ref; 14454 kmod_ref = kmod_ref->next) { 14455 kmod_info_t * rinfo; 14456 14457 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) { 14458 (*printf_func)(" kmod dependency scan stopped " 14459 "due to missing dependency page: %p\n", 14460 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref); 14461 break; 14462 } 14463 rinfo = kmod_ref->info; 14464 14465 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) { 14466 (*printf_func)(" kmod dependency scan stopped " 14467 "due to missing kmod page: %p\n", 14468 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo); 14469 break; 14470 } 14471 14472 if (!rinfo->address) { 14473 continue; // skip fake entries for built-ins 14474 } 14475 14476 dependencySummary = findSummary(rinfo->id); 14477 uuid[0] = 0x00; 14478 tmpAddr = rinfo->address; 14479 tmpSize = rinfo->size; 14480 if (dependencySummary) { 14481 (void) uuid_unparse(dependencySummary->uuid, uuid); 14482 #if defined(__arm__) || defined(__arm64__) 14483 tmpAddr = dependencySummary->text_exec_address; 14484 tmpSize = dependencySummary->text_exec_size; 14485 #endif 14486 } 14487 14488 if (kPrintKextsUnslide & flags) { 14489 tmpAddr = ml_static_unslide(tmpAddr); 14490 } 14491 (*printf_func)(" dependency: %s(%s)[%s]@%p->%p\n", 14492 rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1); 14493 } 14494 return; 14495 } 14496 14497 14498 #if !defined(__arm__) && !defined(__arm64__) 14499 /******************************************************************************* 14500 * substitute() looks at an input string (a pointer within a larger buffer) 14501 * for a match to a substring, and on match it writes the marker & substitution 14502 * character to an output string, updating the scan (from) and 14503 * output (to) indexes as appropriate. 14504 *******************************************************************************/ 14505 static int substitute( 14506 const char * scan_string, 14507 char * string_out, 14508 uint32_t * to_index, 14509 uint32_t * from_index, 14510 const char * substring, 14511 char marker, 14512 char substitution); 14513 14514 /* string_out must be at least KMOD_MAX_NAME bytes. 14515 */ 14516 static int 14517 substitute( 14518 const char * scan_string, 14519 char * string_out, 14520 uint32_t * to_index, 14521 uint32_t * from_index, 14522 const char * substring, 14523 char marker, 14524 char substitution) 14525 { 14526 size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1); 14527 14528 /* On a substring match, append the marker (if there is one) and then 14529 * the substitution character, updating the output (to) index accordingly. 14530 * Then update the input (from) length by the length of the substring 14531 * that got replaced. 14532 */ 14533 if (!strncmp(scan_string, substring, substring_length)) { 14534 if (marker) { 14535 string_out[(*to_index)++] = marker; 14536 } 14537 string_out[(*to_index)++] = substitution; 14538 (*from_index) += substring_length; 14539 return 1; 14540 } 14541 return 0; 14542 } 14543 14544 /******************************************************************************* 14545 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least 14546 * KMOD_MAX_NAME characters and performs various substitutions of common 14547 * prefixes & substrings as defined by tables in kext_panic_report.h. 14548 *******************************************************************************/ 14549 static void compactIdentifier( 14550 const char * identifier, 14551 char * identifier_out, 14552 char ** identifier_out_end); 14553 14554 static void 14555 compactIdentifier( 14556 const char * identifier, 14557 char * identifier_out, 14558 char ** identifier_out_end) 14559 { 14560 uint32_t from_index, to_index; 14561 uint32_t scan_from_index = 0; 14562 uint32_t scan_to_index = 0; 14563 subs_entry_t * subs_entry = NULL; 14564 int did_sub = 0; 14565 14566 from_index = to_index = 0; 14567 identifier_out[0] = '\0'; 14568 14569 /* Replace certain identifier prefixes with shorter @+character sequences. 14570 * Check the return value of substitute() so we only replace the prefix. 14571 */ 14572 for (subs_entry = &kext_identifier_prefix_subs[0]; 14573 subs_entry->substring && !did_sub; 14574 subs_entry++) { 14575 did_sub = substitute(identifier, identifier_out, 14576 &scan_to_index, &scan_from_index, 14577 subs_entry->substring, /* marker */ '\0', subs_entry->substitute); 14578 } 14579 did_sub = 0; 14580 14581 /* Now scan through the identifier looking for the common substrings 14582 * and replacing them with shorter !+character sequences via substitute(). 14583 */ 14584 for (/* see above */; 14585 scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index]; 14586 /* see loop */) { 14587 const char * scan_string = &identifier[scan_from_index]; 14588 14589 did_sub = 0; 14590 14591 if (scan_from_index) { 14592 for (subs_entry = &kext_identifier_substring_subs[0]; 14593 subs_entry->substring && !did_sub; 14594 subs_entry++) { 14595 did_sub = substitute(scan_string, identifier_out, 14596 &scan_to_index, &scan_from_index, 14597 subs_entry->substring, '!', subs_entry->substitute); 14598 } 14599 } 14600 14601 /* If we didn't substitute, copy the input character to the output. 14602 */ 14603 if (!did_sub) { 14604 identifier_out[scan_to_index++] = identifier[scan_from_index++]; 14605 } 14606 } 14607 14608 identifier_out[scan_to_index] = '\0'; 14609 if (identifier_out_end) { 14610 *identifier_out_end = &identifier_out[scan_to_index]; 14611 } 14612 14613 return; 14614 } 14615 #endif /* !defined(__arm__) && !defined(__arm64__) */ 14616 14617 /******************************************************************************* 14618 * assemble_identifier_and_version() adds to a string buffer a compacted 14619 * bundle identifier followed by a version string. 14620 *******************************************************************************/ 14621 14622 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length. 14623 */ 14624 static size_t assemble_identifier_and_version( 14625 kmod_info_t * kmod_info, 14626 char * identPlusVers, 14627 size_t bufSize); 14628 14629 static size_t 14630 assemble_identifier_and_version( 14631 kmod_info_t * kmod_info, 14632 char * identPlusVers, 14633 size_t bufSize) 14634 { 14635 size_t result = 0; 14636 14637 #if defined(__arm__) || defined(__arm64__) 14638 result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME); 14639 #else 14640 compactIdentifier(kmod_info->name, identPlusVers, NULL); 14641 result = strnlen(identPlusVers, KMOD_MAX_NAME - 1); 14642 #endif 14643 identPlusVers[result++] = '\t'; // increment for real char 14644 identPlusVers[result] = '\0'; // don't increment for nul char 14645 result = strlcat(identPlusVers, kmod_info->version, bufSize); 14646 if (result >= bufSize) { 14647 identPlusVers[bufSize - 1] = '\0'; 14648 result = bufSize - 1; 14649 } 14650 14651 return result; 14652 } 14653 14654 /******************************************************************************* 14655 * Assumes sKextLock is held. 14656 *******************************************************************************/ 14657 /* static */ 14658 int 14659 OSKext::saveLoadedKextPanicListTyped( 14660 const char * prefix, 14661 int invertFlag, 14662 int libsFlag, 14663 char * paniclist, 14664 uint32_t list_size) 14665 { 14666 int result = -1; 14667 unsigned int count, i; 14668 14669 count = sLoadedKexts->getCount(); 14670 if (!count) { 14671 goto finish; 14672 } 14673 14674 i = count - 1; 14675 do { 14676 OSObject * rawKext = sLoadedKexts->getObject(i); 14677 OSKext * theKext = OSDynamicCast(OSKext, rawKext); 14678 int match; 14679 size_t identPlusVersLength; 14680 size_t tempLen; 14681 char identPlusVers[2 * KMOD_MAX_NAME]; 14682 14683 if (!rawKext) { 14684 printf("OSKext::saveLoadedKextPanicListTyped - " 14685 "NULL kext in loaded kext list; continuing\n"); 14686 continue; 14687 } 14688 14689 if (!theKext) { 14690 printf("OSKext::saveLoadedKextPanicListTyped - " 14691 "Kext type cast failed in loaded kext list; continuing\n"); 14692 continue; 14693 } 14694 14695 /* Skip all built-in kexts. 14696 */ 14697 if (theKext->isKernelComponent()) { 14698 continue; 14699 } 14700 14701 kmod_info_t * kmod_info = theKext->kmod_info; 14702 14703 /* Filter for kmod name (bundle identifier). 14704 */ 14705 match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME)); 14706 if ((match && invertFlag) || (!match && !invertFlag)) { 14707 continue; 14708 } 14709 14710 /* Filter for libraries (kexts that have a compatible version). 14711 */ 14712 if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) || 14713 (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) { 14714 continue; 14715 } 14716 14717 if (!kmod_info || 14718 !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) { 14719 printf("kext scan stopped due to missing kmod_info page: %p\n", 14720 kmod_info); 14721 goto finish; 14722 } 14723 14724 identPlusVersLength = assemble_identifier_and_version(kmod_info, 14725 identPlusVers, 14726 sizeof(identPlusVers)); 14727 if (!identPlusVersLength) { 14728 printf("error saving loaded kext info\n"); 14729 goto finish; 14730 } 14731 14732 /* make sure everything fits and we null terminate. 14733 */ 14734 tempLen = strlcat(paniclist, identPlusVers, list_size); 14735 if (tempLen >= list_size) { 14736 // panic list is full, keep it and null terminate 14737 paniclist[list_size - 1] = 0x00; 14738 result = 0; 14739 goto finish; 14740 } 14741 tempLen = strlcat(paniclist, "\n", list_size); 14742 if (tempLen >= list_size) { 14743 // panic list is full, keep it and null terminate 14744 paniclist[list_size - 1] = 0x00; 14745 result = 0; 14746 goto finish; 14747 } 14748 } while (i--); 14749 14750 result = 0; 14751 finish: 14752 14753 return result; 14754 } 14755 14756 /********************************************************************* 14757 *********************************************************************/ 14758 /* static */ 14759 void 14760 OSKext::saveLoadedKextPanicList(void) 14761 { 14762 char * newlist = NULL; 14763 uint32_t newlist_size = 0; 14764 14765 newlist_size = KEXT_PANICLIST_SIZE; 14766 newlist = (char *)kheap_alloc_tag(KHEAP_DATA_BUFFERS, newlist_size, 14767 Z_WAITOK, VM_KERN_MEMORY_OSKEXT); 14768 14769 if (!newlist) { 14770 OSKextLog(/* kext */ NULL, 14771 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 14772 "Couldn't allocate kext panic log buffer."); 14773 goto finish; 14774 } 14775 14776 newlist[0] = '\0'; 14777 14778 // non-"com.apple." kexts 14779 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1, 14780 /* libs? */ -1, newlist, newlist_size) != 0) { 14781 goto finish; 14782 } 14783 // "com.apple." nonlibrary kexts 14784 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 14785 /* libs? */ 0, newlist, newlist_size) != 0) { 14786 goto finish; 14787 } 14788 // "com.apple." library kexts 14789 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0, 14790 /* libs? */ 1, newlist, newlist_size) != 0) { 14791 goto finish; 14792 } 14793 14794 if (loaded_kext_paniclist) { 14795 kheap_free(KHEAP_DATA_BUFFERS, loaded_kext_paniclist, 14796 loaded_kext_paniclist_size); 14797 } 14798 loaded_kext_paniclist = newlist; 14799 newlist = NULL; 14800 loaded_kext_paniclist_size = newlist_size; 14801 14802 finish: 14803 if (newlist) { 14804 kheap_free(KHEAP_TEMP, newlist, newlist_size); 14805 } 14806 return; 14807 } 14808 14809 /********************************************************************* 14810 * Assumes sKextLock is held. 14811 *********************************************************************/ 14812 void 14813 OSKext::savePanicString(bool isLoading) 14814 { 14815 u_long len; 14816 14817 if (!kmod_info) { 14818 return; // do not goto finish here b/c of lock 14819 } 14820 14821 len = assemble_identifier_and_version( kmod_info, 14822 (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf, 14823 (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf)); 14824 if (!len) { 14825 printf("error saving unloaded kext info\n"); 14826 goto finish; 14827 } 14828 14829 if (isLoading) { 14830 last_loaded_strlen = len; 14831 last_loaded_address = (void *)kmod_info->address; 14832 last_loaded_size = kmod_info->size; 14833 clock_get_uptime(&last_loaded_timestamp); 14834 } else { 14835 last_unloaded_strlen = len; 14836 last_unloaded_address = (void *)kmod_info->address; 14837 last_unloaded_size = kmod_info->size; 14838 clock_get_uptime(&last_unloaded_timestamp); 14839 } 14840 14841 finish: 14842 return; 14843 } 14844 14845 /********************************************************************* 14846 *********************************************************************/ 14847 /* static */ 14848 void 14849 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...)) 14850 { 14851 if (last_loaded_strlen) { 14852 printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n", 14853 AbsoluteTime_to_scalar(&last_loaded_timestamp), 14854 last_loaded_strlen, last_loaded_str_buf, 14855 last_loaded_address, last_loaded_size); 14856 } 14857 14858 if (last_unloaded_strlen) { 14859 printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n", 14860 AbsoluteTime_to_scalar(&last_unloaded_timestamp), 14861 last_unloaded_strlen, last_unloaded_str_buf, 14862 last_unloaded_address, last_unloaded_size); 14863 } 14864 14865 printf_func("loaded kexts:\n"); 14866 if (loaded_kext_paniclist && 14867 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) && 14868 loaded_kext_paniclist[0]) { 14869 printf_func("%.*s", 14870 strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size), 14871 loaded_kext_paniclist); 14872 } else { 14873 printf_func("(none)\n"); 14874 } 14875 return; 14876 } 14877 14878 /********************************************************************* 14879 * Assumes sKextLock is held. 14880 *********************************************************************/ 14881 /* static */ 14882 void 14883 OSKext::updateLoadedKextSummaries(void) 14884 { 14885 kern_return_t result = KERN_FAILURE; 14886 OSKextLoadedKextSummaryHeader *summaryHeader = NULL; 14887 OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL; 14888 OSKext *aKext; 14889 vm_map_offset_t start, end; 14890 size_t summarySize = 0; 14891 size_t size; 14892 u_int count; 14893 u_int maxKexts; 14894 u_int i, j; 14895 OSKextActiveAccount * accountingList; 14896 OSKextActiveAccount * prevAccountingList; 14897 uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount; 14898 14899 prevAccountingList = NULL; 14900 prevAccountingListCount = 0; 14901 14902 #if DEVELOPMENT || DEBUG 14903 if (IORecursiveLockHaveLock(sKextLock) == false) { 14904 panic("sKextLock must be held"); 14905 } 14906 #endif 14907 14908 IOLockLock(sKextSummariesLock); 14909 14910 count = sLoadedKexts->getCount(); 14911 for (i = 0, maxKexts = 0; i < count; ++i) { 14912 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 14913 maxKexts += (aKext && aKext->isExecutable()); 14914 } 14915 14916 if (!maxKexts) { 14917 goto finish; 14918 } 14919 if (maxKexts < kOSKextTypicalLoadCount) { 14920 maxKexts = kOSKextTypicalLoadCount; 14921 } 14922 14923 /* Calculate the size needed for the new summary headers. 14924 */ 14925 14926 size = sizeof(*gLoadedKextSummaries); 14927 size += maxKexts * sizeof(*gLoadedKextSummaries->summaries); 14928 size = round_page(size); 14929 14930 if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) { 14931 if (gLoadedKextSummaries) { 14932 kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize); 14933 gLoadedKextSummaries = NULL; 14934 gLoadedKextSummariesTimestamp = mach_absolute_time(); 14935 sLoadedKextSummariesAllocSize = 0; 14936 } 14937 result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, VM_KERN_MEMORY_OSKEXT); 14938 if (result != KERN_SUCCESS) { 14939 goto finish; 14940 } 14941 summaryHeader = summaryHeaderAlloc; 14942 summarySize = size; 14943 } else { 14944 summaryHeader = gLoadedKextSummaries; 14945 summarySize = sLoadedKextSummariesAllocSize; 14946 14947 start = (vm_map_offset_t) summaryHeader; 14948 end = start + summarySize; 14949 result = vm_map_protect(kernel_map, 14950 start, 14951 end, 14952 VM_PROT_DEFAULT, 14953 FALSE); 14954 if (result != KERN_SUCCESS) { 14955 goto finish; 14956 } 14957 } 14958 14959 /* Populate the summary header. 14960 */ 14961 14962 bzero(summaryHeader, summarySize); 14963 summaryHeader->version = kOSKextLoadedKextSummaryVersion; 14964 summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary); 14965 14966 /* Populate each kext summary. 14967 */ 14968 14969 count = sLoadedKexts->getCount(); 14970 accountingListAlloc = 0; 14971 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 14972 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 14973 if (!aKext || !aKext->isExecutable()) { 14974 continue; 14975 } 14976 14977 aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]); 14978 summaryHeader->numSummaries++; 14979 accountingListAlloc++; 14980 } 14981 14982 accountingList = IONew(typeof(accountingList[0]), accountingListAlloc); 14983 accountingListCount = 0; 14984 for (i = 0, j = 0; i < count && j < maxKexts; ++i) { 14985 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i)); 14986 if (!aKext || !aKext->isExecutable()) { 14987 continue; 14988 } 14989 14990 OSKextActiveAccount activeAccount; 14991 aKext->updateActiveAccount(&activeAccount); 14992 // order by address 14993 for (idx = 0; idx < accountingListCount; idx++) { 14994 if (activeAccount.address < accountingList[idx].address) { 14995 break; 14996 } 14997 } 14998 bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0])); 14999 accountingList[idx] = activeAccount; 15000 accountingListCount++; 15001 } 15002 assert(accountingListCount == accountingListAlloc); 15003 /* Write protect the buffer and move it into place. 15004 */ 15005 15006 start = (vm_map_offset_t) summaryHeader; 15007 end = start + summarySize; 15008 15009 result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE); 15010 if (result != KERN_SUCCESS) { 15011 goto finish; 15012 } 15013 15014 gLoadedKextSummaries = summaryHeader; 15015 gLoadedKextSummariesTimestamp = mach_absolute_time(); 15016 sLoadedKextSummariesAllocSize = summarySize; 15017 summaryHeaderAlloc = NULL; 15018 15019 /* Call the magic breakpoint function through a static function pointer so 15020 * the compiler can't optimize the function away. 15021 */ 15022 if (sLoadedKextSummariesUpdated) { 15023 (*sLoadedKextSummariesUpdated)(); 15024 } 15025 15026 IOSimpleLockLock(sKextAccountsLock); 15027 prevAccountingList = sKextAccounts; 15028 prevAccountingListCount = sKextAccountsCount; 15029 sKextAccounts = accountingList; 15030 sKextAccountsCount = accountingListCount; 15031 IOSimpleLockUnlock(sKextAccountsLock); 15032 15033 finish: 15034 IOLockUnlock(sKextSummariesLock); 15035 15036 /* If we had to allocate a new buffer but failed to generate the summaries, 15037 * free that now. 15038 */ 15039 if (summaryHeaderAlloc) { 15040 kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize); 15041 } 15042 if (prevAccountingList) { 15043 IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount); 15044 } 15045 15046 return; 15047 } 15048 15049 /********************************************************************* 15050 *********************************************************************/ 15051 void 15052 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary) 15053 { 15054 OSSharedPtr<OSData> uuid; 15055 15056 strlcpy(summary->name, getIdentifierCString(), 15057 sizeof(summary->name)); 15058 15059 uuid = copyUUID(); 15060 if (uuid) { 15061 memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid)); 15062 } 15063 15064 if (flags.builtin) { 15065 // this value will stop lldb from parsing the mach-o header 15066 // summary->address = UINT64_MAX; 15067 // summary->size = 0; 15068 summary->address = kmod_info->address; 15069 summary->size = kmod_info->size; 15070 } else { 15071 summary->address = kmod_info->address; 15072 summary->size = kmod_info->size; 15073 } 15074 summary->version = getVersion(); 15075 summary->loadTag = kmod_info->id; 15076 summary->flags = 0; 15077 summary->reference_list = (uint64_t) kmod_info->reference_list; 15078 15079 summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size); 15080 if (summary->text_exec_address == 0) { 15081 // Fallback to __TEXT 15082 summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size); 15083 } 15084 return; 15085 } 15086 15087 /********************************************************************* 15088 *********************************************************************/ 15089 15090 void 15091 OSKext::updateActiveAccount(OSKextActiveAccount *accountp) 15092 { 15093 kernel_mach_header_t *hdr = NULL; 15094 kernel_segment_command_t *seg = NULL; 15095 15096 bzero(accountp, sizeof(*accountp)); 15097 15098 hdr = (kernel_mach_header_t *)kmod_info->address; 15099 if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) { 15100 /* 15101 * If this kext supports split segments (or is in a new 15102 * MH_FILESET kext collection), use the first 15103 * executable segment as the range for instructions 15104 * (and thus for backtracing. 15105 */ 15106 for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) { 15107 if (seg->initprot & VM_PROT_EXECUTE) { 15108 break; 15109 } 15110 } 15111 } 15112 if (seg) { 15113 accountp->address = seg->vmaddr; 15114 if (accountp->address) { 15115 accountp->address_end = seg->vmaddr + seg->vmsize; 15116 } 15117 } else { 15118 /* For non-split kexts and for kexts without executable 15119 * segments, just use the kmod_info range (as the kext 15120 * is either all in one range or should not show up in 15121 * instruction backtraces). 15122 */ 15123 accountp->address = kmod_info->address; 15124 if (accountp->address) { 15125 accountp->address_end = kmod_info->address + kmod_info->size; 15126 } 15127 } 15128 15129 accountp->account = this->account; 15130 } 15131 15132 bool 15133 OSKext::isDriverKit(void) 15134 { 15135 OSString *bundleType; 15136 15137 if (infoDict) { 15138 bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)); 15139 if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) { 15140 return TRUE; 15141 } 15142 } 15143 return FALSE; 15144 } 15145 15146 bool 15147 OSKext::isInFileset(void) 15148 { 15149 if (!kmod_info) { 15150 goto check_prelinked; 15151 } 15152 15153 if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) { 15154 return true; 15155 } 15156 15157 check_prelinked: 15158 if (isPrelinked()) { 15159 /* 15160 * If we haven't setup kmod_info yet, but we know 15161 * we're loading a prelinked kext in an MH_FILESET KC, 15162 * then return true 15163 */ 15164 kc_format_t kc_format; 15165 if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) { 15166 return true; 15167 } 15168 } 15169 return false; 15170 } 15171 15172 bool 15173 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg) 15174 { 15175 kern_return_t result; 15176 if (!super::init()) { 15177 return false; 15178 } 15179 if (seg == nullptr) { 15180 return false; 15181 } 15182 result = kmem_alloc_pageable(kernel_map, (vm_offset_t *)&data, seg->vmsize, VM_KERN_MEMORY_KEXT); 15183 if (result != KERN_SUCCESS) { 15184 return false; 15185 } 15186 memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize); 15187 savedSegment = seg; 15188 vmsize = seg->vmsize; 15189 vmaddr = seg->vmaddr; 15190 return true; 15191 } 15192 15193 OSSharedPtr<OSKextSavedMutableSegment> 15194 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg) 15195 { 15196 OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>(); 15197 if (me && !me->initWithSegment(seg)) { 15198 return nullptr; 15199 } 15200 return me; 15201 } 15202 15203 void 15204 OSKextSavedMutableSegment::free(void) 15205 { 15206 if (data) { 15207 kmem_free(kernel_map, (vm_offset_t)data, vmsize); 15208 } 15209 } 15210 15211 vm_offset_t 15212 OSKextSavedMutableSegment::getVMAddr() const 15213 { 15214 return vmaddr; 15215 } 15216 15217 vm_offset_t 15218 OSKextSavedMutableSegment::getVMSize() const 15219 { 15220 return vmsize; 15221 } 15222 15223 OSReturn 15224 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg) 15225 { 15226 if (seg != savedSegment) { 15227 return kOSKextReturnInvalidArgument; 15228 } 15229 if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) { 15230 return kOSKextReturnInvalidArgument; 15231 } 15232 memcpy((void *)seg->vmaddr, data, vmsize); 15233 return kOSReturnSuccess; 15234 } 15235 15236 extern "C" const vm_allocation_site_t * 15237 OSKextGetAllocationSiteForCaller(uintptr_t address) 15238 { 15239 OSKextActiveAccount * active; 15240 vm_allocation_site_t * site; 15241 vm_allocation_site_t * releasesite; 15242 15243 uint32_t baseIdx; 15244 uint32_t lim; 15245 #if __has_feature(ptrauth_calls) 15246 address = (uintptr_t)VM_KERNEL_STRIP_PTR(address); 15247 #endif /* __has_feature(ptrauth_calls) */ 15248 15249 IOSimpleLockLock(sKextAccountsLock); 15250 site = releasesite = NULL; 15251 15252 // bsearch sKextAccounts list 15253 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) { 15254 active = &sKextAccounts[baseIdx + (lim >> 1)]; 15255 if ((address >= active->address) && (address < active->address_end)) { 15256 site = &active->account->site; 15257 if (!site->tag) { 15258 vm_tag_alloc_locked(site, &releasesite); 15259 } 15260 break; 15261 } else if (address > active->address) { 15262 // move right 15263 baseIdx += (lim >> 1) + 1; 15264 lim--; 15265 } 15266 // else move left 15267 } 15268 IOSimpleLockUnlock(sKextAccountsLock); 15269 if (releasesite) { 15270 kern_allocation_name_release(releasesite); 15271 } 15272 15273 return site; 15274 } 15275 15276 extern "C" uint32_t 15277 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen) 15278 { 15279 OSKextAccount * account = (typeof(account))site; 15280 const char * kname; 15281 15282 if (name) { 15283 if (account->kext) { 15284 kname = account->kext->getIdentifierCString(); 15285 } else { 15286 kname = "<>"; 15287 } 15288 strlcpy(name, kname, namelen); 15289 } 15290 15291 return account->loadTag; 15292 } 15293 15294 extern "C" void 15295 OSKextFreeSite(vm_allocation_site_t * site) 15296 { 15297 OSKextAccount * freeAccount = (typeof(freeAccount))site; 15298 IODelete(freeAccount, OSKextAccount, 1); 15299 } 15300 15301 /********************************************************************* 15302 *********************************************************************/ 15303 15304 #if CONFIG_IMAGEBOOT 15305 int 15306 OSKextGetUUIDForName(const char *name, uuid_t uuid) 15307 { 15308 OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name); 15309 if (!kext) { 15310 return 1; 15311 } 15312 15313 OSSharedPtr<OSData> uuid_data = kext->copyUUID(); 15314 if (uuid_data) { 15315 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t)); 15316 return 0; 15317 } 15318 15319 return 1; 15320 } 15321 #endif 15322 15323 static int 15324 sysctl_willuserspacereboot 15325 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 15326 { 15327 int new_value = 0, old_value = 0, changed = 0; 15328 int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed); 15329 if (error) { 15330 return error; 15331 } 15332 if (changed) { 15333 OSKext::willUserspaceReboot(); 15334 } 15335 return 0; 15336 } 15337 15338 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot, 15339 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 15340 NULL, 0, sysctl_willuserspacereboot, "I", ""); 15341