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