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