xref: /xnu-11215/libsa/bootstrap.cpp (revision 88cc0b97)
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