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