1 /* 2 * Copyright (c) 2000-2012 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 extern "C" { 29 #include <mach/kmod.h> 30 #include <libkern/kernel_mach_header.h> 31 #include <libkern/prelink.h> 32 } 33 34 #include <libkern/version.h> 35 #include <libkern/c++/OSContainers.h> 36 #include <libkern/OSKextLibPrivate.h> 37 #include <libkern/c++/OSKext.h> 38 #include <IOKit/IOLib.h> 39 #include <IOKit/IOService.h> 40 #include <IOKit/IODeviceTreeSupport.h> 41 #include <IOKit/IOCatalogue.h> 42 43 #if __x86_64__ 44 #define KASLR_KEXT_DEBUG 0 45 #endif 46 47 #if PRAGMA_MARK 48 #pragma mark Bootstrap Declarations 49 #endif 50 /********************************************************************* 51 * Bootstrap Declarations 52 * 53 * The ENTIRE point of the libsa/KLD segment is to isolate bootstrap 54 * code from other parts of the kernel, so function symbols are not 55 * exported; rather pointers to those functions are exported. 56 * 57 * xxx - need to think about locking for handling the 'weak' refs. 58 * xxx - do export a non-KLD function that says you've called a 59 * xxx - bootstrap function that has been removed. 60 * 61 * ALL call-ins to this segment of the kernel must be done through 62 * exported pointers. The symbols themselves are private and not to 63 * be linked against. 64 *********************************************************************/ 65 extern "C" { 66 extern void (*record_startup_extensions_function)(void); 67 extern void (*load_security_extensions_function)(void); 68 }; 69 70 static void bootstrapRecordStartupExtensions(void); 71 static void bootstrapLoadSecurityExtensions(void); 72 73 74 #if NO_KEXTD 75 extern "C" bool IORamDiskBSDRoot(void); 76 #endif 77 78 #if PRAGMA_MARK 79 #pragma mark Macros 80 #endif 81 /********************************************************************* 82 * Macros 83 *********************************************************************/ 84 #define CONST_STRLEN(str) (sizeof(str) - 1) 85 86 #if PRAGMA_MARK 87 #pragma mark Kernel Component Kext Identifiers 88 #endif 89 /********************************************************************* 90 * Kernel Component Kext Identifiers 91 * 92 * We could have each kernel resource kext automatically "load" as 93 * it's created, but it's nicer to have them listed in kextstat in 94 * the order of this list. We'll walk through this after setting up 95 * all the boot kexts and have them load up. 96 *********************************************************************/ 97 static const char * sKernelComponentNames[] = { 98 // The kexts for these IDs must have a version matching 'osrelease'. 99 "com.apple.kernel", 100 "com.apple.kpi.bsd", 101 "com.apple.kpi.dsep", 102 "com.apple.kpi.iokit", 103 "com.apple.kpi.libkern", 104 "com.apple.kpi.mach", 105 "com.apple.kpi.private", 106 "com.apple.kpi.unsupported", 107 "com.apple.iokit.IONVRAMFamily", 108 "com.apple.driver.AppleNMI", 109 "com.apple.iokit.IOSystemManagementFamily", 110 "com.apple.iokit.ApplePlatformFamily", 111 NULL 112 }; 113 114 #if PRAGMA_MARK 115 #pragma mark KLDBootstrap Class 116 #endif 117 /********************************************************************* 118 * KLDBootstrap Class 119 * 120 * We use a C++ class here so that it can be a friend of OSKext and 121 * get at private stuff. We can't hide the class itself, but we can 122 * hide the instance through which we invoke the functions. 123 *********************************************************************/ 124 class KLDBootstrap { 125 friend void bootstrapRecordStartupExtensions(void); 126 friend void bootstrapLoadSecurityExtensions(void); 127 128 private: 129 void readStartupExtensions(void); 130 131 void readPrelinkedExtensions( 132 kernel_section_t * prelinkInfoSect); 133 void readBooterExtensions(void); 134 135 OSReturn loadKernelComponentKexts(void); 136 void loadKernelExternalComponents(void); 137 void readBuiltinPersonalities(void); 138 139 void loadSecurityExtensions(void); 140 141 public: 142 KLDBootstrap(void); 143 ~KLDBootstrap(void); 144 }; 145 146 static KLDBootstrap sBootstrapObject; 147 148 /********************************************************************* 149 * Set the function pointers for the entry points into the bootstrap 150 * segment upon C++ static constructor invocation. 151 *********************************************************************/ 152 KLDBootstrap::KLDBootstrap(void) 153 { 154 if (this != &sBootstrapObject) { 155 panic("Attempt to access bootstrap segment."); 156 } 157 record_startup_extensions_function = &bootstrapRecordStartupExtensions; 158 load_security_extensions_function = &bootstrapLoadSecurityExtensions; 159 } 160 161 /********************************************************************* 162 * Clear the function pointers for the entry points into the bootstrap 163 * segment upon C++ static destructor invocation. 164 *********************************************************************/ 165 KLDBootstrap::~KLDBootstrap(void) 166 { 167 if (this != &sBootstrapObject) { 168 panic("Attempt to access bootstrap segment."); 169 } 170 171 172 record_startup_extensions_function = 0; 173 load_security_extensions_function = 0; 174 } 175 176 /********************************************************************* 177 *********************************************************************/ 178 void 179 KLDBootstrap::readStartupExtensions(void) 180 { 181 kernel_section_t * prelinkInfoSect = NULL; // do not free 182 183 OSKextLog(/* kext */ NULL, 184 kOSKextLogProgressLevel | 185 kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag | 186 kOSKextLogKextBookkeepingFlag, 187 "Reading startup extensions."); 188 189 /* If the prelink info segment has a nonzero size, we are prelinked 190 * and won't have any individual kexts or mkexts to read. 191 * Otherwise, we need to read kexts or the mkext from what the booter 192 * has handed us. 193 */ 194 prelinkInfoSect = getsectbyname(kPrelinkInfoSegment, kPrelinkInfoSection); 195 if (prelinkInfoSect->size) { 196 readPrelinkedExtensions(prelinkInfoSect); 197 } else { 198 readBooterExtensions(); 199 } 200 201 loadKernelComponentKexts(); 202 loadKernelExternalComponents(); 203 readBuiltinPersonalities(); 204 OSKext::sendAllKextPersonalitiesToCatalog(); 205 206 return; 207 } 208 209 /********************************************************************* 210 *********************************************************************/ 211 void 212 KLDBootstrap::readPrelinkedExtensions( 213 kernel_section_t * prelinkInfoSect) 214 { 215 OSArray * infoDictArray = NULL; // do not release 216 OSObject * parsedXML = NULL; // must release 217 OSDictionary * prelinkInfoDict = NULL; // do not release 218 OSString * errorString = NULL; // must release 219 OSKext * theKernel = NULL; // must release 220 221 kernel_segment_command_t * prelinkTextSegment = NULL; // see code 222 kernel_segment_command_t * prelinkInfoSegment = NULL; // see code 223 224 /* We make some copies of data, but if anything fails we're basically 225 * going to fail the boot, so these won't be cleaned up on error. 226 */ 227 void * prelinkData = NULL; // see code 228 vm_size_t prelinkLength = 0; 229 230 231 OSDictionary * infoDict = NULL; // do not release 232 233 IORegistryEntry * registryRoot = NULL; // do not release 234 OSNumber * prelinkCountObj = NULL; // must release 235 236 u_int i = 0; 237 #if NO_KEXTD 238 bool ramDiskBoot; 239 bool developerDevice; 240 bool dontLoad; 241 #endif 242 243 OSKextLog(/* kext */ NULL, 244 kOSKextLogProgressLevel | 245 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 246 "Starting from prelinked kernel."); 247 248 prelinkTextSegment = getsegbyname(kPrelinkTextSegment); 249 if (!prelinkTextSegment) { 250 OSKextLog(/* kext */ NULL, 251 kOSKextLogErrorLevel | 252 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 253 "Can't find prelinked kexts' text segment."); 254 goto finish; 255 } 256 257 #if KASLR_KEXT_DEBUG 258 unsigned long scratchSize; 259 vm_offset_t scratchAddr; 260 261 IOLog("kaslr: prelinked kernel address info: \n"); 262 263 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__TEXT", &scratchSize); 264 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n", 265 (unsigned long)scratchAddr, 266 (unsigned long)(scratchAddr + scratchSize), 267 scratchSize); 268 269 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__DATA", &scratchSize); 270 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n", 271 (unsigned long)scratchAddr, 272 (unsigned long)(scratchAddr + scratchSize), 273 scratchSize); 274 275 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__LINKEDIT", &scratchSize); 276 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n", 277 (unsigned long)scratchAddr, 278 (unsigned long)(scratchAddr + scratchSize), 279 scratchSize); 280 281 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__KLD", &scratchSize); 282 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n", 283 (unsigned long)scratchAddr, 284 (unsigned long)(scratchAddr + scratchSize), 285 scratchSize); 286 287 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_TEXT", &scratchSize); 288 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n", 289 (unsigned long)scratchAddr, 290 (unsigned long)(scratchAddr + scratchSize), 291 scratchSize); 292 293 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_INFO", &scratchSize); 294 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n", 295 (unsigned long)scratchAddr, 296 (unsigned long)(scratchAddr + scratchSize), 297 scratchSize); 298 #endif 299 300 prelinkData = (void *) prelinkTextSegment->vmaddr; 301 prelinkLength = prelinkTextSegment->vmsize; 302 303 304 /* Unserialize the info dictionary from the prelink info section. 305 */ 306 parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr, 307 &errorString); 308 if (parsedXML) { 309 prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML); 310 } 311 if (!prelinkInfoDict) { 312 const char * errorCString = "(unknown error)"; 313 314 if (errorString && errorString->getCStringNoCopy()) { 315 errorCString = errorString->getCStringNoCopy(); 316 } else if (parsedXML) { 317 errorCString = "not a dictionary"; 318 } 319 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 320 "Error unserializing prelink plist: %s.", errorCString); 321 goto finish; 322 } 323 324 #if NO_KEXTD 325 /* Check if we should keep developer kexts around. 326 * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201> 327 */ 328 developerDevice = true; 329 PE_parse_boot_argn("developer", &developerDevice, sizeof(developerDevice)); 330 331 ramDiskBoot = IORamDiskBSDRoot(); 332 #endif /* NO_KEXTD */ 333 334 infoDictArray = OSDynamicCast(OSArray, 335 prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey)); 336 if (!infoDictArray) { 337 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, 338 "The prelinked kernel has no kext info dictionaries"); 339 goto finish; 340 } 341 342 /* Create dictionary of excluded kexts 343 */ 344 OSKext::createExcludeListFromPrelinkInfo(infoDictArray); 345 346 /* Create OSKext objects for each info dictionary. 347 */ 348 for (i = 0; i < infoDictArray->getCount(); ++i) { 349 infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i)); 350 if (!infoDict) { 351 OSKextLog(/* kext */ NULL, 352 kOSKextLogErrorLevel | 353 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 354 "Can't find info dictionary for prelinked kext #%d.", i); 355 continue; 356 } 357 358 #if NO_KEXTD 359 dontLoad = false; 360 361 /* If we're not on a developer device, skip and free developer kexts. 362 */ 363 if (developerDevice == false) { 364 OSBoolean *devOnlyBool = OSDynamicCast(OSBoolean, 365 infoDict->getObject(kOSBundleDeveloperOnlyKey)); 366 if (devOnlyBool == kOSBooleanTrue) { 367 dontLoad = true; 368 } 369 } 370 371 /* Skip and free kexts that are only needed when booted from a ram disk. 372 */ 373 if (ramDiskBoot == false) { 374 OSBoolean *ramDiskOnlyBool = OSDynamicCast(OSBoolean, 375 infoDict->getObject(kOSBundleRamDiskOnlyKey)); 376 if (ramDiskOnlyBool == kOSBooleanTrue) { 377 dontLoad = true; 378 } 379 } 380 381 if (dontLoad == true) { 382 OSString *bundleID = OSDynamicCast(OSString, 383 infoDict->getObject(kCFBundleIdentifierKey)); 384 if (bundleID) { 385 OSKextLog(NULL, kOSKextLogWarningLevel | kOSKextLogGeneralFlag, 386 "Kext %s not loading.", bundleID->getCStringNoCopy()); 387 } 388 389 OSNumber *addressNum = OSDynamicCast(OSNumber, 390 infoDict->getObject(kPrelinkExecutableLoadKey)); 391 OSNumber *lengthNum = OSDynamicCast(OSNumber, 392 infoDict->getObject(kPrelinkExecutableSizeKey)); 393 if (addressNum && lengthNum) { 394 #error Pick the right way to free prelinked data on this arch 395 } 396 397 infoDictArray->removeObject(i--); 398 continue; 399 } 400 #endif /* NO_KEXTD */ 401 402 /* Create the kext for the entry, then release it, because the 403 * kext system keeps them around until explicitly removed. 404 * Any creation/registration failures are already logged for us. 405 */ 406 OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict); 407 OSSafeReleaseNULL(newKext); 408 } 409 410 /* Store the number of prelinked kexts in the registry so we can tell 411 * when the system has been started from a prelinked kernel. 412 */ 413 registryRoot = IORegistryEntry::getRegistryRoot(); 414 assert(registryRoot); 415 416 prelinkCountObj = OSNumber::withNumber( 417 (unsigned long long)infoDictArray->getCount(), 418 8 * sizeof(uint32_t)); 419 assert(prelinkCountObj); 420 if (prelinkCountObj) { 421 registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj); 422 } 423 424 OSKextLog(/* kext */ NULL, 425 kOSKextLogProgressLevel | 426 kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag | 427 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, 428 "%u prelinked kexts", 429 infoDictArray->getCount()); 430 431 #if CONFIG_KEXT_BASEMENT 432 /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own 433 * special VM region during OSKext init time, so we can free the whole 434 * segment now. 435 */ 436 ml_static_mfree((vm_offset_t) prelinkData, prelinkLength); 437 #endif /* __x86_64__ */ 438 439 /* Free the prelink info segment, we're done with it. 440 */ 441 prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment); 442 if (prelinkInfoSegment) { 443 ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr, 444 (vm_size_t)prelinkInfoSegment->vmsize); 445 } 446 447 finish: 448 OSSafeRelease(errorString); 449 OSSafeRelease(parsedXML); 450 OSSafeRelease(theKernel); 451 OSSafeRelease(prelinkCountObj); 452 return; 453 } 454 455 /********************************************************************* 456 *********************************************************************/ 457 #define BOOTER_KEXT_PREFIX "Driver-" 458 459 typedef struct _DeviceTreeBuffer { 460 uint32_t paddr; 461 uint32_t length; 462 } _DeviceTreeBuffer; 463 464 void 465 KLDBootstrap::readBooterExtensions(void) 466 { 467 IORegistryEntry * booterMemoryMap = NULL; // must release 468 OSDictionary * propertyDict = NULL; // must release 469 OSCollectionIterator * keyIterator = NULL; // must release 470 OSString * deviceTreeName = NULL; // do not release 471 472 const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not free 473 char * booterDataPtr = NULL; // do not free 474 OSData * booterData = NULL; // must release 475 476 OSKext * aKext = NULL; // must release 477 478 OSKextLog(/* kext */ NULL, 479 kOSKextLogProgressLevel | 480 kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag, 481 "Reading startup extensions from booter memory."); 482 483 booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane); 484 485 if (!booterMemoryMap) { 486 OSKextLog(/* kext */ NULL, 487 kOSKextLogErrorLevel | 488 kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag, 489 "Can't read booter memory map."); 490 goto finish; 491 } 492 493 propertyDict = booterMemoryMap->dictionaryWithProperties(); 494 if (!propertyDict) { 495 OSKextLog(/* kext */ NULL, 496 kOSKextLogErrorLevel | 497 kOSKextLogDirectoryScanFlag, 498 "Can't get property dictionary from memory map."); 499 goto finish; 500 } 501 502 keyIterator = OSCollectionIterator::withCollection(propertyDict); 503 if (!keyIterator) { 504 OSKextLog(/* kext */ NULL, 505 kOSKextLogErrorLevel | 506 kOSKextLogGeneralFlag, 507 "Can't allocate iterator for driver images."); 508 goto finish; 509 } 510 511 /* Create dictionary of excluded kexts 512 */ 513 OSKext::createExcludeListFromBooterData(propertyDict, keyIterator); 514 keyIterator->reset(); 515 516 while ( ( deviceTreeName = 517 OSDynamicCast(OSString, keyIterator->getNextObject() ))) { 518 519 const char * devTreeNameCString = deviceTreeName->getCStringNoCopy(); 520 OSData * deviceTreeEntry = OSDynamicCast(OSData, 521 propertyDict->getObject(deviceTreeName)); 522 523 /* Clear out the booterData from the prior iteration. 524 */ 525 OSSafeReleaseNULL(booterData); 526 527 /* If there is no entry for the name, we can't do much with it. */ 528 if (!deviceTreeEntry) { 529 continue; 530 } 531 532 /* Make sure it is a kext */ 533 if (strncmp(devTreeNameCString, 534 BOOTER_KEXT_PREFIX, 535 CONST_STRLEN(BOOTER_KEXT_PREFIX))) { 536 continue; 537 } 538 539 deviceTreeBuffer = (const _DeviceTreeBuffer *) 540 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer)); 541 if (!deviceTreeBuffer) { 542 /* We can't get to the data, so we can't do anything, 543 * not even free it from physical memory (if it's there). 544 */ 545 OSKextLog(/* kext */ NULL, 546 kOSKextLogErrorLevel | 547 kOSKextLogDirectoryScanFlag, 548 "Device tree entry %s has NULL pointer.", 549 devTreeNameCString); 550 goto finish; // xxx - continue, panic? 551 } 552 553 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr); 554 if (!booterDataPtr) { 555 OSKextLog(/* kext */ NULL, 556 kOSKextLogErrorLevel | 557 kOSKextLogDirectoryScanFlag, 558 "Can't get virtual address for device tree entry %s.", 559 devTreeNameCString); 560 goto finish; 561 } 562 563 /* Wrap the booter data buffer in an OSData and set a dealloc function 564 * so it will take care of the physical memory when freed. Kexts will 565 * retain the booterData for as long as they need it. Remove the entry 566 * from the booter memory map after this is done. 567 */ 568 booterData = OSData::withBytesNoCopy(booterDataPtr, 569 deviceTreeBuffer->length); 570 if (!booterData) { 571 OSKextLog(/* kext */ NULL, 572 kOSKextLogErrorLevel | 573 kOSKextLogGeneralFlag, 574 "Error - Can't allocate OSData wrapper for device tree entry %s.", 575 devTreeNameCString); 576 goto finish; 577 } 578 booterData->setDeallocFunction(osdata_phys_free); 579 580 /* Create the kext for the entry, then release it, because the 581 * kext system keeps them around until explicitly removed. 582 * Any creation/registration failures are already logged for us. 583 */ 584 OSKext * newKext = OSKext::withBooterData(deviceTreeName, booterData); 585 OSSafeRelease(newKext); 586 587 booterMemoryMap->removeProperty(deviceTreeName); 588 589 } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */ 590 591 finish: 592 593 OSSafeRelease(booterMemoryMap); 594 OSSafeRelease(propertyDict); 595 OSSafeRelease(keyIterator); 596 OSSafeRelease(booterData); 597 OSSafeRelease(aKext); 598 return; 599 } 600 601 /********************************************************************* 602 *********************************************************************/ 603 #define COM_APPLE "com.apple." 604 605 void 606 KLDBootstrap::loadSecurityExtensions(void) 607 { 608 OSDictionary * extensionsDict = NULL; // must release 609 OSCollectionIterator * keyIterator = NULL; // must release 610 OSString * bundleID = NULL; // don't release 611 OSKext * theKext = NULL; // don't release 612 OSBoolean * isSecurityKext = NULL; // don't release 613 614 OSKextLog(/* kext */ NULL, 615 kOSKextLogStepLevel | 616 kOSKextLogLoadFlag, 617 "Loading security extensions."); 618 619 extensionsDict = OSKext::copyKexts(); 620 if (!extensionsDict) { 621 return; 622 } 623 624 keyIterator = OSCollectionIterator::withCollection(extensionsDict); 625 if (!keyIterator) { 626 OSKextLog(/* kext */ NULL, 627 kOSKextLogErrorLevel | 628 kOSKextLogGeneralFlag, 629 "Failed to allocate iterator for security extensions."); 630 goto finish; 631 } 632 633 while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) { 634 635 const char * bundle_id = bundleID->getCStringNoCopy(); 636 637 /* Skip extensions whose bundle IDs don't start with "com.apple.". 638 */ 639 if (!bundle_id || 640 (strncmp(bundle_id, COM_APPLE, CONST_STRLEN(COM_APPLE)) != 0)) { 641 642 continue; 643 } 644 645 theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID)); 646 if (!theKext) { 647 continue; 648 } 649 650 isSecurityKext = OSDynamicCast(OSBoolean, 651 theKext->getPropertyForHostArch(kAppleSecurityExtensionKey)); 652 if (isSecurityKext && isSecurityKext->isTrue()) { 653 OSKextLog(/* kext */ NULL, 654 kOSKextLogStepLevel | 655 kOSKextLogLoadFlag, 656 "Loading security extension %s.", bundleID->getCStringNoCopy()); 657 OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(), 658 /* allowDefer */ false); 659 } 660 } 661 662 finish: 663 OSSafeRelease(keyIterator); 664 OSSafeRelease(extensionsDict); 665 666 return; 667 } 668 669 /********************************************************************* 670 * We used to require that all listed kernel components load, but 671 * nowadays we can get them from userland so we only try to load the 672 * ones we have. If an error occurs later, such is life. 673 * 674 * Note that we look the kexts up first, so we can avoid spurious 675 * (in this context, anyhow) log messages about kexts not being found. 676 * 677 * xxx - do we even need to do this any more? Check if the kernel 678 * xxx - compoonents just load in the regular paths 679 *********************************************************************/ 680 OSReturn 681 KLDBootstrap::loadKernelComponentKexts(void) 682 { 683 OSReturn result = kOSReturnSuccess; // optimistic 684 OSKext * theKext = NULL; // must release 685 const char ** kextIDPtr = NULL; // do not release 686 687 for (kextIDPtr = &sKernelComponentNames[0]; *kextIDPtr; kextIDPtr++) { 688 689 OSSafeReleaseNULL(theKext); 690 theKext = OSKext::lookupKextWithIdentifier(*kextIDPtr); 691 692 if (theKext) { 693 if (kOSReturnSuccess != OSKext::loadKextWithIdentifier( 694 *kextIDPtr, /* allowDefer */ false)) { 695 696 // xxx - check KextBookkeeping, might be redundant 697 OSKextLog(/* kext */ NULL, 698 kOSKextLogErrorLevel | 699 kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag, 700 "Failed to initialize kernel component %s.", *kextIDPtr); 701 result = kOSReturnError; 702 } 703 } 704 } 705 706 OSSafeRelease(theKext); 707 return result; 708 } 709 710 /********************************************************************* 711 * Ensure that Kernel External Components are loaded early in boot, 712 * before other kext personalities get sent to the IOCatalogue. These 713 * kexts are treated specially because they may provide the implementation 714 * for kernel-vended KPI, so they must register themselves before 715 * general purpose IOKit probing begins. 716 *********************************************************************/ 717 718 #define COM_APPLE_KEC "com.apple.kec." 719 720 void 721 KLDBootstrap::loadKernelExternalComponents(void) 722 { 723 OSDictionary * extensionsDict = NULL; // must release 724 OSCollectionIterator * keyIterator = NULL; // must release 725 OSString * bundleID = NULL; // don't release 726 OSKext * theKext = NULL; // don't release 727 OSBoolean * isKernelExternalComponent = NULL; // don't release 728 729 OSKextLog(/* kext */ NULL, 730 kOSKextLogStepLevel | 731 kOSKextLogLoadFlag, 732 "Loading Kernel External Components."); 733 734 extensionsDict = OSKext::copyKexts(); 735 if (!extensionsDict) { 736 return; 737 } 738 739 keyIterator = OSCollectionIterator::withCollection(extensionsDict); 740 if (!keyIterator) { 741 OSKextLog(/* kext */ NULL, 742 kOSKextLogErrorLevel | 743 kOSKextLogGeneralFlag, 744 "Failed to allocate iterator for Kernel External Components."); 745 goto finish; 746 } 747 748 while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) { 749 750 const char * bundle_id = bundleID->getCStringNoCopy(); 751 752 /* Skip extensions whose bundle IDs don't start with "com.apple.kec.". 753 */ 754 if (!bundle_id || 755 (strncmp(bundle_id, COM_APPLE_KEC, CONST_STRLEN(COM_APPLE_KEC)) != 0)) { 756 757 continue; 758 } 759 760 theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID)); 761 if (!theKext) { 762 continue; 763 } 764 765 isKernelExternalComponent = OSDynamicCast(OSBoolean, 766 theKext->getPropertyForHostArch(kAppleKernelExternalComponentKey)); 767 if (isKernelExternalComponent && isKernelExternalComponent->isTrue()) { 768 OSKextLog(/* kext */ NULL, 769 kOSKextLogStepLevel | 770 kOSKextLogLoadFlag, 771 "Loading kernel external component %s.", bundleID->getCStringNoCopy()); 772 OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(), 773 /* allowDefer */ false); 774 } 775 } 776 777 finish: 778 OSSafeRelease(keyIterator); 779 OSSafeRelease(extensionsDict); 780 781 return; 782 } 783 784 /********************************************************************* 785 *********************************************************************/ 786 void 787 KLDBootstrap::readBuiltinPersonalities(void) 788 { 789 OSObject * parsedXML = NULL; // must release 790 OSArray * builtinExtensions = NULL; // do not release 791 OSArray * allPersonalities = NULL; // must release 792 OSString * errorString = NULL; // must release 793 kernel_section_t * infosect = NULL; // do not free 794 OSCollectionIterator * personalitiesIterator = NULL; // must release 795 unsigned int count, i; 796 797 OSKextLog(/* kext */ NULL, 798 kOSKextLogStepLevel | 799 kOSKextLogLoadFlag, 800 "Reading built-in kernel personalities for I/O Kit drivers."); 801 802 /* Look in the __BUILTIN __info segment for an array of Info.plist 803 * entries. For each one, extract the personalities dictionary, add 804 * it to our array, then push them all (without matching) to 805 * the IOCatalogue. This can be used to augment the personalities 806 * in gIOKernelConfigTables, especially when linking entire kexts into 807 * the mach_kernel image. 808 */ 809 infosect = getsectbyname("__BUILTIN", "__info"); 810 if (!infosect) { 811 // this isn't fatal 812 goto finish; 813 } 814 815 parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr, 816 &errorString); 817 if (parsedXML) { 818 builtinExtensions = OSDynamicCast(OSArray, parsedXML); 819 } 820 if (!builtinExtensions) { 821 const char * errorCString = "(unknown error)"; 822 823 if (errorString && errorString->getCStringNoCopy()) { 824 errorCString = errorString->getCStringNoCopy(); 825 } else if (parsedXML) { 826 errorCString = "not an array"; 827 } 828 OSKextLog(/* kext */ NULL, 829 kOSKextLogErrorLevel | 830 kOSKextLogLoadFlag, 831 "Error unserializing built-in personalities: %s.", errorCString); 832 goto finish; 833 } 834 835 // estimate 3 personalities per Info.plist/kext 836 count = builtinExtensions->getCount(); 837 allPersonalities = OSArray::withCapacity(count * 3); 838 839 for (i = 0; i < count; i++) { 840 OSDictionary * infoDict = NULL; // do not release 841 OSString * moduleName = NULL; // do not release 842 OSDictionary * personalities; // do not release 843 OSString * personalityName; // do not release 844 845 OSSafeReleaseNULL(personalitiesIterator); 846 847 infoDict = OSDynamicCast(OSDictionary, 848 builtinExtensions->getObject(i)); 849 if (!infoDict) { 850 continue; 851 } 852 853 moduleName = OSDynamicCast(OSString, 854 infoDict->getObject(kCFBundleIdentifierKey)); 855 if (!moduleName) { 856 continue; 857 } 858 859 OSKextLog(/* kext */ NULL, 860 kOSKextLogStepLevel | 861 kOSKextLogLoadFlag, 862 "Adding personalities for built-in driver %s:", 863 moduleName->getCStringNoCopy()); 864 865 personalities = OSDynamicCast(OSDictionary, 866 infoDict->getObject("IOKitPersonalities")); 867 if (!personalities) { 868 continue; 869 } 870 871 personalitiesIterator = OSCollectionIterator::withCollection(personalities); 872 if (!personalitiesIterator) { 873 continue; // xxx - well really, what can we do? should we panic? 874 } 875 876 while ((personalityName = OSDynamicCast(OSString, 877 personalitiesIterator->getNextObject()))) { 878 879 OSDictionary * personality = OSDynamicCast(OSDictionary, 880 personalities->getObject(personalityName)); 881 882 OSKextLog(/* kext */ NULL, 883 kOSKextLogDetailLevel | 884 kOSKextLogLoadFlag, 885 "Adding built-in driver personality %s.", 886 personalityName->getCStringNoCopy()); 887 888 if (personality && !personality->getObject(kCFBundleIdentifierKey)) { 889 personality->setObject(kCFBundleIdentifierKey, moduleName); 890 } 891 allPersonalities->setObject(personality); 892 } 893 } 894 895 gIOCatalogue->addDrivers(allPersonalities, false); 896 897 finish: 898 OSSafeRelease(parsedXML); 899 OSSafeRelease(allPersonalities); 900 OSSafeRelease(errorString); 901 OSSafeRelease(personalitiesIterator); 902 return; 903 } 904 905 #if PRAGMA_MARK 906 #pragma mark Bootstrap Functions 907 #endif 908 /********************************************************************* 909 * Bootstrap Functions 910 *********************************************************************/ 911 static void bootstrapRecordStartupExtensions(void) 912 { 913 sBootstrapObject.readStartupExtensions(); 914 return; 915 } 916 917 static void bootstrapLoadSecurityExtensions(void) 918 { 919 sBootstrapObject.loadSecurityExtensions(); 920 return; 921 } 922 923