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