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