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