2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach/kmod.h>
30 #include <libkern/kernel_mach_header.h>
31 #include <libkern/prelink.h>
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>
45 #define KASLR_KEXT_DEBUG 0
49 #pragma mark Bootstrap Declarations
51 /*********************************************************************
52 * Bootstrap Declarations
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.
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.
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
65 *********************************************************************/
67 extern void (*record_startup_extensions_function
)(void);
68 extern void (*load_security_extensions_function
)(void);
71 static void bootstrapRecordStartupExtensions(void);
72 static void bootstrapLoadSecurityExtensions(void);
76 extern "C" bool IORamDiskBSDRoot(void);
82 /*********************************************************************
84 *********************************************************************/
85 #define CONST_STRLEN(str) (sizeof(str) - 1)
88 #pragma mark Kernel Component Kext Identifiers
90 /*********************************************************************
91 * Kernel Component Kext Identifiers
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'.
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",
115 static int __whereIsAddr(vm_offset_t theAddr
, unsigned long * segSizes
, vm_offset_t
*segAddrs
, int segCount
);
117 #define PLK_SEGMENTS 12
119 static const char * plk_segNames
[] = {
136 #pragma mark KLDBootstrap Class
138 /*********************************************************************
141 * We use a C++ class here so that it can be a friend of OSKext and
142 * get at private stuff. We can't hide the class itself, but we can
143 * hide the instance through which we invoke the functions.
144 *********************************************************************/
146 friend void bootstrapRecordStartupExtensions(void);
147 friend void bootstrapLoadSecurityExtensions(void);
150 void readStartupExtensions(void);
152 void readPrelinkedExtensions(
153 kernel_section_t
* prelinkInfoSect
);
154 void readBooterExtensions(void);
156 OSReturn
loadKernelComponentKexts(void);
157 void loadKernelExternalComponents(void);
158 void readBuiltinPersonalities(void);
160 void loadSecurityExtensions(void);
167 static KLDBootstrap sBootstrapObject
;
169 /*********************************************************************
170 * Set the function pointers for the entry points into the bootstrap
171 * segment upon C++ static constructor invocation.
172 *********************************************************************/
173 KLDBootstrap::KLDBootstrap(void)
175 if (this != &sBootstrapObject
) {
176 panic("Attempt to access bootstrap segment.");
178 record_startup_extensions_function
= &bootstrapRecordStartupExtensions
;
179 load_security_extensions_function
= &bootstrapLoadSecurityExtensions
;
182 /*********************************************************************
183 * Clear the function pointers for the entry points into the bootstrap
184 * segment upon C++ static destructor invocation.
185 *********************************************************************/
186 KLDBootstrap::~KLDBootstrap(void)
188 if (this != &sBootstrapObject
) {
189 panic("Attempt to access bootstrap segment.");
193 record_startup_extensions_function
= 0;
194 load_security_extensions_function
= 0;
197 /*********************************************************************
198 *********************************************************************/
200 KLDBootstrap::readStartupExtensions(void)
202 kernel_section_t
* prelinkInfoSect
= NULL
; // do not free
204 OSKextLog(/* kext */ NULL
,
205 kOSKextLogProgressLevel
|
206 kOSKextLogGeneralFlag
| kOSKextLogDirectoryScanFlag
|
207 kOSKextLogKextBookkeepingFlag
,
208 "Reading startup extensions.");
210 /* If the prelink info segment has a nonzero size, we are prelinked
211 * and won't have any individual kexts or mkexts to read.
212 * Otherwise, we need to read kexts or the mkext from what the booter
215 prelinkInfoSect
= getsectbyname(kPrelinkInfoSegment
, kPrelinkInfoSection
);
216 if (prelinkInfoSect
->size
) {
217 readPrelinkedExtensions(prelinkInfoSect
);
219 readBooterExtensions();
222 loadKernelComponentKexts();
223 loadKernelExternalComponents();
224 readBuiltinPersonalities();
225 OSKext::sendAllKextPersonalitiesToCatalog();
230 typedef struct kaslrPackedOffsets
{
231 uint32_t count
; /* number of offsets */
232 uint32_t offsetsArray
[]; /* offsets to slide */
233 } kaslrPackedOffsets
;
235 /*********************************************************************
236 *********************************************************************/
238 KLDBootstrap::readPrelinkedExtensions(
239 kernel_section_t
* prelinkInfoSect
)
241 OSArray
* infoDictArray
= NULL
; // do not release
242 OSObject
* parsedXML
= NULL
; // must release
243 OSDictionary
* prelinkInfoDict
= NULL
; // do not release
244 OSString
* errorString
= NULL
; // must release
245 OSKext
* theKernel
= NULL
; // must release
247 kernel_segment_command_t
* prelinkTextSegment
= NULL
; // see code
248 kernel_segment_command_t
* prelinkInfoSegment
= NULL
; // see code
250 /* We make some copies of data, but if anything fails we're basically
251 * going to fail the boot, so these won't be cleaned up on error.
253 void * prelinkData
= NULL
; // see code
254 vm_size_t prelinkLength
= 0;
257 OSDictionary
* infoDict
= NULL
; // do not release
259 IORegistryEntry
* registryRoot
= NULL
; // do not release
260 OSNumber
* prelinkCountObj
= NULL
; // must release
265 bool developerDevice
;
268 OSData
* kaslrOffsets
= NULL
;
269 unsigned long plk_segSizes
[PLK_SEGMENTS
];
270 vm_offset_t plk_segAddrs
[PLK_SEGMENTS
];
272 OSKextLog(/* kext */ NULL
,
273 kOSKextLogProgressLevel
|
274 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
275 "Starting from prelinked kernel.");
277 prelinkTextSegment
= getsegbyname(kPrelinkTextSegment
);
278 if (!prelinkTextSegment
) {
279 OSKextLog(/* kext */ NULL
,
280 kOSKextLogErrorLevel
|
281 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
282 "Can't find prelinked kexts' text segment.");
287 unsigned long scratchSize
;
288 vm_offset_t scratchAddr
;
290 IOLog("kaslr: prelinked kernel address info: \n");
292 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__TEXT", &scratchSize
);
293 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n",
294 (unsigned long)scratchAddr
,
295 (unsigned long)(scratchAddr
+ scratchSize
),
298 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__DATA", &scratchSize
);
299 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n",
300 (unsigned long)scratchAddr
,
301 (unsigned long)(scratchAddr
+ scratchSize
),
304 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__LINKEDIT", &scratchSize
);
305 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n",
306 (unsigned long)scratchAddr
,
307 (unsigned long)(scratchAddr
+ scratchSize
),
310 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__KLD", &scratchSize
);
311 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n",
312 (unsigned long)scratchAddr
,
313 (unsigned long)(scratchAddr
+ scratchSize
),
316 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__PRELINK_TEXT", &scratchSize
);
317 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n",
318 (unsigned long)scratchAddr
,
319 (unsigned long)(scratchAddr
+ scratchSize
),
322 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__PRELINK_INFO", &scratchSize
);
323 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n",
324 (unsigned long)scratchAddr
,
325 (unsigned long)(scratchAddr
+ scratchSize
),
329 prelinkData
= (void *) prelinkTextSegment
->vmaddr
;
330 prelinkLength
= prelinkTextSegment
->vmsize
;
332 /* build arrays of plk info for later use */
333 const char ** segNamePtr
;
335 for (segNamePtr
= &plk_segNames
[0], i
= 0; *segNamePtr
&& i
< PLK_SEGMENTS
; segNamePtr
++, i
++) {
337 plk_segAddrs
[i
] = (vm_offset_t
)getsegdatafromheader(&_mh_execute_header
, *segNamePtr
, &plk_segSizes
[i
]);
341 /* Unserialize the info dictionary from the prelink info section.
343 parsedXML
= OSUnserializeXML((const char *)prelinkInfoSect
->addr
,
346 prelinkInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
348 if (!prelinkInfoDict
) {
349 const char * errorCString
= "(unknown error)";
351 if (errorString
&& errorString
->getCStringNoCopy()) {
352 errorCString
= errorString
->getCStringNoCopy();
353 } else if (parsedXML
) {
354 errorCString
= "not a dictionary";
356 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
357 "Error unserializing prelink plist: %s.", errorCString
);
362 /* Check if we should keep developer kexts around.
363 * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201>
365 developerDevice
= true;
366 PE_parse_boot_argn("developer", &developerDevice
, sizeof(developerDevice
));
368 ramDiskBoot
= IORamDiskBSDRoot();
369 #endif /* NO_KEXTD */
372 infoDictArray
= OSDynamicCast(OSArray
,
373 prelinkInfoDict
->getObject(kPrelinkInfoDictionaryKey
));
374 if (!infoDictArray
) {
375 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
376 "The prelinked kernel has no kext info dictionaries");
380 /* kaslrOffsets are available use them to slide local relocations */
381 kaslrOffsets
= OSDynamicCast(OSData
,
382 prelinkInfoDict
->getObject(kPrelinkLinkKASLROffsetsKey
));
384 /* Create dictionary of excluded kexts
386 OSKext::createExcludeListFromPrelinkInfo(infoDictArray
);
387 /* Create OSKext objects for each info dictionary.
389 for (i
= 0; i
< infoDictArray
->getCount(); ++i
) {
390 infoDict
= OSDynamicCast(OSDictionary
, infoDictArray
->getObject(i
));
392 OSKextLog(/* kext */ NULL
,
393 kOSKextLogErrorLevel
|
394 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
395 "Can't find info dictionary for prelinked kext #%d.", i
);
402 /* If we're not on a developer device, skip and free developer kexts.
404 if (developerDevice
== false) {
405 OSBoolean
*devOnlyBool
= OSDynamicCast(OSBoolean
,
406 infoDict
->getObject(kOSBundleDeveloperOnlyKey
));
407 if (devOnlyBool
== kOSBooleanTrue
) {
412 /* Skip and free kexts that are only needed when booted from a ram disk.
414 if (ramDiskBoot
== false) {
415 OSBoolean
*ramDiskOnlyBool
= OSDynamicCast(OSBoolean
,
416 infoDict
->getObject(kOSBundleRamDiskOnlyKey
));
417 if (ramDiskOnlyBool
== kOSBooleanTrue
) {
422 if (dontLoad
== true) {
423 OSString
*bundleID
= OSDynamicCast(OSString
,
424 infoDict
->getObject(kCFBundleIdentifierKey
));
426 OSKextLog(NULL
, kOSKextLogWarningLevel
| kOSKextLogGeneralFlag
,
427 "Kext %s not loading.", bundleID
->getCStringNoCopy());
430 OSNumber
*addressNum
= OSDynamicCast(OSNumber
,
431 infoDict
->getObject(kPrelinkExecutableLoadKey
));
432 OSNumber
*lengthNum
= OSDynamicCast(OSNumber
,
433 infoDict
->getObject(kPrelinkExecutableSizeKey
));
434 if (addressNum
&& lengthNum
) {
435 #error Pick the right way to free prelinked data on this arch
438 infoDictArray
->removeObject(i
--);
441 #endif /* NO_KEXTD */
443 /* Create the kext for the entry, then release it, because the
444 * kext system keeps them around until explicitly removed.
445 * Any creation/registration failures are already logged for us.
447 OSKext
* newKext
= OSKext::withPrelinkedInfoDict(infoDict
, (kaslrOffsets
? TRUE
: FALSE
));
448 OSSafeReleaseNULL(newKext
);
451 /* slide kxld relocations */
452 if (kaslrOffsets
&& vm_kernel_slide
> 0) {
453 int slidKextAddrCount
= 0;
454 int badSlideAddr
= 0;
455 int badSlideTarget
= 0;
457 kaslrPackedOffsets
* myOffsets
= NULL
;
458 myOffsets
= (kaslrPackedOffsets
*) kaslrOffsets
->getBytesNoCopy();
460 for (uint32_t j
= 0; j
< myOffsets
->count
; j
++) {
462 uint64_t slideOffset
= (uint64_t) myOffsets
->offsetsArray
[j
];
463 uintptr_t * slideAddr
= (uintptr_t *) ((uint64_t)prelinkData
+ slideOffset
);
464 int slideAddrSegIndex
= -1;
465 int addrToSlideSegIndex
= -1;
467 slideAddrSegIndex
= __whereIsAddr( (vm_offset_t
)slideAddr
, &plk_segSizes
[0], &plk_segAddrs
[0], PLK_SEGMENTS
);
468 if (slideAddrSegIndex
>= 0) {
469 addrToSlideSegIndex
= __whereIsAddr( (vm_offset_t
)(*slideAddr
+ vm_kernel_slide
), &plk_segSizes
[0], &plk_segAddrs
[0], PLK_SEGMENTS
);
470 if (addrToSlideSegIndex
< 0) {
481 *(slideAddr
) += vm_kernel_slide
;
484 /* All kexts are now slid, set VM protections for them */
485 OSKext::setAllVMAttributes();
488 /* Store the number of prelinked kexts in the registry so we can tell
489 * when the system has been started from a prelinked kernel.
491 registryRoot
= IORegistryEntry::getRegistryRoot();
492 assert(registryRoot
);
494 prelinkCountObj
= OSNumber::withNumber(
495 (unsigned long long)infoDictArray
->getCount(),
496 8 * sizeof(uint32_t));
497 assert(prelinkCountObj
);
498 if (prelinkCountObj
) {
499 registryRoot
->setProperty(kOSPrelinkKextCountKey
, prelinkCountObj
);
502 OSKextLog(/* kext */ NULL
,
503 kOSKextLogProgressLevel
|
504 kOSKextLogGeneralFlag
| kOSKextLogKextBookkeepingFlag
|
505 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
506 "%u prelinked kexts",
507 infoDictArray
->getCount());
509 #if CONFIG_KEXT_BASEMENT
510 /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own
511 * special VM region during OSKext init time, so we can free the whole
514 ml_static_mfree((vm_offset_t
) prelinkData
, prelinkLength
);
515 #endif /* __x86_64__ */
517 /* Free the prelink info segment, we're done with it.
519 prelinkInfoSegment
= getsegbyname(kPrelinkInfoSegment
);
520 if (prelinkInfoSegment
) {
521 ml_static_mfree((vm_offset_t
)prelinkInfoSegment
->vmaddr
,
522 (vm_size_t
)prelinkInfoSegment
->vmsize
);
526 OSSafeReleaseNULL(errorString
);
527 OSSafeReleaseNULL(parsedXML
);
528 OSSafeReleaseNULL(theKernel
);
529 OSSafeReleaseNULL(prelinkCountObj
);
533 static int __whereIsAddr(vm_offset_t theAddr
, unsigned long * segSizes
, vm_offset_t
*segAddrs
, int segCount
)
537 for (i
= 0; i
< segCount
; i
++) {
538 vm_offset_t myAddr
= *(segAddrs
+ i
);
539 unsigned long mySize
= *(segSizes
+ i
);
541 if (theAddr
>= myAddr
&& theAddr
< (myAddr
+ mySize
)) {
550 /*********************************************************************
551 *********************************************************************/
552 #define BOOTER_KEXT_PREFIX "Driver-"
554 typedef struct _DeviceTreeBuffer
{
560 KLDBootstrap::readBooterExtensions(void)
562 IORegistryEntry
* booterMemoryMap
= NULL
; // must release
563 OSDictionary
* propertyDict
= NULL
; // must release
564 OSCollectionIterator
* keyIterator
= NULL
; // must release
565 OSString
* deviceTreeName
= NULL
; // do not release
567 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not free
568 char * booterDataPtr
= NULL
; // do not free
569 OSData
* booterData
= NULL
; // must release
571 OSKext
* aKext
= NULL
; // must release
573 OSKextLog(/* kext */ NULL
,
574 kOSKextLogProgressLevel
|
575 kOSKextLogDirectoryScanFlag
| kOSKextLogKextBookkeepingFlag
,
576 "Reading startup extensions from booter memory.");
578 booterMemoryMap
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
580 if (!booterMemoryMap
) {
581 OSKextLog(/* kext */ NULL
,
582 kOSKextLogErrorLevel
|
583 kOSKextLogGeneralFlag
| kOSKextLogDirectoryScanFlag
,
584 "Can't read booter memory map.");
588 propertyDict
= booterMemoryMap
->dictionaryWithProperties();
590 OSKextLog(/* kext */ NULL
,
591 kOSKextLogErrorLevel
|
592 kOSKextLogDirectoryScanFlag
,
593 "Can't get property dictionary from memory map.");
597 keyIterator
= OSCollectionIterator::withCollection(propertyDict
);
599 OSKextLog(/* kext */ NULL
,
600 kOSKextLogErrorLevel
|
601 kOSKextLogGeneralFlag
,
602 "Can't allocate iterator for driver images.");
606 /* Create dictionary of excluded kexts
608 OSKext::createExcludeListFromBooterData(propertyDict
, keyIterator
);
609 keyIterator
->reset();
611 while ( ( deviceTreeName
=
612 OSDynamicCast(OSString
, keyIterator
->getNextObject() ))) {
614 const char * devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
615 OSData
* deviceTreeEntry
= OSDynamicCast(OSData
,
616 propertyDict
->getObject(deviceTreeName
));
618 /* Clear out the booterData from the prior iteration.
620 OSSafeReleaseNULL(booterData
);
622 /* If there is no entry for the name, we can't do much with it. */
623 if (!deviceTreeEntry
) {
627 /* Make sure it is a kext */
628 if (strncmp(devTreeNameCString
,
630 CONST_STRLEN(BOOTER_KEXT_PREFIX
))) {
634 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
635 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
636 if (!deviceTreeBuffer
) {
637 /* We can't get to the data, so we can't do anything,
638 * not even free it from physical memory (if it's there).
640 OSKextLog(/* kext */ NULL
,
641 kOSKextLogErrorLevel
|
642 kOSKextLogDirectoryScanFlag
,
643 "Device tree entry %s has NULL pointer.",
645 goto finish
; // xxx - continue, panic?
648 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
649 if (!booterDataPtr
) {
650 OSKextLog(/* kext */ NULL
,
651 kOSKextLogErrorLevel
|
652 kOSKextLogDirectoryScanFlag
,
653 "Can't get virtual address for device tree entry %s.",
658 /* Wrap the booter data buffer in an OSData and set a dealloc function
659 * so it will take care of the physical memory when freed. Kexts will
660 * retain the booterData for as long as they need it. Remove the entry
661 * from the booter memory map after this is done.
663 booterData
= OSData::withBytesNoCopy(booterDataPtr
,
664 deviceTreeBuffer
->length
);
666 OSKextLog(/* kext */ NULL
,
667 kOSKextLogErrorLevel
|
668 kOSKextLogGeneralFlag
,
669 "Error - Can't allocate OSData wrapper for device tree entry %s.",
673 booterData
->setDeallocFunction(osdata_phys_free
);
675 /* Create the kext for the entry, then release it, because the
676 * kext system keeps them around until explicitly removed.
677 * Any creation/registration failures are already logged for us.
679 OSKext
* newKext
= OSKext::withBooterData(deviceTreeName
, booterData
);
680 OSSafeReleaseNULL(newKext
);
682 booterMemoryMap
->removeProperty(deviceTreeName
);
684 } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
688 OSSafeReleaseNULL(booterMemoryMap
);
689 OSSafeReleaseNULL(propertyDict
);
690 OSSafeReleaseNULL(keyIterator
);
691 OSSafeReleaseNULL(booterData
);
692 OSSafeReleaseNULL(aKext
);
696 /*********************************************************************
697 *********************************************************************/
698 #define COM_APPLE "com.apple."
701 KLDBootstrap::loadSecurityExtensions(void)
703 OSDictionary
* extensionsDict
= NULL
; // must release
704 OSCollectionIterator
* keyIterator
= NULL
; // must release
705 OSString
* bundleID
= NULL
; // don't release
706 OSKext
* theKext
= NULL
; // don't release
707 OSBoolean
* isSecurityKext
= NULL
; // don't release
709 OSKextLog(/* kext */ NULL
,
710 kOSKextLogStepLevel
|
712 "Loading security extensions.");
714 extensionsDict
= OSKext::copyKexts();
715 if (!extensionsDict
) {
719 keyIterator
= OSCollectionIterator::withCollection(extensionsDict
);
721 OSKextLog(/* kext */ NULL
,
722 kOSKextLogErrorLevel
|
723 kOSKextLogGeneralFlag
,
724 "Failed to allocate iterator for security extensions.");
728 while ((bundleID
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
730 const char * bundle_id
= bundleID
->getCStringNoCopy();
732 /* Skip extensions whose bundle IDs don't start with "com.apple.".
735 (strncmp(bundle_id
, COM_APPLE
, CONST_STRLEN(COM_APPLE
)) != 0)) {
740 theKext
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
));
745 isSecurityKext
= OSDynamicCast(OSBoolean
,
746 theKext
->getPropertyForHostArch(kAppleSecurityExtensionKey
));
747 if (isSecurityKext
&& isSecurityKext
->isTrue()) {
748 OSKextLog(/* kext */ NULL
,
749 kOSKextLogStepLevel
|
751 "Loading security extension %s.", bundleID
->getCStringNoCopy());
752 OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(),
753 /* allowDefer */ false);
758 OSSafeReleaseNULL(keyIterator
);
759 OSSafeReleaseNULL(extensionsDict
);
764 /*********************************************************************
765 * We used to require that all listed kernel components load, but
766 * nowadays we can get them from userland so we only try to load the
767 * ones we have. If an error occurs later, such is life.
769 * Note that we look the kexts up first, so we can avoid spurious
770 * (in this context, anyhow) log messages about kexts not being found.
772 * xxx - do we even need to do this any more? Check if the kernel
773 * xxx - compoonents just load in the regular paths
774 *********************************************************************/
776 KLDBootstrap::loadKernelComponentKexts(void)
778 OSReturn result
= kOSReturnSuccess
; // optimistic
779 OSKext
* theKext
= NULL
; // must release
780 const char ** kextIDPtr
= NULL
; // do not release
782 for (kextIDPtr
= &sKernelComponentNames
[0]; *kextIDPtr
; kextIDPtr
++) {
784 OSSafeReleaseNULL(theKext
);
785 theKext
= OSKext::lookupKextWithIdentifier(*kextIDPtr
);
788 if (kOSReturnSuccess
!= OSKext::loadKextWithIdentifier(
789 *kextIDPtr
, /* allowDefer */ false)) {
791 // xxx - check KextBookkeeping, might be redundant
792 OSKextLog(/* kext */ NULL
,
793 kOSKextLogErrorLevel
|
794 kOSKextLogDirectoryScanFlag
| kOSKextLogKextBookkeepingFlag
,
795 "Failed to initialize kernel component %s.", *kextIDPtr
);
796 result
= kOSReturnError
;
801 OSSafeReleaseNULL(theKext
);
805 /*********************************************************************
806 * Ensure that Kernel External Components are loaded early in boot,
807 * before other kext personalities get sent to the IOCatalogue. These
808 * kexts are treated specially because they may provide the implementation
809 * for kernel-vended KPI, so they must register themselves before
810 * general purpose IOKit probing begins.
811 *********************************************************************/
813 #define COM_APPLE_KEC "com.apple.kec."
816 KLDBootstrap::loadKernelExternalComponents(void)
818 OSDictionary
* extensionsDict
= NULL
; // must release
819 OSCollectionIterator
* keyIterator
= NULL
; // must release
820 OSString
* bundleID
= NULL
; // don't release
821 OSKext
* theKext
= NULL
; // don't release
822 OSBoolean
* isKernelExternalComponent
= NULL
; // don't release
824 OSKextLog(/* kext */ NULL
,
825 kOSKextLogStepLevel
|
827 "Loading Kernel External Components.");
829 extensionsDict
= OSKext::copyKexts();
830 if (!extensionsDict
) {
834 keyIterator
= OSCollectionIterator::withCollection(extensionsDict
);
836 OSKextLog(/* kext */ NULL
,
837 kOSKextLogErrorLevel
|
838 kOSKextLogGeneralFlag
,
839 "Failed to allocate iterator for Kernel External Components.");
843 while ((bundleID
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
845 const char * bundle_id
= bundleID
->getCStringNoCopy();
847 /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
850 (strncmp(bundle_id
, COM_APPLE_KEC
, CONST_STRLEN(COM_APPLE_KEC
)) != 0)) {
855 theKext
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
));
860 isKernelExternalComponent
= OSDynamicCast(OSBoolean
,
861 theKext
->getPropertyForHostArch(kAppleKernelExternalComponentKey
));
862 if (isKernelExternalComponent
&& isKernelExternalComponent
->isTrue()) {
863 OSKextLog(/* kext */ NULL
,
864 kOSKextLogStepLevel
|
866 "Loading kernel external component %s.", bundleID
->getCStringNoCopy());
867 OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(),
868 /* allowDefer */ false);
873 OSSafeReleaseNULL(keyIterator
);
874 OSSafeReleaseNULL(extensionsDict
);
879 /*********************************************************************
880 *********************************************************************/
882 KLDBootstrap::readBuiltinPersonalities(void)
884 OSObject
* parsedXML
= NULL
; // must release
885 OSArray
* builtinExtensions
= NULL
; // do not release
886 OSArray
* allPersonalities
= NULL
; // must release
887 OSString
* errorString
= NULL
; // must release
888 kernel_section_t
* infosect
= NULL
; // do not free
889 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
890 unsigned int count
, i
;
892 OSKextLog(/* kext */ NULL
,
893 kOSKextLogStepLevel
|
895 "Reading built-in kernel personalities for I/O Kit drivers.");
897 /* Look in the __BUILTIN __info segment for an array of Info.plist
898 * entries. For each one, extract the personalities dictionary, add
899 * it to our array, then push them all (without matching) to
900 * the IOCatalogue. This can be used to augment the personalities
901 * in gIOKernelConfigTables, especially when linking entire kexts into
902 * the mach_kernel image.
904 infosect
= getsectbyname("__BUILTIN", "__info");
910 parsedXML
= OSUnserializeXML((const char *) (uintptr_t)infosect
->addr
,
913 builtinExtensions
= OSDynamicCast(OSArray
, parsedXML
);
915 if (!builtinExtensions
) {
916 const char * errorCString
= "(unknown error)";
918 if (errorString
&& errorString
->getCStringNoCopy()) {
919 errorCString
= errorString
->getCStringNoCopy();
920 } else if (parsedXML
) {
921 errorCString
= "not an array";
923 OSKextLog(/* kext */ NULL
,
924 kOSKextLogErrorLevel
|
926 "Error unserializing built-in personalities: %s.", errorCString
);
930 // estimate 3 personalities per Info.plist/kext
931 count
= builtinExtensions
->getCount();
932 allPersonalities
= OSArray::withCapacity(count
* 3);
934 for (i
= 0; i
< count
; i
++) {
935 OSDictionary
* infoDict
= NULL
; // do not release
936 OSString
* moduleName
= NULL
; // do not release
937 OSDictionary
* personalities
; // do not release
938 OSString
* personalityName
; // do not release
940 OSSafeReleaseNULL(personalitiesIterator
);
942 infoDict
= OSDynamicCast(OSDictionary
,
943 builtinExtensions
->getObject(i
));
948 moduleName
= OSDynamicCast(OSString
,
949 infoDict
->getObject(kCFBundleIdentifierKey
));
954 OSKextLog(/* kext */ NULL
,
955 kOSKextLogStepLevel
|
957 "Adding personalities for built-in driver %s:",
958 moduleName
->getCStringNoCopy());
960 personalities
= OSDynamicCast(OSDictionary
,
961 infoDict
->getObject("IOKitPersonalities"));
962 if (!personalities
) {
966 personalitiesIterator
= OSCollectionIterator::withCollection(personalities
);
967 if (!personalitiesIterator
) {
968 continue; // xxx - well really, what can we do? should we panic?
971 while ((personalityName
= OSDynamicCast(OSString
,
972 personalitiesIterator
->getNextObject()))) {
974 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
975 personalities
->getObject(personalityName
));
977 OSKextLog(/* kext */ NULL
,
978 kOSKextLogDetailLevel
|
980 "Adding built-in driver personality %s.",
981 personalityName
->getCStringNoCopy());
983 if (personality
&& !personality
->getObject(kCFBundleIdentifierKey
)) {
984 personality
->setObject(kCFBundleIdentifierKey
, moduleName
);
986 allPersonalities
->setObject(personality
);
990 gIOCatalogue
->addDrivers(allPersonalities
, false);
993 OSSafeReleaseNULL(parsedXML
);
994 OSSafeReleaseNULL(allPersonalities
);
995 OSSafeReleaseNULL(errorString
);
996 OSSafeReleaseNULL(personalitiesIterator
);
1001 #pragma mark Bootstrap Functions
1003 /*********************************************************************
1004 * Bootstrap Functions
1005 *********************************************************************/
1006 static void bootstrapRecordStartupExtensions(void)
1008 sBootstrapObject
.readStartupExtensions();
1012 static void bootstrapLoadSecurityExtensions(void)
1014 sBootstrapObject
.loadSecurityExtensions();