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