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 */ 28extern "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*********************************************************************/ 65extern "C" { 66 extern void (*record_startup_extensions_function)(void); 67 extern void (*load_security_extensions_function)(void); 68}; 69 70static void bootstrapRecordStartupExtensions(void); 71static void bootstrapLoadSecurityExtensions(void); 72 73 74#if NO_KEXTD 75extern "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*********************************************************************/ 97static 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*********************************************************************/ 124class KLDBootstrap { 125 friend void bootstrapRecordStartupExtensions(void); 126 friend void bootstrapLoadSecurityExtensions(void); 127 128private: 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 141public: 142 KLDBootstrap(void); 143 ~KLDBootstrap(void); 144}; 145 146static KLDBootstrap sBootstrapObject; 147 148/********************************************************************* 149* Set the function pointers for the entry points into the bootstrap 150* segment upon C++ static constructor invocation. 151*********************************************************************/ 152KLDBootstrap::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*********************************************************************/ 165KLDBootstrap::~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*********************************************************************/ 178void 179KLDBootstrap::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*********************************************************************/ 211void 212KLDBootstrap::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 447finish: 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 459typedef struct _DeviceTreeBuffer { 460 uint32_t paddr; 461 uint32_t length; 462} _DeviceTreeBuffer; 463 464void 465KLDBootstrap::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 591finish: 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 605void 606KLDBootstrap::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 662finish: 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*********************************************************************/ 680OSReturn 681KLDBootstrap::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 720void 721KLDBootstrap::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 777finish: 778 OSSafeRelease(keyIterator); 779 OSSafeRelease(extensionsDict); 780 781 return; 782} 783 784/********************************************************************* 785 *********************************************************************/ 786void 787KLDBootstrap::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 897finish: 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*********************************************************************/ 911static void bootstrapRecordStartupExtensions(void) 912{ 913 sBootstrapObject.readStartupExtensions(); 914 return; 915} 916 917static void bootstrapLoadSecurityExtensions(void) 918{ 919 sBootstrapObject.loadSecurityExtensions(); 920 return; 921} 922 923