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