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