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 */
28extern "C" {
29#include <mach/kmod.h>
30#include <libkern/kernel_mach_header.h>
31#include <libkern/prelink.h>
32}
33
34#include <libkern/version.h>
35#include <libkern/c++/OSContainers.h>
36#include <libkern/OSKextLibPrivate.h>
37#include <libkern/c++/OSKext.h>
38#include <IOKit/IOLib.h>
39#include <IOKit/IOService.h>
40#include <IOKit/IODeviceTreeSupport.h>
41#include <IOKit/IOCatalogue.h>
42
43#if __x86_64__
44#define KASLR_KEXT_DEBUG 0
45#endif
46
47#if PRAGMA_MARK
48#pragma mark Bootstrap Declarations
49#endif
50/*********************************************************************
51* Bootstrap Declarations
52*
53* The ENTIRE point of the libsa/KLD segment is to isolate bootstrap
54* code from other parts of the kernel, so function symbols are not
55* exported; rather pointers to those functions are exported.
56*
57* xxx - need to think about locking for handling the 'weak' refs.
58* xxx - do export a non-KLD function that says you've called a
59* xxx - bootstrap function that has been removed.
60*
61* ALL call-ins to this segment of the kernel must be done through
62* exported pointers. The symbols themselves are private and not to
63* be linked against.
64*********************************************************************/
65extern "C" {
66 extern void (*record_startup_extensions_function)(void);
67 extern void (*load_security_extensions_function)(void);
68};
69
70static void bootstrapRecordStartupExtensions(void);
71static void bootstrapLoadSecurityExtensions(void);
72
73
74#if NO_KEXTD
75extern "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*********************************************************************/
97static 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
115static int __whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount );
116
117#define PLK_SEGMENTS 12
118
119static 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*********************************************************************/
145class KLDBootstrap {
146 friend void bootstrapRecordStartupExtensions(void);
147 friend void bootstrapLoadSecurityExtensions(void);
148
149private:
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
162public:
163 KLDBootstrap(void);
164 ~KLDBootstrap(void);
165};
166
167static KLDBootstrap sBootstrapObject;
168
169/*********************************************************************
170* Set the function pointers for the entry points into the bootstrap
171* segment upon C++ static constructor invocation.
172*********************************************************************/
173KLDBootstrap::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*********************************************************************/
186KLDBootstrap::~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*********************************************************************/
199void
200KLDBootstrap::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
230typedef struct kaslrPackedOffsets {
231 uint32_t count; /* number of offsets */
232 uint32_t offsetsArray[]; /* offsets to slide */
233} kaslrPackedOffsets;
234
235/*********************************************************************
236*********************************************************************/
237void
238KLDBootstrap::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
547finish:
548 OSSafeReleaseNULL(errorString);
549 OSSafeReleaseNULL(parsedXML);
550 OSSafeReleaseNULL(theKernel);
551 OSSafeReleaseNULL(prelinkCountObj);
552 return;
553}
554
555static 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
576typedef struct _DeviceTreeBuffer {
577 uint32_t paddr;
578 uint32_t length;
579} _DeviceTreeBuffer;
580
581void
582KLDBootstrap::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
710finish:
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
724void
725KLDBootstrap::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
781finish:
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*********************************************************************/
799OSReturn
800KLDBootstrap::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
839void
840KLDBootstrap::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
896finish:
897 OSSafeReleaseNULL(keyIterator);
898 OSSafeReleaseNULL(extensionsDict);
899
900 return;
901}
902
903/*********************************************************************
904 *********************************************************************/
905void
906KLDBootstrap::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
1016finish:
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*********************************************************************/
1030static void bootstrapRecordStartupExtensions(void)
1031{
1032 sBootstrapObject.readStartupExtensions();
1033 return;
1034}
1035
1036static void bootstrapLoadSecurityExtensions(void)
1037{
1038 sBootstrapObject.loadSecurityExtensions();
1039 return;
1040}
1041
1042