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