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