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