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