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