1/*
2 * Copyright (c) 2008-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
29extern "C" {
30#include <kern/clock.h>
31#include <kern/host.h>
32#include <kern/kext_alloc.h>
33#include <kextd/kextd_mach.h>
34#include <libkern/kernel_mach_header.h>
35#include <libkern/kext_panic_report.h>
36#include <libkern/kext_request_keys.h>
37#include <libkern/mkext.h>
38#include <libkern/prelink.h>
39#include <libkern/version.h>
40#include <libkern/zlib.h>
41#include <mach/host_special_ports.h>
42#include <mach/mach_vm.h>
43#include <mach/mach_time.h>
44#include <sys/sysctl.h>
45#include <uuid/uuid.h>
46// 04/18/11 - gab: <rdar://problem/9236163>
47#include <sys/random.h>
48
49#if CONFIG_MACF
50#include <sys/kauth.h>
51#include <security/mac_framework.h>
52#endif
53};
54
55#include <libkern/OSKextLibPrivate.h>
56#include <libkern/c++/OSKext.h>
57#include <libkern/c++/OSLib.h>
58
59#include <IOKit/IOLib.h>
60#include <IOKit/IOCatalogue.h>
61#include <IOKit/IORegistryEntry.h>
62#include <IOKit/IOService.h>
63
64#include <IOKit/IOStatisticsPrivate.h>
65
66#if PRAGMA_MARK
67#pragma mark External & Internal Function Protos
68#endif
69/*********************************************************************
70*********************************************************************/
71extern "C" {
72extern int  IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
73extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
74extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t * segment);
75extern void OSRuntimeUnloadCPP(kmod_info_t * ki, void * data);
76
77extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
78}
79
80static OSReturn _OSKextCreateRequest(
81    const char    * predicate,
82    OSDictionary ** requestP);
83static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
84static OSObject * _OSKextGetRequestArgument(
85    OSDictionary * requestDict,
86    const char   * argName);
87static bool _OSKextSetRequestArgument(
88    OSDictionary * requestDict,
89    const char   * argName,
90    OSObject     * value);
91static void * _OSKextExtractPointer(OSData * wrapper);
92static OSReturn _OSDictionarySetCStringValue(
93    OSDictionary * dict,
94    const char   * key,
95    const char   * value);
96static bool _OSKextInPrelinkRebuildWindow(void);
97static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
98
99// We really should add containsObject() & containsCString to OSCollection & subclasses.
100// So few pad slots, though....
101static bool _OSArrayContainsCString(OSArray * array, const char * cString);
102
103#if CONFIG_KEC_FIPS
104static void * GetAppleTEXTHashForKext(OSKext * theKext, OSDictionary *theInfoDict);
105#endif // CONFIG_KEC_FIPS
106
107/* Prelinked arm kexts do not have VM entries because the method we use to
108 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
109 * not work on ARM.  To get around that, we must free prelinked kext
110 * executables with ml_static_mfree() instead of kext_free().
111 */
112#if __i386__ || __x86_64__
113#define VM_MAPPED_KEXTS 1
114#define KASLR_KEXT_DEBUG 0
115#define KASLR_IOREG_DEBUG 0
116#else
117#error Unsupported architecture
118#endif
119
120#if PRAGMA_MARK
121#pragma mark Constants & Macros
122#endif
123/*********************************************************************
124* Constants & Macros
125*********************************************************************/
126
127/* A typical Snow Leopard system has a bit under 120 kexts loaded.
128 * Use this number to create containers.
129 */
130#define kOSKextTypicalLoadCount      (120)
131
132/* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
133 * A loaded kext will no dependents or external retains will have 2 retains.
134 */
135#define kOSKextMinRetainCount        (1)
136#define kOSKextMinLoadedRetainCount  (2)
137
138/**********
139 * Strings and substrings used in dependency resolution.
140 */
141#define APPLE_KEXT_PREFIX            "com.apple."
142#define KERNEL_LIB                   "com.apple.kernel"
143
144#define PRIVATE_KPI                  "com.apple.kpi.private"
145
146/* Version for compatbility pseudokexts (com.apple.kernel.*),
147 * compatible back to v6.0.
148 */
149#define KERNEL6_LIB                  "com.apple.kernel.6.0"
150#define KERNEL6_VERSION              "7.9.9"
151
152#define KERNEL_LIB_PREFIX            "com.apple.kernel."
153#define KPI_LIB_PREFIX               "com.apple.kpi."
154
155#define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0)
156
157#define REBUILD_MAX_TIME (60 * 5) // 5 minutes
158#define MINIMUM_WAKEUP_SECONDS (30)
159
160/*********************************************************************
161* infoDict keys for internally-stored data. Saves on ivar slots for
162* objects we don't keep around past boot time or during active load.
163*********************************************************************/
164
165/* A usable, uncompressed file is stored under this key.
166 */
167#define _kOSKextExecutableKey                "_OSKextExecutable"
168
169/* An indirect reference to the executable file from an mkext
170 * is stored under this key.
171 */
172#define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference"
173
174/* If the file is contained in a larger buffer laid down by the booter or
175 * sent from user space, the OSKext stores that OSData under this key so that
176 * references are properly tracked. This is always an mkext, right now.
177 */
178#define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData"
179
180#if PRAGMA_MARK
181#pragma mark Typedefs
182#endif
183/*********************************************************************
184* Typedefs
185*********************************************************************/
186
187/*********************************************************************
188* MkextEntryRef describes the contents of an OSData object
189* referencing a file entry from an mkext so that we can uncompress
190* (if necessary) and extract it on demand.
191*
192* It contains the mkextVersion in case we ever wind up supporting
193* multiple mkext formats. Mkext format 1 is officially retired as of
194* Snow Leopard.
195*********************************************************************/
196typedef struct MkextEntryRef {
197    mkext_basic_header * mkext;     // beginning of whole mkext file
198    void               * fileinfo;  // mkext2_file_entry or equiv; see mkext.h
199} MkextEntryRef;
200
201#if PRAGMA_MARK
202#pragma mark Global and static Module Variables
203#endif
204/*********************************************************************
205* Global & static variables, used to keep track of kexts.
206*********************************************************************/
207
208static  bool                sPrelinkBoot               = false;
209static  bool                sSafeBoot                  = false;
210static  bool                sKeepSymbols               = false;
211
212/*********************************************************************
213* sKextLock is the principal lock for OSKext, and guards all static
214* and global variables not owned by other locks (declared further
215* below). It must be taken by any entry-point method or function,
216* including internal functions called on scheduled threads.
217*
218* sKextLock and sKextInnerLock are recursive due to multiple functions
219* that are called both externally and internally. The other locks are
220* nonrecursive.
221*
222* Which locks are taken depends on what they protect, but if more than
223* one must be taken, they must always be locked in this order
224* (and unlocked in reverse order) to prevent deadlocks:
225*
226*    1. sKextLock
227*    2. sKextInnerLock
228*    3. sKextSummariesLock
229*    4. sKextLoggingLock
230*/
231static IORecursiveLock    * sKextLock                  = NULL;
232
233static OSDictionary       * sKextsByID                 = NULL;
234static OSDictionary       * sExcludeListByID           = NULL;
235static OSArray            * sLoadedKexts               = NULL;
236static OSArray            * sUnloadedPrelinkedKexts    = NULL;
237
238// Requests to kextd waiting to be picked up.
239static OSArray            * sKernelRequests            = NULL;
240// Identifier of kext load requests in sKernelRequests
241static OSSet              * sPostedKextLoadIdentifiers = NULL;
242static OSArray            * sRequestCallbackRecords    = NULL;
243
244// Identifiers of all kexts ever requested in kernel; used for prelinked kernel
245static OSSet              * sAllKextLoadIdentifiers    = NULL;
246static KXLDContext        * sKxldContext               = NULL;
247static uint32_t             sNextLoadTag               = 0;
248static uint32_t             sNextRequestTag            = 0;
249
250static bool                 sUserLoadsActive           = false;
251static bool                 sKextdActive               = false;
252static bool                 sDeferredLoadSucceeded     = false;
253static bool                 sConsiderUnloadsExecuted   = false;
254
255#if NO_KEXTD
256static bool                 sKernelRequestsEnabled     = false;
257#else
258static bool                 sKernelRequestsEnabled     = true;
259#endif
260static bool                 sLoadEnabled               = true;
261static bool                 sUnloadEnabled             = true;
262
263/*********************************************************************
264* Stuff for the OSKext representing the kernel itself.
265**********/
266static OSKext          * sKernelKext             = NULL;
267
268/* Set up a fake kmod_info struct for the kernel.
269 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
270 * before OSKext is initialized; that call only needs the name
271 * and address to be set correctly.
272 *
273 * We don't do much else with the kerne's kmod_info; we never
274 * put it into the kmod list, never adjust the reference count,
275 * and never have kernel components reference it.
276 * For that matter, we don't do much with kmod_info structs
277 * at all anymore! We just keep them filled in for gdb and
278 * binary compability.
279 */
280kmod_info_t g_kernel_kmod_info = {
281    /* next            */ 0,
282    /* info_version    */ KMOD_INFO_VERSION,
283    /* id              */ 0,                 // loadTag: kernel is always 0
284    /* name            */ kOSKextKernelIdentifier,    // bundle identifier
285    /* version         */ "0",               // filled in in OSKext::initialize()
286    /* reference_count */ -1,                // never adjusted; kernel never unloads
287    /* reference_list  */ NULL,
288    /* address         */ NULL,
289    /* size            */ 0,                 // filled in in OSKext::initialize()
290    /* hdr_size        */ 0,
291    /* start           */ 0,
292    /* stop            */ 0
293};
294
295extern "C" {
296// symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
297// dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
298// misc_protos.h, db_low_trace.c, kgmacros
299// 'kmod' is a holdover from the old kmod system, we can't rename it.
300kmod_info_t * kmod = NULL;
301
302#define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE)
303
304
305static char     * loaded_kext_paniclist         = NULL;
306static uint32_t   loaded_kext_paniclist_size    = 0;
307static uint32_t   loaded_kext_paniclist_length  = 0;
308
309AbsoluteTime      last_loaded_timestamp;
310static char       last_loaded_str[2*KMOD_MAX_NAME];
311static u_long     last_loaded_strlen            = 0;
312static void     * last_loaded_address           = NULL;
313static u_long     last_loaded_size              = 0;
314
315AbsoluteTime      last_unloaded_timestamp;
316static char       last_unloaded_str[2*KMOD_MAX_NAME];
317static u_long     last_unloaded_strlen          = 0;
318static void     * last_unloaded_address         = NULL;
319static u_long     last_unloaded_size            = 0;
320
321/*********************************************************************
322* sKextInnerLock protects against cross-calls with IOService and
323* IOCatalogue, and owns the variables declared immediately below.
324*
325* Note that sConsiderUnloadsExecuted above belongs to sKextLock!
326*
327* When both sKextLock and sKextInnerLock need to be taken,
328* always lock sKextLock first and unlock it second. Never take both
329* locks in an entry point to OSKext; if you need to do so, you must
330* spawn an independent thread to avoid potential deadlocks for threads
331* calling into OSKext.
332**********/
333static IORecursiveLock *    sKextInnerLock             = NULL;
334
335static bool                 sAutounloadEnabled         = true;
336static bool                 sConsiderUnloadsCalled     = false;
337static bool                 sConsiderUnloadsPending    = false;
338
339static unsigned int         sConsiderUnloadDelay       = 60;     // seconds
340static thread_call_t        sUnloadCallout             = 0;
341static thread_call_t        sDestroyLinkContextThread  = 0;      // one-shot, one-at-a-time thread
342static bool                 sSystemSleep               = false;  // true when system going to sleep
343static AbsoluteTime         sLastWakeTime;                       // last time we woke up
344
345/*********************************************************************
346* Backtraces can be printed at various times so we need a tight lock
347* on data used for that. sKextSummariesLock protects the variables
348* declared immediately below.
349*
350* gLoadedKextSummaries is accessed by other modules, but only during
351* a panic so the lock isn't needed then.
352*
353* gLoadedKextSummaries has the "used" attribute in order to ensure
354* that it remains visible even when we are performing extremely
355* aggressive optimizations, as it is needed to allow the debugger
356* to automatically parse the list of loaded kexts.
357**********/
358static IOLock                 * sKextSummariesLock                = NULL;
359
360void (*sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
361OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
362static size_t sLoadedKextSummariesAllocSize = 0;
363OSKextLoadedKextSummaryHeader * sPrevLoadedKextSummaries = NULL;
364static size_t sPrevLoadedKextSummariesAllocSize = 0;
365};
366
367/*********************************************************************
368* sKextLoggingLock protects the logging variables declared immediately below.
369**********/
370static IOLock             * sKextLoggingLock           = NULL;
371
372static  const OSKextLogSpec kDefaultKernelLogFilter    = kOSKextLogBasicLevel |
373                                                         kOSKextLogVerboseFlagsMask;
374static  OSKextLogSpec       sKernelLogFilter           = kDefaultKernelLogFilter;
375static  bool                sBootArgLogFilterFound     = false;
376SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
377    sKernelLogFilter, "kernel kext logging");
378
379static  OSKextLogSpec       sUserSpaceKextLogFilter    = kOSKextLogSilentFilter;
380static  OSArray           * sUserSpaceLogSpecArray     = NULL;
381static  OSArray           * sUserSpaceLogMessageArray  = NULL;
382
383/*********
384* End scope for sKextInnerLock-protected variables.
385*********************************************************************/
386
387#if PRAGMA_MARK
388#pragma mark OSData callbacks (need to move to OSData)
389#endif
390/*********************************************************************
391* C functions used for callbacks.
392*********************************************************************/
393extern "C" {
394void osdata_kmem_free(void * ptr, unsigned int length) {
395    kmem_free(kernel_map, (vm_address_t)ptr, length);
396    return;
397}
398
399void osdata_phys_free(void * ptr, unsigned int length) {
400    ml_static_mfree((vm_offset_t)ptr, length);
401    return;
402}
403
404void osdata_vm_deallocate(void * ptr, unsigned int length)
405{
406    (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
407    return;
408}
409
410void osdata_kext_free(void * ptr, unsigned int length)
411{
412    (void)kext_free((vm_offset_t)ptr, length);
413}
414
415};
416
417#if PRAGMA_MARK
418#pragma mark KXLD Allocation Callback
419#endif
420/*********************************************************************
421* KXLD Allocation Callback
422*********************************************************************/
423kxld_addr_t
424kern_allocate(
425    u_long              size,
426    KXLDAllocateFlags * flags,
427    void              * user_data)
428{
429    vm_address_t  result       = 0;     // returned
430    kern_return_t mach_result  = KERN_FAILURE;
431    bool          success      = false;
432    OSKext      * theKext      = (OSKext *)user_data;
433    u_long        roundSize    = round_page(size);
434    OSData      * linkBuffer   = NULL;  // must release
435
436    mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
437    if (mach_result != KERN_SUCCESS) {
438        OSKextLog(theKext,
439            kOSKextLogErrorLevel |
440            kOSKextLogGeneralFlag,
441            "Can't allocate kernel memory to link %s.",
442            theKext->getIdentifierCString());
443        goto finish;
444    }
445
446   /* Create an OSData wrapper for the allocated buffer.
447    */
448    linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
449    if (!linkBuffer) {
450        OSKextLog(theKext,
451            kOSKextLogErrorLevel |
452            kOSKextLogGeneralFlag,
453            "Can't allocate linked executable wrapper for %s.",
454            theKext->getIdentifierCString());
455        goto finish;
456    }
457    linkBuffer->setDeallocFunction(osdata_kext_free);
458    OSKextLog(theKext,
459        kOSKextLogProgressLevel |
460        kOSKextLogLoadFlag | kOSKextLogLinkFlag,
461        "Allocated link buffer for kext %s at %p (%lu bytes).",
462        theKext->getIdentifierCString(),
463        (void *)result, (unsigned long)roundSize);
464
465    theKext->setLinkedExecutable(linkBuffer);
466
467    *flags = kKxldAllocateWritable;
468    success = true;
469
470finish:
471    if (!success && result) {
472        kext_free(result, roundSize);
473        result = 0;
474    }
475
476    OSSafeRelease(linkBuffer);
477
478    return (kxld_addr_t)result;
479}
480
481/*********************************************************************
482*********************************************************************/
483void
484kxld_log_callback(
485    KXLDLogSubsystem    subsystem,
486    KXLDLogLevel        level,
487    const char        * format,
488    va_list             argList,
489    void              * user_data)
490{
491    OSKext *theKext = (OSKext *) user_data;
492    OSKextLogSpec logSpec = 0;
493
494    switch (subsystem) {
495    case kKxldLogLinking:
496        logSpec |= kOSKextLogLinkFlag;
497        break;
498    case kKxldLogPatching:
499        logSpec |= kOSKextLogPatchFlag;
500        break;
501    }
502
503    switch (level) {
504    case kKxldLogExplicit:
505        logSpec |= kOSKextLogExplicitLevel;
506        break;
507    case kKxldLogErr:
508        logSpec |= kOSKextLogErrorLevel;
509        break;
510    case kKxldLogWarn:
511        logSpec |= kOSKextLogWarningLevel;
512        break;
513    case kKxldLogBasic:
514        logSpec |= kOSKextLogProgressLevel;
515        break;
516    case kKxldLogDetail:
517        logSpec |= kOSKextLogDetailLevel;
518        break;
519    case kKxldLogDebug:
520        logSpec |= kOSKextLogDebugLevel;
521        break;
522    }
523
524    OSKextVLog(theKext, logSpec, format, argList);
525}
526
527#if PRAGMA_MARK
528#pragma mark IOStatistics defines
529#endif
530
531#if IOKITSTATS
532
533#define notifyKextLoadObservers(kext, kmod_info) \
534do { \
535    IOStatistics::onKextLoad(kext, kmod_info); \
536} while (0)
537
538#define notifyKextUnloadObservers(kext) \
539do { \
540    IOStatistics::onKextUnload(kext); \
541} while (0)
542
543#define notifyAddClassObservers(kext, addedClass, flags) \
544do { \
545    IOStatistics::onClassAdded(kext, addedClass); \
546} while (0)
547
548#define notifyRemoveClassObservers(kext, removedClass, flags) \
549do { \
550    IOStatistics::onClassRemoved(kext, removedClass); \
551} while (0)
552
553#else
554
555#define notifyKextLoadObservers(kext, kmod_info)
556#define notifyKextUnloadObservers(kext)
557#define notifyAddClassObservers(kext, addedClass, flags)
558#define notifyRemoveClassObservers(kext, removedClass, flags)
559
560#endif /* IOKITSTATS */
561
562#if PRAGMA_MARK
563#pragma mark Module Config (Startup & Shutdown)
564#endif
565/*********************************************************************
566* Module Config (Class Definition & Class Methods)
567*********************************************************************/
568#define super OSObject
569OSDefineMetaClassAndStructors(OSKext, OSObject)
570
571/*********************************************************************
572*********************************************************************/
573/* static */
574void
575OSKext::initialize(void)
576{
577    OSData          * kernelExecutable   = NULL;  // do not release
578    u_char          * kernelStart        = NULL;  // do not free
579    size_t            kernelLength       = 0;
580    OSString        * scratchString      = NULL;  // must release
581    IORegistryEntry * registryRoot       = NULL;  // do not release
582    OSNumber        * kernelCPUType      = NULL;  // must release
583    OSNumber        * kernelCPUSubtype   = NULL;  // must release
584    OSKextLogSpec     bootLogFilter      = kOSKextLogSilentFilter;
585    bool              setResult          = false;
586    uint64_t        * timestamp          = 0;
587    char              bootArgBuffer[16];  // for PE_parse_boot_argn w/strings
588
589   /* This must be the first thing allocated. Everything else grabs this lock.
590    */
591    sKextLock = IORecursiveLockAlloc();
592    sKextInnerLock = IORecursiveLockAlloc();
593    sKextSummariesLock = IOLockAlloc();
594    sKextLoggingLock = IOLockAlloc();
595    assert(sKextLock);
596    assert(sKextInnerLock);
597    assert(sKextSummariesLock);
598    assert(sKextLoggingLock);
599
600    sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
601    sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
602    sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
603    sKernelRequests = OSArray::withCapacity(0);
604    sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
605    sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
606    sRequestCallbackRecords = OSArray::withCapacity(0);
607    assert(sKextsByID && sLoadedKexts && sKernelRequests &&
608        sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
609        sRequestCallbackRecords && sUnloadedPrelinkedKexts);
610
611   /* Read the log flag boot-args and set the log flags.
612    */
613    if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
614        sBootArgLogFilterFound = true;
615        sKernelLogFilter = bootLogFilter;
616        // log this if any flags are set
617        OSKextLog(/* kext */ NULL,
618            kOSKextLogBasicLevel |
619            kOSKextLogFlagsMask,
620            "Kernel kext log filter 0x%x per kextlog boot arg.",
621            (unsigned)sKernelLogFilter);
622    }
623
624    sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
625        sizeof(bootArgBuffer)) ? true : false;
626
627    if (sSafeBoot) {
628        OSKextLog(/* kext */ NULL,
629            kOSKextLogWarningLevel |
630            kOSKextLogGeneralFlag,
631            "SAFE BOOT DETECTED - "
632            "only valid OSBundleRequired kexts will be loaded.");
633    }
634
635    PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
636
637   /* Set up an OSKext instance to represent the kernel itself.
638    */
639    sKernelKext = new OSKext;
640    assert(sKernelKext);
641
642    kernelStart = (u_char *)&_mh_execute_header;
643    kernelLength = getlastaddr() - (vm_offset_t)kernelStart;
644    kernelExecutable = OSData::withBytesNoCopy(
645        kernelStart, kernelLength);
646    assert(kernelExecutable);
647
648#if KASLR_KEXT_DEBUG
649    IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu \n",
650          (unsigned long)kernelStart,
651          (unsigned long)getlastaddr(),
652          kernelLength);
653#endif
654
655    sKernelKext->loadTag = sNextLoadTag++;  // the kernel is load tag 0
656    sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier);
657
658    sKernelKext->version = OSKextParseVersionString(osrelease);
659    sKernelKext->compatibleVersion = sKernelKext->version;
660    sKernelKext->linkedExecutable = kernelExecutable;
661
662    sKernelKext->flags.hasAllDependencies = 1;
663    sKernelKext->flags.kernelComponent = 1;
664    sKernelKext->flags.prelinked = 0;
665    sKernelKext->flags.loaded = 1;
666    sKernelKext->flags.started = 1;
667    sKernelKext->flags.CPPInitialized = 0;
668    sKernelKext->flags.jettisonLinkeditSeg = 0;
669
670    sKernelKext->kmod_info = &g_kernel_kmod_info;
671    strlcpy(g_kernel_kmod_info.version, osrelease,
672        sizeof(g_kernel_kmod_info.version));
673    g_kernel_kmod_info.size = kernelLength;
674    g_kernel_kmod_info.id = sKernelKext->loadTag;
675
676   /* Cons up an info dict, so we don't have to have special-case
677    * checking all over.
678    */
679    sKernelKext->infoDict = OSDictionary::withCapacity(5);
680    assert(sKernelKext->infoDict);
681    setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey,
682        sKernelKext->bundleID);
683    assert(setResult);
684    setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey,
685        kOSBooleanTrue);
686    assert(setResult);
687
688    scratchString = OSString::withCStringNoCopy(osrelease);
689    assert(scratchString);
690    setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey,
691        scratchString);
692    assert(setResult);
693    OSSafeReleaseNULL(scratchString);
694
695    scratchString = OSString::withCStringNoCopy("mach_kernel");
696    assert(scratchString);
697    setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey,
698        scratchString);
699    assert(setResult);
700    OSSafeReleaseNULL(scratchString);
701
702   /* Add the kernel kext to the bookkeeping dictionaries. Note that
703    * the kernel kext doesn't have a kmod_info struct. copyInfo()
704    * gathers info from other places anyhow.
705    */
706    setResult = sKextsByID->setObject(sKernelKext->bundleID, sKernelKext);
707    assert(setResult);
708    setResult = sLoadedKexts->setObject(sKernelKext);
709    assert(setResult);
710    sKernelKext->release();
711
712    registryRoot = IORegistryEntry::getRegistryRoot();
713    kernelCPUType = OSNumber::withNumber(
714        (long long unsigned int)_mh_execute_header.cputype,
715        8 * sizeof(_mh_execute_header.cputype));
716    kernelCPUSubtype = OSNumber::withNumber(
717        (long long unsigned int)_mh_execute_header.cpusubtype,
718        8 * sizeof(_mh_execute_header.cpusubtype));
719    assert(registryRoot && kernelCPUSubtype && kernelCPUType);
720
721    registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType);
722    registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype);
723
724    OSSafeRelease(kernelCPUType);
725    OSSafeRelease(kernelCPUSubtype);
726
727    timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
728    *timestamp = 0;
729    timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
730    *timestamp = 0;
731    timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
732    *timestamp = 0;
733
734    OSKextLog(/* kext */ NULL,
735        kOSKextLogProgressLevel |
736        kOSKextLogGeneralFlag,
737        "Kext system initialized.");
738
739    notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
740
741    return;
742}
743
744/*********************************************************************
745* This could be in OSKextLib.cpp but we need to hold a lock
746* while removing all the segments and sKextLock will do.
747*********************************************************************/
748/* static */
749OSReturn
750OSKext::removeKextBootstrap(void)
751{
752    OSReturn                   result                = kOSReturnError;
753
754    static bool                alreadyDone           = false;
755
756    const char               * dt_kernel_header_name = "Kernel-__HEADER";
757    const char               * dt_kernel_symtab_name = "Kernel-__SYMTAB";
758    kernel_mach_header_t     * dt_mach_header        = NULL;
759    int                        dt_mach_header_size   = 0;
760    struct symtab_command    * dt_symtab             = NULL;
761    int                        dt_symtab_size        = 0;
762    int                        dt_result             = 0;
763
764    kernel_segment_command_t * seg_to_remove         = NULL;
765
766
767   /* This must be the very first thing done by this function.
768    */
769    IORecursiveLockLock(sKextLock);
770
771   /* If we already did this, it's a success.
772    */
773    if (alreadyDone) {
774        result = kOSReturnSuccess;
775        goto finish;
776    }
777
778    OSKextLog(/* kext */ NULL,
779        kOSKextLogProgressLevel |
780        kOSKextLogGeneralFlag,
781        "Jettisoning kext bootstrap segments.");
782
783   /*****
784    * Dispose of unnecessary stuff that the booter didn't need to load.
785    */
786    dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
787        (void **)&dt_mach_header, &dt_mach_header_size);
788    if (dt_result == 0 && dt_mach_header) {
789        IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
790            round_page_32(dt_mach_header_size));
791    }
792    dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
793        (void **)&dt_symtab, &dt_symtab_size);
794    if (dt_result == 0 && dt_symtab) {
795        IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
796            round_page_32(dt_symtab_size));
797    }
798
799   /*****
800    * KLD bootstrap segment.
801    */
802    // xxx - should rename KLD segment
803    seg_to_remove = getsegbyname("__KLD");
804    if (seg_to_remove) {
805        OSRuntimeUnloadCPPForSegment(seg_to_remove);
806    }
807
808#if   __i386__ || __x86_64__
809   /* On x86, use the mapping data from the segment load command to
810    * unload KLD directly.
811    * This may invalidate any assumptions about  "avail_start"
812    * defining the lower bound for valid physical addresses.
813    */
814    if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) {
815        // 04/18/11 - gab: <rdar://problem/9236163>
816        // overwrite memory occupied by KLD segment with random data before
817        // releasing it.
818        read_random((void *) seg_to_remove->vmaddr, seg_to_remove->vmsize);
819        ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize);
820    }
821#else
822#error arch
823#endif
824
825    seg_to_remove = NULL;
826
827    /*****
828    * Prelinked kernel's symtab (if there is one).
829    */
830    kernel_section_t * sect;
831    sect = getsectbyname("__PRELINK", "__symtab");
832    if (sect && sect->addr && sect->size) {
833        ml_static_mfree(sect->addr, sect->size);
834    }
835
836    seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
837
838    /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
839     * pageable, unless keepsyms is set.  To do that, we have to copy it from
840     * its booter-allocated memory, free the booter memory, reallocate proper
841     * managed memory, then copy the segment back in.
842     */
843#if CONFIG_KXLD
844    if (!sKeepSymbols) {
845        kern_return_t mem_result;
846        void *seg_copy = NULL;
847        void *seg_data = NULL;
848        vm_map_offset_t seg_offset = 0;
849        vm_map_offset_t seg_copy_offset = 0;
850        vm_map_size_t seg_length = 0;
851
852        seg_data = (void *) seg_to_remove->vmaddr;
853        seg_offset = (vm_map_offset_t) seg_to_remove->vmaddr;
854        seg_length = (vm_map_size_t) seg_to_remove->vmsize;
855
856       /* Allocate space for the LINKEDIT copy.
857        */
858        mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
859            seg_length);
860        if (mem_result != KERN_SUCCESS) {
861            OSKextLog(/* kext */ NULL,
862                kOSKextLogErrorLevel |
863                kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
864                "Can't copy __LINKEDIT segment for VM reassign.");
865            goto finish;
866        }
867        seg_copy_offset = (vm_map_offset_t) seg_copy;
868
869       /* Copy it out.
870        */
871        memcpy(seg_copy, seg_data, seg_length);
872
873       /* Dump the booter memory.
874        */
875        ml_static_mfree(seg_offset, seg_length);
876
877       /* Set up the VM region.
878        */
879        mem_result = vm_map_enter_mem_object(
880            kernel_map,
881            &seg_offset,
882            seg_length, /* mask */ 0,
883            VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
884            (ipc_port_t)NULL,
885            (vm_object_offset_t) 0,
886            /* copy */ FALSE,
887            /* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
888            /* max_protection */ VM_PROT_ALL,
889            /* inheritance */ VM_INHERIT_DEFAULT);
890        if ((mem_result != KERN_SUCCESS) ||
891            (seg_offset != (vm_map_offset_t) seg_data))
892        {
893            OSKextLog(/* kext */ NULL,
894                kOSKextLogErrorLevel |
895                kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
896                "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
897                seg_data, seg_length, mem_result);
898            goto finish;
899        }
900
901       /* And copy it back.
902        */
903        memcpy(seg_data, seg_copy, seg_length);
904
905       /* Free the copy.
906        */
907        kmem_free(kernel_map, seg_copy_offset, seg_length);
908    }
909#else /* we are not CONFIG_KXLD */
910#error CONFIG_KXLD is expected for this arch
911
912    /*****
913    * Dump the LINKEDIT segment, unless keepsyms is set.
914    */
915    if (!sKeepSymbols) {
916        const char *dt_segment_name = "Kernel-__LINKEDIT";
917        if (0 == IODTGetLoaderInfo(dt_segment_name,
918            &segment_paddress, &segment_size)) {
919#ifdef SECURE_KERNEL
920            vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
921            bzero((void*)vmaddr, segment_size);
922#endif
923            IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
924                (int)segment_size);
925        }
926    } else {
927        OSKextLog(/* kext */ NULL,
928           kOSKextLogBasicLevel |
929           kOSKextLogGeneralFlag,
930           "keepsyms boot arg specified; keeping linkedit segment for symbols.");
931    }
932#endif /* CONFIG_KXLD */
933
934    seg_to_remove = NULL;
935
936    alreadyDone = true;
937    result = kOSReturnSuccess;
938
939finish:
940
941   /* This must be the very last thing done before returning.
942    */
943    IORecursiveLockUnlock(sKextLock);
944
945    return result;
946}
947
948/*********************************************************************
949*********************************************************************/
950void
951OSKext::flushNonloadedKexts(
952    Boolean flushPrelinkedKexts)
953{
954    OSSet                * prelinkedKexts  = NULL;  // must release
955    OSCollectionIterator * kextIterator    = NULL;  // must release
956    OSCollectionIterator * prelinkIterator = NULL;  // must release
957    const OSSymbol       * thisID          = NULL;  // do not release
958    OSKext               * thisKext        = NULL;  // do not release
959    uint32_t               count, i;
960
961    IORecursiveLockLock(sKextLock);
962
963    OSKextLog(/* kext */ NULL,
964        kOSKextLogProgressLevel |
965        kOSKextLogKextBookkeepingFlag,
966        "Flushing nonloaded kexts and other unused data.");
967
968    OSKext::considerDestroyingLinkContext();
969
970   /* If we aren't flushing unused prelinked kexts, we have to put them
971    * aside while we flush everything else so make a container for them.
972    */
973    if (!flushPrelinkedKexts) {
974        prelinkedKexts = OSSet::withCapacity(0);
975        if (!prelinkedKexts) {
976            goto finish;
977        }
978    }
979
980   /* Set aside prelinked kexts (in-use or not) and break
981    * any lingering inter-kext references for nonloaded kexts
982    * so they have min. retain counts.
983    */
984    kextIterator = OSCollectionIterator::withCollection(sKextsByID);
985    if (!kextIterator) {
986        goto finish;
987    }
988
989    while ((thisID = OSDynamicCast(OSSymbol,
990            kextIterator->getNextObject()))) {
991
992        thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
993
994        if (thisKext) {
995            if (prelinkedKexts && thisKext->isPrelinked()) {
996                prelinkedKexts->setObject(thisKext);
997            }
998            thisKext->flushDependencies(/* forceIfLoaded */ false);
999        }
1000    }
1001
1002   /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1003    */
1004    sKextsByID->flushCollection();
1005
1006   /* Now put the loaded kexts back into the ID dictionary.
1007    */
1008    count = sLoadedKexts->getCount();
1009    for (i = 0; i < count; i++) {
1010        thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
1011        sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1012    }
1013
1014   /* Finally, put back the prelinked kexts if we saved any.
1015    */
1016    if (prelinkedKexts) {
1017        prelinkIterator = OSCollectionIterator::withCollection(prelinkedKexts);
1018        if (!prelinkIterator) {
1019            goto finish;
1020        }
1021
1022        while ((thisKext = OSDynamicCast(OSKext,
1023            prelinkIterator->getNextObject()))) {
1024
1025            sKextsByID->setObject(thisKext->getIdentifierCString(),
1026                thisKext);
1027        }
1028    }
1029
1030finish:
1031    IORecursiveLockUnlock(sKextLock);
1032
1033    OSSafeRelease(prelinkedKexts);
1034    OSSafeRelease(kextIterator);
1035    OSSafeRelease(prelinkIterator);
1036
1037    return;
1038}
1039
1040/*********************************************************************
1041*********************************************************************/
1042/* static */
1043void
1044OSKext::setKextdActive(Boolean active)
1045{
1046    IORecursiveLockLock(sKextLock);
1047    sKextdActive = active;
1048    if (sKernelRequests->getCount()) {
1049        OSKext::pingKextd();
1050    }
1051    IORecursiveLockUnlock(sKextLock);
1052
1053    return;
1054}
1055
1056/*********************************************************************
1057* OSKextLib.cpp might need access to this someday but for now it's
1058* private.
1059*********************************************************************/
1060extern "C" {
1061extern void ipc_port_release_send(ipc_port_t);
1062};
1063
1064/* static */
1065OSReturn
1066OSKext::pingKextd(void)
1067{
1068    OSReturn    result     = kOSReturnError;
1069#if !NO_KEXTD
1070    mach_port_t kextd_port = IPC_PORT_NULL;
1071
1072    if (!sKextdActive) {
1073        result = kOSKextReturnDisabled;  // basically unavailable
1074        goto finish;
1075    }
1076
1077    result = host_get_kextd_port(host_priv_self(), &kextd_port);
1078    if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1079        OSKextLog(/* kext */ NULL,
1080            kOSKextLogErrorLevel |
1081            kOSKextLogIPCFlag,
1082            "Can't get kextd port.");
1083        goto finish;
1084    }
1085
1086    result = kextd_ping(kextd_port);
1087    if (result != KERN_SUCCESS) {
1088        OSKextLog(/* kext */ NULL,
1089            kOSKextLogErrorLevel |
1090            kOSKextLogIPCFlag,
1091            "kextd ping failed (0x%x).", (int)result);
1092        goto finish;
1093    }
1094
1095finish:
1096    if (IPC_PORT_VALID(kextd_port)) {
1097        ipc_port_release_send(kextd_port);
1098    }
1099#endif
1100
1101    return result;
1102}
1103
1104/*********************************************************************
1105*********************************************************************/
1106/* static */
1107void
1108OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1109{
1110    IORecursiveLockLock(sKextLock);
1111    sDeferredLoadSucceeded = succeeded;
1112    IORecursiveLockUnlock(sKextLock);
1113
1114    return;
1115}
1116
1117/*********************************************************************
1118* Called from IOSystemShutdownNotification.
1119*********************************************************************/
1120/* static */
1121void
1122OSKext::willShutdown(void)
1123{
1124#if !NO_KEXTD
1125    OSReturn       checkResult = kOSReturnError;
1126#endif
1127    OSDictionary * exitRequest = NULL;  // must release
1128
1129    IORecursiveLockLock(sKextLock);
1130
1131    OSKext::setLoadEnabled(false);
1132    OSKext::setUnloadEnabled(false);
1133    OSKext::setAutounloadsEnabled(false);
1134    OSKext::setKernelRequestsEnabled(false);
1135
1136#if !NO_KEXTD
1137    OSKextLog(/* kext */ NULL,
1138        kOSKextLogProgressLevel |
1139        kOSKextLogGeneralFlag,
1140        "System shutdown; requesting immediate kextd exit.");
1141
1142    checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit,
1143        &exitRequest);
1144    if (checkResult != kOSReturnSuccess) {
1145        goto finish;
1146    }
1147    if (!sKernelRequests->setObject(exitRequest)) {
1148        goto finish;
1149    }
1150
1151    OSKext::pingKextd();
1152
1153finish:
1154#endif
1155
1156    IORecursiveLockUnlock(sKextLock);
1157
1158    OSSafeRelease(exitRequest);
1159    return;
1160}
1161
1162/*********************************************************************
1163*********************************************************************/
1164/* static */
1165bool
1166OSKext::getLoadEnabled(void)
1167{
1168    bool result;
1169
1170    IORecursiveLockLock(sKextLock);
1171    result = sLoadEnabled;
1172    IORecursiveLockUnlock(sKextLock);
1173    return result;
1174}
1175
1176/*********************************************************************
1177*********************************************************************/
1178/* static */
1179bool
1180OSKext::setLoadEnabled(bool flag)
1181{
1182    bool result;
1183
1184    IORecursiveLockLock(sKextLock);
1185    result = sLoadEnabled;
1186    sLoadEnabled = (flag ? true : false);
1187
1188    if (sLoadEnabled != result) {
1189        OSKextLog(/* kext */ NULL,
1190            kOSKextLogBasicLevel |
1191            kOSKextLogLoadFlag,
1192            "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1193    }
1194
1195    IORecursiveLockUnlock(sKextLock);
1196
1197    return result;
1198}
1199
1200/*********************************************************************
1201*********************************************************************/
1202/* static */
1203bool
1204OSKext::getUnloadEnabled(void)
1205{
1206    bool result;
1207
1208    IORecursiveLockLock(sKextLock);
1209    result = sUnloadEnabled;
1210    IORecursiveLockUnlock(sKextLock);
1211    return result;
1212}
1213
1214/*********************************************************************
1215*********************************************************************/
1216/* static */
1217bool
1218OSKext::setUnloadEnabled(bool flag)
1219{
1220    bool result;
1221
1222    IORecursiveLockLock(sKextLock);
1223    result = sUnloadEnabled;
1224    sUnloadEnabled = (flag ? true : false);
1225    IORecursiveLockUnlock(sKextLock);
1226
1227    if (sUnloadEnabled != result) {
1228        OSKextLog(/* kext */ NULL,
1229            kOSKextLogBasicLevel |
1230            kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1231            "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1232    }
1233
1234    return result;
1235}
1236
1237/*********************************************************************
1238* Do not call any function that takes sKextLock here!
1239*********************************************************************/
1240/* static */
1241bool
1242OSKext::getAutounloadEnabled(void)
1243{
1244    bool result;
1245
1246    IORecursiveLockLock(sKextInnerLock);
1247    result = sAutounloadEnabled ? true : false;
1248    IORecursiveLockUnlock(sKextInnerLock);
1249    return result;
1250}
1251
1252/*********************************************************************
1253* Do not call any function that takes sKextLock here!
1254*********************************************************************/
1255/* static */
1256bool
1257OSKext::setAutounloadsEnabled(bool flag)
1258{
1259    bool result;
1260
1261    IORecursiveLockLock(sKextInnerLock);
1262
1263    result = sAutounloadEnabled;
1264    sAutounloadEnabled = (flag ? true : false);
1265    if (!sAutounloadEnabled && sUnloadCallout) {
1266        thread_call_cancel(sUnloadCallout);
1267    }
1268
1269    if (sAutounloadEnabled != result) {
1270        OSKextLog(/* kext */ NULL,
1271            kOSKextLogBasicLevel |
1272            kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1273            "Kext autounloading now %sabled.",
1274            sAutounloadEnabled ? "en" : "dis");
1275    }
1276
1277    IORecursiveLockUnlock(sKextInnerLock);
1278
1279    return result;
1280}
1281
1282/*********************************************************************
1283*********************************************************************/
1284/* instance method operating on OSKext field */
1285bool
1286OSKext::setAutounloadEnabled(bool flag)
1287{
1288    bool result = flags.autounloadEnabled ? true : false;
1289    flags.autounloadEnabled = flag ? 1 : 0;
1290
1291    if (result != (flag ? true : false)) {
1292        OSKextLog(this,
1293            kOSKextLogProgressLevel |
1294            kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1295            "Autounloading for kext %s now %sabled.",
1296            getIdentifierCString(),
1297            flags.autounloadEnabled ? "en" : "dis");
1298    }
1299    return result;
1300}
1301
1302/*********************************************************************
1303*********************************************************************/
1304/* static */
1305bool
1306OSKext::setKernelRequestsEnabled(bool flag)
1307{
1308    bool result;
1309
1310    IORecursiveLockLock(sKextLock);
1311    result = sKernelRequestsEnabled;
1312    sKernelRequestsEnabled = flag ? true : false;
1313
1314    if (sKernelRequestsEnabled != result) {
1315        OSKextLog(/* kext */ NULL,
1316            kOSKextLogBasicLevel |
1317            kOSKextLogGeneralFlag,
1318            "Kernel requests now %sabled.",
1319            sKernelRequestsEnabled ? "en" : "dis");
1320    }
1321    IORecursiveLockUnlock(sKextLock);
1322    return result;
1323}
1324
1325/*********************************************************************
1326*********************************************************************/
1327/* static */
1328bool
1329OSKext::getKernelRequestsEnabled(void)
1330{
1331    bool result;
1332
1333    IORecursiveLockLock(sKextLock);
1334    result = sKernelRequestsEnabled;
1335    IORecursiveLockUnlock(sKextLock);
1336    return result;
1337}
1338
1339#if PRAGMA_MARK
1340#pragma mark Kext Life Cycle
1341#endif
1342/*********************************************************************
1343*********************************************************************/
1344OSKext *
1345OSKext::withPrelinkedInfoDict(
1346    OSDictionary * anInfoDict)
1347{
1348    OSKext * newKext = new OSKext;
1349
1350    if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict)) {
1351        newKext->release();
1352        return NULL;
1353    }
1354
1355    return newKext;
1356}
1357
1358/*********************************************************************
1359*********************************************************************/
1360bool
1361OSKext::initWithPrelinkedInfoDict(
1362    OSDictionary * anInfoDict)
1363{
1364    bool            result              = false;
1365    OSString      * kextPath            = NULL;  // do not release
1366    OSNumber      * addressNum          = NULL;  // reused; do not release
1367    OSNumber      * lengthNum           = NULL;  // reused; do not release
1368    void          * data                = NULL;  // do not free
1369    void          * srcData             = NULL;  // do not free
1370    OSData        * prelinkedExecutable = NULL;  // must release
1371    uint32_t        length              = 0;     // reused
1372
1373    if (!super::init()) {
1374        goto finish;
1375    }
1376
1377   /* Get the path. Don't look for an arch-specific path property.
1378    */
1379    kextPath = OSDynamicCast(OSString,
1380        anInfoDict->getObject(kPrelinkBundlePathKey));
1381
1382    if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1383        goto finish;
1384    }
1385#if KASLR_KEXT_DEBUG
1386    IOLog("kaslr: kext %s \n", getIdentifierCString());
1387#endif
1388
1389   /* Also get the executable's bundle-relative path if present.
1390    * Don't look for an arch-specific path property.
1391    */
1392    executableRelPath = OSDynamicCast(OSString,
1393        anInfoDict->getObject(kPrelinkExecutableRelativePathKey));
1394    if (executableRelPath) {
1395        executableRelPath->retain();
1396    }
1397
1398   /* Don't need the paths to be in the info dictionary any more.
1399    */
1400    anInfoDict->removeObject(kPrelinkBundlePathKey);
1401    anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1402
1403   /* Create an OSData wrapper around the linked executable.
1404    */
1405    addressNum = OSDynamicCast(OSNumber,
1406        anInfoDict->getObject(kPrelinkExecutableLoadKey));
1407    if (addressNum) {
1408        lengthNum = OSDynamicCast(OSNumber,
1409            anInfoDict->getObject(kPrelinkExecutableSizeKey));
1410        if (!lengthNum) {
1411            OSKextLog(this,
1412                kOSKextLogErrorLevel |
1413                kOSKextLogArchiveFlag,
1414                "Kext %s can't find prelinked kext executable size.",
1415                getIdentifierCString());
1416            goto finish;
1417        }
1418
1419        data = (void *) ((intptr_t) (addressNum->unsigned64BitValue()) + vm_kernel_slide);
1420        length = (uint32_t) (lengthNum->unsigned32BitValue());
1421
1422#if KASLR_KEXT_DEBUG
1423        IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1424              (unsigned long)VM_KERNEL_UNSLIDE(data),
1425              (unsigned long)data,
1426              length);
1427#endif
1428
1429        anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1430        anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1431
1432       /* If the kext's load address differs from its source address, allocate
1433        * space in the kext map at the load address and copy the kext over.
1434        */
1435        addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1436        if (addressNum) {
1437            srcData = (void *) ((intptr_t) (addressNum->unsigned64BitValue()) + vm_kernel_slide);
1438
1439#if KASLR_KEXT_DEBUG
1440            IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1441                  (unsigned long)VM_KERNEL_UNSLIDE(srcData),
1442                  (unsigned long)srcData);
1443#endif
1444
1445            if (data != srcData) {
1446#if __LP64__
1447                kern_return_t alloc_result;
1448
1449                alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
1450                if (alloc_result != KERN_SUCCESS) {
1451                    OSKextLog(this,
1452                        kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1453                        "Failed to allocate space for prelinked kext %s.",
1454                        getIdentifierCString());
1455                    goto finish;
1456                }
1457                memcpy(data, srcData, length);
1458#else
1459                OSKextLog(this,
1460                    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1461                    "Error: prelinked kext %s - source and load addresses "
1462                    "differ on ILP32 architecture.",
1463                    getIdentifierCString());
1464                goto finish;
1465#endif /* __LP64__ */
1466            }
1467
1468            anInfoDict->removeObject(kPrelinkExecutableSourceKey);
1469        }
1470
1471        prelinkedExecutable = OSData::withBytesNoCopy(data, length);
1472        if (!prelinkedExecutable) {
1473            OSKextLog(this,
1474                kOSKextLogErrorLevel |
1475                kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1476                "Kext %s failed to create executable wrapper.",
1477                getIdentifierCString());
1478            goto finish;
1479        }
1480
1481#if VM_MAPPED_KEXTS
1482        prelinkedExecutable->setDeallocFunction(osdata_kext_free);
1483#else
1484        prelinkedExecutable->setDeallocFunction(osdata_phys_free);
1485#endif
1486        setLinkedExecutable(prelinkedExecutable);
1487        addressNum = OSDynamicCast(OSNumber,
1488            anInfoDict->getObject(kPrelinkKmodInfoKey));
1489        if (!addressNum) {
1490            OSKextLog(this,
1491                kOSKextLogErrorLevel |
1492                kOSKextLogArchiveFlag,
1493                "Kext %s can't find prelinked kext kmod_info address.",
1494                getIdentifierCString());
1495            goto finish;
1496        }
1497
1498        if (addressNum->unsigned64BitValue() != 0) {
1499            kmod_info = (kmod_info_t *) (intptr_t) (addressNum->unsigned64BitValue() + vm_kernel_slide);
1500            kmod_info->address += vm_kernel_slide;
1501#if KASLR_KEXT_DEBUG
1502            IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1503                  (unsigned long)VM_KERNEL_UNSLIDE(kmod_info),
1504                  (unsigned long)kmod_info);
1505            IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1506                  (unsigned long)VM_KERNEL_UNSLIDE(kmod_info->address),
1507                  (unsigned long)kmod_info->address);
1508 #endif
1509        }
1510
1511        anInfoDict->removeObject(kPrelinkKmodInfoKey);
1512    }
1513
1514   /* If the plist has a UUID for an interface, save that off.
1515    */
1516    if (isInterface()) {
1517        interfaceUUID = OSDynamicCast(OSData,
1518            anInfoDict->getObject(kPrelinkInterfaceUUIDKey));
1519        if (interfaceUUID) {
1520            interfaceUUID->retain();
1521            anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
1522        }
1523    }
1524
1525    flags.prelinked = true;
1526
1527   /* If we created a kext from prelink info,
1528    * we must be booting from a prelinked kernel.
1529    */
1530    sPrelinkBoot = true;
1531
1532    result = registerIdentifier();
1533
1534finish:
1535    OSSafeRelease(prelinkedExecutable);
1536
1537    return result;
1538}
1539
1540/*********************************************************************
1541*********************************************************************/
1542OSKext *
1543OSKext::withBooterData(
1544    OSString * deviceTreeName,
1545    OSData   * booterData)
1546{
1547    OSKext * newKext = new OSKext;
1548
1549    if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
1550        newKext->release();
1551        return NULL;
1552    }
1553
1554    return newKext;
1555}
1556
1557/*********************************************************************
1558*********************************************************************/
1559typedef struct _BooterKextFileInfo {
1560    uint32_t  infoDictPhysAddr;
1561    uint32_t  infoDictLength;
1562    uint32_t  executablePhysAddr;
1563    uint32_t  executableLength;
1564    uint32_t  bundlePathPhysAddr;
1565    uint32_t  bundlePathLength;
1566} _BooterKextFileInfo;
1567
1568bool
1569OSKext::initWithBooterData(
1570    OSString * deviceTreeName,
1571    OSData   * booterData)
1572{
1573    bool                  result         = false;
1574    _BooterKextFileInfo * kextFileInfo   = NULL;  // do not free
1575    char                * infoDictAddr   = NULL;  // do not free
1576    void                * executableAddr = NULL;  // do not free
1577    char                * bundlePathAddr = NULL;  // do not free
1578
1579    OSObject            * parsedXML      = NULL;  // must release
1580    OSDictionary        * theInfoDict    = NULL;  // do not release
1581    OSString            * kextPath       = NULL;  // must release
1582    OSString            * errorString    = NULL;  // must release
1583    OSData              * executable     = NULL;  // must release
1584
1585    if (!super::init()) {
1586        goto finish;
1587    }
1588
1589    kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
1590    if (!kextFileInfo) {
1591        OSKextLog(this,
1592            kOSKextLogErrorLevel |
1593            kOSKextLogGeneralFlag,
1594            "No booter-provided data for kext device tree entry %s.",
1595            deviceTreeName->getCStringNoCopy());
1596        goto finish;
1597    }
1598
1599   /* The info plist must exist or we can't read the kext.
1600    */
1601    if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
1602        OSKextLog(this,
1603            kOSKextLogErrorLevel |
1604            kOSKextLogGeneralFlag,
1605            "No kext info dictionary for booter device tree entry %s.",
1606            deviceTreeName->getCStringNoCopy());
1607        goto finish;
1608    }
1609
1610    infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
1611    if (!infoDictAddr) {
1612        OSKextLog(this,
1613            kOSKextLogErrorLevel |
1614            kOSKextLogGeneralFlag,
1615            "Can't translate physical address 0x%x of kext info dictionary "
1616            "for device tree entry %s.",
1617            (int)kextFileInfo->infoDictPhysAddr,
1618            deviceTreeName->getCStringNoCopy());
1619        goto finish;
1620    }
1621
1622    parsedXML = OSUnserializeXML(infoDictAddr, &errorString);
1623    if (parsedXML) {
1624        theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
1625    }
1626    if (!theInfoDict) {
1627        const char * errorCString = "(unknown error)";
1628
1629        if (errorString && errorString->getCStringNoCopy()) {
1630            errorCString = errorString->getCStringNoCopy();
1631        } else if (parsedXML) {
1632            errorCString = "not a dictionary";
1633        }
1634        OSKextLog(this,
1635            kOSKextLogErrorLevel |
1636            kOSKextLogGeneralFlag,
1637            "Error unserializing info dictionary for device tree entry %s: %s.",
1638            deviceTreeName->getCStringNoCopy(), errorCString);
1639        goto finish;
1640    }
1641
1642   /* A bundle path is not mandatory.
1643    */
1644    if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
1645        bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
1646        if (!bundlePathAddr) {
1647            OSKextLog(this,
1648                kOSKextLogErrorLevel |
1649                kOSKextLogGeneralFlag,
1650                "Can't translate physical address 0x%x of kext bundle path "
1651                "for device tree entry %s.",
1652                (int)kextFileInfo->bundlePathPhysAddr,
1653                deviceTreeName->getCStringNoCopy());
1654            goto finish;
1655        }
1656        bundlePathAddr[kextFileInfo->bundlePathLength-1] = '\0'; // just in case!
1657
1658        kextPath = OSString::withCString(bundlePathAddr);
1659        if (!kextPath) {
1660            OSKextLog(this,
1661                kOSKextLogErrorLevel |
1662                kOSKextLogGeneralFlag,
1663                "Failed to create wrapper for device tree entry %s kext path %s.",
1664                deviceTreeName->getCStringNoCopy(), bundlePathAddr);
1665            goto finish;
1666        }
1667    }
1668
1669    if (!setInfoDictionaryAndPath(theInfoDict, kextPath)) {
1670        goto finish;
1671    }
1672
1673   /* An executable is not mandatory.
1674    */
1675    if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
1676        executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
1677        if (!executableAddr) {
1678            OSKextLog(this,
1679                kOSKextLogErrorLevel |
1680                kOSKextLogGeneralFlag,
1681                "Can't translate physical address 0x%x of kext executable "
1682                "for device tree entry %s.",
1683                (int)kextFileInfo->executablePhysAddr,
1684                deviceTreeName->getCStringNoCopy());
1685            goto finish;
1686        }
1687
1688        executable = OSData::withBytesNoCopy(executableAddr,
1689            kextFileInfo->executableLength);
1690        if (!executable) {
1691            OSKextLog(this,
1692                kOSKextLogErrorLevel |
1693                kOSKextLogGeneralFlag,
1694                "Failed to create executable wrapper for device tree entry %s.",
1695                deviceTreeName->getCStringNoCopy());
1696            goto finish;
1697        }
1698
1699       /* A kext with an executable needs to retain the whole booterData
1700        * object to keep the executable in memory.
1701        */
1702        if (!setExecutable(executable, booterData)) {
1703            OSKextLog(this,
1704                kOSKextLogErrorLevel |
1705                kOSKextLogGeneralFlag,
1706                "Failed to set kext executable for device tree entry %s.",
1707                deviceTreeName->getCStringNoCopy());
1708            goto finish;
1709        }
1710    }
1711
1712    result = registerIdentifier();
1713
1714finish:
1715    OSSafeRelease(parsedXML);
1716    OSSafeRelease(kextPath);
1717    OSSafeRelease(errorString);
1718    OSSafeRelease(executable);
1719
1720    return result;
1721}
1722
1723/*********************************************************************
1724*********************************************************************/
1725bool
1726OSKext::registerIdentifier(void)
1727{
1728    bool            result              = false;
1729    OSKext        * existingKext        = NULL;  // do not release
1730    bool            existingIsLoaded    = false;
1731    bool            existingIsPrelinked = false;
1732    OSKextVersion   newVersion          = -1;
1733    OSKextVersion   existingVersion     = -1;
1734    char            newVersionCString[kOSKextVersionMaxLength];
1735    char            existingVersionCString[kOSKextVersionMaxLength];
1736    OSData        * newUUID             = NULL;  // must release
1737    OSData        * existingUUID        = NULL;  // must release
1738
1739    IORecursiveLockLock(sKextLock);
1740
1741   /* Get the new kext's version for checks & log messages.
1742    */
1743    newVersion = getVersion();
1744    OSKextVersionGetString(newVersion, newVersionCString,
1745        kOSKextVersionMaxLength);
1746
1747   /* If we don't have an existing kext with this identifier,
1748    * just record the new kext and we're done!
1749    */
1750    existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID));
1751    if (!existingKext) {
1752        sKextsByID->setObject(bundleID, this);
1753        result = true;
1754        goto finish;
1755    }
1756
1757   /* Get the existing kext's version for checks & log messages.
1758    */
1759    existingVersion = existingKext->getVersion();
1760    OSKextVersionGetString(existingVersion,
1761        existingVersionCString, kOSKextVersionMaxLength);
1762
1763    existingIsLoaded = existingKext->isLoaded();
1764    existingIsPrelinked = existingKext->isPrelinked();
1765
1766   /* If we have a kext with this identifier that's already loaded/prelinked,
1767    * we can't use the new one, but let's be really thorough and check how
1768    * the two are related for a precise diagnostic log message.
1769    *
1770    * Note that user space can't find out about nonloaded prelinked kexts,
1771    * so in this case we log a message when new & existing are equivalent
1772    * at the step rather than warning level, because we are always going
1773    * be getting a copy of the kext in the user load request mkext.
1774    */
1775    if (existingIsLoaded || existingIsPrelinked) {
1776        bool sameVersion = (newVersion == existingVersion);
1777        bool sameExecutable = true;  // assume true unless we have UUIDs
1778
1779       /* Only get the UUID if the existing kext is loaded. Doing so
1780        * might have to uncompress an mkext executable and we shouldn't
1781        * take that hit when neither kext is loaded.
1782        */
1783        newUUID = copyUUID();
1784        existingUUID = existingKext->copyUUID();
1785
1786       /* I'm entirely too paranoid about checking equivalence of executables,
1787        * but I remember nasty problems with it in the past.
1788        *
1789        * - If we have UUIDs for both kexts, compare them.
1790        * - If only one kext has a UUID, they're definitely different.
1791        */
1792        if (newUUID && existingUUID) {
1793            sameExecutable = newUUID->isEqualTo(existingUUID);
1794        } else if (newUUID || existingUUID) {
1795            sameExecutable = false;
1796        }
1797
1798        if (!newUUID && !existingUUID) {
1799
1800           /* If there are no UUIDs, we can't really tell that the executables
1801            * are *different* without a lot of work; the loaded kext's
1802            * unrelocated executable is no longer around (and we never had it
1803            * in-kernel for a prelinked kext). We certainly don't want to do
1804            * a whole fake link for the new kext just to compare, either.
1805            */
1806
1807            OSKextVersionGetString(version, newVersionCString,
1808                sizeof(newVersionCString));
1809            OSKextLog(this,
1810                kOSKextLogWarningLevel |
1811                kOSKextLogKextBookkeepingFlag,
1812                "Notice - new kext %s, v%s matches %s kext "
1813                "but can't determine if executables are the same (no UUIDs).",
1814                getIdentifierCString(),
1815                newVersionCString,
1816                (existingIsLoaded ? "loaded" : "prelinked"));
1817        }
1818
1819        if (sameVersion && sameExecutable) {
1820            OSKextLog(this,
1821                (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
1822                kOSKextLogKextBookkeepingFlag,
1823                "Refusing new kext %s, v%s: a %s copy is already present "
1824                "(same version and executable).",
1825                getIdentifierCString(), newVersionCString,
1826                (existingIsLoaded ? "loaded" : "prelinked"));
1827        } else {
1828            if (!sameVersion) {
1829               /* This condition is significant so log it under warnings.
1830                */
1831                OSKextLog(this,
1832                    kOSKextLogWarningLevel |
1833                    kOSKextLogKextBookkeepingFlag,
1834                    "Refusing new kext %s, v%s: already have %s v%s.",
1835                    getIdentifierCString(),
1836                    newVersionCString,
1837                    (existingIsLoaded ? "loaded" : "prelinked"),
1838                    existingVersionCString);
1839            } else {
1840               /* This condition is significant so log it under warnings.
1841                */
1842                OSKextLog(this,
1843                    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
1844                    "Refusing new kext %s, v%s: a %s copy with a different "
1845                    "executable UUID is already present.",
1846                    getIdentifierCString(), newVersionCString,
1847                    (existingIsLoaded ? "loaded" : "prelinked"));
1848            }
1849        }
1850        goto finish;
1851    } /* if (existingIsLoaded || existingIsPrelinked) */
1852
1853   /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
1854    * user loads are happening or if we're still in early boot. User agents are
1855    * supposed to resolve dependencies topside and include only the exact
1856    * kexts needed; so we always accept the new kext (in fact we should never
1857    * see an older unloaded copy hanging around).
1858    */
1859    if (sUserLoadsActive) {
1860        sKextsByID->setObject(bundleID, this);
1861        result = true;
1862
1863        OSKextLog(this,
1864            kOSKextLogStepLevel |
1865            kOSKextLogKextBookkeepingFlag,
1866            "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
1867            getIdentifierCString(),
1868            existingVersionCString,
1869            newVersionCString);
1870
1871        goto finish;
1872    }
1873
1874   /* During early boot, the kext with the highest version always wins out.
1875    * Prelinked kernels will never hit this, but mkexts and booter-read
1876    * kexts might have duplicates.
1877    */
1878    if (newVersion > existingVersion) {
1879        sKextsByID->setObject(bundleID, this);
1880        result = true;
1881
1882        OSKextLog(this,
1883            kOSKextLogStepLevel |
1884            kOSKextLogKextBookkeepingFlag,
1885            "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
1886            existingVersionCString,
1887            getIdentifierCString(),
1888            newVersionCString);
1889
1890    } else {
1891        OSKextLog(this,
1892            kOSKextLogStepLevel |
1893            kOSKextLogKextBookkeepingFlag,
1894            "Kext %s is already registered with a higher/same version (v%s); "
1895            "dropping newly-added (v%s).",
1896            getIdentifierCString(),
1897            existingVersionCString,
1898            newVersionCString);
1899    }
1900
1901   /* result has been set appropriately by now. */
1902
1903finish:
1904
1905    IORecursiveLockUnlock(sKextLock);
1906
1907    if (result) {
1908        OSKextLog(this,
1909            kOSKextLogStepLevel |
1910            kOSKextLogKextBookkeepingFlag,
1911            "Kext %s, v%s registered and available for loading.",
1912            getIdentifierCString(), newVersionCString);
1913    }
1914
1915    OSSafeRelease(newUUID);
1916    OSSafeRelease(existingUUID);
1917
1918    return result;
1919}
1920
1921/*********************************************************************
1922* Does the bare minimum validation to look up a kext.
1923* All other validation is done on the spot as needed.
1924**********************************************************************/
1925bool
1926OSKext::setInfoDictionaryAndPath(
1927    OSDictionary * aDictionary,
1928    OSString     * aPath)
1929{
1930    bool           result                   = false;
1931    OSString     * bundleIDString           = NULL;  // do not release
1932    OSString     * versionString            = NULL;  // do not release
1933    OSString     * compatibleVersionString  = NULL;  // do not release
1934    const char   * versionCString           = NULL;  // do not free
1935    const char   * compatibleVersionCString = NULL;  // do not free
1936    OSBoolean    * scratchBool              = NULL;  // do not release
1937    OSDictionary * scratchDict              = NULL;  // do not release
1938
1939    if (infoDict) {
1940        panic("Attempt to set info dictionary on a kext "
1941            "that already has one (%s).",
1942            getIdentifierCString());
1943    }
1944
1945    if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
1946        goto finish;
1947    }
1948
1949    infoDict = aDictionary;
1950    infoDict->retain();
1951
1952   /* Check right away if the info dictionary has any log flags.
1953    */
1954    scratchBool = OSDynamicCast(OSBoolean,
1955        getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
1956    if (scratchBool == kOSBooleanTrue) {
1957        flags.loggingEnabled = 1;
1958    }
1959
1960   /* The very next thing to get is the bundle identifier. Unlike
1961    * in user space, a kext with no bundle identifier gets axed
1962    * immediately.
1963    */
1964    bundleIDString = OSDynamicCast(OSString,
1965        getPropertyForHostArch(kCFBundleIdentifierKey));
1966    if (!bundleIDString) {
1967        OSKextLog(this,
1968            kOSKextLogErrorLevel |
1969            kOSKextLogValidationFlag,
1970            "CFBundleIdentifier missing/invalid type in kext %s.",
1971            aPath ? aPath->getCStringNoCopy() : "(unknown)");
1972        goto finish;
1973    }
1974    bundleID = OSSymbol::withString(bundleIDString);
1975    if (!bundleID) {
1976        OSKextLog(this,
1977            kOSKextLogErrorLevel |
1978            kOSKextLogValidationFlag,
1979            "Can't copy bundle identifier as symbol for kext %s.",
1980            bundleIDString->getCStringNoCopy());
1981        goto finish;
1982    }
1983
1984   /* Save the path if we got one (it should always be available but it's
1985    * just something nice to have for bookkeeping).
1986    */
1987    if (aPath) {
1988        path = aPath;
1989        path->retain();
1990    }
1991
1992   /*****
1993    * Minimal validation to initialize. We'll do other validation on the spot.
1994    */
1995    if (bundleID->getLength() >= KMOD_MAX_NAME) {
1996        OSKextLog(this,
1997            kOSKextLogErrorLevel |
1998            kOSKextLogValidationFlag,
1999            "Kext %s error - CFBundleIdentifier over max length %d.",
2000            getIdentifierCString(), KMOD_MAX_NAME - 1);
2001        goto finish;
2002    }
2003
2004    version = compatibleVersion = -1;
2005
2006    versionString = OSDynamicCast(OSString,
2007        getPropertyForHostArch(kCFBundleVersionKey));
2008    if (!versionString) {
2009        OSKextLog(this,
2010            kOSKextLogErrorLevel |
2011            kOSKextLogValidationFlag,
2012            "Kext %s error - CFBundleVersion missing/invalid type.",
2013            getIdentifierCString());
2014        goto finish;
2015    }
2016    versionCString = versionString->getCStringNoCopy();
2017    version = OSKextParseVersionString(versionCString);
2018    if (version < 0) {
2019        OSKextLog(this,
2020            kOSKextLogErrorLevel |
2021            kOSKextLogValidationFlag,
2022            "Kext %s error - CFBundleVersion bad value '%s'.",
2023            getIdentifierCString(), versionCString);
2024        goto finish;
2025    }
2026
2027    compatibleVersion = -1;  // set to illegal value for kexts that don't have
2028
2029    compatibleVersionString = OSDynamicCast(OSString,
2030        getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2031    if (compatibleVersionString) {
2032        compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2033        compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2034        if (compatibleVersion < 0) {
2035            OSKextLog(this,
2036                kOSKextLogErrorLevel |
2037                kOSKextLogValidationFlag,
2038                "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2039                getIdentifierCString(), compatibleVersionCString);
2040            goto finish;
2041        }
2042
2043        if (compatibleVersion > version) {
2044            OSKextLog(this,
2045                kOSKextLogErrorLevel |
2046                kOSKextLogValidationFlag,
2047                "Kext %s error - %s %s > %s %s (must be <=).",
2048                getIdentifierCString(),
2049                kOSBundleCompatibleVersionKey, compatibleVersionCString,
2050                kCFBundleVersionKey,  versionCString);
2051            goto finish;
2052        }
2053    }
2054
2055    /* Check to see if this kext is in exclude list */
2056    if ( isInExcludeList() ) {
2057        OSKextLog(this,
2058                  kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2059                  "Kext %s is in exclude list, not loadable",
2060                  getIdentifierCString());
2061        goto finish;
2062    }
2063
2064   /* Set flags for later use if the infoDict gets flushed. We only
2065    * check for true values, not false ones(!)
2066    */
2067    scratchBool = OSDynamicCast(OSBoolean,
2068        getPropertyForHostArch(kOSBundleIsInterfaceKey));
2069    if (scratchBool == kOSBooleanTrue) {
2070        flags.interface = 1;
2071    }
2072
2073    scratchBool = OSDynamicCast(OSBoolean,
2074        getPropertyForHostArch(kOSKernelResourceKey));
2075    if (scratchBool == kOSBooleanTrue) {
2076        flags.kernelComponent = 1;
2077        flags.interface = 1;  // xxx - hm. the kernel itself isn't an interface...
2078        flags.started = 1;
2079
2080       /* A kernel component has one implicit dependency on the kernel.
2081        */
2082        flags.hasAllDependencies = 1;
2083    }
2084
2085   /* Make sure common string values in personalities are uniqued to OSSymbols.
2086    */
2087    scratchDict = OSDynamicCast(OSDictionary,
2088        getPropertyForHostArch(kIOKitPersonalitiesKey));
2089    if (scratchDict) {
2090        uniquePersonalityProperties(scratchDict);
2091    }
2092
2093    result = true;
2094
2095finish:
2096
2097    return result;
2098}
2099
2100/*********************************************************************
2101* Not used for prelinked kernel boot as there is no unrelocated
2102* executable.
2103*********************************************************************/
2104bool
2105OSKext::setExecutable(
2106    OSData * anExecutable,
2107    OSData * externalData,
2108    bool     externalDataIsMkext)
2109{
2110    bool         result        = false;
2111    const char * executableKey = NULL;  // do not free
2112
2113    if (!anExecutable) {
2114        infoDict->removeObject(_kOSKextExecutableKey);
2115        infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
2116        infoDict->removeObject(_kOSKextExecutableExternalDataKey);
2117        result = true;
2118        goto finish;
2119    }
2120
2121    if (infoDict->getObject(_kOSKextExecutableKey) ||
2122        infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
2123
2124        panic("Attempt to set an executable on a kext "
2125            "that already has one (%s).",
2126            getIdentifierCString());
2127        goto finish;
2128    }
2129
2130    if (externalDataIsMkext) {
2131        executableKey = _kOSKextMkextExecutableReferenceKey;
2132    } else {
2133        executableKey = _kOSKextExecutableKey;
2134    }
2135
2136    if (anExecutable) {
2137        infoDict->setObject(executableKey, anExecutable);
2138        if (externalData) {
2139            infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
2140        }
2141    }
2142
2143    result = true;
2144
2145finish:
2146    return result;
2147}
2148
2149/*********************************************************************
2150*********************************************************************/
2151static void
2152uniqueStringPlistProperty(OSDictionary * dict, const char * key)
2153{
2154    OSString       * stringValue = NULL;  // do not release
2155    const OSSymbol * symbolValue = NULL;  // must release
2156
2157    stringValue = OSDynamicCast(OSString, dict->getObject(key));
2158    if (!stringValue) {
2159        goto finish;
2160    }
2161
2162    symbolValue = OSSymbol::withString(stringValue);
2163    if (!symbolValue) {
2164        goto finish;
2165    }
2166
2167    dict->setObject(key, symbolValue);
2168
2169finish:
2170    if (symbolValue) symbolValue->release();
2171
2172    return;
2173}
2174
2175/*********************************************************************
2176*********************************************************************/
2177static void
2178uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
2179{
2180    OSString       * stringValue = NULL;  // do not release
2181    const OSSymbol * symbolValue = NULL;  // must release
2182
2183    stringValue = OSDynamicCast(OSString, dict->getObject(key));
2184    if (!stringValue) {
2185        goto finish;
2186    }
2187
2188    symbolValue = OSSymbol::withString(stringValue);
2189    if (!symbolValue) {
2190        goto finish;
2191    }
2192
2193    dict->setObject(key, symbolValue);
2194
2195finish:
2196    if (symbolValue) symbolValue->release();
2197
2198    return;
2199}
2200
2201/*********************************************************************
2202* Replace common personality property values with uniqued instances
2203* to save on wired memory.
2204*********************************************************************/
2205/* static */
2206void
2207OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
2208{
2209   /* Properties every personality has.
2210    */
2211    uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
2212    uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
2213    uniqueStringPlistProperty(personalityDict, gIOClassKey);
2214
2215   /* Other commonly used properties.
2216    */
2217    uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
2218    uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
2219    uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
2220
2221    uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
2222    uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
2223    uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
2224    uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
2225    uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
2226    uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
2227    uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
2228    uniqueStringPlistProperty(personalityDict, "Vendor");
2229    uniqueStringPlistProperty(personalityDict, "Vendor Identification");
2230    uniqueStringPlistProperty(personalityDict, "Vendor Name");
2231    uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
2232    uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
2233    uniqueStringPlistProperty(personalityDict, "idProduct");
2234
2235    return;
2236}
2237
2238/*********************************************************************
2239*********************************************************************/
2240void
2241OSKext::free(void)
2242{
2243    if (isLoaded()) {
2244        panic("Attempt to free loaded kext %s.", getIdentifierCString());
2245    }
2246
2247    OSSafeRelease(infoDict);
2248    OSSafeRelease(bundleID);
2249    OSSafeRelease(path);
2250    OSSafeRelease(executableRelPath);
2251    OSSafeRelease(dependencies);
2252    OSSafeRelease(linkedExecutable);
2253    OSSafeRelease(metaClasses);
2254    OSSafeRelease(interfaceUUID);
2255
2256    if (isInterface() && kmod_info) {
2257        kfree(kmod_info, sizeof(kmod_info_t));
2258    }
2259
2260    super::free();
2261    return;
2262}
2263
2264#if PRAGMA_MARK
2265#pragma mark Mkext files
2266#endif
2267/*********************************************************************
2268*********************************************************************/
2269OSReturn
2270OSKext::readMkextArchive(OSData * mkextData,
2271    uint32_t * checksumPtr)
2272{
2273    OSReturn       result       = kOSKextReturnBadData;
2274    uint32_t       mkextLength  = 0;
2275    mkext_header * mkextHeader  = 0;   // do not free
2276    uint32_t       mkextVersion = 0;
2277
2278   /* Note default return of kOSKextReturnBadData above.
2279    */
2280    mkextLength = mkextData->getLength();
2281    if (mkextLength < sizeof(mkext_basic_header)) {
2282        OSKextLog(/* kext */ NULL,
2283            kOSKextLogErrorLevel |
2284            kOSKextLogArchiveFlag,
2285            "Mkext archive too small to be valid.");
2286        goto finish;
2287    }
2288
2289    mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
2290
2291    if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
2292        MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
2293        OSKextLog(/* kext */ NULL,
2294            kOSKextLogErrorLevel |
2295            kOSKextLogArchiveFlag,
2296            "Mkext archive has invalid magic or signature.");
2297        goto finish;
2298    }
2299
2300    if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
2301        OSKextLog(/* kext */ NULL,
2302            kOSKextLogErrorLevel |
2303            kOSKextLogArchiveFlag,
2304            "Mkext archive recorded length doesn't match actual file length.");
2305        goto finish;
2306    }
2307
2308    mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2309
2310    if (mkextVersion == MKEXT_VERS_2) {
2311        result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
2312    } else if (mkextVersion == MKEXT_VERS_1) {
2313        result = OSKext::readMkext1Archive(mkextData, checksumPtr);
2314    } else {
2315        OSKextLog(/* kext */ NULL,
2316            kOSKextLogErrorLevel |
2317            kOSKextLogArchiveFlag,
2318            "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
2319        result = kOSKextReturnUnsupported;
2320    }
2321
2322finish:
2323    return result;
2324}
2325
2326/*********************************************************************
2327* Assumes magic, signature, version, length have been checked.
2328*
2329* Doesn't do as much bounds-checking as it should, but we're dropping
2330* mkext1 support from the kernel for SnowLeopard soon.
2331*
2332* Should keep track of all kexts created so far, and if we hit a
2333* fatal error halfway through, remove those kexts. If we've dropped
2334* an older version that had already been read, whoops! Might want to
2335* add a level of buffering?
2336*********************************************************************/
2337/* static */
2338OSReturn
2339OSKext::readMkext1Archive(
2340    OSData   * mkextData,
2341    uint32_t * checksumPtr)
2342{
2343    OSReturn        result              = kOSReturnError;
2344    uint32_t        mkextLength;
2345    mkext1_header * mkextHeader         = 0;  // do not free
2346    void          * mkextEnd            = 0;  // do not free
2347    uint32_t        mkextVersion;
2348    uint8_t       * crc_address         = 0;
2349    uint32_t        checksum;
2350    uint32_t        numKexts            = 0;
2351
2352    OSData        * infoDictDataObject  = NULL;  // must release
2353    OSObject      * parsedXML           = NULL;  // must release
2354    OSDictionary  * infoDict            = NULL;  // do not release
2355    OSString      * errorString         = NULL;  // must release
2356    OSData        * mkextExecutableInfo = NULL;  // must release
2357    OSKext        * theKext             = NULL;  // must release
2358
2359    mkextLength = mkextData->getLength();
2360    mkextHeader = (mkext1_header *)mkextData->getBytesNoCopy();
2361    mkextEnd = (char *)mkextHeader + mkextLength;
2362    mkextVersion = OSSwapBigToHostInt32(mkextHeader->version);
2363
2364    crc_address = (u_int8_t *)&mkextHeader->version;
2365    checksum = mkext_adler32(crc_address,
2366        (uintptr_t)mkextHeader +
2367        OSSwapBigToHostInt32(mkextHeader->length) - (uintptr_t)crc_address);
2368
2369    if (OSSwapBigToHostInt32(mkextHeader->adler32) != checksum) {
2370        OSKextLog(/* kext */ NULL,
2371            kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2372            "Kext archive has a bad checksum.");
2373        result = kOSKextReturnBadData;
2374        goto finish;
2375    }
2376
2377    if (checksumPtr) {
2378        *checksumPtr = checksum;
2379    }
2380
2381   /* Check that the CPU type & subtype match that of the running kernel. */
2382    if (OSSwapBigToHostInt32(mkextHeader->cputype) != (UInt32)CPU_TYPE_ANY) {
2383        if ((UInt32)_mh_execute_header.cputype !=
2384            OSSwapBigToHostInt32(mkextHeader->cputype)) {
2385
2386            OSKextLog(/* kext */ NULL,
2387                kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2388                "Kext archive doesn't contain software "
2389                "for this computer's CPU type.");
2390            result = kOSKextReturnArchNotFound;
2391            goto finish;
2392        }
2393    }
2394
2395    numKexts = OSSwapBigToHostInt32(mkextHeader->numkexts);
2396
2397    for (uint32_t i = 0; i < numKexts; i++) {
2398
2399        OSSafeReleaseNULL(infoDictDataObject);
2400        OSSafeReleaseNULL(infoDict);
2401        OSSafeReleaseNULL(mkextExecutableInfo);
2402        OSSafeReleaseNULL(errorString);
2403        OSSafeReleaseNULL(theKext);
2404
2405        mkext_kext * kextEntry = &mkextHeader->kext[i];
2406        mkext_file * infoDictPtr = &kextEntry->plist;
2407        mkext_file * executablePtr = &kextEntry->module;
2408        if (kextEntry >= mkextEnd) {
2409            OSKextLog(/* kext */ NULL,
2410                kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2411                "Mkext file overrun.");
2412            result = kOSKextReturnBadData;
2413            goto finish;
2414        }
2415
2416       /* Note that we're pretty tolerant of errors in individual entries.
2417        * As long as we can keep processing, we do.
2418        */
2419        infoDictDataObject = OSKext::extractMkext1Entry(
2420            mkextHeader, infoDictPtr);
2421        if (!infoDictDataObject) {
2422            OSKextLog(/* kext */ NULL,
2423                kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2424                "Can't uncompress info dictionary "
2425                "from mkext archive entry %d.", i);
2426            continue;
2427        }
2428
2429        parsedXML = OSUnserializeXML(
2430                (const char *)infoDictDataObject->getBytesNoCopy(),
2431                &errorString);
2432        if (parsedXML) {
2433            infoDict = OSDynamicCast(OSDictionary, parsedXML);
2434        }
2435        if (!infoDict) {
2436            const char * errorCString = "(unknown error)";
2437
2438            if (errorString && errorString->getCStringNoCopy()) {
2439                errorCString = errorString->getCStringNoCopy();
2440            } else if (parsedXML) {
2441                errorCString = "not a dictionary";
2442            }
2443            OSKextLog(/* kext */ NULL,
2444                kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2445                "Error: Can't read XML property list "
2446                  "for mkext archive entry %d: %s.", i, errorCString);
2447            continue;
2448        }
2449
2450        theKext = new OSKext;
2451        if (!theKext) {
2452            OSKextLog(/* kext */ NULL,
2453                kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2454                "Kext allocation failure.");
2455            continue;
2456        }
2457
2458       /*****
2459        * Prepare an entry to hold the mkext entry info for the
2460        * compressed binary module, if there is one. If all four fields
2461        * of the module entry are zero, there isn't one.
2462        */
2463        if ((OSSwapBigToHostInt32(executablePtr->offset) ||
2464            OSSwapBigToHostInt32(executablePtr->compsize) ||
2465            OSSwapBigToHostInt32(executablePtr->realsize) ||
2466            OSSwapBigToHostInt32(executablePtr->modifiedsecs))) {
2467
2468            MkextEntryRef entryRef;
2469
2470            mkextExecutableInfo = OSData::withCapacity(sizeof(entryRef));
2471            if (!mkextExecutableInfo) {
2472                panic("Error: Couldn't allocate data object "
2473                      "for mkext archive entry %d.\n", i);
2474            }
2475
2476            entryRef.mkext = (mkext_basic_header *)mkextHeader;
2477            entryRef.fileinfo = (uint8_t *)executablePtr;
2478            if (!mkextExecutableInfo->appendBytes(&entryRef,
2479                sizeof(entryRef))) {
2480
2481                OSKextLog(/* kext */ NULL,
2482                    kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2483                    "Couldn't record executable info "
2484                    "for mkext archive entry %d.", i);
2485                // we might hit a load error later but oh well
2486                // xxx - should probably remove theKext
2487                continue;
2488            }
2489
2490        }
2491
2492       /* Init can fail because of a data/runtime error, or because the
2493        * kext is a dup. Either way, we don't care here.
2494        */
2495        if (!theKext->initWithMkext1Info(infoDict, mkextExecutableInfo,
2496            mkextData)) {
2497
2498            // theKext is released at the top of the loop or in the finish block
2499            continue;
2500        }
2501
2502       /* If we got even one kext out of the mkext archive,
2503        * we have successfully read the archive, in that we
2504        * have data references into its mapped memory.
2505        */
2506        result = kOSReturnSuccess;
2507    }
2508
2509finish:
2510
2511    OSSafeRelease(infoDictDataObject);
2512    OSSafeRelease(parsedXML);
2513    OSSafeRelease(errorString);
2514    OSSafeRelease(mkextExecutableInfo);
2515    OSSafeRelease(theKext);
2516
2517    return result;
2518}
2519
2520/*********************************************************************
2521*********************************************************************/
2522bool
2523OSKext::initWithMkext1Info(
2524    OSDictionary * anInfoDict,
2525    OSData       * executableWrapper,
2526    OSData       * mkextData)
2527{
2528    bool result = false;
2529
2530    // mkext1 doesn't allow for path (might stuff in info dict)
2531    if (!setInfoDictionaryAndPath(anInfoDict, /* path */ NULL)) {
2532        goto finish;
2533    }
2534
2535    if (!registerIdentifier()) {
2536        goto finish;
2537    }
2538
2539    if (!setExecutable(executableWrapper, mkextData, true)) {
2540        goto finish;
2541    }
2542
2543    result = true;
2544
2545finish:
2546
2547   /* If we can't init, remove the kext from the lookup dictionary.
2548    * This is safe to call in init because there's an implicit retain.
2549    */
2550    if (!result) {
2551        OSKext::removeKext(this, /* removePersonalities? */ false);
2552    }
2553
2554    return result;
2555}
2556
2557/*********************************************************************
2558* xxx - this should take the input data length
2559*********************************************************************/
2560/* static */
2561OSData *
2562OSKext::extractMkext1Entry(
2563    const void  * mkextFileBase,
2564    const void  * entry)
2565{
2566    OSData      * result                 = NULL;
2567    OSData      * uncompressedData       = NULL;  // release on error
2568    const char  * errmsg                 = NULL;
2569
2570    mkext_file  * fileinfo;
2571    uint8_t     * uncompressedDataBuffer = 0; // do not free (panic on alloc. fail)
2572    size_t        uncompressed_size      = 0;
2573    kern_return_t kern_result;
2574
2575    fileinfo = (mkext_file *)entry;
2576
2577    size_t offset = OSSwapBigToHostInt32(fileinfo->offset);
2578    size_t compressed_size = OSSwapBigToHostInt32(fileinfo->compsize);
2579    size_t expected_size = OSSwapBigToHostInt32(fileinfo->realsize);
2580
2581    // Add 1 for '\0' to terminate XML string (for plists)
2582    // (we really should have the archive format include that).
2583    size_t alloc_size = expected_size + 1;
2584    time_t modifiedsecs = OSSwapBigToHostInt32(fileinfo->modifiedsecs);
2585
2586   /* If these four fields are zero there's no file, but it's up to
2587    * the calling context to decide if that's an error.
2588    */
2589    if (offset == 0 && compressed_size == 0 &&
2590        expected_size == 0 && modifiedsecs == 0) {
2591        goto finish;
2592    }
2593
2594    kern_result = kmem_alloc(kernel_map,
2595        (vm_offset_t *)&uncompressedDataBuffer,
2596        alloc_size);
2597    if (kern_result != KERN_SUCCESS) {
2598        panic(ALLOC_FAIL);
2599        goto finish;
2600    }
2601
2602    uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer,
2603        alloc_size);
2604    if (uncompressedData == NULL) {
2605       /* No need to free uncompressedDataBuffer here, either. */
2606        panic(ALLOC_FAIL);
2607        goto finish;
2608    }
2609    uncompressedData->setDeallocFunction(&osdata_kmem_free);
2610
2611   /* Do the decompression if necessary. Note that even if the file isn't
2612    * compressed, we want to make a copy so that we don't have the tie to
2613    * the larger mkext file buffer any more.
2614    * xxx - need to detect decompression overflow too
2615    */
2616    if (compressed_size != 0) {
2617        errmsg = "OSKext::uncompressMkext - "
2618            "uncompressed file shorter than expected";
2619        uncompressed_size = decompress_lzss(uncompressedDataBuffer,
2620            expected_size,
2621            ((uint8_t *)mkextFileBase) + offset,
2622            compressed_size);
2623        if (uncompressed_size != expected_size) {
2624            goto finish;
2625        }
2626    } else {
2627        memcpy(uncompressedDataBuffer,
2628            ((uint8_t *)mkextFileBase) + offset,
2629            expected_size);
2630    }
2631
2632    // Add a terminating nul character in case the data is XML.
2633    // (we really should have the archive format include that).
2634    uncompressedDataBuffer[expected_size] = '\0';
2635
2636    result = uncompressedData;
2637    errmsg = NULL;
2638
2639finish:
2640    if (!result) {
2641        OSKextLog(/* kext */ NULL,
2642            kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2643            "%s", errmsg);
2644
2645        if (uncompressedData) {
2646            uncompressedData->release();
2647        }
2648    }
2649    return result;
2650}
2651
2652/*********************************************************************
2653* Assumes magic, signature, version, length have been checked.
2654* xxx - need to add further bounds checking for each file entry
2655*
2656* Should keep track of all kexts created so far, and if we hit a
2657* fatal error halfway through, remove those kexts. If we've dropped
2658* an older version that had already been read, whoops! Might want to
2659* add a level of buffering?
2660*********************************************************************/
2661/* static */
2662OSReturn
2663OSKext::readMkext2Archive(
2664    OSData        * mkextData,
2665    OSDictionary ** mkextPlistOut,
2666    uint32_t      * checksumPtr)
2667{
2668    OSReturn        result                     = kOSReturnError;
2669    uint32_t        mkextLength;
2670    mkext2_header * mkextHeader                = NULL;  // do not free
2671    void          * mkextEnd                   = NULL;  // do not free
2672    uint32_t        mkextVersion;
2673    uint8_t       * crc_address                = NULL;
2674    uint32_t        checksum;
2675    uint32_t        mkextPlistOffset;
2676    uint32_t        mkextPlistCompressedSize;
2677    char          * mkextPlistEnd              = NULL;  // do not free
2678    uint32_t        mkextPlistFullSize;
2679    OSString      * errorString                = NULL;  // must release
2680    OSData        * mkextPlistUncompressedData = NULL;  // must release
2681    const char    * mkextPlistDataBuffer       = NULL;  // do not free
2682    OSObject      * parsedXML                  = NULL;  // must release
2683    OSDictionary  * mkextPlist                 = NULL;  // do not release
2684    OSArray       * mkextInfoDictArray         = NULL;  // do not release
2685    uint32_t        count, i;
2686
2687    mkextLength = mkextData->getLength();
2688    mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
2689    mkextEnd = (char *)mkextHeader + mkextLength;
2690    mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2691
2692    crc_address = (u_int8_t *)&mkextHeader->version;
2693    checksum = mkext_adler32(crc_address,
2694        (uintptr_t)mkextHeader +
2695        MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address);
2696
2697    if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
2698        OSKextLog(/* kext */ NULL,
2699            kOSKextLogErrorLevel |
2700            kOSKextLogArchiveFlag,
2701            "Mkext archive has bad checksum.");
2702        result = kOSKextReturnBadData;
2703        goto finish;
2704    }
2705
2706    if (checksumPtr) {
2707        *checksumPtr = checksum;
2708    }
2709
2710   /* Check that the CPU type & subtype match that of the running kernel. */
2711    if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
2712        OSKextLog(/* kext */ NULL,
2713            kOSKextLogErrorLevel |
2714            kOSKextLogArchiveFlag,
2715            "Mkext archive must have a specific CPU type.");
2716        result = kOSKextReturnBadData;
2717        goto finish;
2718    } else {
2719        if ((UInt32)_mh_execute_header.cputype !=
2720            MKEXT_GET_CPUTYPE(mkextHeader)) {
2721
2722            OSKextLog(/* kext */ NULL,
2723                kOSKextLogErrorLevel |
2724                kOSKextLogArchiveFlag,
2725                "Mkext archive does not match the running kernel's CPU type.");
2726            result = kOSKextReturnArchNotFound;
2727            goto finish;
2728        }
2729    }
2730
2731    mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
2732    mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
2733    mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
2734        mkextPlistCompressedSize;
2735    if (mkextPlistEnd > mkextEnd) {
2736        OSKextLog(/* kext */ NULL,
2737            kOSKextLogErrorLevel |
2738            kOSKextLogArchiveFlag,
2739            "Mkext archive file overrun.");
2740        result = kOSKextReturnBadData;
2741    }
2742
2743    mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
2744    if (mkextPlistCompressedSize) {
2745        mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
2746            (UInt8 *)mkextHeader + mkextPlistOffset,
2747            "plist",
2748            mkextPlistCompressedSize, mkextPlistFullSize);
2749        if (!mkextPlistUncompressedData) {
2750            goto finish;
2751        }
2752        mkextPlistDataBuffer = (const char *)
2753            mkextPlistUncompressedData->getBytesNoCopy();
2754    } else {
2755        mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
2756    }
2757
2758   /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2759    */
2760    parsedXML = OSUnserializeXML(mkextPlistDataBuffer, &errorString);
2761    if (parsedXML) {
2762        mkextPlist = OSDynamicCast(OSDictionary, parsedXML);
2763    }
2764    if (!mkextPlist) {
2765        const char * errorCString = "(unknown error)";
2766
2767        if (errorString && errorString->getCStringNoCopy()) {
2768            errorCString = errorString->getCStringNoCopy();
2769        } else if (parsedXML) {
2770            errorCString = "not a dictionary";
2771        }
2772        OSKextLog(/* kext */ NULL,
2773            kOSKextLogErrorLevel |
2774            kOSKextLogArchiveFlag,
2775            "Error unserializing mkext plist: %s.", errorCString);
2776        goto finish;
2777    }
2778
2779   /* If the caller needs the plist, hand it back and retain it.
2780    * (This function releases it at the end.)
2781    */
2782    if (mkextPlistOut) {
2783        *mkextPlistOut = mkextPlist;
2784        (*mkextPlistOut)->retain();
2785    }
2786
2787    mkextInfoDictArray = OSDynamicCast(OSArray,
2788        mkextPlist->getObject(kMKEXTInfoDictionariesKey));
2789    if (!mkextInfoDictArray) {
2790        OSKextLog(/* kext */ NULL,
2791            kOSKextLogErrorLevel |
2792            kOSKextLogArchiveFlag,
2793            "Mkext archive contains no kext info dictionaries.");
2794        goto finish;
2795    }
2796
2797    count = mkextInfoDictArray->getCount();
2798    for (i = 0; i < count; i++) {
2799        OSDictionary * infoDict;
2800
2801
2802        infoDict = OSDynamicCast(OSDictionary,
2803            mkextInfoDictArray->getObject(i));
2804
2805       /* Create the kext for the entry, then release it, because the
2806        * kext system keeps them around until explicitly removed.
2807        * Any creation/registration failures are already logged for us.
2808        */
2809        OSKext * newKext = OSKext::withMkext2Info(infoDict, mkextData);
2810        OSSafeRelease(newKext);
2811    }
2812
2813   /* Even if we didn't keep any kexts from the mkext, we may have a load
2814    * request to process, so we are successful (no errors occurred).
2815    */
2816    result = kOSReturnSuccess;
2817
2818finish:
2819
2820    OSSafeRelease(parsedXML);
2821    OSSafeRelease(mkextPlistUncompressedData);
2822    OSSafeRelease(errorString);
2823
2824    return result;
2825}
2826
2827/*********************************************************************
2828*********************************************************************/
2829/* static */
2830OSKext *
2831OSKext::withMkext2Info(
2832    OSDictionary * anInfoDict,
2833    OSData       * mkextData)
2834{
2835    OSKext * newKext = new OSKext;
2836
2837    if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
2838        newKext->release();
2839        return NULL;
2840    }
2841
2842    return newKext;
2843}
2844
2845/*********************************************************************
2846*********************************************************************/
2847bool
2848OSKext::initWithMkext2Info(
2849    OSDictionary * anInfoDict,
2850    OSData       * mkextData)
2851{
2852    bool                   result              = false;
2853    OSString             * kextPath            = NULL;  // do not release
2854    OSNumber             * executableOffsetNum = NULL;  // do not release
2855    OSCollectionIterator * iterator            = NULL;  // must release
2856    OSData               * executable          = NULL;  // must release
2857
2858    if (!super::init()) {
2859        goto finish;
2860    }
2861
2862   /* Get the path. Don't look for an arch-specific path property.
2863    */
2864    kextPath = OSDynamicCast(OSString,
2865        anInfoDict->getObject(kMKEXTBundlePathKey));
2866
2867    if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2868        goto finish;
2869    }
2870
2871   /* If we have a path to the executable, save it.
2872    */
2873    executableRelPath = OSDynamicCast(OSString,
2874        anInfoDict->getObject(kMKEXTExecutableRelativePathKey));
2875    if (executableRelPath) {
2876        executableRelPath->retain();
2877    }
2878
2879   /* Don't need the paths to be in the info dictionary any more.
2880    */
2881    anInfoDict->removeObject(kMKEXTBundlePathKey);
2882    anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
2883
2884    executableOffsetNum = OSDynamicCast(OSNumber,
2885        infoDict->getObject(kMKEXTExecutableKey));
2886    if (executableOffsetNum) {
2887        executable = createMkext2FileEntry(mkextData,
2888            executableOffsetNum, "executable");
2889        infoDict->removeObject(kMKEXTExecutableKey);
2890        if (!executable) {
2891            goto finish;
2892        }
2893        if (!setExecutable(executable, mkextData, true)) {
2894            goto finish;
2895        }
2896    }
2897
2898    result = registerIdentifier();
2899
2900finish:
2901
2902    OSSafeRelease(executable);
2903    OSSafeRelease(iterator);
2904    return result;
2905}
2906
2907/*********************************************************************
2908*********************************************************************/
2909OSData *
2910OSKext::createMkext2FileEntry(
2911    OSData     * mkextData,
2912    OSNumber   * offsetNum,
2913    const char * name)
2914{
2915    OSData        * result      = NULL;
2916    MkextEntryRef   entryRef;
2917    uint8_t       * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
2918    uint32_t        entryOffset = offsetNum->unsigned32BitValue();
2919
2920    result = OSData::withCapacity(sizeof(entryRef));
2921    if (!result) {
2922        goto finish;
2923    }
2924
2925    entryRef.mkext = (mkext_basic_header *)mkextBuffer;
2926    entryRef.fileinfo = mkextBuffer + entryOffset;
2927    if (!result->appendBytes(&entryRef, sizeof(entryRef))) {
2928        OSSafeReleaseNULL(result);
2929        goto finish;
2930    }
2931
2932finish:
2933    if (!result) {
2934        OSKextLog(this,
2935            kOSKextLogErrorLevel |
2936            kOSKextLogArchiveFlag,
2937            "Can't create wrapper for mkext file entry '%s' of kext %s.",
2938            name, getIdentifierCString());
2939    }
2940    return result;
2941}
2942
2943/*********************************************************************
2944*********************************************************************/
2945extern "C" {
2946static void * z_alloc(void *, u_int items, u_int size);
2947static void   z_free(void *, void *ptr);
2948
2949typedef struct z_mem {
2950    uint32_t alloc_size;
2951    uint8_t  data[0];
2952} z_mem;
2953
2954/*
2955 * Space allocation and freeing routines for use by zlib routines.
2956 */
2957void *
2958z_alloc(void * notused __unused, u_int num_items, u_int size)
2959{
2960    void     * result = NULL;
2961    z_mem    * zmem = NULL;
2962    uint32_t   total = num_items * size;
2963    uint32_t   allocSize =  total + sizeof(zmem);
2964
2965    zmem = (z_mem *)kalloc(allocSize);
2966    if (!zmem) {
2967        goto finish;
2968    }
2969    zmem->alloc_size = allocSize;
2970    result = (void *)&(zmem->data);
2971finish:
2972    return result;
2973}
2974
2975void
2976z_free(void * notused __unused, void * ptr)
2977{
2978    uint32_t * skipper = (uint32_t *)ptr - 1;
2979    z_mem    * zmem = (z_mem *)skipper;
2980    kfree((void *)zmem, zmem->alloc_size);
2981    return;
2982}
2983};
2984
2985OSData *
2986OSKext::extractMkext2FileData(
2987    UInt8      * data,
2988    const char * name,
2989    uint32_t     compressedSize,
2990    uint32_t     fullSize)
2991{
2992    OSData      * result = NULL;
2993
2994    OSData      * uncompressedData = NULL;   // release on error
2995
2996    uint8_t     * uncompressedDataBuffer = 0;    // do not free
2997    unsigned long uncompressedSize;
2998    z_stream      zstream;
2999    bool          zstream_inited = false;
3000    int           zlib_result;
3001
3002   /* If the file isn't compressed, we want to make a copy
3003    * so that we don't have the tie to the larger mkext file buffer any more.
3004    */
3005    if (!compressedSize) {
3006        uncompressedData = OSData::withBytes(data, fullSize);
3007        // xxx - no check for failure?
3008        result = uncompressedData;
3009        goto finish;
3010    }
3011
3012    if (KERN_SUCCESS != kmem_alloc(kernel_map,
3013        (vm_offset_t*)&uncompressedDataBuffer, fullSize)) {
3014
3015       /* How's this for cheesy? The kernel is only asked to extract
3016        * kext plists so we tailor the log messages.
3017        */
3018        if (isKernel()) {
3019            OSKextLog(this,
3020                kOSKextLogErrorLevel |
3021                kOSKextLogArchiveFlag,
3022                "Allocation failure extracting %s from mkext.", name);
3023        } else {
3024            OSKextLog(this,
3025                kOSKextLogErrorLevel |
3026                kOSKextLogArchiveFlag,
3027                "Allocation failure extracting %s from mkext for kext %s.",
3028                name, getIdentifierCString());
3029        }
3030
3031        goto finish;
3032    }
3033    uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3034    if (!uncompressedData) {
3035        if (isKernel()) {
3036            OSKextLog(this,
3037                kOSKextLogErrorLevel |
3038                kOSKextLogArchiveFlag,
3039                "Allocation failure extracting %s from mkext.", name);
3040        } else {
3041            OSKextLog(this,
3042                kOSKextLogErrorLevel |
3043                kOSKextLogArchiveFlag,
3044                "Allocation failure extracting %s from mkext for kext %s.",
3045                name, getIdentifierCString());
3046        }
3047        goto finish;
3048    }
3049    uncompressedData->setDeallocFunction(&osdata_kmem_free);
3050
3051    if (isKernel()) {
3052        OSKextLog(this,
3053            kOSKextLogDetailLevel |
3054            kOSKextLogArchiveFlag,
3055            "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3056            name, compressedSize, fullSize);
3057    } else {
3058        OSKextLog(this,
3059            kOSKextLogDetailLevel |
3060            kOSKextLogArchiveFlag,
3061            "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3062            getIdentifierCString(), name, compressedSize, fullSize);
3063    }
3064
3065    bzero(&zstream, sizeof(zstream));
3066    zstream.next_in   = (UInt8 *)data;
3067    zstream.avail_in  = compressedSize;
3068
3069    zstream.next_out  = uncompressedDataBuffer;
3070    zstream.avail_out = fullSize;
3071
3072    zstream.zalloc    = z_alloc;
3073    zstream.zfree     = z_free;
3074
3075    zlib_result = inflateInit(&zstream);
3076    if (Z_OK != zlib_result) {
3077        if (isKernel()) {
3078            OSKextLog(this,
3079                kOSKextLogErrorLevel |
3080                kOSKextLogArchiveFlag,
3081                "Mkext error; zlib inflateInit failed (%d) for %s.",
3082                zlib_result, name);
3083        } else {
3084            OSKextLog(this,
3085                kOSKextLogErrorLevel |
3086                kOSKextLogArchiveFlag,
3087                "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3088                getIdentifierCString(), zlib_result, name);
3089        }
3090        goto finish;
3091    } else {
3092        zstream_inited = true;
3093    }
3094
3095    zlib_result = inflate(&zstream, Z_FINISH);
3096
3097    if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3098        uncompressedSize = zstream.total_out;
3099    } else {
3100        if (isKernel()) {
3101            OSKextLog(this,
3102                kOSKextLogErrorLevel |
3103                kOSKextLogArchiveFlag,
3104                "Mkext error; zlib inflate failed (%d) for %s.",
3105                zlib_result, name);
3106        } else {
3107            OSKextLog(this,
3108                kOSKextLogErrorLevel |
3109                kOSKextLogArchiveFlag,
3110                "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3111                getIdentifierCString(), zlib_result, name);
3112        }
3113        if (zstream.msg) {
3114            OSKextLog(this,
3115                kOSKextLogErrorLevel |
3116                kOSKextLogArchiveFlag,
3117                "zlib error: %s.", zstream.msg);
3118        }
3119        goto finish;
3120    }
3121
3122    if (uncompressedSize != fullSize) {
3123        if (isKernel()) {
3124            OSKextLog(this,
3125                kOSKextLogErrorLevel |
3126                kOSKextLogArchiveFlag,
3127                "Mkext error; zlib inflate discrepancy for %s, "
3128                "uncompressed size != original size.", name);
3129        } else {
3130            OSKextLog(this,
3131                kOSKextLogErrorLevel |
3132                kOSKextLogArchiveFlag,
3133                "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3134                "uncompressed size != original size.",
3135                getIdentifierCString(), name);
3136        }
3137        goto finish;
3138    }
3139
3140    result = uncompressedData;
3141
3142finish:
3143   /* Don't bother checking return, nothing we can do on fail.
3144    */
3145    if (zstream_inited) inflateEnd(&zstream);
3146
3147    if (!result) {
3148        OSSafeRelease(uncompressedData);
3149    }
3150
3151    return result;
3152}
3153
3154/*********************************************************************
3155*********************************************************************/
3156/* static */
3157OSReturn
3158OSKext::loadFromMkext(
3159    OSKextLogSpec   clientLogFilter,
3160    char          * mkextBuffer,
3161    uint32_t        mkextBufferLength,
3162    char         ** logInfoOut,
3163    uint32_t      * logInfoLengthOut)
3164{
3165    OSReturn         result                      = kOSReturnError;
3166    OSReturn         tempResult                  = kOSReturnError;
3167
3168    OSData         * mkextData                   = NULL;  // must release
3169    OSDictionary   * mkextPlist                  = NULL;  // must release
3170
3171    OSArray        * logInfoArray                = NULL;  // must release
3172    OSSerialize    * serializer                  = NULL;  // must release
3173
3174    OSString       * predicate                   = NULL;  // do not release
3175    OSDictionary   * requestArgs                 = NULL;  // do not release
3176
3177    OSString       * kextIdentifier              = NULL;  // do not release
3178    OSNumber       * startKextExcludeNum         = NULL;  // do not release
3179    OSNumber       * startMatchingExcludeNum     = NULL;  // do not release
3180    OSBoolean      * delayAutounloadBool         = NULL;  // do not release
3181    OSArray        * personalityNames            = NULL;  // do not release
3182
3183   /* Default values for these two options: regular autounload behavior,
3184    * load all kexts, send no personalities.
3185    */
3186    Boolean            delayAutounload           = false;
3187    OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
3188    OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3189
3190    IORecursiveLockLock(sKextLock);
3191
3192    if (logInfoOut) {
3193        *logInfoOut = NULL;
3194        *logInfoLengthOut = 0;
3195    }
3196
3197    OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3198
3199    OSKextLog(/* kext */ NULL,
3200        kOSKextLogDebugLevel |
3201        kOSKextLogIPCFlag,
3202        "Received kext load request from user space.");
3203
3204   /* Regardless of processing, the fact that we have gotten here means some
3205    * user-space program is up and talking to us, so we'll switch our kext
3206    * registration to reflect that.
3207    */
3208    if (!sUserLoadsActive) {
3209        OSKextLog(/* kext */ NULL,
3210            kOSKextLogProgressLevel |
3211            kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3212            "Switching to late startup (user-space) kext loading policy.");
3213
3214        sUserLoadsActive = true;
3215    }
3216
3217    if (!sLoadEnabled) {
3218        OSKextLog(/* kext */ NULL,
3219            kOSKextLogErrorLevel |
3220            kOSKextLogLoadFlag,
3221            "Kext loading is disabled.");
3222        result = kOSKextReturnDisabled;
3223        goto finish;
3224    }
3225
3226   /* Note that we do not set a dealloc function on this OSData
3227    * object! No references to it can remain after the loadFromMkext()
3228    * call since we are in a MIG function, and will vm_deallocate()
3229    * the buffer.
3230    */
3231    mkextData = OSData::withBytesNoCopy(mkextBuffer,
3232        mkextBufferLength);
3233    if (!mkextData) {
3234        OSKextLog(/* kext */ NULL,
3235            kOSKextLogErrorLevel |
3236            kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3237            "Failed to create wrapper for kext load request.");
3238        result = kOSKextReturnNoMemory;
3239        goto finish;
3240    }
3241
3242    result = readMkext2Archive(mkextData, &mkextPlist, NULL);
3243    if (result != kOSReturnSuccess) {
3244        OSKextLog(/* kext */ NULL,
3245            kOSKextLogErrorLevel |
3246            kOSKextLogLoadFlag,
3247            "Failed to read kext load request.");
3248        goto finish;
3249    }
3250
3251    predicate = _OSKextGetRequestPredicate(mkextPlist);
3252    if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3253        OSKextLog(/* kext */ NULL,
3254            kOSKextLogErrorLevel |
3255            kOSKextLogLoadFlag,
3256            "Received kext load request with no predicate; skipping.");
3257        result = kOSKextReturnInvalidArgument;
3258        goto finish;
3259    }
3260
3261    requestArgs = OSDynamicCast(OSDictionary,
3262        mkextPlist->getObject(kKextRequestArgumentsKey));
3263    if (!requestArgs || !requestArgs->getCount()) {
3264        OSKextLog(/* kext */ NULL,
3265            kOSKextLogErrorLevel |
3266            kOSKextLogLoadFlag,
3267            "Received kext load request with no arguments.");
3268        result = kOSKextReturnInvalidArgument;
3269        goto finish;
3270    }
3271
3272    kextIdentifier = OSDynamicCast(OSString,
3273        requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3274    if (!kextIdentifier) {
3275        OSKextLog(/* kext */ NULL,
3276            kOSKextLogErrorLevel |
3277            kOSKextLogLoadFlag,
3278            "Received kext load request with no kext identifier.");
3279        result = kOSKextReturnInvalidArgument;
3280        goto finish;
3281    }
3282
3283    startKextExcludeNum = OSDynamicCast(OSNumber,
3284        requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3285    startMatchingExcludeNum = OSDynamicCast(OSNumber,
3286        requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3287    delayAutounloadBool = OSDynamicCast(OSBoolean,
3288        requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3289    personalityNames = OSDynamicCast(OSArray,
3290        requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3291
3292    if (delayAutounloadBool) {
3293        delayAutounload = delayAutounloadBool->getValue();
3294    }
3295    if (startKextExcludeNum) {
3296        startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3297    }
3298    if (startMatchingExcludeNum) {
3299        startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3300    }
3301
3302    OSKextLog(/* kext */ NULL,
3303        kOSKextLogProgressLevel |
3304        kOSKextLogIPCFlag,
3305        "Received request from user space to load kext %s.",
3306        kextIdentifier->getCStringNoCopy());
3307
3308   /* Load the kext, with no deferral, since this is a load from outside
3309    * the kernel.
3310    * xxx - Would like a better way to handle the default values for the
3311    * xxx - start/match opt args.
3312    */
3313    result = OSKext::loadKextWithIdentifier(
3314        kextIdentifier,
3315        /* allowDefer */ false,
3316        delayAutounload,
3317        startKextExcludeLevel,
3318        startMatchingExcludeLevel,
3319        personalityNames);
3320    if (result != kOSReturnSuccess) {
3321        goto finish;
3322    }
3323   /* If the load came down from kextd, it will shortly inform IOCatalogue
3324    * for matching via a separate IOKit calldown.
3325    */
3326
3327finish:
3328
3329   /* Gather up the collected log messages for user space. Any
3330    * error messages past this call will not make it up as log messages
3331    * but will be in the system log.
3332    */
3333    logInfoArray = OSKext::clearUserSpaceLogFilter();
3334
3335    if (logInfoArray && logInfoOut && logInfoLengthOut) {
3336        tempResult = OSKext::serializeLogInfo(logInfoArray,
3337            logInfoOut, logInfoLengthOut);
3338        if (tempResult != kOSReturnSuccess) {
3339            result = tempResult;
3340        }
3341    }
3342
3343    OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3344
3345   /* Note: mkextDataObject will have been retained by every kext w/an
3346    * executable in it. That should all have been flushed out at the
3347    * and of the load operation, but you never know....
3348    */
3349    if (mkextData && mkextData->getRetainCount() > 1) {
3350        OSKextLog(/* kext */ NULL,
3351            kOSKextLogErrorLevel |
3352            kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3353            "Kext load request buffer from user space still retained by a kext; "
3354            "probable memory leak.");
3355    }
3356
3357    IORecursiveLockUnlock(sKextLock);
3358
3359    OSSafeRelease(mkextData);
3360    OSSafeRelease(mkextPlist);
3361    OSSafeRelease(serializer);
3362    OSSafeRelease(logInfoArray);
3363
3364    return result;
3365}
3366
3367/*********************************************************************
3368*********************************************************************/
3369/* static */
3370OSReturn
3371OSKext::serializeLogInfo(
3372    OSArray   * logInfoArray,
3373    char     ** logInfoOut,
3374    uint32_t  * logInfoLengthOut)
3375{
3376    OSReturn        result      = kOSReturnError;
3377    char          * buffer      = NULL;
3378    kern_return_t   kmem_result = KERN_FAILURE;
3379    OSSerialize  * serializer   = NULL;  // must release; reused
3380    char         * logInfo            = NULL;  // returned by reference
3381    uint32_t       logInfoLength      = 0;
3382
3383    if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
3384        OSKextLog(/* kext */ NULL,
3385            kOSKextLogErrorLevel |
3386            kOSKextLogIPCFlag,
3387            "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3388       /* Bad programmer. */
3389        result = kOSKextReturnInvalidArgument;
3390        goto finish;
3391    }
3392
3393    serializer = OSSerialize::withCapacity(0);
3394    if (!serializer) {
3395        OSKextLog(/* kext */ NULL,
3396            kOSKextLogErrorLevel |
3397            kOSKextLogIPCFlag,
3398            "Failed to create serializer on log info for request from user space.");
3399       /* Incidental error; we're going to (try to) allow the request
3400        * itself to succeed. */
3401    }
3402
3403    if (!logInfoArray->serialize(serializer)) {
3404        OSKextLog(/* kext */ NULL,
3405            kOSKextLogErrorLevel |
3406            kOSKextLogIPCFlag,
3407            "Failed to serialize log info for request from user space.");
3408       /* Incidental error; we're going to (try to) allow the request
3409        * itself to succeed. */
3410    } else {
3411        logInfo = serializer->text();
3412        logInfoLength = serializer->getLength();
3413
3414        kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength));
3415        if (kmem_result != KERN_SUCCESS) {
3416            OSKextLog(/* kext */ NULL,
3417                kOSKextLogErrorLevel |
3418                kOSKextLogIPCFlag,
3419                "Failed to copy log info for request from user space.");
3420           /* Incidental error; we're going to (try to) allow the request
3421            * to succeed. */
3422        } else {
3423            /* 11981737 - clear uninitialized data in last page */
3424            bzero((void *)(buffer + logInfoLength),
3425                  (round_page(logInfoLength) - logInfoLength));
3426            memcpy(buffer, logInfo, logInfoLength);
3427            *logInfoOut = buffer;
3428            *logInfoLengthOut = logInfoLength;
3429        }
3430    }
3431
3432    result = kOSReturnSuccess;
3433finish:
3434    OSSafeRelease(serializer);
3435    return result;
3436}
3437
3438#if PRAGMA_MARK
3439#pragma mark Instance Management Methods
3440#endif
3441/*********************************************************************
3442*********************************************************************/
3443OSKext *
3444OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
3445{
3446    OSKext * foundKext = NULL;
3447
3448    IORecursiveLockLock(sKextLock);
3449    foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3450    if (foundKext) {
3451        foundKext->retain();
3452    }
3453    IORecursiveLockUnlock(sKextLock);
3454
3455    return foundKext;
3456}
3457
3458/*********************************************************************
3459*********************************************************************/
3460OSKext *
3461OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
3462{
3463    return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
3464}
3465
3466/*********************************************************************
3467*********************************************************************/
3468OSKext *
3469OSKext::lookupKextWithLoadTag(uint32_t aTag)
3470{
3471    OSKext * foundKext = NULL;                 // returned
3472    uint32_t count, i;
3473
3474    IORecursiveLockLock(sKextLock);
3475
3476    count = sLoadedKexts->getCount();
3477    for (i = 0; i < count; i++) {
3478        OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3479        if (thisKext->getLoadTag() == aTag) {
3480            foundKext = thisKext;
3481            foundKext->retain();
3482            goto finish;
3483        }
3484    }
3485
3486finish:
3487    IORecursiveLockUnlock(sKextLock);
3488
3489    return foundKext;
3490}
3491
3492/*********************************************************************
3493*********************************************************************/
3494OSKext *
3495OSKext::lookupKextWithAddress(vm_address_t address)
3496{
3497    OSKext * foundKext = NULL;                 // returned
3498    uint32_t count, i;
3499
3500    IORecursiveLockLock(sKextLock);
3501
3502    count = sLoadedKexts->getCount();
3503    for (i = 0; i < count; i++) {
3504        OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3505        if (thisKext->linkedExecutable) {
3506            vm_address_t kext_start =
3507                (vm_address_t)thisKext->linkedExecutable->getBytesNoCopy();
3508            vm_address_t kext_end = kext_start +
3509                thisKext->linkedExecutable->getLength();
3510
3511            if ((kext_start <= address) && (address < kext_end)) {
3512                foundKext = thisKext;
3513                foundKext->retain();
3514                goto finish;
3515            }
3516        }
3517    }
3518
3519finish:
3520    IORecursiveLockUnlock(sKextLock);
3521
3522    return foundKext;
3523}
3524
3525/*********************************************************************
3526*********************************************************************/
3527/* static */
3528bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
3529{
3530    bool result = false;
3531    OSKext * foundKext = NULL;                 // returned
3532
3533    IORecursiveLockLock(sKextLock);
3534
3535    foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3536    if (foundKext && foundKext->isLoaded()) {
3537        result = true;
3538    }
3539
3540    IORecursiveLockUnlock(sKextLock);
3541
3542    return result;
3543}
3544
3545/*********************************************************************
3546* xxx - should spawn a separate thread so a kext can safely have
3547* xxx - itself unloaded.
3548*********************************************************************/
3549/* static */
3550OSReturn
3551OSKext::removeKext(
3552    OSKext * aKext,
3553    bool     terminateServicesAndRemovePersonalitiesFlag)
3554 {
3555    OSReturn result    = kOSKextReturnInUse;
3556    OSKext * checkKext = NULL;   // do not release
3557#if CONFIG_MACF
3558    int macCheckResult = 0;
3559    kauth_cred_t cred  = NULL;
3560#endif
3561
3562    IORecursiveLockLock(sKextLock);
3563
3564   /* If the kext has no identifier, it failed to init
3565    * so isn't in sKextsByID and it isn't loaded.
3566    */
3567    if (!aKext->getIdentifier()) {
3568        result = kOSReturnSuccess;
3569        goto finish;
3570    }
3571
3572    checkKext = OSDynamicCast(OSKext,
3573        sKextsByID->getObject(aKext->getIdentifier()));
3574    if (checkKext != aKext) {
3575        result = kOSKextReturnNotFound;
3576        goto finish;
3577    }
3578
3579    if (aKext->isLoaded()) {
3580#if CONFIG_MACF
3581        if (current_task() != kernel_task) {
3582            cred = kauth_cred_get_with_ref();
3583            macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
3584            kauth_cred_unref(&cred);
3585        }
3586
3587        if (macCheckResult != 0) {
3588            result = kOSReturnError;
3589            OSKextLog(aKext,
3590                kOSKextLogErrorLevel |
3591                kOSKextLogKextBookkeepingFlag,
3592                "Failed to remove kext %s (MAC policy error 0x%x).",
3593                aKext->getIdentifierCString(), macCheckResult);
3594            goto finish;
3595        }
3596#endif
3597
3598       /* If we are terminating, send the request to the IOCatalogue
3599        * (which will actually call us right back but that's ok we have
3600        * a recursive lock don't you know) but do not ask the IOCatalogue
3601        * to call back with an unload, we'll do that right here.
3602        */
3603        if (terminateServicesAndRemovePersonalitiesFlag) {
3604            result = gIOCatalogue->terminateDriversForModule(
3605                aKext->getIdentifierCString(), /* unload */ false);
3606            if (result != kOSReturnSuccess) {
3607                OSKextLog(aKext,
3608                    kOSKextLogErrorLevel |
3609                    kOSKextLogKextBookkeepingFlag,
3610                    "Can't remove kext %s; services failed to terminate - 0x%x.",
3611                    aKext->getIdentifierCString(), result);
3612                goto finish;
3613            }
3614        }
3615
3616        result = aKext->unload();
3617        if (result != kOSReturnSuccess) {
3618            goto finish;
3619        }
3620    }
3621
3622   /* Remove personalities as requested. This is a bit redundant for a loaded
3623    * kext as IOCatalogue::terminateDriversForModule() removes driver
3624    * personalities, but it doesn't restart matching, which we always want
3625    * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3626    * that happens.
3627    */
3628    if (terminateServicesAndRemovePersonalitiesFlag) {
3629        aKext->removePersonalitiesFromCatalog();
3630    }
3631
3632    OSKextLog(aKext,
3633        kOSKextLogProgressLevel |
3634        kOSKextLogKextBookkeepingFlag,
3635        "Removing kext %s.",
3636        aKext->getIdentifierCString());
3637
3638    sKextsByID->removeObject(aKext->getIdentifier());
3639    result = kOSReturnSuccess;
3640
3641finish:
3642    IORecursiveLockUnlock(sKextLock);
3643    return result;
3644 }
3645
3646/*********************************************************************
3647*********************************************************************/
3648/* static */
3649OSReturn
3650OSKext::removeKextWithIdentifier(
3651    const char * kextIdentifier,
3652    bool         terminateServicesAndRemovePersonalitiesFlag)
3653{
3654    OSReturn result = kOSReturnError;
3655
3656    IORecursiveLockLock(sKextLock);
3657
3658    OSKext * aKext = OSDynamicCast(OSKext,
3659        sKextsByID->getObject(kextIdentifier));
3660    if (!aKext) {
3661        result = kOSKextReturnNotFound;
3662        OSKextLog(/* kext */ NULL,
3663            kOSKextLogErrorLevel |
3664            kOSKextLogKextBookkeepingFlag,
3665            "Can't remove kext %s - not found.",
3666            kextIdentifier);
3667        goto finish;
3668    }
3669
3670    result = OSKext::removeKext(aKext,
3671        terminateServicesAndRemovePersonalitiesFlag);
3672
3673finish:
3674    IORecursiveLockUnlock(sKextLock);
3675
3676    return result;
3677}
3678
3679/*********************************************************************
3680*********************************************************************/
3681/* static */
3682OSReturn
3683OSKext::removeKextWithLoadTag(
3684    OSKextLoadTag loadTag,
3685    bool          terminateServicesAndRemovePersonalitiesFlag)
3686{
3687    OSReturn result    = kOSReturnError;
3688    OSKext * foundKext = NULL;
3689    uint32_t count, i;
3690
3691    IORecursiveLockLock(sKextLock);
3692
3693    count = sLoadedKexts->getCount();
3694    for (i = 0; i < count; i++) {
3695        OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3696        if (thisKext->loadTag == loadTag) {
3697            foundKext = thisKext;
3698            break;
3699        }
3700    }
3701
3702    if (!foundKext) {
3703        result = kOSKextReturnNotFound;
3704        OSKextLog(/* kext */ NULL,
3705            kOSKextLogErrorLevel |
3706            kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
3707            "Can't remove kext with load tag %d - not found.",
3708            loadTag);
3709        goto finish;
3710    }
3711
3712    result = OSKext::removeKext(foundKext,
3713        terminateServicesAndRemovePersonalitiesFlag);
3714
3715finish:
3716    IORecursiveLockUnlock(sKextLock);
3717
3718    return result;
3719 }
3720
3721/*********************************************************************
3722*********************************************************************/
3723OSDictionary *
3724OSKext::copyKexts(void)
3725{
3726    OSDictionary * result;
3727
3728    IORecursiveLockLock(sKextLock);
3729    result = OSDynamicCast(OSDictionary, sKextsByID->copyCollection());
3730    IORecursiveLockUnlock(sKextLock);
3731
3732    return result;
3733}
3734
3735/*********************************************************************
3736 *********************************************************************/
3737#define BOOTER_KEXT_PREFIX   "Driver-"
3738
3739typedef struct _DeviceTreeBuffer {
3740    uint32_t paddr;
3741    uint32_t length;
3742} _DeviceTreeBuffer;
3743
3744/*********************************************************************
3745 * Create a dictionary of excluded kexts from the given booter data.
3746 *********************************************************************/
3747/* static */
3748void
3749OSKext::createExcludeListFromBooterData(
3750                                        OSDictionary *          theDictionary,
3751                                        OSCollectionIterator *  theIterator )
3752{
3753    OSString                  * deviceTreeName      = NULL;  // do not release
3754    const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;  // do not release
3755    char                      * booterDataPtr       = NULL;  // do not release
3756    _BooterKextFileInfo       * kextFileInfo        = NULL;  // do not release
3757    char                      * infoDictAddr        = NULL;  // do not release
3758    OSObject                  * parsedXML           = NULL;  // must release
3759    OSDictionary              * theInfoDict         = NULL;  // do not release
3760
3761    theIterator->reset();
3762
3763    /* look for AppleKextExcludeList.kext */
3764    while ( (deviceTreeName =
3765             OSDynamicCast(OSString, theIterator->getNextObject())) ) {
3766
3767        const char *    devTreeNameCString;
3768        OSData *        deviceTreeEntry;
3769        OSString *      myBundleID;    // do not release
3770
3771        OSSafeReleaseNULL(parsedXML);
3772
3773        deviceTreeEntry =
3774        OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
3775        if (!deviceTreeEntry) {
3776            continue;
3777        }
3778
3779        /* Make sure it is a kext */
3780        devTreeNameCString = deviceTreeName->getCStringNoCopy();
3781        if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
3782                    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
3783            OSKextLog(NULL,
3784                      kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3785                      "\"%s\" not a kext",
3786                      devTreeNameCString);
3787            continue;
3788        }
3789
3790        deviceTreeBuffer = (const _DeviceTreeBuffer *)
3791        deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
3792        if (!deviceTreeBuffer) {
3793            continue;
3794        }
3795
3796        booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
3797        if (!booterDataPtr) {
3798            continue;
3799        }
3800
3801        kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
3802        if (!kextFileInfo->infoDictPhysAddr ||
3803            !kextFileInfo->infoDictLength)       {
3804            continue;
3805        }
3806
3807        infoDictAddr = (char *)
3808        ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
3809        if (!infoDictAddr) {
3810            continue;
3811        }
3812
3813        parsedXML = OSUnserializeXML(infoDictAddr);
3814        if (!parsedXML) {
3815            continue;
3816        }
3817
3818        theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
3819        if (!theInfoDict) {
3820            continue;
3821        }
3822
3823        myBundleID =
3824        OSDynamicCast(OSString,
3825                      theInfoDict->getObject(kCFBundleIdentifierKey));
3826        if ( myBundleID &&
3827            strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3828
3829            /* get copy of exclusion list dictionary */
3830            OSDictionary *      myTempDict;     // do not free
3831
3832            myTempDict = OSDynamicCast(
3833                                       OSDictionary,
3834                                       theInfoDict->getObject("OSKextExcludeList"));
3835            if ( myTempDict ) {
3836                IORecursiveLockLock(sKextLock);
3837
3838                /* get rid of old exclusion list */
3839                if (sExcludeListByID) {
3840                    sExcludeListByID->flushCollection();
3841                    OSSafeRelease(sExcludeListByID);
3842                }
3843                sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
3844                IORecursiveLockUnlock(sKextLock);
3845            }
3846            break;
3847        }
3848
3849    } // while ( (deviceTreeName = ...) )
3850
3851    OSSafeReleaseNULL(parsedXML);
3852    return;
3853}
3854
3855/*********************************************************************
3856 * Create a dictionary of excluded kexts from the given prelink
3857 * info (kernelcache).
3858 *********************************************************************/
3859/* static */
3860void
3861OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
3862{
3863    OSDictionary *  myInfoDict = NULL;  // do not release
3864    OSString *      myBundleID;         // do not release
3865    u_int           i;
3866
3867    /* Find com.apple.driver.KextExcludeList. */
3868    for (i = 0; i < theInfoArray->getCount(); i++) {
3869        myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
3870        if (!myInfoDict) {
3871            continue;
3872        }
3873        myBundleID =
3874        OSDynamicCast(OSString,
3875                      myInfoDict->getObject(kCFBundleIdentifierKey));
3876        if ( myBundleID &&
3877            strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3878            // get copy of exclude list dictionary
3879            OSDictionary *      myTempDict;     // do not free
3880            myTempDict = OSDynamicCast(OSDictionary,
3881                                       myInfoDict->getObject("OSKextExcludeList"));
3882            if ( myTempDict ) {
3883                IORecursiveLockLock(sKextLock);
3884                // get rid of old exclude list
3885                if (sExcludeListByID) {
3886                    sExcludeListByID->flushCollection();
3887                    OSSafeRelease(sExcludeListByID);
3888                }
3889
3890                sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
3891                IORecursiveLockUnlock(sKextLock);
3892            }
3893            break;
3894        }
3895    } // for (i = 0; i < theInfoArray->getCount()...
3896
3897    return;
3898}
3899
3900#if PRAGMA_MARK
3901#pragma mark Accessors
3902#endif
3903/*********************************************************************
3904*********************************************************************/
3905const OSSymbol *
3906OSKext::getIdentifier(void)
3907{
3908    return bundleID;
3909}
3910
3911/*********************************************************************
3912* A kext must have a bundle identifier to even survive initialization;
3913* this is guaranteed to exist past then.
3914*********************************************************************/
3915const char *
3916OSKext::getIdentifierCString(void)
3917{
3918    return bundleID->getCStringNoCopy();
3919}
3920
3921/*********************************************************************
3922*********************************************************************/
3923OSKextVersion
3924OSKext::getVersion(void)
3925{
3926    return version;
3927}
3928
3929/*********************************************************************
3930*********************************************************************/
3931OSKextVersion
3932OSKext::getCompatibleVersion(void)
3933{
3934    return compatibleVersion;
3935}
3936
3937/*********************************************************************
3938*********************************************************************/
3939bool
3940OSKext::isLibrary(void)
3941{
3942    return (getCompatibleVersion() > 0);
3943}
3944
3945/*********************************************************************
3946*********************************************************************/
3947bool
3948OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
3949{
3950    if ((compatibleVersion > -1 && version > -1) &&
3951        (compatibleVersion <= version && aVersion <= version)) {
3952        return true;
3953    }
3954    return false;
3955}
3956
3957/*********************************************************************
3958*********************************************************************/
3959bool
3960OSKext::declaresExecutable(void)
3961{
3962    return (getPropertyForHostArch(kCFBundleExecutableKey) != NULL);
3963}
3964
3965/*********************************************************************
3966*********************************************************************/
3967OSData *
3968OSKext::getExecutable(void)
3969{
3970    OSData * result              = NULL;
3971    OSData * extractedExecutable = NULL;  // must release
3972    OSData * mkextExecutableRef  = NULL;  // do not release
3973
3974    result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
3975    if (result) {
3976        goto finish;
3977    }
3978
3979    mkextExecutableRef = OSDynamicCast(OSData,
3980        getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
3981
3982    if (mkextExecutableRef) {
3983
3984        MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
3985            mkextExecutableRef->getBytesNoCopy();
3986        uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
3987        if (mkextVersion == MKEXT_VERS_2) {
3988            mkext2_file_entry * fileinfo =
3989                (mkext2_file_entry *)mkextEntryRef->fileinfo;
3990            uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
3991            uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
3992            extractedExecutable = extractMkext2FileData(
3993                MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
3994                compressedSize, fullSize);
3995        } else if (mkextVersion == MKEXT_VERS_1) {
3996            extractedExecutable = extractMkext1Entry(
3997                mkextEntryRef->mkext, mkextEntryRef->fileinfo);
3998        } else {
3999            OSKextLog(this, kOSKextLogErrorLevel |
4000            kOSKextLogArchiveFlag,
4001                "Kext %s - unknown mkext version 0x%x for executable.",
4002                getIdentifierCString(), mkextVersion);
4003        }
4004
4005       /* Regardless of success, remove the mkext executable,
4006        * and drop one reference on the mkext.  (setExecutable() does not
4007        * replace, it removes, or panics if asked to replace.)
4008        */
4009        infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4010        infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4011
4012        if (extractedExecutable && extractedExecutable->getLength()) {
4013            if (!setExecutable(extractedExecutable)) {
4014                goto finish;
4015            }
4016            result = extractedExecutable;
4017        } else {
4018            goto finish;
4019        }
4020    }
4021
4022finish:
4023
4024    OSSafeRelease(extractedExecutable);
4025
4026    return result;
4027}
4028
4029/*********************************************************************
4030*********************************************************************/
4031bool
4032OSKext::isInterface(void)
4033{
4034    return flags.interface;
4035}
4036
4037/*********************************************************************
4038*********************************************************************/
4039bool
4040OSKext::isKernel(void)
4041{
4042    return (this == sKernelKext);
4043}
4044
4045/*********************************************************************
4046*********************************************************************/
4047bool
4048OSKext::isKernelComponent(void)
4049{
4050    return flags.kernelComponent ? true : false;
4051}
4052
4053/*********************************************************************
4054*********************************************************************/
4055bool
4056OSKext::isExecutable(void)
4057{
4058    return (!isKernel() && !isInterface() && declaresExecutable());
4059}
4060
4061/*********************************************************************
4062* We might want to check this recursively for all dependencies,
4063* since a subtree of dependencies could get loaded before we hit
4064* a dependency that isn't safe-boot-loadable.
4065*
4066* xxx - Might want to return false if OSBundleEnableKextLogging or
4067* OSBundleDebugLevel
4068* or IOKitDebug is nonzero too (we used to do that, but I don't see
4069* the point except it's usually development drivers, which might
4070* cause panics on startup, that have those properties). Heh; could
4071* use a "kx" boot-arg!
4072*********************************************************************/
4073bool
4074OSKext::isLoadableInSafeBoot(void)
4075{
4076    bool       result   = false;
4077    OSString * required = NULL;  // do not release
4078
4079    if (isKernel()) {
4080        result = true;
4081        goto finish;
4082    }
4083
4084    required = OSDynamicCast(OSString,
4085        getPropertyForHostArch(kOSBundleRequiredKey));
4086    if (!required) {
4087        goto finish;
4088    }
4089    if (required->isEqualTo(kOSBundleRequiredRoot)        ||
4090        required->isEqualTo(kOSBundleRequiredLocalRoot)   ||
4091        required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
4092        required->isEqualTo(kOSBundleRequiredSafeBoot)    ||
4093        required->isEqualTo(kOSBundleRequiredConsole)) {
4094
4095        result = true;
4096    }
4097
4098finish:
4099    return result;
4100}
4101
4102/*********************************************************************
4103*********************************************************************/
4104bool
4105OSKext::isPrelinked(void)
4106{
4107    return flags.prelinked ? true : false;
4108}
4109
4110/*********************************************************************
4111*********************************************************************/
4112bool OSKext::isLoaded(void)
4113{
4114    return flags.loaded ? true : false;
4115}
4116
4117/*********************************************************************
4118*********************************************************************/
4119bool
4120OSKext::isStarted(void)
4121{
4122    return flags.started ? true : false;
4123}
4124
4125/*********************************************************************
4126*********************************************************************/
4127bool
4128OSKext::isCPPInitialized(void)
4129{
4130    return flags.CPPInitialized;
4131}
4132
4133/*********************************************************************
4134*********************************************************************/
4135void
4136OSKext::setCPPInitialized(bool initialized)
4137{
4138    flags.CPPInitialized = initialized;
4139}
4140
4141/*********************************************************************
4142*********************************************************************/
4143uint32_t
4144OSKext::getLoadTag(void)
4145{
4146    return loadTag;
4147}
4148
4149/*********************************************************************
4150 *********************************************************************/
4151void OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
4152{
4153    if (linkedExecutable) {
4154        *loadSize = linkedExecutable->getLength();
4155
4156        /* If we have a kmod_info struct, calculated the wired size
4157         * from that. Otherwise it's the full load size.
4158         */
4159        if (kmod_info) {
4160            *wiredSize = *loadSize - kmod_info->hdr_size;
4161        } else {
4162            *wiredSize = *loadSize;
4163        }
4164    }
4165    else {
4166        *wiredSize = 0;
4167        *loadSize = 0;
4168    }
4169}
4170
4171/*********************************************************************
4172*********************************************************************/
4173OSData *
4174OSKext::copyUUID(void)
4175{
4176    OSData                     * result        = NULL;
4177    OSData                     * theExecutable = NULL;  // do not release
4178    const kernel_mach_header_t * header        = NULL;
4179    const struct load_command  * load_cmd      = NULL;
4180    const struct uuid_command  * uuid_cmd      = NULL;
4181    uint32_t                     i;
4182
4183   /* An interface kext doesn't have a linked executable with an LC_UUID,
4184    * we create one when it's linked.
4185    */
4186    if (interfaceUUID) {
4187        result = interfaceUUID;
4188        result->retain();
4189        goto finish;
4190    }
4191
4192   /* For real kexts, try to get the UUID from the linked executable,
4193    * or if is hasn't been linked yet, the unrelocated executable.
4194    */
4195    theExecutable = linkedExecutable;
4196    if (!theExecutable) {
4197        theExecutable = getExecutable();
4198    }
4199    if (!theExecutable) {
4200        goto finish;
4201    }
4202
4203    header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
4204    load_cmd = (const struct load_command *)&header[1];
4205
4206    for (i = 0; i < header->ncmds; i++) {
4207        if (load_cmd->cmd == LC_UUID) {
4208            uuid_cmd = (struct uuid_command *)load_cmd;
4209            result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid));
4210            goto finish;
4211        }
4212        load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
4213    }
4214
4215finish:
4216    return result;
4217}
4218
4219/*********************************************************************
4220*********************************************************************/
4221
4222#if   defined (__x86_64__)
4223#define ARCHNAME "x86_64"
4224#else
4225#error architecture not supported
4226#endif
4227
4228#define ARCH_SEPARATOR_CHAR  '_'
4229
4230static char * makeHostArchKey(const char * key, uint32_t * keySizeOut)
4231{
4232    char     * result = NULL;
4233    uint32_t   keyLength = strlen(key);
4234    uint32_t   keySize;
4235
4236   /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4237    */
4238    keySize = 1 + 1 + strlen(key) + strlen(ARCHNAME);
4239    result = (char *)kalloc(keySize);
4240    if (!result) {
4241        goto finish;
4242    }
4243    strlcpy(result, key, keySize);
4244    result[keyLength++] = ARCH_SEPARATOR_CHAR;
4245    result[keyLength] = '\0';
4246    strlcat(result, ARCHNAME, keySize);
4247    *keySizeOut = keySize;
4248
4249finish:
4250    return result;
4251}
4252
4253/*********************************************************************
4254*********************************************************************/
4255OSObject *
4256OSKext::getPropertyForHostArch(const char * key)
4257{
4258    OSObject * result           = NULL;  // do not release
4259    uint32_t   hostArchKeySize  = 0;
4260    char     * hostArchKey      = NULL;  // must kfree
4261
4262    if (!key || !infoDict) {
4263        goto finish;
4264    }
4265
4266   /* Some properties are not allowed to be arch-variant:
4267    * - Any CFBundle... property.
4268    * - OSBundleIsInterface.
4269    * - OSKernelResource.
4270    */
4271    if (STRING_HAS_PREFIX(key, "OS") ||
4272        STRING_HAS_PREFIX(key, "IO")) {
4273
4274        hostArchKey = makeHostArchKey(key, &hostArchKeySize);
4275        if (!hostArchKey) {
4276            OSKextLog(/* kext (this isn't about a kext) */ NULL,
4277                kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4278                "Allocation failure.");
4279            goto finish;
4280        }
4281        result = infoDict->getObject(hostArchKey);
4282    }
4283
4284    if (!result) {
4285        result = infoDict->getObject(key);
4286    }
4287
4288finish:
4289    if (hostArchKey) kfree(hostArchKey, hostArchKeySize);
4290    return result;
4291}
4292
4293#if PRAGMA_MARK
4294#pragma mark Load/Start/Stop/Unload
4295#endif
4296
4297#define isWhiteSpace(c)	((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4298
4299/*********************************************************************
4300 * sExcludeListByID is a dictionary with keys / values of:
4301 *  key = bundleID string of kext we will not allow to load
4302 *  value = version string(s) of the kext that is to be denied loading.
4303 *      The version strings can be comma delimited.  For example if kext
4304 *      com.foocompany.fookext has two versions that we want to deny
4305 *      loading then the version strings might look like:
4306 *      1.0.0, 1.0.1
4307 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4308 *      not load the kext.
4309 *
4310 *      Value may also be in the form of "LE 2.0.0" (version numbers
4311 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4312 *      number less than 2.0.0 will not load)
4313 *
4314 *      NOTE - we cannot use the characters "<=" or "<" because we have code
4315 *      that serializes plists and treats '<' as a special character.
4316 *********************************************************************/
4317bool
4318OSKext::isInExcludeList(void)
4319{
4320    OSString *      versionString           = NULL;  // do not release
4321    char *          versionCString          = NULL;  // do not free
4322    size_t          i;
4323    boolean_t       wantLessThan = false;
4324    boolean_t       wantLessThanEqualTo = false;
4325    char            myBuffer[32];
4326
4327    if (!sExcludeListByID) {
4328        return(false);
4329    }
4330    /* look up by bundleID in our exclude list and if found get version
4331     * string (or strings) that we will not allow to load
4332     */
4333    versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID));
4334    if (!versionString) {
4335        return(false);
4336    }
4337
4338    /* parse version strings */
4339    versionCString = (char *) versionString->getCStringNoCopy();
4340
4341    /* look for "LT" or "LE" form of version string, must be in first two
4342     * positions.
4343     */
4344    if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
4345        wantLessThan = true;
4346        versionCString +=2;
4347    }
4348    else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
4349        wantLessThanEqualTo = true;
4350        versionCString +=2;
4351    }
4352
4353    for (i = 0; *versionCString != 0x00; versionCString++) {
4354        /* skip whitespace */
4355        if (isWhiteSpace(*versionCString)) {
4356            continue;
4357        }
4358
4359        /* peek ahead for version string separator or null terminator */
4360        if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
4361
4362            /* OK, we have a version string */
4363            myBuffer[i++] = *versionCString;
4364            myBuffer[i] = 0x00;
4365
4366            OSKextVersion excludeVers;
4367            excludeVers = OSKextParseVersionString(myBuffer);
4368
4369            if (wantLessThanEqualTo) {
4370                if (version <= excludeVers) {
4371                    return(true);
4372                }
4373            }
4374            else if (wantLessThan) {
4375                if (version < excludeVers) {
4376                    return(true);
4377                }
4378            }
4379            else if ( version == excludeVers )  {
4380                return(true);
4381            }
4382
4383            /* reset for the next (if any) version string */
4384            i = 0;
4385            wantLessThan = false;
4386            wantLessThanEqualTo = false;
4387        }
4388        else {
4389            /* save valid version character */
4390            myBuffer[i++] = *versionCString;
4391
4392            /* make sure bogus version string doesn't overrun local buffer */
4393            if ( i >= sizeof(myBuffer) ) {
4394                break;
4395            }
4396        }
4397    }
4398
4399    return(false);
4400}
4401
4402/*********************************************************************
4403*********************************************************************/
4404/* static */
4405OSReturn
4406OSKext::loadKextWithIdentifier(
4407    const char       * kextIdentifierCString,
4408    Boolean            allowDeferFlag,
4409    Boolean            delayAutounloadFlag,
4410    OSKextExcludeLevel startOpt,
4411    OSKextExcludeLevel startMatchingOpt,
4412    OSArray          * personalityNames)
4413{
4414    OSReturn   result         = kOSReturnError;
4415    OSString * kextIdentifier = NULL;  // must release
4416
4417    kextIdentifier = OSString::withCString(kextIdentifierCString);
4418    if (!kextIdentifier) {
4419        result = kOSKextReturnNoMemory;
4420        goto finish;
4421    }
4422    result = OSKext::loadKextWithIdentifier(kextIdentifier,
4423        allowDeferFlag, delayAutounloadFlag,
4424        startOpt, startMatchingOpt, personalityNames);
4425
4426finish:
4427    OSSafeRelease(kextIdentifier);
4428    return result;
4429}
4430
4431/*********************************************************************
4432*********************************************************************/
4433OSReturn
4434OSKext::loadKextWithIdentifier(
4435    OSString          * kextIdentifier,
4436    Boolean             allowDeferFlag,
4437    Boolean             delayAutounloadFlag,
4438    OSKextExcludeLevel  startOpt,
4439    OSKextExcludeLevel  startMatchingOpt,
4440    OSArray           * personalityNames)
4441{
4442    OSReturn          result               = kOSReturnError;
4443    OSReturn          pingResult           = kOSReturnError;
4444    OSKext          * theKext              = NULL;  // do not release
4445    OSDictionary    * loadRequest          = NULL;  // must release
4446    const OSSymbol  * kextIdentifierSymbol = NULL;  // must release
4447#if CONFIG_MACF
4448    int               macCheckResult       = 0;
4449    kauth_cred_t      cred                 = NULL;
4450#endif
4451
4452    IORecursiveLockLock(sKextLock);
4453
4454    if (!kextIdentifier) {
4455        result = kOSKextReturnInvalidArgument;
4456        goto finish;
4457    }
4458
4459    OSKext::recordIdentifierRequest(kextIdentifier);
4460
4461    theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4462    if (!theKext) {
4463        if (!allowDeferFlag) {
4464            OSKextLog(/* kext */ NULL,
4465                kOSKextLogErrorLevel |
4466                kOSKextLogLoadFlag,
4467                "Can't load kext %s - not found.",
4468                kextIdentifier->getCStringNoCopy());
4469             goto finish;
4470        }
4471
4472        if (!sKernelRequestsEnabled) {
4473            OSKextLog(theKext,
4474                kOSKextLogErrorLevel |
4475                kOSKextLogLoadFlag,
4476                "Can't load kext %s - requests to user space are disabled.",
4477                kextIdentifier->getCStringNoCopy());
4478            result = kOSKextReturnDisabled;
4479            goto finish;
4480        }
4481
4482       /* Create a new request unless one is already sitting
4483        * in sKernelRequests for this bundle identifier
4484        */
4485        kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
4486        if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
4487            result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
4488                &loadRequest);
4489            if (result != kOSReturnSuccess) {
4490                goto finish;
4491            }
4492            if (!_OSKextSetRequestArgument(loadRequest,
4493                kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
4494
4495                result = kOSKextReturnNoMemory;
4496                goto finish;
4497            }
4498            if (!sKernelRequests->setObject(loadRequest)) {
4499                result = kOSKextReturnNoMemory;
4500                goto finish;
4501            }
4502
4503            if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
4504                result = kOSKextReturnNoMemory;
4505                goto finish;
4506            }
4507
4508            OSKextLog(theKext,
4509                kOSKextLogDebugLevel |
4510                kOSKextLogLoadFlag,
4511                "Kext %s not found; queued load request to user space.",
4512                kextIdentifier->getCStringNoCopy());
4513        }
4514
4515        pingResult = OSKext::pingKextd();
4516        if (pingResult == kOSKextReturnDisabled) {
4517            OSKextLog(/* kext */ NULL,
4518                ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
4519                kOSKextLogLoadFlag,
4520                "Kext %s might not load - kextd is currently unavailable.",
4521                kextIdentifier->getCStringNoCopy());
4522        }
4523
4524        result = kOSKextReturnDeferred;
4525        goto finish;
4526    }
4527
4528#if CONFIG_MACF
4529    if (current_task() != kernel_task) {
4530        cred = kauth_cred_get_with_ref();
4531        macCheckResult = mac_kext_check_load(cred, kextIdentifier->getCStringNoCopy());
4532        kauth_cred_unref(&cred);
4533    }
4534
4535    if (macCheckResult != 0) {
4536        result = kOSReturnError;
4537
4538        OSKextLog(theKext,
4539            kOSKextLogErrorLevel |
4540            kOSKextLogLoadFlag,
4541            "Failed to load kext %s (MAC policy error 0x%x).",
4542            kextIdentifier->getCStringNoCopy(), macCheckResult);
4543
4544        goto finish;
4545    }
4546#endif
4547
4548    result = theKext->load(startOpt, startMatchingOpt, personalityNames);
4549
4550    if (result != kOSReturnSuccess) {
4551        OSKextLog(theKext,
4552            kOSKextLogErrorLevel |
4553            kOSKextLogLoadFlag,
4554            "Failed to load kext %s (error 0x%x).",
4555            kextIdentifier->getCStringNoCopy(), (int)result);
4556
4557        OSKext::removeKext(theKext,
4558            /* terminateService/removePersonalities */ true);
4559        goto finish;
4560    }
4561
4562    if (delayAutounloadFlag) {
4563        OSKextLog(theKext,
4564            kOSKextLogProgressLevel |
4565            kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4566            "Setting delayed autounload for %s.",
4567            kextIdentifier->getCStringNoCopy());
4568        theKext->flags.delayAutounload = 1;
4569    }
4570
4571finish:
4572    OSSafeRelease(loadRequest);
4573    OSSafeRelease(kextIdentifierSymbol);
4574
4575    IORecursiveLockUnlock(sKextLock);
4576
4577    return result;
4578}
4579
4580/*********************************************************************
4581*********************************************************************/
4582/* static */
4583void
4584OSKext::recordIdentifierRequest(
4585    OSString * kextIdentifier)
4586{
4587    const OSSymbol * kextIdentifierSymbol = NULL;  // must release
4588    bool             fail                 = false;
4589
4590    if (!sAllKextLoadIdentifiers || !kextIdentifier) {
4591        goto finish;
4592    }
4593
4594    kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
4595    if (!kextIdentifierSymbol) {
4596        // xxx - this is really a basic alloc failure
4597        fail = true;
4598        goto finish;
4599    }
4600
4601    if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
4602        if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
4603            fail = true;
4604        } else {
4605            // xxx - need to find a way to associate this whole func w/the kext
4606            OSKextLog(/* kext */ NULL,
4607                // xxx - check level
4608                kOSKextLogStepLevel |
4609                kOSKextLogArchiveFlag,
4610                "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4611                kextIdentifier->getCStringNoCopy());
4612        }
4613    }
4614finish:
4615
4616    if (fail) {
4617        OSKextLog(/* kext */ NULL,
4618            kOSKextLogErrorLevel |
4619            kOSKextLogArchiveFlag,
4620            "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4621            kextIdentifier->getCStringNoCopy());
4622    }
4623    OSSafeRelease(kextIdentifierSymbol);
4624    return;
4625}
4626
4627/*********************************************************************
4628*********************************************************************/
4629OSReturn
4630OSKext::load(
4631    OSKextExcludeLevel   startOpt,
4632    OSKextExcludeLevel   startMatchingOpt,
4633    OSArray            * personalityNames)
4634{
4635    OSReturn             result                       = kOSReturnError;
4636    kern_return_t        kxldResult;
4637    OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
4638    OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
4639    unsigned int         i, count;
4640    Boolean              alreadyLoaded                = false;
4641    OSKext             * lastLoadedKext               = NULL;
4642
4643    if (isInExcludeList()) {
4644        OSKextLog(this,
4645                  kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
4646                  kOSKextLogLoadFlag,
4647                  "Kext %s is in exclude list, not loadable",
4648                  getIdentifierCString());
4649
4650        result = kOSKextReturnNotLoadable;
4651        goto finish;
4652    }
4653
4654    if (isLoaded()) {
4655        alreadyLoaded = true;
4656        result = kOSReturnSuccess;
4657
4658        OSKextLog(this,
4659            kOSKextLogDebugLevel |
4660            kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4661            "Kext %s is already loaded.",
4662            getIdentifierCString());
4663        goto loaded;
4664    }
4665
4666    if (!sLoadEnabled) {
4667        OSKextLog(this,
4668            kOSKextLogErrorLevel |
4669            kOSKextLogLoadFlag,
4670            "Kext loading is disabled (attempt to load kext %s).",
4671            getIdentifierCString());
4672        result = kOSKextReturnDisabled;
4673        goto finish;
4674    }
4675
4676   /* If we've pushed the next available load tag to the invalid value,
4677    * we can't load any more kexts.
4678    */
4679    if (sNextLoadTag == kOSKextInvalidLoadTag) {
4680        OSKextLog(this,
4681            kOSKextLogErrorLevel |
4682            kOSKextLogLoadFlag,
4683            "Can't load kext %s - no more load tags to assign.",
4684            getIdentifierCString());
4685        result = kOSKextReturnNoResources;
4686        goto finish;
4687    }
4688
4689   /* This is a bit of a hack, because we shouldn't be handling
4690    * personalities within the load function.
4691    */
4692    if (!declaresExecutable()) {
4693        result = kOSReturnSuccess;
4694        goto loaded;
4695    }
4696
4697   /* Are we in safe boot?
4698    */
4699    if (sSafeBoot && !isLoadableInSafeBoot()) {
4700        OSKextLog(this,
4701            kOSKextLogErrorLevel |
4702            kOSKextLogLoadFlag,
4703            "Can't load kext %s - not loadable during safe boot.",
4704            getIdentifierCString());
4705        result = kOSKextReturnBootLevel;
4706        goto finish;
4707    }
4708
4709    OSKextLog(this,
4710        kOSKextLogProgressLevel | kOSKextLogLoadFlag,
4711        "Loading kext %s.",
4712        getIdentifierCString());
4713
4714
4715    if (!sKxldContext) {
4716        kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
4717            &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
4718            /* cputype */ 0, /* cpusubtype */ 0);
4719        if (kxldResult) {
4720            OSKextLog(this,
4721                kOSKextLogErrorLevel |
4722                kOSKextLogLoadFlag | kOSKextLogLinkFlag,
4723                "Can't load kext %s - failed to create link context.",
4724                getIdentifierCString());
4725            result = kOSKextReturnNoMemory;
4726            goto finish;
4727        }
4728    }
4729
4730    /* We only need to resolve dependencies once for the whole graph, but
4731     * resolveDependencies will just return if there's no work to do, so it's
4732     * safe to call it more than once.
4733     */
4734    if (!resolveDependencies()) {
4735        // xxx - check resolveDependencies() for log msg
4736        OSKextLog(this,
4737            kOSKextLogErrorLevel |
4738            kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4739            "Can't load kext %s - failed to resolve library dependencies.",
4740            getIdentifierCString());
4741        result = kOSKextReturnDependencies;
4742        goto finish;
4743    }
4744
4745   /* If we are excluding just the kext being loaded now (and not its
4746    * dependencies), drop the exclusion level to none so dependencies
4747    * start and/or add their personalities.
4748    */
4749    if (dependenciesStartOpt == kOSKextExcludeKext) {
4750        dependenciesStartOpt = kOSKextExcludeNone;
4751    }
4752
4753    if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
4754        dependenciesStartMatchingOpt = kOSKextExcludeNone;
4755    }
4756
4757   /* Load the dependencies, recursively.
4758    */
4759    count = getNumDependencies();
4760    for (i = 0; i < count; i++) {
4761        OSKext * dependency = OSDynamicCast(OSKext,
4762            dependencies->getObject(i));
4763        if (dependency == NULL) {
4764            OSKextLog(this,
4765                kOSKextLogErrorLevel |
4766                kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4767                "Internal error loading kext %s; dependency disappeared.",
4768                getIdentifierCString());
4769            result = kOSKextReturnInternalError;
4770            goto finish;
4771        }
4772
4773       /* Dependencies must be started accorting to the opt,
4774        * but not given the personality names of the main kext.
4775        */
4776        result = dependency->load(dependenciesStartOpt,
4777            dependenciesStartMatchingOpt,
4778            /* personalityNames */ NULL);
4779        if (result != KERN_SUCCESS) {
4780            OSKextLog(this,
4781                kOSKextLogErrorLevel |
4782                kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4783                "Dependency %s of kext %s failed to load.",
4784                dependency->getIdentifierCString(),
4785                getIdentifierCString());
4786
4787            OSKext::removeKext(dependency,
4788                /* terminateService/removePersonalities */ true);
4789            result = kOSKextReturnDependencyLoadError;
4790
4791            goto finish;
4792        }
4793    }
4794
4795    result = loadExecutable();
4796    if (result != KERN_SUCCESS) {
4797        goto finish;
4798    }
4799
4800    flags.loaded = true;
4801
4802   /* Add the kext to the list of loaded kexts and update the kmod_info
4803    * struct to point to that of the last loaded kext (which is the way
4804    * it's always been done, though I'd rather do them in order now).
4805    */
4806    lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
4807    sLoadedKexts->setObject(this);
4808
4809   /* Keep the kernel itself out of the kmod list.
4810    */
4811    if (lastLoadedKext->isKernel()) {
4812        lastLoadedKext = NULL;
4813    }
4814
4815    if (lastLoadedKext) {
4816        kmod_info->next = lastLoadedKext->kmod_info;
4817    }
4818
4819    notifyKextLoadObservers(this, kmod_info);
4820
4821   /* Make the global kmod list point at the just-loaded kext. Note that the
4822    * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4823    * although we do report it in kextstat these days by using the newer
4824    * OSArray of loaded kexts, which does contain it.
4825    *
4826    * (The OSKext object representing the kernel doesn't even have a kmod_info
4827    * struct, though I suppose we could stick a pointer to it from the
4828    * static struct in OSRuntime.cpp.)
4829    */
4830    kmod = kmod_info;
4831
4832   /* Save the list of loaded kexts in case we panic.
4833    */
4834    OSKext::saveLoadedKextPanicList();
4835
4836    if (isExecutable()) {
4837        OSKext::updateLoadedKextSummaries();
4838        savePanicString(/* isLoading */ true);
4839
4840#if CONFIG_DTRACE
4841        registerWithDTrace();
4842#else
4843        jettisonLinkeditSegment();
4844#endif /* CONFIG_DTRACE */
4845    }
4846
4847loaded:
4848    if (isExecutable() && !flags.started) {
4849        if (startOpt == kOSKextExcludeNone) {
4850            result = start();
4851            if (result != kOSReturnSuccess) {
4852                OSKextLog(this,
4853                    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4854                    "Kext %s start failed (result 0x%x).",
4855                    getIdentifierCString(), result);
4856                result = kOSKextReturnStartStopError;
4857            }
4858        }
4859    }
4860
4861   /* If not excluding matching, send the personalities to the kernel.
4862    * This never affects the result of the load operation.
4863    * This is a bit of a hack, because we shouldn't be handling
4864    * personalities within the load function.
4865    */
4866    if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
4867        result = sendPersonalitiesToCatalog(true, personalityNames);
4868    }
4869
4870finish:
4871
4872   /* More hack! If the kext doesn't declare an executable, even if we
4873    * "loaded" it, we have to remove any personalities naming it, or we'll
4874    * never see the registry go quiet. Errors here do not count for the
4875    * load operation itself.
4876    *
4877    * Note that in every other regard it's perfectly ok for a kext to
4878    * not declare an executable and serve only as a package for personalities
4879    * naming another kext, so we do have to allow such kexts to be "loaded"
4880    * so that those other personalities get added & matched.
4881    */
4882    if (!declaresExecutable()) {
4883        OSKextLog(this,
4884            kOSKextLogStepLevel | kOSKextLogLoadFlag,
4885            "Kext %s has no executable; removing any personalities naming it.",
4886            getIdentifierCString());
4887        removePersonalitiesFromCatalog();
4888    }
4889
4890    if (result != kOSReturnSuccess) {
4891        OSKextLog(this,
4892            kOSKextLogErrorLevel |
4893            kOSKextLogLoadFlag,
4894            "Kext %s failed to load (0x%x).",
4895            getIdentifierCString(), (int)result);
4896    } else if (!alreadyLoaded) {
4897        OSKextLog(this,
4898            kOSKextLogProgressLevel |
4899            kOSKextLogLoadFlag,
4900            "Kext %s loaded.",
4901            getIdentifierCString());
4902
4903        queueKextNotification(kKextRequestPredicateLoadNotification,
4904            OSDynamicCast(OSString, bundleID));
4905    }
4906    return result;
4907}
4908
4909/*********************************************************************
4910*
4911*********************************************************************/
4912static char * strdup(const char * string)
4913{
4914    char * result = NULL;
4915    size_t size;
4916
4917    if (!string) {
4918        goto finish;
4919    }
4920
4921    size = 1 + strlen(string);
4922    result = (char *)kalloc(size);
4923    if (!result) {
4924        goto finish;
4925    }
4926
4927    memcpy(result, string, size);
4928
4929finish:
4930    return result;
4931}
4932
4933/*********************************************************************
4934*
4935*********************************************************************/
4936OSReturn
4937OSKext::slidePrelinkedExecutable()
4938{
4939    OSReturn                   result           = kOSKextReturnBadData;
4940    kernel_mach_header_t     * mh               = NULL;
4941    kernel_segment_command_t * seg              = NULL;
4942    kernel_segment_command_t * linkeditSeg      = NULL;
4943    kernel_section_t         * sec              = NULL;
4944    char                     * linkeditBase     = NULL;
4945    bool                       haveLinkeditBase = false;
4946    char                     * relocBase        = NULL;
4947    bool                       haveRelocBase    = false;
4948    struct dysymtab_command  * dysymtab         = NULL;
4949    struct symtab_command    * symtab           = NULL;
4950    kernel_nlist_t           * sym              = NULL;
4951    struct relocation_info   * reloc            = NULL;
4952    uint32_t                   i                = 0;
4953    int                        reloc_size;
4954    vm_offset_t                new_kextsize;
4955
4956    if (linkedExecutable == NULL || vm_kernel_slide == 0) {
4957        result = kOSReturnSuccess;
4958        goto finish;
4959    }
4960
4961    mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
4962
4963    for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
4964        if (!seg->vmaddr) {
4965            continue;
4966        }
4967        seg->vmaddr += vm_kernel_slide;
4968
4969#if KASLR_KEXT_DEBUG
4970        IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4971              seg->segname,
4972              (unsigned long)VM_KERNEL_UNSLIDE(seg->vmaddr),
4973              (unsigned long)seg->vmaddr);
4974#endif
4975
4976        if (!haveRelocBase) {
4977            relocBase = (char *) seg->vmaddr;
4978            haveRelocBase = true;
4979        }
4980        if (!strcmp(seg->segname, "__LINKEDIT")) {
4981            linkeditBase = (char *) seg->vmaddr - seg->fileoff;
4982            haveLinkeditBase = true;
4983            linkeditSeg = seg;
4984        }
4985        for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
4986            sec->addr += vm_kernel_slide;
4987
4988#if KASLR_KEXT_DEBUG
4989            IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
4990                  sec->sectname,
4991                  (unsigned long)VM_KERNEL_UNSLIDE(sec->addr),
4992                  (unsigned long)sec->addr);
4993#endif
4994        }
4995    }
4996
4997    dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
4998
4999    symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
5000
5001    if (symtab != NULL) {
5002      /* Some pseudo-kexts have symbol tables without segments.
5003       * Ignore them. */
5004        if (symtab->nsyms > 0 && haveLinkeditBase) {
5005            sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
5006            for (i = 0; i < symtab->nsyms; i++) {
5007                if (sym[i].n_type & N_STAB) {
5008                    continue;
5009                }
5010                sym[i].n_value += vm_kernel_slide;
5011
5012#if KASLR_KEXT_DEBUG
5013#define MAX_SYMS_TO_LOG 5
5014                if ( i < MAX_SYMS_TO_LOG ) {
5015                    IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
5016                          (unsigned long)VM_KERNEL_UNSLIDE(sym[i].n_value),
5017                          (unsigned long)sym[i].n_value);
5018                }
5019#endif
5020            }
5021        }
5022    }
5023
5024    if (dysymtab != NULL) {
5025        if (dysymtab->nextrel > 0) {
5026            OSKextLog(this,
5027                kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5028                kOSKextLogLinkFlag,
5029                "Sliding kext %s: External relocations found.",
5030                getIdentifierCString());
5031            goto finish;
5032        }
5033
5034        if (dysymtab->nlocrel > 0) {
5035            if (!haveLinkeditBase) {
5036                OSKextLog(this,
5037                    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5038                    kOSKextLogLinkFlag,
5039                    "Sliding kext %s: No linkedit segment.",
5040                    getIdentifierCString());
5041                goto finish;
5042            }
5043
5044            if (!haveRelocBase) {
5045                OSKextLog(this,
5046                    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5047                    kOSKextLogLinkFlag,
5048#if __x86_64__
5049                    "Sliding kext %s: No writable segments.",
5050#else
5051                    "Sliding kext %s: No segments.",
5052#endif
5053                    getIdentifierCString());
5054                goto finish;
5055            }
5056
5057            reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
5058            reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
5059
5060            for (i = 0; i < dysymtab->nlocrel; i++) {
5061                if (   reloc[i].r_extern != 0
5062                    || reloc[i].r_type != 0
5063                    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
5064                    ) {
5065                    OSKextLog(this,
5066                        kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5067                        kOSKextLogLinkFlag,
5068                        "Sliding kext %s: Unexpected relocation found.",
5069                        getIdentifierCString());
5070                    goto finish;
5071                }
5072                if (reloc[i].r_pcrel != 0) {
5073                    continue;
5074                }
5075                *((uintptr_t *)(relocBase + reloc[i].r_address)) += vm_kernel_slide;
5076
5077#if KASLR_KEXT_DEBUG
5078#define MAX_DYSYMS_TO_LOG 5
5079                if ( i < MAX_DYSYMS_TO_LOG ) {
5080                    IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
5081                          (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase + reloc[i].r_address))),
5082                          (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
5083                }
5084#endif
5085            }
5086
5087            /* We should free these relocations, not just delete the reference to them.
5088             * <rdar://problem/10535549> Free relocations from PIE kexts.
5089             */
5090            new_kextsize = round_page(kmod_info->size - reloc_size);
5091
5092            if ((kmod_info->size - new_kextsize) > PAGE_SIZE) {
5093                vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
5094                vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
5095                vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
5096                int             bytes_remaining = endofkext - endofrelocInfo;
5097                OSData *        new_osdata = NULL;
5098
5099                /* fix up symbol offsets if they are after the dsymtab local relocs */
5100                if (symtab) {
5101                    if (dysymtab->locreloff < symtab->symoff){
5102                        symtab->symoff -= reloc_size;
5103                    }
5104                    if (dysymtab->locreloff < symtab->stroff) {
5105                        symtab->stroff -= reloc_size;
5106                    }
5107                }
5108                if (dysymtab->locreloff < dysymtab->extreloff) {
5109                    dysymtab->extreloff -= reloc_size;
5110                }
5111
5112                /* move data behind reloc info down to new offset */
5113                if (endofrelocInfo < endofkext) {
5114                   memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
5115                }
5116
5117                /* Create a new OSData for the smaller kext object and reflect
5118                 * new linkedit segment size.
5119                 */
5120                linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
5121                linkeditSeg->filesize = linkeditSeg->vmsize;
5122
5123                new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, new_kextsize);
5124                if (new_osdata) {
5125                    /* Fix up kmod info and linkedExecutable.
5126                     */
5127                    kmod_info->size = new_kextsize;
5128#if VM_MAPPED_KEXTS
5129                    new_osdata->setDeallocFunction(osdata_kext_free);
5130#else
5131                    new_osdata->setDeallocFunction(osdata_phys_free);
5132#endif
5133                    linkedExecutable->setDeallocFunction(NULL);
5134                    linkedExecutable->release();
5135                    linkedExecutable = new_osdata;
5136
5137#if VM_MAPPED_KEXTS
5138                    kext_free(new_endofkext, (endofkext - new_endofkext));
5139#else
5140                    ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
5141#endif
5142                }
5143            }
5144            dysymtab->nlocrel = 0;
5145            dysymtab->locreloff = 0;
5146        }
5147    }
5148
5149    result = kOSReturnSuccess;
5150finish:
5151    return result;
5152}
5153
5154/*********************************************************************
5155* called only by load()
5156*********************************************************************/
5157OSReturn
5158OSKext::loadExecutable()
5159{
5160    OSReturn              result             = kOSReturnError;
5161    kern_return_t         kxldResult;
5162    KXLDDependency     *  kxlddeps           = NULL;  // must kfree
5163    uint32_t              num_kxlddeps       = 0;
5164    OSArray            *  linkDependencies   = NULL;  // must release
5165    uint32_t              numDirectDependencies   = 0;
5166    uint32_t              num_kmod_refs      = 0;
5167    struct mach_header ** kxldHeaderPtr      = NULL;  // do not free
5168    struct mach_header  * kxld_header        = NULL;  // xxx - need to free here?
5169    OSData              * theExecutable      = NULL;  // do not release
5170    OSString            * versString         = NULL;  // do not release
5171    const char          * versCString        = NULL;  // do not free
5172    const char          * string             = NULL;  // do not free
5173    unsigned int          i;
5174
5175   /* We need the version string for a variety of bits below.
5176    */
5177    versString = OSDynamicCast(OSString,
5178        getPropertyForHostArch(kCFBundleVersionKey));
5179    if (!versString) {
5180        goto finish;
5181    }
5182    versCString = versString->getCStringNoCopy();
5183
5184    if (isKernelComponent()) {
5185       if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
5186
5187           if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
5188                OSKextLog(this,
5189                    kOSKextLogErrorLevel |
5190                    kOSKextLogLoadFlag,
5191                    "Kernel component %s has incorrect version %s; "
5192                    "expected %s.",
5193                    getIdentifierCString(),
5194                    versCString, KERNEL6_VERSION);
5195               result = kOSKextReturnInternalError;
5196               goto finish;
5197           } else if (strcmp(versCString, osrelease)) {
5198                OSKextLog(this,
5199                    kOSKextLogErrorLevel |
5200                    kOSKextLogLoadFlag,
5201                    "Kernel component %s has incorrect version %s; "
5202                    "expected %s.",
5203                    getIdentifierCString(),
5204                    versCString, osrelease);
5205               result = kOSKextReturnInternalError;
5206               goto finish;
5207           }
5208       }
5209    }
5210
5211    if (isPrelinked()) {
5212        result = slidePrelinkedExecutable();
5213        if (result != kOSReturnSuccess) {
5214            goto finish;
5215        }
5216        goto register_kmod;
5217    }
5218
5219    theExecutable = getExecutable();
5220    if (!theExecutable) {
5221        if (declaresExecutable()) {
5222            OSKextLog(this,
5223                kOSKextLogErrorLevel |
5224                kOSKextLogLoadFlag,
5225                "Can't load kext %s - executable is missing.",
5226                getIdentifierCString());
5227            result = kOSKextReturnValidation;
5228            goto finish;
5229        }
5230        goto register_kmod;
5231    }
5232
5233    if (isInterface()) {
5234        OSData *executableCopy = OSData::withData(theExecutable);
5235        setLinkedExecutable(executableCopy);
5236        executableCopy->release();
5237        goto register_kmod;
5238    }
5239
5240    numDirectDependencies = getNumDependencies();
5241
5242    if (flags.hasBleedthrough) {
5243        linkDependencies = dependencies;
5244        linkDependencies->retain();
5245    } else {
5246        linkDependencies = OSArray::withArray(dependencies);
5247        if (!linkDependencies) {
5248            OSKextLog(this,
5249                kOSKextLogErrorLevel |
5250                kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5251                "Can't allocate link dependencies to load kext %s.",
5252                getIdentifierCString());
5253            goto finish;
5254        }
5255
5256        for (i = 0; i < numDirectDependencies; ++i) {
5257            OSKext * dependencyKext = OSDynamicCast(OSKext,
5258                dependencies->getObject(i));
5259            dependencyKext->addBleedthroughDependencies(linkDependencies);
5260        }
5261    }
5262
5263    num_kxlddeps = linkDependencies->getCount();
5264    if (!num_kxlddeps) {
5265        OSKextLog(this,
5266            kOSKextLogErrorLevel |
5267            kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5268            "Can't load kext %s - it has no library dependencies.",
5269            getIdentifierCString());
5270        goto finish;
5271    }
5272
5273    kxlddeps = (KXLDDependency *)kalloc(num_kxlddeps * sizeof(*kxlddeps));
5274    if (!kxlddeps) {
5275        OSKextLog(this,
5276            kOSKextLogErrorLevel |
5277            kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5278            "Can't allocate link context to load kext %s.",
5279            getIdentifierCString());
5280        goto finish;
5281    }
5282    bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
5283
5284    for (i = 0; i < num_kxlddeps; ++i ) {
5285        OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
5286
5287        if (dependency->isInterface()) {
5288            OSKext *interfaceTargetKext = NULL;
5289            OSData * interfaceTarget = NULL;
5290
5291            if (dependency->isKernelComponent()) {
5292                interfaceTargetKext = sKernelKext;
5293                interfaceTarget = sKernelKext->linkedExecutable;
5294            } else {
5295                interfaceTargetKext = OSDynamicCast(OSKext,
5296                    dependency->dependencies->getObject(0));
5297
5298                interfaceTarget = interfaceTargetKext->linkedExecutable;
5299            }
5300
5301            if (!interfaceTarget) {
5302                // panic?
5303                goto finish;
5304            }
5305
5306           /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5307            * it will be useful to have them in the debugger.
5308            * strdup() failing isn't critical right here so we don't check that.
5309            */
5310            kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
5311            kxlddeps[i].kext_size = interfaceTarget->getLength();
5312            kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
5313
5314            kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
5315            kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
5316            kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
5317        } else {
5318            kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
5319            kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
5320            kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
5321        }
5322
5323        kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
5324    }
5325
5326    kxldHeaderPtr = &kxld_header;
5327
5328#if DEBUG
5329    OSKextLog(this,
5330        kOSKextLogExplicitLevel |
5331        kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5332        "Kext %s - calling kxld_link_file:\n"
5333        "    kxld_context: %p\n"
5334        "    executable: %p    executable_length: %d\n"
5335        "    user_data: %p\n"
5336        "    kxld_dependencies: %p    num_dependencies: %d\n"
5337        "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
5338        getIdentifierCString(), sKxldContext,
5339        theExecutable->getBytesNoCopy(), theExecutable->getLength(),
5340        this, kxlddeps, num_kxlddeps,
5341        kxldHeaderPtr, &kmod_info);
5342#endif
5343
5344   /* After this call, the linkedExecutable instance variable
5345    * should exist.
5346    */
5347    kxldResult = kxld_link_file(sKxldContext,
5348        (u_char *)theExecutable->getBytesNoCopy(),
5349        theExecutable->getLength(),
5350        getIdentifierCString(), this, kxlddeps, num_kxlddeps,
5351        (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
5352
5353    if (kxldResult != KERN_SUCCESS) {
5354        // xxx - add kxldResult here?
5355        OSKextLog(this,
5356            kOSKextLogErrorLevel |
5357            kOSKextLogLoadFlag,
5358            "Can't load kext %s - link failed.",
5359            getIdentifierCString());
5360        result = kOSKextReturnLinkError;
5361        goto finish;
5362    }
5363
5364   /* We've written data & instructions into kernel memory, so flush the data
5365    * cache and invalidate the instruction cache.
5366    * I/D caches are coherent on x86
5367    */
5368#if !defined(__i386__) && !defined(__x86_64__)
5369    flush_dcache(kmod_info->address, kmod_info->size, false);
5370    invalidate_icache(kmod_info->address, kmod_info->size, false);
5371#endif
5372register_kmod:
5373
5374    if (isInterface()) {
5375
5376       /* Whip up a fake kmod_info entry for the interface kext.
5377        */
5378        kmod_info = (kmod_info_t *)kalloc(sizeof(kmod_info_t));
5379        if (!kmod_info) {
5380            result = KERN_MEMORY_ERROR;
5381            goto finish;
5382        }
5383
5384       /* A pseudokext has almost nothing in its kmod_info struct.
5385        */
5386        bzero(kmod_info, sizeof(kmod_info_t));
5387
5388        kmod_info->info_version = KMOD_INFO_VERSION;
5389
5390       /* An interface kext doesn't have a linkedExecutable, so save a
5391        * copy of the UUID out of the original executable via copyUUID()
5392        * while we still have the original executable.
5393        */
5394        interfaceUUID = copyUUID();
5395    }
5396
5397    kmod_info->id = loadTag = sNextLoadTag++;
5398    kmod_info->reference_count = 0;  // KMOD_DECL... sets it to -1 (invalid).
5399
5400   /* Stamp the bundle ID and version from the OSKext over anything
5401    * resident inside the kmod_info.
5402    */
5403    string = getIdentifierCString();
5404    strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
5405
5406    string = versCString;
5407    strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
5408
5409   /* Add the dependencies' kmod_info structs as kmod_references.
5410    */
5411    num_kmod_refs = getNumDependencies();
5412    if (num_kmod_refs) {
5413        kmod_info->reference_list = (kmod_reference_t *)kalloc(
5414            num_kmod_refs * sizeof(kmod_reference_t));
5415        if (!kmod_info->reference_list) {
5416            result = KERN_MEMORY_ERROR;
5417            goto finish;
5418        }
5419        bzero(kmod_info->reference_list,
5420            num_kmod_refs * sizeof(kmod_reference_t));
5421        for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
5422            kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
5423            OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
5424            ref->info = refKext->kmod_info;
5425            ref->info->reference_count++;
5426
5427            if (refIndex + 1 < num_kmod_refs) {
5428                ref->next = kmod_info->reference_list + refIndex + 1;
5429            }
5430        }
5431    }
5432
5433    if (!isInterface() && linkedExecutable) {
5434        OSKextLog(this,
5435            kOSKextLogProgressLevel |
5436            kOSKextLogLoadFlag,
5437            "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5438            kmod_info->name,
5439            (unsigned)kmod_info->size / PAGE_SIZE,
5440            (unsigned long)VM_KERNEL_UNSLIDE(kmod_info->address),
5441            (unsigned)kmod_info->id);
5442    }
5443
5444    result = setVMProtections();
5445    if (result != KERN_SUCCESS) {
5446        goto finish;
5447    }
5448
5449    result = kOSReturnSuccess;
5450
5451finish:
5452    OSSafeRelease(linkDependencies);
5453
5454   /* Clear up locally allocated dependency info.
5455    */
5456    for (i = 0; i < num_kxlddeps; ++i ) {
5457        size_t size;
5458
5459        if (kxlddeps[i].kext_name) {
5460            size = 1 + strlen(kxlddeps[i].kext_name);
5461            kfree(kxlddeps[i].kext_name, size);
5462        }
5463        if (kxlddeps[i].interface_name) {
5464            size = 1 + strlen(kxlddeps[i].interface_name);
5465            kfree(kxlddeps[i].interface_name, size);
5466        }
5467    }
5468    if (kxlddeps) kfree(kxlddeps, (num_kxlddeps * sizeof(*kxlddeps)));
5469
5470   /* We no longer need the unrelocated executable (which the linker
5471    * has altered anyhow).
5472    */
5473    setExecutable(NULL);
5474
5475    if (result != kOSReturnSuccess) {
5476        OSKextLog(this,
5477            kOSKextLogErrorLevel |
5478            kOSKextLogLoadFlag,
5479            "Failed to load executable for kext %s.",
5480            getIdentifierCString());
5481
5482        if (kmod_info && kmod_info->reference_list) {
5483            kfree(kmod_info->reference_list,
5484                num_kmod_refs * sizeof(kmod_reference_t));
5485        }
5486        if (isInterface()) {
5487            kfree(kmod_info, sizeof(kmod_info_t));
5488        }
5489        kmod_info = NULL;
5490        if (linkedExecutable) {
5491            linkedExecutable->release();
5492            linkedExecutable = NULL;
5493        }
5494    }
5495
5496    return result;
5497}
5498
5499/*********************************************************************
5500* The linkedit segment is used by the kext linker for dependency
5501* resolution, and by dtrace for probe initialization. We can free it
5502* for non-library kexts, since no kexts depend on non-library kexts
5503* by definition, once dtrace has been initialized.
5504*********************************************************************/
5505void
5506OSKext::jettisonLinkeditSegment(void)
5507{
5508    kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
5509    kernel_segment_command_t * linkedit = NULL;
5510    vm_offset_t                start;
5511    vm_size_t                  linkeditsize, kextsize;
5512    OSData                   * data = NULL;
5513
5514#if NO_KEXTD
5515	/* We can free symbol tables for all embedded kexts because we don't
5516	 * support runtime kext linking.
5517	 */
5518    if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
5519#else
5520    if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
5521#endif
5522        goto finish;
5523    }
5524
5525   /* Find the linkedit segment.  If it's not the last segment, then freeing
5526    * it will fragment the kext into multiple VM regions, which OSKext is not
5527    * designed to handle, so we'll have to skip it.
5528    */
5529    linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
5530    if (!linkedit) {
5531        goto finish;
5532    }
5533
5534    if (round_page(kmod_info->address + kmod_info->size) !=
5535        round_page(linkedit->vmaddr + linkedit->vmsize))
5536    {
5537        goto finish;
5538    }
5539
5540   /* Create a new OSData for the smaller kext object.
5541    */
5542    linkeditsize = round_page(linkedit->vmsize);
5543    kextsize = kmod_info->size - linkeditsize;
5544    start = linkedit->vmaddr;
5545
5546    data = OSData::withBytesNoCopy((void *)kmod_info->address, kextsize);
5547    if (!data) {
5548        goto finish;
5549    }
5550
5551   /* Fix the kmod info and linkedExecutable.
5552    */
5553    kmod_info->size = kextsize;
5554
5555#if VM_MAPPED_KEXTS
5556    data->setDeallocFunction(osdata_kext_free);
5557#else
5558    data->setDeallocFunction(osdata_phys_free);
5559#endif
5560    linkedExecutable->setDeallocFunction(NULL);
5561    linkedExecutable->release();
5562    linkedExecutable = data;
5563    flags.jettisonLinkeditSeg = 1;
5564
5565   /* Free the linkedit segment.
5566    */
5567#if VM_MAPPED_KEXTS
5568    kext_free(start, linkeditsize);
5569#else
5570    ml_static_mfree(start, linkeditsize);
5571#endif
5572
5573finish:
5574    return;
5575}
5576
5577/*********************************************************************
5578*********************************************************************/
5579void
5580OSKext::setLinkedExecutable(OSData * anExecutable)
5581{
5582    if (linkedExecutable) {
5583        panic("Attempt to set linked executable on kext "
5584            "that already has one (%s).\n",
5585            getIdentifierCString());
5586    }
5587    linkedExecutable = anExecutable;
5588    linkedExecutable->retain();
5589    return;
5590}
5591
5592#if CONFIG_DTRACE
5593/*********************************************************************
5594* Go through all loaded kexts and tell them to register with dtrace.
5595* The instance method only registers if necessary.
5596*********************************************************************/
5597/* static */
5598void
5599OSKext::registerKextsWithDTrace(void)
5600{
5601    uint32_t count = sLoadedKexts->getCount();
5602    uint32_t i;
5603
5604    IORecursiveLockLock(sKextLock);
5605
5606    for (i = 0; i < count; i++) {
5607        OSKext   * thisKext     = NULL;  // do not release
5608
5609        thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
5610        if (!thisKext || !thisKext->isExecutable()) {
5611            continue;
5612        }
5613
5614        thisKext->registerWithDTrace();
5615    }
5616
5617    IORecursiveLockUnlock(sKextLock);
5618
5619    return;
5620}
5621
5622extern "C" {
5623    extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
5624    extern int (*dtrace_modunload)(struct kmod_info *);
5625};
5626
5627/*********************************************************************
5628*********************************************************************/
5629void
5630OSKext::registerWithDTrace(void)
5631{
5632   /* Register kext with dtrace. A dtrace_modload failure should not
5633    * prevent a kext from loading, so we ignore the return code.
5634    */
5635    if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
5636        uint32_t modflag = 0;
5637        OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
5638        if (forceInit == kOSBooleanTrue) {
5639            modflag |= KMOD_DTRACE_FORCE_INIT;
5640        }
5641
5642        (void)(*dtrace_modload)(kmod_info, modflag);
5643        flags.dtraceInitialized = true;
5644        jettisonLinkeditSegment();
5645    }
5646    return;
5647}
5648/*********************************************************************
5649*********************************************************************/
5650void
5651OSKext::unregisterWithDTrace(void)
5652{
5653   /* Unregister kext with dtrace. A dtrace_modunload failure should not
5654    * prevent a kext from loading, so we ignore the return code.
5655    */
5656    if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
5657        (void)(*dtrace_modunload)(kmod_info);
5658        flags.dtraceInitialized = false;
5659    }
5660    return;
5661}
5662#endif /* CONFIG_DTRACE */
5663
5664
5665/*********************************************************************
5666* called only by loadExecutable()
5667*********************************************************************/
5668#if !VM_MAPPED_KEXTS
5669#error Unrecognized architecture
5670#else
5671static inline kern_return_t
5672OSKext_protect(
5673    vm_map_t   map,
5674    vm_map_offset_t    start,
5675    vm_map_offset_t    end,
5676    vm_prot_t  new_prot,
5677    boolean_t  set_max)
5678{
5679    if (start == end) { // 10538581
5680        return(KERN_SUCCESS);
5681    }
5682    return vm_map_protect(map, start, end, new_prot, set_max);
5683}
5684
5685static inline kern_return_t
5686OSKext_wire(
5687    vm_map_t   map,
5688    vm_map_offset_t    start,
5689    vm_map_offset_t    end,
5690    vm_prot_t  access_type,
5691    boolean_t       user_wire)
5692{
5693	return vm_map_wire(map, start, end, access_type, user_wire);
5694}
5695#endif
5696
5697OSReturn
5698OSKext::setVMProtections(void)
5699{
5700    vm_map_t                    kext_map        = NULL;
5701    kernel_segment_command_t  * seg             = NULL;
5702    vm_map_offset_t             start           = 0;
5703    vm_map_offset_t             end             = 0;
5704    OSReturn                    result          = kOSReturnError;
5705
5706    if (!kmod_info->address && !kmod_info->size) {
5707        result = kOSReturnSuccess;
5708        goto finish;
5709    }
5710
5711    /* Get the kext's vm map */
5712    kext_map = kext_get_vm_map(kmod_info);
5713    if (!kext_map) {
5714        result = KERN_MEMORY_ERROR;
5715        goto finish;
5716    }
5717
5718    /* Protect the headers as read-only; they do not need to be wired */
5719    result = OSKext_protect(kext_map, kmod_info->address,
5720        kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE);
5721    if (result != KERN_SUCCESS) {
5722        goto finish;
5723    }
5724
5725    /* Set the VM protections and wire down each of the segments */
5726    seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
5727    while (seg) {
5728        start = round_page(seg->vmaddr);
5729        end = trunc_page(seg->vmaddr + seg->vmsize);
5730
5731        result = OSKext_protect(kext_map, start, end, seg->maxprot, TRUE);
5732        if (result != KERN_SUCCESS) {
5733            OSKextLog(this,
5734                kOSKextLogErrorLevel |
5735                kOSKextLogLoadFlag,
5736                "Kext %s failed to set maximum VM protections "
5737                "for segment %s - 0x%x.",
5738                getIdentifierCString(), seg->segname, (int)result);
5739            goto finish;
5740        }
5741
5742        result = OSKext_protect(kext_map, start, end, seg->initprot, FALSE);
5743        if (result != KERN_SUCCESS) {
5744            OSKextLog(this,
5745                kOSKextLogErrorLevel |
5746                kOSKextLogLoadFlag,
5747                "Kext %s failed to set initial VM protections "
5748                "for segment %s - 0x%x.",
5749                getIdentifierCString(), seg->segname, (int)result);
5750            goto finish;
5751        }
5752
5753        if (segmentShouldBeWired(seg)) {
5754            result = OSKext_wire(kext_map, start, end, seg->initprot, FALSE);
5755            if (result != KERN_SUCCESS) {
5756                goto finish;
5757            }
5758        }
5759
5760        seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
5761    }
5762
5763finish:
5764    return result;
5765}
5766
5767/*********************************************************************
5768*********************************************************************/
5769boolean_t
5770OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
5771{
5772    return (sKeepSymbols || strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)));
5773}
5774
5775/*********************************************************************
5776*********************************************************************/
5777OSReturn
5778OSKext::validateKextMapping(bool startFlag)
5779{
5780    OSReturn                              result      = kOSReturnError;
5781    const char                          * whichOp = startFlag ? "start" : "stop";
5782    kern_return_t                         kern_result = 0;
5783    vm_map_t                              kext_map    = NULL;
5784    kernel_segment_command_t            * seg         = NULL;
5785    mach_vm_address_t                     address     = 0;
5786    mach_vm_size_t                        size        = 0;
5787    uint32_t                              depth       = 0;
5788    mach_msg_type_number_t                count;
5789    vm_region_submap_short_info_data_64_t info;
5790
5791    count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
5792    bzero(&info, sizeof(info));
5793
5794   // xxx - do we need a distinct OSReturn value for these or is "bad data"
5795   // xxx - sufficient?
5796
5797   /* Verify that the kmod_info and start/stop pointers are non-NULL.
5798    */
5799    if (!kmod_info) {
5800        OSKextLog(this,
5801            kOSKextLogErrorLevel |
5802            kOSKextLogLoadFlag,
5803            "Kext %s - NULL kmod_info pointer.",
5804            getIdentifierCString());
5805        result = kOSKextReturnBadData;
5806        goto finish;
5807    }
5808
5809    if (startFlag) {
5810        address = (mach_vm_address_t)kmod_info->start;
5811    } else {
5812        address = (mach_vm_address_t)kmod_info->stop;
5813    }
5814
5815    if (!address) {
5816        OSKextLog(this,
5817            kOSKextLogErrorLevel |
5818            kOSKextLogLoadFlag,
5819            "Kext %s - NULL module %s pointer.",
5820            getIdentifierCString(), whichOp);
5821        result = kOSKextReturnBadData;
5822        goto finish;
5823    }
5824
5825    kext_map = kext_get_vm_map(kmod_info);
5826    depth = (kernel_map == kext_map) ? 1 : 2;
5827
5828   /* Verify that the start/stop function lies within the kext's address range.
5829    */
5830    if (address < kmod_info->address + kmod_info->hdr_size ||
5831        kmod_info->address + kmod_info->size <= address)
5832    {
5833        OSKextLog(this,
5834            kOSKextLogErrorLevel |
5835            kOSKextLogLoadFlag,
5836            "Kext %s module %s pointer is outside of kext range "
5837            "(%s %p - kext at %p-%p)..",
5838            getIdentifierCString(),
5839            whichOp,
5840            whichOp,
5841            (void *)VM_KERNEL_UNSLIDE(address),
5842            (void *)VM_KERNEL_UNSLIDE(kmod_info->address),
5843            (void *)(VM_KERNEL_UNSLIDE(kmod_info->address) + kmod_info->size));
5844        result = kOSKextReturnBadData;
5845        goto finish;
5846    }
5847
5848   /* Only do these checks before calling the start function;
5849    * If anything goes wrong with the mapping while the kext is running,
5850    * we'll likely have panicked well before any attempt to stop the kext.
5851    */
5852    if (startFlag) {
5853
5854       /* Verify that the start/stop function is executable.
5855        */
5856        kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
5857            (vm_region_recurse_info_t)&info, &count);
5858        if (kern_result != KERN_SUCCESS) {
5859            OSKextLog(this,
5860                kOSKextLogErrorLevel |
5861                kOSKextLogLoadFlag,
5862                "Kext %s - bad %s pointer %p.",
5863                getIdentifierCString(),
5864                whichOp, (void *)VM_KERNEL_UNSLIDE(address));
5865            result = kOSKextReturnBadData;
5866            goto finish;
5867        }
5868
5869#if VM_MAPPED_KEXTS
5870        if (!(info.protection & VM_PROT_EXECUTE)) {
5871            OSKextLog(this,
5872                kOSKextLogErrorLevel |
5873                kOSKextLogLoadFlag,
5874                "Kext %s - memory region containing module %s function "
5875                "is not executable.",
5876                getIdentifierCString(), whichOp);
5877            result = kOSKextReturnBadData;
5878            goto finish;
5879        }
5880#endif
5881
5882       /* Verify that the kext's segments are backed by physical memory.
5883        */
5884        seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
5885        while (seg) {
5886            if (!verifySegmentMapping(seg)) {
5887                result = kOSKextReturnBadData;
5888                goto finish;
5889            }
5890
5891            seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
5892        }
5893
5894    }
5895
5896    result = kOSReturnSuccess;
5897finish:
5898    return result;
5899}
5900
5901/*********************************************************************
5902*********************************************************************/
5903boolean_t
5904OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
5905{
5906    mach_vm_address_t address = 0;
5907
5908    if (!segmentShouldBeWired(seg)) return true;
5909
5910    for (address = seg->vmaddr;
5911         address < round_page(seg->vmaddr + seg->vmsize);
5912         address += PAGE_SIZE)
5913    {
5914        if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
5915            OSKextLog(this,
5916                kOSKextLogErrorLevel |
5917                kOSKextLogLoadFlag,
5918                "Kext %s - page %p is not backed by physical memory.",
5919                getIdentifierCString(),
5920                (void *)address);
5921            return false;
5922        }
5923    }
5924
5925    return true;
5926}
5927
5928/*********************************************************************
5929*********************************************************************/
5930OSReturn
5931OSKext::start(bool startDependenciesFlag)
5932{
5933    OSReturn                            result = kOSReturnError;
5934    kern_return_t                       (* startfunc)(kmod_info_t *, void *);
5935    unsigned int                        i, count;
5936    void                              * kmodStartData = NULL;
5937
5938    if (isStarted() || isInterface() || isKernelComponent()) {
5939        result = kOSReturnSuccess;
5940        goto finish;
5941    }
5942
5943    if (!isLoaded()) {
5944        OSKextLog(this,
5945            kOSKextLogErrorLevel |
5946            kOSKextLogLoadFlag,
5947            "Attempt to start nonloaded kext %s.",
5948            getIdentifierCString());
5949        result = kOSKextReturnInvalidArgument;
5950        goto finish;
5951    }
5952
5953    if (!sLoadEnabled) {
5954        OSKextLog(this,
5955            kOSKextLogErrorLevel |
5956            kOSKextLogLoadFlag,
5957            "Kext loading is disabled (attempt to start kext %s).",
5958            getIdentifierCString());
5959        result = kOSKextReturnDisabled;
5960        goto finish;
5961    }
5962
5963    result = validateKextMapping(/* start? */ true);
5964    if (result != kOSReturnSuccess) {
5965        goto finish;
5966    }
5967
5968    startfunc = kmod_info->start;
5969
5970    count = getNumDependencies();
5971    for (i = 0; i < count; i++) {
5972        OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
5973        if (dependency == NULL) {
5974            OSKextLog(this,
5975                kOSKextLogErrorLevel |
5976                kOSKextLogLoadFlag,
5977                "Kext %s start - internal error, dependency disappeared.",
5978                getIdentifierCString());
5979            goto finish;
5980        }
5981        if (!dependency->isStarted()) {
5982            if (startDependenciesFlag) {
5983                OSReturn dependencyResult =
5984                    dependency->start(startDependenciesFlag);
5985                if (dependencyResult != KERN_SUCCESS) {
5986                    OSKextLog(this,
5987                        kOSKextLogErrorLevel |
5988                        kOSKextLogLoadFlag,
5989                        "Kext %s start - dependency %s failed to start (error 0x%x).",
5990                        getIdentifierCString(),
5991                        dependency->getIdentifierCString(),
5992                        dependencyResult);
5993                    goto finish;
5994                }
5995            } else {
5996                OSKextLog(this,
5997                    kOSKextLogErrorLevel |
5998                    kOSKextLogLoadFlag,
5999                    "Not starting %s - dependency %s not started yet.",
6000                    getIdentifierCString(),
6001                    dependency->getIdentifierCString());
6002                result = kOSKextReturnStartStopError;  // xxx - make new return?
6003                goto finish;
6004            }
6005        }
6006    }
6007
6008    OSKextLog(this,
6009        kOSKextLogDetailLevel |
6010        kOSKextLogLoadFlag,
6011        "Kext %s calling module start function.",
6012        getIdentifierCString());
6013
6014    flags.starting = 1;
6015
6016#if !CONFIG_STATIC_CPPINIT
6017    result = OSRuntimeInitializeCPP(kmod_info, NULL);
6018    if (result == KERN_SUCCESS) {
6019#endif
6020
6021#if CONFIG_KEC_FIPS
6022        kmodStartData = GetAppleTEXTHashForKext(this, this->infoDict);
6023
6024#if 0
6025        if (kmodStartData) {
6026            OSKextLog(this,
6027                      kOSKextLogErrorLevel |
6028                      kOSKextLogGeneralFlag,
6029                      "Kext %s calling module start function. kmodStartData %p. arch %s",
6030                      getIdentifierCString(), kmodStartData, ARCHNAME);
6031        }
6032#endif
6033#endif // CONFIG_KEC_FIPS
6034
6035        result = startfunc(kmod_info, kmodStartData);
6036
6037#if !CONFIG_STATIC_CPPINIT
6038        if (result != KERN_SUCCESS) {
6039            (void) OSRuntimeFinalizeCPP(kmod_info, NULL);
6040        }
6041    }
6042#endif
6043
6044    flags.starting = 0;
6045
6046   /* On success overlap the setting of started/starting. On failure just
6047    * clear starting.
6048    */
6049    if (result == KERN_SUCCESS) {
6050        flags.started = 1;
6051
6052        // xxx - log start error from kernel?
6053        OSKextLog(this,
6054            kOSKextLogProgressLevel |
6055            kOSKextLogLoadFlag,
6056            "Kext %s is now started.",
6057            getIdentifierCString());
6058    } else {
6059        invokeOrCancelRequestCallbacks(
6060            /* result not actually used */ kOSKextReturnStartStopError,
6061            /* invokeFlag */ false);
6062        OSKextLog(this,
6063            kOSKextLogProgressLevel |
6064            kOSKextLogLoadFlag,
6065            "Kext %s did not start (return code 0x%x).",
6066            getIdentifierCString(), result);
6067    }
6068
6069finish:
6070    return result;
6071}
6072
6073/*********************************************************************
6074*********************************************************************/
6075/* static */
6076bool OSKext::canUnloadKextWithIdentifier(
6077    OSString * kextIdentifier,
6078    bool       checkClassesFlag)
6079{
6080    bool     result = false;
6081    OSKext * aKext  = NULL;  // do not release
6082
6083    IORecursiveLockLock(sKextLock);
6084
6085    aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
6086
6087    if (!aKext) {
6088        goto finish;  // can't unload what's not loaded
6089    }
6090
6091    if (aKext->isLoaded()) {
6092        if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
6093            goto finish;
6094        }
6095        if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
6096            goto finish;
6097        }
6098    }
6099
6100    result = true;
6101
6102finish:
6103    IORecursiveLockUnlock(sKextLock);
6104    return result;
6105}
6106
6107/*********************************************************************
6108*********************************************************************/
6109OSReturn
6110OSKext::stop(void)
6111{
6112    OSReturn result = kOSReturnError;
6113    kern_return_t (*stopfunc)(kmod_info_t *, void *);
6114
6115    if (!isStarted() || isInterface()) {
6116        result = kOSReturnSuccess;
6117        goto finish;
6118    }
6119
6120    if (!isLoaded()) {
6121        OSKextLog(this,
6122            kOSKextLogErrorLevel |
6123            kOSKextLogLoadFlag,
6124            "Attempt to stop nonloaded kext %s.",
6125            getIdentifierCString());
6126        result = kOSKextReturnInvalidArgument;
6127        goto finish;
6128    }
6129
6130   /* Refuse to stop if we have clients or instances. It is up to
6131    * the caller to make sure those aren't true.
6132    */
6133    if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6134        OSKextLog(this,
6135            kOSKextLogErrorLevel |
6136            kOSKextLogLoadFlag,
6137            "Kext %s - C++ instances; can't stop.",
6138            getIdentifierCString());
6139        result = kOSKextReturnInUse;
6140        goto finish;
6141    }
6142
6143    if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6144
6145        OSKextLog(this,
6146            kOSKextLogErrorLevel |
6147            kOSKextLogLoadFlag,
6148            "Kext %s - has references (linkage or tracking object); "
6149            "can't stop.",
6150            getIdentifierCString());
6151        result = kOSKextReturnInUse;
6152        goto finish;
6153    }
6154
6155   /* Note: If validateKextMapping fails on the stop & unload path,
6156    * we are in serious trouble and a kernel panic is likely whether
6157    * we stop & unload the kext or not.
6158    */
6159    result = validateKextMapping(/* start? */ false);
6160    if (result != kOSReturnSuccess) {
6161        goto finish;
6162    }
6163
6164    stopfunc = kmod_info->stop;
6165    if (stopfunc) {
6166        OSKextLog(this,
6167            kOSKextLogDetailLevel |
6168            kOSKextLogLoadFlag,
6169            "Kext %s calling module stop function.",
6170            getIdentifierCString());
6171
6172        flags.stopping = 1;
6173
6174        result = stopfunc(kmod_info, /* userData */ NULL);
6175#if !CONFIG_STATIC_CPPINIT
6176        if (result == KERN_SUCCESS) {
6177            result = OSRuntimeFinalizeCPP(kmod_info, NULL);
6178        }
6179#endif
6180
6181        flags.stopping = 0;
6182
6183        if (result == KERN_SUCCESS) {
6184            flags.started = 0;
6185
6186            OSKextLog(this,
6187                kOSKextLogDetailLevel |
6188                kOSKextLogLoadFlag,
6189                "Kext %s is now stopped and ready to unload.",
6190                getIdentifierCString());
6191        } else {
6192            OSKextLog(this,
6193                kOSKextLogErrorLevel |
6194                kOSKextLogLoadFlag,
6195                "Kext %s did not stop (return code 0x%x).",
6196                getIdentifierCString(), result);
6197            result = kOSKextReturnStartStopError;
6198        }
6199    }
6200
6201finish:
6202    return result;
6203}
6204
6205/*********************************************************************
6206*********************************************************************/
6207OSReturn
6208OSKext::unload(void)
6209{
6210    OSReturn     result = kOSReturnError;
6211    unsigned int index;
6212    uint32_t     num_kmod_refs = 0;
6213
6214    if (!sUnloadEnabled) {
6215        OSKextLog(this,
6216            kOSKextLogErrorLevel |
6217            kOSKextLogLoadFlag,
6218            "Kext unloading is disabled (%s).",
6219            this->getIdentifierCString());
6220
6221        result = kOSKextReturnDisabled;
6222        goto finish;
6223    }
6224
6225   /* Refuse to unload if we have clients or instances. It is up to
6226    * the caller to make sure those aren't true.
6227    */
6228    if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6229        // xxx - Don't log under errors? this is more of an info thing
6230        OSKextLog(this,
6231            kOSKextLogErrorLevel |
6232            kOSKextLogKextBookkeepingFlag,
6233            "Can't unload kext %s; outstanding references (linkage or tracking object).",
6234            getIdentifierCString());
6235        result = kOSKextReturnInUse;
6236        goto finish;
6237    }
6238
6239    if (hasOSMetaClassInstances()) {
6240        OSKextLog(this,
6241            kOSKextLogErrorLevel |
6242            kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6243            "Can't unload kext %s; classes have instances:",
6244            getIdentifierCString());
6245        reportOSMetaClassInstances(kOSKextLogErrorLevel |
6246            kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
6247        result = kOSKextReturnInUse;
6248        goto finish;
6249    }
6250
6251    if (!isLoaded()) {
6252        result = kOSReturnSuccess;
6253        goto finish;
6254    }
6255
6256    if (isKernelComponent()) {
6257        result = kOSKextReturnInvalidArgument;
6258        goto finish;
6259    }
6260
6261   /* Note that the kext is unloading before running any code that
6262    * might be in the kext (request callbacks, module stop function).
6263    * We will deny certain requests made against a kext in the process
6264    * of unloading.
6265    */
6266    flags.unloading = 1;
6267
6268   /* Update the string describing the last kext to unload in case we panic.
6269    */
6270    savePanicString(/* isLoading */ false);
6271
6272    if (isStarted()) {
6273        result = stop();
6274        if (result != KERN_SUCCESS) {
6275            OSKextLog(this,
6276                kOSKextLogErrorLevel |
6277                kOSKextLogLoadFlag,
6278                "Kext %s can't unload - module stop returned 0x%x.",
6279                getIdentifierCString(), (unsigned)result);
6280            result = kOSKextReturnStartStopError;
6281            goto finish;
6282        }
6283    }
6284
6285    OSKextLog(this,
6286        kOSKextLogProgressLevel |
6287        kOSKextLogLoadFlag,
6288        "Kext %s unloading.",
6289        getIdentifierCString());
6290
6291   /* Even if we don't call the stop function, we want to be sure we
6292    * have no OSMetaClass references before unloading the kext executable
6293    * from memory. OSMetaClasses may have pointers into the kext executable
6294    * and that would cause a panic on OSKext::free() when metaClasses is freed.
6295    */
6296    if (metaClasses) {
6297        metaClasses->flushCollection();
6298    }
6299
6300   /* Remove the kext from the list of loaded kexts, patch the gap
6301    * in the kmod_info_t linked list, and reset "kmod" to point to the
6302    * last loaded kext that isn't the fake kernel kext (sKernelKext).
6303    */
6304    index = sLoadedKexts->getNextIndexOfObject(this, 0);
6305    if (index != (unsigned int)-1) {
6306
6307        sLoadedKexts->removeObject(index);
6308
6309        OSKext * nextKext = OSDynamicCast(OSKext,
6310            sLoadedKexts->getObject(index));
6311
6312        if (nextKext) {
6313            if (index > 0) {
6314                OSKext * gapKext = OSDynamicCast(OSKext,
6315                    sLoadedKexts->getObject(index - 1));
6316
6317                nextKext->kmod_info->next = gapKext->kmod_info;
6318
6319            } else /* index == 0 */ {
6320                nextKext->kmod_info->next = NULL;
6321            }
6322        }
6323
6324        OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
6325        if (lastKext && !lastKext->isKernel()) {
6326            kmod = lastKext->kmod_info;
6327        } else {
6328            kmod = NULL;  // clear the global kmod variable
6329        }
6330    }
6331
6332   /* Clear out the kmod references that we're keeping for compatibility
6333    * with current panic backtrace code & kgmacros.
6334    * xxx - will want to update those bits sometime and remove this.
6335    */
6336    num_kmod_refs = getNumDependencies();
6337    if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
6338        for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
6339            kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
6340            ref->info->reference_count--;
6341        }
6342        kfree(kmod_info->reference_list,
6343            num_kmod_refs * sizeof(kmod_reference_t));
6344    }
6345
6346#if CONFIG_DTRACE
6347    unregisterWithDTrace();
6348#endif /* CONFIG_DTRACE */
6349
6350    notifyKextUnloadObservers(this);
6351
6352    /* Unwire and free the linked executable.
6353     */
6354    if (linkedExecutable) {
6355#if VM_MAPPED_KEXTS
6356        if (!isInterface()) {
6357            kernel_segment_command_t *seg = NULL;
6358            vm_map_t kext_map = kext_get_vm_map(kmod_info);
6359
6360            if (!kext_map) {
6361                OSKextLog(this,
6362                    kOSKextLogErrorLevel |
6363                    kOSKextLogLoadFlag,
6364                    "Failed to free kext %s; couldn't find the kext map.",
6365                    getIdentifierCString());
6366                result = kOSKextReturnInternalError;
6367                goto finish;
6368            }
6369
6370            OSKextLog(this,
6371                kOSKextLogProgressLevel |
6372                kOSKextLogLoadFlag,
6373                "Kext %s unwiring and unmapping linked executable.",
6374                getIdentifierCString());
6375
6376            seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6377            while (seg) {
6378                if (segmentShouldBeWired(seg)) {
6379                    result = vm_map_unwire(kext_map, seg->vmaddr,
6380                        seg->vmaddr + seg->vmsize, FALSE);
6381                    if (result != KERN_SUCCESS) {
6382                        OSKextLog(this,
6383                            kOSKextLogErrorLevel |
6384                            kOSKextLogLoadFlag,
6385                            "Failed to unwire kext %s.",
6386                            getIdentifierCString());
6387                        result = kOSKextReturnInternalError;
6388                        goto finish;
6389                    }
6390                }
6391
6392                seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6393            }
6394        }
6395#endif
6396        OSSafeReleaseNULL(linkedExecutable);
6397    }
6398
6399   /* An interface kext has a fake kmod_info that was allocated,
6400    * so we have to free it.
6401    */
6402    if (isInterface()) {
6403        kfree(kmod_info, sizeof(kmod_info_t));
6404    }
6405
6406    kmod_info = NULL;
6407
6408    flags.loaded = false;
6409    flushDependencies();
6410
6411    /* save a copy of the bundle ID for us to check when deciding to
6412     * rebuild the kernel cache file.  If a kext was already in the kernel
6413     * cache and unloaded then later loaded we do not need to rebuild the
6414     * kernel cache.  9055303
6415     */
6416    if (isPrelinked()) {
6417        if (!_OSKextInUnloadedPrelinkedKexts(bundleID)) {
6418            IORecursiveLockLock(sKextLock);
6419            if (sUnloadedPrelinkedKexts) {
6420                sUnloadedPrelinkedKexts->setObject(bundleID);
6421            }
6422            IORecursiveLockUnlock(sKextLock);
6423        }
6424    }
6425
6426    OSKextLog(this,
6427        kOSKextLogProgressLevel | kOSKextLogLoadFlag,
6428        "Kext %s unloaded.", getIdentifierCString());
6429
6430    queueKextNotification(kKextRequestPredicateUnloadNotification,
6431        OSDynamicCast(OSString, bundleID));
6432
6433finish:
6434    OSKext::saveLoadedKextPanicList();
6435    OSKext::updateLoadedKextSummaries();
6436
6437    flags.unloading = 0;
6438    return result;
6439}
6440
6441/*********************************************************************
6442* Assumes sKextLock is held.
6443*********************************************************************/
6444/* static */
6445OSReturn
6446OSKext::queueKextNotification(
6447    const char * notificationName,
6448    OSString   * kextIdentifier)
6449{
6450    OSReturn          result               = kOSReturnError;
6451    OSDictionary    * loadRequest          = NULL;  // must release
6452
6453    if (!kextIdentifier) {
6454        result = kOSKextReturnInvalidArgument;
6455        goto finish;
6456    }
6457
6458   /* Create a new request unless one is already sitting
6459    * in sKernelRequests for this bundle identifier
6460    */
6461    result = _OSKextCreateRequest(notificationName, &loadRequest);
6462    if (result != kOSReturnSuccess) {
6463        goto finish;
6464    }
6465    if (!_OSKextSetRequestArgument(loadRequest,
6466        kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
6467
6468        result = kOSKextReturnNoMemory;
6469        goto finish;
6470    }
6471    if (!sKernelRequests->setObject(loadRequest)) {
6472        result = kOSKextReturnNoMemory;
6473        goto finish;
6474    }
6475
6476   /* We might want to only queue the notification if kextd is active,
6477    * but that wouldn't work for embedded. Note that we don't care if
6478    * the ping immediately succeeds here so don't do anything with the
6479    * result of this call.
6480    */
6481    OSKext::pingKextd();
6482
6483    result = kOSReturnSuccess;
6484
6485finish:
6486    OSSafeRelease(loadRequest);
6487
6488    return result;
6489}
6490
6491/*********************************************************************
6492*********************************************************************/
6493static void
6494_OSKextConsiderDestroyingLinkContext(
6495    __unused thread_call_param_t p0,
6496    __unused thread_call_param_t p1)
6497{
6498   /* Take multiple locks in the correct order.
6499    */
6500    IORecursiveLockLock(sKextLock);
6501    IORecursiveLockLock(sKextInnerLock);
6502
6503   /* The first time we destroy the kxldContext is in the first
6504    * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6505    * before calling this function. Thereafter any call to this function
6506    * will actually destroy the context.
6507    */
6508    if (sConsiderUnloadsCalled && sKxldContext) {
6509        kxld_destroy_context(sKxldContext);
6510        sKxldContext = NULL;
6511    }
6512
6513   /* Free the thread_call that was allocated to execute this function.
6514    */
6515    if (sDestroyLinkContextThread) {
6516        if (!thread_call_free(sDestroyLinkContextThread)) {
6517            OSKextLog(/* kext */ NULL,
6518                kOSKextLogErrorLevel |
6519                kOSKextLogGeneralFlag,
6520                "thread_call_free() failed for kext link context.");
6521        }
6522        sDestroyLinkContextThread = 0;
6523    }
6524
6525    IORecursiveLockUnlock(sKextInnerLock);
6526    IORecursiveLockUnlock(sKextLock);
6527
6528    return;
6529}
6530
6531/*********************************************************************
6532* Destroying the kxldContext requires checking variables under both
6533* sKextInnerLock and sKextLock, so we do it on a separate thread
6534* to avoid deadlocks with IOService, with which OSKext has a reciprocal
6535* call relationship.
6536*
6537* This function must be invoked with sKextInnerLock held.
6538* Do not call any function that takes sKextLock here!
6539*********************************************************************/
6540/* static */
6541void
6542OSKext::considerDestroyingLinkContext(void)
6543{
6544    IORecursiveLockLock(sKextInnerLock);
6545
6546   /* If we have already queued a thread to destroy the link context,
6547    * don't bother resetting; that thread will take care of it.
6548    */
6549    if (sDestroyLinkContextThread) {
6550        goto finish;
6551    }
6552
6553   /* The function to be invoked in the thread will deallocate
6554    * this thread_call, so don't share it around.
6555    */
6556    sDestroyLinkContextThread = thread_call_allocate(
6557        &_OSKextConsiderDestroyingLinkContext, 0);
6558    if (!sDestroyLinkContextThread) {
6559        OSKextLog(/* kext */ NULL,
6560            kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
6561            "Can't create thread to destroy kext link context.");
6562        goto finish;
6563    }
6564
6565    thread_call_enter(sDestroyLinkContextThread);
6566
6567finish:
6568    IORecursiveLockUnlock(sKextInnerLock);
6569    return;
6570}
6571
6572#if PRAGMA_MARK
6573#pragma mark Autounload
6574#endif
6575/*********************************************************************
6576* This is a static method because the kext will be deallocated if it
6577* does unload!
6578*********************************************************************/
6579/* static */
6580OSReturn
6581OSKext::autounloadKext(OSKext * aKext)
6582{
6583    OSReturn result = kOSKextReturnInUse;
6584
6585   /* Check for external references to this kext (usu. dependents),
6586    * instances of defined classes (or classes derived from them),
6587    * outstanding requests.
6588    */
6589    if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
6590        !aKext->flags.autounloadEnabled ||
6591        aKext->isKernelComponent()) {
6592
6593        goto finish;
6594    }
6595
6596   /* Skip a delay-autounload kext, once.
6597    */
6598    if (aKext->flags.delayAutounload) {
6599        OSKextLog(aKext,
6600            kOSKextLogProgressLevel |
6601            kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6602            "Kext %s has delayed autounload set; skipping and clearing flag.",
6603            aKext->getIdentifierCString());
6604        aKext->flags.delayAutounload = 0;
6605        goto finish;
6606    }
6607
6608    if (aKext->hasOSMetaClassInstances() ||
6609        aKext->countRequestCallbacks()) {
6610        goto finish;
6611    }
6612
6613    result = OSKext::removeKext(aKext);
6614
6615finish:
6616
6617    return result;
6618}
6619
6620/*********************************************************************
6621*********************************************************************/
6622void
6623_OSKextConsiderUnloads(
6624    __unused thread_call_param_t p0,
6625    __unused thread_call_param_t p1)
6626{
6627    bool         didUnload = false;
6628    unsigned int count, i;
6629
6630   /* Take multiple locks in the correct order
6631    * (note also sKextSummaries lock further down).
6632    */
6633    IORecursiveLockLock(sKextLock);
6634    IORecursiveLockLock(sKextInnerLock);
6635
6636    OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6637
6638    IOLockLock(sKextSummariesLock);
6639
6640   /* If there is an old kext summary, free that now.
6641    */
6642    if (sPrevLoadedKextSummaries) {
6643        kmem_free(kernel_map, (vm_offset_t)sPrevLoadedKextSummaries,
6644            sPrevLoadedKextSummariesAllocSize);
6645        sPrevLoadedKextSummaries = NULL;
6646        sPrevLoadedKextSummariesAllocSize = 0;
6647    }
6648
6649    IOLockUnlock(sKextSummariesLock);
6650
6651   /* If the system is powering down, don't try to unload anything.
6652    */
6653    if (sSystemSleep) {
6654        goto finish;
6655    }
6656
6657    OSKextLog(/* kext */ NULL,
6658        kOSKextLogProgressLevel |
6659        kOSKextLogLoadFlag,
6660        "Checking for unused kexts to autounload.");
6661
6662   /*****
6663    * Remove any request callbacks marked as stale,
6664    * and mark as stale any currently in flight.
6665    */
6666    count = sRequestCallbackRecords->getCount();
6667    if (count) {
6668        i = count - 1;
6669        do {
6670            OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
6671                sRequestCallbackRecords->getObject(i));
6672            OSBoolean * stale = OSDynamicCast(OSBoolean,
6673                callbackRecord->getObject(kKextRequestStaleKey));
6674
6675            if (stale == kOSBooleanTrue) {
6676                OSKext::invokeRequestCallback(callbackRecord,
6677                    kOSKextReturnTimeout);
6678            } else {
6679                callbackRecord->setObject(kKextRequestStaleKey,
6680                    kOSBooleanTrue);
6681            }
6682        } while (i--);
6683    }
6684
6685   /*****
6686    * Make multiple passes through the array of loaded kexts until
6687    * we don't unload any. This handles unwinding of dependency
6688    * chains. We have to go *backwards* through the array because
6689    * kexts are removed from it when unloaded, and we cannot make
6690    * a copy or we'll mess up the retain counts we rely on to
6691    * check whether a kext will unload. If only we could have
6692    * nonretaining collections like CF has....
6693    */
6694    do {
6695        didUnload = false;
6696
6697        count = sLoadedKexts->getCount();
6698        if (count) {
6699            i = count - 1;
6700            do {
6701                OSKext * thisKext = OSDynamicCast(OSKext,
6702                    sLoadedKexts->getObject(i));
6703                didUnload = (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
6704            } while (i--);
6705        }
6706    } while (didUnload);
6707
6708finish:
6709    sConsiderUnloadsPending = false;
6710    sConsiderUnloadsExecuted = true;
6711
6712    (void) OSKext::considerRebuildOfPrelinkedKernel();
6713
6714    IORecursiveLockUnlock(sKextInnerLock);
6715    IORecursiveLockUnlock(sKextLock);
6716
6717    return;
6718}
6719
6720/*********************************************************************
6721* Do not call any function that takes sKextLock here!
6722*********************************************************************/
6723void OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
6724{
6725    AbsoluteTime when;
6726
6727    IORecursiveLockLock(sKextInnerLock);
6728
6729    if (!sUnloadCallout) {
6730        sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, 0);
6731    }
6732
6733    /* we only reset delay value for unloading if we already have something
6734     * pending.  rescheduleOnlyFlag should not start the count down.
6735     */
6736    if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
6737        goto finish;
6738    }
6739
6740    thread_call_cancel(sUnloadCallout);
6741    if (OSKext::getAutounloadEnabled() && !sSystemSleep) {
6742        clock_interval_to_deadline(sConsiderUnloadDelay,
6743            1000 * 1000 * 1000, &when);
6744
6745        OSKextLog(/* kext */ NULL,
6746            kOSKextLogProgressLevel |
6747            kOSKextLogLoadFlag,
6748            "%scheduling %sscan for unused kexts in %lu seconds.",
6749            sConsiderUnloadsPending ? "Res" : "S",
6750            sConsiderUnloadsCalled ? "" : "initial ",
6751            (unsigned long)sConsiderUnloadDelay);
6752
6753        sConsiderUnloadsPending = true;
6754        thread_call_enter_delayed(sUnloadCallout, when);
6755    }
6756
6757finish:
6758   /* The kxld context should be reused throughout boot.  We mark the end of
6759    * period as the first time considerUnloads() is called, and we destroy
6760    * the first kxld context in that function.  Afterwards, it will be
6761    * destroyed in flushNonloadedKexts.
6762    */
6763    if (!sConsiderUnloadsCalled) {
6764        sConsiderUnloadsCalled = true;
6765        OSKext::considerDestroyingLinkContext();
6766    }
6767
6768    IORecursiveLockUnlock(sKextInnerLock);
6769    return;
6770}
6771
6772/*********************************************************************
6773* Do not call any function that takes sKextLock here!
6774*********************************************************************/
6775extern "C" {
6776
6777IOReturn OSKextSystemSleepOrWake(UInt32 messageType)
6778{
6779    IORecursiveLockLock(sKextInnerLock);
6780
6781   /* If the system is going to sleep, cancel the reaper thread timer,
6782    * and note that we're in a sleep state in case it just fired but hasn't
6783    * taken the lock yet. If we are coming back from sleep, just
6784    * clear the sleep flag; IOService's normal operation will cause
6785    * unloads to be considered soon enough.
6786    */
6787    if (messageType == kIOMessageSystemWillSleep) {
6788        if (sUnloadCallout) {
6789            thread_call_cancel(sUnloadCallout);
6790        }
6791        sSystemSleep = true;
6792        AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
6793    } else if (messageType == kIOMessageSystemHasPoweredOn) {
6794        sSystemSleep = false;
6795        clock_get_uptime(&sLastWakeTime);
6796   }
6797    IORecursiveLockUnlock(sKextInnerLock);
6798
6799    return kIOReturnSuccess;
6800}
6801
6802};
6803
6804
6805#if PRAGMA_MARK
6806#pragma mark Prelinked Kernel
6807#endif
6808/*********************************************************************
6809* Do not access sConsiderUnloads... variables other than
6810* sConsiderUnloadsExecuted in this function. They are guarded by a
6811* different lock.
6812*********************************************************************/
6813/* static */
6814void
6815OSKext::considerRebuildOfPrelinkedKernel(void)
6816{
6817    static bool     requestedPrelink        = false;
6818    OSReturn        checkResult             = kOSReturnError;
6819    OSDictionary *  prelinkRequest          = NULL;  // must release
6820    OSCollectionIterator * kextIterator     = NULL;  // must release
6821    const OSSymbol * thisID                 = NULL;  // do not release
6822    bool            doRebuild               = false;
6823    AbsoluteTime    my_abstime;
6824    UInt64          my_ns;
6825    SInt32          delta_secs;
6826
6827    /* Only one auto rebuild per boot and only on boot from prelinked kernel */
6828    if (requestedPrelink || !sPrelinkBoot) {
6829        return;
6830    }
6831
6832    /* no direct return from this point */
6833    IORecursiveLockLock(sKextLock);
6834
6835    /* We need to wait for kextd to get up and running with unloads already done
6836     * and any new startup kexts loaded.
6837     */
6838    if (!sConsiderUnloadsExecuted ||
6839        !sDeferredLoadSucceeded) {
6840        goto finish;
6841    }
6842
6843    /* we really only care about boot / system start up related kexts so bail
6844     * if we're here after REBUILD_MAX_TIME.
6845     */
6846    if (!_OSKextInPrelinkRebuildWindow()) {
6847        OSKextLog(/* kext */ NULL,
6848                  kOSKextLogArchiveFlag,
6849                  "%s prebuild rebuild has expired",
6850                  __FUNCTION__);
6851        requestedPrelink = true;
6852        goto finish;
6853    }
6854
6855    /* we do not want to trigger a rebuild if we get here too close to waking
6856     * up.  (see radar 10233768)
6857     */
6858    IORecursiveLockLock(sKextInnerLock);
6859
6860    clock_get_uptime(&my_abstime);
6861    delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
6862    if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
6863        SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
6864        absolutetime_to_nanoseconds(my_abstime, &my_ns);
6865        delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
6866    }
6867    IORecursiveLockUnlock(sKextInnerLock);
6868
6869    if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
6870        /* too close to time of last wake from sleep */
6871        goto finish;
6872    }
6873    requestedPrelink = true;
6874
6875    /* Now it's time to see if we have a reason to rebuild.  We may have done
6876     * some loads and unloads but the kernel cache didn't actually change.
6877     * We will rebuild if any kext is not marked prelinked AND is not in our
6878     * list of prelinked kexts that got unloaded.  (see radar 9055303)
6879     */
6880    kextIterator = OSCollectionIterator::withCollection(sKextsByID);
6881    if (!kextIterator) {
6882        goto finish;
6883    }
6884
6885    while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
6886        OSKext *    thisKext;  // do not release
6887
6888        thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
6889        if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
6890            continue;
6891        }
6892
6893        if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID)) {
6894            continue;
6895        }
6896        /* kext is loaded and was not in current kernel cache so let's rebuild
6897         */
6898        doRebuild = true;
6899        OSKextLog(/* kext */ NULL,
6900                  kOSKextLogArchiveFlag,
6901                  "considerRebuildOfPrelinkedKernel %s triggered rebuild",
6902                  thisKext->bundleID->getCStringNoCopy());
6903        break;
6904    }
6905    sUnloadedPrelinkedKexts->flushCollection();
6906
6907    if (!doRebuild) {
6908        goto finish;
6909    }
6910
6911    checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
6912                                       &prelinkRequest);
6913    if (checkResult != kOSReturnSuccess) {
6914        goto finish;
6915    }
6916
6917    if (!sKernelRequests->setObject(prelinkRequest)) {
6918        goto finish;
6919    }
6920
6921    OSKext::pingKextd();
6922
6923finish:
6924    IORecursiveLockUnlock(sKextLock);
6925    OSSafeRelease(prelinkRequest);
6926    OSSafeRelease(kextIterator);
6927
6928    return;
6929}
6930
6931#if PRAGMA_MARK
6932#pragma mark Dependencies
6933#endif
6934/*********************************************************************
6935*********************************************************************/
6936bool
6937OSKext::resolveDependencies(
6938    OSArray * loopStack)
6939{
6940    bool                   result                   = false;
6941    OSArray              * localLoopStack           = NULL;   // must release
6942    bool                   addedToLoopStack         = false;
6943    OSDictionary         * libraries                = NULL;   // do not release
6944    OSCollectionIterator * libraryIterator          = NULL;   // must release
6945    OSString             * libraryID                = NULL;   // do not release
6946    OSString             * infoString               = NULL;   // do not release
6947    OSString             * readableString           = NULL;   // do not release
6948    OSKext               * libraryKext              = NULL;   // do not release
6949    bool                   hasRawKernelDependency   = false;
6950    bool                   hasKernelDependency      = false;
6951    bool                   hasKPIDependency         = false;
6952    bool                   hasPrivateKPIDependency  = false;
6953    unsigned int           count;
6954
6955   /* A kernel component will automatically have this flag set,
6956    * and a loaded kext should also have it set (as should all its
6957    * loaded dependencies).
6958    */
6959    if (flags.hasAllDependencies) {
6960        result = true;
6961        goto finish;
6962    }
6963
6964   /* Check for loops in the dependency graph.
6965    */
6966    if (loopStack) {
6967        if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
6968            OSKextLog(this,
6969                kOSKextLogErrorLevel |
6970                kOSKextLogDependenciesFlag,
6971                "Kext %s has a dependency loop; can't resolve dependencies.",
6972                getIdentifierCString());
6973            goto finish;
6974        }
6975    } else {
6976        OSKextLog(this,
6977            kOSKextLogStepLevel |
6978            kOSKextLogDependenciesFlag,
6979            "Kext %s resolving dependencies.",
6980            getIdentifierCString());
6981
6982        loopStack = OSArray::withCapacity(6);  // any small capacity will do
6983        if (!loopStack) {
6984            OSKextLog(this,
6985                kOSKextLogErrorLevel |
6986                kOSKextLogDependenciesFlag,
6987                "Kext %s can't create bookkeeping stack to resolve dependencies.",
6988                getIdentifierCString());
6989            goto finish;
6990        }
6991        localLoopStack = loopStack;
6992    }
6993    if (!loopStack->setObject(this)) {
6994        OSKextLog(this,
6995            kOSKextLogErrorLevel |
6996            kOSKextLogDependenciesFlag,
6997            "Kext %s - internal error resolving dependencies.",
6998            getIdentifierCString());
6999        goto finish;
7000    }
7001    addedToLoopStack = true;
7002
7003   /* Purge any existing kexts in the dependency list and start over.
7004    */
7005    flushDependencies();
7006    if (dependencies) {
7007        OSKextLog(this,
7008            kOSKextLogErrorLevel |
7009            kOSKextLogDependenciesFlag,
7010            "Kext %s - internal error resolving dependencies.",
7011            getIdentifierCString());
7012    }
7013
7014    libraries = OSDynamicCast(OSDictionary,
7015        getPropertyForHostArch(kOSBundleLibrariesKey));
7016    if (libraries == NULL || libraries->getCount() == 0) {
7017        OSKextLog(this,
7018            kOSKextLogErrorLevel |
7019            kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7020            "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7021            getIdentifierCString(), kOSBundleLibrariesKey);
7022        goto finish;
7023    }
7024
7025   /* Make a new array to hold the dependencies (flush freed the old one).
7026    */
7027    dependencies = OSArray::withCapacity(libraries->getCount());
7028    if (!dependencies) {
7029        OSKextLog(this,
7030            kOSKextLogErrorLevel |
7031            kOSKextLogDependenciesFlag,
7032            "Kext %s - can't allocate dependencies array.",
7033            getIdentifierCString());
7034        goto finish;
7035    }
7036
7037    // xxx - compat: We used to add an implicit dependency on kernel 6.0
7038    // xxx - compat: if none were declared.
7039
7040    libraryIterator = OSCollectionIterator::withCollection(libraries);
7041    if (!libraryIterator) {
7042        OSKextLog(this,
7043            kOSKextLogErrorLevel |
7044            kOSKextLogDependenciesFlag,
7045            "Kext %s - can't allocate dependencies iterator.",
7046            getIdentifierCString());
7047        goto finish;
7048    }
7049
7050    while ((libraryID = OSDynamicCast(OSString,
7051           libraryIterator->getNextObject()))) {
7052
7053       const char * library_id = libraryID->getCStringNoCopy();
7054
7055        OSString * libraryVersion = OSDynamicCast(OSString,
7056            libraries->getObject(libraryID));
7057        if (libraryVersion == NULL) {
7058            OSKextLog(this,
7059                kOSKextLogErrorLevel |
7060                kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7061                "Kext %s - illegal type in OSBundleLibraries.",
7062                getIdentifierCString());
7063            goto finish;
7064        }
7065
7066        OSKextVersion libraryVers =
7067            OSKextParseVersionString(libraryVersion->getCStringNoCopy());
7068        if (libraryVers == -1) {
7069            OSKextLog(this,
7070                kOSKextLogErrorLevel |
7071                kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7072                "Kext %s - invalid library version %s.",
7073                getIdentifierCString(),
7074                libraryVersion->getCStringNoCopy());
7075            goto finish;
7076        }
7077
7078        libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
7079        if (libraryKext == NULL) {
7080            OSKextLog(this,
7081                kOSKextLogErrorLevel |
7082                kOSKextLogDependenciesFlag,
7083                "Kext %s - library kext %s not found.",
7084                getIdentifierCString(), library_id);
7085            goto finish;
7086        }
7087
7088        if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
7089            OSKextLog(this,
7090                kOSKextLogErrorLevel |
7091                kOSKextLogDependenciesFlag,
7092                "Kext %s - library kext %s not compatible "
7093                "with requested version %s.",
7094                getIdentifierCString(), library_id,
7095                libraryVersion->getCStringNoCopy());
7096            goto finish;
7097        }
7098
7099       /* If a nonprelinked library somehow got into the mix for a
7100        * prelinked kext, at any point in the chain, we must fail
7101        * because the prelinked relocs for the library will be all wrong.
7102        */
7103        if (this->isPrelinked() &&
7104            libraryKext->declaresExecutable() &&
7105            !libraryKext->isPrelinked()) {
7106
7107            OSKextLog(this,
7108                kOSKextLogErrorLevel |
7109                kOSKextLogDependenciesFlag,
7110                "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7111                getIdentifierCString(), library_id,
7112                libraryVersion->getCStringNoCopy());
7113            goto finish;
7114        }
7115
7116        if (!libraryKext->resolveDependencies(loopStack)) {
7117            goto finish;
7118        }
7119
7120       /* Add the library directly only if it has an executable to link.
7121        * Otherwise it's just used to collect other dependencies, so put
7122        * *its* dependencies on the list for this kext.
7123        */
7124        // xxx - We are losing info here; would like to make fake entries or
7125        // xxx - keep these in the dependency graph for loaded kexts.
7126        // xxx - I really want to make kernel components not a special case!
7127        if (libraryKext->declaresExecutable() ||
7128            libraryKext->isInterface()) {
7129
7130            if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
7131                dependencies->setObject(libraryKext);
7132
7133                OSKextLog(this,
7134                    kOSKextLogDetailLevel |
7135                    kOSKextLogDependenciesFlag,
7136                    "Kext %s added dependency %s.",
7137                    getIdentifierCString(),
7138                    libraryKext->getIdentifierCString());
7139            }
7140        } else {
7141            int       numLibDependencies  = libraryKext->getNumDependencies();
7142            OSArray * libraryDependencies = libraryKext->getDependencies();
7143            int       index;
7144
7145            if (numLibDependencies) {
7146                // xxx - this msg level should be 1 lower than the per-kext one
7147                OSKextLog(this,
7148                    kOSKextLogDetailLevel |
7149                    kOSKextLogDependenciesFlag,
7150                    "Kext %s pulling %d dependencies from codeless library %s.",
7151                    getIdentifierCString(),
7152                    numLibDependencies,
7153                    libraryKext->getIdentifierCString());
7154            }
7155            for (index = 0; index < numLibDependencies; index++) {
7156                OSKext * thisLibDependency = OSDynamicCast(OSKext,
7157                    libraryDependencies->getObject(index));
7158                if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
7159                    dependencies->setObject(thisLibDependency);
7160                    OSKextLog(this,
7161                        kOSKextLogDetailLevel |
7162                        kOSKextLogDependenciesFlag,
7163                        "Kext %s added dependency %s from codeless library %s.",
7164                        getIdentifierCString(),
7165                        thisLibDependency->getIdentifierCString(),
7166                        libraryKext->getIdentifierCString());
7167                }
7168            }
7169        }
7170
7171        if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
7172            0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB)-1)) {
7173
7174            hasRawKernelDependency = true;
7175        } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
7176            hasKernelDependency = true;
7177        } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
7178            hasKPIDependency = true;
7179            if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI)-1)) {
7180                hasPrivateKPIDependency = true;
7181            }
7182        }
7183    }
7184
7185    if (hasRawKernelDependency) {
7186        OSKextLog(this,
7187            kOSKextLogErrorLevel |
7188            kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7189            "Error - kext %s declares a dependency on %s, which is not permitted.",
7190            getIdentifierCString(), KERNEL_LIB);
7191        goto finish;
7192    }
7193#if __LP64__
7194    if (hasKernelDependency) {
7195        OSKextLog(this,
7196            kOSKextLogErrorLevel |
7197            kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7198            "Error - kext %s declares %s dependencies. "
7199            "Only %s* dependencies are supported for 64-bit kexts.",
7200            getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
7201        goto finish;
7202    }
7203    if (!hasKPIDependency) {
7204        OSKextLog(this,
7205            kOSKextLogWarningLevel |
7206            kOSKextLogDependenciesFlag,
7207            "Warning - kext %s declares no %s* dependencies. "
7208            "If it uses any KPIs, the link may fail with undefined symbols.",
7209            getIdentifierCString(), KPI_LIB_PREFIX);
7210    }
7211#else /* __LP64__ */
7212    // xxx - will change to flatly disallow "kernel" dependencies at some point
7213    // xxx - is it invalid to do both "com.apple.kernel" and any
7214    // xxx - "com.apple.kernel.*"?
7215
7216    if (hasKernelDependency && hasKPIDependency) {
7217        OSKextLog(this,
7218            kOSKextLogWarningLevel |
7219            kOSKextLogDependenciesFlag,
7220            "Warning - kext %s has immediate dependencies on both "
7221            "%s* and %s* components; use only one style.",
7222            getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
7223    }
7224
7225    if (!hasKernelDependency && !hasKPIDependency) {
7226        // xxx - do we want to use validation flag for these too?
7227        OSKextLog(this,
7228            kOSKextLogWarningLevel |
7229            kOSKextLogDependenciesFlag,
7230            "Warning - %s declares no kernel dependencies; using %s.",
7231            getIdentifierCString(), KERNEL6_LIB);
7232        OSKext * kernelKext = OSDynamicCast(OSKext,
7233            sKextsByID->getObject(KERNEL6_LIB));
7234        if (kernelKext) {
7235            dependencies->setObject(kernelKext);
7236        } else {
7237            OSKextLog(this,
7238                kOSKextLogErrorLevel |
7239                kOSKextLogDependenciesFlag,
7240                "Error - Library %s not found for %s.",
7241                KERNEL6_LIB, getIdentifierCString());
7242        }
7243    }
7244
7245   /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7246    * its indirect dependencies to simulate old-style linking.  XXX - Should
7247    * check for duplicates.
7248    */
7249    if (!hasKPIDependency) {
7250        unsigned int i;
7251
7252        flags.hasBleedthrough = true;
7253
7254        count = getNumDependencies();
7255
7256       /* We add to the dependencies array in this loop, but do not iterate
7257        * past its original count.
7258        */
7259        for (i = 0; i < count; i++) {
7260            OSKext * dependencyKext = OSDynamicCast(OSKext,
7261                dependencies->getObject(i));
7262            dependencyKext->addBleedthroughDependencies(dependencies);
7263        }
7264    }
7265#endif /* __LP64__ */
7266
7267    if (hasPrivateKPIDependency) {
7268        bool hasApplePrefix = false;
7269        bool infoCopyrightIsValid = false;
7270        bool readableCopyrightIsValid = false;
7271
7272        hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
7273            APPLE_KEXT_PREFIX);
7274
7275        infoString = OSDynamicCast(OSString,
7276            getPropertyForHostArch("CFBundleGetInfoString"));
7277        if (infoString) {
7278            infoCopyrightIsValid =
7279                kxld_validate_copyright_string(infoString->getCStringNoCopy());
7280        }
7281
7282        readableString = OSDynamicCast(OSString,
7283            getPropertyForHostArch("NSHumanReadableCopyright"));
7284        if (readableString) {
7285            readableCopyrightIsValid =
7286                kxld_validate_copyright_string(readableString->getCStringNoCopy());
7287        }
7288
7289        if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
7290            OSKextLog(this,
7291                kOSKextLogErrorLevel |
7292                kOSKextLogDependenciesFlag,
7293                "Error - kext %s declares a dependency on %s. "
7294                  "Only Apple kexts may declare a dependency on %s.",
7295                  getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
7296            goto finish;
7297        }
7298    }
7299
7300    result = true;
7301    flags.hasAllDependencies = 1;
7302
7303finish:
7304
7305    if (addedToLoopStack) {
7306        count = loopStack->getCount();
7307        if (count > 0 && (this == loopStack->getObject(count - 1))) {
7308            loopStack->removeObject(count - 1);
7309        } else {
7310            OSKextLog(this,
7311                kOSKextLogErrorLevel |
7312                kOSKextLogDependenciesFlag,
7313                "Kext %s - internal error resolving dependencies.",
7314                getIdentifierCString());
7315        }
7316    }
7317
7318    if (result && localLoopStack) {
7319        OSKextLog(this,
7320            kOSKextLogStepLevel |
7321            kOSKextLogDependenciesFlag,
7322            "Kext %s successfully resolved dependencies.",
7323            getIdentifierCString());
7324    }
7325
7326    OSSafeRelease(localLoopStack);
7327    OSSafeRelease(libraryIterator);
7328
7329    return result;
7330}
7331
7332/*********************************************************************
7333*********************************************************************/
7334bool
7335OSKext::addBleedthroughDependencies(OSArray * anArray)
7336{
7337    bool result = false;
7338    unsigned int dependencyIndex, dependencyCount;
7339
7340    dependencyCount = getNumDependencies();
7341
7342    for (dependencyIndex = 0;
7343         dependencyIndex < dependencyCount;
7344         dependencyIndex++) {
7345
7346        OSKext * dependency = OSDynamicCast(OSKext,
7347            dependencies->getObject(dependencyIndex));
7348        if (!dependency) {
7349            OSKextLog(this,
7350                kOSKextLogErrorLevel |
7351                kOSKextLogDependenciesFlag,
7352                "Kext %s - internal error propagating compatibility dependencies.",
7353                getIdentifierCString());
7354            goto finish;
7355        }
7356        if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
7357            anArray->setObject(dependency);
7358        }
7359        dependency->addBleedthroughDependencies(anArray);
7360    }
7361
7362    result = true;
7363
7364finish:
7365    return result;
7366}
7367
7368/*********************************************************************
7369*********************************************************************/
7370bool
7371OSKext::flushDependencies(bool forceFlag)
7372{
7373    bool result = false;
7374
7375   /* Only clear the dependencies if the kext isn't loaded;
7376    * we need the info for loaded kexts to track references.
7377    */
7378    if (!isLoaded() || forceFlag) {
7379        if (dependencies) {
7380            // xxx - check level
7381            OSKextLog(this,
7382                kOSKextLogProgressLevel |
7383                kOSKextLogDependenciesFlag,
7384                "Kext %s flushing dependencies.",
7385                getIdentifierCString());
7386            OSSafeReleaseNULL(dependencies);
7387
7388        }
7389        if (!isKernelComponent()) {
7390            flags.hasAllDependencies = 0;
7391        }
7392        result = true;
7393    }
7394
7395    return result;
7396}
7397
7398/*********************************************************************
7399*********************************************************************/
7400uint32_t
7401OSKext::getNumDependencies(void)
7402{
7403    if (!dependencies) {
7404        return 0;
7405    }
7406    return dependencies->getCount();
7407}
7408
7409/*********************************************************************
7410*********************************************************************/
7411OSArray *
7412OSKext::getDependencies(void)
7413{
7414    return dependencies;
7415}
7416
7417#if PRAGMA_MARK
7418#pragma mark OSMetaClass Support
7419#endif
7420/*********************************************************************
7421*********************************************************************/
7422OSReturn
7423OSKext::addClass(
7424    OSMetaClass * aClass,
7425    uint32_t      numClasses)
7426{
7427    OSReturn result = kOSMetaClassNoInsKModSet;
7428
7429    if (!metaClasses) {
7430        metaClasses = OSSet::withCapacity(numClasses);
7431        if (!metaClasses) {
7432            goto finish;
7433        }
7434    }
7435
7436    if (metaClasses->containsObject(aClass)) {
7437        OSKextLog(this,
7438            kOSKextLogWarningLevel |
7439            kOSKextLogLoadFlag,
7440            "Notice - kext %s has already registered class %s.",
7441            getIdentifierCString(),
7442            aClass->getClassName());
7443        result = kOSReturnSuccess;
7444        goto finish;
7445    }
7446
7447    if (!metaClasses->setObject(aClass)) {
7448        goto finish;
7449    } else {
7450        OSKextLog(this,
7451            kOSKextLogDetailLevel |
7452            kOSKextLogLoadFlag,
7453            "Kext %s registered class %s.",
7454            getIdentifierCString(),
7455            aClass->getClassName());
7456    }
7457
7458    if (!flags.autounloadEnabled) {
7459        const OSMetaClass * metaScan  = NULL;  // do not release
7460
7461        for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
7462            if (metaScan == OSTypeID(IOService)) {
7463
7464                OSKextLog(this,
7465                    kOSKextLogProgressLevel |
7466                    kOSKextLogLoadFlag,
7467                    "Kext %s has IOService subclass %s; enabling autounload.",
7468                    getIdentifierCString(),
7469                    aClass->getClassName());
7470
7471                flags.autounloadEnabled = 1;
7472                break;
7473            }
7474        }
7475    }
7476
7477    notifyAddClassObservers(this, aClass, flags);
7478
7479    result = kOSReturnSuccess;
7480
7481finish:
7482    if (result != kOSReturnSuccess) {
7483        OSKextLog(this,
7484            kOSKextLogErrorLevel |
7485            kOSKextLogLoadFlag,
7486            "Kext %s failed to register class %s.",
7487            getIdentifierCString(),
7488            aClass->getClassName());
7489    }
7490
7491    return result;
7492}
7493
7494/*********************************************************************
7495*********************************************************************/
7496OSReturn
7497OSKext::removeClass(
7498    OSMetaClass * aClass)
7499{
7500    OSReturn result = kOSMetaClassNoKModSet;
7501
7502    if (!metaClasses) {
7503        goto finish;
7504    }
7505
7506    if (!metaClasses->containsObject(aClass)) {
7507        OSKextLog(this,
7508            kOSKextLogWarningLevel |
7509            kOSKextLogLoadFlag,
7510            "Notice - kext %s asked to unregister unknown class %s.",
7511            getIdentifierCString(),
7512            aClass->getClassName());
7513        result = kOSReturnSuccess;
7514        goto finish;
7515    }
7516
7517    OSKextLog(this,
7518        kOSKextLogDetailLevel |
7519        kOSKextLogLoadFlag,
7520        "Kext %s unregistering class %s.",
7521        getIdentifierCString(),
7522        aClass->getClassName());
7523
7524    metaClasses->removeObject(aClass);
7525
7526    notifyRemoveClassObservers(this, aClass, flags);
7527
7528    result = kOSReturnSuccess;
7529
7530finish:
7531    if (result != kOSReturnSuccess) {
7532        OSKextLog(this,
7533            kOSKextLogErrorLevel |
7534            kOSKextLogLoadFlag,
7535            "Failed to unregister kext %s class %s.",
7536            getIdentifierCString(),
7537            aClass->getClassName());
7538    }
7539    return result;
7540}
7541
7542/*********************************************************************
7543*********************************************************************/
7544OSSet *
7545OSKext::getMetaClasses(void)
7546{
7547    return metaClasses;
7548}
7549
7550/*********************************************************************
7551*********************************************************************/
7552bool
7553OSKext::hasOSMetaClassInstances(void)
7554{
7555    bool                   result        = false;
7556    OSCollectionIterator * classIterator = NULL;  // must release
7557    OSMetaClass          * checkClass    = NULL;  // do not release
7558
7559    if (!metaClasses) {
7560        goto finish;
7561    }
7562
7563    classIterator = OSCollectionIterator::withCollection(metaClasses);
7564    if (!classIterator) {
7565        // xxx - log alloc failure?
7566        goto finish;
7567    }
7568    while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
7569        if (checkClass->getInstanceCount()) {
7570            result = true;
7571            goto finish;
7572        }
7573    }
7574
7575finish:
7576
7577    OSSafeRelease(classIterator);
7578    return result;
7579}
7580
7581/*********************************************************************
7582*********************************************************************/
7583/* static */
7584void
7585OSKext::reportOSMetaClassInstances(
7586    const char     * kextIdentifier,
7587    OSKextLogSpec    msgLogSpec)
7588{
7589    OSKext * theKext = NULL; // must release
7590
7591    theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
7592    if (!theKext) {
7593        goto finish;
7594    }
7595
7596    theKext->reportOSMetaClassInstances(msgLogSpec);
7597finish:
7598    OSSafeRelease(theKext);
7599    return;
7600}
7601
7602/*********************************************************************
7603*********************************************************************/
7604void
7605OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
7606{
7607    OSCollectionIterator * classIterator = NULL;  // must release
7608    OSMetaClass          * checkClass    = NULL;  // do not release
7609
7610    if (!metaClasses) {
7611        goto finish;
7612    }
7613
7614    classIterator = OSCollectionIterator::withCollection(metaClasses);
7615    if (!classIterator) {
7616        goto finish;
7617    }
7618    while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
7619        if (checkClass->getInstanceCount()) {
7620            OSKextLog(this,
7621                msgLogSpec,
7622                "    Kext %s class %s has %d instance%s.",
7623                getIdentifierCString(),
7624                checkClass->getClassName(),
7625                checkClass->getInstanceCount(),
7626                checkClass->getInstanceCount() == 1 ? "" : "s");
7627        }
7628    }
7629
7630finish:
7631    OSSafeRelease(classIterator);
7632    return;
7633}
7634
7635#if PRAGMA_MARK
7636#pragma mark User-Space Requests
7637#endif
7638/*********************************************************************
7639* XXX - this function is a big ugly mess
7640*********************************************************************/
7641/* static */
7642OSReturn
7643OSKext::handleRequest(
7644    host_priv_t     hostPriv,
7645    OSKextLogSpec   clientLogFilter,
7646    char          * requestBuffer,
7647    uint32_t        requestLength,
7648    char         ** responseOut,
7649    uint32_t      * responseLengthOut,
7650    char         ** logInfoOut,
7651    uint32_t      * logInfoLengthOut)
7652{
7653    OSReturn       result             = kOSReturnError;
7654    kern_return_t  kmem_result        = KERN_FAILURE;
7655
7656    char         * response           = NULL;  // returned by reference
7657    uint32_t       responseLength     = 0;
7658
7659    OSObject     * parsedXML          = NULL;  // must release
7660    OSDictionary * requestDict        = NULL;  // do not release
7661    OSString     * errorString        = NULL;  // must release
7662
7663    OSData       * responseData       = NULL;  // must release
7664    OSObject     * responseObject     = NULL;  // must release
7665
7666    OSSerialize  * serializer         = NULL;  // must release
7667
7668    OSArray      * logInfoArray       = NULL;  // must release
7669
7670    OSString     * predicate          = NULL;  // do not release
7671    OSString     * kextIdentifier     = NULL;  // do not release
7672    OSArray      * kextIdentifiers    = NULL;  // do not release
7673    OSKext       * theKext            = NULL;  // do not release
7674    OSBoolean    * boolArg            = NULL;  // do not release
7675
7676    bool           hideTheSlide       = false;
7677
7678    IORecursiveLockLock(sKextLock);
7679
7680    if (responseOut) {
7681        *responseOut = NULL;
7682        *responseLengthOut = 0;
7683    }
7684    if (logInfoOut) {
7685        *logInfoOut = NULL;
7686        *logInfoLengthOut = 0;
7687    }
7688
7689    OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
7690
7691   /* XML must be nul-terminated.
7692    */
7693    if (requestBuffer[requestLength - 1] != '\0') {
7694        OSKextLog(/* kext */ NULL,
7695            kOSKextLogErrorLevel |
7696            kOSKextLogIPCFlag,
7697            "Invalid request from user space (not nul-terminated).");
7698        result = kOSKextReturnBadData;
7699        goto finish;
7700    }
7701    parsedXML = OSUnserializeXML((const char *)requestBuffer, &errorString);
7702    if (parsedXML) {
7703        requestDict = OSDynamicCast(OSDictionary, parsedXML);
7704    }
7705    if (!requestDict) {
7706        const char * errorCString = "(unknown error)";
7707
7708        if (errorString && errorString->getCStringNoCopy()) {
7709            errorCString = errorString->getCStringNoCopy();
7710        } else if (parsedXML) {
7711            errorCString = "not a dictionary";
7712        }
7713        OSKextLog(/* kext */ NULL,
7714            kOSKextLogErrorLevel |
7715            kOSKextLogIPCFlag,
7716            "Error unserializing request from user space: %s.",
7717            errorCString);
7718        result = kOSKextReturnSerialization;
7719        goto finish;
7720    }
7721
7722    predicate = _OSKextGetRequestPredicate(requestDict);
7723    if (!predicate) {
7724        OSKextLog(/* kext */ NULL,
7725            kOSKextLogErrorLevel |
7726            kOSKextLogIPCFlag,
7727            "Recieved kext request from user space with no predicate.");
7728        result = kOSKextReturnInvalidArgument;
7729        goto finish;
7730    }
7731
7732    OSKextLog(/* kext */ NULL,
7733        kOSKextLogDebugLevel |
7734        kOSKextLogIPCFlag,
7735        "Received '%s' request from user space.",
7736        predicate->getCStringNoCopy());
7737
7738    result = kOSKextReturnNotPrivileged;
7739    if (hostPriv == HOST_PRIV_NULL) {
7740        if (sPrelinkBoot) {
7741            hideTheSlide = true;
7742            /* must be root to use these kext requests */
7743            if (predicate->isEqualTo(kKextRequestPredicateGetKernelLoadAddress) ||
7744                predicate->isEqualTo(kKextRequestPredicateUnload) ||
7745                predicate->isEqualTo(kKextRequestPredicateStart) ||
7746                predicate->isEqualTo(kKextRequestPredicateStop) ) {
7747                OSKextLog(/* kext */ NULL,
7748                          kOSKextLogErrorLevel |
7749                          kOSKextLogIPCFlag,
7750                          "Access Failure - must be root user.");
7751                goto finish;
7752            }
7753       }
7754    }
7755
7756   /* Get common args in anticipation of use.
7757    */
7758    kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
7759        requestDict, kKextRequestArgumentBundleIdentifierKey));
7760    kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
7761        requestDict, kKextRequestArgumentBundleIdentifierKey));
7762    if (kextIdentifier) {
7763        theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
7764    }
7765    boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
7766        requestDict, kKextRequestArgumentValueKey));
7767
7768    result = kOSKextReturnInvalidArgument;
7769
7770    if (predicate->isEqualTo(kKextRequestPredicateStart)) {
7771        if (!kextIdentifier) {
7772            OSKextLog(/* kext */ NULL,
7773                kOSKextLogErrorLevel |
7774                kOSKextLogIPCFlag,
7775                "Invalid arguments to kext start request.");
7776        } else if (!theKext) {
7777            OSKextLog(/* kext */ NULL,
7778                kOSKextLogErrorLevel |
7779                kOSKextLogIPCFlag,
7780                "Kext %s not found for start request.",
7781                kextIdentifier->getCStringNoCopy());
7782            result = kOSKextReturnNotFound;
7783        } else {
7784            result = theKext->start();
7785        }
7786
7787    } else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
7788        if (!kextIdentifier) {
7789            OSKextLog(/* kext */ NULL,
7790                kOSKextLogErrorLevel |
7791                kOSKextLogIPCFlag,
7792                "Invalid arguments to kext stop request.");
7793        } else if (!theKext) {
7794            OSKextLog(/* kext */ NULL,
7795                kOSKextLogErrorLevel |
7796                kOSKextLogIPCFlag,
7797                "Kext %s not found for stop request.",
7798                kextIdentifier->getCStringNoCopy());
7799            result = kOSKextReturnNotFound;
7800        } else {
7801            result = theKext->stop();
7802        }
7803
7804    } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
7805        if (!kextIdentifier) {
7806            OSKextLog(/* kext */ NULL,
7807                kOSKextLogErrorLevel |
7808                kOSKextLogIPCFlag,
7809                "Invalid arguments to kext unload request.");
7810        } else if (!theKext) {
7811            OSKextLog(/* kext */ NULL,
7812                kOSKextLogErrorLevel |
7813                kOSKextLogIPCFlag,
7814                "Kext %s not found for unload request.",
7815                kextIdentifier->getCStringNoCopy());
7816            result = kOSKextReturnNotFound;
7817        } else {
7818            OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
7819                _OSKextGetRequestArgument(requestDict,
7820                    kKextRequestArgumentTerminateIOServicesKey));
7821            result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
7822        }
7823
7824    } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
7825        result = OSKext::dispatchResource(requestDict);
7826
7827    } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
7828        OSBoolean    * delayAutounloadBool = NULL;
7829        OSObject     * infoKeysRaw         = NULL;
7830        OSArray      * infoKeys            = NULL;
7831        uint32_t       infoKeysCount       = 0;
7832
7833        delayAutounloadBool = OSDynamicCast(OSBoolean,
7834            _OSKextGetRequestArgument(requestDict,
7835                kKextRequestArgumentDelayAutounloadKey));
7836
7837       /* If asked to delay autounload, reset the timer if it's currently set.
7838        * (That is, don't schedule an unload if one isn't already pending.
7839        */
7840        if (delayAutounloadBool == kOSBooleanTrue) {
7841            OSKext::considerUnloads(/* rescheduleOnly? */ true);
7842        }
7843
7844        infoKeysRaw = _OSKextGetRequestArgument(requestDict,
7845                kKextRequestArgumentInfoKeysKey);
7846        infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
7847        if (infoKeysRaw && !infoKeys) {
7848            OSKextLog(/* kext */ NULL,
7849                kOSKextLogErrorLevel |
7850                kOSKextLogIPCFlag,
7851                "Invalid arguments to kext info request.");
7852            goto finish;
7853        }
7854
7855        if (infoKeys) {
7856            infoKeysCount = infoKeys->getCount();
7857            for (uint32_t i = 0; i < infoKeysCount; i++) {
7858                if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
7859                    OSKextLog(/* kext */ NULL,
7860                        kOSKextLogErrorLevel |
7861                        kOSKextLogIPCFlag,
7862                        "Invalid arguments to kext info request.");
7863                    goto finish;
7864                }
7865            }
7866        }
7867
7868        responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
7869        if (!responseObject) {
7870            result = kOSKextReturnInternalError;
7871        } else {
7872            OSKextLog(/* kext */ NULL,
7873                kOSKextLogDebugLevel |
7874                kOSKextLogIPCFlag,
7875                "Returning loaded kext info.");
7876            result = kOSReturnSuccess;
7877        }
7878#if !SECURE_KERNEL
7879    } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelLoadAddress)) {
7880        OSNumber * addressNum = NULL;  // released as responseObject
7881        unsigned long long unslid_addr = 0;
7882        kernel_segment_command_t * textseg = getsegbyname("__TEXT");
7883
7884        if (!textseg) {
7885            OSKextLog(/* kext */ NULL,
7886                kOSKextLogErrorLevel |
7887                kOSKextLogGeneralFlag | kOSKextLogIPCFlag,
7888                "Can't find text segment for kernel load address.");
7889            result = kOSReturnError;
7890            goto finish;
7891        }
7892
7893        unslid_addr = VM_KERNEL_UNSLIDE(textseg->vmaddr);
7894
7895        OSKextLog(/* kext */ NULL,
7896            kOSKextLogDebugLevel |
7897            kOSKextLogIPCFlag,
7898            "Returning kernel load address 0x%llx.",
7899            (unsigned long long) unslid_addr);
7900
7901        addressNum = OSNumber::withNumber((long long unsigned int) unslid_addr,
7902            8 * sizeof(long long unsigned int));
7903        responseObject = addressNum;
7904        result = kOSReturnSuccess;
7905#endif
7906    } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
7907
7908       /* Hand the current sKernelRequests array to the caller
7909        * (who must release it), and make a new one.
7910        */
7911        responseObject = sKernelRequests;
7912        sKernelRequests = OSArray::withCapacity(0);
7913        sPostedKextLoadIdentifiers->flushCollection();
7914        OSKextLog(/* kext */ NULL,
7915            kOSKextLogDebugLevel |
7916            kOSKextLogIPCFlag,
7917            "Returning kernel requests.");
7918        result = kOSReturnSuccess;
7919
7920    } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
7921
7922        /* Return the set of all requested bundle identifiers */
7923        responseObject = sAllKextLoadIdentifiers;
7924        responseObject->retain();
7925        OSKextLog(/* kext */ NULL,
7926            kOSKextLogDebugLevel |
7927            kOSKextLogIPCFlag,
7928            "Returning load requests.");
7929        result = kOSReturnSuccess;
7930    }
7931    else {
7932        OSKextLog(/* kext */ NULL,
7933                  kOSKextLogDebugLevel |
7934                  kOSKextLogIPCFlag,
7935                  "Received '%s' invalid request from user space.",
7936                  predicate->getCStringNoCopy());
7937        goto finish;
7938    }
7939
7940   /**********
7941    * Now we have handle the request, or not. Gather up the response & logging
7942    * info to ship to user space.
7943    *********/
7944
7945   /* Note: Nothing in OSKext is supposed to retain requestDict,
7946    * but you never know....
7947    */
7948    if (requestDict->getRetainCount() > 1) {
7949        OSKextLog(/* kext */ NULL,
7950            kOSKextLogWarningLevel |
7951            kOSKextLogIPCFlag,
7952            "Request from user space still retained by a kext; "
7953            "probable memory leak.");
7954    }
7955
7956    if (responseData && responseObject) {
7957        OSKextLog(/* kext */ NULL,
7958            kOSKextLogErrorLevel |
7959            kOSKextLogIPCFlag,
7960            "Mistakenly generated both data & plist responses to user request "
7961            "(returning only data).");
7962    }
7963
7964    if (responseData && responseData->getLength() && responseOut) {
7965
7966        response = (char *)responseData->getBytesNoCopy();
7967        responseLength = responseData->getLength();
7968    } else if (responseOut && responseObject) {
7969        serializer = OSSerialize::withCapacity(0);
7970        if (!serializer) {
7971            result = kOSKextReturnNoMemory;
7972            goto finish;
7973        }
7974
7975        if (!responseObject->serialize(serializer)) {
7976            OSKextLog(/* kext */ NULL,
7977                kOSKextLogErrorLevel |
7978                kOSKextLogIPCFlag,
7979                "Failed to serialize response to request from user space.");
7980            result = kOSKextReturnSerialization;
7981            goto finish;
7982        }
7983
7984        response = (char *)serializer->text();
7985        responseLength = serializer->getLength();
7986    }
7987
7988    if (responseOut && response) {
7989        char * buffer;
7990
7991       /* This kmem_alloc sets the return value of the function.
7992        */
7993        kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
7994            round_page(responseLength));
7995        if (kmem_result != KERN_SUCCESS) {
7996            OSKextLog(/* kext */ NULL,
7997                kOSKextLogErrorLevel |
7998                kOSKextLogIPCFlag,
7999                "Failed to copy response to request from user space.");
8000            result = kmem_result;
8001            goto finish;
8002        } else {
8003            /* 11981737 - clear uninitialized data in last page */
8004            bzero((void *)(buffer + responseLength),
8005                  (round_page(responseLength) - responseLength));
8006            memcpy(buffer, response, responseLength);
8007            *responseOut = buffer;
8008            *responseLengthOut = responseLength;
8009        }
8010    }
8011
8012finish:
8013
8014   /* Gather up the collected log messages for user space. Any messages
8015    * messages past this call will not make it up as log messages but
8016    * will be in the system log. Note that we ignore the return of the
8017    * serialize; it has no bearing on the operation at hand even if we
8018    * fail to get the log messages.
8019    */
8020    logInfoArray = OSKext::clearUserSpaceLogFilter();
8021
8022    if (logInfoArray && logInfoOut && logInfoLengthOut) {
8023        (void)OSKext::serializeLogInfo(logInfoArray,
8024            logInfoOut, logInfoLengthOut);
8025    }
8026
8027    IORecursiveLockUnlock(sKextLock);
8028
8029    OSSafeRelease(parsedXML);
8030    OSSafeRelease(errorString);
8031    OSSafeRelease(responseData);
8032    OSSafeRelease(responseObject);
8033    OSSafeRelease(serializer);
8034    OSSafeRelease(logInfoArray);
8035
8036    return result;
8037}
8038
8039/*********************************************************************
8040*********************************************************************/
8041/* static */
8042OSDictionary *
8043OSKext::copyLoadedKextInfo(
8044    OSArray * kextIdentifiers,
8045    OSArray * infoKeys)
8046{
8047    OSDictionary * result = NULL;
8048    OSDictionary * kextInfo = NULL;  // must release
8049    uint32_t       count, i;
8050    uint32_t       idCount = 0;
8051    uint32_t       idIndex = 0;
8052
8053    IORecursiveLockLock(sKextLock);
8054
8055   /* Empty list of bundle ids is equivalent to no list (get all).
8056    */
8057    if (kextIdentifiers && !kextIdentifiers->getCount()) {
8058        kextIdentifiers = NULL;
8059    } else if (kextIdentifiers) {
8060        idCount = kextIdentifiers->getCount();
8061    }
8062
8063   /* Same for keys.
8064    */
8065    if (infoKeys && !infoKeys->getCount()) {
8066        infoKeys = NULL;
8067    }
8068
8069    count = sLoadedKexts->getCount();
8070    result = OSDictionary::withCapacity(count);
8071    if (!result) {
8072        goto finish;
8073    }
8074    for (i = 0; i < count; i++) {
8075        OSKext   * thisKext     = NULL;  // do not release
8076        Boolean    includeThis  = true;
8077
8078        if (kextInfo) {
8079            kextInfo->release();
8080            kextInfo = NULL;
8081        }
8082        thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
8083        if (!thisKext) {
8084            continue;
8085        }
8086
8087       /* Skip current kext if we have a list of bundle IDs and
8088        * it isn't in the list.
8089        */
8090        if (kextIdentifiers) {
8091            const OSString * thisKextID = thisKext->getIdentifier();
8092
8093            includeThis = false;
8094
8095            for (idIndex = 0; idIndex < idCount; idIndex++) {
8096                const OSString * thisRequestID = OSDynamicCast(OSString,
8097                    kextIdentifiers->getObject(idIndex));
8098                if (thisKextID->isEqualTo(thisRequestID)) {
8099                    includeThis = true;
8100                    break;
8101                }
8102            }
8103        }
8104
8105        if (!includeThis) {
8106            continue;
8107        }
8108
8109        kextInfo = thisKext->copyInfo(infoKeys);
8110        if (kextInfo) {
8111            result->setObject(thisKext->getIdentifier(), kextInfo);
8112        }
8113    }
8114
8115finish:
8116    IORecursiveLockUnlock(sKextLock);
8117
8118    if (kextInfo) kextInfo->release();
8119
8120    return result;
8121}
8122
8123/*********************************************************************
8124* Any info that needs to do allocations must goto finish on alloc
8125* failure. Info that is just a lookup should just not set the object
8126* if the info does not exist.
8127*********************************************************************/
8128#define _OSKextLoadInfoDictCapacity   (12)
8129
8130OSDictionary *
8131OSKext::copyInfo(OSArray * infoKeys)
8132{
8133    OSDictionary         * result                      = NULL;
8134    bool                   success                     = false;
8135    OSData               * headerData                  = NULL;  // must release
8136    OSNumber             * cpuTypeNumber               = NULL;  // must release
8137    OSNumber             * cpuSubtypeNumber            = NULL;  // must release
8138    OSString             * versionString               = NULL;  // do not release
8139    uint32_t               executablePathCStringSize = 0;
8140    char                 * executablePathCString       = NULL;  // must release
8141    OSString             * executablePathString        = NULL;  // must release
8142    OSData               * uuid                        = NULL;  // must release
8143    OSNumber             * scratchNumber               = NULL;  // must release
8144    OSArray              * dependencyLoadTags          = NULL;  // must release
8145    OSCollectionIterator * metaClassIterator           = NULL;  // must release
8146    OSArray              * metaClassInfo               = NULL;  // must release
8147    OSDictionary         * metaClassDict               = NULL;  // must release
8148    OSMetaClass          * thisMetaClass               = NULL;  // do not release
8149    OSString             * metaClassName               = NULL;  // must release
8150    OSString             * superclassName              = NULL;  // must release
8151    uint32_t               count, i;
8152
8153    result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
8154    if (!result) {
8155        goto finish;
8156    }
8157
8158
8159   /* Empty keys means no keys, but NULL is quicker to check.
8160    */
8161    if (infoKeys && !infoKeys->getCount()) {
8162        infoKeys = NULL;
8163    }
8164
8165   /* Headers, CPU type, and CPU subtype.
8166    */
8167    if (!infoKeys ||
8168        _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
8169        _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
8170        _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey))
8171    {
8172
8173        if (linkedExecutable && !isInterface()) {
8174
8175            kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
8176                linkedExecutable->getBytesNoCopy();
8177
8178            if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
8179                kernel_mach_header_t *  temp_kext_mach_hdr;
8180                struct load_command *   lcp;
8181
8182                headerData = OSData::withBytes(kext_mach_hdr,
8183                    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
8184                if (!headerData) {
8185                    goto finish;
8186                }
8187
8188                // unslide any vmaddrs we return to userspace - 10726716
8189               temp_kext_mach_hdr = (kernel_mach_header_t *)
8190                    headerData->getBytesNoCopy();
8191                if (temp_kext_mach_hdr == NULL) {
8192                    goto finish;
8193                }
8194
8195                lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
8196                for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
8197                    if (lcp->cmd == LC_SEGMENT_KERNEL) {
8198                        kernel_segment_command_t *  segp;
8199                        kernel_section_t *          secp;
8200
8201                        segp = (kernel_segment_command_t *) lcp;
8202                        // 10543468 - if we jettisoned __LINKEDIT clear size info
8203                        if (flags.jettisonLinkeditSeg) {
8204                            if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
8205                                segp->vmsize = 0;
8206                                segp->fileoff = 0;
8207                                segp->filesize = 0;
8208                            }
8209                        }
8210#if 0
8211                        OSKextLog(/* kext */ NULL,
8212                                  kOSKextLogErrorLevel |
8213                                  kOSKextLogGeneralFlag,
8214                                  "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
8215                                  __FUNCTION__, segp->segname, segp->vmaddr,
8216                                  VM_KERNEL_UNSLIDE(segp->vmaddr),
8217                                  segp->vmsize, segp->nsects);
8218#endif
8219                        segp->vmaddr = VM_KERNEL_UNSLIDE(segp->vmaddr);
8220
8221                        for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
8222                            secp->addr = VM_KERNEL_UNSLIDE(secp->addr);
8223                        }
8224                   }
8225                    lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
8226                }
8227                result->setObject(kOSBundleMachOHeadersKey, headerData);
8228            }
8229
8230            if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
8231                cpuTypeNumber = OSNumber::withNumber(
8232                    (uint64_t) kext_mach_hdr->cputype,
8233                    8 * sizeof(kext_mach_hdr->cputype));
8234                if (!cpuTypeNumber) {
8235                    goto finish;
8236                }
8237                result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber);
8238            }
8239
8240            if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
8241                cpuSubtypeNumber = OSNumber::withNumber(
8242                    (uint64_t) kext_mach_hdr->cpusubtype,
8243                    8 * sizeof(kext_mach_hdr->cpusubtype));
8244                if (!cpuSubtypeNumber) {
8245                    goto finish;
8246                }
8247                result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber);
8248            }
8249        }
8250    }
8251
8252   /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
8253    */
8254    result->setObject(kCFBundleIdentifierKey, bundleID);
8255
8256   /* CFBundleVersion.
8257    */
8258    if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
8259        versionString = OSDynamicCast(OSString,
8260            getPropertyForHostArch(kCFBundleVersionKey));
8261        if (versionString) {
8262            result->setObject(kCFBundleVersionKey, versionString);
8263        }
8264    }
8265
8266   /* OSBundleCompatibleVersion.
8267    */
8268    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
8269        versionString = OSDynamicCast(OSString,
8270            getPropertyForHostArch(kOSBundleCompatibleVersionKey));
8271        if (versionString) {
8272            result->setObject(kOSBundleCompatibleVersionKey, versionString);
8273        }
8274    }
8275
8276   /* Path.
8277    */
8278    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
8279        if (path) {
8280            result->setObject(kOSBundlePathKey, path);
8281        }
8282    }
8283
8284
8285   /* OSBundleExecutablePath.
8286    */
8287    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
8288         if (path && executableRelPath) {
8289
8290            uint32_t pathLength = path->getLength();  // gets incremented below
8291
8292            // +1 for slash, +1 for \0
8293            executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
8294
8295            executablePathCString = (char *)kalloc((executablePathCStringSize) *
8296                sizeof(char)); // +1 for \0
8297            if (!executablePathCString) {
8298                goto finish;
8299            }
8300            strlcpy(executablePathCString, path->getCStringNoCopy(),
8301                executablePathCStringSize);
8302            executablePathCString[pathLength++] = '/';
8303            executablePathCString[pathLength++] = '\0';
8304            strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
8305                executablePathCStringSize);
8306
8307            executablePathString = OSString::withCString(executablePathCString);
8308
8309            if (!executablePathCString) {
8310                goto finish;
8311            }
8312
8313            result->setObject(kOSBundleExecutablePathKey, executablePathString);
8314        }
8315    }
8316
8317   /* UUID, if the kext has one.
8318    */
8319    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
8320        uuid = copyUUID();
8321        if (uuid) {
8322            result->setObject(kOSBundleUUIDKey, uuid);
8323        }
8324    }
8325
8326   /*****
8327    * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
8328    */
8329    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
8330        result->setObject(kOSKernelResourceKey,
8331            isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
8332    }
8333
8334    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
8335        result->setObject(kOSBundleIsInterfaceKey,
8336            isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
8337    }
8338
8339    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
8340        result->setObject(kOSBundlePrelinkedKey,
8341            isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
8342    }
8343
8344    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
8345        result->setObject(kOSBundleStartedKey,
8346            isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
8347    }
8348
8349   /* LoadTag (Index).
8350    */
8351    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
8352        scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
8353            /* numBits */ 8 * sizeof(loadTag));
8354        if (!scratchNumber) {
8355            goto finish;
8356        }
8357        result->setObject(kOSBundleLoadTagKey, scratchNumber);
8358        OSSafeReleaseNULL(scratchNumber);
8359    }
8360
8361   /* LoadAddress, LoadSize.
8362    */
8363    if (!infoKeys ||
8364        _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
8365        _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
8366        _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey))
8367    {
8368        if (isInterface() || linkedExecutable) {
8369           /* These go to userspace via serialization, so we don't want any doubts
8370            * about their size.
8371            */
8372            uint64_t    loadAddress = 0;
8373            uint32_t    loadSize    = 0;
8374            uint32_t    wiredSize   = 0;
8375
8376           /* Interfaces always report 0 load address & size.
8377            * Just the way they roll.
8378            *
8379            * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
8380            * xxx - shouldn't have one!
8381            */
8382            if (linkedExecutable /* && !isInterface() */) {
8383                loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
8384                loadAddress = VM_KERNEL_UNSLIDE(loadAddress);
8385                loadSize = linkedExecutable->getLength();
8386
8387               /* If we have a kmod_info struct, calculated the wired size
8388                * from that. Otherwise it's the full load size.
8389                */
8390                if (kmod_info) {
8391                    wiredSize = loadSize - kmod_info->hdr_size;
8392                } else {
8393                    wiredSize = loadSize;
8394                }
8395            }
8396
8397            if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
8398                scratchNumber = OSNumber::withNumber(
8399                    (unsigned long long)(loadAddress),
8400                    /* numBits */ 8 * sizeof(loadAddress));
8401                if (!scratchNumber) {
8402                    goto finish;
8403                }
8404                result->setObject(kOSBundleLoadAddressKey, scratchNumber);
8405                OSSafeReleaseNULL(scratchNumber);
8406            }
8407            if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
8408                scratchNumber = OSNumber::withNumber(
8409                    (unsigned long long)(loadSize),
8410                    /* numBits */ 8 * sizeof(loadSize));
8411                if (!scratchNumber) {
8412                    goto finish;
8413                }
8414                result->setObject(kOSBundleLoadSizeKey, scratchNumber);
8415                OSSafeReleaseNULL(scratchNumber);
8416            }
8417            if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
8418                scratchNumber = OSNumber::withNumber(
8419                    (unsigned long long)(wiredSize),
8420                    /* numBits */ 8 * sizeof(wiredSize));
8421                if (!scratchNumber) {
8422                    goto finish;
8423                }
8424                result->setObject(kOSBundleWiredSizeKey, scratchNumber);
8425                OSSafeReleaseNULL(scratchNumber);
8426            }
8427        }
8428    }
8429
8430   /* OSBundleDependencies. In descending order for
8431    * easy compatibility with kextstat(8).
8432    */
8433    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
8434        if ((count = getNumDependencies())) {
8435            dependencyLoadTags = OSArray::withCapacity(count);
8436            result->setObject(kOSBundleDependenciesKey, dependencyLoadTags);
8437
8438            i = count - 1;
8439            do {
8440                OSKext * dependency = OSDynamicCast(OSKext,
8441                    dependencies->getObject(i));
8442
8443                OSSafeReleaseNULL(scratchNumber);
8444
8445                if (!dependency) {
8446                    continue;
8447                }
8448                scratchNumber = OSNumber::withNumber(
8449                    (unsigned long long)dependency->getLoadTag(),
8450                    /* numBits*/ 8 * sizeof(loadTag));
8451                if (!scratchNumber) {
8452                    goto finish;
8453                }
8454                dependencyLoadTags->setObject(scratchNumber);
8455            } while (i--);
8456        }
8457    }
8458
8459    OSSafeReleaseNULL(scratchNumber);
8460
8461   /* OSBundleMetaClasses.
8462    */
8463    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
8464        if (metaClasses && metaClasses->getCount()) {
8465            metaClassIterator = OSCollectionIterator::withCollection(metaClasses);
8466            metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
8467            if (!metaClassIterator || !metaClassInfo) {
8468                goto finish;
8469            }
8470            result->setObject(kOSBundleClassesKey, metaClassInfo);
8471
8472            while ( (thisMetaClass = OSDynamicCast(OSMetaClass,
8473                metaClassIterator->getNextObject())) ) {
8474
8475                OSSafeReleaseNULL(metaClassDict);
8476                OSSafeReleaseNULL(scratchNumber);
8477                OSSafeReleaseNULL(metaClassName);
8478                OSSafeReleaseNULL(superclassName);
8479
8480                metaClassDict = OSDictionary::withCapacity(3);
8481                if (!metaClassDict) {
8482                    goto finish;
8483                }
8484
8485                metaClassName = OSString::withCString(thisMetaClass->getClassName());
8486                if (thisMetaClass->getSuperClass()) {
8487                    superclassName = OSString::withCString(
8488                        thisMetaClass->getSuperClass()->getClassName());
8489                }
8490                scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
8491                    8 * sizeof(unsigned int));
8492
8493               /* Bail if any of the essentials is missing. The root class lacks a superclass,
8494                * of course.
8495                */
8496                if (!metaClassDict || !metaClassName || !scratchNumber) {
8497                    goto finish;
8498                }
8499
8500                metaClassInfo->setObject(metaClassDict);
8501                metaClassDict->setObject(kOSMetaClassNameKey, metaClassName);
8502                if (superclassName) {
8503                    metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName);
8504                }
8505                metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber);
8506            }
8507        }
8508    }
8509
8510   /* OSBundleRetainCount.
8511    */
8512    if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
8513        OSSafeReleaseNULL(scratchNumber);
8514        {
8515            int kextRetainCount = getRetainCount() - 1;
8516            if (isLoaded()) {
8517                kextRetainCount--;
8518            }
8519            scratchNumber = OSNumber::withNumber(
8520                (int)kextRetainCount,
8521                /* numBits*/ 8 * sizeof(int));
8522            if (scratchNumber) {
8523                result->setObject(kOSBundleRetainCountKey, scratchNumber);
8524            }
8525        }
8526    }
8527
8528    success = true;
8529
8530finish:
8531    OSSafeRelease(headerData);
8532    OSSafeRelease(cpuTypeNumber);
8533    OSSafeRelease(cpuSubtypeNumber);
8534    OSSafeRelease(executablePathString);
8535    if (executablePathString) kfree(executablePathCString, executablePathCStringSize);
8536    OSSafeRelease(uuid);
8537    OSSafeRelease(scratchNumber);
8538    OSSafeRelease(dependencyLoadTags);
8539    OSSafeRelease(metaClassIterator);
8540    OSSafeRelease(metaClassInfo);
8541    OSSafeRelease(metaClassDict);
8542    OSSafeRelease(metaClassName);
8543    OSSafeRelease(superclassName);
8544    if (!success) {
8545        OSSafeReleaseNULL(result);
8546    }
8547    return result;
8548}
8549
8550/*********************************************************************
8551 *********************************************************************/
8552/* static */
8553OSReturn
8554OSKext::requestResource(
8555    const char                    * kextIdentifierCString,
8556    const char                    * resourceNameCString,
8557    OSKextRequestResourceCallback   callback,
8558    void                          * context,
8559    OSKextRequestTag              * requestTagOut)
8560{
8561    OSReturn           result          = kOSReturnError;
8562    OSKext           * callbackKext    = NULL;  // must release (looked up)
8563
8564    OSKextRequestTag   requestTag      = -1;
8565    OSNumber         * requestTagNum   = NULL;  // must release
8566
8567    OSDictionary     * requestDict     = NULL;  // must release
8568    OSString         * kextIdentifier  = NULL;  // must release
8569    OSString         * resourceName    = NULL;  // must release
8570
8571    OSDictionary     * callbackRecord  = NULL;  // must release
8572    OSData           * callbackWrapper = NULL;  // must release
8573
8574    OSData           * contextWrapper  = NULL;  // must release
8575
8576    IORecursiveLockLock(sKextLock);
8577
8578    if (requestTagOut) {
8579        *requestTagOut = kOSKextRequestTagInvalid;
8580    }
8581
8582    /* If requests to user space are disabled, don't go any further */
8583    if (!sKernelRequestsEnabled) {
8584        OSKextLog(/* kext */ NULL,
8585            kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8586            "Can't request resource %s for %s - requests to user space are disabled.",
8587            resourceNameCString,
8588            kextIdentifierCString);
8589        result = kOSKextReturnDisabled;
8590        goto finish;
8591    }
8592
8593    if (!kextIdentifierCString || !resourceNameCString || !callback) {
8594        result = kOSKextReturnInvalidArgument;
8595        goto finish;
8596    }
8597
8598    callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
8599    if (!callbackKext) {
8600        OSKextLog(/* kext */ NULL,
8601            kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8602            "Resource request has bad callback address.");
8603        result = kOSKextReturnInvalidArgument;
8604        goto finish;
8605    }
8606    if (!callbackKext->flags.starting && !callbackKext->flags.started) {
8607        OSKextLog(/* kext */ NULL,
8608            kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8609            "Resource request callback is in a kext that is not started.");
8610        result = kOSKextReturnInvalidArgument;
8611        goto finish;
8612    }
8613
8614   /* Do not allow any new requests to be made on a kext that is unloading.
8615    */
8616    if (callbackKext->flags.stopping) {
8617        result = kOSKextReturnStopping;
8618        goto finish;
8619    }
8620
8621   /* If we're wrapped the next available request tag around to the negative
8622    * numbers, we can't service any more requests.
8623    */
8624    if (sNextRequestTag == kOSKextRequestTagInvalid) {
8625        OSKextLog(/* kext */ NULL,
8626            kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8627            "No more request tags available; restart required.");
8628        result = kOSKextReturnNoResources;
8629        goto finish;
8630    }
8631    requestTag = sNextRequestTag++;
8632
8633    result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
8634        &requestDict);
8635    if (result != kOSReturnSuccess) {
8636        goto finish;
8637    }
8638
8639    kextIdentifier = OSString::withCString(kextIdentifierCString);
8640    resourceName   = OSString::withCString(resourceNameCString);
8641    requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
8642        8 * sizeof(requestTag));
8643    if (!kextIdentifier ||
8644        !resourceName   ||
8645        !requestTagNum  ||
8646        !_OSKextSetRequestArgument(requestDict,
8647            kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
8648        !_OSKextSetRequestArgument(requestDict,
8649            kKextRequestArgumentNameKey, resourceName) ||
8650        !_OSKextSetRequestArgument(requestDict,
8651            kKextRequestArgumentRequestTagKey, requestTagNum)) {
8652
8653        result = kOSKextReturnNoMemory;
8654        goto finish;
8655    }
8656
8657    callbackRecord = OSDynamicCast(OSDictionary, requestDict->copyCollection());
8658    if (!callbackRecord) {
8659        result = kOSKextReturnNoMemory;
8660        goto finish;
8661    }
8662    // we validate callback address at call time
8663    callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *));
8664    if (context) {
8665        contextWrapper = OSData::withBytes((void *)&context, sizeof(void *));
8666    }
8667    if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord,
8668            kKextRequestArgumentCallbackKey, callbackWrapper)) {
8669
8670        result = kOSKextReturnNoMemory;
8671        goto finish;
8672    }
8673
8674    if (context) {
8675        if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord,
8676            kKextRequestArgumentContextKey, contextWrapper)) {
8677
8678            result = kOSKextReturnNoMemory;
8679            goto finish;
8680        }
8681    }
8682
8683   /* Only post the requests after all the other potential failure points
8684    * have been passed.
8685    */
8686    if (!sKernelRequests->setObject(requestDict) ||
8687        !sRequestCallbackRecords->setObject(callbackRecord)) {
8688
8689        result = kOSKextReturnNoMemory;
8690        goto finish;
8691    }
8692
8693    OSKext::pingKextd();
8694
8695    result = kOSReturnSuccess;
8696    if (requestTagOut) {
8697        *requestTagOut = requestTag;
8698    }
8699
8700finish:
8701
8702   /* If we didn't succeed, yank the request & callback
8703    * from their holding arrays.
8704    */
8705    if (result != kOSReturnSuccess) {
8706        unsigned int index;
8707
8708        index = sKernelRequests->getNextIndexOfObject(requestDict, 0);
8709        if (index != (unsigned int)-1) {
8710            sKernelRequests->removeObject(index);
8711        }
8712        index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord, 0);
8713        if (index != (unsigned int)-1) {
8714            sRequestCallbackRecords->removeObject(index);
8715        }
8716    }
8717
8718    OSKext::considerUnloads(/* rescheduleOnly? */ true);
8719
8720    IORecursiveLockUnlock(sKextLock);
8721
8722    if (callbackKext)    callbackKext->release();
8723    if (requestTagNum)   requestTagNum->release();
8724
8725    if (requestDict)     requestDict->release();
8726    if (kextIdentifier)  kextIdentifier->release();
8727    if (resourceName)    resourceName->release();
8728
8729    if (callbackRecord)  callbackRecord->release();
8730    if (callbackWrapper) callbackWrapper->release();
8731    if (contextWrapper)  contextWrapper->release();
8732
8733    return result;
8734}
8735
8736/*********************************************************************
8737* Assumes sKextLock is held.
8738*********************************************************************/
8739/* static */
8740OSReturn
8741OSKext::dequeueCallbackForRequestTag(
8742    OSKextRequestTag    requestTag,
8743    OSDictionary     ** callbackRecordOut)
8744{
8745    OSReturn   result = kOSReturnError;
8746    OSNumber * requestTagNum  = NULL;  // must release
8747
8748    requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
8749        8 * sizeof(requestTag));
8750    if (!requestTagNum) {
8751        goto finish;
8752    }
8753
8754    result = OSKext::dequeueCallbackForRequestTag(requestTagNum,
8755        callbackRecordOut);
8756
8757finish:
8758    OSSafeRelease(requestTagNum);
8759
8760    return result;
8761}
8762
8763/*********************************************************************
8764* Assumes sKextLock is held.
8765*********************************************************************/
8766/* static */
8767OSReturn
8768OSKext::dequeueCallbackForRequestTag(
8769    OSNumber     *    requestTagNum,
8770    OSDictionary ** callbackRecordOut)
8771{
8772    OSReturn        result          = kOSKextReturnInvalidArgument;
8773    OSDictionary  * callbackRecord  = NULL;  // retain if matched!
8774    OSNumber      * callbackTagNum  = NULL;  // do not release
8775    unsigned int    count, i;
8776
8777    result = kOSReturnError;
8778    count = sRequestCallbackRecords->getCount();
8779    for (i = 0; i < count; i++) {
8780        callbackRecord = OSDynamicCast(OSDictionary,
8781            sRequestCallbackRecords->getObject(i));
8782        if (!callbackRecord) {
8783            goto finish;
8784        }
8785
8786       /* If we don't find a tag, we basically have a leak here. Maybe
8787        * we should just remove it.
8788        */
8789        callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
8790            callbackRecord, kKextRequestArgumentRequestTagKey));
8791        if (!callbackTagNum) {
8792            goto finish;
8793        }
8794
8795       /* We could be even more paranoid and check that all the incoming
8796        * args match what's in the callback record.
8797        */
8798        if (callbackTagNum->isEqualTo(requestTagNum)) {
8799            if (callbackRecordOut) {
8800                *callbackRecordOut = callbackRecord;
8801                callbackRecord->retain();
8802            }
8803            sRequestCallbackRecords->removeObject(i);
8804            result = kOSReturnSuccess;
8805            goto finish;
8806        }
8807    }
8808    result = kOSKextReturnNotFound;
8809
8810finish:
8811    return result;
8812}
8813
8814/*********************************************************************
8815* Assumes sKextLock is held.
8816*********************************************************************/
8817/* static */
8818OSReturn
8819OSKext::dispatchResource(OSDictionary * requestDict)
8820{
8821    OSReturn                        result          = kOSReturnError;
8822    OSDictionary                  * callbackRecord  = NULL;  // must release
8823    OSNumber                      * requestTag      = NULL;  // do not release
8824    OSNumber                      * requestResult   = NULL;  // do not release
8825    OSData                        * dataObj         = NULL;  // do not release
8826    uint32_t                        dataLength      = 0;
8827    const void                    * dataPtr         = NULL;  // do not free
8828    OSData                        * callbackWrapper = NULL;  // do not release
8829    OSKextRequestResourceCallback   callback        = NULL;
8830    OSData                        * contextWrapper  = NULL;  // do not release
8831    void                          * context         = NULL;  // do not free
8832    OSKext                        * callbackKext    = NULL;  // must release (looked up)
8833
8834   /* Get the args from the request. Right now we need the tag
8835    * to look up the callback record, and the result for invoking the callback.
8836    */
8837    requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
8838        kKextRequestArgumentRequestTagKey));
8839    requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
8840        kKextRequestArgumentResultKey));
8841    if (!requestTag || !requestResult) {
8842        result = kOSKextReturnInvalidArgument;
8843        goto finish;
8844    }
8845
8846   /* Look for a callback record matching this request's tag.
8847    */
8848    result = dequeueCallbackForRequestTag(requestTag, &callbackRecord);
8849    if (result != kOSReturnSuccess) {
8850        goto finish;
8851    }
8852
8853   /*****
8854    * Get the context pointer of the callback record (if there is one).
8855    */
8856    contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord,
8857        kKextRequestArgumentContextKey));
8858    context = _OSKextExtractPointer(contextWrapper);
8859    if (contextWrapper && !context) {
8860        goto finish;
8861    }
8862
8863    callbackWrapper = OSDynamicCast(OSData,
8864        _OSKextGetRequestArgument(callbackRecord,
8865            kKextRequestArgumentCallbackKey));
8866    callback = (OSKextRequestResourceCallback)
8867        _OSKextExtractPointer(callbackWrapper);
8868    if (!callback) {
8869        goto finish;
8870    }
8871
8872   /* Check for a data obj. We might not have one and that's ok, that means
8873    * we didn't find the requested resource, and we still have to tell the
8874    * caller that via the callback.
8875    */
8876    dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
8877        kKextRequestArgumentValueKey));
8878    if (dataObj) {
8879        dataPtr = dataObj->getBytesNoCopy();
8880        dataLength = dataObj->getLength();
8881    }
8882
8883    callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
8884    if (!callbackKext) {
8885        OSKextLog(/* kext */ NULL,
8886            kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8887            "Can't invoke callback for resource request; ");
8888        goto finish;
8889    }
8890    if (!callbackKext->flags.starting && !callbackKext->flags.started) {
8891        OSKextLog(/* kext */ NULL,
8892            kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8893            "Can't invoke kext resource callback; ");
8894        goto finish;
8895    }
8896
8897    (void)callback(requestTag->unsigned32BitValue(),
8898        (OSReturn)requestResult->unsigned32BitValue(),
8899        dataPtr, dataLength, context);
8900
8901    result = kOSReturnSuccess;
8902
8903finish:
8904    if (callbackKext)   callbackKext->release();
8905    if (callbackRecord) callbackRecord->release();
8906
8907    return result;
8908}
8909
8910/*********************************************************************
8911*********************************************************************/
8912/* static */
8913void
8914OSKext::invokeRequestCallback(
8915    OSDictionary * callbackRecord,
8916    OSReturn       callbackResult)
8917{
8918    OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
8919    OSNumber * resultNum  = NULL;  // must release
8920
8921    if (!predicate) {
8922        goto finish;
8923    }
8924
8925    resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
8926        8 * sizeof(callbackResult));
8927    if (!resultNum) {
8928        goto finish;
8929    }
8930
8931   /* Insert the result into the callback record and dispatch it as if it
8932    * were the reply coming down from user space.
8933    */
8934    _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
8935        resultNum);
8936
8937    if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
8938       /* This removes the pending callback record.
8939        */
8940        OSKext::dispatchResource(callbackRecord);
8941    }
8942
8943finish:
8944    if (resultNum) resultNum->release();
8945    return;
8946}
8947
8948/*********************************************************************
8949* Assumes sKextLock is held.
8950*********************************************************************/
8951/* static */
8952OSReturn
8953OSKext::cancelRequest(
8954    OSKextRequestTag    requestTag,
8955    void             ** contextOut)
8956{
8957    OSReturn       result         = kOSKextReturnNoMemory;
8958    OSDictionary * callbackRecord = NULL;  // must release
8959    OSData       * contextWrapper = NULL;  // do not release
8960
8961    IORecursiveLockLock(sKextLock);
8962    result = OSKext::dequeueCallbackForRequestTag(requestTag,
8963        &callbackRecord);
8964    IORecursiveLockUnlock(sKextLock);
8965
8966    if (result == kOSReturnSuccess && contextOut) {
8967        contextWrapper = OSDynamicCast(OSData,
8968            _OSKextGetRequestArgument(callbackRecord,
8969                kKextRequestArgumentContextKey));
8970        *contextOut = _OSKextExtractPointer(contextWrapper);
8971    }
8972
8973    if (callbackRecord) callbackRecord->release();
8974
8975    return result;
8976}
8977
8978/*********************************************************************
8979* Assumes sKextLock is held.
8980*********************************************************************/
8981void
8982OSKext::invokeOrCancelRequestCallbacks(
8983    OSReturn callbackResult,
8984    bool     invokeFlag)
8985{
8986    unsigned int count, i;
8987
8988    count = sRequestCallbackRecords->getCount();
8989    if (!count) {
8990        goto finish;
8991    }
8992
8993    i = count - 1;
8994    do {
8995        OSDictionary * request = OSDynamicCast(OSDictionary,
8996            sRequestCallbackRecords->getObject(i));
8997
8998        if (!request) {
8999            continue;
9000        }
9001        OSData * callbackWrapper = OSDynamicCast(OSData,
9002            _OSKextGetRequestArgument(request,
9003                kKextRequestArgumentCallbackKey));
9004
9005        if (!callbackWrapper) {
9006            sRequestCallbackRecords->removeObject(i);
9007            continue;
9008        }
9009
9010        vm_address_t callbackAddress = (vm_address_t)
9011            _OSKextExtractPointer(callbackWrapper);
9012
9013        if ((kmod_info->address <= callbackAddress) &&
9014            (callbackAddress < (kmod_info->address + kmod_info->size))) {
9015
9016            if (invokeFlag) {
9017               /* This removes the callback record.
9018                */
9019                invokeRequestCallback(request, callbackResult);
9020            } else {
9021                sRequestCallbackRecords->removeObject(i);
9022            }
9023        }
9024    } while (i--);
9025
9026finish:
9027    return;
9028}
9029
9030/*********************************************************************
9031* Assumes sKextLock is held.
9032*********************************************************************/
9033uint32_t
9034OSKext::countRequestCallbacks(void)
9035{
9036    uint32_t     result = 0;
9037    unsigned int count, i;
9038
9039    count = sRequestCallbackRecords->getCount();
9040    if (!count) {
9041        goto finish;
9042    }
9043
9044    i = count - 1;
9045    do {
9046        OSDictionary * request = OSDynamicCast(OSDictionary,
9047            sRequestCallbackRecords->getObject(i));
9048
9049        if (!request) {
9050            continue;
9051        }
9052        OSData * callbackWrapper = OSDynamicCast(OSData,
9053            _OSKextGetRequestArgument(request,
9054                kKextRequestArgumentCallbackKey));
9055
9056        if (!callbackWrapper) {
9057            continue;
9058        }
9059
9060        vm_address_t callbackAddress = (vm_address_t)
9061            _OSKextExtractPointer(callbackWrapper);
9062
9063        if ((kmod_info->address <= callbackAddress) &&
9064            (callbackAddress < (kmod_info->address + kmod_info->size))) {
9065
9066            result++;
9067        }
9068    } while (i--);
9069
9070finish:
9071    return result;
9072}
9073
9074/*********************************************************************
9075*********************************************************************/
9076static OSReturn _OSKextCreateRequest(
9077    const char    * predicate,
9078    OSDictionary ** requestP)
9079{
9080    OSReturn result = kOSKextReturnNoMemory;
9081    OSDictionary * request = NULL;  // must release on error
9082    OSDictionary * args = NULL;     // must release
9083
9084    request = OSDictionary::withCapacity(2);
9085    if (!request) {
9086        goto finish;
9087    }
9088    result = _OSDictionarySetCStringValue(request,
9089        kKextRequestPredicateKey, predicate);
9090    if (result != kOSReturnSuccess) {
9091        goto finish;
9092    }
9093    result = kOSReturnSuccess;
9094
9095finish:
9096    if (result != kOSReturnSuccess) {
9097        if (request) request->release();
9098    } else {
9099        *requestP = request;
9100    }
9101    if (args) args->release();
9102
9103    return result;
9104}
9105
9106/*********************************************************************
9107*********************************************************************/
9108static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict)
9109{
9110    return OSDynamicCast(OSString,
9111        requestDict->getObject(kKextRequestPredicateKey));
9112}
9113
9114/*********************************************************************
9115*********************************************************************/
9116static OSObject * _OSKextGetRequestArgument(
9117    OSDictionary * requestDict,
9118    const char   * argName)
9119{
9120    OSDictionary * args = OSDynamicCast(OSDictionary,
9121        requestDict->getObject(kKextRequestArgumentsKey));
9122    if (args) {
9123        return args->getObject(argName);
9124    }
9125    return NULL;
9126}
9127
9128/*********************************************************************
9129*********************************************************************/
9130static bool _OSKextSetRequestArgument(
9131    OSDictionary * requestDict,
9132    const char   * argName,
9133    OSObject     * value)
9134{
9135    OSDictionary * args = OSDynamicCast(OSDictionary,
9136        requestDict->getObject(kKextRequestArgumentsKey));
9137    if (!args) {
9138        args = OSDictionary::withCapacity(2);
9139        if (!args) {
9140            goto finish;
9141        }
9142        requestDict->setObject(kKextRequestArgumentsKey, args);
9143        args->release();
9144    }
9145    if (args) {
9146        return args->setObject(argName, value);
9147    }
9148finish:
9149    return false;
9150}
9151
9152/*********************************************************************
9153*********************************************************************/
9154static void * _OSKextExtractPointer(OSData * wrapper)
9155{
9156    void       * result = NULL;
9157    const void * resultPtr = NULL;
9158
9159    if (!wrapper) {
9160        goto finish;
9161    }
9162    resultPtr = wrapper->getBytesNoCopy();
9163    result = *(void **)resultPtr;
9164finish:
9165    return result;
9166}
9167
9168/*********************************************************************
9169*********************************************************************/
9170static OSReturn _OSDictionarySetCStringValue(
9171    OSDictionary * dict,
9172    const char   * cKey,
9173    const char   * cValue)
9174{
9175    OSReturn result = kOSKextReturnNoMemory;
9176    const OSSymbol * key = NULL;  // must release
9177    OSString * value = NULL;  // must release
9178
9179    key = OSSymbol::withCString(cKey);
9180    value = OSString::withCString(cValue);
9181    if (!key || !value) {
9182        goto finish;
9183    }
9184    if (dict->setObject(key, value)) {
9185        result = kOSReturnSuccess;
9186    }
9187
9188finish:
9189    if (key)   key->release();
9190    if (value) value->release();
9191
9192    return result;
9193}
9194
9195/*********************************************************************
9196*********************************************************************/
9197static bool _OSArrayContainsCString(
9198    OSArray    * array,
9199    const char * cString)
9200{
9201    bool             result = false;
9202    const OSSymbol * symbol = NULL;
9203    uint32_t         count, i;
9204
9205    if (!array || !cString) {
9206        goto finish;
9207    }
9208
9209    symbol = OSSymbol::withCStringNoCopy(cString);
9210    if (!symbol) {
9211        goto finish;
9212    }
9213
9214    count = array->getCount();
9215    for (i = 0; i < count; i++) {
9216        OSObject * thisObject = array->getObject(i);
9217        if (symbol->isEqualTo(thisObject)) {
9218            result = true;
9219            goto finish;
9220        }
9221    }
9222
9223finish:
9224    if (symbol) symbol->release();
9225    return result;
9226}
9227
9228/*********************************************************************
9229 * We really only care about boot / system start up related kexts.
9230 * We return true if we're less than REBUILD_MAX_TIME since start up,
9231 * otherwise return false.
9232 *********************************************************************/
9233bool _OSKextInPrelinkRebuildWindow(void)
9234{
9235    static bool     outside_the_window = false;
9236    AbsoluteTime    my_abstime;
9237    UInt64          my_ns;
9238    SInt32          my_secs;
9239
9240    if (outside_the_window) {
9241        return(false);
9242    }
9243    clock_get_uptime(&my_abstime);
9244    absolutetime_to_nanoseconds(my_abstime, &my_ns);
9245    my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
9246    if (my_secs > REBUILD_MAX_TIME) {
9247        outside_the_window = true;
9248        return(false);
9249    }
9250    return(true);
9251}
9252
9253/*********************************************************************
9254 *********************************************************************/
9255bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
9256{
9257    int unLoadedCount, i;
9258    bool result = false;
9259
9260    IORecursiveLockLock(sKextLock);
9261
9262    if (sUnloadedPrelinkedKexts == NULL) {
9263        goto finish;
9264    }
9265    unLoadedCount = sUnloadedPrelinkedKexts->getCount();
9266    if (unLoadedCount == 0) {
9267        goto finish;
9268    }
9269
9270    for (i = 0; i < unLoadedCount; i++) {
9271        const OSSymbol *    myBundleID;     // do not release
9272
9273        myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
9274        if (!myBundleID) continue;
9275        if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
9276            result = true;
9277            break;
9278        }
9279    }
9280finish:
9281    IORecursiveLockUnlock(sKextLock);
9282    return(result);
9283}
9284
9285#if PRAGMA_MARK
9286#pragma mark Personalities (IOKit Drivers)
9287#endif
9288/*********************************************************************
9289*********************************************************************/
9290/* static */
9291OSArray *
9292OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
9293{
9294    OSArray              * result                = NULL;  // returned
9295    OSCollectionIterator * kextIterator          = NULL;  // must release
9296    OSArray              * personalities         = NULL;  // must release
9297    OSCollectionIterator * personalitiesIterator = NULL;  // must release
9298
9299    OSString             * kextID                = NULL;  // do not release
9300    OSKext               * theKext               = NULL;  // do not release
9301
9302    IORecursiveLockLock(sKextLock);
9303
9304   /* Let's conservatively guess that any given kext has around 3
9305    * personalities for now.
9306    */
9307    result = OSArray::withCapacity(sKextsByID->getCount() * 3);
9308    if (!result) {
9309        goto finish;
9310    }
9311
9312    kextIterator = OSCollectionIterator::withCollection(sKextsByID);
9313    if (!kextIterator) {
9314        goto finish;
9315    }
9316
9317    while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
9318        if (personalitiesIterator) {
9319            personalitiesIterator->release();
9320            personalitiesIterator = NULL;
9321        }
9322        if (personalities) {
9323            personalities->release();
9324            personalities = NULL;
9325        }
9326
9327        theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
9328        if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
9329            personalities = theKext->copyPersonalitiesArray();
9330            if (!personalities) {
9331                continue;
9332            }
9333            result->merge(personalities);
9334        } else {
9335            // xxx - check for better place to put this log msg
9336            OSKextLog(theKext,
9337                kOSKextLogWarningLevel |
9338                kOSKextLogLoadFlag,
9339                "Kext %s is not loadable during safe boot; "
9340                "omitting its personalities.",
9341                theKext->getIdentifierCString());
9342        }
9343
9344    }
9345
9346finish:
9347    IORecursiveLockUnlock(sKextLock);
9348
9349    if (kextIterator)          kextIterator->release();
9350    if (personalitiesIterator) personalitiesIterator->release();
9351    if (personalities)         personalities->release();
9352
9353    return result;
9354}
9355
9356/*********************************************************************
9357*********************************************************************/
9358/* static */
9359void
9360OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
9361{
9362    int numPersonalities = 0;
9363
9364    OSKextLog(/* kext */ NULL,
9365        kOSKextLogStepLevel |
9366        kOSKextLogLoadFlag,
9367        "Sending all eligible registered kexts' personalities "
9368        "to the IOCatalogue %s.",
9369        startMatching ? "and starting matching" : "but not starting matching");
9370
9371    OSArray * personalities = OSKext::copyAllKextPersonalities(
9372        /* filterSafeBootFlag */ true);
9373
9374    if (personalities) {
9375        gIOCatalogue->addDrivers(personalities, startMatching);
9376        numPersonalities = personalities->getCount();
9377        personalities->release();
9378    }
9379
9380    OSKextLog(/* kext */ NULL,
9381        kOSKextLogStepLevel |
9382        kOSKextLogLoadFlag,
9383        "%d kext personalit%s sent to the IOCatalogue; %s.",
9384        numPersonalities, numPersonalities > 0 ? "ies" : "y",
9385        startMatching ? "matching started" : "matching not started");
9386    return;
9387}
9388
9389/*********************************************************************
9390* Do not make a deep copy, just convert the IOKitPersonalities dict
9391* to an array for sending to the IOCatalogue.
9392*********************************************************************/
9393OSArray *
9394OSKext::copyPersonalitiesArray(void)
9395{
9396    OSArray              * result                      = NULL;
9397    OSDictionary         * personalities               = NULL;  // do not release
9398    OSCollectionIterator * personalitiesIterator       = NULL;  // must release
9399
9400    OSString             * personalityName             = NULL;  // do not release
9401    OSString             * personalityBundleIdentifier = NULL;  // do not release
9402
9403    personalities = OSDynamicCast(OSDictionary,
9404        getPropertyForHostArch(kIOKitPersonalitiesKey));
9405    if (!personalities) {
9406        goto finish;
9407    }
9408
9409    result = OSArray::withCapacity(personalities->getCount());
9410    if (!result) {
9411        goto finish;
9412    }
9413
9414    personalitiesIterator =
9415        OSCollectionIterator::withCollection(personalities);
9416    if (!personalitiesIterator) {
9417        goto finish;
9418    }
9419    while ((personalityName = OSDynamicCast(OSString,
9420            personalitiesIterator->getNextObject()))) {
9421
9422        OSDictionary * personality = OSDynamicCast(OSDictionary,
9423            personalities->getObject(personalityName));
9424
9425       /******
9426        * If the personality doesn't have a CFBundleIdentifier, or if it
9427        * differs from the kext's, insert the kext's ID so we can find it.
9428        * The publisher ID is used to remove personalities from bundles
9429        * correctly.
9430        */
9431        personalityBundleIdentifier = OSDynamicCast(OSString,
9432            personality->getObject(kCFBundleIdentifierKey));
9433
9434        if (!personalityBundleIdentifier) {
9435            personality->setObject(kCFBundleIdentifierKey, bundleID);
9436        } else if (!personalityBundleIdentifier->isEqualTo(bundleID)) {
9437            personality->setObject(kIOPersonalityPublisherKey, bundleID);
9438        }
9439
9440        result->setObject(personality);
9441    }
9442
9443finish:
9444    if (personalitiesIterator) personalitiesIterator->release();
9445
9446    return result;
9447}
9448
9449/*********************************************************************
9450Might want to change this to a bool return?
9451*********************************************************************/
9452OSReturn
9453OSKext::sendPersonalitiesToCatalog(
9454    bool      startMatching,
9455    OSArray * personalityNames)
9456{
9457    OSReturn       result              = kOSReturnSuccess;
9458    OSArray      * personalitiesToSend = NULL;  // must release
9459    OSDictionary * kextPersonalities   = NULL;  // do not release
9460    int            count, i;
9461
9462    if (!sLoadEnabled) {
9463        OSKextLog(this,
9464            kOSKextLogErrorLevel |
9465            kOSKextLogLoadFlag,
9466            "Kext loading is disabled (attempt to start matching for kext %s).",
9467            getIdentifierCString());
9468        result = kOSKextReturnDisabled;
9469        goto finish;
9470    }
9471
9472    if (sSafeBoot && !isLoadableInSafeBoot()) {
9473        OSKextLog(this,
9474            kOSKextLogErrorLevel |
9475            kOSKextLogLoadFlag,
9476            "Kext %s is not loadable during safe boot; "
9477            "not sending personalities to the IOCatalogue.",
9478            getIdentifierCString());
9479        result = kOSKextReturnNotLoadable;
9480        goto finish;
9481    }
9482
9483    if (!personalityNames || !personalityNames->getCount()) {
9484        personalitiesToSend = copyPersonalitiesArray();
9485    } else {
9486        kextPersonalities = OSDynamicCast(OSDictionary,
9487            getPropertyForHostArch(kIOKitPersonalitiesKey));
9488        if (!kextPersonalities || !kextPersonalities->getCount()) {
9489            // not an error
9490            goto finish;
9491        }
9492        personalitiesToSend = OSArray::withCapacity(0);
9493        if (!personalitiesToSend) {
9494            result = kOSKextReturnNoMemory;
9495            goto finish;
9496        }
9497        count = personalityNames->getCount();
9498        for (i = 0; i < count; i++) {
9499            OSString * name = OSDynamicCast(OSString,
9500                personalityNames->getObject(i));
9501            if (!name) {
9502                continue;
9503            }
9504            OSDictionary * personality = OSDynamicCast(OSDictionary,
9505                kextPersonalities->getObject(name));
9506            if (personality) {
9507                personalitiesToSend->setObject(personality);
9508            }
9509        }
9510    }
9511    if (personalitiesToSend) {
9512        unsigned numPersonalities = personalitiesToSend->getCount();
9513        OSKextLog(this,
9514            kOSKextLogStepLevel |
9515            kOSKextLogLoadFlag,
9516            "Kext %s sending %d personalit%s to the IOCatalogue%s.",
9517            getIdentifierCString(),
9518            numPersonalities,
9519            numPersonalities > 1 ? "ies" : "y",
9520            startMatching ? " and starting matching" : " but not starting matching");
9521        gIOCatalogue->addDrivers(personalitiesToSend, startMatching);
9522    }
9523finish:
9524    if (personalitiesToSend) {
9525        personalitiesToSend->release();
9526    }
9527    return result;
9528}
9529
9530/*********************************************************************
9531* xxx - We should allow removing the kext's declared personalities,
9532* xxx - even with other bundle identifiers.
9533*********************************************************************/
9534void
9535OSKext::removePersonalitiesFromCatalog(void)
9536{
9537    OSDictionary * personality = NULL;   // do not release
9538
9539    personality = OSDictionary::withCapacity(1);
9540    if (!personality) {
9541        goto finish;
9542    }
9543    personality->setObject(kCFBundleIdentifierKey, getIdentifier());
9544
9545    OSKextLog(this,
9546        kOSKextLogStepLevel |
9547        kOSKextLogLoadFlag,
9548        "Kext %s removing all personalities naming it from the IOCatalogue.",
9549        getIdentifierCString());
9550
9551   /* Have the IOCatalog remove all personalities matching this kext's
9552    * bundle ID and trigger matching anew.
9553    */
9554    gIOCatalogue->removeDrivers(personality, /* startMatching */ true);
9555
9556 finish:
9557    if (personality) personality->release();
9558
9559    return;
9560}
9561
9562
9563#if PRAGMA_MARK
9564#pragma mark Logging
9565#endif
9566/*********************************************************************
9567* Do not call any function that takes sKextLock here!
9568*********************************************************************/
9569/* static */
9570OSKextLogSpec
9571OSKext::setUserSpaceLogFilter(
9572    OSKextLogSpec   newUserLogFilter,
9573    bool            captureFlag)
9574{
9575    OSKextLogSpec result;
9576    bool          allocError = false;
9577
9578   /* Do not call any function that takes sKextLoggingLock during
9579    * this critical block. That means do logging after.
9580    */
9581    IOLockLock(sKextLoggingLock);
9582
9583    result = sUserSpaceKextLogFilter;
9584    sUserSpaceKextLogFilter = newUserLogFilter;
9585
9586    if (newUserLogFilter && captureFlag &&
9587        !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
9588
9589        // xxx - do some measurements for a good initial capacity?
9590        sUserSpaceLogSpecArray = OSArray::withCapacity(0);
9591        sUserSpaceLogMessageArray = OSArray::withCapacity(0);
9592
9593        if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
9594            OSSafeReleaseNULL(sUserSpaceLogSpecArray);
9595            OSSafeReleaseNULL(sUserSpaceLogMessageArray);
9596            allocError = true;
9597        }
9598    }
9599
9600    IOLockUnlock(sKextLoggingLock);
9601
9602   /* If the config flag itself is changing, log the state change
9603    * going both ways, before setting up the user-space log arrays,
9604    * so that this is only logged in the kernel.
9605    */
9606    if (result != newUserLogFilter) {
9607        OSKextLog(/* kext */ NULL,
9608            kOSKextLogDebugLevel |
9609            kOSKextLogGeneralFlag,
9610            "User-space log flags changed from 0x%x to 0x%x.",
9611            result, newUserLogFilter);
9612    }
9613    if (allocError) {
9614        OSKextLog(/* kext */ NULL,
9615            kOSKextLogErrorLevel |
9616            kOSKextLogGeneralFlag,
9617            "Failed to allocate user-space log message arrays.");
9618    }
9619
9620    return result;
9621}
9622
9623/*********************************************************************
9624* Do not call any function that takes sKextLock here!
9625*********************************************************************/
9626/* static */
9627OSArray *
9628OSKext::clearUserSpaceLogFilter(void)
9629{
9630    OSArray       * result       = NULL;
9631    OSKextLogSpec   oldLogFilter;
9632    OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
9633
9634   /* Do not call any function that takes sKextLoggingLock during
9635    * this critical block. That means do logging after.
9636    */
9637    IOLockLock(sKextLoggingLock);
9638
9639    result = OSArray::withCapacity(2);
9640    if (result) {
9641        result->setObject(sUserSpaceLogSpecArray);
9642        result->setObject(sUserSpaceLogMessageArray);
9643    }
9644    OSSafeReleaseNULL(sUserSpaceLogSpecArray);
9645    OSSafeReleaseNULL(sUserSpaceLogMessageArray);
9646
9647    oldLogFilter = sUserSpaceKextLogFilter;
9648    sUserSpaceKextLogFilter = newLogFilter;
9649
9650    IOLockUnlock(sKextLoggingLock);
9651
9652   /* If the config flag itself is changing, log the state change
9653    * going both ways, after tearing down the user-space log
9654    * arrays, so this is only logged within the kernel.
9655    */
9656    if (oldLogFilter != newLogFilter) {
9657        OSKextLog(/* kext */ NULL,
9658            kOSKextLogDebugLevel |
9659            kOSKextLogGeneralFlag,
9660            "User-space log flags changed from 0x%x to 0x%x.",
9661            oldLogFilter, newLogFilter);
9662    }
9663
9664    return result;
9665}
9666
9667
9668/*********************************************************************
9669* Do not call any function that takes sKextLock here!
9670*********************************************************************/
9671/* static */
9672OSKextLogSpec
9673OSKext::getUserSpaceLogFilter(void)
9674{
9675    OSKextLogSpec result;
9676
9677    IOLockLock(sKextLoggingLock);
9678    result = sUserSpaceKextLogFilter;
9679    IOLockUnlock(sKextLoggingLock);
9680
9681    return result;
9682}
9683
9684/*********************************************************************
9685* This function is called by OSMetaClass during kernel C++ setup.
9686* Be careful what you access here; assume only OSKext::initialize()
9687* has been called.
9688*
9689* Do not call any function that takes sKextLock here!
9690*********************************************************************/
9691#define VTRESET   "\033[0m"
9692
9693#define VTBOLD    "\033[1m"
9694#define VTUNDER   "\033[4m"
9695
9696#define VTRED     "\033[31m"
9697#define VTGREEN   "\033[32m"
9698#define VTYELLOW  "\033[33m"
9699#define VTBLUE    "\033[34m"
9700#define VTMAGENTA "\033[35m"
9701#define VTCYAN    "\033[36m"
9702
9703inline const char * colorForFlags(OSKextLogSpec flags)
9704{
9705    OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
9706
9707    switch (logLevel) {
9708    case kOSKextLogErrorLevel:
9709        return VTRED VTBOLD;
9710        break;
9711    case kOSKextLogWarningLevel:
9712        return VTRED;
9713        break;
9714    case kOSKextLogBasicLevel:
9715        return VTYELLOW VTUNDER;
9716        break;
9717    case kOSKextLogProgressLevel:
9718        return VTYELLOW;
9719        break;
9720    case kOSKextLogStepLevel:
9721        return VTGREEN;
9722        break;
9723    case kOSKextLogDetailLevel:
9724        return VTCYAN;
9725        break;
9726    case kOSKextLogDebugLevel:
9727        return VTMAGENTA;
9728        break;
9729    default:
9730        return "";  // white
9731        break;
9732    }
9733    return "";
9734}
9735
9736inline bool logSpecMatch(
9737    OSKextLogSpec msgLogSpec,
9738    OSKextLogSpec logFilter)
9739{
9740    OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
9741    OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
9742    OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
9743
9744    OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
9745    OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
9746    OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
9747
9748   /* Explicit messages always get logged.
9749    */
9750    if (msgLevel == kOSKextLogExplicitLevel) {
9751        return true;
9752    }
9753
9754   /* Warnings and errors are logged regardless of the flags.
9755    */
9756    if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
9757        return true;
9758    }
9759
9760   /* A verbose message that isn't for a logging-enabled kext and isn't global
9761    * does *not* get logged.
9762    */
9763    if (!msgKextGlobal && !filterKextGlobal) {
9764        return false;
9765    }
9766
9767   /* Warnings and errors are logged regardless of the flags.
9768    * All other messages must fit the flags and
9769    * have a level at or below the filter.
9770    *
9771    */
9772    if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
9773        return true;
9774    }
9775    return false;
9776}
9777
9778extern "C" {
9779
9780void
9781OSKextLog(
9782    OSKext         * aKext,
9783    OSKextLogSpec    msgLogSpec,
9784    const char     * format, ...)
9785{
9786    va_list argList;
9787
9788    va_start(argList, format);
9789    OSKextVLog(aKext, msgLogSpec, format, argList);
9790    va_end(argList);
9791}
9792
9793void
9794OSKextVLog(
9795    OSKext         * aKext,
9796    OSKextLogSpec    msgLogSpec,
9797    const char     * format,
9798    va_list          srcArgList)
9799{
9800    extern int       disableConsoleOutput;
9801
9802    bool             logForKernel       = false;
9803    bool             logForUser         = false;
9804    va_list          argList;
9805    char             stackBuffer[120];
9806    uint32_t         length            = 0;
9807    char           * allocBuffer       = NULL;         // must kfree
9808    OSNumber       * logSpecNum        = NULL;         // must release
9809    OSString       * logString         = NULL;         // must release
9810    char           * buffer            = stackBuffer;  // do not free
9811
9812    IOLockLock(sKextLoggingLock);
9813
9814   /* Set the kext/global bit in the message spec if we have no
9815    * kext or if the kext requests logging.
9816    */
9817    if (!aKext || aKext->flags.loggingEnabled) {
9818        msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
9819    }
9820
9821    logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
9822    if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
9823        logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
9824    }
9825
9826    if (! (logForKernel || logForUser) ) {
9827        goto finish;
9828    }
9829
9830   /* No goto from here until past va_end()!
9831    */
9832    va_copy(argList, srcArgList);
9833    length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
9834    va_end(argList);
9835
9836    if (length + 1 >= sizeof(stackBuffer)) {
9837        allocBuffer = (char *)kalloc((length + 1) * sizeof(char));
9838        if (!allocBuffer) {
9839            goto finish;
9840        }
9841
9842       /* No goto from here until past va_end()!
9843        */
9844        va_copy(argList, srcArgList);
9845        vsnprintf(allocBuffer, length + 1, format, argList);
9846        va_end(argList);
9847
9848        buffer = allocBuffer;
9849    }
9850
9851   /* If user space wants the log message, queue it up.
9852    */
9853    if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
9854        logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
9855        logString = OSString::withCString(buffer);
9856        if (logSpecNum && logString) {
9857            sUserSpaceLogSpecArray->setObject(logSpecNum);
9858            sUserSpaceLogMessageArray->setObject(logString);
9859        }
9860    }
9861
9862   /* Always log messages from the kernel according to the kernel's
9863    * log flags.
9864    */
9865    if (logForKernel) {
9866
9867       /* If we are in console mode and have a custom log filter,
9868        * colorize the log message.
9869        */
9870        if (!disableConsoleOutput && sBootArgLogFilterFound) {
9871            const char * color = "";  // do not free
9872            color = colorForFlags(msgLogSpec);
9873            printf("%s%s%s\n", colorForFlags(msgLogSpec),
9874                buffer, color[0] ? VTRESET : "");
9875        } else {
9876            printf("%s\n", buffer);
9877        }
9878    }
9879
9880finish:
9881    IOLockUnlock(sKextLoggingLock);
9882
9883    if (allocBuffer) {
9884        kfree(allocBuffer, (length + 1) * sizeof(char));
9885    }
9886    OSSafeRelease(logString);
9887    OSSafeRelease(logSpecNum);
9888    return;
9889}
9890
9891#if KASLR_IOREG_DEBUG
9892
9893#define IOLOG_INDENT( the_indention ) \
9894{ \
9895    int     i; \
9896    for ( i = 0; i < (the_indention); i++ ) { \
9897        IOLog(" "); \
9898    } \
9899}
9900
9901extern vm_offset_t	 vm_kernel_stext;
9902extern vm_offset_t	 vm_kernel_etext;
9903extern mach_vm_offset_t kext_alloc_base;
9904extern mach_vm_offset_t kext_alloc_max;
9905
9906bool ScanForAddrInObject(OSObject * theObject,
9907                         int indent );
9908
9909bool ScanForAddrInObject(OSObject * theObject,
9910                         int indent)
9911{
9912    const OSMetaClass *     myTypeID;
9913    OSCollectionIterator *  myIter;
9914    OSSymbol *              myKey;
9915    OSObject *              myValue;
9916    bool                    myResult = false;
9917
9918    if ( theObject == NULL ) {
9919        IOLog("%s: theObject is NULL \n",
9920              __FUNCTION__);
9921        return myResult;
9922    }
9923
9924    myTypeID = OSTypeIDInst(theObject);
9925
9926    if ( myTypeID == OSTypeID(OSDictionary) ) {
9927        OSDictionary *      myDictionary;
9928
9929        myDictionary = OSDynamicCast(OSDictionary, theObject);
9930        myIter = OSCollectionIterator::withCollection( myDictionary );
9931        if ( myIter == NULL )
9932            return myResult;
9933        myIter->reset();
9934
9935        while ( (myKey = OSDynamicCast(OSSymbol, myIter->getNextObject())) ) {
9936            bool    myTempResult;
9937
9938            myValue = myDictionary->getObject(myKey);
9939            myTempResult = ScanForAddrInObject(myValue, (indent + 4));
9940            if (myTempResult) {
9941                // if we ever get a true result return true
9942                myResult = true;
9943                IOLOG_INDENT(indent);
9944                IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
9945            }
9946        }
9947        myIter->release();
9948    }
9949    else if ( myTypeID == OSTypeID(OSArray) ) {
9950        OSArray *   myArray;
9951
9952        myArray = OSDynamicCast(OSArray, theObject);
9953        myIter = OSCollectionIterator::withCollection(myArray);
9954        if ( myIter == NULL )
9955            return myResult;
9956        myIter->reset();
9957
9958        while ( (myValue = myIter->getNextObject()) ) {
9959            bool        myTempResult;
9960            myTempResult = ScanForAddrInObject(myValue, (indent + 4));
9961            if (myTempResult) {
9962                // if we ever get a true result return true
9963                myResult = true;
9964                IOLOG_INDENT(indent);
9965                IOLog("OSArray: \n");
9966            }
9967        }
9968        myIter->release();
9969    }
9970    else if ( myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol) ) {
9971
9972        // should we look for addresses in strings?
9973    }
9974    else if ( myTypeID == OSTypeID(OSData) ) {
9975
9976        void * *        myPtrPtr;
9977        unsigned int    myLen;
9978        OSData *        myDataObj;
9979
9980        myDataObj =    OSDynamicCast(OSData, theObject);
9981        myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
9982        myLen = myDataObj->getLength();
9983
9984        if (myPtrPtr && myLen && myLen > 7) {
9985            int     i;
9986            int     myPtrCount = (myLen / sizeof(void *));
9987
9988            for (i = 0; i < myPtrCount; i++) {
9989                UInt64 numberValue = (UInt64) *(myPtrPtr);
9990
9991                if ( kext_alloc_max != 0 &&
9992                    numberValue >= kext_alloc_base &&
9993                    numberValue < kext_alloc_max ) {
9994
9995                    OSKext * myKext    = NULL;  // must release (looked up)
9996                                                // IOLog("found OSData %p in kext map %p to %p  \n",
9997                                                //       *(myPtrPtr),
9998                                                //       (void *) kext_alloc_base,
9999                                                //       (void *) kext_alloc_max);
10000
10001                    myKext = OSKext::lookupKextWithAddress( (vm_address_t) *(myPtrPtr) );
10002                    if (myKext) {
10003                        IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
10004                              *(myPtrPtr),
10005                              myKext->getIdentifierCString());
10006                        myKext->release();
10007                    }
10008                    myResult = true;
10009                }
10010                if ( vm_kernel_etext != 0 &&
10011                    numberValue >= vm_kernel_stext &&
10012                    numberValue < vm_kernel_etext ) {
10013                    IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
10014                          *(myPtrPtr),
10015                          (void *) vm_kernel_stext,
10016                          (void *) vm_kernel_etext);
10017                    myResult = true;
10018                }
10019                myPtrPtr++;
10020            }
10021        }
10022    }
10023    else if ( myTypeID == OSTypeID(OSBoolean) ) {
10024
10025        // do nothing here...
10026    }
10027    else if ( myTypeID == OSTypeID(OSNumber) ) {
10028
10029        OSNumber * number = OSDynamicCast(OSNumber, theObject);
10030
10031        UInt64 numberValue = number->unsigned64BitValue();
10032
10033        if ( kext_alloc_max != 0 &&
10034            numberValue >= kext_alloc_base &&
10035            numberValue < kext_alloc_max ) {
10036
10037            OSKext * myKext    = NULL;  // must release (looked up)
10038            IOLog("found OSNumber in kext map %p to %p  \n",
10039                  (void *) kext_alloc_base,
10040                  (void *) kext_alloc_max);
10041            IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
10042
10043            myKext = OSKext::lookupKextWithAddress( (vm_address_t) numberValue );
10044            if (myKext) {
10045                IOLog("found in kext \"%s\"  \n",
10046                      myKext->getIdentifierCString());
10047                myKext->release();
10048            }
10049
10050            myResult = true;
10051        }
10052        if ( vm_kernel_etext != 0 &&
10053            numberValue >= vm_kernel_stext &&
10054            numberValue < vm_kernel_etext ) {
10055            IOLog("found OSNumber in kernel text segment %p to %p  \n",
10056                  (void *) vm_kernel_stext,
10057                  (void *) vm_kernel_etext);
10058            IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
10059            myResult = true;
10060        }
10061    }
10062#if 0
10063    else {
10064        const OSMetaClass* myMetaClass = NULL;
10065
10066        myMetaClass = theObject->getMetaClass();
10067        if ( myMetaClass ) {
10068            IOLog("class %s \n", myMetaClass->getClassName() );
10069        }
10070        else {
10071            IOLog("Unknown object \n" );
10072        }
10073    }
10074#endif
10075
10076    return myResult;
10077}
10078#endif // KASLR_KEXT_DEBUG
10079
10080}; /* extern "C" */
10081
10082#if PRAGMA_MARK
10083#pragma mark Backtrace Dump & kmod_get_info() support
10084#endif
10085/*********************************************************************
10086* This function must be safe to call in panic context.
10087*********************************************************************/
10088/* static */
10089void
10090OSKext::printKextsInBacktrace(
10091    vm_offset_t  * addr,
10092    unsigned int   cnt,
10093    int         (* printf_func)(const char *fmt, ...),
10094    bool           lockFlag)
10095{
10096    addr64_t    summary_page = 0;
10097    addr64_t    last_summary_page = 0;
10098    bool        found_kmod = false;
10099    u_int       i = 0;
10100
10101    if (lockFlag) {
10102        IOLockLock(sKextSummariesLock);
10103    }
10104
10105    if (!gLoadedKextSummaries) {
10106        (*printf_func)("         can't perform kext scan: no kext summary");
10107        goto finish;
10108    }
10109
10110    summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
10111    last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
10112    for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
10113        if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
10114            (*printf_func)("         can't perform kext scan: "
10115                "missing kext summary page %p", summary_page);
10116            goto finish;
10117        }
10118    }
10119
10120    for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
10121        OSKextLoadedKextSummary * summary;
10122
10123        summary = gLoadedKextSummaries->summaries + i;
10124        if (!summary->address) {
10125            continue;
10126        }
10127
10128        if (!summaryIsInBacktrace(summary, addr, cnt)) {
10129            continue;
10130        }
10131
10132        if (!found_kmod) {
10133            (*printf_func)("      Kernel Extensions in backtrace:\n");
10134            found_kmod = true;
10135        }
10136
10137        printSummary(summary, printf_func);
10138    }
10139
10140finish:
10141    if (lockFlag) {
10142        IOLockUnlock(sKextSummariesLock);
10143    }
10144
10145    return;
10146}
10147
10148/*********************************************************************
10149* This function must be safe to call in panic context.
10150*********************************************************************/
10151/* static */
10152boolean_t
10153OSKext::summaryIsInBacktrace(
10154    OSKextLoadedKextSummary   * summary,
10155    vm_offset_t               * addr,
10156    unsigned int                cnt)
10157{
10158    u_int i = 0;
10159
10160    for (i = 0; i < cnt; i++) {
10161        vm_offset_t kscan_addr = addr[i];
10162        if ((kscan_addr >= summary->address) &&
10163            (kscan_addr < (summary->address + summary->size)))
10164        {
10165            return TRUE;
10166        }
10167    }
10168
10169    return FALSE;
10170}
10171
10172/*********************************************************************
10173 * scan list of loaded kext summaries looking for a load address match and if
10174 * found return the UUID C string.  If not found then set empty string.
10175 *********************************************************************/
10176static void findSummaryUUID(
10177                            uint32_t        tag_ID,
10178                            uuid_string_t   uuid);
10179
10180static void findSummaryUUID(
10181                            uint32_t        tag_ID,
10182                            uuid_string_t   uuid)
10183{
10184    u_int     i;
10185
10186    uuid[0] = 0x00; // default to no UUID
10187
10188    for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
10189        OSKextLoadedKextSummary * summary;
10190
10191        summary = gLoadedKextSummaries->summaries + i;
10192
10193        if (summary->loadTag == tag_ID) {
10194            (void) uuid_unparse(summary->uuid, uuid);
10195            break;
10196        }
10197    }
10198    return;
10199}
10200
10201/*********************************************************************
10202* This function must be safe to call in panic context.
10203*********************************************************************/
10204void OSKext::printSummary(
10205    OSKextLoadedKextSummary * summary,
10206    int                    (* printf_func)(const char *fmt, ...))
10207{
10208    kmod_reference_t * kmod_ref = NULL;
10209    uuid_string_t uuid;
10210    char version[kOSKextVersionMaxLength];
10211
10212    if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
10213        strlcpy(version, "unknown version", sizeof(version));
10214    }
10215    (void) uuid_unparse(summary->uuid, uuid);
10216
10217    (*printf_func)("         %s(%s)[%s]@0x%llx->0x%llx\n",
10218        summary->name, version, uuid,
10219        summary->address, summary->address + summary->size - 1);
10220
10221    /* print dependency info */
10222    for (kmod_ref = (kmod_reference_t *) summary->reference_list;
10223         kmod_ref;
10224         kmod_ref = kmod_ref->next) {
10225        kmod_info_t * rinfo;
10226
10227        if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
10228            (*printf_func)("            kmod dependency scan stopped "
10229                           "due to missing dependency page: %p\n", kmod_ref);
10230            break;
10231        }
10232        rinfo = kmod_ref->info;
10233
10234        if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
10235            (*printf_func)("            kmod dependency scan stopped "
10236                           "due to missing kmod page: %p\n", rinfo);
10237            break;
10238        }
10239
10240        if (!rinfo->address) {
10241            continue; // skip fake entries for built-ins
10242        }
10243
10244        /* locate UUID in gLoadedKextSummaries */
10245        findSummaryUUID(rinfo->id, uuid);
10246
10247        (*printf_func)("            dependency: %s(%s)[%s]@%p\n",
10248                       rinfo->name, rinfo->version, uuid, rinfo->address);
10249    }
10250    return;
10251}
10252
10253
10254/*******************************************************************************
10255* substitute() looks at an input string (a pointer within a larger buffer)
10256* for a match to a substring, and on match it writes the marker & substitution
10257* character to an output string, updating the scan (from) and
10258* output (to) indexes as appropriate.
10259*******************************************************************************/
10260static int substitute(
10261    const char * scan_string,
10262    char       * string_out,
10263    uint32_t   * to_index,
10264    uint32_t   * from_index,
10265    const char * substring,
10266    char         marker,
10267    char         substitution);
10268
10269/* string_out must be at least KMOD_MAX_NAME bytes.
10270 */
10271static int
10272substitute(
10273    const char * scan_string,
10274    char       * string_out,
10275    uint32_t   * to_index,
10276    uint32_t   * from_index,
10277    const char * substring,
10278    char         marker,
10279    char         substitution)
10280{
10281    uint32_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
10282
10283   /* On a substring match, append the marker (if there is one) and then
10284    * the substitution character, updating the output (to) index accordingly.
10285    * Then update the input (from) length by the length of the substring
10286    * that got replaced.
10287    */
10288    if (!strncmp(scan_string, substring, substring_length)) {
10289        if (marker) {
10290            string_out[(*to_index)++] = marker;
10291        }
10292        string_out[(*to_index)++] = substitution;
10293        (*from_index) += substring_length;
10294        return 1;
10295    }
10296    return 0;
10297}
10298
10299/*******************************************************************************
10300* compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
10301* KMOD_MAX_NAME characters and performs various substitutions of common
10302* prefixes & substrings as defined by tables in kext_panic_report.h.
10303*******************************************************************************/
10304static void compactIdentifier(
10305    const char * identifier,
10306    char       * identifier_out,
10307    char      ** identifier_out_end);
10308
10309static void
10310compactIdentifier(
10311    const char * identifier,
10312    char       * identifier_out,
10313    char      ** identifier_out_end)
10314{
10315    uint32_t       from_index, to_index;
10316    uint32_t       scan_from_index = 0;
10317    uint32_t       scan_to_index   = 0;
10318    subs_entry_t * subs_entry    = NULL;
10319    int            did_sub       = 0;
10320
10321    from_index = to_index = 0;
10322    identifier_out[0] = '\0';
10323
10324   /* Replace certain identifier prefixes with shorter @+character sequences.
10325    * Check the return value of substitute() so we only replace the prefix.
10326    */
10327    for (subs_entry = &kext_identifier_prefix_subs[0];
10328         subs_entry->substring && !did_sub;
10329         subs_entry++) {
10330
10331        did_sub = substitute(identifier, identifier_out,
10332            &scan_to_index, &scan_from_index,
10333            subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
10334    }
10335    did_sub = 0;
10336
10337   /* Now scan through the identifier looking for the common substrings
10338    * and replacing them with shorter !+character sequences via substitute().
10339    */
10340    for (/* see above */;
10341         scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
10342         /* see loop */) {
10343
10344        const char   * scan_string = &identifier[scan_from_index];
10345
10346        did_sub = 0;
10347
10348        if (scan_from_index) {
10349            for (subs_entry = &kext_identifier_substring_subs[0];
10350                 subs_entry->substring && !did_sub;
10351                 subs_entry++) {
10352
10353                did_sub = substitute(scan_string, identifier_out,
10354                    &scan_to_index, &scan_from_index,
10355                    subs_entry->substring, '!', subs_entry->substitute);
10356            }
10357        }
10358
10359       /* If we didn't substitute, copy the input character to the output.
10360        */
10361        if (!did_sub) {
10362            identifier_out[scan_to_index++] = identifier[scan_from_index++];
10363        }
10364    }
10365
10366    identifier_out[scan_to_index] = '\0';
10367    if (identifier_out_end) {
10368        *identifier_out_end = &identifier_out[scan_to_index];
10369    }
10370
10371    return;
10372}
10373
10374/*******************************************************************************
10375* assemble_identifier_and_version() adds to a string buffer a compacted
10376* bundle identifier followed by a version string.
10377*******************************************************************************/
10378
10379/* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
10380 */
10381static int assemble_identifier_and_version(
10382    kmod_info_t * kmod_info,
10383    char        * identPlusVers);
10384static int
10385assemble_identifier_and_version(
10386    kmod_info_t * kmod_info,
10387    char        * identPlusVers)
10388{
10389    int result = 0;
10390
10391    compactIdentifier(kmod_info->name, identPlusVers, NULL);
10392    result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
10393    identPlusVers[result++] = '\t';  // increment for real char
10394    identPlusVers[result] = '\0';    // don't increment for nul char
10395    result = strlcat(identPlusVers, kmod_info->version, KMOD_MAX_NAME);
10396
10397    return result;
10398}
10399
10400/*******************************************************************************
10401* Assumes sKextLock is held.
10402*******************************************************************************/
10403/* static */
10404uint32_t
10405OSKext::saveLoadedKextPanicListTyped(
10406    const char * prefix,
10407    int          invertFlag,
10408    int          libsFlag,
10409    char       * paniclist,
10410    uint32_t     list_size,
10411    uint32_t   * list_length_ptr)
10412{
10413    uint32_t      result = 0;
10414    int           error  = 0;
10415    unsigned int  count, i;
10416
10417    count = sLoadedKexts->getCount();
10418    if (!count) {
10419        goto finish;
10420    }
10421
10422    i = count - 1;
10423    do {
10424        OSObject    * rawKext = sLoadedKexts->getObject(i);
10425        OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
10426        int           match;
10427        char          identPlusVers[2*KMOD_MAX_NAME];
10428        uint32_t      identPlusVersLength;
10429
10430        if (!rawKext) {
10431            printf("OSKext::saveLoadedKextPanicListTyped - "
10432                "NULL kext in loaded kext list; continuing\n");
10433            continue;
10434        }
10435
10436        if (!theKext) {
10437            printf("OSKext::saveLoadedKextPanicListTyped - "
10438                "Kext type cast failed in loaded kext list; continuing\n");
10439            continue;
10440        }
10441
10442       /* Skip all built-in kexts.
10443        */
10444        if (theKext->isKernelComponent()) {
10445            continue;
10446        }
10447
10448        kmod_info_t * kmod_info = theKext->kmod_info;
10449
10450       /* Filter for kmod name (bundle identifier).
10451        */
10452        match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
10453        if ((match && invertFlag) || (!match && !invertFlag)) {
10454            continue;
10455        }
10456
10457       /* Filter for libraries (kexts that have a compatible version).
10458        */
10459        if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
10460            (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
10461
10462            continue;
10463        }
10464
10465        if (!kmod_info ||
10466            !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
10467
10468            printf("kext scan stopped due to missing kmod_info page: %p\n",
10469                kmod_info);
10470            error = 1;
10471            goto finish;
10472        }
10473
10474        identPlusVersLength = assemble_identifier_and_version(kmod_info,
10475            identPlusVers);
10476        if (!identPlusVersLength) {
10477            printf("error saving loaded kext info\n");
10478            goto finish;
10479        }
10480
10481       /* Adding 1 for the newline.
10482        */
10483        if (*list_length_ptr + identPlusVersLength + 1 >= list_size) {
10484            goto finish;
10485        }
10486
10487        *list_length_ptr = strlcat(paniclist, identPlusVers, list_size);
10488        *list_length_ptr = strlcat(paniclist, "\n", list_size);
10489
10490    } while (i--);
10491
10492finish:
10493    if (!error) {
10494        if (*list_length_ptr + 1 <= list_size) {
10495            result = list_size - (*list_length_ptr + 1);
10496        }
10497    }
10498
10499    return result;
10500}
10501
10502/*********************************************************************
10503*********************************************************************/
10504/* static */
10505void
10506OSKext::saveLoadedKextPanicList(void)
10507{
10508    char     * newlist        = NULL;
10509    uint32_t   newlist_size   = 0;
10510    uint32_t   newlist_length = 0;
10511
10512    newlist_length = 0;
10513    newlist_size = KEXT_PANICLIST_SIZE;
10514    newlist = (char *)kalloc(newlist_size);
10515
10516    if (!newlist) {
10517        OSKextLog(/* kext */ NULL,
10518            kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
10519            "Couldn't allocate kext panic log buffer.");
10520        goto finish;
10521    }
10522
10523    newlist[0] = '\0';
10524
10525    // non-"com.apple." kexts
10526    if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
10527        /* libs? */ -1, newlist, newlist_size, &newlist_length)) {
10528
10529        goto finish;
10530    }
10531    // "com.apple." nonlibrary kexts
10532    if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10533        /* libs? */ 0, newlist, newlist_size, &newlist_length)) {
10534
10535        goto finish;
10536    }
10537    // "com.apple." library kexts
10538    if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10539        /* libs? */ 1, newlist, newlist_size, &newlist_length)) {
10540
10541        goto finish;
10542    }
10543
10544    if (loaded_kext_paniclist) {
10545        kfree(loaded_kext_paniclist, loaded_kext_paniclist_size);
10546    }
10547    loaded_kext_paniclist = newlist;
10548    loaded_kext_paniclist_size = newlist_size;
10549    loaded_kext_paniclist_length = newlist_length;
10550
10551finish:
10552    return;
10553}
10554
10555/*********************************************************************
10556* Assumes sKextLock is held.
10557*********************************************************************/
10558void
10559OSKext::savePanicString(bool isLoading)
10560{
10561    u_long len;
10562
10563    if (!kmod_info) {
10564        return;  // do not goto finish here b/c of lock
10565    }
10566
10567    len = assemble_identifier_and_version(kmod_info,
10568        (isLoading) ? last_loaded_str : last_unloaded_str);
10569    if (!len) {
10570        printf("error saving unloaded kext info\n");
10571        goto finish;
10572    }
10573
10574    if (isLoading) {
10575        last_loaded_strlen = len;
10576        last_loaded_address = (void *)kmod_info->address;
10577        last_loaded_size = kmod_info->size;
10578        clock_get_uptime(&last_loaded_timestamp);
10579    } else {
10580        last_unloaded_strlen = len;
10581        last_unloaded_address = (void *)kmod_info->address;
10582        last_unloaded_size = kmod_info->size;
10583        clock_get_uptime(&last_unloaded_timestamp);
10584    }
10585
10586finish:
10587    return;
10588}
10589
10590/*********************************************************************
10591*********************************************************************/
10592/* static */
10593void
10594OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
10595{
10596    if (last_loaded_strlen) {
10597        printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
10598            AbsoluteTime_to_scalar(&last_loaded_timestamp),
10599            last_loaded_strlen, last_loaded_str,
10600            last_loaded_address, last_loaded_size);
10601    }
10602
10603    if (last_unloaded_strlen) {
10604        printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
10605            AbsoluteTime_to_scalar(&last_unloaded_timestamp),
10606            last_unloaded_strlen, last_unloaded_str,
10607            last_unloaded_address, last_unloaded_size);
10608    }
10609
10610    printf_func("loaded kexts:\n");
10611    if (loaded_kext_paniclist &&
10612        pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
10613        loaded_kext_paniclist[0]) {
10614
10615        printf_func("%.*s", loaded_kext_paniclist_length, loaded_kext_paniclist);
10616    } else {
10617        printf_func("(none)\n");
10618    }
10619    return;
10620}
10621
10622/*********************************************************************
10623* Assumes sKextLock is held.
10624*********************************************************************/
10625/* static */
10626void
10627OSKext::updateLoadedKextSummaries(void)
10628{
10629    kern_return_t result = KERN_FAILURE;
10630    OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
10631    OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
10632    OSKext *aKext;
10633    vm_map_offset_t start, end;
10634    size_t summarySize = 0;
10635    size_t size;
10636    u_int count;
10637    u_int numKexts;
10638    u_int i, j;
10639
10640    IOLockLock(sKextSummariesLock);
10641
10642    count = sLoadedKexts->getCount();
10643    for (i = 0, numKexts = 0; i < count; ++i) {
10644        aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
10645        numKexts += (aKext && aKext->isExecutable());
10646    }
10647
10648    if (!numKexts) goto finish;
10649
10650   /* Calculate the size needed for the new summary headers.
10651    */
10652
10653    size = sizeof(*gLoadedKextSummaries);
10654    size += numKexts * sizeof(*gLoadedKextSummaries->summaries);
10655    size = round_page(size);
10656
10657   /* If the previous summary is large enough, use it (and be sure to make
10658    * it writable). If it's too small, free it and allocate a new buffer.
10659    */
10660
10661    if (sPrevLoadedKextSummariesAllocSize < size) {
10662        if (sPrevLoadedKextSummaries) {
10663            kmem_free(kernel_map, (vm_offset_t)sPrevLoadedKextSummaries,
10664                sPrevLoadedKextSummariesAllocSize);
10665            sPrevLoadedKextSummaries = NULL;
10666            sPrevLoadedKextSummariesAllocSize = 0;
10667        }
10668
10669        result = kmem_alloc(kernel_map,
10670            (vm_offset_t*)&summaryHeaderAlloc, size);
10671        if (result != KERN_SUCCESS) goto finish;
10672
10673        summaryHeader = summaryHeaderAlloc;
10674        summarySize = size;
10675    } else {
10676        summaryHeader = sPrevLoadedKextSummaries;
10677        summarySize = sPrevLoadedKextSummariesAllocSize;
10678
10679        start = (vm_map_offset_t) summaryHeader;
10680        end = start + summarySize;
10681        result = vm_map_protect(kernel_map, start, end, VM_PROT_DEFAULT, FALSE);
10682        if (result != KERN_SUCCESS) goto finish;
10683    }
10684
10685   /* Populate the summary header.
10686    */
10687
10688    bzero(summaryHeader, summarySize);
10689    summaryHeader->version = kOSKextLoadedKextSummaryVersion;
10690    summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
10691    summaryHeader->numSummaries = numKexts;
10692
10693   /* Populate each kext summary.
10694    */
10695
10696    count = sLoadedKexts->getCount();
10697    for (i = 0, j = 0; i < count; ++i) {
10698        aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
10699        if (!aKext || !aKext->isExecutable()) continue;
10700
10701        aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
10702    }
10703
10704   /* Write protect the buffer and move it into place.
10705    */
10706
10707    start = (vm_map_offset_t) summaryHeader;
10708    end = start + summarySize;
10709    result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
10710    if (result != KERN_SUCCESS) goto finish;
10711
10712    sPrevLoadedKextSummaries = gLoadedKextSummaries;
10713    sPrevLoadedKextSummariesAllocSize = sLoadedKextSummariesAllocSize;
10714
10715    gLoadedKextSummaries = summaryHeader;
10716    sLoadedKextSummariesAllocSize = summarySize;
10717
10718    summaryHeaderAlloc = NULL;
10719
10720   /* Call the magic breakpoint function through a static function pointer so
10721    * the compiler can't optimize the function away.
10722    */
10723    if (sLoadedKextSummariesUpdated) (*sLoadedKextSummariesUpdated)();
10724
10725finish:
10726    IOLockUnlock(sKextSummariesLock);
10727
10728   /* If we had to allocate a new buffer but failed to generate the summaries,
10729    * free that now.
10730    */
10731    if (summaryHeaderAlloc) {
10732        kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
10733    }
10734
10735    return;
10736}
10737
10738/*********************************************************************
10739*********************************************************************/
10740void
10741OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
10742{
10743    OSData *uuid;
10744
10745    strlcpy(summary->name, getIdentifierCString(),
10746        sizeof(summary->name));
10747
10748    uuid = copyUUID();
10749    if (uuid) {
10750        memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
10751        OSSafeRelease(uuid);
10752    }
10753
10754    summary->address = kmod_info->address;
10755    summary->size = kmod_info->size;
10756    summary->version = getVersion();
10757    summary->loadTag = kmod_info->id;
10758    summary->flags = 0;
10759    summary->reference_list = (uint64_t) kmod_info->reference_list;
10760
10761    return;
10762}
10763
10764/*********************************************************************
10765*********************************************************************/
10766
10767#if CONFIG_KEC_FIPS
10768
10769#if PRAGMA_MARK
10770#pragma mark Kernel External Components for FIPS compliance
10771#endif
10772
10773/*********************************************************************
10774 * Kernel External Components for FIPS compliance (KEC_FIPS)
10775 *********************************************************************/
10776static void *
10777GetAppleTEXTHashForKext(OSKext * theKext, OSDictionary *theInfoDict)
10778{
10779    AppleTEXTHash_t         my_ath = {1, 0, NULL};
10780    AppleTEXTHash_t *       my_athp = NULL;         // do not release
10781    OSDictionary *          textHashDict = NULL;    // do not release
10782    OSData *                segmentHash = NULL;     // do not release
10783
10784    if (theKext == NULL || theInfoDict == NULL) {
10785        return(NULL);
10786    }
10787
10788    textHashDict = OSDynamicCast(OSDictionary, theInfoDict->getObject(kAppleTextHashesKey));
10789    if (textHashDict == NULL) {
10790        return(NULL);
10791    }
10792
10793    segmentHash = OSDynamicCast(OSData,
10794                                textHashDict->getObject(ARCHNAME));
10795    if (segmentHash == NULL) {
10796        return(NULL);
10797    }
10798
10799    // KEC_FIPS type kexts never unload so we don't have to clean up our
10800    // AppleTEXTHash_t
10801    if (kmem_alloc(kernel_map, (vm_offset_t *) &my_athp,
10802                   sizeof(AppleTEXTHash_t)) != KERN_SUCCESS) {
10803        return(NULL);
10804    }
10805
10806    memcpy(my_athp, &my_ath, sizeof(my_ath));
10807    my_athp->ath_length = segmentHash->getLength();
10808    if (my_athp->ath_length > 0) {
10809        my_athp->ath_hash = (void *)segmentHash->getBytesNoCopy();
10810    }
10811
10812#if 0
10813    OSKextLog(theKext,
10814              kOSKextLogErrorLevel |
10815              kOSKextLogGeneralFlag,
10816              "Kext %s ath_version %d ath_length %d ath_hash %p",
10817              theKext->getIdentifierCString(),
10818              my_athp->ath_version,
10819              my_athp->ath_length,
10820              my_athp->ath_hash);
10821#endif
10822
10823    return( (void *) my_athp );
10824}
10825
10826#endif // CONFIG_KEC_FIPS
10827
10828