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