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