xref: /xnu-11215/libkern/c++/OSKext.cpp (revision e6231be0)
1 /*
2  * Copyright (c) 2008-2021 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 #define IOKIT_ENABLE_SHARED_PTR
30 
31 extern "C" {
32 #include <string.h>
33 #include <kern/clock.h>
34 #include <kern/host.h>
35 #include <kern/kext_alloc.h>
36 #include <firehose/tracepoint_private.h>
37 #include <firehose/chunk_private.h>
38 #include <os/firehose_buffer_private.h>
39 #include <vm/vm_map.h>
40 #include <kextd/kextd_mach.h>
41 #include <libkern/kernel_mach_header.h>
42 #include <libkern/kext_panic_report.h>
43 #include <libkern/kext_request_keys.h>
44 #include <libkern/mkext.h>
45 #include <libkern/prelink.h>
46 #include <libkern/version.h>
47 #include <libkern/zlib.h>
48 #include <mach/host_special_ports.h>
49 #include <mach/mach_vm.h>
50 #include <mach/mach_time.h>
51 #include <uuid/uuid.h>
52 #include <sys/random.h>
53 #include <pexpert/pexpert.h>
54 
55 #include <sys/pgo.h>
56 
57 #if CONFIG_CSR
58 #include <sys/csr.h>
59 #include <sys/stat.h>
60 #include <sys/vnode.h>
61 #endif /* CONFIG_CSR */
62 };
63 
64 #if CONFIG_MACF
65 #include <sys/kauth.h>
66 #include <security/mac_framework.h>
67 #endif
68 
69 #include <vm/vm_kern.h>
70 #include <sys/sysctl.h>
71 #include <kern/task.h>
72 #include <os/cpp_util.h>
73 
74 #include <libkern/OSKextLibPrivate.h>
75 #include <libkern/c++/OSKext.h>
76 #include <libkern/c++/OSLib.h>
77 
78 #include <IOKit/IOLib.h>
79 #include <IOKit/IOCatalogue.h>
80 #include <IOKit/IORegistryEntry.h>
81 #include <IOKit/IOService.h>
82 #include <IOKit/IOUserServer.h>
83 
84 #include <IOKit/IOStatisticsPrivate.h>
85 #include <IOKit/IOBSD.h>
86 #include <IOKit/IOPlatformExpert.h>
87 
88 #include <san/kasan.h>
89 
90 #if PRAGMA_MARK
91 #pragma mark External & Internal Function Protos
92 #endif
93 /*********************************************************************
94 *********************************************************************/
95 extern "C" {
96 extern int  IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
97 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
98 
99 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
100 extern int dtrace_keep_kernel_symbols(void);
101 
102 #if defined(__x86_64__) || defined(__i386__)
103 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide);
104 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers);
105 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size);
106 static void *allocate_kcfileset_map_entry_list(void);
107 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size);
108 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable);
109 int vnode_put(struct vnode *vp);
110 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size,
111     void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot);
112 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size);
113 void * ubc_getobject(struct vnode *vp, __unused int flags);
114 #endif //(__x86_64__) || defined(__i386__)
115 }
116 
117 extern unsigned long gVirtBase;
118 extern unsigned long gPhysBase;
119 extern vm_map_t g_kext_map;
120 
121 bool pageableKCloaded = false;
122 bool auxKCloaded = false;
123 bool resetAuxKCSegmentOnUnload = false;
124 
125 extern boolean_t pageablekc_uuid_valid;
126 extern uuid_t pageablekc_uuid;
127 extern uuid_string_t pageablekc_uuid_string;
128 
129 extern boolean_t auxkc_uuid_valid;
130 extern uuid_t auxkc_uuid;
131 extern uuid_string_t auxkc_uuid_string;
132 
133 static OSReturn _OSKextCreateRequest(
134 	const char    * predicate,
135 	OSSharedPtr<OSDictionary> & requestP);
136 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
137 static OSObject * _OSKextGetRequestArgument(
138 	OSDictionary * requestDict,
139 	const char   * argName);
140 static bool _OSKextSetRequestArgument(
141 	OSDictionary * requestDict,
142 	const char   * argName,
143 	OSObject     * value);
144 static void * _OSKextExtractPointer(OSData * wrapper);
145 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSData * wrapper);
146 static OSReturn _OSDictionarySetCStringValue(
147 	OSDictionary * dict,
148 	const char   * key,
149 	const char   * value);
150 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
151 #if CONFIG_KXLD
152 static bool _OSKextInPrelinkRebuildWindow(void);
153 #endif
154 
155 // We really should add containsObject() & containsCString to OSCollection & subclasses.
156 // So few pad slots, though....
157 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
158 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
159 
160 /* Prelinked arm kexts do not have VM entries because the method we use to
161  * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
162  * not work on ARM.  To get around that, we must free prelinked kext
163  * executables with ml_static_mfree() instead of kext_free().
164  */
165 #if __i386__ || __x86_64__
166 #define VM_MAPPED_KEXTS 1
167 #define KASLR_KEXT_DEBUG 0
168 #define KASLR_IOREG_DEBUG 0
169 #elif __arm__ || __arm64__
170 #define VM_MAPPED_KEXTS 0
171 #define KASLR_KEXT_DEBUG 0
172 #else
173 #error Unsupported architecture
174 #endif
175 
176 #if PRAGMA_MARK
177 #pragma mark Constants & Macros
178 #endif
179 /*********************************************************************
180 * Constants & Macros
181 *********************************************************************/
182 
183 /* Use this number to create containers.
184  */
185 #define kOSKextTypicalLoadCount      (150)
186 
187 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
188  * A loaded kext will no dependents or external retains will have 2 retains.
189  */
190 #define kOSKextMinRetainCount        (1)
191 #define kOSKextMinLoadedRetainCount  (2)
192 
193 /**********
194  * Strings and substrings used in dependency resolution.
195  */
196 #define APPLE_KEXT_PREFIX            "com.apple."
197 #define KERNEL_LIB                   "com.apple.kernel"
198 
199 #define PRIVATE_KPI                  "com.apple.kpi.private"
200 
201 /* Version for compatbility pseudokexts (com.apple.kernel.*),
202  * compatible back to v6.0.
203  */
204 #define KERNEL6_LIB                  "com.apple.kernel.6.0"
205 #define KERNEL6_VERSION              "7.9.9"
206 
207 #define KERNEL_LIB_PREFIX            "com.apple.kernel."
208 #define KPI_LIB_PREFIX               "com.apple.kpi."
209 
210 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0)
211 
212 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
213 #define MINIMUM_WAKEUP_SECONDS (30)
214 
215 /*********************************************************************
216 * infoDict keys for internally-stored data. Saves on ivar slots for
217 * objects we don't keep around past boot time or during active load.
218 *********************************************************************/
219 
220 /* A usable, uncompressed file is stored under this key.
221  */
222 #define _kOSKextExecutableKey                "_OSKextExecutable"
223 
224 /* An indirect reference to the executable file from an mkext
225  * is stored under this key.
226  */
227 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference"
228 
229 /* If the file is contained in a larger buffer laid down by the booter or
230  * sent from user space, the OSKext stores that OSData under this key so that
231  * references are properly tracked. This is always an mkext, right now.
232  */
233 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData"
234 
235 #define OS_LOG_HDR_VERSION  1
236 #define NUM_OS_LOG_SECTIONS 3
237 
238 #define OS_LOG_SECT_IDX         0
239 #define CSTRING_SECT_IDX        1
240 #define ASAN_CSTRING_SECT_IDX   2
241 
242 #if PRAGMA_MARK
243 #pragma mark Typedefs
244 #endif
245 /*********************************************************************
246 * Typedefs
247 *********************************************************************/
248 
249 /*********************************************************************
250 * osLogDataHeaderRef describes the header information of an OSData
251 * object that is returned when querying for kOSBundleLogStringsKey.
252 * We currently return information regarding 2 sections - os_log and
253 * cstring. In the case that the os_log section doesn't exist, we just
254 * return an offset and length of 0 for that section.
255 *********************************************************************/
256 typedef struct osLogDataHeader {
257 	uint32_t version;
258 	uint32_t sect_count;
259 	struct {
260 		uint32_t sect_offset;
261 		uint32_t sect_size;
262 	} sections[0];
263 } osLogDataHeaderRef;
264 
265 /*********************************************************************
266 * MkextEntryRef describes the contents of an OSData object
267 * referencing a file entry from an mkext so that we can uncompress
268 * (if necessary) and extract it on demand.
269 *
270 * It contains the mkextVersion in case we ever wind up supporting
271 * multiple mkext formats. Mkext format 1 is officially retired as of
272 * Snow Leopard.
273 *********************************************************************/
274 typedef struct MkextEntryRef {
275 	mkext_basic_header * mkext; // beginning of whole mkext file
276 	void               * fileinfo;// mkext2_file_entry or equiv; see mkext.h
277 } MkextEntryRef;
278 
279 #if PRAGMA_MARK
280 #pragma mark Global and static Module Variables
281 #endif
282 /*********************************************************************
283 * Global & static variables, used to keep track of kexts.
284 *********************************************************************/
285 
286 static  bool                sPrelinkBoot               = false;
287 static  bool                sSafeBoot                  = false;
288 static  bool                sKeepSymbols               = false;
289 static  bool                sPanicOnKCMismatch         = false;
290 static  bool                sOSKextWasResetAfterUserspaceReboot = false;
291 
292 /*********************************************************************
293  * sKextLock is the principal lock for OSKext, and guards all static
294  * and global variables not owned by other locks (declared further
295  * below). It must be taken by any entry-point method or function,
296  * including internal functions called on scheduled threads.
297  *
298  * sKextLock and sKextInnerLock are recursive due to multiple functions
299  * that are called both externally and internally. The other locks are
300  * nonrecursive.
301  *
302  * Which locks are taken depends on what they protect, but if more than
303  * one must be taken, they must always be locked in this order
304  * (and unlocked in reverse order) to prevent deadlocks:
305  *
306  *    1. sKextLock
307  *    2. sKextInnerLock
308  *    3. sKextSummariesLock
309  *    4. sKextLoggingLock
310  */
311 static IORecursiveLock    * sKextLock                  = NULL;
312 
313 static OSSharedPtr<OSDictionary>   sKextsByID;
314 static OSSharedPtr<OSDictionary>   sExcludeListByID;
315 static OSKextVersion               sExcludeListVersion        = 0;
316 static OSSharedPtr<OSArray>        sLoadedKexts;
317 static OSSharedPtr<OSDictionary>   sNonLoadableKextsByID;
318 static OSSharedPtr<OSArray>        sUnloadedPrelinkedKexts;
319 static OSSharedPtr<OSArray>        sLoadedDriverKitKexts;
320 
321 // Requests to the IOKit daemon waiting to be picked up.
322 static OSSharedPtr<OSArray>        sKernelRequests;
323 // Identifier of kext load requests in sKernelRequests
324 static OSSharedPtr<OSSet>          sPostedKextLoadIdentifiers;
325 static OSSharedPtr<OSArray>        sRequestCallbackRecords;
326 
327 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
328 static OSSharedPtr<OSSet>          sAllKextLoadIdentifiers;
329 #if CONFIG_KXLD
330 static KXLDContext        * sKxldContext               = NULL;
331 #endif
332 static uint32_t             sNextLoadTag               = 0;
333 static uint32_t             sNextRequestTag            = 0;
334 
335 static bool                 sUserLoadsActive           = false;
336 static bool                 sIOKitDaemonActive         = false;
337 static bool                 sDeferredLoadSucceeded     = false;
338 static bool                 sConsiderUnloadsExecuted   = false;
339 
340 #if NO_KEXTD
341 static bool                 sKernelRequestsEnabled     = false;
342 #else
343 static bool                 sKernelRequestsEnabled     = true;
344 #endif
345 static bool                 sLoadEnabled               = true;
346 static bool                 sUnloadEnabled             = true;
347 
348 /*********************************************************************
349  * Stuff for the OSKext representing the kernel itself.
350  **********/
351 static OSKext          * sKernelKext             = NULL;
352 
353 /* Set up a fake kmod_info struct for the kernel.
354  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
355  * before OSKext is initialized; that call only needs the name
356  * and address to be set correctly.
357  *
358  * We don't do much else with the kerne's kmod_info; we never
359  * put it into the kmod list, never adjust the reference count,
360  * and never have kernel components reference it.
361  * For that matter, we don't do much with kmod_info structs
362  * at all anymore! We just keep them filled in for gdb and
363  * binary compability.
364  */
365 kmod_info_t g_kernel_kmod_info = {
366 	.next =            NULL,
367 	.info_version =    KMOD_INFO_VERSION,
368 	.id =              0,             // loadTag: kernel is always 0
369 	.name =            kOSKextKernelIdentifier,// bundle identifier
370 	.version =         "0",           // filled in in OSKext::initialize()
371 	.reference_count = -1,            // never adjusted; kernel never unloads
372 	.reference_list =  NULL,
373 	.address =         0,
374 	.size =            0,             // filled in in OSKext::initialize()
375 	.hdr_size =        0,
376 	.start =           NULL,
377 	.stop =            NULL
378 };
379 
380 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
381 
382 kmod_info_t invalid_kmod_info = {
383 	.next =            NULL,
384 	.info_version =    KMOD_INFO_VERSION,
385 	.id =              UINT32_MAX,
386 	.name =            "invalid",
387 	.version =         "0",
388 	.reference_count = -1,
389 	.reference_list =  NULL,
390 	.address =         0,
391 	.size =            0,
392 	.hdr_size =        0,
393 	.start =           NULL,
394 	.stop =            NULL
395 };
396 
397 extern "C" {
398 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
399 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
400 // misc_protos.h, db_low_trace.c, kgmacros
401 // 'kmod' is a holdover from the old kmod system, we can't rename it.
402 kmod_info_t * kmod = NULL;
403 
404 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE)
405 
406 
407 static char     * loaded_kext_paniclist         = NULL;
408 static uint32_t   loaded_kext_paniclist_size    = 0;
409 
410 AbsoluteTime      last_loaded_timestamp;
411 static char       last_loaded_str_buf[2 * KMOD_MAX_NAME];
412 static u_long     last_loaded_strlen            = 0;
413 static void     * last_loaded_address           = NULL;
414 static u_long     last_loaded_size              = 0;
415 
416 AbsoluteTime      last_unloaded_timestamp;
417 static char       last_unloaded_str_buf[2 * KMOD_MAX_NAME];
418 static u_long     last_unloaded_strlen          = 0;
419 static void     * last_unloaded_address         = NULL;
420 static u_long     last_unloaded_size            = 0;
421 
422 // Statically linked kmods described by several mach-o sections:
423 //
424 // kPrelinkInfoSegment:kBuiltinInfoSection
425 // Array of pointers to kmod_info_t structs.
426 //
427 // kPrelinkInfoSegment:kBuiltinInfoSection
428 // Array of pointers to an embedded mach-o header.
429 //
430 // __DATA:kBuiltinInitSection, kBuiltinTermSection
431 // Structors for all kmods. Has to be filtered by proc address.
432 //
433 
434 static uint32_t gBuiltinKmodsCount;
435 static kernel_section_t * gBuiltinKmodsSectionInfo;
436 static kernel_section_t * gBuiltinKmodsSectionStart;
437 
438 const OSSymbol              * gIOSurfaceIdentifier;
439 vm_tag_t                      gIOSurfaceTag;
440 
441 /*********************************************************************
442  * sKextInnerLock protects against cross-calls with IOService and
443  * IOCatalogue, and owns the variables declared immediately below.
444  *
445  * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
446  *
447  * When both sKextLock and sKextInnerLock need to be taken,
448  * always lock sKextLock first and unlock it second. Never take both
449  * locks in an entry point to OSKext; if you need to do so, you must
450  * spawn an independent thread to avoid potential deadlocks for threads
451  * calling into OSKext.
452  **********/
453 static IORecursiveLock *    sKextInnerLock             = NULL;
454 
455 #if XNU_TARGET_OS_OSX
456 static bool                 sAutounloadEnabled         = true;
457 #endif
458 static bool                 sConsiderUnloadsCalled     = false;
459 static bool                 sConsiderUnloadsPending    = false;
460 
461 static unsigned int         sConsiderUnloadDelay       = 60;     // seconds
462 static thread_call_t        sUnloadCallout             = NULL;
463 #if CONFIG_KXLD
464 static thread_call_t        sDestroyLinkContextThread  = NULL;   // one-shot, one-at-a-time thread
465 #endif // CONFIG_KXLD
466 static bool                 sSystemSleep               = false;  // true when system going to sleep
467 static AbsoluteTime         sLastWakeTime;                       // last time we woke up
468 
469 /*********************************************************************
470  * Backtraces can be printed at various times so we need a tight lock
471  * on data used for that. sKextSummariesLock protects the variables
472  * declared immediately below.
473  *
474  * gLoadedKextSummaries is accessed by other modules, but only during
475  * a panic so the lock isn't needed then.
476  *
477  * gLoadedKextSummaries has the "used" attribute in order to ensure
478  * that it remains visible even when we are performing extremely
479  * aggressive optimizations, as it is needed to allow the debugger
480  * to automatically parse the list of loaded kexts.
481  **********/
482 static IOLock                 * sKextSummariesLock                = NULL;
483 extern "C" lck_spin_t           vm_allocation_sites_lock;
484 static IOSimpleLock           * sKextAccountsLock = &vm_allocation_sites_lock;
485 
486 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
487 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
488 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
489 static size_t sLoadedKextSummariesAllocSize = 0;
490 
491 static OSKextActiveAccount    * sKextAccounts;
492 static uint32_t                 sKextAccountsCount;
493 };
494 
495 /*********************************************************************
496  * sKextLoggingLock protects the logging variables declared immediately below.
497  **********/
498 static IOLock                 * sKextLoggingLock           = NULL;
499 
500 static  const OSKextLogSpec     kDefaultKernelLogFilter    = kOSKextLogBasicLevel |
501     kOSKextLogVerboseFlagsMask;
502 static  OSKextLogSpec           sKernelLogFilter           = kDefaultKernelLogFilter;
503 static  bool                    sBootArgLogFilterFound     = false;
504 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
505     0, "kernel kext logging");
506 
507 static  OSKextLogSpec           sUserSpaceKextLogFilter    = kOSKextLogSilentFilter;
508 static  OSSharedPtr<OSArray>    sUserSpaceLogSpecArray;
509 static  OSSharedPtr<OSArray>    sUserSpaceLogMessageArray;
510 
511 /*********
512  * End scope for sKextInnerLock-protected variables.
513  *********************************************************************/
514 
515 
516 /*********************************************************************
517  *  helper function used for collecting PGO data upon unload of a kext
518  */
519 
520 static int OSKextGrabPgoDataLocked(OSKext *kext,
521     bool metadata,
522     uuid_t instance_uuid,
523     uint64_t *pSize,
524     char *pBuffer,
525     uint64_t bufferSize);
526 
527 /**********************************************************************/
528 
529 
530 
531 #if PRAGMA_MARK
532 #pragma mark OSData callbacks (need to move to OSData)
533 #endif
534 /*********************************************************************
535 * C functions used for callbacks.
536 *********************************************************************/
537 extern "C" {
538 void
539 osdata_kmem_free(void * ptr, unsigned int length)
540 {
541 	kmem_free(kernel_map, (vm_address_t)ptr, length);
542 	return;
543 }
544 
545 void
546 osdata_phys_free(void * ptr, unsigned int length)
547 {
548 	ml_static_mfree((vm_offset_t)ptr, length);
549 	return;
550 }
551 
552 void
553 osdata_vm_deallocate(void * ptr, unsigned int length)
554 {
555 	(void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
556 	return;
557 }
558 
559 void
560 osdata_kext_free(void * ptr, unsigned int length)
561 {
562 	(void)kext_free((vm_offset_t)ptr, length);
563 }
564 };
565 
566 #if PRAGMA_MARK
567 #pragma mark KXLD Allocation Callback
568 #endif
569 #if CONFIG_KXLD
570 /*********************************************************************
571 * KXLD Allocation Callback
572 *********************************************************************/
573 kxld_addr_t
574 kern_allocate(
575 	u_long              size,
576 	KXLDAllocateFlags * flags,
577 	void              * user_data)
578 {
579 	vm_address_t  result       = 0; // returned
580 	kern_return_t mach_result  = KERN_FAILURE;
581 	bool          success      = false;
582 	OSKext      * theKext      = (OSKext *)user_data;
583 	unsigned int  roundSize    = 0;
584 	OSSharedPtr<OSData>      linkBuffer;
585 
586 	if (round_page(size) > UINT_MAX) {
587 		OSKextLog(theKext,
588 		    kOSKextLogErrorLevel |
589 		    kOSKextLogGeneralFlag,
590 		    "%s: Requested memory size is greater than UINT_MAX.",
591 		    theKext->getIdentifierCString());
592 		goto finish;
593 	}
594 
595 	roundSize = (unsigned int)round_page(size);
596 
597 	mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
598 	if (mach_result != KERN_SUCCESS) {
599 		OSKextLog(theKext,
600 		    kOSKextLogErrorLevel |
601 		    kOSKextLogGeneralFlag,
602 		    "Can't allocate kernel memory to link %s.",
603 		    theKext->getIdentifierCString());
604 		goto finish;
605 	}
606 
607 	/* Create an OSData wrapper for the allocated buffer.
608 	 */
609 	linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
610 	if (!linkBuffer) {
611 		OSKextLog(theKext,
612 		    kOSKextLogErrorLevel |
613 		    kOSKextLogGeneralFlag,
614 		    "Can't allocate linked executable wrapper for %s.",
615 		    theKext->getIdentifierCString());
616 		goto finish;
617 	}
618 	linkBuffer->setDeallocFunction(osdata_kext_free);
619 	OSKextLog(theKext,
620 	    kOSKextLogProgressLevel |
621 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
622 	    "Allocated link buffer for kext %s at %p (%lu bytes).",
623 	    theKext->getIdentifierCString(),
624 	    (void *)result, (unsigned long)roundSize);
625 
626 	theKext->setLinkedExecutable(linkBuffer.get());
627 
628 	*flags = kKxldAllocateWritable;
629 	success = true;
630 
631 finish:
632 	if (!success && result) {
633 		kext_free(result, roundSize);
634 		result = 0;
635 	}
636 
637 	return (kxld_addr_t)result;
638 }
639 
640 /*********************************************************************
641 *********************************************************************/
642 void
643 kxld_log_callback(
644 	KXLDLogSubsystem    subsystem,
645 	KXLDLogLevel        level,
646 	const char        * format,
647 	va_list             argList,
648 	void              * user_data)
649 {
650 	OSKext *theKext = (OSKext *) user_data;
651 	OSKextLogSpec logSpec = 0;
652 
653 	switch (subsystem) {
654 	case kKxldLogLinking:
655 		logSpec |= kOSKextLogLinkFlag;
656 		break;
657 	case kKxldLogPatching:
658 		logSpec |= kOSKextLogPatchFlag;
659 		break;
660 	}
661 
662 	switch (level) {
663 	case kKxldLogExplicit:
664 		logSpec |= kOSKextLogExplicitLevel;
665 		break;
666 	case kKxldLogErr:
667 		logSpec |= kOSKextLogErrorLevel;
668 		break;
669 	case kKxldLogWarn:
670 		logSpec |= kOSKextLogWarningLevel;
671 		break;
672 	case kKxldLogBasic:
673 		logSpec |= kOSKextLogProgressLevel;
674 		break;
675 	case kKxldLogDetail:
676 		logSpec |= kOSKextLogDetailLevel;
677 		break;
678 	case kKxldLogDebug:
679 		logSpec |= kOSKextLogDebugLevel;
680 		break;
681 	}
682 
683 	OSKextVLog(theKext, logSpec, format, argList);
684 }
685 #endif // CONFIG_KXLD
686 
687 #if PRAGMA_MARK
688 #pragma mark IOStatistics defines
689 #endif
690 
691 #if IOKITSTATS
692 
693 #define notifyKextLoadObservers(kext, kmod_info) \
694 do { \
695     IOStatistics::onKextLoad(kext, kmod_info); \
696 } while (0)
697 
698 #define notifyKextUnloadObservers(kext) \
699 do { \
700     IOStatistics::onKextUnload(kext); \
701 } while (0)
702 
703 #define notifyAddClassObservers(kext, addedClass, flags) \
704 do { \
705     IOStatistics::onClassAdded(kext, addedClass); \
706 } while (0)
707 
708 #define notifyRemoveClassObservers(kext, removedClass, flags) \
709 do { \
710     IOStatistics::onClassRemoved(kext, removedClass); \
711 } while (0)
712 
713 #else
714 
715 #define notifyKextLoadObservers(kext, kmod_info)
716 #define notifyKextUnloadObservers(kext)
717 #define notifyAddClassObservers(kext, addedClass, flags)
718 #define notifyRemoveClassObservers(kext, removedClass, flags)
719 
720 #endif /* IOKITSTATS */
721 
722 #if PRAGMA_MARK
723 #pragma mark Module Config (Startup & Shutdown)
724 #endif
725 /*********************************************************************
726 * Module Config (Class Definition & Class Methods)
727 *********************************************************************/
728 #define super OSObject
729 OSDefineMetaClassAndStructors(OSKext, OSObject)
730 
731 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject);
732 
733 /*********************************************************************
734 *********************************************************************/
735 /* static */
736 void
737 OSKext::initialize(void)
738 {
739 	OSSharedPtr<OSData>     kernelExecutable   = NULL;// do not release
740 	u_char          * kernelStart        = NULL;// do not free
741 	size_t            kernelLength       = 0;
742 	IORegistryEntry * registryRoot       = NULL;// do not release
743 	OSSharedPtr<OSNumber> kernelCPUType;
744 	OSSharedPtr<OSNumber> kernelCPUSubtype;
745 	OSKextLogSpec     bootLogFilter      = kOSKextLogSilentFilter;
746 	bool              setResult          = false;
747 	uint64_t        * timestamp          = NULL;
748 	__unused char     bootArgBuffer[16];// for PE_parse_boot_argn w/strings
749 
750 	/* This must be the first thing allocated. Everything else grabs this lock.
751 	 */
752 	sKextLock = IORecursiveLockAlloc();
753 	sKextInnerLock = IORecursiveLockAlloc();
754 	sKextSummariesLock = IOLockAlloc();
755 	sKextLoggingLock = IOLockAlloc();
756 	assert(sKextLock);
757 	assert(sKextInnerLock);
758 	assert(sKextSummariesLock);
759 	assert(sKextLoggingLock);
760 
761 	sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
762 	sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
763 	sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
764 	sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
765 	sKernelRequests = OSArray::withCapacity(0);
766 	sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
767 	sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
768 	sRequestCallbackRecords = OSArray::withCapacity(0);
769 	assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
770 	    sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
771 	    sRequestCallbackRecords && sUnloadedPrelinkedKexts);
772 
773 	/* Read the log flag boot-args and set the log flags.
774 	 */
775 	if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
776 		sBootArgLogFilterFound = true;
777 		sKernelLogFilter = bootLogFilter;
778 		// log this if any flags are set
779 		OSKextLog(/* kext */ NULL,
780 		    kOSKextLogBasicLevel |
781 		    kOSKextLogFlagsMask,
782 		    "Kernel kext log filter 0x%x per kextlog boot arg.",
783 		    (unsigned)sKernelLogFilter);
784 	}
785 
786 #if !defined(__arm__) && !defined(__arm64__)
787 	/*
788 	 * On our ARM targets, the kernelcache/boot kernel collection contains
789 	 * the set of kexts required to boot, as specified by KCB.  Safeboot is
790 	 * either unsupported, or is supported by the bootloader only loading
791 	 * the boot kernel collection; as a result OSKext has no role to play
792 	 * in safeboot policy on ARM.
793 	 */
794 	sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
795 	    sizeof(bootArgBuffer)) ? true : false;
796 #endif /* defined(__arm__) && defined(__arm64__) */
797 
798 	if (sSafeBoot) {
799 		OSKextLog(/* kext */ NULL,
800 		    kOSKextLogWarningLevel |
801 		    kOSKextLogGeneralFlag,
802 		    "SAFE BOOT DETECTED - "
803 		    "only valid OSBundleRequired kexts will be loaded.");
804 	}
805 
806 	PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
807 #if CONFIG_DTRACE
808 	if (dtrace_keep_kernel_symbols()) {
809 		sKeepSymbols = true;
810 	}
811 #endif /* CONFIG_DTRACE */
812 #if KASAN_DYNAMIC_BLACKLIST
813 	/* needed for function lookup */
814 	sKeepSymbols = true;
815 #endif
816 
817 	/*
818 	 * Should we panic when the SystemKC is not linked against the
819 	 * BootKC that was loaded by the booter? By default: yes, if the
820 	 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic
821 	 * on mis-match and instead just print an error and continue.
822 	 */
823 	sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer,
824 	    sizeof(bootArgBuffer)) ? false : true;
825 
826 	/* Set up an OSKext instance to represent the kernel itself.
827 	 */
828 	sKernelKext = new OSKext;
829 	assert(sKernelKext);
830 
831 	kernelStart = (u_char *)&_mh_execute_header;
832 	kernelLength = getlastaddr() - (vm_offset_t)kernelStart;
833 	assert(kernelLength <= UINT_MAX);
834 	kernelExecutable = OSData::withBytesNoCopy(
835 		kernelStart, (unsigned int)kernelLength);
836 	assert(kernelExecutable);
837 
838 #if KASLR_KEXT_DEBUG
839 	IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %lu (0x%016lx) \n",
840 	    (unsigned long)kernelStart,
841 	    (unsigned long)getlastaddr(),
842 	    kernelLength,
843 	    (unsigned long)vm_kernel_slide,
844 	    (unsigned long)vm_kernel_slide);
845 #endif
846 
847 	sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0
848 	sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier);
849 
850 	sKernelKext->version = OSKextParseVersionString(osrelease);
851 	sKernelKext->compatibleVersion = sKernelKext->version;
852 	sKernelKext->linkedExecutable = os::move(kernelExecutable);
853 	sKernelKext->interfaceUUID = sKernelKext->copyUUID();
854 
855 	sKernelKext->flags.hasAllDependencies = 1;
856 	sKernelKext->flags.kernelComponent = 1;
857 	sKernelKext->flags.prelinked = 0;
858 	sKernelKext->flags.loaded = 1;
859 	sKernelKext->flags.started = 1;
860 	sKernelKext->flags.CPPInitialized = 0;
861 	sKernelKext->flags.jettisonLinkeditSeg = 0;
862 
863 	sKernelKext->kmod_info = &g_kernel_kmod_info;
864 	strlcpy(g_kernel_kmod_info.version, osrelease,
865 	    sizeof(g_kernel_kmod_info.version));
866 	g_kernel_kmod_info.size = kernelLength;
867 	g_kernel_kmod_info.id = sKernelKext->loadTag;
868 
869 	/* Cons up an info dict, so we don't have to have special-case
870 	 * checking all over.
871 	 */
872 	sKernelKext->infoDict = OSDictionary::withCapacity(5);
873 	assert(sKernelKext->infoDict);
874 	setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey,
875 	    sKernelKext->bundleID.get());
876 	assert(setResult);
877 	setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey,
878 	    kOSBooleanTrue);
879 	assert(setResult);
880 
881 	{
882 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease));
883 		assert(scratchString);
884 		setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey,
885 		    scratchString.get());
886 		assert(setResult);
887 	}
888 
889 	{
890 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy("mach_kernel"));
891 		assert(scratchString);
892 		setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey,
893 		    scratchString.get());
894 		assert(setResult);
895 	}
896 
897 	/* Add the kernel kext to the bookkeeping dictionaries. Note that
898 	 * the kernel kext doesn't have a kmod_info struct. copyInfo()
899 	 * gathers info from other places anyhow.
900 	 */
901 	setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext);
902 	assert(setResult);
903 	setResult = sLoadedKexts->setObject(sKernelKext);
904 	assert(setResult);
905 
906 	// XXX: better way with OSSharedPtr?
907 	// sKernelKext remains a valid pointer even after the decref
908 	sKernelKext->release();
909 
910 	registryRoot = IORegistryEntry::getRegistryRoot();
911 	kernelCPUType = OSNumber::withNumber(
912 		(long long unsigned int)_mh_execute_header.cputype,
913 		8 * sizeof(_mh_execute_header.cputype));
914 	kernelCPUSubtype = OSNumber::withNumber(
915 		(long long unsigned int)_mh_execute_header.cpusubtype,
916 		8 * sizeof(_mh_execute_header.cpusubtype));
917 	assert(registryRoot && kernelCPUSubtype && kernelCPUType);
918 
919 	registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get());
920 	registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get());
921 
922 	gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
923 	if (gBuiltinKmodsSectionInfo) {
924 		uint32_t count;
925 
926 		assert(gBuiltinKmodsSectionInfo->addr);
927 		assert(gBuiltinKmodsSectionInfo->size);
928 		assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX);
929 		gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
930 
931 		gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
932 		assert(gBuiltinKmodsSectionStart);
933 		assert(gBuiltinKmodsSectionStart->addr);
934 		assert(gBuiltinKmodsSectionStart->size);
935 		assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX);
936 		count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
937 		// one extra pointer for the end of last kmod
938 		assert(count == (gBuiltinKmodsCount + 1));
939 
940 		vm_kernel_builtinkmod_text     = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
941 		vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
942 	}
943 
944 	// Don't track this object -- it's never released
945 	gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach();
946 
947 	timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
948 	*timestamp = 0;
949 	timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
950 	*timestamp = 0;
951 	timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
952 	*timestamp = 0;
953 
954 	OSKextLog(/* kext */ NULL,
955 	    kOSKextLogProgressLevel |
956 	    kOSKextLogGeneralFlag,
957 	    "Kext system initialized.");
958 
959 	notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
960 
961 	return;
962 }
963 
964 /*********************************************************************
965 * This is expected to be called exactly once, from exactly one thread
966 * context, during kernel bootstrap.
967 *********************************************************************/
968 /* static */
969 OSReturn
970 OSKext::removeKextBootstrap(void)
971 {
972 	OSReturn                   result                = kOSReturnError;
973 
974 	const char               * dt_kernel_header_name = "Kernel-__HEADER";
975 	const char               * dt_kernel_symtab_name = "Kernel-__SYMTAB";
976 	kernel_mach_header_t     * dt_mach_header        = NULL;
977 	int                        dt_mach_header_size   = 0;
978 	struct symtab_command    * dt_symtab             = NULL;
979 	int                        dt_symtab_size        = 0;
980 	int                        dt_result             = 0;
981 
982 	kernel_segment_command_t * seg_kld               = NULL;
983 	kernel_segment_command_t * seg_klddata           = NULL;
984 	kernel_segment_command_t * seg_linkedit          = NULL;
985 
986 	const char __unused      * dt_segment_name       = NULL;
987 	void       __unused      * segment_paddress      = NULL;
988 	int        __unused        segment_size          = 0;
989 
990 	OSKextLog(/* kext */ NULL,
991 	    kOSKextLogProgressLevel |
992 	    kOSKextLogGeneralFlag,
993 	    "Jettisoning kext bootstrap segments.");
994 
995 	/*
996 	 * keep the linkedit segment around when booted from a new MH_FILESET
997 	 * KC because all the kexts shared a linkedit segment.
998 	 */
999 	kc_format_t kc_format;
1000 	if (!PE_get_primary_kc_format(&kc_format)) {
1001 		OSKextLog(/* kext */ NULL,
1002 		    kOSKextLogErrorLevel |
1003 		    kOSKextLogGeneralFlag,
1004 		    "Unable to determine primary KC format");
1005 	}
1006 
1007 	/*****
1008 	 * Dispose of unnecessary stuff that the booter didn't need to load.
1009 	 */
1010 	dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
1011 	    (void **)&dt_mach_header, &dt_mach_header_size);
1012 	if (dt_result == 0 && dt_mach_header) {
1013 		IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
1014 		    round_page_32(dt_mach_header_size));
1015 	}
1016 	dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
1017 	    (void **)&dt_symtab, &dt_symtab_size);
1018 	if (dt_result == 0 && dt_symtab) {
1019 		IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
1020 		    round_page_32(dt_symtab_size));
1021 	}
1022 
1023 	/*****
1024 	 * KLD & KLDDATA bootstrap segments.
1025 	 */
1026 	// xxx - should rename KLD segment
1027 	seg_kld = getsegbyname("__KLD");
1028 	seg_klddata = getsegbyname("__KLDDATA");
1029 	if (seg_klddata) {
1030 		// __mod_term_func is part of __KLDDATA
1031 		OSRuntimeUnloadCPPForSegment(seg_klddata);
1032 	}
1033 
1034 #if __arm__ || __arm64__
1035 	/* Free the memory that was set up by iBoot.
1036 	 */
1037 #if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR)
1038 	/* We cannot free the KLD segment with CTRR enabled as it contains text and
1039 	 * is covered by the contiguous rorgn.
1040 	 */
1041 	dt_segment_name = "Kernel-__KLD";
1042 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1043 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1044 		    (int)segment_size); // calls ml_static_mfree
1045 	} else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1046 		/* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */
1047 		ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase),
1048 		    seg_kld->vmsize);
1049 	}
1050 #endif
1051 	dt_segment_name = "Kernel-__KLDDATA";
1052 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1053 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1054 		    (int)segment_size);  // calls ml_static_mfree
1055 	} else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1056 		/* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */
1057 		ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase),
1058 		    seg_klddata->vmsize);
1059 	}
1060 #elif __i386__ || __x86_64__
1061 	/* On x86, use the mapping data from the segment load command to
1062 	 * unload KLD & KLDDATA directly.
1063 	 * This may invalidate any assumptions about  "avail_start"
1064 	 * defining the lower bound for valid physical addresses.
1065 	 */
1066 	if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1067 		bzero((void *)seg_kld->vmaddr, seg_kld->vmsize);
1068 		ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
1069 	}
1070 	if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1071 		bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize);
1072 		ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
1073 	}
1074 #else
1075 #error arch
1076 #endif
1077 
1078 	/*****
1079 	 * Prelinked kernel's symtab (if there is one).
1080 	 */
1081 	if (kc_format != KCFormatFileset) {
1082 		kernel_section_t * sect;
1083 		sect = getsectbyname("__PRELINK", "__symtab");
1084 		if (sect && sect->addr && sect->size) {
1085 			ml_static_mfree(sect->addr, sect->size);
1086 		}
1087 	}
1088 
1089 	seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
1090 
1091 	/* kxld always needs the kernel's __LINKEDIT segment, but we can make it
1092 	 * pageable, unless keepsyms is set.  To do that, we have to copy it from
1093 	 * its booter-allocated memory, free the booter memory, reallocate proper
1094 	 * managed memory, then copy the segment back in.
1095 	 *
1096 	 * NOTE: This optimization is not valid for fileset KCs because each
1097 	 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment
1098 	 * that points to one fileset-global LINKEDIT segment. This
1099 	 * optimization is also only valid for platforms that support vm
1100 	 * mapped kexts or mapped kext collections (pageable KCs)
1101 	 */
1102 #if VM_MAPPED_KEXTS
1103 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1104 		kern_return_t mem_result;
1105 		void *seg_copy = NULL;
1106 		void *seg_data = NULL;
1107 		vm_map_offset_t seg_offset = 0;
1108 		vm_map_offset_t seg_copy_offset = 0;
1109 		vm_map_size_t seg_length = 0;
1110 
1111 		seg_data = (void *) seg_linkedit->vmaddr;
1112 		seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr;
1113 		seg_length = (vm_map_size_t) seg_linkedit->vmsize;
1114 
1115 		/* Allocate space for the LINKEDIT copy.
1116 		 */
1117 		mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
1118 		    seg_length, VM_KERN_MEMORY_KEXT);
1119 		if (mem_result != KERN_SUCCESS) {
1120 			OSKextLog(/* kext */ NULL,
1121 			    kOSKextLogErrorLevel |
1122 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1123 			    "Can't copy __LINKEDIT segment for VM reassign.");
1124 			return result;
1125 		}
1126 		seg_copy_offset = (vm_map_offset_t) seg_copy;
1127 
1128 		/* Copy it out.
1129 		 */
1130 		memcpy(seg_copy, seg_data, seg_length);
1131 
1132 		/* Dump the booter memory.
1133 		 */
1134 		ml_static_mfree(seg_offset, seg_length);
1135 
1136 		/* Set up the VM region.
1137 		 */
1138 		mem_result = vm_map_enter_mem_object(
1139 			kernel_map,
1140 			&seg_offset,
1141 			seg_length, /* mask */ 0,
1142 			VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
1143 			VM_MAP_KERNEL_FLAGS_NONE,
1144 			VM_KERN_MEMORY_NONE,
1145 			(ipc_port_t)NULL,
1146 			(vm_object_offset_t) 0,
1147 			/* copy */ FALSE,
1148 			/* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1149 			/* max_protection */ VM_PROT_ALL,
1150 			/* inheritance */ VM_INHERIT_DEFAULT);
1151 		if ((mem_result != KERN_SUCCESS) ||
1152 		    (seg_offset != (vm_map_offset_t) seg_data)) {
1153 			OSKextLog(/* kext */ NULL,
1154 			    kOSKextLogErrorLevel |
1155 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1156 			    "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1157 			    seg_data, seg_length, mem_result);
1158 			return result;
1159 		}
1160 
1161 		/* And copy it back.
1162 		 */
1163 		memcpy(seg_data, seg_copy, seg_length);
1164 
1165 		/* Free the copy.
1166 		 */
1167 		kmem_free(kernel_map, seg_copy_offset, seg_length);
1168 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1169 		/* Remove the linkedit segment of the Boot KC */
1170 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1171 		OSKext::jettisonFileSetLinkeditSegment(mh);
1172 	}
1173 #else // !VM_MAPPED_KEXTS
1174 	/*****
1175 	 * Dump the LINKEDIT segment, unless keepsyms is set.
1176 	 */
1177 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1178 		dt_segment_name = "Kernel-__LINKEDIT";
1179 		if (0 == IODTGetLoaderInfo(dt_segment_name,
1180 		    &segment_paddress, &segment_size)) {
1181 #ifdef SECURE_KERNEL
1182 			vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1183 			bzero((void*)vmaddr, segment_size);
1184 #endif
1185 			IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1186 			    (int)segment_size);
1187 		}
1188 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1189 		/* Remove the linkedit segment of the Boot KC */
1190 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1191 		OSKext::jettisonFileSetLinkeditSegment(mh);
1192 	} else {
1193 		OSKextLog(/* kext */ NULL,
1194 		    kOSKextLogBasicLevel |
1195 		    kOSKextLogGeneralFlag,
1196 		    "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1197 	}
1198 #endif // VM_MAPPED_KEXTS
1199 
1200 	result = kOSReturnSuccess;
1201 
1202 	return result;
1203 }
1204 
1205 #if CONFIG_KXLD
1206 /*********************************************************************
1207 *********************************************************************/
1208 void
1209 OSKext::flushNonloadedKexts(
1210 	Boolean flushPrelinkedKexts)
1211 {
1212 	OSSharedPtr<OSSet>                keepKexts;
1213 
1214 	/* TODO: make this more efficient with MH_FILESET kexts */
1215 
1216 	// Do not unload prelinked kexts on arm because the kernelcache is not
1217 	// structured in a way that allows them to be unmapped
1218 #if !defined(__x86_64__)
1219 	flushPrelinkedKexts = false;
1220 #endif /* defined(__x86_64__) */
1221 
1222 	IORecursiveLockLock(sKextLock);
1223 
1224 	OSKextLog(/* kext */ NULL,
1225 	    kOSKextLogProgressLevel |
1226 	    kOSKextLogKextBookkeepingFlag,
1227 	    "Flushing nonloaded kexts and other unused data.");
1228 
1229 	OSKext::considerDestroyingLinkContext();
1230 
1231 	/* If we aren't flushing unused prelinked kexts, we have to put them
1232 	 * aside while we flush everything else so make a container for them.
1233 	 */
1234 	keepKexts = OSSet::withCapacity(16);
1235 	if (!keepKexts) {
1236 		goto finish;
1237 	}
1238 
1239 	/* Set aside prelinked kexts (in-use or not) and break
1240 	 * any lingering inter-kext references for nonloaded kexts
1241 	 * so they have min. retain counts.
1242 	 */
1243 	{
1244 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1245 			OSKext * thisKext = OSDynamicCast(OSKext, obj);
1246 			if (!thisKext) {
1247 			        return false;
1248 			}
1249 			if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
1250 			        keepKexts->setObject(thisKext);
1251 			} else if (!thisKext->declaresExecutable()) {
1252 			        /*
1253 			         * Don't unload codeless kexts, because they never appear in the loadedKexts array.
1254 			         * Requesting one from the IOKit daemon will load it and then immediately remove it by calling
1255 			         * flushNonloadedKexts().
1256 			         * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
1257 			         */
1258 			        keepKexts->setObject(thisKext);
1259 			} else if (thisKext->isInFileset()) {
1260 			        /* keep all kexts in the new MH_FILESET KC */
1261 			        keepKexts->setObject(thisKext);
1262 			}
1263 
1264 			thisKext->flushDependencies(/* forceIfLoaded */ false);
1265 			return false;
1266 		});
1267 	}
1268 	/* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1269 	 */
1270 	sKextsByID->flushCollection();
1271 
1272 	/* Now put the loaded kexts back into the ID dictionary.
1273 	 */
1274 	sLoadedKexts->iterateObjects(^bool (OSObject * obj) {
1275 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1276 		if (!thisKext) {
1277 		        return false;
1278 		}
1279 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1280 		return false;
1281 	});
1282 
1283 	/* Finally, put back the kept kexts if we saved any.
1284 	 */
1285 	keepKexts->iterateObjects(^bool (OSObject * obj) {
1286 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1287 		if (!thisKext) {
1288 		        return false;
1289 		}
1290 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1291 		return false;
1292 	});
1293 
1294 finish:
1295 	IORecursiveLockUnlock(sKextLock);
1296 	return;
1297 }
1298 #else /* !CONFIG_KXLD */
1299 
1300 void
1301 OSKext::flushNonloadedKexts(
1302 	Boolean flushPrelinkedKexts __unused)
1303 {
1304 	IORecursiveLockLock(sKextLock);
1305 
1306 	OSKextLog(/* kext */ NULL,
1307 	    kOSKextLogProgressLevel |
1308 	    kOSKextLogKextBookkeepingFlag,
1309 	    "Flushing dependency info for non-loaded kexts.");
1310 
1311 	/*
1312 	 * In a world where we don't dynamically link kexts, they all come
1313 	 * from a kext collection that's either in wired memory, or
1314 	 * wire-on-demand. We don't need to mess around with moving kexts in
1315 	 * and out of the sKextsByID array - they can all just stay there.
1316 	 * Here we just flush the dependency list for kexts that are not
1317 	 * loaded.
1318 	 */
1319 	sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1320 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1321 		if (!thisKext) {
1322 		        return false;
1323 		}
1324 		thisKext->flushDependencies(/* forceIfLoaded */ false);
1325 		return false;
1326 	});
1327 
1328 	IORecursiveLockUnlock(sKextLock);
1329 	return;
1330 }
1331 
1332 #endif /* CONFIG_KXLD */
1333 
1334 /*********************************************************************
1335 *********************************************************************/
1336 /* static */
1337 void
1338 OSKext::setIOKitDaemonActive(bool active)
1339 {
1340 	IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
1341 	IORecursiveLockLock(sKextLock);
1342 	sIOKitDaemonActive = active;
1343 	if (sKernelRequests->getCount()) {
1344 		OSKext::pingIOKitDaemon();
1345 	}
1346 	IORecursiveLockUnlock(sKextLock);
1347 
1348 	return;
1349 }
1350 
1351 /*********************************************************************
1352 * OSKextLib.cpp might need access to this someday but for now it's
1353 * private.
1354 *********************************************************************/
1355 extern "C" {
1356 extern void ipc_port_release_send(ipc_port_t);
1357 };
1358 
1359 /* static */
1360 OSReturn
1361 OSKext::pingIOKitDaemon(void)
1362 {
1363 	OSReturn    result     = kOSReturnError;
1364 #if !NO_KEXTD
1365 	mach_port_t kextd_port = IPC_PORT_NULL;
1366 
1367 	if (!sIOKitDaemonActive) {
1368 		result = kOSKextReturnDisabled; // basically unavailable
1369 		goto finish;
1370 	}
1371 
1372 	result = host_get_kextd_port(host_priv_self(), &kextd_port);
1373 	if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1374 		OSKextLog(/* kext */ NULL,
1375 		    kOSKextLogErrorLevel |
1376 		    kOSKextLogIPCFlag,
1377 		    "Can't get " kIOKitDaemonName " port.");
1378 		goto finish;
1379 	}
1380 
1381 	result = kextd_ping(kextd_port);
1382 	if (result != KERN_SUCCESS) {
1383 		OSKextLog(/* kext */ NULL,
1384 		    kOSKextLogErrorLevel |
1385 		    kOSKextLogIPCFlag,
1386 		    kIOKitDaemonName " ping failed (0x%x).", (int)result);
1387 		goto finish;
1388 	}
1389 
1390 finish:
1391 	if (IPC_PORT_VALID(kextd_port)) {
1392 		ipc_port_release_send(kextd_port);
1393 	}
1394 #endif
1395 
1396 	return result;
1397 }
1398 
1399 /*********************************************************************
1400 *********************************************************************/
1401 /* static */
1402 void
1403 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1404 {
1405 	IORecursiveLockLock(sKextLock);
1406 	sDeferredLoadSucceeded = succeeded;
1407 	IORecursiveLockUnlock(sKextLock);
1408 
1409 	return;
1410 }
1411 
1412 /*********************************************************************
1413 * Called from IOSystemShutdownNotification.
1414 *********************************************************************/
1415 /* static */
1416 void
1417 OSKext::willShutdown(void)
1418 {
1419 #if !NO_KEXTD
1420 	OSReturn       checkResult = kOSReturnError;
1421 #endif
1422 	OSSharedPtr<OSDictionary> exitRequest;
1423 
1424 	IORecursiveLockLock(sKextLock);
1425 
1426 	OSKext::setLoadEnabled(false);
1427 	OSKext::setUnloadEnabled(false);
1428 	OSKext::setAutounloadsEnabled(false);
1429 	OSKext::setKernelRequestsEnabled(false);
1430 
1431 #if defined(__x86_64__) || defined(__i386__)
1432 	if (IOPMRootDomainGetWillShutdown()) {
1433 		OSKext::freeKCFileSetcontrol();
1434 	}
1435 #endif // (__x86_64__) || defined(__i386__)
1436 
1437 #if !NO_KEXTD
1438 	OSKextLog(/* kext */ NULL,
1439 	    kOSKextLogProgressLevel |
1440 	    kOSKextLogGeneralFlag,
1441 	    "System shutdown; requesting immediate " kIOKitDaemonName " exit.");
1442 
1443 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit,
1444 	    exitRequest);
1445 	if (checkResult != kOSReturnSuccess) {
1446 		goto finish;
1447 	}
1448 	if (!sKernelRequests->setObject(exitRequest.get())) {
1449 		goto finish;
1450 	}
1451 
1452 	OSKext::pingIOKitDaemon();
1453 
1454 finish:
1455 #endif
1456 
1457 	IORecursiveLockUnlock(sKextLock);
1458 	return;
1459 }
1460 
1461 void
1462 OSKext::willUserspaceReboot(void)
1463 {
1464 	OSKext::willShutdown();
1465 	IOService::userSpaceWillReboot();
1466 	gIOCatalogue->terminateDriversForUserspaceReboot();
1467 }
1468 
1469 void
1470 OSKext::resetAfterUserspaceReboot(void)
1471 {
1472 	OSSharedPtr<OSArray> arr = OSArray::withCapacity(1);
1473 	IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */);
1474 
1475 	IORecursiveLockLock(sKextLock);
1476 	gIOCatalogue->resetAfterUserspaceReboot();
1477 	IOService::userSpaceDidReboot();
1478 	OSKext::removeDaemonExitRequests();
1479 	OSKext::setLoadEnabled(true);
1480 	OSKext::setUnloadEnabled(true);
1481 	OSKext::setAutounloadsEnabled(true);
1482 	OSKext::setKernelRequestsEnabled(true);
1483 	sOSKextWasResetAfterUserspaceReboot = true;
1484 	IORecursiveLockUnlock(sKextLock);
1485 }
1486 
1487 extern "C" void
1488 OSKextResetAfterUserspaceReboot(void)
1489 {
1490 	OSKext::resetAfterUserspaceReboot();
1491 }
1492 
1493 /*
1494  * Remove daemon exit requests from sKernelRequests
1495  *
1496  * If we sent a daemon exit request during a userspace reboot and launchd
1497  * killed the IOKit daemon before it was able to dequeue the exit request, the
1498  * next time the daemon starts up it will immediately exit as it gets the old exit request.
1499  *
1500  * This removes exit requests so that this does not happen.
1501  */
1502 void
1503 OSKext::removeDaemonExitRequests(void)
1504 {
1505 	OSDictionary * current = NULL;
1506 	OSString     * predicate = NULL;
1507 	size_t         index     = 0;
1508 	OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey);
1509 
1510 	while (index < sKernelRequests->getCount()) {
1511 		current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index));
1512 		if (current) {
1513 			predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get()));
1514 			if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) {
1515 				sKernelRequests->removeObject(index);
1516 				continue;
1517 			}
1518 		}
1519 		index++;
1520 	}
1521 }
1522 
1523 /*********************************************************************
1524 *********************************************************************/
1525 /* static */
1526 bool
1527 OSKext::getLoadEnabled(void)
1528 {
1529 	bool result;
1530 
1531 	IORecursiveLockLock(sKextLock);
1532 	result = sLoadEnabled;
1533 	IORecursiveLockUnlock(sKextLock);
1534 	return result;
1535 }
1536 
1537 /*********************************************************************
1538 *********************************************************************/
1539 /* static */
1540 bool
1541 OSKext::setLoadEnabled(bool flag)
1542 {
1543 	bool result;
1544 
1545 	IORecursiveLockLock(sKextLock);
1546 	result = sLoadEnabled;
1547 	sLoadEnabled = (flag ? true : false);
1548 
1549 	if (sLoadEnabled != result) {
1550 		OSKextLog(/* kext */ NULL,
1551 		    kOSKextLogBasicLevel |
1552 		    kOSKextLogLoadFlag,
1553 		    "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1554 	}
1555 
1556 	IORecursiveLockUnlock(sKextLock);
1557 
1558 	return result;
1559 }
1560 
1561 /*********************************************************************
1562 *********************************************************************/
1563 /* static */
1564 bool
1565 OSKext::getUnloadEnabled(void)
1566 {
1567 	bool result;
1568 
1569 	IORecursiveLockLock(sKextLock);
1570 	result = sUnloadEnabled;
1571 	IORecursiveLockUnlock(sKextLock);
1572 	return result;
1573 }
1574 
1575 /*********************************************************************
1576 *********************************************************************/
1577 /* static */
1578 bool
1579 OSKext::setUnloadEnabled(bool flag)
1580 {
1581 	bool result;
1582 
1583 	IORecursiveLockLock(sKextLock);
1584 	result = sUnloadEnabled;
1585 	sUnloadEnabled = (flag ? true : false);
1586 	IORecursiveLockUnlock(sKextLock);
1587 
1588 	if (sUnloadEnabled != result) {
1589 		OSKextLog(/* kext */ NULL,
1590 		    kOSKextLogBasicLevel |
1591 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1592 		    "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1593 	}
1594 
1595 	return result;
1596 }
1597 
1598 /*********************************************************************
1599 * Do not call any function that takes sKextLock here!
1600 *********************************************************************/
1601 /* static */
1602 bool
1603 OSKext::getAutounloadEnabled(void)
1604 {
1605 #if XNU_TARGET_OS_OSX
1606 	bool result;
1607 
1608 	IORecursiveLockLock(sKextInnerLock);
1609 	result = sAutounloadEnabled ? true : false;
1610 	IORecursiveLockUnlock(sKextInnerLock);
1611 	return result;
1612 #else
1613 	return false;
1614 #endif /* XNU_TARGET_OS_OSX */
1615 }
1616 
1617 /*********************************************************************
1618 * Do not call any function that takes sKextLock here!
1619 *********************************************************************/
1620 /* static */
1621 bool
1622 OSKext::setAutounloadsEnabled(bool flag)
1623 {
1624 #if XNU_TARGET_OS_OSX
1625 	bool result;
1626 
1627 	IORecursiveLockLock(sKextInnerLock);
1628 
1629 	result = sAutounloadEnabled;
1630 	sAutounloadEnabled = (flag ? true : false);
1631 	if (!sAutounloadEnabled && sUnloadCallout) {
1632 		thread_call_cancel(sUnloadCallout);
1633 	}
1634 
1635 	if (sAutounloadEnabled != result) {
1636 		OSKextLog(/* kext */ NULL,
1637 		    kOSKextLogBasicLevel |
1638 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1639 		    "Kext autounloading now %sabled.",
1640 		    sAutounloadEnabled ? "en" : "dis");
1641 	}
1642 
1643 	IORecursiveLockUnlock(sKextInnerLock);
1644 
1645 	return result;
1646 #else
1647 	(void)flag;
1648 	return false;
1649 #endif /* XNU_TARGET_OS_OSX */
1650 }
1651 
1652 /*********************************************************************
1653 *********************************************************************/
1654 /* instance method operating on OSKext field */
1655 bool
1656 OSKext::setAutounloadEnabled(bool flag)
1657 {
1658 	bool result = flags.autounloadEnabled ? true : false;
1659 	flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0;
1660 
1661 	if (result != (flag ? true : false)) {
1662 		OSKextLog(this,
1663 		    kOSKextLogProgressLevel |
1664 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1665 		    "Autounloading for kext %s now %sabled.",
1666 		    getIdentifierCString(),
1667 		    flags.autounloadEnabled ? "en" : "dis");
1668 	}
1669 	return result;
1670 }
1671 
1672 /*********************************************************************
1673 *********************************************************************/
1674 /* static */
1675 bool
1676 OSKext::setKernelRequestsEnabled(bool flag)
1677 {
1678 	bool result;
1679 
1680 	IORecursiveLockLock(sKextLock);
1681 	result = sKernelRequestsEnabled;
1682 	sKernelRequestsEnabled = flag ? true : false;
1683 
1684 	if (sKernelRequestsEnabled != result) {
1685 		OSKextLog(/* kext */ NULL,
1686 		    kOSKextLogBasicLevel |
1687 		    kOSKextLogGeneralFlag,
1688 		    "Kernel requests now %sabled.",
1689 		    sKernelRequestsEnabled ? "en" : "dis");
1690 	}
1691 	IORecursiveLockUnlock(sKextLock);
1692 	return result;
1693 }
1694 
1695 /*********************************************************************
1696 *********************************************************************/
1697 /* static */
1698 bool
1699 OSKext::getKernelRequestsEnabled(void)
1700 {
1701 	bool result;
1702 
1703 	IORecursiveLockLock(sKextLock);
1704 	result = sKernelRequestsEnabled;
1705 	IORecursiveLockUnlock(sKextLock);
1706 	return result;
1707 }
1708 
1709 static bool
1710 segmentIsMutable(kernel_segment_command_t *seg)
1711 {
1712 	/* Mutable segments have to have VM_PROT_WRITE */
1713 	if ((seg->maxprot & VM_PROT_WRITE) == 0) {
1714 		return false;
1715 	}
1716 	/* Exclude the __DATA_CONST segment */
1717 	if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) {
1718 		return false;
1719 	}
1720 	/* Exclude __LINKEDIT */
1721 	if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) {
1722 		return false;
1723 	}
1724 	return true;
1725 }
1726 
1727 #if PRAGMA_MARK
1728 #pragma mark Kext Life Cycle
1729 #endif
1730 /*********************************************************************
1731 *********************************************************************/
1732 OSSharedPtr<OSKext>
1733 OSKext::withPrelinkedInfoDict(
1734 	OSDictionary * anInfoDict,
1735 	bool doCoalescedSlides,
1736 	kc_kind_t type)
1737 {
1738 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
1739 
1740 	if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) {
1741 		return NULL;
1742 	}
1743 
1744 	return newKext;
1745 }
1746 
1747 /*********************************************************************
1748 *********************************************************************/
1749 bool
1750 OSKext::initWithPrelinkedInfoDict(
1751 	OSDictionary * anInfoDict,
1752 	bool doCoalescedSlides,
1753 	kc_kind_t type)
1754 {
1755 	bool            result              = false;
1756 	OSString      * kextPath            = NULL;                // do not release
1757 	OSNumber      * addressNum          = NULL;                // reused; do not release
1758 	OSNumber      * lengthNum           = NULL;                // reused; do not release
1759 	OSBoolean     * scratchBool         = NULL;                // do not release
1760 	void          * data                = NULL;                // do not free
1761 	void          * srcData             = NULL;                // do not free
1762 	OSSharedPtr<OSData>        prelinkedExecutable;
1763 	uint32_t        length              = 0;                // reused
1764 	uintptr_t       kext_slide          = PE_get_kc_slide(type);
1765 	bool            shouldSaveSegments  = false;
1766 
1767 	if (!super::init()) {
1768 		goto finish;
1769 	}
1770 
1771 	/* Get the path. Don't look for an arch-specific path property.
1772 	 */
1773 	kextPath = OSDynamicCast(OSString,
1774 	    anInfoDict->getObject(kPrelinkBundlePathKey));
1775 
1776 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1777 		goto finish;
1778 	}
1779 
1780 #if KASLR_KEXT_DEBUG
1781 	IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString());
1782 #endif
1783 
1784 	/* Also get the executable's bundle-relative path if present.
1785 	 * Don't look for an arch-specific path property.
1786 	 */
1787 	executableRelPath.reset(OSDynamicCast(OSString,
1788 	    anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain);
1789 	userExecutableRelPath.reset(OSDynamicCast(OSString,
1790 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
1791 
1792 	/* Don't need the paths to be in the info dictionary any more.
1793 	 */
1794 	anInfoDict->removeObject(kPrelinkBundlePathKey);
1795 	anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1796 
1797 	scratchBool = OSDynamicCast(OSBoolean,
1798 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
1799 	if (scratchBool == kOSBooleanTrue) {
1800 		flags.requireExplicitLoad = 1;
1801 	}
1802 
1803 	/* Create an OSData wrapper around the linked executable.
1804 	 */
1805 	addressNum = OSDynamicCast(OSNumber,
1806 	    anInfoDict->getObject(kPrelinkExecutableLoadKey));
1807 	if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) {
1808 		lengthNum = OSDynamicCast(OSNumber,
1809 		    anInfoDict->getObject(kPrelinkExecutableSizeKey));
1810 		if (!lengthNum) {
1811 			OSKextLog(this,
1812 			    kOSKextLogErrorLevel |
1813 			    kOSKextLogArchiveFlag,
1814 			    "Kext %s can't find prelinked kext executable size.",
1815 			    getIdentifierCString());
1816 			return result;
1817 		}
1818 
1819 		data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1820 		length = (uint32_t) (lengthNum->unsigned32BitValue());
1821 
1822 #if KASLR_KEXT_DEBUG
1823 		IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1824 		    (unsigned long)ml_static_unslide((vm_offset_t)data),
1825 		    (unsigned long)data,
1826 		    length);
1827 #endif
1828 
1829 		anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1830 		anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1831 
1832 		/* If the kext's load address differs from its source address, allocate
1833 		 * space in the kext map at the load address and copy the kext over.
1834 		 */
1835 		addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1836 		if (addressNum) {
1837 			srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1838 
1839 #if KASLR_KEXT_DEBUG
1840 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1841 			    (unsigned long)ml_static_unslide((vm_offset_t)srcData),
1842 			    (unsigned long)srcData);
1843 #endif
1844 
1845 			if (data != srcData) {
1846 #if __LP64__
1847 				kern_return_t alloc_result;
1848 
1849 				alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
1850 				if (alloc_result != KERN_SUCCESS) {
1851 					OSKextLog(this,
1852 					    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1853 					    "Failed to allocate space for prelinked kext %s.",
1854 					    getIdentifierCString());
1855 					goto finish;
1856 				}
1857 				memcpy(data, srcData, length);
1858 #else
1859 				OSKextLog(this,
1860 				    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1861 				    "Error: prelinked kext %s - source and load addresses "
1862 				    "differ on ILP32 architecture.",
1863 				    getIdentifierCString());
1864 				goto finish;
1865 #endif /* __LP64__ */
1866 			}
1867 
1868 			anInfoDict->removeObject(kPrelinkExecutableSourceKey);
1869 		}
1870 
1871 		prelinkedExecutable = OSData::withBytesNoCopy(data, length);
1872 		if (!prelinkedExecutable) {
1873 			OSKextLog(this,
1874 			    kOSKextLogErrorLevel |
1875 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1876 			    "Kext %s failed to create executable wrapper.",
1877 			    getIdentifierCString());
1878 			goto finish;
1879 		}
1880 
1881 #if VM_MAPPED_KEXTS
1882 		prelinkedExecutable->setDeallocFunction(osdata_kext_free);
1883 #else
1884 		prelinkedExecutable->setDeallocFunction(osdata_phys_free);
1885 #endif
1886 		setLinkedExecutable(prelinkedExecutable.get());
1887 		addressNum = OSDynamicCast(OSNumber,
1888 		    anInfoDict->getObject(kPrelinkKmodInfoKey));
1889 		if (!addressNum) {
1890 			OSKextLog(this,
1891 			    kOSKextLogErrorLevel |
1892 			    kOSKextLogArchiveFlag,
1893 			    "Kext %s can't find prelinked kext kmod_info address.",
1894 			    getIdentifierCString());
1895 			goto finish;
1896 		}
1897 
1898 		if (addressNum->unsigned64BitValue() != 0) {
1899 			kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1900 			if (kmod_info->address) {
1901 				kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide);
1902 			} else {
1903 				kmod_info->address = (uintptr_t)data;
1904 				kmod_info->size = length;
1905 			}
1906 #if KASLR_KEXT_DEBUG
1907 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1908 			    (unsigned long)((vm_offset_t)kmod_info) - kext_slide,
1909 			    (unsigned long)kmod_info);
1910 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1911 			    (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide,
1912 			    (unsigned long)kmod_info->address);
1913  #endif
1914 		}
1915 
1916 		anInfoDict->removeObject(kPrelinkKmodInfoKey);
1917 	}
1918 
1919 	if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
1920 		uintptr_t builtinTextStart;
1921 		uintptr_t builtinTextEnd;
1922 
1923 		flags.builtin = true;
1924 		builtinKmodIdx = addressNum->unsigned32BitValue();
1925 		assert(builtinKmodIdx < gBuiltinKmodsCount);
1926 
1927 		builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
1928 		builtinTextEnd   = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
1929 
1930 		kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
1931 		kmod_info->address = builtinTextStart;
1932 		kmod_info->size    = builtinTextEnd - builtinTextStart;
1933 	}
1934 
1935 	/* If the plist has a UUID for an interface, save that off.
1936 	 */
1937 	if (isInterface()) {
1938 		interfaceUUID.reset(OSDynamicCast(OSData,
1939 		    anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain);
1940 		if (interfaceUUID) {
1941 			anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
1942 		}
1943 	}
1944 
1945 	result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides));
1946 	if (!result) {
1947 		goto finish;
1948 	}
1949 
1950 	kc_type = type;
1951 	/* Exclude builtin and codeless kexts */
1952 	if (prelinkedExecutable && kmod_info) {
1953 		switch (kc_type) {
1954 		case KCKindPrimary:
1955 			shouldSaveSegments = (
1956 				getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue ||
1957 				getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue);
1958 			if (shouldSaveSegments) {
1959 				flags.resetSegmentsFromImmutableCopy = 1;
1960 			} else {
1961 				flags.unloadUnsupported = 1;
1962 			}
1963 			break;
1964 		case KCKindPageable:
1965 			flags.resetSegmentsFromVnode = 1;
1966 			break;
1967 		case KCKindAuxiliary:
1968 			if (!pageableKCloaded) {
1969 				flags.resetSegmentsFromImmutableCopy = 1;
1970 			} else if (resetAuxKCSegmentOnUnload) {
1971 				flags.resetSegmentsFromVnode = 1;
1972 			} else {
1973 				flags.unloadUnsupported = 1;
1974 			}
1975 			break;
1976 		default:
1977 			break;
1978 		}
1979 	}
1980 
1981 	if (flags.resetSegmentsFromImmutableCopy) {
1982 		/* Save a pristine copy of the mutable segments */
1983 		kernel_segment_command_t *seg = NULL;
1984 		kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
1985 
1986 		savedMutableSegments = OSArray::withCapacity(0);
1987 
1988 		for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) {
1989 			if (!segmentIsMutable(seg)) {
1990 				continue;
1991 			}
1992 			uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
1993 			uint64_t vmsize = seg->vmsize;
1994 			OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
1995 			    "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
1996 			OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg);
1997 			if (!savedSegment) {
1998 				OSKextLog(this,
1999 				    kOSKextLogErrorLevel |
2000 				    kOSKextLogGeneralFlag,
2001 				    "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2002 				result = kOSKextReturnInternalError;
2003 				goto finish;
2004 			}
2005 			savedMutableSegments->setObject(savedSegment);
2006 		}
2007 	}
2008 
2009 	if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) {
2010 		/*
2011 		 * set VM protections now, wire pages for the old style Aux KC now,
2012 		 * wire pages for the rest of the KC types at load time.
2013 		 */
2014 		result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false));
2015 		if (!result) {
2016 			goto finish;
2017 		}
2018 	}
2019 
2020 	flags.prelinked = true;
2021 
2022 	/* If we created a kext from prelink info,
2023 	 * we must be booting from a prelinked kernel.
2024 	 */
2025 	sPrelinkBoot = true;
2026 
2027 	result = registerIdentifier();
2028 
2029 finish:
2030 	return result;
2031 }
2032 
2033 /*********************************************************************
2034 *********************************************************************/
2035 /* static */
2036 OSSharedPtr<OSKext>
2037 OSKext::withCodelessInfo(OSDictionary * anInfoDict)
2038 {
2039 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
2040 
2041 	if (newKext && !newKext->initWithCodelessInfo(anInfoDict)) {
2042 		return NULL;
2043 	}
2044 
2045 	return newKext;
2046 }
2047 
2048 /*********************************************************************
2049 *********************************************************************/
2050 bool
2051 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict)
2052 {
2053 	bool        result      = false;
2054 	OSString  * kextPath    = NULL;        // do not release
2055 	OSBoolean * scratchBool = NULL;        // do not release
2056 
2057 	if (anInfoDict == NULL || !super::init()) {
2058 		goto finish;
2059 	}
2060 
2061 	/*
2062 	 * Get the path. Don't look for an arch-specific path property.
2063 	 */
2064 	kextPath = OSDynamicCast(OSString,
2065 	    anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey));
2066 	if (!kextPath) {
2067 		OSKextLog(NULL,
2068 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2069 		    "Requested codeless kext dictionary does not contain the '%s' key",
2070 		    kKextRequestArgumentCodelessInfoBundlePathKey);
2071 		goto finish;
2072 	}
2073 
2074 	uniquePersonalityProperties(anInfoDict);
2075 
2076 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2077 		goto finish;
2078 	}
2079 
2080 	/*
2081 	 * This path is meant to initialize codeless kexts only. Refuse
2082 	 * anything that looks like it has an executable and/or declares
2083 	 * itself as a kernel component.
2084 	 */
2085 	if (declaresExecutable() || isKernelComponent()) {
2086 		OSKextLog(NULL,
2087 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2088 		    "Refusing to register codeless kext that declares an executable/kernel component: %s",
2089 		    getIdentifierCString());
2090 		goto finish;
2091 	}
2092 
2093 	if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
2094 		boolean_t updated = updateExcludeList(infoDict.get());
2095 		if (updated) {
2096 			OSKextLog(this,
2097 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2098 			    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
2099 		}
2100 	}
2101 
2102 	kc_type = KCKindNone;
2103 
2104 	scratchBool = OSDynamicCast(OSBoolean,
2105 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
2106 	if (scratchBool == kOSBooleanTrue) {
2107 		flags.requireExplicitLoad = 1;
2108 	}
2109 
2110 	/* Also get the executable's bundle-relative path if present.
2111 	 * Don't look for an arch-specific path property.
2112 	 */
2113 	userExecutableRelPath.reset(OSDynamicCast(OSString,
2114 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
2115 
2116 	/* remove unnecessary paths from the info dict */
2117 	anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey);
2118 
2119 	result = registerIdentifier();
2120 
2121 finish:
2122 	return result;
2123 }
2124 
2125 /*********************************************************************
2126 *********************************************************************/
2127 /* static */
2128 void
2129 OSKext::setAllVMAttributes(void)
2130 {
2131 	OSSharedPtr<OSCollectionIterator> kextIterator;
2132 	const OSSymbol * thisID                 = NULL;        // do not release
2133 
2134 	IORecursiveLockLock(sKextLock);
2135 
2136 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
2137 	if (!kextIterator) {
2138 		goto finish;
2139 	}
2140 
2141 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
2142 		OSKext *    thisKext;        // do not release
2143 
2144 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
2145 		if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
2146 			continue;
2147 		}
2148 
2149 		if (!thisKext->flags.resetSegmentsFromVnode) {
2150 			/*
2151 			 * set VM protections now, wire pages for the old style Aux KC now,
2152 			 * wire pages for the rest of the KC types at load time.
2153 			 */
2154 			thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false);
2155 		}
2156 	}
2157 
2158 finish:
2159 	IORecursiveLockUnlock(sKextLock);
2160 
2161 	return;
2162 }
2163 
2164 /*********************************************************************
2165 *********************************************************************/
2166 OSSharedPtr<OSKext>
2167 OSKext::withBooterData(
2168 	OSString * deviceTreeName,
2169 	OSData   * booterData)
2170 {
2171 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
2172 
2173 	if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
2174 		return NULL;
2175 	}
2176 
2177 	return newKext;
2178 }
2179 
2180 /*********************************************************************
2181 *********************************************************************/
2182 typedef struct _BooterKextFileInfo {
2183 	uint32_t  infoDictPhysAddr;
2184 	uint32_t  infoDictLength;
2185 	uint32_t  executablePhysAddr;
2186 	uint32_t  executableLength;
2187 	uint32_t  bundlePathPhysAddr;
2188 	uint32_t  bundlePathLength;
2189 } _BooterKextFileInfo;
2190 
2191 bool
2192 OSKext::initWithBooterData(
2193 	OSString * deviceTreeName,
2194 	OSData   * booterData)
2195 {
2196 	bool                  result         = false;
2197 	_BooterKextFileInfo * kextFileInfo   = NULL;        // do not free
2198 	char                * infoDictAddr   = NULL;        // do not free
2199 	void                * executableAddr = NULL;        // do not free
2200 	char                * bundlePathAddr = NULL;        // do not free
2201 
2202 	OSDictionary        * theInfoDict    = NULL;        // do not release
2203 	OSSharedPtr<OSObject> parsedXML;
2204 	OSSharedPtr<OSString> kextPath;
2205 
2206 	OSSharedPtr<OSString> errorString;
2207 	OSSharedPtr<OSData>   executable;
2208 
2209 	if (!super::init()) {
2210 		goto finish;
2211 	}
2212 
2213 	kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
2214 	if (!kextFileInfo) {
2215 		OSKextLog(this,
2216 		    kOSKextLogErrorLevel |
2217 		    kOSKextLogGeneralFlag,
2218 		    "No booter-provided data for kext device tree entry %s.",
2219 		    deviceTreeName->getCStringNoCopy());
2220 		goto finish;
2221 	}
2222 
2223 	/* The info plist must exist or we can't read the kext.
2224 	 */
2225 	if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
2226 		OSKextLog(this,
2227 		    kOSKextLogErrorLevel |
2228 		    kOSKextLogGeneralFlag,
2229 		    "No kext info dictionary for booter device tree entry %s.",
2230 		    deviceTreeName->getCStringNoCopy());
2231 		goto finish;
2232 	}
2233 
2234 	infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
2235 	if (!infoDictAddr) {
2236 		OSKextLog(this,
2237 		    kOSKextLogErrorLevel |
2238 		    kOSKextLogGeneralFlag,
2239 		    "Can't translate physical address 0x%x of kext info dictionary "
2240 		    "for device tree entry %s.",
2241 		    (int)kextFileInfo->infoDictPhysAddr,
2242 		    deviceTreeName->getCStringNoCopy());
2243 		goto finish;
2244 	}
2245 
2246 	parsedXML = OSUnserializeXML(infoDictAddr, errorString);
2247 	if (parsedXML) {
2248 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
2249 	}
2250 	if (!theInfoDict) {
2251 		const char * errorCString = "(unknown error)";
2252 
2253 		if (errorString && errorString->getCStringNoCopy()) {
2254 			errorCString = errorString->getCStringNoCopy();
2255 		} else if (parsedXML) {
2256 			errorCString = "not a dictionary";
2257 		}
2258 		OSKextLog(this,
2259 		    kOSKextLogErrorLevel |
2260 		    kOSKextLogGeneralFlag,
2261 		    "Error unserializing info dictionary for device tree entry %s: %s.",
2262 		    deviceTreeName->getCStringNoCopy(), errorCString);
2263 		goto finish;
2264 	}
2265 
2266 	/* A bundle path is not mandatory.
2267 	 */
2268 	if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
2269 		bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
2270 		if (!bundlePathAddr) {
2271 			OSKextLog(this,
2272 			    kOSKextLogErrorLevel |
2273 			    kOSKextLogGeneralFlag,
2274 			    "Can't translate physical address 0x%x of kext bundle path "
2275 			    "for device tree entry %s.",
2276 			    (int)kextFileInfo->bundlePathPhysAddr,
2277 			    deviceTreeName->getCStringNoCopy());
2278 			goto finish;
2279 		}
2280 		bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0';         // just in case!
2281 
2282 		kextPath = OSString::withCString(bundlePathAddr);
2283 		if (!kextPath) {
2284 			OSKextLog(this,
2285 			    kOSKextLogErrorLevel |
2286 			    kOSKextLogGeneralFlag,
2287 			    "Failed to create wrapper for device tree entry %s kext path %s.",
2288 			    deviceTreeName->getCStringNoCopy(), bundlePathAddr);
2289 			goto finish;
2290 		}
2291 	}
2292 
2293 	if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) {
2294 		goto finish;
2295 	}
2296 
2297 	/* An executable is not mandatory.
2298 	 */
2299 	if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
2300 		executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
2301 		if (!executableAddr) {
2302 			OSKextLog(this,
2303 			    kOSKextLogErrorLevel |
2304 			    kOSKextLogGeneralFlag,
2305 			    "Can't translate physical address 0x%x of kext executable "
2306 			    "for device tree entry %s.",
2307 			    (int)kextFileInfo->executablePhysAddr,
2308 			    deviceTreeName->getCStringNoCopy());
2309 			goto finish;
2310 		}
2311 
2312 		executable = OSData::withBytesNoCopy(executableAddr,
2313 		    kextFileInfo->executableLength);
2314 		if (!executable) {
2315 			OSKextLog(this,
2316 			    kOSKextLogErrorLevel |
2317 			    kOSKextLogGeneralFlag,
2318 			    "Failed to create executable wrapper for device tree entry %s.",
2319 			    deviceTreeName->getCStringNoCopy());
2320 			goto finish;
2321 		}
2322 
2323 		/* A kext with an executable needs to retain the whole booterData
2324 		 * object to keep the executable in memory.
2325 		 */
2326 		if (!setExecutable(executable.get(), booterData)) {
2327 			OSKextLog(this,
2328 			    kOSKextLogErrorLevel |
2329 			    kOSKextLogGeneralFlag,
2330 			    "Failed to set kext executable for device tree entry %s.",
2331 			    deviceTreeName->getCStringNoCopy());
2332 			goto finish;
2333 		}
2334 	}
2335 
2336 	result = registerIdentifier();
2337 
2338 finish:
2339 	return result;
2340 }
2341 
2342 /*********************************************************************
2343 *********************************************************************/
2344 bool
2345 OSKext::registerIdentifier(void)
2346 {
2347 	bool            result              = false;
2348 	OSKext        * existingKext        = NULL;        // do not release
2349 	bool            existingIsLoaded    = false;
2350 	bool            existingIsPrelinked = false;
2351 	bool            existingIsCodeless  = false;
2352 	bool            existingIsDext      = false;
2353 	OSKextVersion   newVersion          = -1;
2354 	OSKextVersion   existingVersion     = -1;
2355 	char            newVersionCString[kOSKextVersionMaxLength];
2356 	char            existingVersionCString[kOSKextVersionMaxLength];
2357 	OSSharedPtr<OSData> newUUID;
2358 	OSSharedPtr<OSData> existingUUID;
2359 
2360 	IORecursiveLockLock(sKextLock);
2361 
2362 	/* Get the new kext's version for checks & log messages.
2363 	 */
2364 	newVersion = getVersion();
2365 	OSKextVersionGetString(newVersion, newVersionCString,
2366 	    kOSKextVersionMaxLength);
2367 
2368 	/* If we don't have an existing kext with this identifier,
2369 	 * just record the new kext and we're done!
2370 	 */
2371 	existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get()));
2372 	if (!existingKext) {
2373 		sKextsByID->setObject(bundleID.get(), this);
2374 		result = true;
2375 		goto finish;
2376 	}
2377 
2378 	/* Get the existing kext's version for checks & log messages.
2379 	 */
2380 	existingVersion = existingKext->getVersion();
2381 	OSKextVersionGetString(existingVersion,
2382 	    existingVersionCString, kOSKextVersionMaxLength);
2383 
2384 	existingIsLoaded = existingKext->isLoaded();
2385 	existingIsPrelinked = existingKext->isPrelinked();
2386 	existingIsDext = existingKext->isDriverKit();
2387 	existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext;
2388 
2389 	/* If we have a non-codeless kext with this identifier that's already
2390 	 * loaded/prelinked, we can't use the new one, but let's be really
2391 	 * thorough and check how the two are related for a precise diagnostic
2392 	 * log message.
2393 	 *
2394 	 * This check is valid for kexts that declare an executable and for
2395 	 * dexts, but not for codeless kexts - we can just replace those.
2396 	 */
2397 	if ((!existingIsCodeless || existingIsDext) &&
2398 	    (existingIsLoaded || existingIsPrelinked)) {
2399 		bool sameVersion = (newVersion == existingVersion);
2400 		bool sameExecutable = true;         // assume true unless we have UUIDs
2401 
2402 		/* Only get the UUID if the existing kext is loaded. Doing so
2403 		 * might have to uncompress an mkext executable and we shouldn't
2404 		 * take that hit when neither kext is loaded.
2405 		 *
2406 		 * Note: there is no decompression that happens when all kexts
2407 		 * are loaded from kext collecitons.
2408 		 */
2409 		newUUID = copyUUID();
2410 		existingUUID = existingKext->copyUUID();
2411 
2412 		if (existingIsDext && !isDriverKit()) {
2413 			OSKextLog(this,
2414 			    kOSKextLogWarningLevel |
2415 			    kOSKextLogKextBookkeepingFlag,
2416 			    "Notice - new kext %s, v%s matches a %s dext"
2417 			    "with the same bundle ID, v%s.",
2418 			    getIdentifierCString(), newVersionCString,
2419 			    (existingIsLoaded ? "loaded" : "prelinked"),
2420 			    existingVersionCString);
2421 			goto finish;
2422 		}
2423 
2424 		/* I'm entirely too paranoid about checking equivalence of executables,
2425 		 * but I remember nasty problems with it in the past.
2426 		 *
2427 		 * - If we have UUIDs for both kexts, compare them.
2428 		 * - If only one kext has a UUID, they're definitely different.
2429 		 */
2430 		if (newUUID && existingUUID) {
2431 			sameExecutable = newUUID->isEqualTo(existingUUID.get());
2432 		} else if (newUUID || existingUUID) {
2433 			sameExecutable = false;
2434 		}
2435 
2436 		if (!newUUID && !existingUUID) {
2437 			/* If there are no UUIDs, we can't really tell that the executables
2438 			 * are *different* without a lot of work; the loaded kext's
2439 			 * unrelocated executable is no longer around (and we never had it
2440 			 * in-kernel for a prelinked kext). We certainly don't want to do
2441 			 * a whole fake link for the new kext just to compare, either.
2442 			 */
2443 			OSKextLog(this,
2444 			    kOSKextLogWarningLevel |
2445 			    kOSKextLogKextBookkeepingFlag,
2446 			    "Notice - new kext %s, v%s matches %s kext "
2447 			    "but can't determine if executables are the same (no UUIDs).",
2448 			    getIdentifierCString(),
2449 			    newVersionCString,
2450 			    (existingIsLoaded ? "loaded" : "prelinked"));
2451 		}
2452 
2453 		if (sameVersion && sameExecutable) {
2454 			OSKextLog(this,
2455 			    (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2456 			    kOSKextLogKextBookkeepingFlag,
2457 			    "Refusing new kext %s, v%s: a %s copy is already present "
2458 			    "(same version and executable).",
2459 			    getIdentifierCString(), newVersionCString,
2460 			    (existingIsLoaded ? "loaded" : "prelinked"));
2461 		} else {
2462 			if (!sameVersion) {
2463 				/* This condition is significant so log it under warnings.
2464 				 */
2465 				OSKextLog(this,
2466 				    kOSKextLogWarningLevel |
2467 				    kOSKextLogKextBookkeepingFlag,
2468 				    "Refusing new kext %s, v%s: already have %s v%s.",
2469 				    getIdentifierCString(),
2470 				    newVersionCString,
2471 				    (existingIsLoaded ? "loaded" : "prelinked"),
2472 				    existingVersionCString);
2473 			} else {
2474 				/* This condition is significant so log it under warnings.
2475 				 */
2476 				OSKextLog(this,
2477 				    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2478 				    "Refusing new kext %s, v%s: a %s copy with a different "
2479 				    "executable UUID is already present.",
2480 				    getIdentifierCString(), newVersionCString,
2481 				    (existingIsLoaded ? "loaded" : "prelinked"));
2482 			}
2483 		}
2484 		goto finish;
2485 	} /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */
2486 
2487 	/* Refuse to allow an existing loaded codeless kext be replaced by a
2488 	 * normal kext with the same bundle ID.
2489 	 */
2490 	if (existingIsCodeless && declaresExecutable()) {
2491 		OSKextLog(this,
2492 		    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2493 		    "Refusing new kext %s, v%s: a codeless copy is already %s",
2494 		    getIdentifierCString(), newVersionCString,
2495 		    (existingIsLoaded ? "loaded" : "prelinked"));
2496 		goto finish;
2497 	}
2498 
2499 	/* Dexts packaged in the BootKC will be protected against replacement
2500 	 * by non-dexts by the logic above which checks if they are prelinked.
2501 	 * Dexts which are prelinked into the System KC will be registered
2502 	 * before any other kexts in the AuxKC are registered, and we never
2503 	 * put dexts in the AuxKC. Therefore, there is no need to check if an
2504 	 * existing object is a dext and is being replaced by a non-dext.
2505 	 * The scenario cannot happen by construction.
2506 	 *
2507 	 * See: OSKext::loadFileSetKexts()
2508 	 */
2509 
2510 	/* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2511 	 * user loads are happening or if we're still in early boot. User agents are
2512 	 * supposed to resolve dependencies topside and include only the exact
2513 	 * kexts needed; so we always accept the new kext (in fact we should never
2514 	 * see an older unloaded copy hanging around).
2515 	 */
2516 	if (sUserLoadsActive) {
2517 		sKextsByID->setObject(bundleID.get(), this);
2518 		result = true;
2519 
2520 		OSKextLog(this,
2521 		    kOSKextLogStepLevel |
2522 		    kOSKextLogKextBookkeepingFlag,
2523 		    "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2524 		    getIdentifierCString(),
2525 		    existingVersionCString,
2526 		    newVersionCString);
2527 
2528 		goto finish;
2529 	}
2530 
2531 	/* During early boot, the kext with the highest version always wins out.
2532 	 * Prelinked kernels will never hit this, but mkexts and booter-read
2533 	 * kexts might have duplicates.
2534 	 */
2535 	if (newVersion > existingVersion) {
2536 		sKextsByID->setObject(bundleID.get(), this);
2537 		result = true;
2538 
2539 		OSKextLog(this,
2540 		    kOSKextLogStepLevel |
2541 		    kOSKextLogKextBookkeepingFlag,
2542 		    "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2543 		    existingVersionCString,
2544 		    getIdentifierCString(),
2545 		    newVersionCString);
2546 	} else {
2547 		OSKextLog(this,
2548 		    kOSKextLogStepLevel |
2549 		    kOSKextLogKextBookkeepingFlag,
2550 		    "Kext %s is already registered with a higher/same version (v%s); "
2551 		    "dropping newly-added (v%s).",
2552 		    getIdentifierCString(),
2553 		    existingVersionCString,
2554 		    newVersionCString);
2555 	}
2556 
2557 	/* result has been set appropriately by now. */
2558 
2559 finish:
2560 
2561 	IORecursiveLockUnlock(sKextLock);
2562 
2563 	if (result) {
2564 		OSKextLog(this,
2565 		    kOSKextLogStepLevel |
2566 		    kOSKextLogKextBookkeepingFlag,
2567 		    "Kext %s, v%s registered and available for loading.",
2568 		    getIdentifierCString(), newVersionCString);
2569 	}
2570 
2571 	return result;
2572 }
2573 
2574 /*********************************************************************
2575  * Does the bare minimum validation to look up a kext.
2576  * All other validation is done on the spot as needed.
2577  **********************************************************************/
2578 bool
2579 OSKext::setInfoDictionaryAndPath(
2580 	OSDictionary * aDictionary,
2581 	OSString     * aPath)
2582 {
2583 	bool           result                   = false;
2584 	OSString     * bundleIDString           = NULL;        // do not release
2585 	OSString     * versionString            = NULL;        // do not release
2586 	OSString     * compatibleVersionString  = NULL;        // do not release
2587 	const char   * versionCString           = NULL;        // do not free
2588 	const char   * compatibleVersionCString = NULL;        // do not free
2589 	OSBoolean    * scratchBool              = NULL;        // do not release
2590 	OSDictionary * scratchDict              = NULL;        // do not release
2591 
2592 	if (infoDict) {
2593 		panic("Attempt to set info dictionary on a kext "
2594 		    "that already has one (%s).",
2595 		    getIdentifierCString());
2596 	}
2597 
2598 	if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
2599 		goto finish;
2600 	}
2601 
2602 	infoDict.reset(aDictionary, OSRetain);
2603 
2604 	/* Check right away if the info dictionary has any log flags.
2605 	 */
2606 	scratchBool = OSDynamicCast(OSBoolean,
2607 	    getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
2608 	if (scratchBool == kOSBooleanTrue) {
2609 		flags.loggingEnabled = 1;
2610 	}
2611 
2612 	/* The very next thing to get is the bundle identifier. Unlike
2613 	 * in user space, a kext with no bundle identifier gets axed
2614 	 * immediately.
2615 	 */
2616 	bundleIDString = OSDynamicCast(OSString,
2617 	    getPropertyForHostArch(kCFBundleIdentifierKey));
2618 	if (!bundleIDString) {
2619 		OSKextLog(this,
2620 		    kOSKextLogErrorLevel |
2621 		    kOSKextLogValidationFlag,
2622 		    "CFBundleIdentifier missing/invalid type in kext %s.",
2623 		    aPath ? aPath->getCStringNoCopy() : "(unknown)");
2624 		goto finish;
2625 	}
2626 	bundleID = OSSymbol::withString(bundleIDString);
2627 	if (!bundleID) {
2628 		OSKextLog(this,
2629 		    kOSKextLogErrorLevel |
2630 		    kOSKextLogValidationFlag,
2631 		    "Can't copy bundle identifier as symbol for kext %s.",
2632 		    bundleIDString->getCStringNoCopy());
2633 		goto finish;
2634 	}
2635 
2636 	/* Save the path if we got one (it should always be available but it's
2637 	 * just something nice to have for bookkeeping).
2638 	 */
2639 	if (aPath) {
2640 		path.reset(aPath, OSRetain);
2641 	}
2642 
2643 	/*****
2644 	 * Minimal validation to initialize. We'll do other validation on the spot.
2645 	 */
2646 	if (bundleID->getLength() >= KMOD_MAX_NAME) {
2647 		OSKextLog(this,
2648 		    kOSKextLogErrorLevel |
2649 		    kOSKextLogValidationFlag,
2650 		    "Kext %s error - CFBundleIdentifier over max length %d.",
2651 		    getIdentifierCString(), KMOD_MAX_NAME - 1);
2652 		goto finish;
2653 	}
2654 
2655 	version = compatibleVersion = -1;
2656 
2657 	versionString = OSDynamicCast(OSString,
2658 	    getPropertyForHostArch(kCFBundleVersionKey));
2659 	if (!versionString) {
2660 		OSKextLog(this,
2661 		    kOSKextLogErrorLevel |
2662 		    kOSKextLogValidationFlag,
2663 		    "Kext %s error - CFBundleVersion missing/invalid type.",
2664 		    getIdentifierCString());
2665 		goto finish;
2666 	}
2667 	versionCString = versionString->getCStringNoCopy();
2668 	version = OSKextParseVersionString(versionCString);
2669 	if (version < 0) {
2670 		OSKextLog(this,
2671 		    kOSKextLogErrorLevel |
2672 		    kOSKextLogValidationFlag,
2673 		    "Kext %s error - CFBundleVersion bad value '%s'.",
2674 		    getIdentifierCString(), versionCString);
2675 		goto finish;
2676 	}
2677 
2678 	compatibleVersion = -1;         // set to illegal value for kexts that don't have
2679 
2680 	compatibleVersionString = OSDynamicCast(OSString,
2681 	    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2682 	if (compatibleVersionString) {
2683 		compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2684 		compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2685 		if (compatibleVersion < 0) {
2686 			OSKextLog(this,
2687 			    kOSKextLogErrorLevel |
2688 			    kOSKextLogValidationFlag,
2689 			    "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2690 			    getIdentifierCString(), compatibleVersionCString);
2691 			goto finish;
2692 		}
2693 
2694 		if (compatibleVersion > version) {
2695 			OSKextLog(this,
2696 			    kOSKextLogErrorLevel |
2697 			    kOSKextLogValidationFlag,
2698 			    "Kext %s error - %s %s > %s %s (must be <=).",
2699 			    getIdentifierCString(),
2700 			    kOSBundleCompatibleVersionKey, compatibleVersionCString,
2701 			    kCFBundleVersionKey, versionCString);
2702 			goto finish;
2703 		}
2704 	}
2705 
2706 	/* Check to see if this kext is in exclude list */
2707 	if (isInExcludeList()) {
2708 		OSKextLog(this,
2709 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2710 		    "Kext %s is in exclude list, not loadable",
2711 		    getIdentifierCString());
2712 		goto finish;
2713 	}
2714 
2715 	/* Set flags for later use if the infoDict gets flushed. We only
2716 	 * check for true values, not false ones(!)
2717 	 */
2718 	scratchBool = OSDynamicCast(OSBoolean,
2719 	    getPropertyForHostArch(kOSBundleIsInterfaceKey));
2720 	if (scratchBool == kOSBooleanTrue) {
2721 		flags.interface = 1;
2722 	}
2723 
2724 	scratchBool = OSDynamicCast(OSBoolean,
2725 	    getPropertyForHostArch(kOSKernelResourceKey));
2726 	if (scratchBool == kOSBooleanTrue) {
2727 		flags.kernelComponent = 1;
2728 		flags.interface = 1;         // xxx - hm. the kernel itself isn't an interface...
2729 		flags.started = 1;
2730 
2731 		/* A kernel component has one implicit dependency on the kernel.
2732 		 */
2733 		flags.hasAllDependencies = 1;
2734 	}
2735 
2736 	/* Make sure common string values in personalities are uniqued to OSSymbols.
2737 	 */
2738 	scratchDict = OSDynamicCast(OSDictionary,
2739 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
2740 	if (scratchDict) {
2741 		uniquePersonalityProperties(scratchDict);
2742 	}
2743 
2744 	result = true;
2745 
2746 finish:
2747 
2748 	return result;
2749 }
2750 
2751 /*********************************************************************
2752 * Not used for prelinked kernel boot as there is no unrelocated
2753 * executable.
2754 *********************************************************************/
2755 bool
2756 OSKext::setExecutable(
2757 	OSData * anExecutable,
2758 	OSData * externalData,
2759 	bool     externalDataIsMkext)
2760 {
2761 	bool         result        = false;
2762 	const char * executableKey = NULL;         // do not free
2763 
2764 	if (!anExecutable) {
2765 		infoDict->removeObject(_kOSKextExecutableKey);
2766 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
2767 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
2768 		result = true;
2769 		goto finish;
2770 	}
2771 
2772 	if (infoDict->getObject(_kOSKextExecutableKey) ||
2773 	    infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
2774 		panic("Attempt to set an executable on a kext "
2775 		    "that already has one (%s).",
2776 		    getIdentifierCString());
2777 		goto finish;
2778 	}
2779 
2780 	if (externalDataIsMkext) {
2781 		executableKey = _kOSKextMkextExecutableReferenceKey;
2782 	} else {
2783 		executableKey = _kOSKextExecutableKey;
2784 	}
2785 
2786 	if (anExecutable) {
2787 		infoDict->setObject(executableKey, anExecutable);
2788 		if (externalData) {
2789 			infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
2790 		}
2791 	}
2792 
2793 	result = true;
2794 
2795 finish:
2796 	return result;
2797 }
2798 
2799 /*********************************************************************
2800 *********************************************************************/
2801 static void
2802 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
2803 {
2804 	OSObject       * value       = NULL;        // do not release
2805 	OSString       * stringValue = NULL;        // do not release
2806 	OSSharedPtr<const OSSymbol> symbolValue;
2807 
2808 	value = dict->getObject(key);
2809 	if (!value) {
2810 		goto finish;
2811 	}
2812 	if (OSDynamicCast(OSSymbol, value)) {
2813 		/* this is already an OSSymbol: we're good */
2814 		goto finish;
2815 	}
2816 
2817 	stringValue = OSDynamicCast(OSString, value);
2818 	if (!stringValue) {
2819 		goto finish;
2820 	}
2821 
2822 	symbolValue = OSSymbol::withString(stringValue);
2823 	if (!symbolValue) {
2824 		goto finish;
2825 	}
2826 
2827 	dict->setObject(key, symbolValue.get());
2828 
2829 finish:
2830 	return;
2831 }
2832 
2833 /*********************************************************************
2834 *********************************************************************/
2835 static void
2836 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
2837 {
2838 	OSObject       * value       = NULL;        // do not release
2839 	OSString       * stringValue = NULL;        // do not release
2840 	OSSharedPtr<const OSSymbol> symbolValue;
2841 
2842 	value = dict->getObject(key);
2843 	if (!value) {
2844 		goto finish;
2845 	}
2846 	if (OSDynamicCast(OSSymbol, value)) {
2847 		/* this is already an OSSymbol: we're good */
2848 		goto finish;
2849 	}
2850 
2851 	stringValue = OSDynamicCast(OSString, value);
2852 	if (!stringValue) {
2853 		goto finish;
2854 	}
2855 
2856 	symbolValue = OSSymbol::withString(stringValue);
2857 	if (!symbolValue) {
2858 		goto finish;
2859 	}
2860 
2861 	dict->setObject(key, symbolValue.get());
2862 
2863 finish:
2864 	return;
2865 }
2866 
2867 void
2868 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
2869 {
2870 	OSKext::uniquePersonalityProperties(personalityDict, true);
2871 }
2872 
2873 /*********************************************************************
2874 * Replace common personality property values with uniqued instances
2875 * to save on wired memory.
2876 *********************************************************************/
2877 /* static */
2878 void
2879 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier)
2880 {
2881 	/* Properties every personality has.
2882 	 */
2883 	uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
2884 	uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
2885 	uniqueStringPlistProperty(personalityDict, gIOClassKey.get());
2886 	if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
2887 		uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
2888 	} else if (defaultAddKernelBundleIdentifier) {
2889 		personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
2890 	}
2891 
2892 	/* Other commonly used properties.
2893 	 */
2894 	uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
2895 	uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
2896 	uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
2897 
2898 	uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
2899 	uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
2900 	uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
2901 	uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
2902 	uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
2903 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
2904 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
2905 	uniqueStringPlistProperty(personalityDict, "Vendor");
2906 	uniqueStringPlistProperty(personalityDict, "Vendor Identification");
2907 	uniqueStringPlistProperty(personalityDict, "Vendor Name");
2908 	uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
2909 	uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
2910 	uniqueStringPlistProperty(personalityDict, "idProduct");
2911 
2912 	return;
2913 }
2914 
2915 /*********************************************************************
2916 *********************************************************************/
2917 void
2918 OSKext::free(void)
2919 {
2920 	if (isLoaded()) {
2921 		panic("Attempt to free loaded kext %s.", getIdentifierCString());
2922 	}
2923 
2924 	infoDict.reset();
2925 	bundleID.reset();
2926 	path.reset();
2927 	executableRelPath.reset();
2928 	userExecutableRelPath.reset();
2929 	dependencies.reset();
2930 	linkedExecutable.reset();
2931 	metaClasses.reset();
2932 	interfaceUUID.reset();
2933 	driverKitUUID.reset();
2934 
2935 	if (isInterface() && kmod_info) {
2936 		kfree_type(kmod_info_t, kmod_info);
2937 	}
2938 
2939 	super::free();
2940 	return;
2941 }
2942 
2943 #if PRAGMA_MARK
2944 #pragma mark Mkext files
2945 #endif
2946 
2947 #if CONFIG_KXLD
2948 /*
2949  * mkext archives are really only relevant on kxld-enabled kernels.
2950  * Without a dynamic kernel linker, we don't need to support any mkexts.
2951  */
2952 
2953 /*********************************************************************
2954 *********************************************************************/
2955 OSReturn
2956 OSKext::readMkextArchive(OSData * mkextData,
2957     uint32_t * checksumPtr)
2958 {
2959 	OSReturn       result       = kOSKextReturnBadData;
2960 	uint32_t       mkextLength  = 0;
2961 	mkext_header * mkextHeader  = NULL;        // do not free
2962 	uint32_t       mkextVersion = 0;
2963 
2964 	/* Note default return of kOSKextReturnBadData above.
2965 	 */
2966 	mkextLength = mkextData->getLength();
2967 	if (mkextLength < sizeof(mkext_basic_header)) {
2968 		OSKextLog(/* kext */ NULL,
2969 		    kOSKextLogErrorLevel |
2970 		    kOSKextLogArchiveFlag,
2971 		    "Mkext archive too small to be valid.");
2972 		goto finish;
2973 	}
2974 
2975 	mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
2976 
2977 	if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
2978 	    MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
2979 		OSKextLog(/* kext */ NULL,
2980 		    kOSKextLogErrorLevel |
2981 		    kOSKextLogArchiveFlag,
2982 		    "Mkext archive has invalid magic or signature.");
2983 		goto finish;
2984 	}
2985 
2986 	if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
2987 		OSKextLog(/* kext */ NULL,
2988 		    kOSKextLogErrorLevel |
2989 		    kOSKextLogArchiveFlag,
2990 		    "Mkext archive recorded length doesn't match actual file length.");
2991 		goto finish;
2992 	}
2993 
2994 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2995 
2996 	if (mkextVersion == MKEXT_VERS_2) {
2997 		result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
2998 	} else {
2999 		OSKextLog(/* kext */ NULL,
3000 		    kOSKextLogErrorLevel |
3001 		    kOSKextLogArchiveFlag,
3002 		    "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
3003 		result = kOSKextReturnUnsupported;
3004 	}
3005 
3006 finish:
3007 	return result;
3008 }
3009 
3010 /*********************************************************************
3011 * Assumes magic, signature, version, length have been checked.
3012 * xxx - need to add further bounds checking for each file entry
3013 *
3014 * Should keep track of all kexts created so far, and if we hit a
3015 * fatal error halfway through, remove those kexts. If we've dropped
3016 * an older version that had already been read, whoops! Might want to
3017 * add a level of buffering?
3018 *********************************************************************/
3019 /* static */
3020 OSReturn
3021 OSKext::readMkext2Archive(
3022 	OSData        * mkextData,
3023 	OSDictionary ** mkextPlistOut,
3024 	uint32_t      * checksumPtr)
3025 {
3026 	OSReturn        result                     = kOSReturnError;
3027 	uint32_t        mkextLength;
3028 	mkext2_header * mkextHeader                = NULL;        // do not free
3029 	void          * mkextEnd                   = NULL;        // do not free
3030 	uint32_t        mkextVersion;
3031 	uint8_t       * crc_address                = NULL;
3032 	size_t          crc_buffer_size            = 0;
3033 	uint32_t        checksum;
3034 	uint32_t        mkextPlistOffset;
3035 	uint32_t        mkextPlistCompressedSize;
3036 	char          * mkextPlistEnd              = NULL;        // do not free
3037 	uint32_t        mkextPlistFullSize;
3038 	OSSharedPtr<OSString>     errorString;
3039 	OSSharedPtr<OSData>       mkextPlistUncompressedData;
3040 	const char    * mkextPlistDataBuffer       = NULL;        // do not free
3041 	OSSharedPtr<OSObject>      parsedXML;
3042 	OSDictionary  * mkextPlist                 = NULL;        // do not release
3043 	OSArray       * mkextInfoDictArray         = NULL;        // do not release
3044 	uint32_t        count, i;
3045 	kc_format_t kc_format;
3046 
3047 	if (!PE_get_primary_kc_format(&kc_format)) {
3048 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3049 		    "Unable to determine primary KC format");
3050 		goto finish;
3051 	}
3052 
3053 	mkextLength = mkextData->getLength();
3054 	mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
3055 	mkextEnd = (char *)mkextHeader + mkextLength;
3056 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3057 
3058 	crc_address = (u_int8_t *)&mkextHeader->version;
3059 	crc_buffer_size = (uintptr_t)mkextHeader +
3060 	    MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address;
3061 	if (crc_buffer_size > INT32_MAX) {
3062 		OSKextLog(/* kext */ NULL,
3063 		    kOSKextLogErrorLevel |
3064 		    kOSKextLogArchiveFlag,
3065 		    "Mkext archive size is too large (%lu > INT32_MAX).",
3066 		    crc_buffer_size);
3067 		result = kOSKextReturnBadData;
3068 		goto finish;
3069 	}
3070 	checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size);
3071 
3072 	if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
3073 		OSKextLog(/* kext */ NULL,
3074 		    kOSKextLogErrorLevel |
3075 		    kOSKextLogArchiveFlag,
3076 		    "Mkext archive has bad checksum.");
3077 		result = kOSKextReturnBadData;
3078 		goto finish;
3079 	}
3080 
3081 	if (checksumPtr) {
3082 		*checksumPtr = checksum;
3083 	}
3084 
3085 	/* Check that the CPU type & subtype match that of the running kernel. */
3086 	if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
3087 		OSKextLog(/* kext */ NULL,
3088 		    kOSKextLogErrorLevel |
3089 		    kOSKextLogArchiveFlag,
3090 		    "Mkext archive must have a specific CPU type.");
3091 		result = kOSKextReturnBadData;
3092 		goto finish;
3093 	} else {
3094 		if ((UInt32)_mh_execute_header.cputype !=
3095 		    MKEXT_GET_CPUTYPE(mkextHeader)) {
3096 			OSKextLog(/* kext */ NULL,
3097 			    kOSKextLogErrorLevel |
3098 			    kOSKextLogArchiveFlag,
3099 			    "Mkext archive does not match the running kernel's CPU type.");
3100 			result = kOSKextReturnArchNotFound;
3101 			goto finish;
3102 		}
3103 	}
3104 
3105 	mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
3106 	mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
3107 	mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
3108 	    mkextPlistCompressedSize;
3109 	if (mkextPlistEnd > mkextEnd) {
3110 		OSKextLog(/* kext */ NULL,
3111 		    kOSKextLogErrorLevel |
3112 		    kOSKextLogArchiveFlag,
3113 		    "Mkext archive file overrun.");
3114 		result = kOSKextReturnBadData;
3115 	}
3116 
3117 	mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
3118 	if (mkextPlistCompressedSize) {
3119 		mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
3120 			(UInt8 *)mkextHeader + mkextPlistOffset,
3121 			"plist",
3122 			mkextPlistCompressedSize, mkextPlistFullSize);
3123 		if (!mkextPlistUncompressedData) {
3124 			goto finish;
3125 		}
3126 		mkextPlistDataBuffer = (const char *)
3127 		    mkextPlistUncompressedData->getBytesNoCopy();
3128 	} else {
3129 		mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
3130 	}
3131 
3132 	/* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
3133 	 */
3134 	parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString);
3135 	if (parsedXML) {
3136 		mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get());
3137 	}
3138 	if (!mkextPlist) {
3139 		const char * errorCString = "(unknown error)";
3140 
3141 		if (errorString && errorString->getCStringNoCopy()) {
3142 			errorCString = errorString->getCStringNoCopy();
3143 		} else if (parsedXML) {
3144 			errorCString = "not a dictionary";
3145 		}
3146 		OSKextLog(/* kext */ NULL,
3147 		    kOSKextLogErrorLevel |
3148 		    kOSKextLogArchiveFlag,
3149 		    "Error unserializing mkext plist: %s.", errorCString);
3150 		goto finish;
3151 	}
3152 
3153 	mkextInfoDictArray = OSDynamicCast(OSArray,
3154 	    mkextPlist->getObject(kMKEXTInfoDictionariesKey));
3155 	if (!mkextInfoDictArray) {
3156 		OSKextLog(/* kext */ NULL,
3157 		    kOSKextLogErrorLevel |
3158 		    kOSKextLogArchiveFlag,
3159 		    "Mkext archive contains no kext info dictionaries.");
3160 		goto finish;
3161 	}
3162 
3163 	count = mkextInfoDictArray->getCount();
3164 	for (i = 0; i < count; i++) {
3165 		OSDictionary * infoDict;
3166 
3167 
3168 		infoDict = OSDynamicCast(OSDictionary,
3169 		    mkextInfoDictArray->getObject(i));
3170 
3171 		/* Create the kext for the entry, then release it, because the
3172 		 * kext system keeps them around until explicitly removed.
3173 		 * Any creation/registration failures are already logged for us.
3174 		 */
3175 		if (infoDict) {
3176 			OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData);
3177 
3178 			/* Fail dynamic loading of a kext when booted from MH_FILESET */
3179 			if (kc_format == KCFormatFileset &&
3180 			    newKext &&
3181 			    !(newKext->isPrelinked()) &&
3182 			    newKext->declaresExecutable()) {
3183 				result = kOSReturnError;
3184 				printf("Kext LOG: Dynamic loading of kext denied for kext %s\n",
3185 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3186 
3187 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
3188 				    "Dynamic loading of kext denied for kext %s\n",
3189 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3190 				goto finish;
3191 			}
3192 		}
3193 	}
3194 
3195 	/* If the caller needs the plist, hand them back our copy
3196 	 */
3197 	if (mkextPlistOut) {
3198 		*mkextPlistOut = mkextPlist;
3199 		parsedXML.detach();
3200 	}
3201 
3202 	/* Even if we didn't keep any kexts from the mkext, we may have a load
3203 	 * request to process, so we are successful (no errors occurred).
3204 	 */
3205 	result = kOSReturnSuccess;
3206 
3207 finish:
3208 	return result;
3209 }
3210 
3211 /* static */
3212 OSReturn
3213 OSKext::readMkext2Archive(
3214 	OSData        * mkextData,
3215 	OSSharedPtr<OSDictionary> &mkextPlistOut,
3216 	uint32_t      * checksumPtr)
3217 {
3218 	OSDictionary * mkextPlist = NULL;
3219 	OSReturn ret;
3220 
3221 	if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData,
3222 	    &mkextPlist,
3223 	    checksumPtr))) {
3224 		mkextPlistOut.reset(mkextPlist, OSNoRetain);
3225 	}
3226 	return ret;
3227 }
3228 
3229 /*********************************************************************
3230 *********************************************************************/
3231 /* static */
3232 OSSharedPtr<OSKext>
3233 OSKext::withMkext2Info(
3234 	OSDictionary * anInfoDict,
3235 	OSData       * mkextData)
3236 {
3237 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
3238 
3239 	if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
3240 		return NULL;
3241 	}
3242 
3243 	return newKext;
3244 }
3245 
3246 /*********************************************************************
3247 *********************************************************************/
3248 bool
3249 OSKext::initWithMkext2Info(
3250 	OSDictionary * anInfoDict,
3251 	OSData       * mkextData)
3252 {
3253 	bool                   result              = false;
3254 	OSString             * kextPath            = NULL;        // do not release
3255 	OSNumber             * executableOffsetNum = NULL;        // do not release
3256 	OSSharedPtr<OSData>               executable;
3257 
3258 	if (anInfoDict == NULL || !super::init()) {
3259 		goto finish;
3260 	}
3261 
3262 	/* Get the path. Don't look for an arch-specific path property.
3263 	 */
3264 	kextPath = OSDynamicCast(OSString,
3265 	    anInfoDict->getObject(kMKEXTBundlePathKey));
3266 
3267 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
3268 		goto finish;
3269 	}
3270 
3271 	/* If we have a path to the executable, save it.
3272 	 */
3273 	executableRelPath.reset(OSDynamicCast(OSString,
3274 	    anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain);
3275 
3276 	/* Don't need the paths to be in the info dictionary any more.
3277 	 */
3278 	anInfoDict->removeObject(kMKEXTBundlePathKey);
3279 	anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
3280 
3281 	executableOffsetNum = OSDynamicCast(OSNumber,
3282 	    infoDict->getObject(kMKEXTExecutableKey));
3283 	if (executableOffsetNum) {
3284 		executable = createMkext2FileEntry(mkextData,
3285 		    executableOffsetNum, "executable");
3286 		infoDict->removeObject(kMKEXTExecutableKey);
3287 		if (!executable) {
3288 			goto finish;
3289 		}
3290 		if (!setExecutable(executable.get(), mkextData, true)) {
3291 			goto finish;
3292 		}
3293 	}
3294 
3295 	result = registerIdentifier();
3296 
3297 finish:
3298 	return result;
3299 }
3300 
3301 /*********************************************************************
3302 *********************************************************************/
3303 OSSharedPtr<OSData>
3304 OSKext::createMkext2FileEntry(
3305 	OSData     * mkextData,
3306 	OSNumber   * offsetNum,
3307 	const char * name)
3308 {
3309 	OSSharedPtr<OSData> result;
3310 	MkextEntryRef   entryRef;
3311 	uint8_t       * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
3312 	uint32_t        entryOffset = offsetNum->unsigned32BitValue();
3313 
3314 	result = OSData::withCapacity(sizeof(entryRef));
3315 	if (!result) {
3316 		goto finish;
3317 	}
3318 
3319 	entryRef.mkext = (mkext_basic_header *)mkextBuffer;
3320 	entryRef.fileinfo = mkextBuffer + entryOffset;
3321 	if (!result->appendBytes(&entryRef, sizeof(entryRef))) {
3322 		result.reset();
3323 		goto finish;
3324 	}
3325 
3326 finish:
3327 	if (!result) {
3328 		OSKextLog(this,
3329 		    kOSKextLogErrorLevel |
3330 		    kOSKextLogArchiveFlag,
3331 		    "Can't create wrapper for mkext file entry '%s' of kext %s.",
3332 		    name, getIdentifierCString());
3333 	}
3334 	return result;
3335 }
3336 
3337 /*********************************************************************
3338 *********************************************************************/
3339 extern "C" {
3340 static void * z_alloc(void *, u_int items, u_int size);
3341 static void   z_free(void *, void *ptr);
3342 
3343 typedef struct z_mem {
3344 	uint32_t alloc_size;
3345 	uint8_t  data[0];
3346 } z_mem;
3347 
3348 /*
3349  * Space allocation and freeing routines for use by zlib routines.
3350  */
3351 void *
3352 z_alloc(void * notused __unused, u_int num_items, u_int size)
3353 {
3354 	void     * result = NULL;
3355 	z_mem    * zmem = NULL;
3356 
3357 	uint64_t   total = ((uint64_t)num_items) * ((uint64_t)size);
3358 	//Check for overflow due to multiplication
3359 	if (total > UINT32_MAX) {
3360 		panic("z_alloc(%p, %x, %x): overflow caused by %x * %x",
3361 		    notused, num_items, size, num_items, size);
3362 	}
3363 
3364 	uint64_t   allocSize64 =  total + ((uint64_t)sizeof(zmem));
3365 	//Check for overflow due to addition
3366 	if (allocSize64 > UINT32_MAX) {
3367 		panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx",
3368 		    notused, num_items, size, (uint32_t)total, sizeof(zmem));
3369 	}
3370 	uint32_t allocSize = (uint32_t)allocSize64;
3371 
3372 	zmem = (z_mem *)kheap_alloc_tag(KHEAP_DATA_BUFFERS, allocSize,
3373 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
3374 	if (!zmem) {
3375 		goto finish;
3376 	}
3377 	zmem->alloc_size = allocSize;
3378 	result = (void *)&(zmem->data);
3379 finish:
3380 	return result;
3381 }
3382 
3383 void
3384 z_free(void * notused __unused, void * ptr)
3385 {
3386 	uint32_t * skipper = (uint32_t *)ptr - 1;
3387 	z_mem    * zmem = (z_mem *)skipper;
3388 	kheap_free(KHEAP_DATA_BUFFERS, zmem, zmem->alloc_size);
3389 	return;
3390 }
3391 };
3392 
3393 OSSharedPtr<OSData>
3394 OSKext::extractMkext2FileData(
3395 	UInt8      * data,
3396 	const char * name,
3397 	uint32_t     compressedSize,
3398 	uint32_t     fullSize)
3399 {
3400 	OSSharedPtr<OSData>      result;
3401 	OSSharedPtr<OSData>      uncompressedData;        // release on error
3402 
3403 	uint8_t     * uncompressedDataBuffer = NULL;        // do not free
3404 	unsigned long uncompressedSize;
3405 	z_stream      zstream;
3406 	bool          zstream_inited = false;
3407 	int           zlib_result;
3408 
3409 	/* If the file isn't compressed, we want to make a copy
3410 	 * so that we don't have the tie to the larger mkext file buffer any more.
3411 	 */
3412 	if (!compressedSize) {
3413 		uncompressedData = OSData::withBytes(data, fullSize);
3414 		// xxx - no check for failure?
3415 		result = uncompressedData;
3416 		goto finish;
3417 	}
3418 
3419 	if (KERN_SUCCESS != kmem_alloc(kernel_map,
3420 	    (vm_offset_t*)&uncompressedDataBuffer, fullSize, VM_KERN_MEMORY_OSKEXT)) {
3421 		/* How's this for cheesy? The kernel is only asked to extract
3422 		 * kext plists so we tailor the log messages.
3423 		 */
3424 		if (isKernel()) {
3425 			OSKextLog(this,
3426 			    kOSKextLogErrorLevel |
3427 			    kOSKextLogArchiveFlag,
3428 			    "Allocation failure extracting %s from mkext.", name);
3429 		} else {
3430 			OSKextLog(this,
3431 			    kOSKextLogErrorLevel |
3432 			    kOSKextLogArchiveFlag,
3433 			    "Allocation failure extracting %s from mkext for kext %s.",
3434 			    name, getIdentifierCString());
3435 		}
3436 
3437 		goto finish;
3438 	}
3439 	uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3440 	if (!uncompressedData) {
3441 		if (isKernel()) {
3442 			OSKextLog(this,
3443 			    kOSKextLogErrorLevel |
3444 			    kOSKextLogArchiveFlag,
3445 			    "Allocation failure extracting %s from mkext.", name);
3446 		} else {
3447 			OSKextLog(this,
3448 			    kOSKextLogErrorLevel |
3449 			    kOSKextLogArchiveFlag,
3450 			    "Allocation failure extracting %s from mkext for kext %s.",
3451 			    name, getIdentifierCString());
3452 		}
3453 		goto finish;
3454 	}
3455 	uncompressedData->setDeallocFunction(&osdata_kmem_free);
3456 
3457 	if (isKernel()) {
3458 		OSKextLog(this,
3459 		    kOSKextLogDetailLevel |
3460 		    kOSKextLogArchiveFlag,
3461 		    "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3462 		    name, compressedSize, fullSize);
3463 	} else {
3464 		OSKextLog(this,
3465 		    kOSKextLogDetailLevel |
3466 		    kOSKextLogArchiveFlag,
3467 		    "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3468 		    getIdentifierCString(), name, compressedSize, fullSize);
3469 	}
3470 
3471 	bzero(&zstream, sizeof(zstream));
3472 	zstream.next_in   = (UInt8 *)data;
3473 	zstream.avail_in  = compressedSize;
3474 
3475 	zstream.next_out  = uncompressedDataBuffer;
3476 	zstream.avail_out = fullSize;
3477 
3478 	zstream.zalloc    = z_alloc;
3479 	zstream.zfree     = z_free;
3480 
3481 	zlib_result = inflateInit(&zstream);
3482 	if (Z_OK != zlib_result) {
3483 		if (isKernel()) {
3484 			OSKextLog(this,
3485 			    kOSKextLogErrorLevel |
3486 			    kOSKextLogArchiveFlag,
3487 			    "Mkext error; zlib inflateInit failed (%d) for %s.",
3488 			    zlib_result, name);
3489 		} else {
3490 			OSKextLog(this,
3491 			    kOSKextLogErrorLevel |
3492 			    kOSKextLogArchiveFlag,
3493 			    "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3494 			    getIdentifierCString(), zlib_result, name);
3495 		}
3496 		goto finish;
3497 	} else {
3498 		zstream_inited = true;
3499 	}
3500 
3501 	zlib_result = inflate(&zstream, Z_FINISH);
3502 
3503 	if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3504 		uncompressedSize = zstream.total_out;
3505 	} else {
3506 		if (isKernel()) {
3507 			OSKextLog(this,
3508 			    kOSKextLogErrorLevel |
3509 			    kOSKextLogArchiveFlag,
3510 			    "Mkext error; zlib inflate failed (%d) for %s.",
3511 			    zlib_result, name);
3512 		} else {
3513 			OSKextLog(this,
3514 			    kOSKextLogErrorLevel |
3515 			    kOSKextLogArchiveFlag,
3516 			    "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3517 			    getIdentifierCString(), zlib_result, name);
3518 		}
3519 		if (zstream.msg) {
3520 			OSKextLog(this,
3521 			    kOSKextLogErrorLevel |
3522 			    kOSKextLogArchiveFlag,
3523 			    "zlib error: %s.", zstream.msg);
3524 		}
3525 		goto finish;
3526 	}
3527 
3528 	if (uncompressedSize != fullSize) {
3529 		if (isKernel()) {
3530 			OSKextLog(this,
3531 			    kOSKextLogErrorLevel |
3532 			    kOSKextLogArchiveFlag,
3533 			    "Mkext error; zlib inflate discrepancy for %s, "
3534 			    "uncompressed size != original size.", name);
3535 		} else {
3536 			OSKextLog(this,
3537 			    kOSKextLogErrorLevel |
3538 			    kOSKextLogArchiveFlag,
3539 			    "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3540 			    "uncompressed size != original size.",
3541 			    getIdentifierCString(), name);
3542 		}
3543 		goto finish;
3544 	}
3545 
3546 	result = os::move(uncompressedData);
3547 
3548 finish:
3549 	/* Don't bother checking return, nothing we can do on fail.
3550 	 */
3551 	if (zstream_inited) {
3552 		inflateEnd(&zstream);
3553 	}
3554 
3555 	return result;
3556 }
3557 
3558 /*********************************************************************
3559 *********************************************************************/
3560 /* static */
3561 OSReturn
3562 OSKext::loadFromMkext(
3563 	OSKextLogSpec   clientLogFilter,
3564 	char          * mkextBuffer,
3565 	uint32_t        mkextBufferLength,
3566 	char         ** logInfoOut,
3567 	uint32_t      * logInfoLengthOut)
3568 {
3569 	OSReturn         result                      = kOSReturnError;
3570 	OSReturn         tempResult                  = kOSReturnError;
3571 
3572 	OSSharedPtr<OSData>        mkextData;
3573 	OSSharedPtr<OSDictionary>  mkextPlist;
3574 
3575 	OSSharedPtr<OSArray>       logInfoArray;
3576 	OSSharedPtr<OSSerialize>   serializer;
3577 
3578 	OSString       * predicate                   = NULL;        // do not release
3579 	OSDictionary   * requestArgs                 = NULL;        // do not release
3580 
3581 	OSString       * kextIdentifier              = NULL;        // do not release
3582 	OSNumber       * startKextExcludeNum         = NULL;        // do not release
3583 	OSNumber       * startMatchingExcludeNum     = NULL;        // do not release
3584 	OSBoolean      * delayAutounloadBool         = NULL;        // do not release
3585 	OSArray        * personalityNames            = NULL;        // do not release
3586 
3587 	/* Default values for these two options: regular autounload behavior,
3588 	 * load all kexts, send no personalities.
3589 	 */
3590 	Boolean            delayAutounload           = false;
3591 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
3592 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3593 
3594 	IORecursiveLockLock(sKextLock);
3595 
3596 	if (logInfoOut) {
3597 		*logInfoOut = NULL;
3598 		*logInfoLengthOut = 0;
3599 	}
3600 
3601 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3602 
3603 	OSKextLog(/* kext */ NULL,
3604 	    kOSKextLogDebugLevel |
3605 	    kOSKextLogIPCFlag,
3606 	    "Received kext load request from user space.");
3607 
3608 	/* Regardless of processing, the fact that we have gotten here means some
3609 	 * user-space program is up and talking to us, so we'll switch our kext
3610 	 * registration to reflect that.
3611 	 */
3612 	if (!sUserLoadsActive) {
3613 		OSKextLog(/* kext */ NULL,
3614 		    kOSKextLogProgressLevel |
3615 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3616 		    "Switching to late startup (user-space) kext loading policy.");
3617 
3618 		sUserLoadsActive = true;
3619 	}
3620 
3621 	if (!sLoadEnabled) {
3622 		OSKextLog(/* kext */ NULL,
3623 		    kOSKextLogErrorLevel |
3624 		    kOSKextLogLoadFlag,
3625 		    "Kext loading is disabled.");
3626 		result = kOSKextReturnDisabled;
3627 		goto finish;
3628 	}
3629 
3630 	/* Note that we do not set a dealloc function on this OSData
3631 	 * object! No references to it can remain after the loadFromMkext()
3632 	 * call since we are in a MIG function, and will vm_deallocate()
3633 	 * the buffer.
3634 	 */
3635 	mkextData = OSData::withBytesNoCopy(mkextBuffer,
3636 	    mkextBufferLength);
3637 	if (!mkextData) {
3638 		OSKextLog(/* kext */ NULL,
3639 		    kOSKextLogErrorLevel |
3640 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3641 		    "Failed to create wrapper for kext load request.");
3642 		result = kOSKextReturnNoMemory;
3643 		goto finish;
3644 	}
3645 
3646 	result = readMkext2Archive(mkextData.get(), mkextPlist, NULL);
3647 	if (result != kOSReturnSuccess) {
3648 		OSKextLog(/* kext */ NULL,
3649 		    kOSKextLogErrorLevel |
3650 		    kOSKextLogLoadFlag,
3651 		    "Failed to read kext load request.");
3652 		goto finish;
3653 	}
3654 
3655 	predicate = _OSKextGetRequestPredicate(mkextPlist.get());
3656 	if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3657 		OSKextLog(/* kext */ NULL,
3658 		    kOSKextLogErrorLevel |
3659 		    kOSKextLogLoadFlag,
3660 		    "Received kext load request with no predicate; skipping.");
3661 		result = kOSKextReturnInvalidArgument;
3662 		goto finish;
3663 	}
3664 
3665 	requestArgs = OSDynamicCast(OSDictionary,
3666 	    mkextPlist->getObject(kKextRequestArgumentsKey));
3667 	if (!requestArgs || !requestArgs->getCount()) {
3668 		OSKextLog(/* kext */ NULL,
3669 		    kOSKextLogErrorLevel |
3670 		    kOSKextLogLoadFlag,
3671 		    "Received kext load request with no arguments.");
3672 		result = kOSKextReturnInvalidArgument;
3673 		goto finish;
3674 	}
3675 
3676 	kextIdentifier = OSDynamicCast(OSString,
3677 	    requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3678 
3679 	if (!kextIdentifier) {
3680 		OSKextLog(/* kext */ NULL,
3681 		    kOSKextLogErrorLevel |
3682 		    kOSKextLogLoadFlag,
3683 		    "Received kext load request with no kext identifier.");
3684 		result = kOSKextReturnInvalidArgument;
3685 		goto finish;
3686 	}
3687 
3688 	startKextExcludeNum = OSDynamicCast(OSNumber,
3689 	    requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3690 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
3691 	    requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3692 	delayAutounloadBool = OSDynamicCast(OSBoolean,
3693 	    requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3694 	personalityNames = OSDynamicCast(OSArray,
3695 	    requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3696 
3697 	if (delayAutounloadBool) {
3698 		delayAutounload = delayAutounloadBool->getValue();
3699 	}
3700 	if (startKextExcludeNum) {
3701 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3702 	}
3703 	if (startMatchingExcludeNum) {
3704 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3705 	}
3706 
3707 	OSKextLog(/* kext */ NULL,
3708 	    kOSKextLogProgressLevel |
3709 	    kOSKextLogIPCFlag,
3710 	    "Received request from user space to load kext %s.",
3711 	    kextIdentifier->getCStringNoCopy());
3712 
3713 	/* Load the kext, with no deferral, since this is a load from outside
3714 	 * the kernel.
3715 	 * xxx - Would like a better way to handle the default values for the
3716 	 * xxx - start/match opt args.
3717 	 */
3718 	result = OSKext::loadKextWithIdentifier(
3719 		kextIdentifier,
3720 		/* kextRef */ NULL,
3721 		/* allowDefer */ false,
3722 		delayAutounload,
3723 		startKextExcludeLevel,
3724 		startMatchingExcludeLevel,
3725 		personalityNames);
3726 	if (result != kOSReturnSuccess) {
3727 		goto finish;
3728 	}
3729 	/* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue
3730 	 * for matching via a separate IOKit calldown.
3731 	 */
3732 
3733 finish:
3734 
3735 	/* Gather up the collected log messages for user space. Any
3736 	 * error messages past this call will not make it up as log messages
3737 	 * but will be in the system log.
3738 	 */
3739 	logInfoArray = OSKext::clearUserSpaceLogFilter();
3740 
3741 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
3742 		tempResult = OSKext::serializeLogInfo(logInfoArray.get(),
3743 		    logInfoOut, logInfoLengthOut);
3744 		if (tempResult != kOSReturnSuccess) {
3745 			result = tempResult;
3746 		}
3747 	}
3748 
3749 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3750 
3751 	IORecursiveLockUnlock(sKextLock);
3752 
3753 	/* Note: mkextDataObject will have been retained by every kext w/an
3754 	 * executable in it. That should all have been flushed out at the
3755 	 * and of the load operation, but you never know....
3756 	 */
3757 	if (mkextData && mkextData->getRetainCount() > 1) {
3758 		OSKextLog(/* kext */ NULL,
3759 		    kOSKextLogErrorLevel |
3760 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3761 		    "Kext load request buffer from user space still retained by a kext; "
3762 		    "probable memory leak.");
3763 	}
3764 
3765 	return result;
3766 }
3767 
3768 #endif // CONFIG_KXLD
3769 
3770 /*********************************************************************
3771 *********************************************************************/
3772 /* static */
3773 OSReturn
3774 OSKext::serializeLogInfo(
3775 	OSArray   * logInfoArray,
3776 	char     ** logInfoOut,
3777 	uint32_t  * logInfoLengthOut)
3778 {
3779 	OSReturn        result      = kOSReturnError;
3780 	char          * buffer      = NULL;
3781 	kern_return_t   kmem_result = KERN_FAILURE;
3782 	OSSharedPtr<OSSerialize>  serializer;
3783 	char         * logInfo            = NULL;        // returned by reference
3784 	uint32_t       logInfoLength      = 0;
3785 
3786 	if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
3787 		OSKextLog(/* kext */ NULL,
3788 		    kOSKextLogErrorLevel |
3789 		    kOSKextLogIPCFlag,
3790 		    "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3791 		/* Bad programmer. */
3792 		result = kOSKextReturnInvalidArgument;
3793 		goto finish;
3794 	}
3795 
3796 	serializer = OSSerialize::withCapacity(0);
3797 	if (!serializer) {
3798 		OSKextLog(/* kext */ NULL,
3799 		    kOSKextLogErrorLevel |
3800 		    kOSKextLogIPCFlag,
3801 		    "Failed to create serializer on log info for request from user space.");
3802 		/* Incidental error; we're going to (try to) allow the request
3803 		 * itself to succeed. */
3804 	}
3805 
3806 	if (!logInfoArray->serialize(serializer.get())) {
3807 		OSKextLog(/* kext */ NULL,
3808 		    kOSKextLogErrorLevel |
3809 		    kOSKextLogIPCFlag,
3810 		    "Failed to serialize log info for request from user space.");
3811 		/* Incidental error; we're going to (try to) allow the request
3812 		 * itself to succeed. */
3813 	} else {
3814 		logInfo = serializer->text();
3815 		logInfoLength = serializer->getLength();
3816 
3817 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT);
3818 		if (kmem_result != KERN_SUCCESS) {
3819 			OSKextLog(/* kext */ NULL,
3820 			    kOSKextLogErrorLevel |
3821 			    kOSKextLogIPCFlag,
3822 			    "Failed to copy log info for request from user space.");
3823 			/* Incidental error; we're going to (try to) allow the request
3824 			 * to succeed. */
3825 		} else {
3826 			/* 11981737 - clear uninitialized data in last page */
3827 			bzero((void *)(buffer + logInfoLength),
3828 			    (round_page(logInfoLength) - logInfoLength));
3829 			memcpy(buffer, logInfo, logInfoLength);
3830 			*logInfoOut = buffer;
3831 			*logInfoLengthOut = logInfoLength;
3832 		}
3833 	}
3834 
3835 	result = kOSReturnSuccess;
3836 finish:
3837 	return result;
3838 }
3839 
3840 #if PRAGMA_MARK
3841 #pragma mark Instance Management Methods
3842 #endif
3843 /*********************************************************************
3844 *********************************************************************/
3845 OSSharedPtr<OSKext>
3846 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
3847 {
3848 	OSSharedPtr<OSKext> foundKext;
3849 
3850 	IORecursiveLockLock(sKextLock);
3851 	foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain);
3852 	IORecursiveLockUnlock(sKextLock);
3853 
3854 	return foundKext;
3855 }
3856 
3857 /*********************************************************************
3858 *********************************************************************/
3859 OSSharedPtr<OSKext>
3860 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
3861 {
3862 	return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
3863 }
3864 
3865 /*********************************************************************
3866 *********************************************************************/
3867 OSSharedPtr<OSKext>
3868 OSKext::lookupKextWithLoadTag(uint32_t aTag)
3869 {
3870 	OSSharedPtr<OSKext> foundKext;             // returned
3871 	uint32_t i, j;
3872 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
3873 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3874 
3875 	IORecursiveLockLock(sKextLock);
3876 
3877 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3878 		for (i = 0; i < count[j]; i++) {
3879 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3880 			if (thisKext->getLoadTag() == aTag) {
3881 				foundKext.reset(thisKext, OSRetain);
3882 				goto finish;
3883 			}
3884 		}
3885 	}
3886 
3887 finish:
3888 	IORecursiveLockUnlock(sKextLock);
3889 
3890 	return foundKext;
3891 }
3892 
3893 /*********************************************************************
3894 *********************************************************************/
3895 OSSharedPtr<OSKext>
3896 OSKext::lookupKextWithAddress(vm_address_t address)
3897 {
3898 	OSSharedPtr<OSKext> foundKext;             // returned
3899 	uint32_t count, i;
3900 	kmod_info_t *kmod_info;
3901 	vm_address_t originalAddress;
3902 #if defined(__arm64__)
3903 	uint64_t   textExecBase;
3904 	size_t     textExecSize;
3905 #endif /* defined(__arm64__) */
3906 
3907 	originalAddress = address;
3908 #if  __has_feature(ptrauth_calls)
3909 	address = (vm_address_t)VM_KERNEL_STRIP_PTR(address);
3910 #endif /*  __has_feature(ptrauth_calls) */
3911 
3912 	IORecursiveLockLock(sKextLock);
3913 
3914 	count = sLoadedKexts->getCount();
3915 	for (i = 0; i < count; i++) {
3916 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3917 		if (thisKext == sKernelKext) {
3918 			continue;
3919 		}
3920 		if (thisKext->kmod_info && thisKext->kmod_info->address) {
3921 			kmod_info = thisKext->kmod_info;
3922 			vm_address_t kext_start = kmod_info->address;
3923 			vm_address_t kext_end = kext_start + kmod_info->size;
3924 			if ((kext_start <= address) && (address < kext_end)) {
3925 				foundKext.reset(thisKext, OSRetain);
3926 				goto finish;
3927 			}
3928 #if defined(__arm64__)
3929 			textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize);
3930 			if ((textExecBase <= address) && (address < textExecBase + textExecSize)) {
3931 				foundKext.reset(thisKext, OSRetain);
3932 				goto finish;
3933 			}
3934 #endif /* defined (__arm64__) */
3935 		}
3936 	}
3937 	if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) {
3938 		foundKext.reset(sKernelKext, OSRetain);
3939 		goto finish;
3940 	}
3941 	/*
3942 	 * DriverKit userspace executables do not have a kernel linkedExecutable,
3943 	 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address
3944 	 * here, so use the original address passed to this method.
3945 	 *
3946 	 * This is supposed to be used for logging reasons only. When logd
3947 	 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
3948 	 * remove it here before checking it against the LoadTag.
3949 	 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
3950 	 */
3951 
3952 	address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
3953 	count = sLoadedDriverKitKexts->getCount();
3954 	for (i = 0; i < count; i++) {
3955 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
3956 		if (thisKext->getLoadTag() == address) {
3957 			foundKext.reset(thisKext, OSRetain);
3958 		}
3959 	}
3960 
3961 finish:
3962 	IORecursiveLockUnlock(sKextLock);
3963 
3964 	return foundKext;
3965 }
3966 
3967 OSSharedPtr<OSData>
3968 OSKext::copyKextUUIDForAddress(OSNumber *address)
3969 {
3970 	OSSharedPtr<OSData>   uuid;
3971 	OSSharedPtr<OSKext>   kext;
3972 
3973 	if (!address) {
3974 		return NULL;
3975 	}
3976 
3977 #if CONFIG_MACF
3978 	/* Is the calling process allowed to query kext info? */
3979 	if (current_task() != kernel_task) {
3980 		int macCheckResult = 0;
3981 		kauth_cred_t cred = NULL;
3982 
3983 		cred = kauth_cred_get_with_ref();
3984 		macCheckResult = mac_kext_check_query(cred);
3985 		kauth_cred_unref(&cred);
3986 
3987 		if (macCheckResult != 0) {
3988 			OSKextLog(/* kext */ NULL,
3989 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
3990 			    "Failed to query kext UUID (MAC policy error 0x%x).",
3991 			    macCheckResult);
3992 			return NULL;
3993 		}
3994 	}
3995 #endif
3996 
3997 	uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue());
3998 	if (slidAddress != 0) {
3999 		kext = lookupKextWithAddress(slidAddress);
4000 		if (kext) {
4001 			uuid = kext->copyTextUUID();
4002 		}
4003 	}
4004 
4005 	if (!uuid) {
4006 		/*
4007 		 * If we still don't have a UUID, then we failed to match the slid + stripped address with
4008 		 * a kext. This might have happened because the log message came from a dext.
4009 		 *
4010 		 * Try again with the original address.
4011 		 */
4012 		kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue());
4013 		if (kext && kext->isDriverKit()) {
4014 			uuid = kext->copyTextUUID();
4015 		}
4016 	}
4017 
4018 	return uuid;
4019 }
4020 
4021 /*********************************************************************
4022 *********************************************************************/
4023 OSSharedPtr<OSKext>
4024 OSKext::lookupKextWithUUID(uuid_t wanted)
4025 {
4026 	OSSharedPtr<OSKext> foundKext;             // returned
4027 	uint32_t j, i;
4028 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4029 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4030 
4031 
4032 	IORecursiveLockLock(sKextLock);
4033 
4034 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4035 		for (i = 0; i < count[j]; i++) {
4036 			OSKext   * thisKext     = NULL;
4037 
4038 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4039 			if (!thisKext) {
4040 				continue;
4041 			}
4042 
4043 			OSSharedPtr<OSData> uuid_data = thisKext->copyUUID();
4044 			if (!uuid_data) {
4045 				continue;
4046 			}
4047 
4048 			uuid_t uuid;
4049 			memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
4050 
4051 			if (0 == uuid_compare(wanted, uuid)) {
4052 				foundKext.reset(thisKext, OSRetain);
4053 				goto finish;
4054 			}
4055 		}
4056 	}
4057 finish:
4058 	IORecursiveLockUnlock(sKextLock);
4059 
4060 	return foundKext;
4061 }
4062 
4063 
4064 
4065 
4066 /*********************************************************************
4067 *********************************************************************/
4068 /* static */
4069 bool
4070 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
4071 {
4072 	bool result = false;
4073 	OSKext * foundKext = NULL;             // returned
4074 
4075 	IORecursiveLockLock(sKextLock);
4076 
4077 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4078 	if (foundKext && foundKext->isLoaded()) {
4079 		result = true;
4080 	}
4081 
4082 	IORecursiveLockUnlock(sKextLock);
4083 
4084 	return result;
4085 }
4086 
4087 /*********************************************************************
4088 * xxx - should spawn a separate thread so a kext can safely have
4089 * xxx - itself unloaded.
4090 *********************************************************************/
4091 /* static */
4092 OSReturn
4093 OSKext::removeKext(
4094 	OSKext * aKext,
4095 #if CONFIG_EMBEDDED
4096 	__unused
4097 #endif
4098 	bool     terminateServicesAndRemovePersonalitiesFlag)
4099 {
4100 #if CONFIG_EMBEDDED
4101 	OSKextLog(aKext,
4102 	    kOSKextLogErrorLevel |
4103 	    kOSKextLogKextBookkeepingFlag,
4104 	    "removeKext() called for %s, not supported on embedded",
4105 	    aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
4106 
4107 	return kOSReturnSuccess;
4108 #else /* CONFIG_EMBEDDED */
4109 
4110 	OSReturn result    = kOSKextReturnInUse;
4111 	OSKext * checkKext = NULL;         // do not release
4112 #if CONFIG_MACF
4113 	int macCheckResult = 0;
4114 	kauth_cred_t cred  = NULL;
4115 #endif
4116 
4117 	IORecursiveLockLock(sKextLock);
4118 
4119 	/* If the kext has no identifier, it failed to init
4120 	 * so isn't in sKextsByID and it isn't loaded.
4121 	 */
4122 	if (!aKext->getIdentifier()) {
4123 		result = kOSReturnSuccess;
4124 		goto finish;
4125 	}
4126 
4127 	checkKext = OSDynamicCast(OSKext,
4128 	    sKextsByID->getObject(aKext->getIdentifier()));
4129 	if (checkKext != aKext) {
4130 		result = kOSKextReturnNotFound;
4131 		goto finish;
4132 	}
4133 
4134 	if (aKext->isLoaded()) {
4135 #if CONFIG_MACF
4136 		if (current_task() != kernel_task) {
4137 			cred = kauth_cred_get_with_ref();
4138 			macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
4139 			kauth_cred_unref(&cred);
4140 		}
4141 
4142 		if (macCheckResult != 0) {
4143 			result = kOSReturnError;
4144 			OSKextLog(aKext,
4145 			    kOSKextLogErrorLevel |
4146 			    kOSKextLogKextBookkeepingFlag,
4147 			    "Failed to remove kext %s (MAC policy error 0x%x).",
4148 			    aKext->getIdentifierCString(), macCheckResult);
4149 			goto finish;
4150 		}
4151 #endif
4152 
4153 		/* make sure there are no resource requests in flight - 17187548 */
4154 		if (aKext->countRequestCallbacks()) {
4155 			goto finish;
4156 		}
4157 		if (aKext->flags.unloadUnsupported) {
4158 			result = kOSKextReturnInUse;
4159 			OSKextLog(aKext,
4160 			    kOSKextLogErrorLevel |
4161 			    kOSKextLogKextBookkeepingFlag,
4162 			    "Can't remove kext %s; unsupported by cache.",
4163 			    aKext->getIdentifierCString());
4164 			goto finish;
4165 		}
4166 
4167 		/* If we are terminating, send the request to the IOCatalogue
4168 		 * (which will actually call us right back but that's ok we have
4169 		 * a recursive lock don't you know) but do not ask the IOCatalogue
4170 		 * to call back with an unload, we'll do that right here.
4171 		 */
4172 		if (terminateServicesAndRemovePersonalitiesFlag) {
4173 			result = gIOCatalogue->terminateDriversForModule(
4174 				aKext->getIdentifierCString(), /* unload */ false);
4175 			if (result != kOSReturnSuccess) {
4176 				OSKextLog(aKext,
4177 				    kOSKextLogErrorLevel |
4178 				    kOSKextLogKextBookkeepingFlag,
4179 				    "Can't remove kext %s; services failed to terminate - 0x%x.",
4180 				    aKext->getIdentifierCString(), result);
4181 				goto finish;
4182 			}
4183 		}
4184 
4185 		result = aKext->unload();
4186 		if (result != kOSReturnSuccess) {
4187 			goto finish;
4188 		}
4189 	}
4190 
4191 	/* Remove personalities as requested. This is a bit redundant for a loaded
4192 	 * kext as IOCatalogue::terminateDriversForModule() removes driver
4193 	 * personalities, but it doesn't restart matching, which we always want
4194 	 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
4195 	 * that happens.
4196 	 */
4197 	if (terminateServicesAndRemovePersonalitiesFlag) {
4198 		aKext->removePersonalitiesFromCatalog();
4199 	}
4200 
4201 	if (aKext->isInFileset()) {
4202 		OSKextLog(aKext,
4203 		    kOSKextLogProgressLevel |
4204 		    kOSKextLogKextBookkeepingFlag,
4205 		    "Fileset kext %s unloaded.",
4206 		    aKext->getIdentifierCString());
4207 	} else {
4208 		OSKextLog(aKext,
4209 		    kOSKextLogProgressLevel |
4210 		    kOSKextLogKextBookkeepingFlag,
4211 		    "Removing kext %s.",
4212 		    aKext->getIdentifierCString());
4213 
4214 		sKextsByID->removeObject(aKext->getIdentifier());
4215 	}
4216 	result = kOSReturnSuccess;
4217 
4218 finish:
4219 	IORecursiveLockUnlock(sKextLock);
4220 	return result;
4221 #endif /* CONFIG_EMBEDDED */
4222 }
4223 
4224 /*********************************************************************
4225 *********************************************************************/
4226 /* static */
4227 OSReturn
4228 OSKext::removeKextWithIdentifier(
4229 	const char * kextIdentifier,
4230 	bool         terminateServicesAndRemovePersonalitiesFlag)
4231 {
4232 	OSReturn result = kOSReturnError;
4233 
4234 	IORecursiveLockLock(sKextLock);
4235 
4236 	OSKext * aKext = OSDynamicCast(OSKext,
4237 	    sKextsByID->getObject(kextIdentifier));
4238 	if (!aKext) {
4239 		result = kOSKextReturnNotFound;
4240 		OSKextLog(/* kext */ NULL,
4241 		    kOSKextLogErrorLevel |
4242 		    kOSKextLogKextBookkeepingFlag,
4243 		    "Can't remove kext %s - not found.",
4244 		    kextIdentifier);
4245 		goto finish;
4246 	}
4247 
4248 	result = OSKext::removeKext(aKext,
4249 	    terminateServicesAndRemovePersonalitiesFlag);
4250 
4251 finish:
4252 	IORecursiveLockUnlock(sKextLock);
4253 
4254 	return result;
4255 }
4256 
4257 /*********************************************************************
4258 *********************************************************************/
4259 /* static */
4260 OSReturn
4261 OSKext::removeKextWithLoadTag(
4262 	OSKextLoadTag loadTag,
4263 	bool          terminateServicesAndRemovePersonalitiesFlag)
4264 {
4265 	OSReturn result    = kOSReturnError;
4266 	OSKext * foundKext = NULL;
4267 	uint32_t i, j;
4268 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4269 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4270 
4271 
4272 	IORecursiveLockLock(sKextLock);
4273 
4274 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4275 		for (i = 0; i < count[j]; i++) {
4276 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4277 			if (thisKext->loadTag == loadTag) {
4278 				foundKext = thisKext;
4279 				break;
4280 			}
4281 		}
4282 	}
4283 
4284 	if (!foundKext) {
4285 		result = kOSKextReturnNotFound;
4286 		OSKextLog(/* kext */ NULL,
4287 		    kOSKextLogErrorLevel |
4288 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4289 		    "Can't remove kext with load tag %d - not found.",
4290 		    loadTag);
4291 		goto finish;
4292 	}
4293 
4294 	result = OSKext::removeKext(foundKext,
4295 	    terminateServicesAndRemovePersonalitiesFlag);
4296 
4297 finish:
4298 	IORecursiveLockUnlock(sKextLock);
4299 
4300 	return result;
4301 }
4302 
4303 /*********************************************************************
4304 *********************************************************************/
4305 OSSharedPtr<OSDictionary>
4306 OSKext::copyKexts(void)
4307 {
4308 	OSSharedPtr<OSDictionary> result;
4309 
4310 	IORecursiveLockLock(sKextLock);
4311 	result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection());
4312 	IORecursiveLockUnlock(sKextLock);
4313 
4314 	return result;
4315 }
4316 
4317 /*********************************************************************
4318 *********************************************************************/
4319 #define BOOTER_KEXT_PREFIX   "Driver-"
4320 
4321 typedef struct _DeviceTreeBuffer {
4322 	uint32_t paddr;
4323 	uint32_t length;
4324 } _DeviceTreeBuffer;
4325 
4326 /*********************************************************************
4327 * Create a dictionary of excluded kexts from the given booter data.
4328 *********************************************************************/
4329 /* static */
4330 void
4331 OSKext::createExcludeListFromBooterData(
4332 	OSDictionary *          theDictionary,
4333 	OSCollectionIterator *  theIterator )
4334 {
4335 	OSString                  * deviceTreeName      = NULL;        // do not release
4336 	const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;        // do not release
4337 	char                      * booterDataPtr       = NULL;        // do not release
4338 	_BooterKextFileInfo       * kextFileInfo        = NULL;        // do not release
4339 	char                      * infoDictAddr        = NULL;        // do not release
4340 	OSSharedPtr<OSObject>       parsedXML;
4341 	OSDictionary              * theInfoDict         = NULL;        // do not release
4342 
4343 	theIterator->reset();
4344 
4345 	/* look for AppleKextExcludeList.kext */
4346 	while ((deviceTreeName =
4347 	    OSDynamicCast(OSString, theIterator->getNextObject()))) {
4348 		const char *    devTreeNameCString;
4349 		OSData *        deviceTreeEntry;        // do not release
4350 		OSString *      myBundleID;        // do not release
4351 
4352 		deviceTreeEntry =
4353 		    OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
4354 		if (!deviceTreeEntry) {
4355 			continue;
4356 		}
4357 
4358 		/* Make sure it is a kext */
4359 		devTreeNameCString = deviceTreeName->getCStringNoCopy();
4360 		if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
4361 		    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
4362 			OSKextLog(NULL,
4363 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4364 			    "\"%s\" not a kext",
4365 			    devTreeNameCString);
4366 			continue;
4367 		}
4368 
4369 		deviceTreeBuffer = (const _DeviceTreeBuffer *)
4370 		    deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
4371 		if (!deviceTreeBuffer) {
4372 			continue;
4373 		}
4374 
4375 		booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
4376 		if (!booterDataPtr) {
4377 			continue;
4378 		}
4379 
4380 		kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
4381 		if (!kextFileInfo->infoDictPhysAddr ||
4382 		    !kextFileInfo->infoDictLength) {
4383 			continue;
4384 		}
4385 
4386 		infoDictAddr = (char *)
4387 		    ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
4388 		if (!infoDictAddr) {
4389 			continue;
4390 		}
4391 
4392 		parsedXML = OSUnserializeXML(infoDictAddr);
4393 		if (!parsedXML) {
4394 			continue;
4395 		}
4396 
4397 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
4398 		if (!theInfoDict) {
4399 			continue;
4400 		}
4401 
4402 		myBundleID =
4403 		    OSDynamicCast(OSString,
4404 		    theInfoDict->getObject(kCFBundleIdentifierKey));
4405 		if (myBundleID &&
4406 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4407 			boolean_t updated = updateExcludeList(theInfoDict);
4408 			if (!updated) {
4409 				/* 25322874 */
4410 				panic("Missing OSKextExcludeList dictionary");
4411 			}
4412 			break;
4413 		}
4414 	}         // while ( (deviceTreeName = ...) )
4415 
4416 	return;
4417 }
4418 
4419 /*********************************************************************
4420 * Create a dictionary of excluded kexts from the given prelink
4421 * info (kernelcache).
4422 *********************************************************************/
4423 /* static */
4424 void
4425 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
4426 {
4427 	OSDictionary *  myInfoDict = NULL;        // do not release
4428 	OSString *      myBundleID;        // do not release
4429 	u_int           i;
4430 
4431 	/* Find the Apple Kext Exclude List. */
4432 	for (i = 0; i < theInfoArray->getCount(); i++) {
4433 		myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
4434 		if (!myInfoDict) {
4435 			continue;
4436 		}
4437 		myBundleID =
4438 		    OSDynamicCast(OSString,
4439 		    myInfoDict->getObject(kCFBundleIdentifierKey));
4440 		if (myBundleID &&
4441 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4442 			boolean_t updated = updateExcludeList(myInfoDict);
4443 			if (!updated) {
4444 				/* 25322874 */
4445 				panic("Missing OSKextExcludeList dictionary");
4446 			}
4447 			break;
4448 		}
4449 	}         // for (i = 0; i < theInfoArray->getCount()...
4450 
4451 	return;
4452 }
4453 
4454 /* static */
4455 boolean_t
4456 OSKext::updateExcludeList(OSDictionary *infoDict)
4457 {
4458 	OSDictionary *myTempDict = NULL;         // do not free
4459 	OSString     *myTempString = NULL;        // do not free
4460 	OSKextVersion newVersion = 0;
4461 	boolean_t updated = false;
4462 
4463 	if (!infoDict) {
4464 		return false;
4465 	}
4466 
4467 	myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
4468 	if (!myTempDict) {
4469 		return false;
4470 	}
4471 
4472 	myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
4473 	if (!myTempString) {
4474 		return false;
4475 	}
4476 
4477 	newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
4478 	if (newVersion == 0) {
4479 		return false;
4480 	}
4481 
4482 	IORecursiveLockLock(sKextLock);
4483 
4484 	if (newVersion > sExcludeListVersion) {
4485 		sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
4486 		sExcludeListVersion = newVersion;
4487 		updated = true;
4488 	}
4489 
4490 	IORecursiveLockUnlock(sKextLock);
4491 	return updated;
4492 }
4493 
4494 #if PRAGMA_MARK
4495 #pragma mark Accessors
4496 #endif
4497 /*********************************************************************
4498 *********************************************************************/
4499 const OSSymbol *
4500 OSKext::getIdentifier(void)
4501 {
4502 	return bundleID.get();
4503 }
4504 
4505 /*********************************************************************
4506 * A kext must have a bundle identifier to even survive initialization;
4507 * this is guaranteed to exist past then.
4508 *********************************************************************/
4509 const char *
4510 OSKext::getIdentifierCString(void)
4511 {
4512 	return bundleID->getCStringNoCopy();
4513 }
4514 
4515 /*********************************************************************
4516 *********************************************************************/
4517 OSKextVersion
4518 OSKext::getVersion(void)
4519 {
4520 	return version;
4521 }
4522 
4523 /*********************************************************************
4524 *********************************************************************/
4525 OSKextVersion
4526 OSKext::getCompatibleVersion(void)
4527 {
4528 	return compatibleVersion;
4529 }
4530 
4531 /*********************************************************************
4532 *********************************************************************/
4533 bool
4534 OSKext::isLibrary(void)
4535 {
4536 	return getCompatibleVersion() > 0;
4537 }
4538 
4539 /*********************************************************************
4540 *********************************************************************/
4541 bool
4542 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
4543 {
4544 	if ((compatibleVersion > -1 && version > -1) &&
4545 	    (compatibleVersion <= version && aVersion <= version)) {
4546 		return true;
4547 	}
4548 	return false;
4549 }
4550 
4551 /*********************************************************************
4552 *********************************************************************/
4553 bool
4554 OSKext::declaresExecutable(void)
4555 {
4556 	if (isDriverKit()) {
4557 		return false;
4558 	}
4559 	return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
4560 }
4561 
4562 /*********************************************************************
4563 *********************************************************************/
4564 OSData *
4565 OSKext::getExecutable(void)
4566 {
4567 	OSData * result              = NULL;
4568 	OSSharedPtr<OSData> extractedExecutable;
4569 
4570 	if (flags.builtin) {
4571 		return sKernelKext->linkedExecutable.get();
4572 	}
4573 
4574 	result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
4575 	if (result) {
4576 		return result;
4577 	}
4578 
4579 #if CONFIG_KXLD
4580 	OSData * mkextExecutableRef  = NULL;        // do not release
4581 	mkextExecutableRef = OSDynamicCast(OSData,
4582 	    getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
4583 
4584 	if (mkextExecutableRef) {
4585 		MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
4586 		    mkextExecutableRef->getBytesNoCopy();
4587 		uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
4588 		if (mkextVersion == MKEXT_VERS_2) {
4589 			mkext2_file_entry * fileinfo =
4590 			    (mkext2_file_entry *)mkextEntryRef->fileinfo;
4591 			uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
4592 			uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
4593 			extractedExecutable = extractMkext2FileData(
4594 				MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
4595 				compressedSize, fullSize);
4596 		} else {
4597 			OSKextLog(this, kOSKextLogErrorLevel |
4598 			    kOSKextLogArchiveFlag,
4599 			    "Kext %s - unknown mkext version 0x%x for executable.",
4600 			    getIdentifierCString(), mkextVersion);
4601 		}
4602 
4603 		/* Regardless of success, remove the mkext executable,
4604 		 * and drop one reference on the mkext.  (setExecutable() does not
4605 		 * replace, it removes, or panics if asked to replace.)
4606 		 */
4607 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4608 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4609 
4610 		if (extractedExecutable && extractedExecutable->getLength()) {
4611 			if (!setExecutable(extractedExecutable.get())) {
4612 				goto finish;
4613 			}
4614 			result = extractedExecutable.get();
4615 		} else {
4616 			goto finish;
4617 		}
4618 	}
4619 
4620 finish:
4621 #endif // CONFIG_KXLD
4622 	return result;
4623 }
4624 
4625 /*********************************************************************
4626 *********************************************************************/
4627 bool
4628 OSKext::isInterface(void)
4629 {
4630 	return flags.interface;
4631 }
4632 
4633 /*********************************************************************
4634 *********************************************************************/
4635 bool
4636 OSKext::isKernel(void)
4637 {
4638 	return this == sKernelKext;
4639 }
4640 
4641 /*********************************************************************
4642 *********************************************************************/
4643 bool
4644 OSKext::isKernelComponent(void)
4645 {
4646 	return flags.kernelComponent ? true : false;
4647 }
4648 
4649 /*********************************************************************
4650 *********************************************************************/
4651 bool
4652 OSKext::isExecutable(void)
4653 {
4654 	return !isKernel() && !isInterface() && declaresExecutable();
4655 }
4656 
4657 /*********************************************************************
4658 * We might want to check this recursively for all dependencies,
4659 * since a subtree of dependencies could get loaded before we hit
4660 * a dependency that isn't safe-boot-loadable.
4661 *
4662 * xxx - Might want to return false if OSBundleEnableKextLogging or
4663 * OSBundleDebugLevel
4664 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4665 * the point except it's usually development drivers, which might
4666 * cause panics on startup, that have those properties). Heh; could
4667 * use a "kx" boot-arg!
4668 *********************************************************************/
4669 bool
4670 OSKext::isLoadableInSafeBoot(void)
4671 {
4672 	bool       result   = false;
4673 	OSString * required = NULL;         // do not release
4674 
4675 	if (isKernel()) {
4676 		result = true;
4677 		goto finish;
4678 	}
4679 
4680 	if (isDriverKit()) {
4681 		result = true;
4682 		goto finish;
4683 	}
4684 
4685 	required = OSDynamicCast(OSString,
4686 	    getPropertyForHostArch(kOSBundleRequiredKey));
4687 	if (!required) {
4688 		goto finish;
4689 	}
4690 	if (required->isEqualTo(kOSBundleRequiredRoot) ||
4691 	    required->isEqualTo(kOSBundleRequiredLocalRoot) ||
4692 	    required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
4693 	    required->isEqualTo(kOSBundleRequiredSafeBoot) ||
4694 	    required->isEqualTo(kOSBundleRequiredConsole)) {
4695 		result = true;
4696 	}
4697 
4698 finish:
4699 	return result;
4700 }
4701 
4702 /*********************************************************************
4703 *********************************************************************/
4704 bool
4705 OSKext::isPrelinked(void)
4706 {
4707 	return flags.prelinked ? true : false;
4708 }
4709 
4710 /*********************************************************************
4711 *********************************************************************/
4712 bool
4713 OSKext::isLoaded(void)
4714 {
4715 	return flags.loaded ? true : false;
4716 }
4717 
4718 /*********************************************************************
4719 *********************************************************************/
4720 bool
4721 OSKext::isStarted(void)
4722 {
4723 	return flags.started ? true : false;
4724 }
4725 
4726 /*********************************************************************
4727 *********************************************************************/
4728 bool
4729 OSKext::isCPPInitialized(void)
4730 {
4731 	return flags.CPPInitialized;
4732 }
4733 
4734 /*********************************************************************
4735 *********************************************************************/
4736 void
4737 OSKext::setCPPInitialized(bool initialized)
4738 {
4739 	flags.CPPInitialized = initialized;
4740 }
4741 
4742 /*********************************************************************
4743 *********************************************************************/
4744 uint32_t
4745 OSKext::getLoadTag(void)
4746 {
4747 	return loadTag;
4748 }
4749 
4750 /*********************************************************************
4751 *********************************************************************/
4752 void
4753 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
4754 {
4755 	if (linkedExecutable) {
4756 		*loadSize = linkedExecutable->getLength();
4757 
4758 		/* If we have a kmod_info struct, calculated the wired size
4759 		 * from that. Otherwise it's the full load size.
4760 		 */
4761 		if (kmod_info) {
4762 			*wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size;
4763 		} else {
4764 			*wiredSize = *loadSize;
4765 		}
4766 	} else {
4767 		*wiredSize = 0;
4768 		*loadSize = 0;
4769 	}
4770 }
4771 
4772 /*********************************************************************
4773 *********************************************************************/
4774 OSSharedPtr<OSData>
4775 OSKext::copyUUID(void)
4776 {
4777 	OSSharedPtr<OSData>          result;
4778 	OSData                     * theExecutable = NULL;        // do not release
4779 	const kernel_mach_header_t * header;
4780 
4781 	/* An interface kext doesn't have a linked executable with an LC_UUID,
4782 	 * we create one when it's linked.
4783 	 */
4784 	if (interfaceUUID) {
4785 		result = interfaceUUID;
4786 		goto finish;
4787 	}
4788 
4789 	if (flags.builtin || isInterface()) {
4790 		return sKernelKext->copyUUID();
4791 	}
4792 
4793 	if (isDriverKit() && infoDict) {
4794 		return driverKitUUID;
4795 	}
4796 
4797 	/* For real kexts, try to get the UUID from the linked executable,
4798 	 * or if is hasn't been linked yet, the unrelocated executable.
4799 	 */
4800 	theExecutable = linkedExecutable.get();
4801 	if (!theExecutable) {
4802 		theExecutable = getExecutable();
4803 	}
4804 
4805 	if (!theExecutable) {
4806 		goto finish;
4807 	}
4808 
4809 	header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
4810 	result = copyMachoUUID(header);
4811 
4812 finish:
4813 	return result;
4814 }
4815 
4816 /*********************************************************************
4817 *********************************************************************/
4818 OSSharedPtr<OSData>
4819 OSKext::copyTextUUID(void)
4820 {
4821 	if (flags.builtin) {
4822 		return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
4823 	}
4824 	return copyUUID();
4825 }
4826 
4827 /*********************************************************************
4828 *********************************************************************/
4829 OSSharedPtr<OSData>
4830 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
4831 {
4832 	OSSharedPtr<OSData>                     result;
4833 	const struct load_command  * load_cmd      = NULL;
4834 	const struct uuid_command  * uuid_cmd      = NULL;
4835 	uint32_t                     i;
4836 
4837 	load_cmd = (const struct load_command *)&header[1];
4838 
4839 	if (header->magic != MH_MAGIC_KERNEL) {
4840 		OSKextLog(NULL,
4841 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4842 		    "%s: bad header %p",
4843 		    __func__,
4844 		    header);
4845 		goto finish;
4846 	}
4847 
4848 	for (i = 0; i < header->ncmds; i++) {
4849 		if (load_cmd->cmd == LC_UUID) {
4850 			uuid_cmd = (struct uuid_command *)load_cmd;
4851 			result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid));
4852 			goto finish;
4853 		}
4854 		load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
4855 	}
4856 
4857 finish:
4858 	return result;
4859 }
4860 
4861 void
4862 OSKext::setDriverKitUUID(OSData *uuid)
4863 {
4864 	if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
4865 		OSSafeReleaseNULL(uuid);
4866 	}
4867 }
4868 
4869 /*********************************************************************
4870 *********************************************************************/
4871 #if defined (__arm__)
4872 #include <arm/arch.h>
4873 #endif
4874 
4875 #if   defined (__x86_64__)
4876 #define ARCHNAME "x86_64"
4877 #elif defined (__arm64__)
4878 #define ARCHNAME "arm64"
4879 #elif defined (__arm__)
4880 
4881 #if defined (__ARM_ARCH_7S__)
4882 #define ARCHNAME "armv7s"
4883 #elif defined (__ARM_ARCH_7F__)
4884 #define ARCHNAME "armv7f"
4885 #elif defined (__ARM_ARCH_7K__)
4886 #define ARCHNAME "armv7k"
4887 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
4888 #define ARCHNAME "armv7"
4889 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
4890 #define ARCHNAME "armv6"
4891 #endif
4892 
4893 #elif defined (__arm64__)
4894 #define ARCHNAME "arm64"
4895 #else
4896 #error architecture not supported
4897 #endif
4898 
4899 #define ARCH_SEPARATOR_CHAR  '_'
4900 
4901 static char *
4902 makeHostArchKey(const char * key, size_t * keySizeOut)
4903 {
4904 	char     * result = NULL;
4905 	size_t     keyLength = strlen(key);
4906 	size_t     keySize;
4907 
4908 	/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4909 	 */
4910 	keySize = 1 + 1 + keyLength + strlen(ARCHNAME);
4911 	result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
4912 
4913 	if (!result) {
4914 		goto finish;
4915 	}
4916 	strlcpy(result, key, keySize);
4917 	result[keyLength++] = ARCH_SEPARATOR_CHAR;
4918 	result[keyLength] = '\0';
4919 	strlcat(result, ARCHNAME, keySize);
4920 	*keySizeOut = keySize;
4921 
4922 finish:
4923 	return result;
4924 }
4925 
4926 /*********************************************************************
4927 *********************************************************************/
4928 OSObject *
4929 OSKext::getPropertyForHostArch(const char * key)
4930 {
4931 	OSObject * result           = NULL;// do not release
4932 	size_t     hostArchKeySize  = 0;
4933 	char     * hostArchKey      = NULL;// must kfree
4934 
4935 	if (!key || !infoDict) {
4936 		goto finish;
4937 	}
4938 
4939 	/* Some properties are not allowed to be arch-variant:
4940 	 * - Any CFBundle... property.
4941 	 * - OSBundleIsInterface.
4942 	 * - OSKernelResource.
4943 	 */
4944 	if (STRING_HAS_PREFIX(key, "OS") ||
4945 	    STRING_HAS_PREFIX(key, "IO")) {
4946 		hostArchKey = makeHostArchKey(key, &hostArchKeySize);
4947 		if (!hostArchKey) {
4948 			OSKextLog(/* kext (this isn't about a kext) */ NULL,
4949 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4950 			    "Allocation failure.");
4951 			goto finish;
4952 		}
4953 		result = infoDict->getObject(hostArchKey);
4954 	}
4955 
4956 	if (!result) {
4957 		result = infoDict->getObject(key);
4958 	}
4959 
4960 finish:
4961 	if (hostArchKey) {
4962 		kfree_data(hostArchKey, hostArchKeySize);
4963 	}
4964 	return result;
4965 }
4966 
4967 #if PRAGMA_MARK
4968 #pragma mark Load/Start/Stop/Unload
4969 #endif
4970 
4971 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4972 
4973 /*********************************************************************
4974 * sExcludeListByID is a dictionary with keys / values of:
4975 *  key = bundleID string of kext we will not allow to load
4976 *  value = version string(s) of the kext that is to be denied loading.
4977 *      The version strings can be comma delimited.  For example if kext
4978 *      com.foocompany.fookext has two versions that we want to deny
4979 *      loading then the version strings might look like:
4980 *      1.0.0, 1.0.1
4981 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4982 *      not load the kext.
4983 *
4984 *      Value may also be in the form of "LE 2.0.0" (version numbers
4985 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4986 *      number less than 2.0.0 will not load)
4987 *
4988 *      NOTE - we cannot use the characters "<=" or "<" because we have code
4989 *      that serializes plists and treats '<' as a special character.
4990 *********************************************************************/
4991 bool
4992 OSKext::isInExcludeList(void)
4993 {
4994 	OSString *      versionString           = NULL;        // do not release
4995 	char *          versionCString          = NULL;        // do not free
4996 	size_t          i;
4997 	boolean_t       wantLessThan = false;
4998 	boolean_t       wantLessThanEqualTo = false;
4999 	boolean_t       isInExcludeList = true;
5000 	char            myBuffer[32];
5001 
5002 	IORecursiveLockLock(sKextLock);
5003 
5004 	if (!sExcludeListByID) {
5005 		isInExcludeList = false;
5006 	} else {
5007 		/* look up by bundleID in our exclude list and if found get version
5008 		 * string (or strings) that we will not allow to load
5009 		 */
5010 		versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get()));
5011 		if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
5012 			isInExcludeList = false;
5013 		}
5014 	}
5015 
5016 	IORecursiveLockUnlock(sKextLock);
5017 
5018 	if (!isInExcludeList) {
5019 		return false;
5020 	}
5021 
5022 	/* parse version strings */
5023 	versionCString = (char *) versionString->getCStringNoCopy();
5024 
5025 	/* look for "LT" or "LE" form of version string, must be in first two
5026 	 * positions.
5027 	 */
5028 	if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
5029 		wantLessThan = true;
5030 		versionCString += 2;
5031 	} else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
5032 		wantLessThanEqualTo = true;
5033 		versionCString += 2;
5034 	}
5035 
5036 	for (i = 0; *versionCString != 0x00; versionCString++) {
5037 		/* skip whitespace */
5038 		if (isWhiteSpace(*versionCString)) {
5039 			continue;
5040 		}
5041 
5042 		/* peek ahead for version string separator or null terminator */
5043 		if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
5044 			/* OK, we have a version string */
5045 			myBuffer[i++] = *versionCString;
5046 			myBuffer[i] = 0x00;
5047 
5048 			OSKextVersion excludeVers;
5049 			excludeVers = OSKextParseVersionString(myBuffer);
5050 
5051 			if (wantLessThanEqualTo) {
5052 				if (version <= excludeVers) {
5053 					return true;
5054 				}
5055 			} else if (wantLessThan) {
5056 				if (version < excludeVers) {
5057 					return true;
5058 				}
5059 			} else if (version == excludeVers) {
5060 				return true;
5061 			}
5062 
5063 			/* reset for the next (if any) version string */
5064 			i = 0;
5065 			wantLessThan = false;
5066 			wantLessThanEqualTo = false;
5067 		} else {
5068 			/* save valid version character */
5069 			myBuffer[i++] = *versionCString;
5070 
5071 			/* make sure bogus version string doesn't overrun local buffer */
5072 			if (i >= sizeof(myBuffer)) {
5073 				break;
5074 			}
5075 		}
5076 	}
5077 
5078 	return false;
5079 }
5080 
5081 /*********************************************************************
5082 * sNonLoadableKextsByID is a dictionary with keys / values of:
5083 *  key = bundleID string of kext we will not allow to load
5084 *  value = boolean (true == loadable, false == not loadable)
5085 *
5086 *  Only kexts which are in the AuxKC will be marked as "not loadble,"
5087 *  i.e., the value for the kext's bundleID will be false. All kexts in
5088 *  the primary and system KCs will always be marked as "loadable."
5089 *
5090 *  This list ultimately comes from kexts which have been uninstalled
5091 *  in user space by deleting the kext from disk, but which have not
5092 *  yet been removed from the AuxKC. Because the user could choose to
5093 *  re-install the exact same version of the kext, we need to keep
5094 *  a dictionary of boolean values so that user space only needs to
5095 *  keep a simple list of "uninstalled" or "missing" bundles. When
5096 *  a bundle is re-installed, the iokit daemon can use the
5097 *  AucKCBundleAvailable  predicate to set the individual kext's
5098 *  availability to true.
5099 *********************************************************************/
5100 bool
5101 OSKext::isLoadable(void)
5102 {
5103 	bool isLoadable = true;
5104 
5105 	if (kc_type != KCKindAuxiliary) {
5106 		/* this filtering only applies to kexts in the auxkc */
5107 		return true;
5108 	}
5109 
5110 	IORecursiveLockLock(sKextLock);
5111 
5112 	if (sNonLoadableKextsByID) {
5113 		/* look up by bundleID in our exclude list and if found get version
5114 		 * string (or strings) that we will not allow to load
5115 		 */
5116 		OSBoolean *loadableVal;
5117 		loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get()));
5118 		if (loadableVal && !loadableVal->getValue()) {
5119 			isLoadable = false;
5120 		}
5121 	}
5122 	IORecursiveLockUnlock(sKextLock);
5123 
5124 	return isLoadable;
5125 }
5126 
5127 /*********************************************************************
5128 *********************************************************************/
5129 /* static */
5130 OSReturn
5131 OSKext::loadKextWithIdentifier(
5132 	const char       * kextIdentifierCString,
5133 	Boolean            allowDeferFlag,
5134 	Boolean            delayAutounloadFlag,
5135 	OSKextExcludeLevel startOpt,
5136 	OSKextExcludeLevel startMatchingOpt,
5137 	OSArray          * personalityNames)
5138 {
5139 	OSReturn   result         = kOSReturnError;
5140 	OSSharedPtr<OSString> kextIdentifier;
5141 
5142 	kextIdentifier = OSString::withCString(kextIdentifierCString);
5143 	if (!kextIdentifier) {
5144 		result = kOSKextReturnNoMemory;
5145 		goto finish;
5146 	}
5147 	result = OSKext::loadKextWithIdentifier(kextIdentifier.get(),
5148 	    NULL /* kextRef */,
5149 	    allowDeferFlag, delayAutounloadFlag,
5150 	    startOpt, startMatchingOpt, personalityNames);
5151 
5152 finish:
5153 	return result;
5154 }
5155 
5156 OSReturn
5157 OSKext::loadKextWithIdentifier(
5158 	OSString          * kextIdentifier,
5159 	OSSharedPtr<OSObject>         &kextRef,
5160 	Boolean             allowDeferFlag,
5161 	Boolean             delayAutounloadFlag,
5162 	OSKextExcludeLevel  startOpt,
5163 	OSKextExcludeLevel  startMatchingOpt,
5164 	OSArray           * personalityNames)
5165 {
5166 	OSObject * kextRefRaw = NULL;
5167 	OSReturn result;
5168 
5169 	result = loadKextWithIdentifier(kextIdentifier,
5170 	    &kextRefRaw,
5171 	    allowDeferFlag,
5172 	    delayAutounloadFlag,
5173 	    startOpt,
5174 	    startMatchingOpt,
5175 	    personalityNames);
5176 	if ((kOSReturnSuccess == result) && kextRefRaw) {
5177 		kextRef.reset(kextRefRaw, OSNoRetain);
5178 	}
5179 	return result;
5180 }
5181 
5182 /*********************************************************************
5183 *********************************************************************/
5184 OSReturn
5185 OSKext::loadKextWithIdentifier(
5186 	OSString          * kextIdentifier,
5187 	OSObject         ** kextRef,
5188 	Boolean             allowDeferFlag,
5189 	Boolean             delayAutounloadFlag,
5190 	OSKextExcludeLevel  startOpt,
5191 	OSKextExcludeLevel  startMatchingOpt,
5192 	OSArray           * personalityNames)
5193 {
5194 	OSReturn          result               = kOSReturnError;
5195 	OSReturn          pingResult           = kOSReturnError;
5196 	OSKext          * theKext              = NULL;        // do not release
5197 	OSSharedPtr<OSDictionary>   loadRequest;
5198 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5199 
5200 	if (kextRef) {
5201 		*kextRef = NULL;
5202 	}
5203 
5204 	IORecursiveLockLock(sKextLock);
5205 
5206 	if (!kextIdentifier) {
5207 		result = kOSKextReturnInvalidArgument;
5208 		goto finish;
5209 	}
5210 
5211 	OSKext::recordIdentifierRequest(kextIdentifier);
5212 
5213 	theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
5214 	if (!theKext) {
5215 		if (!allowDeferFlag) {
5216 			OSKextLog(/* kext */ NULL,
5217 			    kOSKextLogErrorLevel |
5218 			    kOSKextLogLoadFlag,
5219 			    "Can't load kext %s - not found.",
5220 			    kextIdentifier->getCStringNoCopy());
5221 			goto finish;
5222 		}
5223 
5224 		if (!sKernelRequestsEnabled) {
5225 			OSKextLog(theKext,
5226 			    kOSKextLogErrorLevel |
5227 			    kOSKextLogLoadFlag,
5228 			    "Can't load kext %s - requests to user space are disabled.",
5229 			    kextIdentifier->getCStringNoCopy());
5230 			result = kOSKextReturnDisabled;
5231 			goto finish;
5232 		}
5233 
5234 		/* Create a new request unless one is already sitting
5235 		 * in sKernelRequests for this bundle identifier
5236 		 */
5237 		kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5238 		if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5239 			result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
5240 			    loadRequest);
5241 			if (result != kOSReturnSuccess) {
5242 				goto finish;
5243 			}
5244 			if (!_OSKextSetRequestArgument(loadRequest.get(),
5245 			    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
5246 				result = kOSKextReturnNoMemory;
5247 				goto finish;
5248 			}
5249 			if (!sKernelRequests->setObject(loadRequest.get())) {
5250 				result = kOSKextReturnNoMemory;
5251 				goto finish;
5252 			}
5253 
5254 			if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
5255 				result = kOSKextReturnNoMemory;
5256 				goto finish;
5257 			}
5258 
5259 			OSKextLog(theKext,
5260 			    kOSKextLogDebugLevel |
5261 			    kOSKextLogLoadFlag,
5262 			    "Kext %s not found; queued load request to user space.",
5263 			    kextIdentifier->getCStringNoCopy());
5264 		}
5265 
5266 		pingResult = OSKext::pingIOKitDaemon();
5267 		if (pingResult == kOSKextReturnDisabled) {
5268 			OSKextLog(/* kext */ NULL,
5269 			    ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
5270 			    kOSKextLogLoadFlag,
5271 			    "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.",
5272 			    kextIdentifier->getCStringNoCopy());
5273 		}
5274 
5275 		result = kOSKextReturnDeferred;
5276 		goto finish;
5277 	}
5278 
5279 	result = theKext->load(startOpt, startMatchingOpt, personalityNames);
5280 
5281 	if (result != kOSReturnSuccess) {
5282 		OSKextLog(theKext,
5283 		    kOSKextLogErrorLevel |
5284 		    kOSKextLogLoadFlag,
5285 		    "Failed to load kext %s (error 0x%x).",
5286 		    kextIdentifier->getCStringNoCopy(), (int)result);
5287 
5288 		if (theKext->kc_type == KCKindUnknown) {
5289 			OSKext::removeKext(theKext,
5290 			    /* terminateService/removePersonalities */ true);
5291 		}
5292 		goto finish;
5293 	}
5294 
5295 	if (delayAutounloadFlag) {
5296 		OSKextLog(theKext,
5297 		    kOSKextLogProgressLevel |
5298 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5299 		    "Setting delayed autounload for %s.",
5300 		    kextIdentifier->getCStringNoCopy());
5301 		theKext->flags.delayAutounload = 1;
5302 	}
5303 
5304 finish:
5305 	if ((kOSReturnSuccess == result) && kextRef) {
5306 		*kextRef = theKext;
5307 		theKext->matchingRefCount++;
5308 		theKext->retain();
5309 	}
5310 
5311 	IORecursiveLockUnlock(sKextLock);
5312 
5313 	return result;
5314 }
5315 
5316 /*********************************************************************
5317 *********************************************************************/
5318 /* static */
5319 OSReturn
5320 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict)
5321 {
5322 	OSReturn  result = kOSReturnError;
5323 
5324 	OSBoolean *delayAutounloadBool     = NULL; // do not release
5325 	OSNumber  *startKextExcludeNum     = NULL; // do not release
5326 	OSNumber  *startMatchingExcludeNum = NULL; // do not release
5327 	OSArray   *personalityNames        = NULL; // do not release
5328 
5329 	/*
5330 	 * Default values for these options:
5331 	 *      regular autounload behavior
5332 	 *      start the kext
5333 	 *      send all personalities to the catalog
5334 	 */
5335 	Boolean            delayAutounload           = false;
5336 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
5337 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone;
5338 
5339 	IORecursiveLockLock(sKextLock);
5340 
5341 	OSKextLog(/* kext */ NULL,
5342 	    kOSKextLogDebugLevel |
5343 	    kOSKextLogIPCFlag,
5344 	    "Received kext KC load request from user space.");
5345 
5346 	/* Regardless of processing, the fact that we have gotten here means some
5347 	 * user-space program is up and talking to us, so we'll switch our kext
5348 	 * registration to reflect that.
5349 	 */
5350 	if (!sUserLoadsActive) {
5351 		OSKextLog(/* kext */ NULL,
5352 		    kOSKextLogProgressLevel |
5353 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5354 		    "Switching to late startup (user-space) kext loading policy.");
5355 		sUserLoadsActive = true;
5356 	}
5357 
5358 	delayAutounloadBool = OSDynamicCast(OSBoolean,
5359 	    _OSKextGetRequestArgument(requestDict,
5360 	    kKextRequestArgumentDelayAutounloadKey));
5361 	startKextExcludeNum = OSDynamicCast(OSNumber,
5362 	    _OSKextGetRequestArgument(requestDict,
5363 	    kKextRequestArgumentStartExcludeKey));
5364 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
5365 	    _OSKextGetRequestArgument(requestDict,
5366 	    kKextRequestArgumentStartMatchingExcludeKey));
5367 	personalityNames = OSDynamicCast(OSArray,
5368 	    _OSKextGetRequestArgument(requestDict,
5369 	    kKextRequestArgumentPersonalityNamesKey));
5370 
5371 	if (delayAutounloadBool) {
5372 		delayAutounload = delayAutounloadBool->getValue();
5373 	}
5374 	if (startKextExcludeNum) {
5375 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
5376 	}
5377 	if (startMatchingExcludeNum) {
5378 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
5379 	}
5380 
5381 	OSKextLog(/* kext */ NULL,
5382 	    kOSKextLogProgressLevel |
5383 	    kOSKextLogIPCFlag,
5384 	    "Received request from user space to load KC kext %s.",
5385 	    theKext->getIdentifierCString());
5386 
5387 	/* this could be in the Auxiliary KC, so record the load request */
5388 	OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier()));
5389 
5390 	/*
5391 	 * Load the kext
5392 	 */
5393 	result = theKext->load(startKextExcludeLevel,
5394 	    startMatchingExcludeLevel, personalityNames);
5395 
5396 	if (result != kOSReturnSuccess) {
5397 		OSKextLog(theKext,
5398 		    kOSKextLogErrorLevel |
5399 		    kOSKextLogLoadFlag,
5400 		    "Failed to load kext %s (error 0x%x).",
5401 		    theKext->getIdentifierCString(), (int)result);
5402 
5403 		OSKext::removeKext(theKext,
5404 		    /* terminateService/removePersonalities */ true);
5405 		goto finish;
5406 	} else {
5407 		OSKextLog(theKext,
5408 		    kOSKextLogProgressLevel |
5409 		    kOSKextLogLoadFlag,
5410 		    "Kext %s Loaded successfully from %s KC",
5411 		    theKext->getIdentifierCString(), theKext->getKCTypeString());
5412 	}
5413 
5414 	if (delayAutounload) {
5415 		OSKextLog(theKext,
5416 		    kOSKextLogProgressLevel |
5417 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5418 		    "Setting delayed autounload for %s.",
5419 		    theKext->getIdentifierCString());
5420 		theKext->flags.delayAutounload = 1;
5421 	}
5422 
5423 finish:
5424 	IORecursiveLockUnlock(sKextLock);
5425 
5426 	return result;
5427 }
5428 
5429 /*********************************************************************
5430 *********************************************************************/
5431 /* static */
5432 OSReturn
5433 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict)
5434 {
5435 	OSReturn  result = kOSReturnError;
5436 	OSDictionary *anInfoDict = NULL; // do not release
5437 
5438 	anInfoDict = OSDynamicCast(OSDictionary,
5439 	    _OSKextGetRequestArgument(requestDict,
5440 	    kKextRequestArgumentCodelessInfoKey));
5441 	if (anInfoDict == NULL) {
5442 		OSKextLog(/* kext */ NULL,
5443 		    kOSKextLogErrorLevel |
5444 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5445 		    "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.",
5446 		    kextIdentifier->getCStringNoCopy());
5447 		return kOSKextReturnInvalidArgument;
5448 	}
5449 
5450 	IORecursiveLockLock(sKextLock);
5451 
5452 	OSKextLog(/* kext */ NULL,
5453 	    kOSKextLogProgressLevel |
5454 	    kOSKextLogIPCFlag,
5455 	    "Received request from user space to load codeless kext %s.",
5456 	    kextIdentifier->getCStringNoCopy());
5457 
5458 	{
5459 		// instantiate a new kext, and don't hold a reference
5460 		// (the kext subsystem will hold one implicitly)
5461 		OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict);
5462 		if (!newKext) {
5463 			OSKextLog(/* kext */ NULL,
5464 			    kOSKextLogErrorLevel |
5465 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5466 			    "Could not instantiate codeless kext.");
5467 			result = kOSKextReturnNotLoadable;
5468 			goto finish;
5469 		}
5470 		if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) {
5471 			OSKextLog(/* kext */ NULL,
5472 			    kOSKextLogErrorLevel |
5473 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5474 			    "Codeless kext identifiers don't match '%s' != '%s'",
5475 			    kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString());
5476 
5477 			OSKext::removeKext(newKext.get(), false);
5478 			result = kOSKextReturnInvalidArgument;
5479 			goto finish;
5480 		}
5481 
5482 		/* Record the request for the codeless kext */
5483 		OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier()));
5484 
5485 		result = kOSReturnSuccess;
5486 		/* Send the kext's personalities to the IOCatalog. This is an explicit load. */
5487 		result = newKext->sendPersonalitiesToCatalog(true, NULL);
5488 	}
5489 
5490 finish:
5491 	IORecursiveLockUnlock(sKextLock);
5492 
5493 	return result;
5494 }
5495 
5496 /*********************************************************************
5497 *********************************************************************/
5498 /* static */
5499 void
5500 OSKext::dropMatchingReferences(
5501 	OSSet * kexts)
5502 {
5503 	IORecursiveLockLock(sKextLock);
5504 	kexts->iterateObjects(^bool (OSObject * obj) {
5505 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
5506 		if (!thisKext) {
5507 		        return false;
5508 		}
5509 		thisKext->matchingRefCount--;
5510 		return false;
5511 	});
5512 	IORecursiveLockUnlock(sKextLock);
5513 }
5514 
5515 /*********************************************************************
5516 *********************************************************************/
5517 /* static */
5518 void
5519 OSKext::recordIdentifierRequest(
5520 	OSString * kextIdentifier)
5521 {
5522 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5523 	bool             fail                 = false;
5524 
5525 	if (!sAllKextLoadIdentifiers || !kextIdentifier) {
5526 		goto finish;
5527 	}
5528 
5529 	kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5530 	if (!kextIdentifierSymbol) {
5531 		// xxx - this is really a basic alloc failure
5532 		fail = true;
5533 		goto finish;
5534 	}
5535 
5536 	IORecursiveLockLock(sKextLock);
5537 	if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5538 		if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
5539 			fail = true;
5540 		} else {
5541 			// xxx - need to find a way to associate this whole func w/the kext
5542 			OSKextLog(/* kext */ NULL,
5543 			    // xxx - check level
5544 			    kOSKextLogStepLevel |
5545 			    kOSKextLogArchiveFlag,
5546 			    "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
5547 			    kextIdentifier->getCStringNoCopy());
5548 		}
5549 	}
5550 	IORecursiveLockUnlock(sKextLock);
5551 
5552 finish:
5553 
5554 	if (fail) {
5555 		OSKextLog(/* kext */ NULL,
5556 		    kOSKextLogErrorLevel |
5557 		    kOSKextLogArchiveFlag,
5558 		    "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
5559 		    kextIdentifier->getCStringNoCopy());
5560 	}
5561 	return;
5562 }
5563 
5564 /*********************************************************************
5565 *********************************************************************/
5566 OSReturn
5567 OSKext::load(
5568 	OSKextExcludeLevel   startOpt,
5569 	OSKextExcludeLevel   startMatchingOpt,
5570 	OSArray            * personalityNames)
5571 {
5572 	OSReturn             result                       = kOSReturnError;
5573 	OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
5574 	OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
5575 	unsigned int         i, count;
5576 	Boolean              alreadyLoaded                = false;
5577 	OSKext             * lastLoadedKext               = NULL;        // do not release
5578 
5579 	if (isInExcludeList()) {
5580 		OSKextLog(this,
5581 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
5582 		    kOSKextLogLoadFlag,
5583 		    "Kext %s is in exclude list, not loadable",
5584 		    getIdentifierCString());
5585 
5586 		result = kOSKextReturnNotLoadable;
5587 		goto finish;
5588 	}
5589 	if (!isLoadable()) {
5590 		OSKextLog(this,
5591 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
5592 		    kOSKextLogLoadFlag,
5593 		    "Kext %s is not loadable",
5594 		    getIdentifierCString());
5595 
5596 		result = kOSKextReturnNotLoadable;
5597 		goto finish;
5598 	}
5599 
5600 	if (isLoaded()) {
5601 		alreadyLoaded = true;
5602 		result = kOSReturnSuccess;
5603 
5604 		OSKextLog(this,
5605 		    kOSKextLogDebugLevel |
5606 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5607 		    "Kext %s is already loaded.",
5608 		    getIdentifierCString());
5609 		goto loaded;
5610 	}
5611 
5612 #if CONFIG_MACF
5613 	/*
5614 	 * On kxld and on embedded, only call into the MAC hook when on a
5615 	 * user thread, for access control over userspace kextloads.
5616 	 *
5617 	 * On non-kxld systems, additionally check the MAC hook for kexts in
5618 	 * the Pageable and Aux KCs, regardless of whether we are on a user
5619 	 * thread or not. This means on Apple silicon devices that the MAC
5620 	 * hook will only be useful to block 3rd party kexts loaded via
5621 	 * matching, and any kexts loaded from userspace kextloads.
5622 	 *
5623 	 * Note that this should _not_ be called on kexts loaded from the
5624 	 * kernel bootstrap thread as the kernel proc's cred struct is not
5625 	 * yet initialized! This won't happen on macOS because all the kexts
5626 	 * in the BootKC are self-contained and their kc_type = KCKindPrimary.
5627 	 */
5628 	if (current_task() != kernel_task
5629 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD
5630 	    || (kc_type != KCKindPrimary && kc_type != KCKindUnknown)
5631 #endif
5632 	    ) {
5633 		int                 macCheckResult      = 0;
5634 		kauth_cred_t        cred                = NULL;
5635 
5636 		cred = kauth_cred_get_with_ref();
5637 		macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
5638 		kauth_cred_unref(&cred);
5639 
5640 		if (macCheckResult != 0) {
5641 			result = kOSReturnError;
5642 			OSKextLog(this,
5643 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5644 			    "Failed to load kext %s (MAC policy error 0x%x).",
5645 			    getIdentifierCString(), macCheckResult);
5646 			goto finish;
5647 		}
5648 	}
5649 #endif /* CONFIG_MACF */
5650 
5651 	if (!sLoadEnabled) {
5652 		OSKextLog(this,
5653 		    kOSKextLogErrorLevel |
5654 		    kOSKextLogLoadFlag,
5655 		    "Kext loading is disabled (attempt to load kext %s).",
5656 		    getIdentifierCString());
5657 		result = kOSKextReturnDisabled;
5658 		goto finish;
5659 	}
5660 
5661 	/* If we've pushed the next available load tag to the invalid value,
5662 	 * we can't load any more kexts.
5663 	 */
5664 	if (sNextLoadTag == kOSKextInvalidLoadTag) {
5665 		OSKextLog(this,
5666 		    kOSKextLogErrorLevel |
5667 		    kOSKextLogLoadFlag,
5668 		    "Can't load kext %s - no more load tags to assign.",
5669 		    getIdentifierCString());
5670 		result = kOSKextReturnNoResources;
5671 		goto finish;
5672 	}
5673 
5674 	/* This is a bit of a hack, because we shouldn't be handling
5675 	 * personalities within the load function.
5676 	 */
5677 	if (!declaresExecutable()) {
5678 		/* There is a special case where a non-executable kext can be loaded: the
5679 		 * AppleKextExcludeList.  Detect that special kext by bundle identifier and
5680 		 * load its metadata into the global data structures, if appropriate
5681 		 */
5682 		if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
5683 			boolean_t updated = updateExcludeList(infoDict.get());
5684 			if (updated) {
5685 				OSKextLog(this,
5686 				    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
5687 				    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
5688 			}
5689 		}
5690 
5691 		if (isDriverKit()) {
5692 			if (loadTag == 0) {
5693 				sLoadedDriverKitKexts->setObject(this);
5694 				loadTag = sNextLoadTag++;
5695 			}
5696 		}
5697 		result = kOSReturnSuccess;
5698 		goto loaded;
5699 	}
5700 
5701 	/* Are we in safe boot?
5702 	 */
5703 	if (sSafeBoot && !isLoadableInSafeBoot()) {
5704 		OSKextLog(this,
5705 		    kOSKextLogErrorLevel |
5706 		    kOSKextLogLoadFlag,
5707 		    "Can't load kext %s - not loadable during safe boot.",
5708 		    getIdentifierCString());
5709 		result = kOSKextReturnBootLevel;
5710 		goto finish;
5711 	}
5712 
5713 	OSKextLog(this,
5714 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5715 	    "Loading kext %s.",
5716 	    getIdentifierCString());
5717 
5718 #if !VM_MAPPED_KEXTS
5719 	if (isPrelinked() == false) {
5720 		OSKextLog(this,
5721 		    kOSKextLogErrorLevel |
5722 		    kOSKextLogLoadFlag,
5723 		    "Can't load kext %s - not in a kext collection.",
5724 		    getIdentifierCString());
5725 		result = kOSKextReturnDisabled;
5726 		goto finish;
5727 	}
5728 #endif /* defined(__x86_64__) */
5729 
5730 #if CONFIG_KXLD
5731 	if (!sKxldContext) {
5732 		kern_return_t kxldResult;
5733 		kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
5734 		    &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
5735 		    /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
5736 		if (kxldResult) {
5737 			OSKextLog(this,
5738 			    kOSKextLogErrorLevel |
5739 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5740 			    "Can't load kext %s - failed to create link context.",
5741 			    getIdentifierCString());
5742 			result = kOSKextReturnNoMemory;
5743 			goto finish;
5744 		}
5745 	}
5746 #endif // CONFIG_KXLD
5747 
5748 	/* We only need to resolve dependencies once for the whole graph, but
5749 	 * resolveDependencies will just return if there's no work to do, so it's
5750 	 * safe to call it more than once.
5751 	 */
5752 	if (!resolveDependencies()) {
5753 		// xxx - check resolveDependencies() for log msg
5754 		OSKextLog(this,
5755 		    kOSKextLogErrorLevel |
5756 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5757 		    "Can't load kext %s - failed to resolve library dependencies.",
5758 		    getIdentifierCString());
5759 		result = kOSKextReturnDependencies;
5760 		goto finish;
5761 	}
5762 
5763 	/* If we are excluding just the kext being loaded now (and not its
5764 	 * dependencies), drop the exclusion level to none so dependencies
5765 	 * start and/or add their personalities.
5766 	 */
5767 	if (dependenciesStartOpt == kOSKextExcludeKext) {
5768 		dependenciesStartOpt = kOSKextExcludeNone;
5769 	}
5770 
5771 	if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
5772 		dependenciesStartMatchingOpt = kOSKextExcludeNone;
5773 	}
5774 
5775 	/* Load the dependencies, recursively.
5776 	 */
5777 	count = getNumDependencies();
5778 	for (i = 0; i < count; i++) {
5779 		OSKext * dependency = OSDynamicCast(OSKext,
5780 		    dependencies->getObject(i));
5781 		if (dependency == NULL) {
5782 			OSKextLog(this,
5783 			    kOSKextLogErrorLevel |
5784 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5785 			    "Internal error loading kext %s; dependency disappeared.",
5786 			    getIdentifierCString());
5787 			result = kOSKextReturnInternalError;
5788 			goto finish;
5789 		}
5790 
5791 		/* Dependencies must be started accorting to the opt,
5792 		 * but not given the personality names of the main kext.
5793 		 */
5794 		result = dependency->load(dependenciesStartOpt,
5795 		    dependenciesStartMatchingOpt,
5796 		    /* personalityNames */ NULL);
5797 		if (result != KERN_SUCCESS) {
5798 			OSKextLog(this,
5799 			    kOSKextLogErrorLevel |
5800 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5801 			    "Dependency %s of kext %s failed to load.",
5802 			    dependency->getIdentifierCString(),
5803 			    getIdentifierCString());
5804 
5805 			OSKext::removeKext(dependency,
5806 			    /* terminateService/removePersonalities */ true);
5807 			result = kOSKextReturnDependencyLoadError;
5808 
5809 			goto finish;
5810 		}
5811 	}
5812 
5813 	result = loadExecutable();
5814 	if (result != KERN_SUCCESS) {
5815 		goto finish;
5816 	}
5817 
5818 	pendingPgoHead.next = &pendingPgoHead;
5819 	pendingPgoHead.prev = &pendingPgoHead;
5820 
5821 	// The kernel PRNG is not initialized when the first kext is
5822 	// loaded, so use early random
5823 	uuid_generate_early_random(instance_uuid);
5824 	account = IOMallocType(OSKextAccount);
5825 
5826 	account->loadTag = kmod_info->id;
5827 	account->site.refcount = 0;
5828 	account->site.flags = VM_TAG_KMOD;
5829 
5830 #if DEVELOPMENT || DEBUG
5831 	/* Setup the task reference group. */
5832 	(void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name),
5833 	    "task_%s", getIdentifierCString());
5834 	account->task_refgrp.grp_name = account->task_refgrp_name;
5835 	account->task_refgrp.grp_parent = &task_external_refgrp;
5836 	os_ref_log_init(&account->task_refgrp);
5837 #endif /* DEVELOPMENT || DEBUG */
5838 
5839 	account->kext = this;
5840 	if (gIOSurfaceIdentifier == bundleID) {
5841 		vm_tag_alloc(&account->site);
5842 		gIOSurfaceTag = account->site.tag;
5843 	}
5844 
5845 	flags.loaded = true;
5846 
5847 	/* Add the kext to the list of loaded kexts and update the kmod_info
5848 	 * struct to point to that of the last loaded kext (which is the way
5849 	 * it's always been done, though I'd rather do them in order now).
5850 	 */
5851 	lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
5852 	sLoadedKexts->setObject(this);
5853 
5854 	/* Keep the kernel itself out of the kmod list.
5855 	 */
5856 	if (lastLoadedKext->isKernel()) {
5857 		lastLoadedKext = NULL;
5858 	}
5859 
5860 	if (lastLoadedKext) {
5861 		kmod_info->next = lastLoadedKext->kmod_info;
5862 	}
5863 
5864 	notifyKextLoadObservers(this, kmod_info);
5865 
5866 	/* Make the global kmod list point at the just-loaded kext. Note that the
5867 	 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
5868 	 * although we do report it in kextstat these days by using the newer
5869 	 * OSArray of loaded kexts, which does contain it.
5870 	 *
5871 	 * (The OSKext object representing the kernel doesn't even have a kmod_info
5872 	 * struct, though I suppose we could stick a pointer to it from the
5873 	 * static struct in OSRuntime.cpp.)
5874 	 */
5875 	kmod = kmod_info;
5876 
5877 	/* Save the list of loaded kexts in case we panic.
5878 	 */
5879 	OSKext::saveLoadedKextPanicList();
5880 
5881 	if (isExecutable()) {
5882 		OSKext::updateLoadedKextSummaries();
5883 		savePanicString(/* isLoading */ true);
5884 
5885 #if CONFIG_DTRACE
5886 		registerWithDTrace();
5887 #else
5888 		jettisonLinkeditSegment();
5889 #endif /* CONFIG_DTRACE */
5890 
5891 #if !VM_MAPPED_KEXTS
5892 		/* If there is a page (or more) worth of padding after the end
5893 		 * of the last data section but before the end of the data segment
5894 		 * then free it in the same manner the LinkeditSegment is freed
5895 		 */
5896 		jettisonDATASegmentPadding();
5897 #endif
5898 	}
5899 
5900 loaded:
5901 	if (isExecutable() && !flags.started) {
5902 		if (startOpt == kOSKextExcludeNone) {
5903 			result = start();
5904 			if (result != kOSReturnSuccess) {
5905 				OSKextLog(this,
5906 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5907 				    "Kext %s start failed (result 0x%x).",
5908 				    getIdentifierCString(), result);
5909 				result = kOSKextReturnStartStopError;
5910 			}
5911 		}
5912 	}
5913 
5914 	/* If not excluding matching, send the personalities to the kernel.
5915 	 * This never affects the result of the load operation.
5916 	 * This is a bit of a hack, because we shouldn't be handling
5917 	 * personalities within the load function.
5918 	 */
5919 	if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
5920 		result = sendPersonalitiesToCatalog(true, personalityNames);
5921 	}
5922 
5923 finish:
5924 
5925 	if (result != kOSReturnSuccess) {
5926 		OSKextLog(this,
5927 		    kOSKextLogErrorLevel |
5928 		    kOSKextLogLoadFlag,
5929 		    "Kext %s failed to load (0x%x).",
5930 		    getIdentifierCString(), (int)result);
5931 	} else if (!alreadyLoaded) {
5932 		OSKextLog(this,
5933 		    kOSKextLogProgressLevel |
5934 		    kOSKextLogLoadFlag,
5935 		    "Kext %s loaded.",
5936 		    getIdentifierCString());
5937 
5938 		queueKextNotification(kKextRequestPredicateLoadNotification,
5939 		    OSDynamicCast(OSString, bundleID.get()));
5940 	}
5941 	return result;
5942 }
5943 
5944 #if CONFIG_KXLD
5945 /*********************************************************************
5946 *
5947 *********************************************************************/
5948 static char *
5949 strdup(const char * string)
5950 {
5951 	char * result = NULL;
5952 	size_t size;
5953 
5954 	if (!string) {
5955 		goto finish;
5956 	}
5957 
5958 	size = 1 + strlen(string);
5959 	result = (char *)kheap_alloc_tag(KHEAP_DATA_BUFFERS, size,
5960 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
5961 	if (!result) {
5962 		goto finish;
5963 	}
5964 
5965 	memcpy(result, string, size);
5966 
5967 finish:
5968 	return result;
5969 }
5970 #endif // CONFIG_KXLD
5971 
5972 /*********************************************************************
5973 *
5974 *********************************************************************/
5975 
5976 kernel_section_t *
5977 OSKext::lookupSection(const char *segname, const char *secname)
5978 {
5979 	kernel_section_t         * found_section = NULL;
5980 	kernel_mach_header_t     * mh            = NULL;
5981 	kernel_segment_command_t * seg           = NULL;
5982 	kernel_section_t         * sec           = NULL;
5983 
5984 	if (!linkedExecutable) {
5985 		return NULL;
5986 	}
5987 
5988 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5989 
5990 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5991 		if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
5992 			continue;
5993 		}
5994 
5995 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5996 			if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
5997 				found_section = sec;
5998 				goto out;
5999 			}
6000 		}
6001 	}
6002 
6003 out:
6004 	return found_section;
6005 }
6006 
6007 /*********************************************************************
6008 *
6009 *********************************************************************/
6010 
6011 OSReturn
6012 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides)
6013 {
6014 	OSReturn                       result           = kOSKextReturnBadData;
6015 	kernel_mach_header_t         * mh               = NULL;
6016 	kernel_segment_command_t     * seg              = NULL;
6017 	kernel_segment_command_t     * linkeditSeg      = NULL;
6018 	kernel_section_t             * sec              = NULL;
6019 	char                         * linkeditBase     = NULL;
6020 	bool                           haveLinkeditBase = false;
6021 	char                         * relocBase        = NULL;
6022 	bool                           haveRelocBase    = false;
6023 	struct dysymtab_command      * dysymtab         = NULL;
6024 	struct linkedit_data_command * segmentSplitInfo = NULL;
6025 	struct symtab_command        * symtab           = NULL;
6026 	kernel_nlist_t               * sym              = NULL;
6027 	struct relocation_info       * reloc            = NULL;
6028 	uint32_t                       i                = 0;
6029 	int                            reloc_size;
6030 	vm_offset_t                    new_kextsize;
6031 
6032 	if (linkedExecutable == NULL || flags.builtin) {
6033 		result = kOSReturnSuccess;
6034 		goto finish;
6035 	}
6036 
6037 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6038 	if (kernel_mach_header_is_in_fileset(mh)) {
6039 		// kexts in filesets are slid as part of collection sliding
6040 		result = kOSReturnSuccess;
6041 		goto finish;
6042 	}
6043 
6044 	segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
6045 
6046 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6047 		if (!seg->vmaddr) {
6048 			continue;
6049 		}
6050 
6051 		seg->vmaddr = ml_static_slide(seg->vmaddr);
6052 
6053 #if KASLR_KEXT_DEBUG
6054 		IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
6055 		    seg->segname,
6056 		    (unsigned long)ml_static_unslide(seg->vmaddr),
6057 		    (unsigned long)seg->vmaddr);
6058 #endif
6059 
6060 		if (!haveRelocBase) {
6061 			relocBase = (char *) seg->vmaddr;
6062 			haveRelocBase = true;
6063 		}
6064 		if (!strcmp(seg->segname, "__LINKEDIT")) {
6065 			linkeditBase = (char *) seg->vmaddr - seg->fileoff;
6066 			haveLinkeditBase = true;
6067 			linkeditSeg = seg;
6068 		}
6069 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6070 			sec->addr = ml_static_slide(sec->addr);
6071 
6072 #if KASLR_KEXT_DEBUG
6073 			IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
6074 			    sec->sectname,
6075 			    (unsigned long)ml_static_unslide(sec->addr),
6076 			    (unsigned long)sec->addr);
6077 #endif
6078 		}
6079 	}
6080 
6081 	dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
6082 
6083 	symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
6084 
6085 	if (symtab != NULL && doCoalescedSlides == false) {
6086 		/* Some pseudo-kexts have symbol tables without segments.
6087 		 * Ignore them. */
6088 		if (symtab->nsyms > 0 && haveLinkeditBase) {
6089 			sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
6090 			for (i = 0; i < symtab->nsyms; i++) {
6091 				if (sym[i].n_type & N_STAB) {
6092 					continue;
6093 				}
6094 				sym[i].n_value = ml_static_slide(sym[i].n_value);
6095 
6096 #if KASLR_KEXT_DEBUG
6097 #define MAX_SYMS_TO_LOG 5
6098 				if (i < MAX_SYMS_TO_LOG) {
6099 					IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
6100 					    (unsigned long)ml_static_unslide(sym[i].n_value),
6101 					    (unsigned long)sym[i].n_value);
6102 				}
6103 #endif
6104 			}
6105 		}
6106 	}
6107 
6108 	if (dysymtab != NULL && doCoalescedSlides == false) {
6109 		if (dysymtab->nextrel > 0) {
6110 			OSKextLog(this,
6111 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6112 			    kOSKextLogLinkFlag,
6113 			    "Sliding kext %s: External relocations found.",
6114 			    getIdentifierCString());
6115 			goto finish;
6116 		}
6117 
6118 		if (dysymtab->nlocrel > 0) {
6119 			if (!haveLinkeditBase) {
6120 				OSKextLog(this,
6121 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6122 				    kOSKextLogLinkFlag,
6123 				    "Sliding kext %s: No linkedit segment.",
6124 				    getIdentifierCString());
6125 				goto finish;
6126 			}
6127 
6128 			if (!haveRelocBase) {
6129 				OSKextLog(this,
6130 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6131 				    kOSKextLogLinkFlag,
6132 #if __x86_64__
6133 				    "Sliding kext %s: No writable segments.",
6134 #else
6135 				    "Sliding kext %s: No segments.",
6136 #endif
6137 				    getIdentifierCString());
6138 				goto finish;
6139 			}
6140 
6141 			reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
6142 			reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
6143 
6144 			for (i = 0; i < dysymtab->nlocrel; i++) {
6145 				if (reloc[i].r_extern != 0
6146 				    || reloc[i].r_type != 0
6147 				    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
6148 				    ) {
6149 					OSKextLog(this,
6150 					    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6151 					    kOSKextLogLinkFlag,
6152 					    "Sliding kext %s: Unexpected relocation found.",
6153 					    getIdentifierCString());
6154 					goto finish;
6155 				}
6156 				if (reloc[i].r_pcrel != 0) {
6157 					continue;
6158 				}
6159 				uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
6160 				*relocAddr = ml_static_slide(*relocAddr);
6161 
6162 #if KASLR_KEXT_DEBUG
6163 #define MAX_DYSYMS_TO_LOG 5
6164 				if (i < MAX_DYSYMS_TO_LOG) {
6165 					IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
6166 					    (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
6167 					    (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
6168 				}
6169 #endif
6170 			}
6171 
6172 			/* We should free these relocations, not just delete the reference to them.
6173 			 * <rdar://problem/10535549> Free relocations from PIE kexts.
6174 			 *
6175 			 * For now, we do not free LINKEDIT for kexts with split segments.
6176 			 */
6177 			new_kextsize = round_page(kmod_info->size - reloc_size);
6178 			if (new_kextsize > UINT_MAX) {
6179 				OSKextLog(this,
6180 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6181 				    kOSKextLogLinkFlag,
6182 				    "Kext %s: new kext size is too large.",
6183 				    getIdentifierCString());
6184 				goto finish;
6185 			}
6186 			if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
6187 				vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
6188 				vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
6189 				vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
6190 				size_t          bytes_remaining = endofkext - endofrelocInfo;
6191 				OSSharedPtr<OSData>        new_osdata;
6192 
6193 				/* fix up symbol offsets if they are after the dsymtab local relocs */
6194 				if (symtab) {
6195 					if (dysymtab->locreloff < symtab->symoff) {
6196 						symtab->symoff -= reloc_size;
6197 					}
6198 					if (dysymtab->locreloff < symtab->stroff) {
6199 						symtab->stroff -= reloc_size;
6200 					}
6201 				}
6202 				if (dysymtab->locreloff < dysymtab->extreloff) {
6203 					dysymtab->extreloff -= reloc_size;
6204 				}
6205 
6206 				/* move data behind reloc info down to new offset */
6207 				if (endofrelocInfo < endofkext) {
6208 					memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
6209 				}
6210 
6211 				/* Create a new OSData for the smaller kext object and reflect
6212 				 * new linkedit segment size.
6213 				 */
6214 				linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
6215 				linkeditSeg->filesize = linkeditSeg->vmsize;
6216 
6217 				new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize);
6218 				if (new_osdata) {
6219 					/* Fix up kmod info and linkedExecutable.
6220 					 */
6221 					kmod_info->size = new_kextsize;
6222 #if VM_MAPPED_KEXTS
6223 					new_osdata->setDeallocFunction(osdata_kext_free);
6224 #else
6225 					new_osdata->setDeallocFunction(osdata_phys_free);
6226 #endif
6227 					linkedExecutable->setDeallocFunction(NULL);
6228 					linkedExecutable = os::move(new_osdata);
6229 
6230 #if VM_MAPPED_KEXTS
6231 					kext_free(new_endofkext, (endofkext - new_endofkext));
6232 #else
6233 					ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
6234 #endif
6235 				}
6236 			}
6237 			dysymtab->nlocrel = 0;
6238 			dysymtab->locreloff = 0;
6239 		}
6240 	}
6241 
6242 	result = kOSReturnSuccess;
6243 finish:
6244 	return result;
6245 }
6246 
6247 /*********************************************************************
6248 * called only by load()
6249 *********************************************************************/
6250 OSReturn
6251 OSKext::loadExecutable()
6252 {
6253 	OSReturn              result             = kOSReturnError;
6254 	OSSharedPtr<OSArray>  linkDependencies;
6255 	uint32_t              num_kmod_refs      = 0;
6256 	OSData              * theExecutable      = NULL;        // do not release
6257 	OSString            * versString         = NULL;        // do not release
6258 	const char          * versCString        = NULL;        // do not free
6259 	const char          * string             = NULL;        // do not free
6260 
6261 #if CONFIG_KXLD
6262 	unsigned int          i;
6263 	uint32_t              numDirectDependencies   = 0;
6264 	kern_return_t         kxldResult;
6265 	KXLDDependency     *  kxlddeps           = NULL;        // must kfree
6266 	uint32_t              num_kxlddeps       = 0;
6267 	struct mach_header ** kxldHeaderPtr      = NULL;        // do not free
6268 	struct mach_header  * kxld_header        = NULL;        // xxx - need to free here?
6269 #endif // CONFIG_KXLD
6270 
6271 	/* We need the version string for a variety of bits below.
6272 	 */
6273 	versString = OSDynamicCast(OSString,
6274 	    getPropertyForHostArch(kCFBundleVersionKey));
6275 	if (!versString) {
6276 		goto finish;
6277 	}
6278 	versCString = versString->getCStringNoCopy();
6279 
6280 	if (isKernelComponent()) {
6281 		if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
6282 			if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
6283 				OSKextLog(this,
6284 				    kOSKextLogErrorLevel |
6285 				    kOSKextLogLoadFlag,
6286 				    "Kernel component %s has incorrect version %s; "
6287 				    "expected %s.",
6288 				    getIdentifierCString(),
6289 				    versCString, KERNEL6_VERSION);
6290 				result = kOSKextReturnInternalError;
6291 				goto finish;
6292 			} else if (strcmp(versCString, osrelease)) {
6293 				OSKextLog(this,
6294 				    kOSKextLogErrorLevel |
6295 				    kOSKextLogLoadFlag,
6296 				    "Kernel component %s has incorrect version %s; "
6297 				    "expected %s.",
6298 				    getIdentifierCString(),
6299 				    versCString, osrelease);
6300 				result = kOSKextReturnInternalError;
6301 				goto finish;
6302 			}
6303 		}
6304 	}
6305 
6306 #if defined(__x86_64__) || defined(__i386__)
6307 	if (flags.resetSegmentsFromVnode) {
6308 		/* Fixup the chains and slide the mach headers */
6309 		kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address;
6310 
6311 		if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) {
6312 			result = kOSKextReturnValidation;
6313 			goto finish;
6314 		}
6315 	}
6316 #endif //(__x86_64__) || defined(__i386__)
6317 
6318 	if (isPrelinked()) {
6319 		goto register_kmod;
6320 	}
6321 
6322 	/* <rdar://problem/21444003> all callers must be entitled */
6323 	if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) {
6324 		OSKextLog(this,
6325 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6326 		    "Not entitled to link kext '%s'",
6327 		    getIdentifierCString());
6328 		result = kOSKextReturnNotPrivileged;
6329 		goto finish;
6330 	}
6331 
6332 	theExecutable = getExecutable();
6333 	if (!theExecutable) {
6334 		if (declaresExecutable()) {
6335 			OSKextLog(this,
6336 			    kOSKextLogErrorLevel |
6337 			    kOSKextLogLoadFlag,
6338 			    "Can't load kext %s - executable is missing.",
6339 			    getIdentifierCString());
6340 			result = kOSKextReturnValidation;
6341 			goto finish;
6342 		}
6343 		goto register_kmod;
6344 	}
6345 
6346 	if (isInterface()) {
6347 		OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable);
6348 		if (executableCopy) {
6349 			setLinkedExecutable(executableCopy.get());
6350 		}
6351 		goto register_kmod;
6352 	}
6353 
6354 #if CONFIG_KXLD
6355 	numDirectDependencies = getNumDependencies();
6356 
6357 	if (flags.hasBleedthrough) {
6358 		linkDependencies = dependencies;
6359 	} else {
6360 		linkDependencies = OSArray::withArray(dependencies.get());
6361 		if (!linkDependencies) {
6362 			OSKextLog(this,
6363 			    kOSKextLogErrorLevel |
6364 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6365 			    "Can't allocate link dependencies to load kext %s.",
6366 			    getIdentifierCString());
6367 			goto finish;
6368 		}
6369 
6370 		for (i = 0; i < numDirectDependencies; ++i) {
6371 			OSKext * dependencyKext = OSDynamicCast(OSKext,
6372 			    dependencies->getObject(i));
6373 			dependencyKext->addBleedthroughDependencies(linkDependencies.get());
6374 		}
6375 	}
6376 
6377 	num_kxlddeps = linkDependencies->getCount();
6378 	if (!num_kxlddeps) {
6379 		OSKextLog(this,
6380 		    kOSKextLogErrorLevel |
6381 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6382 		    "Can't load kext %s - it has no library dependencies.",
6383 		    getIdentifierCString());
6384 		goto finish;
6385 	}
6386 
6387 	kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
6388 	if (!kxlddeps) {
6389 		OSKextLog(this,
6390 		    kOSKextLogErrorLevel |
6391 		    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6392 		    "Can't allocate link context to load kext %s.",
6393 		    getIdentifierCString());
6394 		goto finish;
6395 	}
6396 	bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
6397 
6398 	for (i = 0; i < num_kxlddeps; ++i) {
6399 		OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
6400 
6401 		if (dependency->isInterface()) {
6402 			OSKext *interfaceTargetKext = NULL;        //do not release
6403 			OSData * interfaceTarget = NULL;        //do not release
6404 
6405 			if (dependency->isKernelComponent()) {
6406 				interfaceTargetKext = sKernelKext;
6407 				interfaceTarget = sKernelKext->linkedExecutable.get();
6408 			} else {
6409 				interfaceTargetKext = OSDynamicCast(OSKext,
6410 				    dependency->dependencies->getObject(0));
6411 
6412 				interfaceTarget = interfaceTargetKext->linkedExecutable.get();
6413 			}
6414 
6415 			if (!interfaceTarget) {
6416 				// panic?
6417 				goto finish;
6418 			}
6419 
6420 			/* The names set here aren't actually logged yet <rdar://problem/7941514>,
6421 			 * it will be useful to have them in the debugger.
6422 			 * strdup() failing isn't critical right here so we don't check that.
6423 			 */
6424 			kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
6425 			kxlddeps[i].kext_size = interfaceTarget->getLength();
6426 			kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
6427 
6428 			if (dependency->linkedExecutable != NULL) {
6429 				kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
6430 				kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
6431 			} else {
6432 				kxlddeps[i].interface = (u_char *) NULL;
6433 				kxlddeps[i].interface_size = 0;
6434 			}
6435 			kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
6436 		} else {
6437 			kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
6438 			kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
6439 			kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
6440 		}
6441 
6442 		kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
6443 	}
6444 
6445 	kxldHeaderPtr = &kxld_header;
6446 
6447 #if DEBUG
6448 	OSKextLog(this,
6449 	    kOSKextLogExplicitLevel |
6450 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6451 	    "Kext %s - calling kxld_link_file:\n"
6452 	    "    kxld_context: %p\n"
6453 	    "    executable: %p    executable_length: %d\n"
6454 	    "    user_data: %p\n"
6455 	    "    kxld_dependencies: %p    num_dependencies: %d\n"
6456 	    "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
6457 	    getIdentifierCString(), sKxldContext,
6458 	    theExecutable->getBytesNoCopy(), theExecutable->getLength(),
6459 	    this, kxlddeps, num_kxlddeps,
6460 	    kxldHeaderPtr, &kmod_info);
6461 #endif
6462 
6463 	/* After this call, the linkedExecutable instance variable
6464 	 * should exist.
6465 	 */
6466 	kxldResult = kxld_link_file(sKxldContext,
6467 	    (u_char *)theExecutable->getBytesNoCopy(),
6468 	    theExecutable->getLength(),
6469 	    getIdentifierCString(), this, kxlddeps, num_kxlddeps,
6470 	    (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
6471 
6472 	if (kxldResult != KERN_SUCCESS) {
6473 		// xxx - add kxldResult here?
6474 		OSKextLog(this,
6475 		    kOSKextLogErrorLevel |
6476 		    kOSKextLogLoadFlag,
6477 		    "Can't load kext %s - link failed.",
6478 		    getIdentifierCString());
6479 		result = kOSKextReturnLinkError;
6480 		goto finish;
6481 	}
6482 
6483 	/* We've written data & instructions into kernel memory, so flush the data
6484 	 * cache and invalidate the instruction cache.
6485 	 * I/D caches are coherent on x86
6486 	 */
6487 #if !defined(__i386__) && !defined(__x86_64__)
6488 	flush_dcache(kmod_info->address, kmod_info->size, false);
6489 	invalidate_icache(kmod_info->address, kmod_info->size, false);
6490 #endif
6491 
6492 #else // !CONFIG_KXLD
6493 	OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6494 	    "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString());
6495 	result = kOSKextReturnLinkError;
6496 	goto finish;
6497 #endif // CONFIG_KXLD
6498 
6499 register_kmod:
6500 
6501 	if (isInterface()) {
6502 		/* Whip up a fake kmod_info entry for the interface kext.
6503 		 */
6504 		kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
6505 		if (!kmod_info) {
6506 			result = KERN_MEMORY_ERROR;
6507 			goto finish;
6508 		}
6509 
6510 		/* A pseudokext has almost nothing in its kmod_info struct.
6511 		 */
6512 		kmod_info->info_version = KMOD_INFO_VERSION;
6513 
6514 		/* An interface kext doesn't have a linkedExecutable, so save a
6515 		 * copy of the UUID out of the original executable via copyUUID()
6516 		 * while we still have the original executable.
6517 		 */
6518 		interfaceUUID = copyUUID();
6519 	}
6520 
6521 	kmod_info->id = loadTag = sNextLoadTag++;
6522 	kmod_info->reference_count = 0;         // KMOD_DECL... sets it to -1 (invalid).
6523 
6524 	/* Stamp the bundle ID and version from the OSKext over anything
6525 	 * resident inside the kmod_info.
6526 	 */
6527 	string = getIdentifierCString();
6528 	strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
6529 
6530 	string = versCString;
6531 	strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
6532 
6533 	/* Add the dependencies' kmod_info structs as kmod_references.
6534 	 */
6535 	num_kmod_refs = getNumDependencies();
6536 	if (num_kmod_refs) {
6537 		kmod_info->reference_list = kalloc_type_tag(kmod_reference_t,
6538 		    num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT);
6539 		if (!kmod_info->reference_list) {
6540 			result = KERN_MEMORY_ERROR;
6541 			goto finish;
6542 		}
6543 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
6544 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
6545 			OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
6546 			ref->info = refKext->kmod_info;
6547 			ref->info->reference_count++;
6548 
6549 			if (refIndex + 1 < num_kmod_refs) {
6550 				ref->next = kmod_info->reference_list + refIndex + 1;
6551 			}
6552 		}
6553 	}
6554 
6555 	if (kmod_info->hdr_size > UINT32_MAX) {
6556 		OSKextLog(this,
6557 		    kOSKextLogErrorLevel |
6558 		    kOSKextLogLoadFlag,
6559 #if __LP64__
6560 		    "Kext %s header size is too large (%lu > UINT32_MAX).",
6561 #else
6562 		    "Kext %s header size is too large (%u > UINT32_MAX).",
6563 #endif
6564 		    kmod_info->name,
6565 		    kmod_info->hdr_size);
6566 		result = KERN_FAILURE;
6567 		goto finish;
6568 	}
6569 
6570 	if (kmod_info->size > UINT32_MAX) {
6571 		OSKextLog(this,
6572 		    kOSKextLogErrorLevel |
6573 		    kOSKextLogLoadFlag,
6574 #if __LP64__
6575 		    "Kext %s size is too large (%lu > UINT32_MAX).",
6576 #else
6577 		    "Kext %s size is too large (%u > UINT32_MAX).",
6578 #endif
6579 		    kmod_info->name,
6580 		    kmod_info->size);
6581 		result = KERN_FAILURE;
6582 		goto finish;
6583 	}
6584 
6585 	if (!isInterface() && linkedExecutable) {
6586 		OSKextLog(this,
6587 		    kOSKextLogProgressLevel |
6588 		    kOSKextLogLoadFlag,
6589 		    "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
6590 		    kmod_info->name,
6591 		    (unsigned)kmod_info->size / PAGE_SIZE,
6592 		    (unsigned long)ml_static_unslide(kmod_info->address),
6593 		    (unsigned)kmod_info->id);
6594 	}
6595 
6596 	/* VM protections and wiring for the Aux KC are done at collection loading time */
6597 	if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) {
6598 		/* if prelinked and primary KC, VM protections are already set */
6599 		result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true);
6600 		if (result != KERN_SUCCESS) {
6601 			goto finish;
6602 		}
6603 	}
6604 
6605 #if KASAN
6606 	if (linkedExecutable) {
6607 		kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
6608 		    linkedExecutable->getLength(), getIdentifierCString());
6609 	}
6610 #else
6611 	if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
6612 		OSKextLog(this,
6613 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6614 		    "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
6615 		    getIdentifierCString()
6616 		    );
6617 		result = KERN_FAILURE;
6618 		goto finish;
6619 	}
6620 #endif
6621 
6622 	result = kOSReturnSuccess;
6623 
6624 finish:
6625 
6626 #if CONFIG_KXLD
6627 	/* Clear up locally allocated dependency info.
6628 	 */
6629 	for (i = 0; i < num_kxlddeps; ++i) {
6630 		size_t size;
6631 
6632 		if (kxlddeps[i].kext_name) {
6633 			size = 1 + strlen(kxlddeps[i].kext_name);
6634 			kheap_free(KHEAP_DATA_BUFFERS, kxlddeps[i].kext_name, size);
6635 		}
6636 		if (kxlddeps[i].interface_name) {
6637 			size = 1 + strlen(kxlddeps[i].interface_name);
6638 			kheap_free(KHEAP_DATA_BUFFERS, kxlddeps[i].interface_name, size);
6639 		}
6640 	}
6641 	if (kxlddeps) {
6642 		kfree_type(KXLDDependency, num_kxlddeps, kxlddeps);
6643 	}
6644 #endif // CONFIG_KXLD
6645 
6646 	/* We no longer need the unrelocated executable (which the linker
6647 	 * has altered anyhow).
6648 	 */
6649 	setExecutable(NULL);
6650 
6651 	if (result != kOSReturnSuccess) {
6652 		OSKextLog(this,
6653 		    kOSKextLogErrorLevel |
6654 		    kOSKextLogLoadFlag,
6655 		    "Failed to load executable for kext %s.",
6656 		    getIdentifierCString());
6657 
6658 		if (kmod_info && kmod_info->reference_list) {
6659 			kfree_type(kmod_reference_t, num_kmod_refs,
6660 			    kmod_info->reference_list);
6661 		}
6662 		if (isInterface()) {
6663 			kfree_type(kmod_info_t, kmod_info);
6664 			kmod_info = NULL;
6665 		}
6666 		if (kc_type == KCKindUnknown) {
6667 			kmod_info = NULL;
6668 			if (linkedExecutable) {
6669 				linkedExecutable.reset();
6670 			}
6671 		}
6672 	}
6673 
6674 	return result;
6675 }
6676 
6677 /* static */
6678 void
6679 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh)
6680 {
6681 	kernel_segment_command_t *linkeditseg = NULL;
6682 
6683 	linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT);
6684 	if (linkeditseg == NULL) {
6685 		panic("FileSet booted with no Linkedit segment");
6686 	}
6687 
6688 #if VM_MAPPED_KEXTS
6689 	/* BootKC on x86_64 is not vm mapped */
6690 	ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize);
6691 
6692 	OSKextLog(/* kext */ NULL,
6693 	    kOSKextLogProgressLevel |
6694 	    kOSKextLogGeneralFlag,
6695 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
6696 	    linkeditseg->vmaddr, linkeditseg->vmsize);
6697 #else
6698 	/* BootKC on arm64 is not vm mapped, but is slid */
6699 	vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase));
6700 
6701 	ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize);
6702 
6703 	OSKextLog(/* kext */ NULL,
6704 	    kOSKextLogProgressLevel |
6705 	    kOSKextLogGeneralFlag,
6706 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
6707 	    (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize);
6708 #endif /* VM_MAPPED_KEXTS */
6709 }
6710 
6711 /*********************************************************************
6712 * The linkedit segment is used by the kext linker for dependency
6713 * resolution, and by dtrace for probe initialization. We can free it
6714 * for non-library kexts, since no kexts depend on non-library kexts
6715 * by definition, once dtrace has been initialized.
6716 *********************************************************************/
6717 void
6718 OSKext::jettisonLinkeditSegment(void)
6719 {
6720 	kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
6721 	kernel_segment_command_t * linkedit = NULL;
6722 	vm_offset_t                start;
6723 	vm_size_t                  linkeditsize, kextsize;
6724 	OSSharedPtr<OSData>        data;
6725 
6726 	if (isInFileset()) {
6727 		return;
6728 	}
6729 
6730 #if NO_KEXTD
6731 	/* We can free symbol tables for all embedded kexts because we don't
6732 	 * support runtime kext linking.
6733 	 */
6734 	if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
6735 #else
6736 	if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
6737 #endif
6738 		goto finish;
6739 	}
6740 
6741 	/* Find the linkedit segment.  If it's not the last segment, then freeing
6742 	 * it will fragment the kext into multiple VM regions, which OSKext is not
6743 	 * designed to handle, so we'll have to skip it.
6744 	 */
6745 	linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
6746 	if (!linkedit) {
6747 		goto finish;
6748 	}
6749 
6750 	if (round_page(kmod_info->address + kmod_info->size) !=
6751 	    round_page(linkedit->vmaddr + linkedit->vmsize)) {
6752 		goto finish;
6753 	}
6754 
6755 	/* Create a new OSData for the smaller kext object.
6756 	 */
6757 	linkeditsize = round_page(linkedit->vmsize);
6758 	kextsize = kmod_info->size - linkeditsize;
6759 	start = linkedit->vmaddr;
6760 
6761 	if (kextsize > UINT_MAX) {
6762 		goto finish;
6763 	}
6764 	data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize);
6765 	if (!data) {
6766 		goto finish;
6767 	}
6768 
6769 	/* Fix the kmod info and linkedExecutable.
6770 	 */
6771 	kmod_info->size = kextsize;
6772 
6773 #if VM_MAPPED_KEXTS
6774 	data->setDeallocFunction(osdata_kext_free);
6775 #else
6776 	data->setDeallocFunction(osdata_phys_free);
6777 #endif
6778 	linkedExecutable->setDeallocFunction(NULL);
6779 	linkedExecutable = os::move(data);
6780 	flags.jettisonLinkeditSeg = 1;
6781 
6782 	/* Free the linkedit segment.
6783 	 */
6784 #if VM_MAPPED_KEXTS
6785 	kext_free(start, linkeditsize);
6786 #else
6787 	ml_static_mfree(start, linkeditsize);
6788 #endif
6789 
6790 finish:
6791 	return;
6792 }
6793 
6794 /*********************************************************************
6795 * If there are whole pages that are unused betweem the last section
6796 * of the DATA segment and the end of the DATA segment then we can free
6797 * them
6798 *********************************************************************/
6799 void
6800 OSKext::jettisonDATASegmentPadding(void)
6801 {
6802 	kernel_mach_header_t * mh;
6803 	kernel_segment_command_t * dataSeg;
6804 	kernel_section_t * sec, * lastSec;
6805 	vm_offset_t dataSegEnd, lastSecEnd;
6806 	vm_size_t padSize;
6807 
6808 	if (flags.builtin) {
6809 		return;
6810 	}
6811 	mh = (kernel_mach_header_t *)kmod_info->address;
6812 
6813 	if (isInFileset()) {
6814 		return;
6815 	}
6816 
6817 	dataSeg = getsegbynamefromheader(mh, SEG_DATA);
6818 	if (dataSeg == NULL) {
6819 		return;
6820 	}
6821 
6822 	lastSec = NULL;
6823 	sec = firstsect(dataSeg);
6824 	while (sec != NULL) {
6825 		lastSec = sec;
6826 		sec = nextsect(dataSeg, sec);
6827 	}
6828 
6829 	if (lastSec == NULL) {
6830 		return;
6831 	}
6832 
6833 	if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
6834 	    (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
6835 		return;
6836 	}
6837 
6838 	dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
6839 	lastSecEnd = round_page(lastSec->addr + lastSec->size);
6840 
6841 	if (dataSegEnd <= lastSecEnd) {
6842 		return;
6843 	}
6844 
6845 	padSize = dataSegEnd - lastSecEnd;
6846 
6847 	if (padSize >= PAGE_SIZE) {
6848 #if VM_MAPPED_KEXTS
6849 		kext_free(lastSecEnd, padSize);
6850 #else
6851 		ml_static_mfree(lastSecEnd, padSize);
6852 #endif
6853 	}
6854 }
6855 
6856 /*********************************************************************
6857 *********************************************************************/
6858 void
6859 OSKext::setLinkedExecutable(OSData * anExecutable)
6860 {
6861 	if (linkedExecutable) {
6862 		panic("Attempt to set linked executable on kext "
6863 		    "that already has one (%s).\n",
6864 		    getIdentifierCString());
6865 	}
6866 	linkedExecutable.reset(anExecutable, OSRetain);
6867 	return;
6868 }
6869 
6870 #if CONFIG_DTRACE
6871 /*********************************************************************
6872 * Go through all loaded kexts and tell them to register with dtrace.
6873 * The instance method only registers if necessary.
6874 *********************************************************************/
6875 /* static */
6876 void
6877 OSKext::registerKextsWithDTrace(void)
6878 {
6879 	uint32_t count = sLoadedKexts->getCount();
6880 	uint32_t i;
6881 
6882 	IORecursiveLockLock(sKextLock);
6883 
6884 	for (i = 0; i < count; i++) {
6885 		OSKext   * thisKext     = NULL;        // do not release
6886 
6887 		thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
6888 		if (!thisKext || !thisKext->isExecutable()) {
6889 			continue;
6890 		}
6891 
6892 		thisKext->registerWithDTrace();
6893 	}
6894 
6895 	IORecursiveLockUnlock(sKextLock);
6896 
6897 	return;
6898 }
6899 
6900 extern "C" {
6901 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
6902 extern int (*dtrace_modunload)(struct kmod_info *);
6903 };
6904 
6905 /*********************************************************************
6906 *********************************************************************/
6907 void
6908 OSKext::registerWithDTrace(void)
6909 {
6910 	/* Register kext with dtrace. A dtrace_modload failure should not
6911 	 * prevent a kext from loading, so we ignore the return code.
6912 	 */
6913 	if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
6914 		uint32_t modflag = 0;
6915 		OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
6916 
6917 #if XNU_TARGET_OS_OSX
6918 		if (!sKeepSymbols && kc_type == KCKindPrimary) {
6919 			if (forceInit == kOSBooleanTrue) {
6920 				OSKextLog(this,
6921 				    kOSKextLogBasicLevel |
6922 				    kOSKextLogGeneralFlag,
6923 				    "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s",
6924 				    getIdentifierCString());
6925 				forceInit = kOSBooleanFalse;
6926 			}
6927 			/* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */
6928 			modflag |= KMOD_DTRACE_NO_KERNEL_SYMS;
6929 		}
6930 #endif /* XNU_TARGET_OS_OSX */
6931 		if (forceInit == kOSBooleanTrue) {
6932 			modflag |= KMOD_DTRACE_FORCE_INIT;
6933 		}
6934 		if (flags.builtin) {
6935 			modflag |= KMOD_DTRACE_STATIC_KEXT;
6936 		}
6937 
6938 		(void)(*dtrace_modload)(kmod_info, modflag);
6939 		flags.dtraceInitialized = true;
6940 		jettisonLinkeditSegment();
6941 	}
6942 	return;
6943 }
6944 /*********************************************************************
6945 *********************************************************************/
6946 void
6947 OSKext::unregisterWithDTrace(void)
6948 {
6949 	/* Unregister kext with dtrace. A dtrace_modunload failure should not
6950 	 * prevent a kext from loading, so we ignore the return code.
6951 	 */
6952 	if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
6953 		(void)(*dtrace_modunload)(kmod_info);
6954 		flags.dtraceInitialized = false;
6955 	}
6956 	return;
6957 }
6958 #endif /* CONFIG_DTRACE */
6959 
6960 
6961 /*********************************************************************
6962 * called only by loadExecutable()
6963 *********************************************************************/
6964 #if !VM_MAPPED_KEXTS
6965 #if defined(__arm__) || defined(__arm64__)
6966 static inline kern_return_t
6967 OSKext_protect(
6968 	kernel_mach_header_t *kext_mh,
6969 	vm_map_t   map,
6970 	vm_map_offset_t    start,
6971 	vm_map_offset_t    end,
6972 	vm_prot_t  new_prot,
6973 	boolean_t  set_max,
6974 	kc_kind_t  kc_type)
6975 {
6976 #pragma unused(kext_mh,map,kc_type)
6977 	assert(map == kernel_map);         // we can handle KEXTs arising from the PRELINK segment and no others
6978 	assert(start <= end);
6979 	if (start >= end) {
6980 		return KERN_SUCCESS;         // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
6981 	} else if (set_max) {
6982 		return KERN_SUCCESS;         // Punt set_max, as there's no mechanism to record that state
6983 	} else {
6984 		return ml_static_protect(start, end - start, new_prot);
6985 	}
6986 }
6987 
6988 static inline kern_return_t
6989 OSKext_wire(
6990 	kernel_mach_header_t *kext_mh,
6991 	vm_map_t   map,
6992 	vm_map_offset_t    start,
6993 	vm_map_offset_t    end,
6994 	vm_prot_t  access_type,
6995 	boolean_t       user_wire,
6996 	kc_kind_t       kc_type)
6997 {
6998 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type)
6999 	return KERN_SUCCESS;         // No-op as PRELINK kexts are cemented into physical memory at boot
7000 }
7001 #else
7002 #error Unrecognized architecture
7003 #endif
7004 #else
7005 static inline kern_return_t
7006 OSKext_protect(
7007 	kernel_mach_header_t *kext_mh,
7008 	vm_map_t   map,
7009 	vm_map_offset_t    start,
7010 	vm_map_offset_t    end,
7011 	vm_prot_t  new_prot,
7012 	boolean_t  set_max,
7013 	kc_kind_t  kc_type)
7014 {
7015 	if (start == end) {         // 10538581
7016 		return KERN_SUCCESS;
7017 	}
7018 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7019 		/*
7020 		 * XXX: This will probably need to be different for AuxKC and
7021 		 * pageableKC!
7022 		 */
7023 		return ml_static_protect(start, end - start, new_prot);
7024 	}
7025 	return vm_map_protect(map, start, end, new_prot, set_max);
7026 }
7027 
7028 static inline kern_return_t
7029 OSKext_wire(
7030 	kernel_mach_header_t *kext_mh,
7031 	vm_map_t   map,
7032 	vm_map_offset_t    start,
7033 	vm_map_offset_t    end,
7034 	vm_prot_t  access_type,
7035 	boolean_t       user_wire,
7036 	kc_kind_t       kc_type)
7037 {
7038 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7039 		/* TODO: we may need to hook this for the pageableKC */
7040 		return KERN_SUCCESS;
7041 	}
7042 	return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
7043 }
7044 #endif
7045 
7046 OSReturn
7047 OSKext::setVMAttributes(bool protect, bool wire)
7048 {
7049 	vm_map_t                    kext_map        = NULL;
7050 	kernel_segment_command_t  * seg             = NULL;
7051 	vm_map_offset_t             start_protect   = 0;
7052 	vm_map_offset_t             start_wire      = 0;
7053 	vm_map_offset_t             end_protect     = 0;
7054 	vm_map_offset_t             end_wire        = 0;
7055 	OSReturn                    result          = kOSReturnError;
7056 
7057 	if (isInterface() || !declaresExecutable() || flags.builtin) {
7058 		result = kOSReturnSuccess;
7059 		goto finish;
7060 	}
7061 
7062 	/* Get the kext's vm map */
7063 	kext_map = kext_get_vm_map(kmod_info);
7064 	if (!kext_map) {
7065 		result = KERN_MEMORY_ERROR;
7066 		goto finish;
7067 	}
7068 
7069 #if !VM_MAPPED_KEXTS
7070 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
7071 		/* This is a split kext in a prelinked kernelcache; we'll let the
7072 		 * platform code take care of protecting it.  It is already wired.
7073 		 */
7074 		/* TODO: Should this still allow protections for the first segment
7075 		 * to go through, in the event that we have a mix of split and
7076 		 * unsplit kexts?
7077 		 */
7078 		result = KERN_SUCCESS;
7079 		goto finish;
7080 	}
7081 
7082 	if (isInFileset() && kc_type != KCKindPageable) {
7083 		// kexts in filesets have protections setup as part of collection loading
7084 		result = KERN_SUCCESS;
7085 		goto finish;
7086 	}
7087 #endif
7088 
7089 	/* Protect the headers as read-only; they do not need to be wired */
7090 	result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7091 	    kext_map, kmod_info->address,
7092 	    kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type)
7093 	    : KERN_SUCCESS;
7094 	if (result != KERN_SUCCESS) {
7095 		goto finish;
7096 	}
7097 
7098 	/* Set the VM protections and wire down each of the segments */
7099 	seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7100 	while (seg) {
7101 #if __arm__
7102 		/* We build all ARM kexts, so we can ensure they are aligned */
7103 		assert((seg->vmaddr & PAGE_MASK) == 0);
7104 		assert((seg->vmsize & PAGE_MASK) == 0);
7105 #endif
7106 
7107 		/*
7108 		 * For the non page aligned segments, the range calculation for protection
7109 		 * and wiring differ as follows:
7110 		 *
7111 		 * Protection: The non page aligned data at the start or at the end of the
7112 		 * segment is excluded from the protection. This exclusion is needed to make
7113 		 * sure OSKext_protect is not called twice on same page, if the page is shared
7114 		 * between two segments.
7115 		 *
7116 		 * Wiring: The non page aligned data at the start or at the end of the
7117 		 * segment is included in the wiring range, this inclusion is needed to make sure
7118 		 * all the data of the segment is wired.
7119 		 */
7120 		start_protect = round_page(seg->vmaddr);
7121 		end_protect = trunc_page(seg->vmaddr + seg->vmsize);
7122 
7123 		start_wire = trunc_page(seg->vmaddr);
7124 		end_wire = round_page(seg->vmaddr + seg->vmsize);
7125 
7126 		/*
7127 		 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared
7128 		 * across kexts and data from kexts is not page aligned
7129 		 */
7130 		if (protect && (end_protect > start_protect) &&
7131 		    ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 &&
7132 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) ||
7133 		    (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) {
7134 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7135 			    kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type);
7136 			if (result != KERN_SUCCESS) {
7137 				OSKextLog(this,
7138 				    kOSKextLogErrorLevel |
7139 				    kOSKextLogLoadFlag,
7140 				    "Kext %s failed to set maximum VM protections "
7141 				    "for segment %s - 0x%x.",
7142 				    getIdentifierCString(), seg->segname, (int)result);
7143 				goto finish;
7144 			}
7145 
7146 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7147 			    kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type);
7148 			if (result != KERN_SUCCESS) {
7149 				OSKextLog(this,
7150 				    kOSKextLogErrorLevel |
7151 				    kOSKextLogLoadFlag,
7152 				    "Kext %s failed to set initial VM protections "
7153 				    "for segment %s - 0x%x.",
7154 				    getIdentifierCString(), seg->segname, (int)result);
7155 				goto finish;
7156 			}
7157 		}
7158 
7159 		if (segmentShouldBeWired(seg) && wire) {
7160 			result = OSKext_wire((kernel_mach_header_t *)kmod_info->address,
7161 			    kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type);
7162 			if (result != KERN_SUCCESS) {
7163 				goto finish;
7164 			}
7165 		}
7166 
7167 		seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7168 	}
7169 
7170 finish:
7171 	return result;
7172 }
7173 
7174 /*********************************************************************
7175 *********************************************************************/
7176 boolean_t
7177 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
7178 {
7179 	return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) &&
7180 	       strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)));
7181 }
7182 
7183 /*********************************************************************
7184 *********************************************************************/
7185 OSReturn
7186 OSKext::validateKextMapping(bool startFlag)
7187 {
7188 	OSReturn                              result      = kOSReturnError;
7189 	const char                          * whichOp = startFlag ? "start" : "stop";
7190 	kern_return_t                         kern_result = 0;
7191 	vm_map_t                              kext_map    = NULL;
7192 	kernel_segment_command_t            * seg         = NULL;
7193 	mach_vm_address_t                     address     = 0;
7194 	mach_vm_size_t                        size        = 0;
7195 	uint32_t                              depth       = 0;
7196 	uint64_t                              kext_segbase = 0;
7197 	uint64_t                              kext_segsize = 0;
7198 	mach_msg_type_number_t                count;
7199 	vm_region_submap_short_info_data_64_t info;
7200 	uintptr_t                             kext_slide = PE_get_kc_slide(kc_type);
7201 
7202 	if (flags.builtin) {
7203 		return kOSReturnSuccess;
7204 	}
7205 
7206 	count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
7207 	bzero(&info, sizeof(info));
7208 
7209 	// xxx - do we need a distinct OSReturn value for these or is "bad data"
7210 	// xxx - sufficient?
7211 
7212 	/* Verify that the kmod_info and start/stop pointers are non-NULL.
7213 	 */
7214 	if (!kmod_info) {
7215 		OSKextLog(this,
7216 		    kOSKextLogErrorLevel |
7217 		    kOSKextLogLoadFlag,
7218 		    "Kext %s - NULL kmod_info pointer.",
7219 		    getIdentifierCString());
7220 		result = kOSKextReturnBadData;
7221 		goto finish;
7222 	}
7223 
7224 	if (startFlag) {
7225 		address = (mach_vm_address_t)kmod_info->start;
7226 	} else {
7227 		address = (mach_vm_address_t)kmod_info->stop;
7228 	}
7229 
7230 	if (!address) {
7231 		OSKextLog(this,
7232 		    kOSKextLogErrorLevel |
7233 		    kOSKextLogLoadFlag,
7234 		    "Kext %s - NULL module %s pointer.",
7235 		    getIdentifierCString(), whichOp);
7236 		result = kOSKextReturnBadData;
7237 		goto finish;
7238 	}
7239 
7240 	kext_map = kext_get_vm_map(kmod_info);
7241 	depth = (kernel_map == kext_map) ? 1 : 2;
7242 	if (isInFileset()) {
7243 #if defined(HAS_APPLE_PAC)
7244 		address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0);
7245 #endif /* defined(HAS_APPLE_PAC) */
7246 	}
7247 
7248 	/* Verify that the start/stop function lies within the kext's address range.
7249 	 */
7250 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) ||
7251 	    isInFileset()) {
7252 		/* This will likely be how we deal with split kexts; walk the segments to
7253 		 * check that the function lies inside one of the segments of this kext.
7254 		 */
7255 		for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7256 		    seg != NULL;
7257 		    seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
7258 			if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
7259 				kext_segbase = seg->vmaddr;
7260 				kext_segsize = seg->vmsize;
7261 				break;
7262 			}
7263 		}
7264 
7265 		if (!seg) {
7266 			OSKextLog(this,
7267 			    kOSKextLogErrorLevel |
7268 			    kOSKextLogLoadFlag,
7269 			    "Kext %s module %s pointer is outside of kext range "
7270 			    "(%s %p - kext starts at %p).",
7271 			    getIdentifierCString(),
7272 			    whichOp,
7273 			    whichOp,
7274 			    (void *)(((uintptr_t)address) - kext_slide),
7275 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide));
7276 			result = kOSKextReturnBadData;
7277 			goto finish;
7278 		}
7279 
7280 		seg = NULL;
7281 	} else {
7282 		if (address < kmod_info->address + kmod_info->hdr_size ||
7283 		    kmod_info->address + kmod_info->size <= address) {
7284 			OSKextLog(this,
7285 			    kOSKextLogErrorLevel |
7286 			    kOSKextLogLoadFlag,
7287 			    "Kext %s module %s pointer is outside of kext range "
7288 			    "(%s %p - kext at %p-%p).",
7289 			    getIdentifierCString(),
7290 			    whichOp,
7291 			    whichOp,
7292 			    (void *)(((uintptr_t)address) - kext_slide),
7293 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide),
7294 			    (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size));
7295 			result = kOSKextReturnBadData;
7296 			goto finish;
7297 		}
7298 	}
7299 
7300 	/* Only do these checks before calling the start function;
7301 	 * If anything goes wrong with the mapping while the kext is running,
7302 	 * we'll likely have panicked well before any attempt to stop the kext.
7303 	 */
7304 	if (startFlag) {
7305 		if (!isInFileset() || kc_type != KCKindPrimary) {
7306 			/*
7307 			 * Verify that the start/stop function is executable.
7308 			 */
7309 			kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
7310 			    (vm_region_recurse_info_t)&info, &count);
7311 			if (kern_result != KERN_SUCCESS) {
7312 				OSKextLog(this,
7313 				    kOSKextLogErrorLevel |
7314 				    kOSKextLogLoadFlag,
7315 				    "Kext %s - bad %s pointer %p.",
7316 				    getIdentifierCString(),
7317 				    whichOp, (void *)ml_static_unslide(address));
7318 				result = kOSKextReturnBadData;
7319 				goto finish;
7320 			}
7321 		} else {
7322 			/*
7323 			 * Since kexts loaded from the primary KC are held in memory
7324 			 * allocated by efiboot, we cannot use mach_vm_region_recurse() to
7325 			 * discover that memory's protection flags.  Instead, we need to
7326 			 * get that information from the kernel pmap itself.  Above, we
7327 			 * (potentially) saved the size of the segment in which the address
7328 			 * in question was located.  If we have a non-zero size, verify
7329 			 * that all pages in the (address, address + kext_segsize) range
7330 			 * are marked executable.  If we somehow did not record the size
7331 			 * (or the base) just verify the single page that includes the address.
7332 			 */
7333 			if (kext_segbase == 0 || kext_segsize == 0) {
7334 				kext_segbase = address & ~(uint64_t)PAGE_MASK;
7335 				kext_segsize = PAGE_SIZE;
7336 			}
7337 		}
7338 
7339 #if VM_MAPPED_KEXTS
7340 		if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) ||
7341 		    ((isInFileset() && kc_type == KCKindPrimary) &&
7342 		    ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) {
7343 			OSKextLog(this,
7344 			    kOSKextLogErrorLevel |
7345 			    kOSKextLogLoadFlag,
7346 			    "Kext %s - memory region containing module %s function "
7347 			    "is not executable.",
7348 			    getIdentifierCString(), whichOp);
7349 			result = kOSKextReturnBadData;
7350 			goto finish;
7351 		}
7352 #endif
7353 
7354 		/* Verify that the kext's segments are backed by physical memory.
7355 		 */
7356 		seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7357 		while (seg) {
7358 			if (!verifySegmentMapping(seg)) {
7359 				result = kOSKextReturnBadData;
7360 				goto finish;
7361 			}
7362 
7363 			seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7364 		}
7365 	}
7366 
7367 	result = kOSReturnSuccess;
7368 finish:
7369 	return result;
7370 }
7371 
7372 /*********************************************************************
7373 *********************************************************************/
7374 boolean_t
7375 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
7376 {
7377 	mach_vm_address_t address = 0;
7378 
7379 	if (seg->vmsize > UINT32_MAX) {
7380 		return false;
7381 	}
7382 
7383 	if (!segmentShouldBeWired(seg)) {
7384 		return true;
7385 	}
7386 
7387 	for (address = seg->vmaddr;
7388 	    address < round_page(seg->vmaddr + seg->vmsize);
7389 	    address += PAGE_SIZE) {
7390 		if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
7391 			OSKextLog(this,
7392 			    kOSKextLogErrorLevel |
7393 			    kOSKextLogLoadFlag,
7394 			    "Kext %s - page %p is not backed by physical memory.",
7395 			    getIdentifierCString(),
7396 			    (void *)address);
7397 			return false;
7398 		}
7399 	}
7400 
7401 	return true;
7402 }
7403 
7404 /*********************************************************************
7405 *********************************************************************/
7406 static void
7407 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
7408 {
7409 	uint64_t                            stamp = 0;
7410 	firehose_tracepoint_id_u            trace_id;
7411 	struct firehose_trace_uuid_info_s   uuid_info_s;
7412 	firehose_trace_uuid_info_t          uuid_info = &uuid_info_s;
7413 	size_t                              uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
7414 	OSSharedPtr<OSData>                 uuid_data;
7415 
7416 	stamp = firehose_tracepoint_time(firehose_activity_flags_default);
7417 	trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
7418 
7419 	uuid_data = aKext->copyTextUUID();
7420 	if (uuid_data) {
7421 		memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
7422 	}
7423 
7424 	uuid_info->ftui_size    = size;
7425 	if (aKext->isDriverKit()) {
7426 		uuid_info->ftui_address = address;
7427 	} else {
7428 		uuid_info->ftui_address = ml_static_unslide(address);
7429 	}
7430 	firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
7431 	return;
7432 }
7433 
7434 void
7435 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
7436 {
7437 	OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
7438 }
7439 
7440 /*********************************************************************
7441 *********************************************************************/
7442 OSReturn
7443 OSKext::start(bool startDependenciesFlag)
7444 {
7445 	OSReturn                            result = kOSReturnError;
7446 	kern_return_t                       (* startfunc)(kmod_info_t *, void *);
7447 	unsigned int                        i, count;
7448 	void                              * kmodStartData = NULL;
7449 
7450 	if (isStarted() || isInterface() || isKernelComponent()) {
7451 		result = kOSReturnSuccess;
7452 		goto finish;
7453 	}
7454 
7455 	if (!isLoaded()) {
7456 		OSKextLog(this,
7457 		    kOSKextLogErrorLevel |
7458 		    kOSKextLogLoadFlag,
7459 		    "Attempt to start nonloaded kext %s.",
7460 		    getIdentifierCString());
7461 		result = kOSKextReturnInvalidArgument;
7462 		goto finish;
7463 	}
7464 
7465 	if (!sLoadEnabled) {
7466 		OSKextLog(this,
7467 		    kOSKextLogErrorLevel |
7468 		    kOSKextLogLoadFlag,
7469 		    "Kext loading is disabled (attempt to start kext %s).",
7470 		    getIdentifierCString());
7471 		result = kOSKextReturnDisabled;
7472 		goto finish;
7473 	}
7474 
7475 	result = validateKextMapping(/* start? */ true);
7476 	if (result != kOSReturnSuccess) {
7477 		goto finish;
7478 	}
7479 
7480 	startfunc = kmod_info->start;
7481 
7482 	count = getNumDependencies();
7483 	for (i = 0; i < count; i++) {
7484 		OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
7485 		if (dependency == NULL) {
7486 			OSKextLog(this,
7487 			    kOSKextLogErrorLevel |
7488 			    kOSKextLogLoadFlag,
7489 			    "Kext %s start - internal error, dependency disappeared.",
7490 			    getIdentifierCString());
7491 			goto finish;
7492 		}
7493 		if (!dependency->isStarted()) {
7494 			if (startDependenciesFlag) {
7495 				OSReturn dependencyResult =
7496 				    dependency->start(startDependenciesFlag);
7497 				if (dependencyResult != KERN_SUCCESS) {
7498 					OSKextLog(this,
7499 					    kOSKextLogErrorLevel |
7500 					    kOSKextLogLoadFlag,
7501 					    "Kext %s start - dependency %s failed to start (error 0x%x).",
7502 					    getIdentifierCString(),
7503 					    dependency->getIdentifierCString(),
7504 					    dependencyResult);
7505 					goto finish;
7506 				}
7507 			} else {
7508 				OSKextLog(this,
7509 				    kOSKextLogErrorLevel |
7510 				    kOSKextLogLoadFlag,
7511 				    "Not starting %s - dependency %s not started yet.",
7512 				    getIdentifierCString(),
7513 				    dependency->getIdentifierCString());
7514 				result = kOSKextReturnStartStopError;         // xxx - make new return?
7515 				goto finish;
7516 			}
7517 		}
7518 	}
7519 
7520 	OSKextLog(this,
7521 	    kOSKextLogDetailLevel |
7522 	    kOSKextLogLoadFlag,
7523 	    "Kext %s calling module start function.",
7524 	    getIdentifierCString());
7525 
7526 	flags.starting = 1;
7527 
7528 	// Drop a log message so logd can grab the needed information to decode this kext
7529 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
7530 	result = OSRuntimeInitializeCPP(this);
7531 	if (result == KERN_SUCCESS) {
7532 		result = startfunc(kmod_info, kmodStartData);
7533 	}
7534 
7535 	flags.starting = 0;
7536 
7537 	/* On success overlap the setting of started/starting. On failure just
7538 	 * clear starting.
7539 	 */
7540 	if (result == KERN_SUCCESS) {
7541 		flags.started = 1;
7542 
7543 		// xxx - log start error from kernel?
7544 		OSKextLog(this,
7545 		    kOSKextLogProgressLevel |
7546 		    kOSKextLogLoadFlag,
7547 		    "Kext %s is now started.",
7548 		    getIdentifierCString());
7549 	} else {
7550 		invokeOrCancelRequestCallbacks(
7551 			/* result not actually used */ kOSKextReturnStartStopError,
7552 			/* invokeFlag */ false);
7553 		OSKextLog(this,
7554 		    kOSKextLogWarningLevel |
7555 		    kOSKextLogLoadFlag,
7556 		    "Kext %s did not start (return code 0x%x).",
7557 		    getIdentifierCString(), result);
7558 	}
7559 
7560 finish:
7561 	return result;
7562 }
7563 
7564 /*********************************************************************
7565 *********************************************************************/
7566 /* static */
7567 bool
7568 OSKext::canUnloadKextWithIdentifier(
7569 	OSString * kextIdentifier,
7570 	bool       checkClassesFlag)
7571 {
7572 	bool     result = false;
7573 	OSKext * aKext  = NULL;        // do not release
7574 
7575 	IORecursiveLockLock(sKextLock);
7576 
7577 	aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
7578 
7579 	if (!aKext) {
7580 		goto finish;         // can't unload what's not loaded
7581 	}
7582 
7583 	if (aKext->isLoaded()) {
7584 		if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
7585 			goto finish;
7586 		}
7587 		if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
7588 			goto finish;
7589 		}
7590 	}
7591 
7592 	result = true;
7593 
7594 finish:
7595 	IORecursiveLockUnlock(sKextLock);
7596 	return result;
7597 }
7598 
7599 /*********************************************************************
7600 *********************************************************************/
7601 OSReturn
7602 OSKext::stop(void)
7603 {
7604 	OSReturn result = kOSReturnError;
7605 	kern_return_t (*stopfunc)(kmod_info_t *, void *);
7606 
7607 	if (!isStarted() || isInterface()) {
7608 		result = kOSReturnSuccess;
7609 		goto finish;
7610 	}
7611 
7612 	if (!isLoaded()) {
7613 		OSKextLog(this,
7614 		    kOSKextLogErrorLevel |
7615 		    kOSKextLogLoadFlag,
7616 		    "Attempt to stop nonloaded kext %s.",
7617 		    getIdentifierCString());
7618 		result = kOSKextReturnInvalidArgument;
7619 		goto finish;
7620 	}
7621 
7622 	/* Refuse to stop if we have clients or instances. It is up to
7623 	 * the caller to make sure those aren't true.
7624 	 */
7625 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7626 		OSKextLog(this,
7627 		    kOSKextLogErrorLevel |
7628 		    kOSKextLogLoadFlag,
7629 		    "Kext %s - C++ instances; can't stop.",
7630 		    getIdentifierCString());
7631 		result = kOSKextReturnInUse;
7632 		goto finish;
7633 	}
7634 
7635 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7636 		OSKextLog(this,
7637 		    kOSKextLogErrorLevel |
7638 		    kOSKextLogLoadFlag,
7639 		    "Kext %s - has references (linkage or tracking object); "
7640 		    "can't stop.",
7641 		    getIdentifierCString());
7642 		result = kOSKextReturnInUse;
7643 		goto finish;
7644 	}
7645 
7646 	/* Note: If validateKextMapping fails on the stop & unload path,
7647 	 * we are in serious trouble and a kernel panic is likely whether
7648 	 * we stop & unload the kext or not.
7649 	 */
7650 	result = validateKextMapping(/* start? */ false);
7651 	if (result != kOSReturnSuccess) {
7652 		goto finish;
7653 	}
7654 
7655 	stopfunc = kmod_info->stop;
7656 	if (stopfunc) {
7657 		OSKextLog(this,
7658 		    kOSKextLogDetailLevel |
7659 		    kOSKextLogLoadFlag,
7660 		    "Kext %s calling module stop function.",
7661 		    getIdentifierCString());
7662 
7663 		flags.stopping = 1;
7664 
7665 		result = stopfunc(kmod_info, /* userData */ NULL);
7666 		if (result == KERN_SUCCESS) {
7667 			result = OSRuntimeFinalizeCPP(this);
7668 		}
7669 
7670 		flags.stopping = 0;
7671 
7672 		if (result == KERN_SUCCESS) {
7673 			flags.started = 0;
7674 
7675 			OSKextLog(this,
7676 			    kOSKextLogDetailLevel |
7677 			    kOSKextLogLoadFlag,
7678 			    "Kext %s is now stopped and ready to unload.",
7679 			    getIdentifierCString());
7680 		} else {
7681 			OSKextLog(this,
7682 			    kOSKextLogErrorLevel |
7683 			    kOSKextLogLoadFlag,
7684 			    "Kext %s did not stop (return code 0x%x).",
7685 			    getIdentifierCString(), result);
7686 			result = kOSKextReturnStartStopError;
7687 		}
7688 	}
7689 
7690 finish:
7691 	// Drop a log message so logd can update this kext's metadata
7692 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
7693 	return result;
7694 }
7695 
7696 /*********************************************************************
7697 *********************************************************************/
7698 OSReturn
7699 OSKext::unload(void)
7700 {
7701 	OSReturn        result = kOSReturnError;
7702 	unsigned int    index;
7703 	uint32_t        num_kmod_refs = 0;
7704 	OSKextAccount * freeAccount;
7705 	bool            in_fileset = false;
7706 
7707 	if (!sUnloadEnabled) {
7708 		OSKextLog(this,
7709 		    kOSKextLogErrorLevel |
7710 		    kOSKextLogLoadFlag,
7711 		    "Kext unloading is disabled (%s).",
7712 		    this->getIdentifierCString());
7713 
7714 		result = kOSKextReturnDisabled;
7715 		goto finish;
7716 	}
7717 
7718 	// cache this result so we don't need to access the kmod_info after
7719 	// it's been potentially free'd
7720 	in_fileset = isInFileset();
7721 
7722 	/* Refuse to unload if we have clients or instances. It is up to
7723 	 * the caller to make sure those aren't true.
7724 	 */
7725 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7726 		// xxx - Don't log under errors? this is more of an info thing
7727 		OSKextLog(this,
7728 		    kOSKextLogErrorLevel |
7729 		    kOSKextLogKextBookkeepingFlag,
7730 		    "Can't unload kext %s; outstanding references (linkage or tracking object).",
7731 		    getIdentifierCString());
7732 		result = kOSKextReturnInUse;
7733 		goto finish;
7734 	}
7735 
7736 	if (isDriverKit()) {
7737 		index = sLoadedKexts->getNextIndexOfObject(this, 0);
7738 		if (index != (unsigned int)-1) {
7739 			sLoadedDriverKitKexts->removeObject(index);
7740 			OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
7741 			loadTag = 0;
7742 		}
7743 	}
7744 
7745 	if (!isLoaded()) {
7746 		result = kOSReturnSuccess;
7747 		goto finish;
7748 	}
7749 
7750 	if (isKernelComponent()) {
7751 		result = kOSKextReturnInvalidArgument;
7752 		goto finish;
7753 	}
7754 
7755 	if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) {
7756 		OSKextLog(this,
7757 		    kOSKextLogErrorLevel |
7758 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
7759 		    "Can't unload kext %s; classes have instances:",
7760 		    getIdentifierCString());
7761 		reportOSMetaClassInstances(kOSKextLogErrorLevel |
7762 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
7763 		result = kOSKextReturnInUse;
7764 		goto finish;
7765 	}
7766 
7767 	/* Note that the kext is unloading before running any code that
7768 	 * might be in the kext (request callbacks, module stop function).
7769 	 * We will deny certain requests made against a kext in the process
7770 	 * of unloading.
7771 	 */
7772 	flags.unloading = 1;
7773 
7774 	/* Update the string describing the last kext to unload in case we panic.
7775 	 */
7776 	savePanicString(/* isLoading */ false);
7777 
7778 	if (isStarted()) {
7779 		result = stop();
7780 		if (result != KERN_SUCCESS) {
7781 			OSKextLog(this,
7782 			    kOSKextLogErrorLevel |
7783 			    kOSKextLogLoadFlag,
7784 			    "Kext %s can't unload - module stop returned 0x%x.",
7785 			    getIdentifierCString(), (unsigned)result);
7786 			result = kOSKextReturnStartStopError;
7787 			goto finish;
7788 		}
7789 	}
7790 
7791 	OSKextLog(this,
7792 	    kOSKextLogProgressLevel |
7793 	    kOSKextLogLoadFlag,
7794 	    "Kext %s unloading.",
7795 	    getIdentifierCString());
7796 
7797 	{
7798 		struct list_head *p;
7799 		struct list_head *prev;
7800 		struct list_head *next;
7801 		for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
7802 			OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
7803 			s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
7804 			prev = p->prev;
7805 			next = p->next;
7806 			prev->next = next;
7807 			next->prev = prev;
7808 			p->prev = p;
7809 			p->next = p;
7810 			IORecursiveLockWakeup(sKextLock, s, false);
7811 		}
7812 	}
7813 
7814 
7815 	/* Even if we don't call the stop function, we want to be sure we
7816 	 * have no OSMetaClass references before unloading the kext executable
7817 	 * from memory. OSMetaClasses may have pointers into the kext executable
7818 	 * and that would cause a panic on OSKext::free() when metaClasses is freed.
7819 	 */
7820 	if (metaClasses) {
7821 		metaClasses->flushCollection();
7822 	}
7823 	(void) OSRuntimeFinalizeCPP(this);
7824 
7825 	/* Remove the kext from the list of loaded kexts, patch the gap
7826 	 * in the kmod_info_t linked list, and reset "kmod" to point to the
7827 	 * last loaded kext that isn't the fake kernel kext (sKernelKext).
7828 	 */
7829 	index = sLoadedKexts->getNextIndexOfObject(this, 0);
7830 	if (index != (unsigned int)-1) {
7831 		sLoadedKexts->removeObject(index);
7832 
7833 		OSKext * nextKext = OSDynamicCast(OSKext,
7834 		    sLoadedKexts->getObject(index));
7835 
7836 		if (nextKext) {
7837 			if (index > 0) {
7838 				OSKext * gapKext = OSDynamicCast(OSKext,
7839 				    sLoadedKexts->getObject(index - 1));
7840 
7841 				nextKext->kmod_info->next = gapKext->kmod_info;
7842 			} else {         /* index == 0 */
7843 				nextKext->kmod_info->next = NULL;
7844 			}
7845 		}
7846 
7847 		OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
7848 		if (lastKext && !lastKext->isKernel()) {
7849 			kmod = lastKext->kmod_info;
7850 		} else {
7851 			kmod = NULL;         // clear the global kmod variable
7852 		}
7853 	}
7854 
7855 	/* Clear out the kmod references that we're keeping for compatibility
7856 	 * with current panic backtrace code & kgmacros.
7857 	 * xxx - will want to update those bits sometime and remove this.
7858 	 */
7859 	num_kmod_refs = getNumDependencies();
7860 	if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
7861 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
7862 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
7863 			ref->info->reference_count--;
7864 		}
7865 		kfree_type(kmod_reference_t, num_kmod_refs,
7866 		    kmod_info->reference_list);
7867 	}
7868 
7869 #if CONFIG_DTRACE
7870 	unregisterWithDTrace();
7871 #endif /* CONFIG_DTRACE */
7872 
7873 	notifyKextUnloadObservers(this);
7874 
7875 	freeAccount = NULL;
7876 	IOSimpleLockLock(sKextAccountsLock);
7877 	account->kext = NULL;
7878 	if (account->site.tag) {
7879 		account->site.flags |= VM_TAG_UNLOAD;
7880 	} else {
7881 		freeAccount = account;
7882 	}
7883 
7884 #if DEVELOPMENT || DEBUG
7885 	assertf(account->task_refgrp.grp_count == 0,
7886 	    "unloading a kext with active task references");
7887 #endif /* DEVELOPMENT || DEBUG */
7888 
7889 	IOSimpleLockUnlock(sKextAccountsLock);
7890 	if (freeAccount) {
7891 		IOFreeType(freeAccount, OSKextAccount);
7892 	}
7893 
7894 	/* Unwire and free the linked executable.
7895 	 */
7896 	if (linkedExecutable) {
7897 #if KASAN
7898 		kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
7899 #endif
7900 
7901 #if VM_MAPPED_KEXTS
7902 		if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) {
7903 			kernel_segment_command_t *seg = NULL;
7904 			vm_map_t kext_map = kext_get_vm_map(kmod_info);
7905 
7906 			if (!kext_map) {
7907 				OSKextLog(this,
7908 				    kOSKextLogErrorLevel |
7909 				    kOSKextLogLoadFlag,
7910 				    "Failed to free kext %s; couldn't find the kext map.",
7911 				    getIdentifierCString());
7912 				result = kOSKextReturnInternalError;
7913 				goto finish;
7914 			}
7915 
7916 			OSKextLog(this,
7917 			    kOSKextLogProgressLevel |
7918 			    kOSKextLogLoadFlag,
7919 			    "Kext %s unwiring and unmapping linked executable.",
7920 			    getIdentifierCString());
7921 
7922 			seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7923 			while (seg) {
7924 				if (segmentShouldBeWired(seg)) {
7925 					vm_map_offset_t start_wire = trunc_page(seg->vmaddr);
7926 					vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize);
7927 
7928 					result = vm_map_unwire(kext_map, start_wire,
7929 					    end_wire, FALSE);
7930 					if (result != KERN_SUCCESS) {
7931 						OSKextLog(this,
7932 						    kOSKextLogErrorLevel |
7933 						    kOSKextLogLoadFlag,
7934 						    "Failed to unwire kext %s.",
7935 						    getIdentifierCString());
7936 						result = kOSKextReturnInternalError;
7937 						goto finish;
7938 					}
7939 				}
7940 
7941 				seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7942 			}
7943 #if defined(__x86_64__) || defined(__i386__)
7944 			if (in_fileset && flags.resetSegmentsFromVnode) {
7945 				IORecursiveLockLock(sKextLock);
7946 				resetKCFileSetSegments();
7947 				IORecursiveLockUnlock(sKextLock);
7948 			}
7949 #endif // (__x86_64__) || defined(__i386__)
7950 		}
7951 #endif /* VM_MAPPED_KEXTS */
7952 		if (flags.resetSegmentsFromImmutableCopy) {
7953 			result = resetMutableSegments();
7954 			if (result != kOSReturnSuccess) {
7955 				OSKextLog(this,
7956 				    kOSKextLogErrorLevel |
7957 				    kOSKextLogLoadFlag,
7958 				    "Failed to reset kext %s.",
7959 				    getIdentifierCString());
7960 				result = kOSKextReturnInternalError;
7961 				goto finish;
7962 			}
7963 		}
7964 		if (kc_type == KCKindUnknown) {
7965 			linkedExecutable.reset();
7966 		}
7967 	}
7968 
7969 	/* An interface kext has a fake kmod_info that was allocated,
7970 	 * so we have to free it.
7971 	 */
7972 	if (isInterface()) {
7973 		kfree_type(kmod_info_t, kmod_info);
7974 		kmod_info = NULL;
7975 	}
7976 
7977 	if (!in_fileset) {
7978 		kmod_info = NULL;
7979 	}
7980 
7981 	flags.loaded = false;
7982 	flushDependencies();
7983 
7984 	/* save a copy of the bundle ID for us to check when deciding to
7985 	 * rebuild the kernel cache file.  If a kext was already in the kernel
7986 	 * cache and unloaded then later loaded we do not need to rebuild the
7987 	 * kernel cache.  9055303
7988 	 */
7989 	if (isPrelinked()) {
7990 		if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) {
7991 			IORecursiveLockLock(sKextLock);
7992 			if (sUnloadedPrelinkedKexts) {
7993 				sUnloadedPrelinkedKexts->setObject(bundleID.get());
7994 			}
7995 			IORecursiveLockUnlock(sKextLock);
7996 		}
7997 	}
7998 
7999 	OSKextLog(this,
8000 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8001 	    "Kext %s unloaded.", getIdentifierCString());
8002 
8003 	queueKextNotification(kKextRequestPredicateUnloadNotification,
8004 	    OSDynamicCast(OSString, bundleID.get()));
8005 
8006 finish:
8007 	OSKext::saveLoadedKextPanicList();
8008 	OSKext::updateLoadedKextSummaries();
8009 
8010 	flags.unloading = 0;
8011 	return result;
8012 }
8013 
8014 /*********************************************************************
8015 * Assumes sKextLock is held.
8016 *********************************************************************/
8017 /* static */
8018 OSReturn
8019 OSKext::queueKextNotification(
8020 	const char * notificationName,
8021 	OSString   * kextIdentifier)
8022 {
8023 	OSReturn          result               = kOSReturnError;
8024 	OSSharedPtr<OSDictionary>    loadRequest;
8025 
8026 	if (!kextIdentifier) {
8027 		result = kOSKextReturnInvalidArgument;
8028 		goto finish;
8029 	}
8030 
8031 	/* Create a new request unless one is already sitting
8032 	 * in sKernelRequests for this bundle identifier
8033 	 */
8034 	result = _OSKextCreateRequest(notificationName, loadRequest);
8035 	if (result != kOSReturnSuccess) {
8036 		goto finish;
8037 	}
8038 	if (!_OSKextSetRequestArgument(loadRequest.get(),
8039 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
8040 		result = kOSKextReturnNoMemory;
8041 		goto finish;
8042 	}
8043 	if (!sKernelRequests->setObject(loadRequest.get())) {
8044 		result = kOSKextReturnNoMemory;
8045 		goto finish;
8046 	}
8047 
8048 	/* We might want to only queue the notification if the IOKit daemon is active,
8049 	 * but that wouldn't work for embedded. Note that we don't care if
8050 	 * the ping immediately succeeds here so don't do anything with the
8051 	 * result of this call.
8052 	 */
8053 	OSKext::pingIOKitDaemon();
8054 
8055 	result = kOSReturnSuccess;
8056 
8057 finish:
8058 	return result;
8059 }
8060 
8061 
8062 #if CONFIG_KXLD
8063 /*********************************************************************
8064 *********************************************************************/
8065 static void
8066 _OSKextConsiderDestroyingLinkContext(
8067 	__unused thread_call_param_t p0,
8068 	__unused thread_call_param_t p1)
8069 {
8070 	/* Take multiple locks in the correct order.
8071 	 */
8072 	IORecursiveLockLock(sKextLock);
8073 	IORecursiveLockLock(sKextInnerLock);
8074 
8075 	/* The first time we destroy the kxldContext is in the first
8076 	 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
8077 	 * before calling this function. Thereafter any call to this function
8078 	 * will actually destroy the context.
8079 	 */
8080 	if (sConsiderUnloadsCalled && sKxldContext) {
8081 		kxld_destroy_context(sKxldContext);
8082 		sKxldContext = NULL;
8083 	}
8084 
8085 	/* Free the thread_call that was allocated to execute this function.
8086 	 */
8087 	if (sDestroyLinkContextThread) {
8088 		if (!thread_call_free(sDestroyLinkContextThread)) {
8089 			OSKextLog(/* kext */ NULL,
8090 			    kOSKextLogErrorLevel |
8091 			    kOSKextLogGeneralFlag,
8092 			    "thread_call_free() failed for kext link context.");
8093 		}
8094 		sDestroyLinkContextThread = NULL;
8095 	}
8096 
8097 	IORecursiveLockUnlock(sKextInnerLock);
8098 	IORecursiveLockUnlock(sKextLock);
8099 
8100 	return;
8101 }
8102 
8103 /*********************************************************************
8104 * Destroying the kxldContext requires checking variables under both
8105 * sKextInnerLock and sKextLock, so we do it on a separate thread
8106 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
8107 * call relationship.
8108 *
8109 * This function must be invoked with sKextInnerLock held.
8110 * Do not call any function that takes sKextLock here!
8111 *********************************************************************/
8112 /* static */
8113 void
8114 OSKext::considerDestroyingLinkContext(void)
8115 {
8116 	IORecursiveLockLock(sKextInnerLock);
8117 
8118 	/* If we have already queued a thread to destroy the link context,
8119 	 * don't bother resetting; that thread will take care of it.
8120 	 */
8121 	if (sDestroyLinkContextThread) {
8122 		goto finish;
8123 	}
8124 
8125 	/* The function to be invoked in the thread will deallocate
8126 	 * this thread_call, so don't share it around.
8127 	 */
8128 	sDestroyLinkContextThread = thread_call_allocate(
8129 		&_OSKextConsiderDestroyingLinkContext, NULL);
8130 	if (!sDestroyLinkContextThread) {
8131 		OSKextLog(/* kext */ NULL,
8132 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
8133 		    "Can't create thread to destroy kext link context.");
8134 		goto finish;
8135 	}
8136 
8137 	thread_call_enter(sDestroyLinkContextThread);
8138 
8139 finish:
8140 	IORecursiveLockUnlock(sKextInnerLock);
8141 	return;
8142 }
8143 
8144 #else // !CONFIG_KXLD
8145 
8146 /* static */
8147 void
8148 OSKext::considerDestroyingLinkContext(void)
8149 {
8150 	return;
8151 }
8152 
8153 #endif // CONFIG_KXLD
8154 
8155 #if PRAGMA_MARK
8156 #pragma mark Autounload
8157 #endif
8158 /*********************************************************************
8159 * This is a static method because the kext will be deallocated if it
8160 * does unload!
8161 *********************************************************************/
8162 /* static */
8163 OSReturn
8164 OSKext::autounloadKext(OSKext * aKext)
8165 {
8166 	OSReturn result = kOSKextReturnInUse;
8167 
8168 #if NO_KEXTD
8169 	/*
8170 	 * Do not unload prelinked kexts on platforms that do not have an
8171 	 * IOKit daemon as there is no way to reload the kext or restart
8172 	 * matching.
8173 	 */
8174 	if (aKext->isPrelinked()) {
8175 		goto finish;
8176 	}
8177 #endif /* defined(__x86_64__) */
8178 
8179 	/* Check for external references to this kext (usu. dependents),
8180 	 * instances of defined classes (or classes derived from them),
8181 	 * outstanding requests.
8182 	 */
8183 	if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
8184 	    !aKext->flags.autounloadEnabled ||
8185 	    aKext->isKernelComponent()) {
8186 		goto finish;
8187 	}
8188 
8189 	/* Skip a delay-autounload kext, once.
8190 	 */
8191 	if (aKext->flags.delayAutounload) {
8192 		OSKextLog(aKext,
8193 		    kOSKextLogProgressLevel |
8194 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8195 		    "Kext %s has delayed autounload set; skipping and clearing flag.",
8196 		    aKext->getIdentifierCString());
8197 		aKext->flags.delayAutounload = 0;
8198 		goto finish;
8199 	}
8200 
8201 	if (aKext->hasOSMetaClassInstances() ||
8202 	    aKext->countRequestCallbacks()) {
8203 		goto finish;
8204 	}
8205 
8206 	result = OSKext::removeKext(aKext);
8207 
8208 finish:
8209 	return result;
8210 }
8211 
8212 /*********************************************************************
8213 *********************************************************************/
8214 void
8215 _OSKextConsiderUnloads(
8216 	__unused thread_call_param_t p0,
8217 	__unused thread_call_param_t p1)
8218 {
8219 	bool         didUnload = false;
8220 	unsigned int count, i;
8221 
8222 	/* Take multiple locks in the correct order
8223 	 * (note also sKextSummaries lock further down).
8224 	 */
8225 	IORecursiveLockLock(sKextLock);
8226 	IORecursiveLockLock(sKextInnerLock);
8227 
8228 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
8229 
8230 	/* If the system is powering down, don't try to unload anything.
8231 	 */
8232 	if (sSystemSleep) {
8233 		goto finish;
8234 	}
8235 
8236 	OSKextLog(/* kext */ NULL,
8237 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8238 	    "Checking for unused kexts to autounload.");
8239 
8240 	/*****
8241 	 * Remove any request callbacks marked as stale,
8242 	 * and mark as stale any currently in flight.
8243 	 */
8244 	count = sRequestCallbackRecords->getCount();
8245 	if (count) {
8246 		i = count - 1;
8247 		do {
8248 			OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
8249 			    sRequestCallbackRecords->getObject(i));
8250 			OSBoolean * stale = OSDynamicCast(OSBoolean,
8251 			    callbackRecord->getObject(kKextRequestStaleKey));
8252 
8253 			if (stale == kOSBooleanTrue) {
8254 				OSKext::invokeRequestCallback(callbackRecord,
8255 				    kOSKextReturnTimeout);
8256 			} else {
8257 				callbackRecord->setObject(kKextRequestStaleKey,
8258 				    kOSBooleanTrue);
8259 			}
8260 		} while (i--);
8261 	}
8262 
8263 	/*****
8264 	 * Make multiple passes through the array of loaded kexts until
8265 	 * we don't unload any. This handles unwinding of dependency
8266 	 * chains. We have to go *backwards* through the array because
8267 	 * kexts are removed from it when unloaded, and we cannot make
8268 	 * a copy or we'll mess up the retain counts we rely on to
8269 	 * check whether a kext will unload. If only we could have
8270 	 * nonretaining collections like CF has....
8271 	 */
8272 	do {
8273 		didUnload = false;
8274 
8275 		count = sLoadedKexts->getCount();
8276 		if (count) {
8277 			i = count - 1;
8278 			do {
8279 				OSKext * thisKext = OSDynamicCast(OSKext,
8280 				    sLoadedKexts->getObject(i));
8281 				didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
8282 			} while (i--);
8283 		}
8284 	} while (didUnload);
8285 
8286 finish:
8287 	sConsiderUnloadsPending = false;
8288 	sConsiderUnloadsExecuted = true;
8289 
8290 	(void) OSKext::considerRebuildOfPrelinkedKernel();
8291 
8292 	IORecursiveLockUnlock(sKextInnerLock);
8293 	IORecursiveLockUnlock(sKextLock);
8294 
8295 	return;
8296 }
8297 
8298 /*********************************************************************
8299 * Do not call any function that takes sKextLock here!
8300 *********************************************************************/
8301 void
8302 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
8303 {
8304 	AbsoluteTime when;
8305 
8306 	IORecursiveLockLock(sKextInnerLock);
8307 
8308 	if (!sUnloadCallout) {
8309 		sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
8310 	}
8311 
8312 	/* we only reset delay value for unloading if we already have something
8313 	 * pending.  rescheduleOnlyFlag should not start the count down.
8314 	 */
8315 	if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
8316 		goto finish;
8317 	}
8318 
8319 	thread_call_cancel(sUnloadCallout);
8320 	if (OSKext::getAutounloadEnabled() && !sSystemSleep
8321 #if !NO_KEXTD
8322 	    && sIOKitDaemonActive
8323 #endif
8324 	    ) {
8325 		clock_interval_to_deadline(sConsiderUnloadDelay,
8326 		    1000 * 1000 * 1000, &when);
8327 
8328 		OSKextLog(/* kext */ NULL,
8329 		    kOSKextLogProgressLevel |
8330 		    kOSKextLogLoadFlag,
8331 		    "%scheduling %sscan for unused kexts in %lu seconds.",
8332 		    sConsiderUnloadsPending ? "Res" : "S",
8333 		    sConsiderUnloadsCalled ? "" : "initial ",
8334 		    (unsigned long)sConsiderUnloadDelay);
8335 
8336 		sConsiderUnloadsPending = true;
8337 		thread_call_enter_delayed(sUnloadCallout, when);
8338 	}
8339 
8340 finish:
8341 	/* The kxld context should be reused throughout boot.  We mark the end of
8342 	 * period as the first time considerUnloads() is called, and we destroy
8343 	 * the first kxld context in that function.  Afterwards, it will be
8344 	 * destroyed in flushNonloadedKexts.
8345 	 */
8346 	if (!sConsiderUnloadsCalled) {
8347 		sConsiderUnloadsCalled = true;
8348 		OSKext::considerDestroyingLinkContext();
8349 	}
8350 
8351 	IORecursiveLockUnlock(sKextInnerLock);
8352 	return;
8353 }
8354 
8355 /*********************************************************************
8356 * Do not call any function that takes sKextLock here!
8357 *********************************************************************/
8358 extern "C" {
8359 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
8360 IOReturn
8361 OSKextSystemSleepOrWake(UInt32 messageType)
8362 {
8363 	IORecursiveLockLock(sKextInnerLock);
8364 
8365 	/* If the system is going to sleep, cancel the reaper thread timer,
8366 	 * and note that we're in a sleep state in case it just fired but hasn't
8367 	 * taken the lock yet. If we are coming back from sleep, just
8368 	 * clear the sleep flag; IOService's normal operation will cause
8369 	 * unloads to be considered soon enough.
8370 	 */
8371 	if (messageType == kIOMessageSystemWillSleep) {
8372 		if (sUnloadCallout) {
8373 			thread_call_cancel(sUnloadCallout);
8374 		}
8375 		sSystemSleep = true;
8376 		AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
8377 	} else if (messageType == kIOMessageSystemHasPoweredOn) {
8378 		sSystemSleep = false;
8379 		clock_get_uptime(&sLastWakeTime);
8380 	}
8381 	IORecursiveLockUnlock(sKextInnerLock);
8382 
8383 	return kIOReturnSuccess;
8384 }
8385 };
8386 
8387 
8388 #if PRAGMA_MARK
8389 #pragma mark Prelinked Kernel
8390 #endif
8391 
8392 #ifdef CONFIG_KXLD
8393 /*********************************************************************
8394 * Do not access sConsiderUnloads... variables other than
8395 * sConsiderUnloadsExecuted in this function. They are guarded by a
8396 * different lock.
8397 *********************************************************************/
8398 /* static */
8399 void
8400 OSKext::considerRebuildOfPrelinkedKernel(void)
8401 {
8402 	static bool     requestedPrelink        = false;
8403 	OSReturn        checkResult             = kOSReturnError;
8404 	OSSharedPtr<OSDictionary>         prelinkRequest;
8405 	OSSharedPtr<OSCollectionIterator> kextIterator;
8406 	const OSSymbol * thisID                 = NULL;        // do not release
8407 	bool            doRebuild               = false;
8408 	AbsoluteTime    my_abstime;
8409 	UInt64          my_ns;
8410 	SInt32          delta_secs;
8411 
8412 	/* Only one auto rebuild per boot and only on boot from prelinked kernel */
8413 	if (requestedPrelink || !sPrelinkBoot) {
8414 		return;
8415 	}
8416 
8417 	/* no direct return from this point */
8418 	IORecursiveLockLock(sKextLock);
8419 
8420 	/* We need to wait for the IOKit daemon to get up and running with unloads already done
8421 	 * and any new startup kexts loaded.
8422 	 */
8423 	if (!sConsiderUnloadsExecuted ||
8424 	    !sDeferredLoadSucceeded) {
8425 		goto finish;
8426 	}
8427 
8428 	/* we really only care about boot / system start up related kexts so bail
8429 	 * if we're here after REBUILD_MAX_TIME.
8430 	 */
8431 	if (!_OSKextInPrelinkRebuildWindow()) {
8432 		OSKextLog(/* kext */ NULL,
8433 		    kOSKextLogArchiveFlag,
8434 		    "%s prebuild rebuild has expired",
8435 		    __FUNCTION__);
8436 		requestedPrelink = true;
8437 		goto finish;
8438 	}
8439 
8440 	/* we do not want to trigger a rebuild if we get here too close to waking
8441 	 * up.  (see radar 10233768)
8442 	 */
8443 	IORecursiveLockLock(sKextInnerLock);
8444 
8445 	clock_get_uptime(&my_abstime);
8446 	delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
8447 	if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
8448 		SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
8449 		absolutetime_to_nanoseconds(my_abstime, &my_ns);
8450 		delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
8451 	}
8452 	IORecursiveLockUnlock(sKextInnerLock);
8453 
8454 	if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
8455 		/* too close to time of last wake from sleep */
8456 		goto finish;
8457 	}
8458 	requestedPrelink = true;
8459 
8460 	/* Now it's time to see if we have a reason to rebuild.  We may have done
8461 	 * some loads and unloads but the kernel cache didn't actually change.
8462 	 * We will rebuild if any kext is not marked prelinked AND is not in our
8463 	 * list of prelinked kexts that got unloaded.  (see radar 9055303)
8464 	 */
8465 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
8466 	if (!kextIterator) {
8467 		goto finish;
8468 	}
8469 
8470 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
8471 		OSKext *    thisKext;        // do not release
8472 
8473 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
8474 		if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
8475 			continue;
8476 		}
8477 
8478 		if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) {
8479 			continue;
8480 		}
8481 		/* kext is loaded and was not in current kernel cache so let's rebuild
8482 		 */
8483 		doRebuild = true;
8484 		OSKextLog(/* kext */ NULL,
8485 		    kOSKextLogArchiveFlag,
8486 		    "considerRebuildOfPrelinkedKernel %s triggered rebuild",
8487 		    thisKext->bundleID->getCStringNoCopy());
8488 		break;
8489 	}
8490 	sUnloadedPrelinkedKexts->flushCollection();
8491 
8492 	if (!doRebuild) {
8493 		goto finish;
8494 	}
8495 
8496 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
8497 	    prelinkRequest);
8498 	if (checkResult != kOSReturnSuccess) {
8499 		goto finish;
8500 	}
8501 
8502 	if (!sKernelRequests->setObject(prelinkRequest.get())) {
8503 		goto finish;
8504 	}
8505 
8506 	OSKext::pingIOKitDaemon();
8507 
8508 finish:
8509 	IORecursiveLockUnlock(sKextLock);
8510 
8511 	return;
8512 }
8513 
8514 #else /* !CONFIG_KXLD */
8515 
8516 void
8517 OSKext::considerRebuildOfPrelinkedKernel(void)
8518 {
8519 	/* in a non-dynamic kext loading world, there is never a reason to rebuild */
8520 	return;
8521 }
8522 
8523 #endif /* CONFIG_KXLD */
8524 
8525 #if PRAGMA_MARK
8526 #pragma mark Dependencies
8527 #endif
8528 /*********************************************************************
8529 *********************************************************************/
8530 bool
8531 OSKext::resolveDependencies(
8532 	OSArray * loopStack)
8533 {
8534 	bool                   result                   = false;
8535 	OSSharedPtr<OSArray>   localLoopStack;
8536 	bool                   addedToLoopStack         = false;
8537 	OSDictionary         * libraries                = NULL;        // do not release
8538 	OSSharedPtr<OSCollectionIterator> libraryIterator;
8539 	OSString             * libraryID                = NULL;        // do not release
8540 	OSKext               * libraryKext              = NULL;        // do not release
8541 	bool                   hasRawKernelDependency   = false;
8542 	bool                   hasKernelDependency      = false;
8543 	bool                   hasKPIDependency         = false;
8544 	bool                   hasPrivateKPIDependency  = false;
8545 	unsigned int           count;
8546 
8547 #if CONFIG_KXLD
8548 	OSString             * infoString               = NULL;        // do not release
8549 	OSString             * readableString           = NULL;        // do not release
8550 #endif // CONFIG_KXLD
8551 
8552 	/* A kernel component will automatically have this flag set,
8553 	 * and a loaded kext should also have it set (as should all its
8554 	 * loaded dependencies).
8555 	 */
8556 	if (flags.hasAllDependencies) {
8557 		result = true;
8558 		goto finish;
8559 	}
8560 
8561 	/* Check for loops in the dependency graph.
8562 	 */
8563 	if (loopStack) {
8564 		if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
8565 			OSKextLog(this,
8566 			    kOSKextLogErrorLevel |
8567 			    kOSKextLogDependenciesFlag,
8568 			    "Kext %s has a dependency loop; can't resolve dependencies.",
8569 			    getIdentifierCString());
8570 			goto finish;
8571 		}
8572 	} else {
8573 		OSKextLog(this,
8574 		    kOSKextLogStepLevel |
8575 		    kOSKextLogDependenciesFlag,
8576 		    "Kext %s resolving dependencies.",
8577 		    getIdentifierCString());
8578 
8579 		localLoopStack = OSArray::withCapacity(6);         // any small capacity will do
8580 		if (!localLoopStack) {
8581 			OSKextLog(this,
8582 			    kOSKextLogErrorLevel |
8583 			    kOSKextLogDependenciesFlag,
8584 			    "Kext %s can't create bookkeeping stack to resolve dependencies.",
8585 			    getIdentifierCString());
8586 			goto finish;
8587 		}
8588 		loopStack = localLoopStack.get();
8589 	}
8590 	if (!loopStack->setObject(this)) {
8591 		OSKextLog(this,
8592 		    kOSKextLogErrorLevel |
8593 		    kOSKextLogDependenciesFlag,
8594 		    "Kext %s - internal error resolving dependencies.",
8595 		    getIdentifierCString());
8596 		goto finish;
8597 	}
8598 	addedToLoopStack = true;
8599 
8600 	/* Purge any existing kexts in the dependency list and start over.
8601 	 */
8602 	flushDependencies();
8603 	if (dependencies) {
8604 		OSKextLog(this,
8605 		    kOSKextLogErrorLevel |
8606 		    kOSKextLogDependenciesFlag,
8607 		    "Kext %s - internal error resolving dependencies.",
8608 		    getIdentifierCString());
8609 	}
8610 
8611 	libraries = OSDynamicCast(OSDictionary,
8612 	    getPropertyForHostArch(kOSBundleLibrariesKey));
8613 	if (libraries == NULL || libraries->getCount() == 0) {
8614 		OSKextLog(this,
8615 		    kOSKextLogErrorLevel |
8616 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8617 		    "Kext %s - can't resolve dependencies; %s missing/invalid type.",
8618 		    getIdentifierCString(), kOSBundleLibrariesKey);
8619 		goto finish;
8620 	}
8621 
8622 	/* Make a new array to hold the dependencies (flush freed the old one).
8623 	 */
8624 	dependencies = OSArray::withCapacity(libraries->getCount());
8625 	if (!dependencies) {
8626 		OSKextLog(this,
8627 		    kOSKextLogErrorLevel |
8628 		    kOSKextLogDependenciesFlag,
8629 		    "Kext %s - can't allocate dependencies array.",
8630 		    getIdentifierCString());
8631 		goto finish;
8632 	}
8633 
8634 	// xxx - compat: We used to add an implicit dependency on kernel 6.0
8635 	// xxx - compat: if none were declared.
8636 
8637 	libraryIterator = OSCollectionIterator::withCollection(libraries);
8638 	if (!libraryIterator) {
8639 		OSKextLog(this,
8640 		    kOSKextLogErrorLevel |
8641 		    kOSKextLogDependenciesFlag,
8642 		    "Kext %s - can't allocate dependencies iterator.",
8643 		    getIdentifierCString());
8644 		goto finish;
8645 	}
8646 
8647 	while ((libraryID = OSDynamicCast(OSString,
8648 	    libraryIterator->getNextObject()))) {
8649 		const char * library_id = libraryID->getCStringNoCopy();
8650 
8651 		OSString * libraryVersion = OSDynamicCast(OSString,
8652 		    libraries->getObject(libraryID));
8653 		if (libraryVersion == NULL) {
8654 			OSKextLog(this,
8655 			    kOSKextLogErrorLevel |
8656 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8657 			    "Kext %s - illegal type in OSBundleLibraries.",
8658 			    getIdentifierCString());
8659 			goto finish;
8660 		}
8661 
8662 		OSKextVersion libraryVers =
8663 		    OSKextParseVersionString(libraryVersion->getCStringNoCopy());
8664 		if (libraryVers == -1) {
8665 			OSKextLog(this,
8666 			    kOSKextLogErrorLevel |
8667 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8668 			    "Kext %s - invalid library version %s.",
8669 			    getIdentifierCString(),
8670 			    libraryVersion->getCStringNoCopy());
8671 			goto finish;
8672 		}
8673 
8674 		libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
8675 		if (libraryKext == NULL) {
8676 			OSKextLog(this,
8677 			    kOSKextLogErrorLevel |
8678 			    kOSKextLogDependenciesFlag,
8679 			    "Kext %s - library kext %s not found.",
8680 			    getIdentifierCString(), library_id);
8681 			goto finish;
8682 		}
8683 
8684 		if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
8685 			OSKextLog(this,
8686 			    kOSKextLogErrorLevel |
8687 			    kOSKextLogDependenciesFlag,
8688 			    "Kext %s - library kext %s not compatible "
8689 			    "with requested version %s.",
8690 			    getIdentifierCString(), library_id,
8691 			    libraryVersion->getCStringNoCopy());
8692 			goto finish;
8693 		}
8694 
8695 		/* If a nonprelinked library somehow got into the mix for a
8696 		 * prelinked kext, at any point in the chain, we must fail
8697 		 * because the prelinked relocs for the library will be all wrong.
8698 		 */
8699 		if (this->isPrelinked() &&
8700 		    libraryKext->declaresExecutable() &&
8701 		    !libraryKext->isPrelinked()) {
8702 			OSKextLog(this,
8703 			    kOSKextLogErrorLevel |
8704 			    kOSKextLogDependenciesFlag,
8705 			    "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
8706 			    getIdentifierCString(), library_id,
8707 			    libraryVersion->getCStringNoCopy());
8708 			goto finish;
8709 		}
8710 
8711 		if (!libraryKext->resolveDependencies(loopStack)) {
8712 			goto finish;
8713 		}
8714 
8715 		/* Add the library directly only if it has an executable to link.
8716 		 * Otherwise it's just used to collect other dependencies, so put
8717 		 * *its* dependencies on the list for this kext.
8718 		 */
8719 		// xxx - We are losing info here; would like to make fake entries or
8720 		// xxx - keep these in the dependency graph for loaded kexts.
8721 		// xxx - I really want to make kernel components not a special case!
8722 		if (libraryKext->declaresExecutable() ||
8723 		    libraryKext->isInterface()) {
8724 			if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
8725 				dependencies->setObject(libraryKext);
8726 
8727 				OSKextLog(this,
8728 				    kOSKextLogDetailLevel |
8729 				    kOSKextLogDependenciesFlag,
8730 				    "Kext %s added dependency %s.",
8731 				    getIdentifierCString(),
8732 				    libraryKext->getIdentifierCString());
8733 			}
8734 		} else {
8735 			int       numLibDependencies  = libraryKext->getNumDependencies();
8736 			OSArray * libraryDependencies = libraryKext->getDependencies();
8737 			int       index;
8738 
8739 			if (numLibDependencies) {
8740 				// xxx - this msg level should be 1 lower than the per-kext one
8741 				OSKextLog(this,
8742 				    kOSKextLogDetailLevel |
8743 				    kOSKextLogDependenciesFlag,
8744 				    "Kext %s pulling %d dependencies from codeless library %s.",
8745 				    getIdentifierCString(),
8746 				    numLibDependencies,
8747 				    libraryKext->getIdentifierCString());
8748 			}
8749 			for (index = 0; index < numLibDependencies; index++) {
8750 				OSKext * thisLibDependency = OSDynamicCast(OSKext,
8751 				    libraryDependencies->getObject(index));
8752 				if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
8753 					dependencies->setObject(thisLibDependency);
8754 					OSKextLog(this,
8755 					    kOSKextLogDetailLevel |
8756 					    kOSKextLogDependenciesFlag,
8757 					    "Kext %s added dependency %s from codeless library %s.",
8758 					    getIdentifierCString(),
8759 					    thisLibDependency->getIdentifierCString(),
8760 					    libraryKext->getIdentifierCString());
8761 				}
8762 			}
8763 		}
8764 
8765 		if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
8766 		    0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
8767 			hasRawKernelDependency = true;
8768 		} else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
8769 			hasKernelDependency = true;
8770 		} else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
8771 			hasKPIDependency = true;
8772 			if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
8773 				hasPrivateKPIDependency = true;
8774 			}
8775 		}
8776 	}
8777 
8778 	if (hasRawKernelDependency) {
8779 		OSKextLog(this,
8780 		    kOSKextLogErrorLevel |
8781 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8782 		    "Error - kext %s declares a dependency on %s, which is not permitted.",
8783 		    getIdentifierCString(), KERNEL_LIB);
8784 		goto finish;
8785 	}
8786 #if __LP64__
8787 	if (hasKernelDependency) {
8788 		OSKextLog(this,
8789 		    kOSKextLogErrorLevel |
8790 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8791 		    "Error - kext %s declares %s dependencies. "
8792 		    "Only %s* dependencies are supported for 64-bit kexts.",
8793 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
8794 		goto finish;
8795 	}
8796 	if (!hasKPIDependency) {
8797 		OSKextLog(this,
8798 		    kOSKextLogWarningLevel |
8799 		    kOSKextLogDependenciesFlag,
8800 		    "Warning - kext %s declares no %s* dependencies. "
8801 		    "If it uses any KPIs, the link may fail with undefined symbols.",
8802 		    getIdentifierCString(), KPI_LIB_PREFIX);
8803 	}
8804 #else /* __LP64__ */
8805 	// xxx - will change to flatly disallow "kernel" dependencies at some point
8806 	// xxx - is it invalid to do both "com.apple.kernel" and any
8807 	// xxx - "com.apple.kernel.*"?
8808 
8809 	if (hasKernelDependency && hasKPIDependency) {
8810 		OSKextLog(this,
8811 		    kOSKextLogWarningLevel |
8812 		    kOSKextLogDependenciesFlag,
8813 		    "Warning - kext %s has immediate dependencies on both "
8814 		    "%s* and %s* components; use only one style.",
8815 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
8816 	}
8817 
8818 	if (!hasKernelDependency && !hasKPIDependency) {
8819 		// xxx - do we want to use validation flag for these too?
8820 		OSKextLog(this,
8821 		    kOSKextLogWarningLevel |
8822 		    kOSKextLogDependenciesFlag,
8823 		    "Warning - %s declares no kernel dependencies; using %s.",
8824 		    getIdentifierCString(), KERNEL6_LIB);
8825 		OSKext * kernelKext = OSDynamicCast(OSKext,
8826 		    sKextsByID->getObject(KERNEL6_LIB));
8827 		if (kernelKext) {
8828 			dependencies->setObject(kernelKext);
8829 		} else {
8830 			OSKextLog(this,
8831 			    kOSKextLogErrorLevel |
8832 			    kOSKextLogDependenciesFlag,
8833 			    "Error - Library %s not found for %s.",
8834 			    KERNEL6_LIB, getIdentifierCString());
8835 		}
8836 	}
8837 
8838 	/* If the kext doesn't have a raw kernel or KPI dependency, then add all of
8839 	 * its indirect dependencies to simulate old-style linking.  XXX - Should
8840 	 * check for duplicates.
8841 	 */
8842 	if (!hasKPIDependency) {
8843 		unsigned int i;
8844 
8845 		flags.hasBleedthrough = true;
8846 
8847 		count = getNumDependencies();
8848 
8849 		/* We add to the dependencies array in this loop, but do not iterate
8850 		 * past its original count.
8851 		 */
8852 		for (i = 0; i < count; i++) {
8853 			OSKext * dependencyKext = OSDynamicCast(OSKext,
8854 			    dependencies->getObject(i));
8855 			dependencyKext->addBleedthroughDependencies(dependencies.get());
8856 		}
8857 	}
8858 #endif /* __LP64__ */
8859 
8860 #if CONFIG_KXLD
8861 	/*
8862 	 * If we're not dynamically linking kexts, then we don't need to check
8863 	 * copyright strings. The linker in user space has already done this.
8864 	 */
8865 	if (hasPrivateKPIDependency) {
8866 		bool hasApplePrefix = false;
8867 		bool infoCopyrightIsValid = false;
8868 		bool readableCopyrightIsValid = false;
8869 
8870 		hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
8871 		    APPLE_KEXT_PREFIX);
8872 
8873 		infoString = OSDynamicCast(OSString,
8874 		    getPropertyForHostArch("CFBundleGetInfoString"));
8875 		if (infoString) {
8876 			infoCopyrightIsValid =
8877 			    kxld_validate_copyright_string(infoString->getCStringNoCopy());
8878 		}
8879 
8880 		readableString = OSDynamicCast(OSString,
8881 		    getPropertyForHostArch("NSHumanReadableCopyright"));
8882 		if (readableString) {
8883 			readableCopyrightIsValid =
8884 			    kxld_validate_copyright_string(readableString->getCStringNoCopy());
8885 		}
8886 
8887 		if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
8888 			OSKextLog(this,
8889 			    kOSKextLogErrorLevel |
8890 			    kOSKextLogDependenciesFlag,
8891 			    "Error - kext %s declares a dependency on %s. "
8892 			    "Only Apple kexts may declare a dependency on %s.",
8893 			    getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
8894 			goto finish;
8895 		}
8896 	}
8897 #endif // CONFIG_KXLD
8898 
8899 	result = true;
8900 	flags.hasAllDependencies = 1;
8901 
8902 finish:
8903 
8904 	if (addedToLoopStack) {
8905 		count = loopStack->getCount();
8906 		if (count > 0 && (this == loopStack->getObject(count - 1))) {
8907 			loopStack->removeObject(count - 1);
8908 		} else {
8909 			OSKextLog(this,
8910 			    kOSKextLogErrorLevel |
8911 			    kOSKextLogDependenciesFlag,
8912 			    "Kext %s - internal error resolving dependencies.",
8913 			    getIdentifierCString());
8914 		}
8915 	}
8916 
8917 	if (result && localLoopStack) {
8918 		OSKextLog(this,
8919 		    kOSKextLogStepLevel |
8920 		    kOSKextLogDependenciesFlag,
8921 		    "Kext %s successfully resolved dependencies.",
8922 		    getIdentifierCString());
8923 	}
8924 
8925 	return result;
8926 }
8927 
8928 /*********************************************************************
8929 *********************************************************************/
8930 bool
8931 OSKext::addBleedthroughDependencies(OSArray * anArray)
8932 {
8933 	bool result = false;
8934 	unsigned int dependencyIndex, dependencyCount;
8935 
8936 	dependencyCount = getNumDependencies();
8937 
8938 	for (dependencyIndex = 0;
8939 	    dependencyIndex < dependencyCount;
8940 	    dependencyIndex++) {
8941 		OSKext * dependency = OSDynamicCast(OSKext,
8942 		    dependencies->getObject(dependencyIndex));
8943 		if (!dependency) {
8944 			OSKextLog(this,
8945 			    kOSKextLogErrorLevel |
8946 			    kOSKextLogDependenciesFlag,
8947 			    "Kext %s - internal error propagating compatibility dependencies.",
8948 			    getIdentifierCString());
8949 			goto finish;
8950 		}
8951 		if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
8952 			anArray->setObject(dependency);
8953 		}
8954 		dependency->addBleedthroughDependencies(anArray);
8955 	}
8956 
8957 	result = true;
8958 
8959 finish:
8960 	return result;
8961 }
8962 
8963 /*********************************************************************
8964 *********************************************************************/
8965 bool
8966 OSKext::flushDependencies(bool forceFlag)
8967 {
8968 	bool result = false;
8969 
8970 	/* Only clear the dependencies if the kext isn't loaded;
8971 	 * we need the info for loaded kexts to track references.
8972 	 */
8973 	if (!isLoaded() || forceFlag) {
8974 		if (dependencies) {
8975 			// xxx - check level
8976 			OSKextLog(this,
8977 			    kOSKextLogProgressLevel |
8978 			    kOSKextLogDependenciesFlag,
8979 			    "Kext %s flushing dependencies.",
8980 			    getIdentifierCString());
8981 			dependencies.reset();
8982 		}
8983 		if (!isKernelComponent()) {
8984 			flags.hasAllDependencies = 0;
8985 		}
8986 		result = true;
8987 	}
8988 
8989 	return result;
8990 }
8991 
8992 /*********************************************************************
8993 *********************************************************************/
8994 uint32_t
8995 OSKext::getNumDependencies(void)
8996 {
8997 	if (!dependencies) {
8998 		return 0;
8999 	}
9000 	return dependencies->getCount();
9001 }
9002 
9003 /*********************************************************************
9004 *********************************************************************/
9005 OSArray *
9006 OSKext::getDependencies(void)
9007 {
9008 	return dependencies.get();
9009 }
9010 
9011 bool
9012 OSKext::hasDependency(const OSSymbol * depID)
9013 {
9014 	bool result __block;
9015 
9016 	if (depID == getIdentifier()) {
9017 		return true;
9018 	}
9019 	if (!dependencies) {
9020 		return false;
9021 	}
9022 	result = false;
9023 	dependencies->iterateObjects(^bool (OSObject * obj) {
9024 		OSKext * kext;
9025 		kext = OSDynamicCast(OSKext, obj);
9026 		if (!kext) {
9027 		        return false;
9028 		}
9029 		result = (depID == kext->getIdentifier());
9030 		return result;
9031 	});
9032 	return result;
9033 }
9034 
9035 #if PRAGMA_MARK
9036 #pragma mark OSMetaClass Support
9037 #endif
9038 /*********************************************************************
9039 *********************************************************************/
9040 OSReturn
9041 OSKext::addClass(
9042 	OSMetaClass * aClass,
9043 	uint32_t      numClasses)
9044 {
9045 	OSReturn result = kOSMetaClassNoInsKModSet;
9046 
9047 	if (!metaClasses) {
9048 		metaClasses = OSSet::withCapacity(numClasses);
9049 		if (!metaClasses) {
9050 			goto finish;
9051 		}
9052 	}
9053 
9054 	if (metaClasses->containsObject(aClass)) {
9055 		OSKextLog(this,
9056 		    kOSKextLogWarningLevel |
9057 		    kOSKextLogLoadFlag,
9058 		    "Notice - kext %s has already registered class %s.",
9059 		    getIdentifierCString(),
9060 		    aClass->getClassName());
9061 		result = kOSReturnSuccess;
9062 		goto finish;
9063 	}
9064 
9065 	if (!metaClasses->setObject(aClass)) {
9066 		goto finish;
9067 	} else {
9068 		OSKextLog(this,
9069 		    kOSKextLogDetailLevel |
9070 		    kOSKextLogLoadFlag,
9071 		    "Kext %s registered class %s.",
9072 		    getIdentifierCString(),
9073 		    aClass->getClassName());
9074 	}
9075 
9076 	if (!flags.autounloadEnabled) {
9077 		const OSMetaClass * metaScan  = NULL;        // do not release
9078 
9079 		for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
9080 			if (metaScan == OSTypeID(IOService)) {
9081 				OSKextLog(this,
9082 				    kOSKextLogProgressLevel |
9083 				    kOSKextLogLoadFlag,
9084 				    "Kext %s has IOService subclass %s; enabling autounload.",
9085 				    getIdentifierCString(),
9086 				    aClass->getClassName());
9087 
9088 				flags.autounloadEnabled = (0 == flags.unloadUnsupported);
9089 				break;
9090 			}
9091 		}
9092 	}
9093 
9094 	notifyAddClassObservers(this, aClass, flags);
9095 
9096 	result = kOSReturnSuccess;
9097 
9098 finish:
9099 	if (result != kOSReturnSuccess) {
9100 		OSKextLog(this,
9101 		    kOSKextLogErrorLevel |
9102 		    kOSKextLogLoadFlag,
9103 		    "Kext %s failed to register class %s.",
9104 		    getIdentifierCString(),
9105 		    aClass->getClassName());
9106 	}
9107 
9108 	return result;
9109 }
9110 
9111 /*********************************************************************
9112 *********************************************************************/
9113 OSReturn
9114 OSKext::removeClass(
9115 	OSMetaClass * aClass)
9116 {
9117 	OSReturn result = kOSMetaClassNoKModSet;
9118 
9119 	if (!metaClasses) {
9120 		goto finish;
9121 	}
9122 
9123 	if (!metaClasses->containsObject(aClass)) {
9124 		OSKextLog(this,
9125 		    kOSKextLogWarningLevel |
9126 		    kOSKextLogLoadFlag,
9127 		    "Notice - kext %s asked to unregister unknown class %s.",
9128 		    getIdentifierCString(),
9129 		    aClass->getClassName());
9130 		result = kOSReturnSuccess;
9131 		goto finish;
9132 	}
9133 
9134 	OSKextLog(this,
9135 	    kOSKextLogDetailLevel |
9136 	    kOSKextLogLoadFlag,
9137 	    "Kext %s unregistering class %s.",
9138 	    getIdentifierCString(),
9139 	    aClass->getClassName());
9140 
9141 	metaClasses->removeObject(aClass);
9142 
9143 	notifyRemoveClassObservers(this, aClass, flags);
9144 
9145 	result = kOSReturnSuccess;
9146 
9147 finish:
9148 	if (result != kOSReturnSuccess) {
9149 		OSKextLog(this,
9150 		    kOSKextLogErrorLevel |
9151 		    kOSKextLogLoadFlag,
9152 		    "Failed to unregister kext %s class %s.",
9153 		    getIdentifierCString(),
9154 		    aClass->getClassName());
9155 	}
9156 	return result;
9157 }
9158 
9159 /*********************************************************************
9160 *********************************************************************/
9161 OSSet *
9162 OSKext::getMetaClasses(void)
9163 {
9164 	return metaClasses.get();
9165 }
9166 
9167 /*********************************************************************
9168 *********************************************************************/
9169 bool
9170 OSKext::hasOSMetaClassInstances(void)
9171 {
9172 	bool                   result        = false;
9173 	OSSharedPtr<OSCollectionIterator> classIterator;
9174 	OSMetaClass          * checkClass    = NULL;        // do not release
9175 
9176 	if (!metaClasses) {
9177 		goto finish;
9178 	}
9179 
9180 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9181 	if (!classIterator) {
9182 		// xxx - log alloc failure?
9183 		goto finish;
9184 	}
9185 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9186 		if (checkClass->getInstanceCount()) {
9187 			result = true;
9188 			goto finish;
9189 		}
9190 	}
9191 
9192 finish:
9193 	return result;
9194 }
9195 
9196 /*********************************************************************
9197 *********************************************************************/
9198 /* static */
9199 void
9200 OSKext::reportOSMetaClassInstances(
9201 	const char     * kextIdentifier,
9202 	OSKextLogSpec    msgLogSpec)
9203 {
9204 	OSSharedPtr<OSKext> theKext;
9205 
9206 	theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
9207 	if (!theKext) {
9208 		goto finish;
9209 	}
9210 
9211 	theKext->reportOSMetaClassInstances(msgLogSpec);
9212 finish:
9213 	return;
9214 }
9215 
9216 /*********************************************************************
9217 *********************************************************************/
9218 void
9219 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
9220 {
9221 	OSSharedPtr<OSCollectionIterator> classIterator;
9222 	OSMetaClass          * checkClass    = NULL;        // do not release
9223 
9224 	if (!metaClasses) {
9225 		goto finish;
9226 	}
9227 
9228 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9229 	if (!classIterator) {
9230 		goto finish;
9231 	}
9232 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9233 		if (checkClass->getInstanceCount()) {
9234 			OSKextLog(this,
9235 			    msgLogSpec,
9236 			    "    Kext %s class %s has %d instance%s.",
9237 			    getIdentifierCString(),
9238 			    checkClass->getClassName(),
9239 			    checkClass->getInstanceCount(),
9240 			    checkClass->getInstanceCount() == 1 ? "" : "s");
9241 		}
9242 	}
9243 
9244 finish:
9245 	return;
9246 }
9247 
9248 #if PRAGMA_MARK
9249 #pragma mark User-Space Requests
9250 #endif
9251 
9252 static kern_return_t
9253 patchDextLaunchRequests(task_t calling_task, OSArray *requests)
9254 {
9255 	OSReturn result = kOSReturnSuccess;
9256 	for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) {
9257 		OSDictionary * request = NULL;         //do not release
9258 		IOUserServerCheckInToken * token = NULL;         //do not release
9259 		OSString * requestPredicate = NULL;         //do not release
9260 		OSSharedPtr<OSNumber> portNameNumber;
9261 		mach_port_name_t portName = 0;
9262 		request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex));
9263 		if (!request) {
9264 			OSKextLog(/* kext */ NULL,
9265 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9266 			    "Elements of request should be of type OSDictionary");
9267 			result = kOSKextReturnInternalError;
9268 			goto finish;
9269 		}
9270 		requestPredicate = _OSKextGetRequestPredicate(request);
9271 		if (!requestPredicate) {
9272 			OSKextLog(/* kext */ NULL,
9273 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9274 			    "Failed to get request predicate");
9275 			result = kOSKextReturnInternalError;
9276 			goto finish;
9277 		}
9278 		// is this a dext launch?
9279 		if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) {
9280 			token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken));
9281 			if (!token) {
9282 				OSKextLog(/* kext */ NULL,
9283 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9284 				    "Could not find a IOUserServerCheckInToken in daemon launch request.");
9285 				result = kOSKextReturnInternalError;
9286 				goto finish;
9287 			}
9288 			portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT);
9289 			if (portName == 0 || portName == MACH_PORT_DEAD) {
9290 				OSKextLog(/* kext */ NULL,
9291 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9292 				    "Could not create send right for object.");
9293 				result = kOSKextReturnInternalError;
9294 				goto finish;
9295 			}
9296 			// Store the mach port name as a OSNumber
9297 			portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName));
9298 			if (!portNameNumber) {
9299 				OSKextLog(/* kext */ NULL,
9300 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9301 				    "Could not create OSNumber object.");
9302 				result = kOSKextReturnNoMemory;
9303 				goto finish;
9304 			}
9305 			if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) {
9306 				OSKextLog(/* kext */ NULL,
9307 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9308 				    "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken);
9309 				result = kOSKextReturnNoMemory;
9310 				goto finish;
9311 			}
9312 		}
9313 finish:
9314 		if (result != kOSReturnSuccess) {
9315 			break;
9316 		}
9317 	}
9318 	return result;
9319 }
9320 
9321 /*********************************************************************
9322 * XXX - this function is a big ugly mess
9323 *********************************************************************/
9324 /* static */
9325 OSReturn
9326 OSKext::handleRequest(
9327 	host_priv_t     hostPriv,
9328 	OSKextLogSpec   clientLogFilter,
9329 	char          * requestBuffer,
9330 	uint32_t        requestLength,
9331 	char         ** responseOut,
9332 	uint32_t      * responseLengthOut,
9333 	char         ** logInfoOut,
9334 	uint32_t      * logInfoLengthOut)
9335 {
9336 	OSReturn       result             = kOSReturnError;
9337 	kern_return_t  kmem_result        = KERN_FAILURE;
9338 
9339 	char         * response           = NULL;        // returned by reference
9340 	uint32_t       responseLength     = 0;
9341 
9342 	bool           taskCanManageAllKCs   = false;
9343 	bool           taskOnlyManagesBootKC = false;
9344 
9345 	OSSharedPtr<OSObject>     parsedXML;
9346 	OSDictionary            * requestDict    = NULL;        // do not release
9347 	OSSharedPtr<OSString>     errorString;
9348 
9349 	OSSharedPtr<OSObject>     responseObject;
9350 
9351 	OSSharedPtr<OSSerialize>  serializer;
9352 
9353 	OSSharedPtr<OSArray>      logInfoArray;
9354 
9355 	OSString     * predicate          = NULL;        // do not release
9356 	OSString     * kextIdentifier     = NULL;        // do not release
9357 	OSArray      * kextIdentifiers    = NULL;        // do not release
9358 	OSKext       * theKext            = NULL;        // do not release
9359 	OSBoolean    * boolArg            = NULL;        // do not release
9360 
9361 	IORecursiveLockLock(sKextLock);
9362 
9363 	if (responseOut) {
9364 		*responseOut = NULL;
9365 		*responseLengthOut = 0;
9366 	}
9367 	if (logInfoOut) {
9368 		*logInfoOut = NULL;
9369 		*logInfoLengthOut = 0;
9370 	}
9371 
9372 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
9373 
9374 	/* XML must be nul-terminated.
9375 	 */
9376 	if (requestBuffer[requestLength - 1] != '\0') {
9377 		OSKextLog(/* kext */ NULL,
9378 		    kOSKextLogErrorLevel |
9379 		    kOSKextLogIPCFlag,
9380 		    "Invalid request from user space (not nul-terminated).");
9381 		result = kOSKextReturnBadData;
9382 		goto finish;
9383 	}
9384 	parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString);
9385 	if (parsedXML) {
9386 		requestDict = OSDynamicCast(OSDictionary, parsedXML.get());
9387 	}
9388 	if (!requestDict) {
9389 		const char * errorCString = "(unknown error)";
9390 
9391 		if (errorString && errorString->getCStringNoCopy()) {
9392 			errorCString = errorString->getCStringNoCopy();
9393 		} else if (parsedXML) {
9394 			errorCString = "not a dictionary";
9395 		}
9396 		OSKextLog(/* kext */ NULL,
9397 		    kOSKextLogErrorLevel |
9398 		    kOSKextLogIPCFlag,
9399 		    "Error unserializing request from user space: %s.",
9400 		    errorCString);
9401 		result = kOSKextReturnSerialization;
9402 		goto finish;
9403 	}
9404 
9405 	predicate = _OSKextGetRequestPredicate(requestDict);
9406 	if (!predicate) {
9407 		OSKextLog(/* kext */ NULL,
9408 		    kOSKextLogErrorLevel |
9409 		    kOSKextLogIPCFlag,
9410 		    "Recieved kext request from user space with no predicate.");
9411 		result = kOSKextReturnInvalidArgument;
9412 		goto finish;
9413 	}
9414 
9415 	OSKextLog(/* kext */ NULL,
9416 	    kOSKextLogDebugLevel |
9417 	    kOSKextLogIPCFlag,
9418 	    "Received '%s' request from user space.",
9419 	    predicate->getCStringNoCopy());
9420 
9421 	/*
9422 	 * All management of file sets requires an entitlement
9423 	 */
9424 	result = kOSKextReturnNotPrivileged;
9425 	if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
9426 	    predicate->isEqualTo(kKextRequestPredicateStart) ||
9427 	    predicate->isEqualTo(kKextRequestPredicateStop) ||
9428 	    predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
9429 	    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
9430 	    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
9431 	    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
9432 	    predicate->isEqualTo(kKextRequestPredicateLoadFromKC) ||
9433 	    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
9434 	    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
9435 	    predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
9436 		if (hostPriv == HOST_PRIV_NULL) {
9437 			OSKextLog(/* kext */ NULL,
9438 			    kOSKextLogErrorLevel |
9439 			    kOSKextLogIPCFlag,
9440 			    "Access Failure - must be root user.");
9441 			goto finish;
9442 		}
9443 		taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE;
9444 		taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE;
9445 
9446 		if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) {
9447 			OSKextLog(/* kext */ NULL,
9448 			    kOSKextLogErrorLevel |
9449 			    kOSKextLogIPCFlag,
9450 			    "Access Failure - client not entitled to manage file sets.");
9451 			goto finish;
9452 		}
9453 
9454 		/*
9455 		 * The OnlyBootKC entitlement restricts the
9456 		 * collection-management entitlement to only managing kexts in
9457 		 * the BootKC. All other predicates that alter global state or
9458 		 * add new KCs are disallowed.
9459 		 */
9460 		if (taskOnlyManagesBootKC &&
9461 		    (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
9462 		    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
9463 		    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
9464 		    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
9465 		    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
9466 		    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
9467 		    predicate->isEqualTo(kKextRequestPredicateDaemonReady))) {
9468 			OSKextLog(/* kext */ NULL,
9469 			    kOSKextLogErrorLevel |
9470 			    kOSKextLogIPCFlag,
9471 			    "Access Failure - client not entitled to manage non-primary KCs");
9472 			goto finish;
9473 		}
9474 
9475 		/*
9476 		 * If we get here, then the process either has the full KC
9477 		 * management entitlement, or it has the BootKC-only
9478 		 * entitlement and the request is about the BootKC.
9479 		 */
9480 	}
9481 
9482 	/* Get common args in anticipation of use.
9483 	 */
9484 	kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
9485 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
9486 	kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
9487 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
9488 	if (kextIdentifier) {
9489 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
9490 	}
9491 	boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
9492 		    requestDict, kKextRequestArgumentValueKey));
9493 
9494 	if (taskOnlyManagesBootKC &&
9495 	    theKext &&
9496 	    theKext->isInFileset() &&
9497 	    theKext->kc_type != KCKindPrimary) {
9498 		OSKextLog(/* kext */ NULL,
9499 		    kOSKextLogErrorLevel |
9500 		    kOSKextLogIPCFlag,
9501 		    "Access Failure - client not entitled to manage kext in non-primary KC");
9502 		result = kOSKextReturnNotPrivileged;
9503 		goto finish;
9504 	}
9505 
9506 	result = kOSKextReturnInvalidArgument;
9507 
9508 	if (predicate->isEqualTo(kKextRequestPredicateStart)) {
9509 		if (!kextIdentifier) {
9510 			OSKextLog(/* kext */ NULL,
9511 			    kOSKextLogErrorLevel |
9512 			    kOSKextLogIPCFlag,
9513 			    "Invalid arguments to kext start request.");
9514 		} else if (!theKext) {
9515 			OSKextLog(/* kext */ NULL,
9516 			    kOSKextLogErrorLevel |
9517 			    kOSKextLogIPCFlag,
9518 			    "Kext %s not found for start request.",
9519 			    kextIdentifier->getCStringNoCopy());
9520 			result = kOSKextReturnNotFound;
9521 		} else {
9522 			result = theKext->start();
9523 		}
9524 	} else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
9525 		if (!kextIdentifier) {
9526 			OSKextLog(/* kext */ NULL,
9527 			    kOSKextLogErrorLevel |
9528 			    kOSKextLogIPCFlag,
9529 			    "Invalid arguments to kext stop request.");
9530 		} else if (!theKext) {
9531 			OSKextLog(/* kext */ NULL,
9532 			    kOSKextLogErrorLevel |
9533 			    kOSKextLogIPCFlag,
9534 			    "Kext %s not found for stop request.",
9535 			    kextIdentifier->getCStringNoCopy());
9536 			result = kOSKextReturnNotFound;
9537 		} else {
9538 			result = theKext->stop();
9539 		}
9540 	} else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) {
9541 		result = OSKext::setMissingAuxKCBundles(requestDict);
9542 	} else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) {
9543 		if (!kextIdentifier) {
9544 			OSKextLog(/* kext */ NULL,
9545 			    kOSKextLogErrorLevel |
9546 			    kOSKextLogIPCFlag,
9547 			    "Invalid arguments to AuxKC Bundle Available request.");
9548 		} else {
9549 			result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict);
9550 		}
9551 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) {
9552 		if (!kextIdentifier) {
9553 			OSKextLog(/* kext */ NULL,
9554 			    kOSKextLogErrorLevel |
9555 			    kOSKextLogIPCFlag,
9556 			    "Invalid arguments to kext load from KC request.");
9557 		} else if (!theKext) {
9558 			OSKextLog(/* kext */ NULL,
9559 			    kOSKextLogErrorLevel |
9560 			    kOSKextLogIPCFlag,
9561 			    "Kext %s not found for load from KC request.",
9562 			    kextIdentifier->getCStringNoCopy());
9563 			result = kOSKextReturnNotFound;
9564 		} else if (!theKext->isInFileset()) {
9565 			OSKextLog(/* kext */ NULL,
9566 			    kOSKextLogErrorLevel |
9567 			    kOSKextLogIPCFlag,
9568 			    "Kext %s does not exist in a KC: refusing to load.",
9569 			    kextIdentifier->getCStringNoCopy());
9570 			result = kOSKextReturnNotLoadable;
9571 		} else {
9572 			result = OSKext::loadKextFromKC(theKext, requestDict);
9573 		}
9574 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) {
9575 		if (!kextIdentifier) {
9576 			OSKextLog(/* kext */ NULL,
9577 			    kOSKextLogErrorLevel |
9578 			    kOSKextLogIPCFlag,
9579 			    "Invalid arguments to codeless kext load interface (missing identifier).");
9580 		} else {
9581 			result = OSKext::loadCodelessKext(kextIdentifier, requestDict);
9582 		}
9583 	} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
9584 		if (!kextIdentifier) {
9585 			OSKextLog(/* kext */ NULL,
9586 			    kOSKextLogErrorLevel |
9587 			    kOSKextLogIPCFlag,
9588 			    "Invalid arguments to kext unload request.");
9589 		} else if (!theKext) {
9590 			OSKextLog(/* kext */ NULL,
9591 			    kOSKextLogErrorLevel |
9592 			    kOSKextLogIPCFlag,
9593 			    "Kext %s not found for unload request.",
9594 			    kextIdentifier->getCStringNoCopy());
9595 			result = kOSKextReturnNotFound;
9596 		} else {
9597 			OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
9598 			    _OSKextGetRequestArgument(requestDict,
9599 			    kKextRequestArgumentTerminateIOServicesKey));
9600 			result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
9601 		}
9602 	} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
9603 		result = OSKext::dispatchResource(requestDict);
9604 	} else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
9605 		OSNumber     *lookupNum   = NULL;
9606 		lookupNum = OSDynamicCast(OSNumber,
9607 		    _OSKextGetRequestArgument(requestDict,
9608 		    kKextRequestArgumentLookupAddressKey));
9609 
9610 		responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
9611 		if (responseObject) {
9612 			result = kOSReturnSuccess;
9613 		} else {
9614 			goto finish;
9615 		}
9616 	} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
9617 	    predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) ||
9618 	    predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
9619 		OSBoolean    * delayAutounloadBool = NULL;
9620 		OSObject     * infoKeysRaw         = NULL;
9621 		OSArray      * infoKeys            = NULL;
9622 		uint32_t       infoKeysCount       = 0;
9623 
9624 		delayAutounloadBool = OSDynamicCast(OSBoolean,
9625 		    _OSKextGetRequestArgument(requestDict,
9626 		    kKextRequestArgumentDelayAutounloadKey));
9627 
9628 		/* If asked to delay autounload, reset the timer if it's currently set.
9629 		 * (That is, don't schedule an unload if one isn't already pending.
9630 		 */
9631 		if (delayAutounloadBool == kOSBooleanTrue) {
9632 			OSKext::considerUnloads(/* rescheduleOnly? */ true);
9633 		}
9634 
9635 		infoKeysRaw = _OSKextGetRequestArgument(requestDict,
9636 		    kKextRequestArgumentInfoKeysKey);
9637 		infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
9638 		if (infoKeysRaw && !infoKeys) {
9639 			OSKextLog(/* kext */ NULL,
9640 			    kOSKextLogErrorLevel |
9641 			    kOSKextLogIPCFlag,
9642 			    "Invalid arguments to kext info request.");
9643 			goto finish;
9644 		}
9645 
9646 		if (infoKeys) {
9647 			infoKeysCount = infoKeys->getCount();
9648 			for (uint32_t i = 0; i < infoKeysCount; i++) {
9649 				if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
9650 					OSKextLog(/* kext */ NULL,
9651 					    kOSKextLogErrorLevel |
9652 					    kOSKextLogIPCFlag,
9653 					    "Invalid arguments to kext info request.");
9654 					goto finish;
9655 				}
9656 			}
9657 		}
9658 
9659 		if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
9660 			responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
9661 		} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
9662 			responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
9663 		} else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
9664 			responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys);
9665 		}
9666 
9667 		if (!responseObject) {
9668 			result = kOSKextReturnInternalError;
9669 		} else {
9670 			OSKextLog(/* kext */ NULL,
9671 			    kOSKextLogDebugLevel |
9672 			    kOSKextLogIPCFlag,
9673 			    "Returning loaded kext info.");
9674 			result = kOSReturnSuccess;
9675 		}
9676 	} else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
9677 		/* Hand the current sKernelRequests array to the caller
9678 		 * (who must release it), and make a new one.
9679 		 */
9680 		responseObject = os::move(sKernelRequests);
9681 		sKernelRequests = OSArray::withCapacity(0);
9682 		sPostedKextLoadIdentifiers->flushCollection();
9683 		OSKextLog(/* kext */ NULL,
9684 		    kOSKextLogDebugLevel |
9685 		    kOSKextLogIPCFlag,
9686 		    "Returning kernel requests.");
9687 		result = kOSReturnSuccess;
9688 	} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
9689 		/* Return the set of all requested bundle identifiers */
9690 		responseObject = sAllKextLoadIdentifiers;
9691 		OSKextLog(/* kext */ NULL,
9692 		    kOSKextLogDebugLevel |
9693 		    kOSKextLogIPCFlag,
9694 		    "Returning load requests.");
9695 		result = kOSReturnSuccess;
9696 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) {
9697 		printf("KextLog: Loading FileSet KC(s)\n");
9698 		result = OSKext::loadFileSetKexts(requestDict);
9699 	} else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
9700 		printf("KextLog: " kIOKitDaemonName " is %s\n", sIOKitDaemonActive ? "active" : "not active");
9701 		result = (sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot) ? kOSReturnSuccess : kIOReturnNotReady;
9702 	} else {
9703 		OSKextLog(/* kext */ NULL,
9704 		    kOSKextLogDebugLevel |
9705 		    kOSKextLogIPCFlag,
9706 		    "Received '%s' invalid request from user space.",
9707 		    predicate->getCStringNoCopy());
9708 		goto finish;
9709 	}
9710 
9711 	/**********
9712 	 * Now we have handle the request, or not. Gather up the response & logging
9713 	 * info to ship to user space.
9714 	 *********/
9715 
9716 	/* Note: Nothing in OSKext is supposed to retain requestDict,
9717 	 * but you never know....
9718 	 */
9719 	if (requestDict->getRetainCount() > 1) {
9720 		OSKextLog(/* kext */ NULL,
9721 		    kOSKextLogWarningLevel |
9722 		    kOSKextLogIPCFlag,
9723 		    "Request from user space still retained by a kext; "
9724 		    "probable memory leak.");
9725 	}
9726 
9727 	if (responseOut && responseObject) {
9728 		serializer = OSSerialize::withCapacity(0);
9729 		if (!serializer) {
9730 			result = kOSKextReturnNoMemory;
9731 			goto finish;
9732 		}
9733 		/*
9734 		 * Before serializing the kernel requests, patch the dext launch requests so
9735 		 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the
9736 		 * IOUserServerCheckInToken kernel object.
9737 		 */
9738 		if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
9739 			OSArray * requests = OSDynamicCast(OSArray, responseObject.get());
9740 			task_t calling_task = current_task();
9741 			if (!requests) {
9742 				OSKextLog(/* kext */ NULL,
9743 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9744 				    "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests);
9745 				result = kOSKextReturnInternalError;
9746 				goto finish;
9747 			}
9748 			result = patchDextLaunchRequests(calling_task, requests);
9749 			if (result != kOSReturnSuccess) {
9750 				OSKextLog(/* kext */ NULL,
9751 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9752 				    "Failed to patch dext launch requests.");
9753 				goto finish;
9754 			}
9755 		}
9756 
9757 		if (!responseObject->serialize(serializer.get())) {
9758 			OSKextLog(/* kext */ NULL,
9759 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9760 			    "Failed to serialize response to request from user space.");
9761 			result = kOSKextReturnSerialization;
9762 			goto finish;
9763 		}
9764 
9765 		response = (char *)serializer->text();
9766 		responseLength = serializer->getLength();
9767 	}
9768 
9769 	if (responseOut && response) {
9770 		char * buffer;
9771 
9772 		/* This kmem_alloc sets the return value of the function.
9773 		 */
9774 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
9775 		    round_page(responseLength), VM_KERN_MEMORY_OSKEXT);
9776 		if (kmem_result != KERN_SUCCESS) {
9777 			OSKextLog(/* kext */ NULL,
9778 			    kOSKextLogErrorLevel |
9779 			    kOSKextLogIPCFlag,
9780 			    "Failed to copy response to request from user space.");
9781 			result = kmem_result;
9782 			goto finish;
9783 		} else {
9784 			/* 11981737 - clear uninitialized data in last page */
9785 			bzero((void *)(buffer + responseLength),
9786 			    (round_page(responseLength) - responseLength));
9787 			memcpy(buffer, response, responseLength);
9788 			*responseOut = buffer;
9789 			*responseLengthOut = responseLength;
9790 		}
9791 	}
9792 
9793 finish:
9794 
9795 	/* Gather up the collected log messages for user space. Any messages
9796 	 * messages past this call will not make it up as log messages but
9797 	 * will be in the system log. Note that we ignore the return of the
9798 	 * serialize; it has no bearing on the operation at hand even if we
9799 	 * fail to get the log messages.
9800 	 */
9801 	logInfoArray = OSKext::clearUserSpaceLogFilter();
9802 
9803 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
9804 		(void)OSKext::serializeLogInfo(logInfoArray.get(),
9805 		    logInfoOut, logInfoLengthOut);
9806 	}
9807 
9808 	IORecursiveLockUnlock(sKextLock);
9809 
9810 	return result;
9811 }
9812 
9813 #if PRAGMA_MARK
9814 #pragma mark Linked Kext Collection Support
9815 #endif
9816 
9817 static int
9818 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount)
9819 {
9820 	for (int i = 0; i < segCount; i++) {
9821 		vm_offset_t segStart = segAddrs[i];
9822 		vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i];
9823 
9824 		if (theAddr >= segStart && theAddr < segEnd) {
9825 			return i;
9826 		}
9827 	}
9828 	return -1;
9829 }
9830 
9831 static void
9832 __slideOldKaslrOffsets(kernel_mach_header_t *mh,
9833     kernel_segment_command_t *kextTextSeg,
9834     OSData *kaslrOffsets)
9835 {
9836 	static const char *plk_segNames[] = {
9837 		"__TEXT",
9838 		"__TEXT_EXEC",
9839 		"__DATA",
9840 		"__DATA_CONST",
9841 		"__LINKEDIT",
9842 		"__PRELINK_TEXT",
9843 		"__PLK_TEXT_EXEC",
9844 		"__PRELINK_DATA",
9845 		"__PLK_DATA_CONST",
9846 		"__PLK_LLVM_COV",
9847 		"__PLK_LINKEDIT",
9848 		"__PRELINK_INFO"
9849 	};
9850 	static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0]));
9851 
9852 	unsigned long plk_segSizes[num_plk_seg];
9853 	vm_offset_t   plk_segAddrs[num_plk_seg];
9854 
9855 	for (size_t i = 0; i < num_plk_seg; i++) {
9856 		plk_segSizes[i] = 0;
9857 		plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]);
9858 	}
9859 
9860 	uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr;
9861 
9862 	int slidKextAddrCount = 0;
9863 	int badSlideAddr = 0;
9864 	int badSlideTarget = 0;
9865 
9866 	struct kaslrPackedOffsets {
9867 		uint32_t    count;          /* number of offsets */
9868 		uint32_t    offsetsArray[];        /* offsets to slide */
9869 	};
9870 	const struct kaslrPackedOffsets *myOffsets = NULL;
9871 	myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy();
9872 
9873 	for (uint32_t j = 0; j < myOffsets->count; j++) {
9874 		uint64_t   slideOffset = (uint64_t)myOffsets->offsetsArray[j];
9875 		vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset);
9876 		int        slideAddrSegIndex = -1;
9877 		int        addrToSlideSegIndex = -1;
9878 
9879 		slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
9880 		if (slideAddrSegIndex >= 0) {
9881 			addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
9882 			if (addrToSlideSegIndex < 0) {
9883 				badSlideTarget++;
9884 				continue;
9885 			}
9886 		} else {
9887 			badSlideAddr++;
9888 			continue;
9889 		}
9890 
9891 		slidKextAddrCount++;
9892 		*slideAddr = ml_static_slide(*slideAddr);
9893 	}         // for ...
9894 }
9895 
9896 
9897 
9898 /********************************************************************
9899 * addKextsFromKextCollection
9900 *
9901 * Input: MachO header of kext collection. The MachO is assumed to
9902 *        have a section named 'info_seg_name,info_sect_name' that
9903 *        contains a serialized XML info dictionary. This dictionary
9904 *        contains a UUID, possibly a set of relocations (for older
9905 *        kxld-built binaries), and an array of kext personalities.
9906 *
9907 ********************************************************************/
9908 bool
9909 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
9910     OSDictionary *infoDict, const char *text_seg_name,
9911     OSData **kcUUID, kc_kind_t type)
9912 {
9913 	bool result = false;
9914 
9915 	OSArray *kextArray     = NULL;        // do not release
9916 	OSData *infoDictKCUUID = NULL;         // do not release
9917 	OSData *kaslrOffsets   = NULL;        // do not release
9918 
9919 	IORegistryEntry *registryRoot = NULL;         // do not release
9920 	OSSharedPtr<OSNumber> kcKextCount;
9921 
9922 	/* extract the KC UUID from the dictionary */
9923 	infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
9924 	if (infoDictKCUUID) {
9925 		if (infoDictKCUUID->getLength() != sizeof(uuid_t)) {
9926 			panic("kcUUID length is %d, expected %lu",
9927 			    infoDictKCUUID->getLength(), sizeof(uuid_t));
9928 		}
9929 	}
9930 
9931 	/* locate the array of kext dictionaries */
9932 	kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey));
9933 	if (!kextArray) {
9934 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9935 		    "The given KC has no kext info dictionaries");
9936 		goto finish;
9937 	}
9938 
9939 	/*
9940 	 * old-style KASLR offsets may be present in the info dictionary. If
9941 	 * we find them, use them and eventually slide them.
9942 	 */
9943 	kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey));
9944 
9945 	/*
9946 	 * Before processing any kexts, locate the special kext bundle which
9947 	 * contains a list of kexts that we are to prevent from loading.
9948 	 */
9949 	createExcludeListFromPrelinkInfo(kextArray);
9950 
9951 	/*
9952 	 * Create OSKext objects for each kext we find in the array of kext
9953 	 * info plist dictionaries.
9954 	 */
9955 	for (int i = 0; i < (int)kextArray->getCount(); ++i) {
9956 		OSDictionary *kextDict = NULL;
9957 		kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i));
9958 		if (!kextDict) {
9959 			OSKextLog(/* kext */ NULL,
9960 			    kOSKextLogErrorLevel |
9961 			    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
9962 			    "Kext info dictionary for kext #%d isn't a dictionary?", i);
9963 			continue;
9964 		}
9965 
9966 		/*
9967 		 * Create the kext for the entry, then release it, because the
9968 		 * kext system keeps a reference around until the kext is
9969 		 * explicitly removed.  Any creation/registration failures are
9970 		 * already logged for us.
9971 		 */
9972 		withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type);
9973 	}
9974 
9975 	/*
9976 	 * slide old-style kxld relocations
9977 	 * NOTE: this is still used on embedded KCs built with kcgen
9978 	 * TODO: Remove this once we use the new kext linker everywhere!
9979 	 */
9980 	if (kaslrOffsets && vm_kernel_slide > 0) {
9981 		kernel_segment_command_t *text_segment = NULL;
9982 		text_segment = getsegbynamefromheader(mh, text_seg_name);
9983 		if (!text_segment) {
9984 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9985 			    "Can't find a TEXT segment named '%s' in macho header", text_seg_name);
9986 			goto finish;
9987 		}
9988 
9989 		__slideOldKaslrOffsets(mh, text_segment, kaslrOffsets);
9990 		/* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */
9991 		setAllVMAttributes();
9992 	}
9993 
9994 	/* Store the number of prelinked kexts in the registry so we can tell
9995 	 * when the system has been started from a prelinked kernel.
9996 	 */
9997 	registryRoot = IORegistryEntry::getRegistryRoot();
9998 	assert(registryRoot);
9999 
10000 	kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t));
10001 	assert(kcKextCount);
10002 	if (kcKextCount) {
10003 		OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey);
10004 		OSNumber *num;
10005 		num = OSDynamicCast(OSNumber, prop.get());
10006 		if (num) {
10007 			kcKextCount->addValue(num->unsigned64BitValue());
10008 		}
10009 		registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get());
10010 	}
10011 
10012 	OSKextLog(/* kext */ NULL,
10013 	    kOSKextLogProgressLevel |
10014 	    kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
10015 	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10016 	    "%u prelinked kexts", infoDict->getCount());
10017 
10018 
10019 	if (kcUUID && infoDictKCUUID) {
10020 		*kcUUID = OSData::withData(infoDictKCUUID).detach();
10021 	}
10022 
10023 	result = true;
10024 
10025 finish:
10026 	return result;
10027 }
10028 
10029 bool
10030 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10031     OSDictionary *infoDict, const char *text_seg_name,
10032     OSSharedPtr<OSData> &kcUUID, kc_kind_t type)
10033 {
10034 	OSData  *result = NULL;
10035 	bool success = addKextsFromKextCollection(mh,
10036 	    infoDict,
10037 	    text_seg_name,
10038 	    &result,
10039 	    type);
10040 	if (success) {
10041 		kcUUID.reset(result, OSNoRetain);
10042 	}
10043 	return success;
10044 }
10045 
10046 static OSSharedPtr<OSObject> deferredAuxKCXML;
10047 bool
10048 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh,
10049     OSSharedPtr<OSObject> &parsedXML, kc_kind_t type)
10050 {
10051 	if (type != KCKindAuxiliary) {
10052 		return false;
10053 	}
10054 
10055 	kernel_mach_header_t *_mh;
10056 	_mh = (kernel_mach_header_t*)PE_get_kc_header(type);
10057 	if (!_mh || _mh != mh) {
10058 		return false;
10059 	}
10060 
10061 	if (deferredAuxKCXML) {
10062 		/* only allow this to be called once */
10063 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10064 		    "An Aux KC has already been registered for deferred processing.");
10065 		return false;
10066 	}
10067 
10068 	OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
10069 	if (!infoDict) {
10070 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10071 		    "The Aux KC has info dictionary");
10072 		return false;
10073 	}
10074 
10075 	OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10076 	if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) {
10077 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10078 		    "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey);
10079 		return false;
10080 	}
10081 
10082 	/*
10083 	 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid
10084 	 * sysctl can return the UUID to user space which will check this
10085 	 * value for errors.
10086 	 */
10087 	memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(),
10088 	    kcUUID->getLength());
10089 	uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
10090 	auxkc_uuid_valid = TRUE;
10091 
10092 	deferredAuxKCXML = parsedXML;
10093 
10094 	return true;
10095 }
10096 
10097 OSSharedPtr<OSObject>
10098 OSKext::consumeDeferredKextCollection(kc_kind_t type)
10099 {
10100 	if (type != KCKindAuxiliary || !deferredAuxKCXML) {
10101 		return NULL;
10102 	}
10103 
10104 	return os::move(deferredAuxKCXML);
10105 }
10106 
10107 #if PRAGMA_MARK
10108 #pragma mark Profile-Guided-Optimization Support
10109 #endif
10110 
10111 // #include <InstrProfiling.h>
10112 extern "C" {
10113 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
10114     const char *DataEnd,
10115     const char *CountersBegin,
10116     const char *CountersEnd,
10117     const char *NamesBegin,
10118     const char *NamesEnd);
10119 int __llvm_profile_write_buffer_internal(char *Buffer,
10120     const char *DataBegin,
10121     const char *DataEnd,
10122     const char *CountersBegin,
10123     const char *CountersEnd,
10124     const char *NamesBegin,
10125     const char *NamesEnd);
10126 }
10127 
10128 
10129 static
10130 void
10131 OSKextPgoMetadataPut(char *pBuffer,
10132     size_t *position,
10133     size_t bufferSize,
10134     uint32_t *num_pairs,
10135     const char *key,
10136     const char *value)
10137 {
10138 	size_t strlen_key = strlen(key);
10139 	size_t strlen_value = strlen(value);
10140 	size_t len = strlen(key) + 1 + strlen(value) + 1;
10141 	char *pos = pBuffer + *position;
10142 	*position += len;
10143 	if (pBuffer && bufferSize && *position <= bufferSize) {
10144 		memcpy(pos, key, strlen_key); pos += strlen_key;
10145 		*(pos++) = '=';
10146 		memcpy(pos, value, strlen_value); pos += strlen_value;
10147 		*(pos++) = 0;
10148 		if (num_pairs) {
10149 			(*num_pairs)++;
10150 		}
10151 	}
10152 }
10153 
10154 
10155 static
10156 void
10157 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
10158 {
10159 	*position += strlen(key) + 1 + value_max + 1;
10160 }
10161 
10162 
10163 static
10164 void
10165 OSKextPgoMetadataPutAll(OSKext *kext,
10166     uuid_t instance_uuid,
10167     char *pBuffer,
10168     size_t *position,
10169     size_t bufferSize,
10170     uint32_t *num_pairs)
10171 {
10172 	_static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
10173 	//log_10 2^16 ≈ 4.82
10174 	const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
10175 	const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
10176 
10177 	if (!pBuffer) {
10178 		OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
10179 		OSKextPgoMetadataPutMax(position, "UUID", 36);
10180 		OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
10181 	} else {
10182 		uuid_string_t instance_uuid_string;
10183 		uuid_unparse(instance_uuid, instance_uuid_string);
10184 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10185 		    "INSTANCE", instance_uuid_string);
10186 
10187 		OSSharedPtr<OSData> uuid_data;
10188 		uuid_t uuid;
10189 		uuid_string_t uuid_string;
10190 		uuid_data = kext->copyUUID();
10191 		if (uuid_data) {
10192 			memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
10193 			uuid_unparse(uuid, uuid_string);
10194 			OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10195 			    "UUID", uuid_string);
10196 		}
10197 
10198 		clock_sec_t secs;
10199 		clock_usec_t usecs;
10200 		clock_get_calendar_microtime(&secs, &usecs);
10201 		assert(usecs < 1000000);
10202 		char timestamp[max_timestamp_string_size + 1];
10203 		_static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
10204 		snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
10205 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10206 		    "TIMESTAMP", timestamp);
10207 	}
10208 
10209 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10210 	    "NAME", kext->getIdentifierCString());
10211 
10212 	char versionCString[kOSKextVersionMaxLength];
10213 	OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
10214 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10215 	    "VERSION", versionCString);
10216 }
10217 
10218 static
10219 size_t
10220 OSKextPgoMetadataSize(OSKext *kext)
10221 {
10222 	size_t position = 0;
10223 	uuid_t fakeuuid = {};
10224 	OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
10225 	return position;
10226 }
10227 
10228 int
10229 OSKextGrabPgoDataLocked(OSKext *kext,
10230     bool metadata,
10231     uuid_t instance_uuid,
10232     uint64_t *pSize,
10233     char *pBuffer,
10234     uint64_t bufferSize)
10235 {
10236 	int err = 0;
10237 
10238 	kernel_section_t *sect_prf_data = NULL;
10239 	kernel_section_t *sect_prf_name = NULL;
10240 	kernel_section_t *sect_prf_cnts = NULL;
10241 	uint64_t size;
10242 	size_t metadata_size = 0;
10243 	size_t offset_to_pairs = 0;
10244 
10245 	sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
10246 	sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
10247 	if (!sect_prf_name) {
10248 		// kextcache sometimes truncates the section name to 15 chars
10249 		// <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
10250 		sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
10251 	}
10252 	sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
10253 
10254 	if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
10255 		err = ENOTSUP;
10256 		goto out;
10257 	}
10258 
10259 	size = __llvm_profile_get_size_for_buffer_internal(
10260 		(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
10261 		(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
10262 		(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
10263 
10264 	if (metadata) {
10265 		metadata_size = OSKextPgoMetadataSize(kext);
10266 		size += metadata_size;
10267 		size += sizeof(pgo_metadata_footer);
10268 	}
10269 
10270 
10271 	if (pSize) {
10272 		*pSize = size;
10273 	}
10274 
10275 	if (pBuffer && bufferSize) {
10276 		if (bufferSize < size) {
10277 			err = ERANGE;
10278 			goto out;
10279 		}
10280 
10281 		err = __llvm_profile_write_buffer_internal(
10282 			pBuffer,
10283 			(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
10284 			(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
10285 			(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
10286 
10287 		if (err) {
10288 			err = EIO;
10289 			goto out;
10290 		}
10291 
10292 		if (metadata) {
10293 			offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size;
10294 			if (offset_to_pairs > UINT32_MAX) {
10295 				err = E2BIG;
10296 				goto out;
10297 			}
10298 
10299 			char *end_of_buffer = pBuffer + size;
10300 			struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
10301 			char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
10302 
10303 			size_t metadata_position = 0;
10304 			uint32_t num_pairs = 0;
10305 			OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
10306 			while (metadata_position < metadata_size) {
10307 				metadata_buffer[metadata_position++] = 0;
10308 			}
10309 
10310 			struct pgo_metadata_footer footer;
10311 			footer.magic = htonl(0x6d657461);
10312 			footer.number_of_pairs = htonl( num_pairs );
10313 			footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs );
10314 			memcpy(footerp, &footer, sizeof(footer));
10315 		}
10316 	}
10317 
10318 out:
10319 	return err;
10320 }
10321 
10322 
10323 int
10324 OSKextGrabPgoData(uuid_t uuid,
10325     uint64_t *pSize,
10326     char *pBuffer,
10327     uint64_t bufferSize,
10328     int wait_for_unload,
10329     int metadata)
10330 {
10331 	int err = 0;
10332 	OSSharedPtr<OSKext> kext;
10333 
10334 
10335 	IORecursiveLockLock(sKextLock);
10336 
10337 	kext = OSKext::lookupKextWithUUID(uuid);
10338 	if (!kext) {
10339 		err = ENOENT;
10340 		goto out;
10341 	}
10342 
10343 	if (wait_for_unload) {
10344 		OSKextGrabPgoStruct s;
10345 
10346 		s.metadata = metadata;
10347 		s.pSize = pSize;
10348 		s.pBuffer = pBuffer;
10349 		s.bufferSize = bufferSize;
10350 		s.err = EINTR;
10351 
10352 		struct list_head *prev = &kext->pendingPgoHead;
10353 		struct list_head *next = kext->pendingPgoHead.next;
10354 
10355 		s.list_head.prev = prev;
10356 		s.list_head.next = next;
10357 
10358 		prev->next = &s.list_head;
10359 		next->prev = &s.list_head;
10360 
10361 		kext.reset();
10362 
10363 		IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
10364 
10365 		prev = s.list_head.prev;
10366 		next = s.list_head.next;
10367 
10368 		prev->next = next;
10369 		next->prev = prev;
10370 
10371 		err = s.err;
10372 	} else {
10373 		err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
10374 	}
10375 
10376 out:
10377 
10378 	IORecursiveLockUnlock(sKextLock);
10379 
10380 	return err;
10381 }
10382 
10383 void
10384 OSKextResetPgoCountersLock()
10385 {
10386 	IORecursiveLockLock(sKextLock);
10387 }
10388 
10389 void
10390 OSKextResetPgoCountersUnlock()
10391 {
10392 	IORecursiveLockUnlock(sKextLock);
10393 }
10394 
10395 
10396 extern unsigned int not_in_kdp;
10397 
10398 void
10399 OSKextResetPgoCounters()
10400 {
10401 	assert(!not_in_kdp);
10402 	uint32_t count = sLoadedKexts->getCount();
10403 	for (uint32_t i = 0; i < count; i++) {
10404 		OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
10405 		kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
10406 		if (!sect_prf_cnts) {
10407 			continue;
10408 		}
10409 		memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
10410 	}
10411 }
10412 
10413 OSSharedPtr<OSDictionary>
10414 OSKext::copyLoadedKextInfoByUUID(
10415 	OSArray * kextIdentifiers,
10416 	OSArray * infoKeys)
10417 {
10418 	OSSharedPtr<OSDictionary> result;
10419 	OSSharedPtr<OSDictionary> kextInfo;
10420 	uint32_t       max_count, i, j;
10421 	uint32_t       idCount = 0;
10422 	uint32_t       idIndex = 0;
10423 	IORecursiveLockLock(sKextLock);
10424 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
10425 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
10426 
10427 #if CONFIG_MACF
10428 	/* Is the calling process allowed to query kext info? */
10429 	if (current_task() != kernel_task) {
10430 		int                 macCheckResult      = 0;
10431 		kauth_cred_t        cred                = NULL;
10432 
10433 		cred = kauth_cred_get_with_ref();
10434 		macCheckResult = mac_kext_check_query(cred);
10435 		kauth_cred_unref(&cred);
10436 
10437 		if (macCheckResult != 0) {
10438 			OSKextLog(/* kext */ NULL,
10439 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10440 			    "Failed to query kext info (MAC policy error 0x%x).",
10441 			    macCheckResult);
10442 			goto finish;
10443 		}
10444 	}
10445 #endif
10446 
10447 	/* Empty list of UUIDs is equivalent to no list (get all).
10448 	 */
10449 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
10450 		kextIdentifiers = NULL;
10451 	} else if (kextIdentifiers) {
10452 		idCount = kextIdentifiers->getCount();
10453 	}
10454 
10455 	/* Same for keys.
10456 	 */
10457 	if (infoKeys && !infoKeys->getCount()) {
10458 		infoKeys = NULL;
10459 	}
10460 
10461 	max_count = count[0] + count[1];
10462 	result = OSDictionary::withCapacity(max_count);
10463 	if (!result) {
10464 		goto finish;
10465 	}
10466 
10467 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
10468 		for (i = 0; i < count[j]; i++) {
10469 			OSKext       *thisKext     = NULL;        // do not release
10470 			Boolean       includeThis  = true;
10471 			uuid_t        thisKextUUID;
10472 			uuid_t        thisKextTextUUID;
10473 			OSSharedPtr<OSData> uuid_data;
10474 			uuid_string_t uuid_key;
10475 
10476 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
10477 			if (!thisKext) {
10478 				continue;
10479 			}
10480 
10481 			uuid_data = thisKext->copyUUID();
10482 			if (!uuid_data) {
10483 				continue;
10484 			}
10485 
10486 			memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
10487 
10488 			uuid_unparse(thisKextUUID, uuid_key);
10489 
10490 			uuid_data = thisKext->copyTextUUID();
10491 			if (!uuid_data) {
10492 				continue;
10493 			}
10494 			memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
10495 
10496 			/* Skip current kext if we have a list of UUIDs and
10497 			 * it isn't in the list.
10498 			 */
10499 			if (kextIdentifiers) {
10500 				includeThis = false;
10501 
10502 				for (idIndex = 0; idIndex < idCount; idIndex++) {
10503 					const OSString* wantedUUID = OSDynamicCast(OSString,
10504 					    kextIdentifiers->getObject(idIndex));
10505 
10506 					uuid_t uuid;
10507 					uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
10508 
10509 					if ((0 == uuid_compare(uuid, thisKextUUID))
10510 					    || (0 == uuid_compare(uuid, thisKextTextUUID))) {
10511 						includeThis = true;
10512 						/* Only need to find the first kext if multiple match,
10513 						 * ie. asking for the kernel uuid does not need to find
10514 						 * interface kexts or builtin static kexts.
10515 						 */
10516 						kextIdentifiers->removeObject(idIndex);
10517 						uuid_unparse(uuid, uuid_key);
10518 						break;
10519 					}
10520 				}
10521 			}
10522 
10523 			if (!includeThis) {
10524 				continue;
10525 			}
10526 
10527 			kextInfo = thisKext->copyInfo(infoKeys);
10528 			if (kextInfo) {
10529 				result->setObject(uuid_key, kextInfo.get());
10530 			}
10531 
10532 			if (kextIdentifiers && !kextIdentifiers->getCount()) {
10533 				goto finish;
10534 			}
10535 		}
10536 	}
10537 
10538 finish:
10539 	IORecursiveLockUnlock(sKextLock);
10540 
10541 	return result;
10542 }
10543 
10544 /*********************************************************************
10545 *********************************************************************/
10546 /* static */
10547 OSSharedPtr<OSDictionary>
10548 OSKext::copyKextCollectionInfo(
10549 	OSDictionary *requestDict,
10550 	OSArray  *infoKeys)
10551 {
10552 	OSSharedPtr<OSDictionary> result;
10553 	OSString *collectionType = NULL;
10554 	OSObject *rawLoadedState = NULL;
10555 	OSString *loadedState    = NULL;
10556 
10557 	kc_kind_t kc_request_kind = KCKindUnknown;
10558 	bool onlyLoaded = false;
10559 	bool onlyUnloaded = false;
10560 
10561 #if CONFIG_MACF
10562 	/* Is the calling process allowed to query kext info? */
10563 	if (current_task() != kernel_task) {
10564 		int                 macCheckResult      = 0;
10565 		kauth_cred_t        cred                = NULL;
10566 
10567 		cred = kauth_cred_get_with_ref();
10568 		macCheckResult = mac_kext_check_query(cred);
10569 		kauth_cred_unref(&cred);
10570 
10571 		if (macCheckResult != 0) {
10572 			OSKextLog(/* kext */ NULL,
10573 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10574 			    "Failed to query kext info (MAC policy error 0x%x).",
10575 			    macCheckResult);
10576 			goto finish;
10577 		}
10578 	}
10579 #endif
10580 
10581 	if (infoKeys && !infoKeys->getCount()) {
10582 		infoKeys = NULL;
10583 	}
10584 
10585 	collectionType = OSDynamicCast(OSString,
10586 	    _OSKextGetRequestArgument(requestDict,
10587 	    kKextRequestArgumentCollectionTypeKey));
10588 	if (!collectionType) {
10589 		OSKextLog(/* kext */ NULL,
10590 		    kOSKextLogErrorLevel |
10591 		    kOSKextLogIPCFlag,
10592 		    "Invalid '%s' argument to kext collection info request.",
10593 		    kKextRequestArgumentCollectionTypeKey);
10594 		goto finish;
10595 	}
10596 	if (collectionType->isEqualTo(kKCTypePrimary)) {
10597 		kc_request_kind = KCKindPrimary;
10598 	} else if (collectionType->isEqualTo(kKCTypeSystem)) {
10599 		kc_request_kind = KCKindPageable;
10600 	} else if (collectionType->isEqualTo(kKCTypeAuxiliary)) {
10601 		kc_request_kind = KCKindAuxiliary;
10602 	} else if (collectionType->isEqualTo(kKCTypeCodeless)) {
10603 		kc_request_kind = KCKindNone;
10604 	} else if (!collectionType->isEqualTo(kKCTypeAny)) {
10605 		OSKextLog(/* kext */ NULL,
10606 		    kOSKextLogErrorLevel |
10607 		    kOSKextLogIPCFlag,
10608 		    "Invalid '%s' argument value '%s' to kext collection info request.",
10609 		    kKextRequestArgumentCollectionTypeKey,
10610 		    collectionType->getCStringNoCopy());
10611 		goto finish;
10612 	}
10613 
10614 	rawLoadedState = _OSKextGetRequestArgument(requestDict,
10615 	    kKextRequestArgumentLoadedStateKey);
10616 	if (rawLoadedState) {
10617 		loadedState = OSDynamicCast(OSString, rawLoadedState);
10618 		if (!loadedState) {
10619 			OSKextLog(/* kext */ NULL,
10620 			    kOSKextLogErrorLevel |
10621 			    kOSKextLogIPCFlag,
10622 			    "Invalid '%s' argument to kext collection info request.",
10623 			    kKextRequestArgumentLoadedStateKey);
10624 			goto finish;
10625 		}
10626 	}
10627 	if (loadedState) {
10628 		if (loadedState->isEqualTo("Loaded")) {
10629 			onlyLoaded = true;
10630 		} else if (loadedState->isEqualTo("Unloaded")) {
10631 			onlyUnloaded = true;
10632 		} else if (!loadedState->isEqualTo("Any")) {
10633 			OSKextLog(/* kext */ NULL,
10634 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10635 			    "Invalid '%s' argument value '%s' for '%s' collection info",
10636 			    kKextRequestArgumentLoadedStateKey,
10637 			    loadedState->getCStringNoCopy(),
10638 			    collectionType->getCStringNoCopy());
10639 			goto finish;
10640 		}
10641 	}
10642 
10643 	result = OSDictionary::withCapacity(sKextsByID->getCount());
10644 	if (!result) {
10645 		goto finish;
10646 	}
10647 
10648 	IORecursiveLockLock(sKextLock);
10649 	{         // start block scope
10650 		sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
10651 		{
10652 			OSKext       *thisKext    = NULL;  // do not release
10653 			OSSharedPtr<OSDictionary> kextInfo;
10654 
10655 			(void)thisKextID;
10656 
10657 			thisKext = OSDynamicCast(OSKext, obj);
10658 			if (!thisKext) {
10659 			        return false;
10660 			}
10661 
10662 			/*
10663 			 * skip the kext if it came from the wrong collection type
10664 			 * (and the caller requested a specific type)
10665 			 */
10666 			if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) {
10667 			        return false;
10668 			}
10669 
10670 			/*
10671 			 * respect the caller's desire to find only loaded or
10672 			 * unloaded kexts
10673 			 */
10674 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10675 			        return false;
10676 			}
10677 			if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10678 			        return false;
10679 			}
10680 
10681 			kextInfo = thisKext->copyInfo(infoKeys);
10682 			if (kextInfo) {
10683 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
10684 			}
10685 			return false;
10686 		});
10687 	} // end block scope
10688 	IORecursiveLockUnlock(sKextLock);
10689 
10690 finish:
10691 	return result;
10692 }
10693 
10694 /*********************************************************************
10695 *********************************************************************/
10696 /* static */
10697 OSSharedPtr<OSDictionary>
10698 OSKext::copyLoadedKextInfo(
10699 	OSArray * kextIdentifiers,
10700 	OSArray * infoKeys)
10701 {
10702 	OSSharedPtr<OSDictionary> result;
10703 	uint32_t       idCount = 0;
10704 	bool           onlyLoaded;
10705 
10706 	IORecursiveLockLock(sKextLock);
10707 
10708 #if CONFIG_MACF
10709 	/* Is the calling process allowed to query kext info? */
10710 	if (current_task() != kernel_task) {
10711 		int                 macCheckResult      = 0;
10712 		kauth_cred_t        cred                = NULL;
10713 
10714 		cred = kauth_cred_get_with_ref();
10715 		macCheckResult = mac_kext_check_query(cred);
10716 		kauth_cred_unref(&cred);
10717 
10718 		if (macCheckResult != 0) {
10719 			OSKextLog(/* kext */ NULL,
10720 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10721 			    "Failed to query kext info (MAC policy error 0x%x).",
10722 			    macCheckResult);
10723 			goto finish;
10724 		}
10725 	}
10726 #endif
10727 
10728 	/* Empty list of bundle ids is equivalent to no list (get all).
10729 	 */
10730 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
10731 		kextIdentifiers = NULL;
10732 	} else if (kextIdentifiers) {
10733 		idCount = kextIdentifiers->getCount();
10734 	}
10735 
10736 	/* Same for keys.
10737 	 */
10738 	if (infoKeys && !infoKeys->getCount()) {
10739 		infoKeys = NULL;
10740 	}
10741 
10742 	onlyLoaded =  (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
10743 
10744 	result = OSDictionary::withCapacity(128);
10745 	if (!result) {
10746 		goto finish;
10747 	}
10748 
10749 #if 0
10750 	OSKextLog(/* kext */ NULL,
10751 	    kOSKextLogErrorLevel |
10752 	    kOSKextLogGeneralFlag,
10753 	    "kaslr: vm_kernel_slide 0x%lx \n",
10754 	    vm_kernel_slide);
10755 	OSKextLog(/* kext */ NULL,
10756 	    kOSKextLogErrorLevel |
10757 	    kOSKextLogGeneralFlag,
10758 	    "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
10759 	    vm_kernel_stext, vm_kernel_etext);
10760 	OSKextLog(/* kext */ NULL,
10761 	    kOSKextLogErrorLevel |
10762 	    kOSKextLogGeneralFlag,
10763 	    "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
10764 	    vm_kernel_base, vm_kernel_top);
10765 	OSKextLog(/* kext */ NULL,
10766 	    kOSKextLogErrorLevel |
10767 	    kOSKextLogGeneralFlag,
10768 	    "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
10769 	    vm_kext_base, vm_kext_top);
10770 	OSKextLog(/* kext */ NULL,
10771 	    kOSKextLogErrorLevel |
10772 	    kOSKextLogGeneralFlag,
10773 	    "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
10774 	    vm_prelink_stext, vm_prelink_etext);
10775 	OSKextLog(/* kext */ NULL,
10776 	    kOSKextLogErrorLevel |
10777 	    kOSKextLogGeneralFlag,
10778 	    "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
10779 	    vm_prelink_sinfo, vm_prelink_einfo);
10780 	OSKextLog(/* kext */ NULL,
10781 	    kOSKextLogErrorLevel |
10782 	    kOSKextLogGeneralFlag,
10783 	    "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
10784 	    vm_slinkedit, vm_elinkedit);
10785 #endif
10786 	{         // start block scope
10787 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
10788 		{
10789 			OSKext       * thisKext     = NULL;        // do not release
10790 			Boolean        includeThis  = true;
10791 			OSSharedPtr<OSDictionary> kextInfo;
10792 
10793 			thisKext = OSDynamicCast(OSKext, obj);
10794 			if (!thisKext) {
10795 			        return false;
10796 			}
10797 
10798 			/* Skip current kext if not yet started and caller didn't request all.
10799 			 */
10800 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10801 			        return false;
10802 			}
10803 
10804 			/* Skip current kext if we have a list of bundle IDs and
10805 			 * it isn't in the list.
10806 			 */
10807 			if (kextIdentifiers) {
10808 			        includeThis = false;
10809 
10810 			        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
10811 			                const OSString * thisRequestID = OSDynamicCast(OSString,
10812 			                kextIdentifiers->getObject(idIndex));
10813 			                if (thisKextID->isEqualTo(thisRequestID)) {
10814 			                        includeThis = true;
10815 			                        break;
10816 					}
10817 				}
10818 			}
10819 
10820 			if (!includeThis) {
10821 			        return false;
10822 			}
10823 
10824 			kextInfo = thisKext->copyInfo(infoKeys);
10825 			if (kextInfo) {
10826 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
10827 			}
10828 			return false;
10829 		});
10830 	}         // end block scope
10831 
10832 finish:
10833 	IORecursiveLockUnlock(sKextLock);
10834 
10835 	return result;
10836 }
10837 
10838 /*********************************************************************
10839 * Any info that needs to do allocations must goto finish on alloc
10840 * failure. Info that is just a lookup should just not set the object
10841 * if the info does not exist.
10842 *********************************************************************/
10843 #define _OSKextLoadInfoDictCapacity   (12)
10844 
10845 OSSharedPtr<OSDictionary>
10846 OSKext::copyInfo(OSArray * infoKeys)
10847 {
10848 	OSSharedPtr<OSDictionary>  result;
10849 	bool                       success                     = false;
10850 	OSSharedPtr<OSData>        headerData;
10851 	OSSharedPtr<OSData>        logData;
10852 	OSSharedPtr<OSNumber>      cpuTypeNumber;
10853 	OSSharedPtr<OSNumber>      cpuSubtypeNumber;
10854 	OSString                 * versionString               = NULL;        // do not release
10855 	OSString                 * bundleType                  = NULL;        // do not release
10856 	uint32_t                   executablePathCStringSize   = 0;
10857 	char                     * executablePathCString       = NULL;        // must kfree
10858 	OSSharedPtr<OSString>      executablePathString;
10859 	OSSharedPtr<OSData>        uuid;
10860 	OSSharedPtr<OSArray>       dependencyLoadTags;
10861 	OSSharedPtr<OSCollectionIterator>      metaClassIterator;
10862 	OSSharedPtr<OSArray>       metaClassInfo;
10863 	OSSharedPtr<OSDictionary>  metaClassDict;
10864 	OSMetaClass              * thisMetaClass               = NULL;        // do not release
10865 	OSSharedPtr<OSString>      metaClassName;
10866 	OSSharedPtr<OSString>      superclassName;
10867 	kc_format_t                kcformat;
10868 	uint32_t                   count, i;
10869 
10870 	result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
10871 	if (!result) {
10872 		goto finish;
10873 	}
10874 
10875 
10876 	/* Empty keys means no keys, but NULL is quicker to check.
10877 	 */
10878 	if (infoKeys && !infoKeys->getCount()) {
10879 		infoKeys = NULL;
10880 	}
10881 
10882 	if (!PE_get_primary_kc_format(&kcformat)) {
10883 		goto finish;
10884 	}
10885 
10886 	/* Headers, CPU type, and CPU subtype.
10887 	 */
10888 	if (!infoKeys ||
10889 	    _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
10890 	    _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
10891 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
10892 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
10893 		if (linkedExecutable && !isInterface()) {
10894 			kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
10895 			    linkedExecutable->getBytesNoCopy();
10896 
10897 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX
10898 			// do not return macho header info on shipping embedded - 19095897
10899 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
10900 				kernel_mach_header_t *  temp_kext_mach_hdr;
10901 				struct load_command *   lcp;
10902 
10903 				headerData = OSData::withBytes(kext_mach_hdr,
10904 				    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
10905 				if (!headerData) {
10906 					goto finish;
10907 				}
10908 
10909 				// unslide any vmaddrs we return to userspace - 10726716
10910 				temp_kext_mach_hdr = (kernel_mach_header_t *)
10911 				    headerData->getBytesNoCopy();
10912 				if (temp_kext_mach_hdr == NULL) {
10913 					goto finish;
10914 				}
10915 
10916 				lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
10917 				for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
10918 					if (lcp->cmd == LC_SEGMENT_KERNEL) {
10919 						kernel_segment_command_t *  segp;
10920 						kernel_section_t *          secp;
10921 
10922 						segp = (kernel_segment_command_t *) lcp;
10923 						// 10543468 - if we jettisoned __LINKEDIT clear size info
10924 						if (flags.jettisonLinkeditSeg) {
10925 							if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
10926 								segp->vmsize = 0;
10927 								segp->fileoff = 0;
10928 								segp->filesize = 0;
10929 							}
10930 						}
10931 
10932 #if __arm__ || __arm64__
10933 						// iBoot disregards zero-size segments, just set their addresses to gVirtBase
10934 						// and unslide them to avoid vm assertion failures / kernel logging breakage.
10935 						if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) {
10936 							segp->vmaddr = gVirtBase;
10937 							for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
10938 								secp->size = 0; // paranoia :)
10939 								secp->addr = gVirtBase;
10940 							}
10941 						}
10942 #endif
10943 
10944 #if 0
10945 						OSKextLog(/* kext */ NULL,
10946 						    kOSKextLogErrorLevel |
10947 						    kOSKextLogGeneralFlag,
10948 						    "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
10949 						    __FUNCTION__, segp->segname, segp->vmaddr,
10950 						    VM_KERNEL_UNSLIDE(segp->vmaddr),
10951 						    segp->vmsize, segp->nsects);
10952 						if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
10953 						    (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
10954 						    (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
10955 						    (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
10956 						    (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
10957 							OSKextLog(/* kext */ NULL,
10958 							    kOSKextLogErrorLevel |
10959 							    kOSKextLogGeneralFlag,
10960 							    "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
10961 							    __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
10962 						}
10963 #endif
10964 						segp->vmaddr = ml_static_unslide(segp->vmaddr);
10965 
10966 						for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
10967 							secp->addr = ml_static_unslide(secp->addr);
10968 						}
10969 					}
10970 					lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
10971 				}
10972 				result->setObject(kOSBundleMachOHeadersKey, headerData.get());
10973 			}
10974 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX
10975 
10976 			if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
10977 				osLogDataHeaderRef *header;
10978 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
10979 
10980 				void *os_log_data               = NULL;
10981 				void *cstring_data              = NULL;
10982 				void *asan_cstring_data         = NULL;
10983 				unsigned long os_log_size       = 0;
10984 				unsigned long cstring_size      = 0;
10985 				unsigned long asan_cstring_size = 0;
10986 				uint32_t os_log_offset          = 0;
10987 				uint32_t cstring_offset         = 0;
10988 				uint32_t asan_cstring_offset    = 0;
10989 				bool res;
10990 
10991 				os_log_data         = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
10992 				os_log_offset       = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr;
10993 				cstring_data        = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
10994 				cstring_offset      = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr;
10995 				asan_cstring_data   = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size);
10996 				asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr;
10997 
10998 				header             = (osLogDataHeaderRef *) headerBytes;
10999 				header->version    = OS_LOG_HDR_VERSION;
11000 				header->sect_count = NUM_OS_LOG_SECTIONS;
11001 				header->sections[OS_LOG_SECT_IDX].sect_offset       = os_log_offset;
11002 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) os_log_size;
11003 				header->sections[CSTRING_SECT_IDX].sect_offset      = cstring_offset;
11004 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) cstring_size;
11005 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset;
11006 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) asan_cstring_size;
11007 
11008 
11009 				logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
11010 				if (!logData) {
11011 					goto finish;
11012 				}
11013 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
11014 				if (!res) {
11015 					goto finish;
11016 				}
11017 				if (os_log_data) {
11018 					res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
11019 					if (!res) {
11020 						goto finish;
11021 					}
11022 				}
11023 				if (cstring_data) {
11024 					res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
11025 					if (!res) {
11026 						goto finish;
11027 					}
11028 				}
11029 				if (asan_cstring_data) {
11030 					res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size);
11031 					if (!res) {
11032 						goto finish;
11033 					}
11034 				}
11035 				result->setObject(kOSBundleLogStringsKey, logData.get());
11036 			}
11037 
11038 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
11039 				cpuTypeNumber = OSNumber::withNumber(
11040 					(uint64_t) kext_mach_hdr->cputype,
11041 					8 * sizeof(kext_mach_hdr->cputype));
11042 				if (!cpuTypeNumber) {
11043 					goto finish;
11044 				}
11045 				result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get());
11046 			}
11047 
11048 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
11049 				cpuSubtypeNumber = OSNumber::withNumber(
11050 					(uint64_t) kext_mach_hdr->cpusubtype,
11051 					8 * sizeof(kext_mach_hdr->cpusubtype));
11052 				if (!cpuSubtypeNumber) {
11053 					goto finish;
11054 				}
11055 				result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get());
11056 			}
11057 		} else {
11058 			if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
11059 				osLogDataHeaderRef *header;
11060 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
11061 				bool res;
11062 
11063 				header             = (osLogDataHeaderRef *) headerBytes;
11064 				header->version    = OS_LOG_HDR_VERSION;
11065 				header->sect_count = NUM_OS_LOG_SECTIONS;
11066 				header->sections[OS_LOG_SECT_IDX].sect_offset       = 0;
11067 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) 0;
11068 				header->sections[CSTRING_SECT_IDX].sect_offset      = 0;
11069 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) 0;
11070 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0;
11071 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) 0;
11072 
11073 				logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
11074 				if (!logData) {
11075 					goto finish;
11076 				}
11077 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
11078 				if (!res) {
11079 					goto finish;
11080 				}
11081 				result->setObject(kOSBundleLogStringsKey, logData.get());
11082 			}
11083 		}
11084 	}
11085 
11086 	/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
11087 	 */
11088 	result->setObject(kCFBundleIdentifierKey, bundleID.get());
11089 
11090 	/* CFBundlePackageType
11091 	 */
11092 	bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL;
11093 	if (bundleType) {
11094 		result->setObject(kCFBundlePackageTypeKey, bundleType);
11095 	}
11096 
11097 	/* CFBundleVersion.
11098 	 */
11099 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
11100 		versionString = OSDynamicCast(OSString,
11101 		    getPropertyForHostArch(kCFBundleVersionKey));
11102 		if (versionString) {
11103 			result->setObject(kCFBundleVersionKey, versionString);
11104 		}
11105 	}
11106 
11107 	/* OSBundleCompatibleVersion.
11108 	 */
11109 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
11110 		versionString = OSDynamicCast(OSString,
11111 		    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
11112 		if (versionString) {
11113 			result->setObject(kOSBundleCompatibleVersionKey, versionString);
11114 		}
11115 	}
11116 
11117 	/* Path.
11118 	 */
11119 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
11120 		if (path) {
11121 			result->setObject(kOSBundlePathKey, path.get());
11122 		}
11123 	}
11124 
11125 
11126 	/* OSBundleExecutablePath.
11127 	 */
11128 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
11129 		if (path && executableRelPath) {
11130 			uint32_t pathLength = path->getLength();         // gets incremented below
11131 
11132 			// +1 for slash, +1 for \0
11133 			executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
11134 
11135 			executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
11136 			    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);         // +1 for \0
11137 			if (!executablePathCString) {
11138 				goto finish;
11139 			}
11140 			strlcpy(executablePathCString, path->getCStringNoCopy(),
11141 			    executablePathCStringSize);
11142 			executablePathCString[pathLength++] = '/';
11143 			executablePathCString[pathLength++] = '\0';
11144 			strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
11145 			    executablePathCStringSize);
11146 
11147 			executablePathString = OSString::withCString(executablePathCString);
11148 
11149 			if (!executablePathString) {
11150 				goto finish;
11151 			}
11152 
11153 			result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
11154 		} else if (flags.builtin) {
11155 			result->setObject(kOSBundleExecutablePathKey, bundleID.get());
11156 		} else if (isDriverKit()) {
11157 			if (path) {
11158 				// +1 for slash, +1 for \0
11159 				uint32_t pathLength = path->getLength();
11160 				executablePathCStringSize = pathLength + 2;
11161 
11162 				executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
11163 				    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
11164 				if (!executablePathCString) {
11165 					goto finish;
11166 				}
11167 				strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
11168 				executablePathCString[pathLength++] = '/';
11169 				executablePathCString[pathLength++] = '\0';
11170 
11171 				executablePathString = OSString::withCString(executablePathCString);
11172 
11173 				if (!executablePathString) {
11174 					goto finish;
11175 				}
11176 
11177 				result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
11178 			}
11179 		}
11180 	}
11181 
11182 	/* UUID, if the kext has one.
11183 	 */
11184 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
11185 		uuid = copyUUID();
11186 		if (uuid) {
11187 			result->setObject(kOSBundleUUIDKey, uuid.get());
11188 		}
11189 	}
11190 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
11191 		uuid = copyTextUUID();
11192 		if (uuid) {
11193 			result->setObject(kOSBundleTextUUIDKey, uuid.get());
11194 		}
11195 	}
11196 
11197 	/*
11198 	 * Info.plist digest
11199 	 */
11200 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) {
11201 		OSData *digest;
11202 		digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL;
11203 		if (digest) {
11204 			result->setObject(kOSKextInfoPlistDigestKey, digest);
11205 		}
11206 	}
11207 
11208 	/*
11209 	 * Collection type
11210 	 */
11211 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) {
11212 		result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString()));
11213 	}
11214 
11215 	/*
11216 	 * Collection availability
11217 	 */
11218 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) {
11219 		result->setObject(kOSKextAuxKCAvailabilityKey,
11220 		    isLoadable() ? kOSBooleanTrue : kOSBooleanFalse);
11221 	}
11222 
11223 	/*
11224 	 * Allows user load
11225 	 */
11226 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) {
11227 		OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey));
11228 		if (allowUserLoad) {
11229 			result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad);
11230 		}
11231 	}
11232 
11233 	/*
11234 	 * Bundle Dependencies (OSBundleLibraries)
11235 	 */
11236 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) {
11237 		OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey));
11238 		if (libraries) {
11239 			result->setObject(kOSBundleLibrariesKey, libraries);
11240 		}
11241 	}
11242 
11243 	/*****
11244 	 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
11245 	 */
11246 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
11247 		result->setObject(kOSKernelResourceKey,
11248 		    isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
11249 	}
11250 
11251 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
11252 		result->setObject(kOSBundleIsInterfaceKey,
11253 		    isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
11254 	}
11255 
11256 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
11257 		result->setObject(kOSBundlePrelinkedKey,
11258 		    isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
11259 	}
11260 
11261 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
11262 		result->setObject(kOSBundleStartedKey,
11263 		    isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
11264 	}
11265 
11266 	/* LoadTag (Index).
11267 	 */
11268 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
11269 		OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
11270 		    /* numBits */ 8 * sizeof(loadTag));
11271 		if (!scratchNumber) {
11272 			goto finish;
11273 		}
11274 		result->setObject(kOSBundleLoadTagKey, scratchNumber.get());
11275 	}
11276 
11277 	/* LoadAddress, LoadSize.
11278 	 */
11279 	if (!infoKeys ||
11280 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
11281 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
11282 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
11283 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
11284 	    _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
11285 		bool is_dext = isDriverKit();
11286 		if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
11287 			/* These go to userspace via serialization, so we don't want any doubts
11288 			 * about their size.
11289 			 */
11290 			uint64_t    loadAddress     = 0;
11291 			uint32_t    loadSize        = 0;
11292 			uint32_t    wiredSize       = 0;
11293 			uint64_t    execLoadAddress = 0;
11294 			uint32_t    execLoadSize    = 0;
11295 
11296 			/* Interfaces always report 0 load address & size.
11297 			 * Just the way they roll.
11298 			 *
11299 			 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
11300 			 * xxx - shouldn't have one!
11301 			 */
11302 
11303 			if (flags.builtin || linkedExecutable) {
11304 				kernel_mach_header_t     *mh  = NULL;
11305 				kernel_segment_command_t *seg = NULL;
11306 
11307 				if (flags.builtin) {
11308 					loadAddress = kmod_info->address;
11309 					loadSize    = (uint32_t)kmod_info->size;
11310 				} else {
11311 					loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
11312 					loadSize = linkedExecutable->getLength();
11313 				}
11314 				mh = (kernel_mach_header_t *)loadAddress;
11315 				loadAddress = ml_static_unslide(loadAddress);
11316 
11317 				/* Walk through the kext, looking for the first executable
11318 				 * segment in case we were asked for its size/address.
11319 				 */
11320 				for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
11321 					if (seg->initprot & VM_PROT_EXECUTE) {
11322 						execLoadAddress = ml_static_unslide(seg->vmaddr);
11323 						execLoadSize = (uint32_t)seg->vmsize;
11324 						break;
11325 					}
11326 				}
11327 
11328 				/* If we have a kmod_info struct, calculated the wired size
11329 				 * from that. Otherwise it's the full load size.
11330 				 */
11331 				if (kmod_info) {
11332 					wiredSize = loadSize - (uint32_t)kmod_info->hdr_size;
11333 				} else {
11334 					wiredSize = loadSize;
11335 				}
11336 			} else if (is_dext) {
11337 				/*
11338 				 * DriverKit userspace executables do not have a kernel linkedExecutable,
11339 				 * so we "fake" their address range with the LoadTag.
11340 				 */
11341 				if (loadTag) {
11342 					loadAddress = execLoadAddress = loadTag;
11343 					loadSize = execLoadSize = 1;
11344 				}
11345 			}
11346 
11347 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
11348 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11349 					(unsigned long long)(loadAddress),
11350 					/* numBits */ 8 * sizeof(loadAddress));
11351 				if (!scratchNumber) {
11352 					goto finish;
11353 				}
11354 				result->setObject(kOSBundleLoadAddressKey, scratchNumber.get());
11355 			}
11356 			if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) {
11357 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
11358 				    && loadAddress && loadSize) {
11359 					void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary);
11360 					if (!baseAddress) {
11361 						goto finish;
11362 					}
11363 
11364 					OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11365 						(unsigned long long)ml_static_unslide((vm_offset_t)baseAddress),
11366 						/* numBits */ 8 * sizeof(loadAddress));
11367 					if (!scratchNumber) {
11368 						goto finish;
11369 					}
11370 					result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get());
11371 				}
11372 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
11373 				    && (this == sKernelKext) && gBuiltinKmodsCount) {
11374 					result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
11375 				}
11376 			}
11377 
11378 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
11379 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11380 					(unsigned long long)(execLoadAddress),
11381 					/* numBits */ 8 * sizeof(execLoadAddress));
11382 				if (!scratchNumber) {
11383 					goto finish;
11384 				}
11385 				result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get());
11386 			}
11387 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
11388 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11389 					(unsigned long long)(loadSize),
11390 					/* numBits */ 8 * sizeof(loadSize));
11391 				if (!scratchNumber) {
11392 					goto finish;
11393 				}
11394 				result->setObject(kOSBundleLoadSizeKey, scratchNumber.get());
11395 			}
11396 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
11397 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11398 					(unsigned long long)(execLoadSize),
11399 					/* numBits */ 8 * sizeof(execLoadSize));
11400 				if (!scratchNumber) {
11401 					goto finish;
11402 				}
11403 				result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get());
11404 			}
11405 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
11406 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11407 					(unsigned long long)(wiredSize),
11408 					/* numBits */ 8 * sizeof(wiredSize));
11409 				if (!scratchNumber) {
11410 					goto finish;
11411 				}
11412 				result->setObject(kOSBundleWiredSizeKey, scratchNumber.get());
11413 			}
11414 		}
11415 	}
11416 
11417 	/* OSBundleDependencies. In descending order for
11418 	 * easy compatibility with kextstat(8).
11419 	 */
11420 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
11421 		if ((count = getNumDependencies())) {
11422 			dependencyLoadTags = OSArray::withCapacity(count);
11423 			result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get());
11424 
11425 			i = count - 1;
11426 			do {
11427 				OSKext * dependency = OSDynamicCast(OSKext,
11428 				    dependencies->getObject(i));
11429 
11430 				if (!dependency) {
11431 					continue;
11432 				}
11433 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11434 					(unsigned long long)dependency->getLoadTag(),
11435 					/* numBits*/ 8 * sizeof(loadTag));
11436 				if (!scratchNumber) {
11437 					goto finish;
11438 				}
11439 				dependencyLoadTags->setObject(scratchNumber.get());
11440 			} while (i--);
11441 		}
11442 	}
11443 
11444 	/* OSBundleMetaClasses.
11445 	 */
11446 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
11447 		if (metaClasses && metaClasses->getCount()) {
11448 			metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get());
11449 			metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
11450 			if (!metaClassIterator || !metaClassInfo) {
11451 				goto finish;
11452 			}
11453 			result->setObject(kOSBundleClassesKey, metaClassInfo.get());
11454 
11455 			while ((thisMetaClass = OSDynamicCast(OSMetaClass,
11456 			    metaClassIterator->getNextObject()))) {
11457 				metaClassDict = OSDictionary::withCapacity(3);
11458 				if (!metaClassDict) {
11459 					goto finish;
11460 				}
11461 
11462 				metaClassName = OSString::withCString(thisMetaClass->getClassName());
11463 				if (thisMetaClass->getSuperClass()) {
11464 					superclassName = OSString::withCString(
11465 						thisMetaClass->getSuperClass()->getClassName());
11466 				}
11467 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
11468 				    8 * sizeof(unsigned int));
11469 
11470 				/* Bail if any of the essentials is missing. The root class lacks a superclass,
11471 				 * of course.
11472 				 */
11473 				if (!metaClassDict || !metaClassName || !scratchNumber) {
11474 					goto finish;
11475 				}
11476 
11477 				metaClassInfo->setObject(metaClassDict.get());
11478 				metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get());
11479 				if (superclassName) {
11480 					metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get());
11481 				}
11482 				metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get());
11483 			}
11484 		}
11485 	}
11486 
11487 	/* OSBundleRetainCount.
11488 	 */
11489 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
11490 		{
11491 			int kextRetainCount = getRetainCount() - 1;
11492 			if (isLoaded()) {
11493 				kextRetainCount--;
11494 			}
11495 			OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11496 				(int)kextRetainCount,
11497 				/* numBits*/ 8 * sizeof(int));
11498 			if (scratchNumber) {
11499 				result->setObject(kOSBundleRetainCountKey, scratchNumber.get());
11500 			}
11501 		}
11502 	}
11503 
11504 	success = true;
11505 
11506 finish:
11507 	if (executablePathCString) {
11508 		kfree_data(executablePathCString, executablePathCStringSize);
11509 	}
11510 	if (!success) {
11511 		result.reset();
11512 	}
11513 	return result;
11514 }
11515 
11516 /*********************************************************************
11517 *********************************************************************/
11518 /* static */
11519 bool
11520 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
11521 {
11522 	bool ok;
11523 	OSSharedPtr<OSKext> kext;
11524 
11525 	IORecursiveLockLock(sKextLock);
11526 	kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain);
11527 	IORecursiveLockUnlock(sKextLock);
11528 
11529 	if (!kext || !kext->path || !kext->userExecutableRelPath) {
11530 		return false;
11531 	}
11532 	snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
11533 	    kext->path->getCStringNoCopy(),
11534 	    kext->userExecutableRelPath->getCStringNoCopy());
11535 	ok = true;
11536 
11537 	return ok;
11538 }
11539 
11540 /*********************************************************************
11541 *********************************************************************/
11542 /* static */
11543 OSReturn
11544 OSKext::requestResource(
11545 	const char                    * kextIdentifierCString,
11546 	const char                    * resourceNameCString,
11547 	OSKextRequestResourceCallback   callback,
11548 	void                          * context,
11549 	OSKextRequestTag              * requestTagOut)
11550 {
11551 	OSReturn                        result = kOSReturnError;
11552 	OSSharedPtr<OSKext>             callbackKext;        // looked up
11553 
11554 	OSKextRequestTag   requestTag      = -1;
11555 	OSSharedPtr<OSNumber>           requestTagNum;
11556 	OSSharedPtr<OSDictionary>       requestDict;
11557 	OSSharedPtr<OSString>           kextIdentifier;
11558 	OSSharedPtr<OSString>           resourceName;
11559 
11560 	OSSharedPtr<OSDictionary>       callbackRecord;
11561 	OSSharedPtr<OSData>             callbackWrapper;
11562 
11563 	OSSharedPtr<OSData>             contextWrapper;
11564 
11565 	IORecursiveLockLock(sKextLock);
11566 
11567 	if (requestTagOut) {
11568 		*requestTagOut = kOSKextRequestTagInvalid;
11569 	}
11570 
11571 	/* If requests to user space are disabled, don't go any further */
11572 	if (!sKernelRequestsEnabled) {
11573 		OSKextLog(/* kext */ NULL,
11574 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11575 		    "Can't request resource %s for %s - requests to user space are disabled.",
11576 		    resourceNameCString,
11577 		    kextIdentifierCString);
11578 		result = kOSKextReturnDisabled;
11579 		goto finish;
11580 	}
11581 
11582 	if (!kextIdentifierCString || !resourceNameCString || !callback) {
11583 		result = kOSKextReturnInvalidArgument;
11584 		goto finish;
11585 	}
11586 
11587 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
11588 	if (!callbackKext) {
11589 		OSKextLog(/* kext */ NULL,
11590 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11591 		    "Resource request has bad callback address.");
11592 		result = kOSKextReturnInvalidArgument;
11593 		goto finish;
11594 	}
11595 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
11596 		OSKextLog(/* kext */ NULL,
11597 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11598 		    "Resource request callback is in a kext that is not started.");
11599 		result = kOSKextReturnInvalidArgument;
11600 		goto finish;
11601 	}
11602 
11603 	/* Do not allow any new requests to be made on a kext that is unloading.
11604 	 */
11605 	if (callbackKext->flags.stopping) {
11606 		result = kOSKextReturnStopping;
11607 		goto finish;
11608 	}
11609 
11610 	/* If we're wrapped the next available request tag around to the negative
11611 	 * numbers, we can't service any more requests.
11612 	 */
11613 	if (sNextRequestTag == kOSKextRequestTagInvalid) {
11614 		OSKextLog(/* kext */ NULL,
11615 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11616 		    "No more request tags available; restart required.");
11617 		result = kOSKextReturnNoResources;
11618 		goto finish;
11619 	}
11620 	requestTag = sNextRequestTag++;
11621 
11622 	result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
11623 	    requestDict);
11624 	if (result != kOSReturnSuccess) {
11625 		goto finish;
11626 	}
11627 
11628 	kextIdentifier = OSString::withCString(kextIdentifierCString);
11629 	resourceName   = OSString::withCString(resourceNameCString);
11630 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
11631 	    8 * sizeof(requestTag));
11632 	if (!kextIdentifier ||
11633 	    !resourceName ||
11634 	    !requestTagNum ||
11635 	    !_OSKextSetRequestArgument(requestDict.get(),
11636 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) ||
11637 	    !_OSKextSetRequestArgument(requestDict.get(),
11638 	    kKextRequestArgumentNameKey, resourceName.get()) ||
11639 	    !_OSKextSetRequestArgument(requestDict.get(),
11640 	    kKextRequestArgumentRequestTagKey, requestTagNum.get())) {
11641 		result = kOSKextReturnNoMemory;
11642 		goto finish;
11643 	}
11644 
11645 	callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection());
11646 	if (!callbackRecord) {
11647 		result = kOSKextReturnNoMemory;
11648 		goto finish;
11649 	}
11650 	// we validate callback address at call time
11651 	callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *));
11652 	if (context) {
11653 		contextWrapper = OSData::withBytes((void *)&context, sizeof(void *));
11654 	}
11655 	if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
11656 	    kKextRequestArgumentCallbackKey, callbackWrapper.get())) {
11657 		result = kOSKextReturnNoMemory;
11658 		goto finish;
11659 	}
11660 
11661 	if (context) {
11662 		if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
11663 		    kKextRequestArgumentContextKey, contextWrapper.get())) {
11664 			result = kOSKextReturnNoMemory;
11665 			goto finish;
11666 		}
11667 	}
11668 
11669 	/* Only post the requests after all the other potential failure points
11670 	 * have been passed.
11671 	 */
11672 	if (!sKernelRequests->setObject(requestDict.get()) ||
11673 	    !sRequestCallbackRecords->setObject(callbackRecord.get())) {
11674 		result = kOSKextReturnNoMemory;
11675 		goto finish;
11676 	}
11677 
11678 	OSKext::pingIOKitDaemon();
11679 
11680 	result = kOSReturnSuccess;
11681 	if (requestTagOut) {
11682 		*requestTagOut = requestTag;
11683 	}
11684 
11685 finish:
11686 
11687 	/* If we didn't succeed, yank the request & callback
11688 	 * from their holding arrays.
11689 	 */
11690 	if (result != kOSReturnSuccess) {
11691 		unsigned int index;
11692 
11693 		index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0);
11694 		if (index != (unsigned int)-1) {
11695 			sKernelRequests->removeObject(index);
11696 		}
11697 		index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0);
11698 		if (index != (unsigned int)-1) {
11699 			sRequestCallbackRecords->removeObject(index);
11700 		}
11701 	}
11702 
11703 	OSKext::considerUnloads(/* rescheduleOnly? */ true);
11704 
11705 	IORecursiveLockUnlock(sKextLock);
11706 
11707 	return result;
11708 }
11709 
11710 OSReturn
11711 OSKext::requestDaemonLaunch(
11712 	OSString *kextIdentifier,
11713 	OSString *serverName,
11714 	OSNumber *serverTag,
11715 	IOUserServerCheckInToken * checkInToken)
11716 {
11717 	OSReturn       result        = kOSReturnError;
11718 	OSSharedPtr<OSDictionary> requestDict;
11719 
11720 	if (!kextIdentifier || !serverName || !serverTag || !checkInToken) {
11721 		return kOSKextReturnInvalidArgument;
11722 	}
11723 
11724 	IORecursiveLockLock(sKextLock);
11725 
11726 	OSKextLog(/* kext */ NULL,
11727 	    kOSKextLogDebugLevel |
11728 	    kOSKextLogGeneralFlag,
11729 	    "Requesting daemon launch for %s with serverName %s and tag %llu",
11730 	    kextIdentifier->getCStringNoCopy(),
11731 	    serverName->getCStringNoCopy(),
11732 	    serverTag->unsigned64BitValue()
11733 	    );
11734 
11735 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict);
11736 	if (result != kOSReturnSuccess) {
11737 		goto finish;
11738 	}
11739 
11740 	if (!_OSKextSetRequestArgument(requestDict.get(),
11741 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
11742 	    !_OSKextSetRequestArgument(requestDict.get(),
11743 	    kKextRequestArgumentDriverExtensionServerName, serverName) ||
11744 	    !_OSKextSetRequestArgument(requestDict.get(),
11745 	    kKextRequestArgumentDriverExtensionServerTag, serverTag) ||
11746 	    !_OSKextSetRequestArgument(requestDict.get(),
11747 	    kKextRequestArgumentCheckInToken, checkInToken)) {
11748 		result = kOSKextReturnNoMemory;
11749 		goto finish;
11750 	}
11751 
11752 	/* Only post the requests after all the other potential failure points
11753 	 * have been passed.
11754 	 */
11755 	if (!sKernelRequests->setObject(requestDict.get())) {
11756 		result = kOSKextReturnNoMemory;
11757 		goto finish;
11758 	}
11759 	OSKext::pingIOKitDaemon();
11760 
11761 	result = kOSReturnSuccess;
11762 finish:
11763 	IORecursiveLockUnlock(sKextLock);
11764 	return result;
11765 }
11766 
11767 /*********************************************************************
11768 * Assumes sKextLock is held.
11769 *********************************************************************/
11770 /* static */
11771 OSReturn
11772 OSKext::dequeueCallbackForRequestTag(
11773 	OSKextRequestTag    requestTag,
11774 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
11775 {
11776 	OSDictionary * callbackRecordOutRaw = NULL;
11777 	OSReturn result;
11778 
11779 	result = dequeueCallbackForRequestTag(requestTag,
11780 	    &callbackRecordOutRaw);
11781 
11782 	if (kOSReturnSuccess == result) {
11783 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
11784 	}
11785 
11786 	return result;
11787 }
11788 OSReturn
11789 OSKext::dequeueCallbackForRequestTag(
11790 	OSKextRequestTag    requestTag,
11791 	OSDictionary     ** callbackRecordOut)
11792 {
11793 	OSReturn   result = kOSReturnError;
11794 	OSSharedPtr<OSNumber> requestTagNum;
11795 
11796 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
11797 	    8 * sizeof(requestTag));
11798 	if (!requestTagNum) {
11799 		goto finish;
11800 	}
11801 
11802 	result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(),
11803 	    callbackRecordOut);
11804 
11805 finish:
11806 	return result;
11807 }
11808 
11809 /*********************************************************************
11810 * Assumes sKextLock is held.
11811 *********************************************************************/
11812 /* static */
11813 OSReturn
11814 OSKext::dequeueCallbackForRequestTag(
11815 	OSNumber     *    requestTagNum,
11816 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
11817 {
11818 	OSDictionary * callbackRecordOutRaw = NULL;
11819 	OSReturn result;
11820 
11821 	result = dequeueCallbackForRequestTag(requestTagNum,
11822 	    &callbackRecordOutRaw);
11823 
11824 	if (kOSReturnSuccess == result) {
11825 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
11826 	}
11827 
11828 	return result;
11829 }
11830 OSReturn
11831 OSKext::dequeueCallbackForRequestTag(
11832 	OSNumber     *    requestTagNum,
11833 	OSDictionary ** callbackRecordOut)
11834 {
11835 	OSReturn        result          = kOSKextReturnInvalidArgument;
11836 	OSDictionary  * callbackRecord  = NULL;        // retain if matched!
11837 	OSNumber      * callbackTagNum  = NULL;        // do not release
11838 	unsigned int    count, i;
11839 
11840 	result = kOSReturnError;
11841 	count = sRequestCallbackRecords->getCount();
11842 	for (i = 0; i < count; i++) {
11843 		callbackRecord = OSDynamicCast(OSDictionary,
11844 		    sRequestCallbackRecords->getObject(i));
11845 		if (!callbackRecord) {
11846 			goto finish;
11847 		}
11848 
11849 		/* If we don't find a tag, we basically have a leak here. Maybe
11850 		 * we should just remove it.
11851 		 */
11852 		callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
11853 			    callbackRecord, kKextRequestArgumentRequestTagKey));
11854 		if (!callbackTagNum) {
11855 			goto finish;
11856 		}
11857 
11858 		/* We could be even more paranoid and check that all the incoming
11859 		 * args match what's in the callback record.
11860 		 */
11861 		if (callbackTagNum->isEqualTo(requestTagNum)) {
11862 			if (callbackRecordOut) {
11863 				*callbackRecordOut = callbackRecord;
11864 				callbackRecord->retain();
11865 			}
11866 			sRequestCallbackRecords->removeObject(i);
11867 			result = kOSReturnSuccess;
11868 			goto finish;
11869 		}
11870 	}
11871 	result = kOSKextReturnNotFound;
11872 
11873 finish:
11874 	return result;
11875 }
11876 
11877 
11878 /*********************************************************************
11879 * Busy timeout triage
11880 *********************************************************************/
11881 /* static */
11882 bool
11883 OSKext::pendingIOKitDaemonRequests(void)
11884 {
11885 	return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
11886 }
11887 
11888 extern "C" int vm_enable_driverkit_shared_region;
11889 
11890 /*********************************************************************
11891 * Acquires and releases sKextLock
11892 *
11893 * This function is designed to be called exactly once on boot by
11894 * the IOKit management daemon, kernelmanagerd. It gathers all codeless
11895 * kext and dext personalities, and then attempts to map a System
11896 * (pageable) KC and an Auxiliary (aux) KC.
11897 *
11898 * Even if the pageable or aux KC fail to load - this function will
11899 * not allow a second call. This avoids security issues where
11900 * kernelmanagerd has been compromised or the pageable kc has been
11901 * tampered with and the attacker attempts to re-load a malicious
11902 * variant.
11903 *
11904 * Return: if a KC fails to load the return value will contain:
11905 *         kOSKextReturnKCLoadFailure. If the pageable KC fails,
11906 *         the return value will contain kOSKextReturnKCLoadFailureSystemKC.
11907 *         Similarly, if the aux kc load fails, the return value will
11908 *         contain kOSKextReturnKCLoadFailureAuxKC. The two values
11909 *         compose with each other and with kOSKextReturnKCLoadFailure.
11910 *********************************************************************/
11911 /* static */
11912 OSReturn
11913 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused)
11914 {
11915 	static bool daemon_ready = false;
11916 
11917 	OSReturn ret = kOSKextReturnInvalidArgument;
11918 	OSReturn kcerr = 0;
11919 	bool start_matching = false;
11920 
11921 	bool allow_fileset_load = !daemon_ready;
11922 #if !(defined(__x86_64__) || defined(__i386__))
11923 	/* never allow KCs full of kexts on non-x86 machines */
11924 	allow_fileset_load = false;
11925 #endif
11926 
11927 	/*
11928 	 * Change with 70582300
11929 	 */
11930 #if 0 || !defined(VM_MAPPED_KEXTS)
11931 	/*
11932 	 * On platforms that don't support the SystemKC or a file-backed
11933 	 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter
11934 	 * needs to be queried before we load any codeless kexts or release
11935 	 * any 3rd party kexts to run. On platforms that support a file-backed
11936 	 * AuxKC, this process is done via the kext audit mechanism.
11937 	 */
11938 
11939 	printf("KextLog: waiting for kext receipt to be queried.\n");
11940 	while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) {
11941 		IOSleep(30);
11942 	}
11943 #endif /* !VM_MAPPED_KEXTS */
11944 
11945 	/*
11946 	 * Get the args from the request. Right now we need the file
11947 	 * name for the pageable and the aux kext collection file sets.
11948 	 */
11949 	OSDictionary * requestArgs                = NULL;        // do not release
11950 	OSString     * pageable_filepath          = NULL;        // do not release
11951 	OSString     * aux_filepath               = NULL;        // do not release
11952 	OSArray      * codeless_kexts             = NULL;        // do not release
11953 	OSNumber     * enable_dk_shared_region    = NULL;        // do not release
11954 
11955 	kernel_mach_header_t *akc_mh              = NULL;
11956 
11957 	requestArgs = OSDynamicCast(OSDictionary,
11958 	    requestDict->getObject(kKextRequestArgumentsKey));
11959 
11960 	if (requestArgs == NULL) {
11961 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
11962 		    "KextLog: No arguments in plist for loading fileset kext\n");
11963 		printf("KextLog: No arguments in plist for loading fileset kext\n");
11964 		return ret;
11965 	}
11966 
11967 	ret = kOSKextReturnDisabled;
11968 
11969 	IORecursiveLockLock(sKextLock);
11970 
11971 	if (!sLoadEnabled) {
11972 		OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11973 		    "KextLog: Kext loading is disabled (attempt to load KCs).");
11974 		IORecursiveLockUnlock(sKextLock);
11975 		return ret;
11976 	}
11977 
11978 	pageable_filepath = OSDynamicCast(OSString,
11979 	    requestArgs->getObject(kKextRequestArgumentPageableKCFilename));
11980 
11981 	if (allow_fileset_load && pageable_filepath != NULL) {
11982 		printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy());
11983 
11984 		ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable);
11985 		if (ret) {
11986 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
11987 			    "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
11988 
11989 			printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
11990 			ret = kOSKextReturnKCLoadFailure;
11991 			kcerr |= kOSKextReturnKCLoadFailureSystemKC;
11992 			goto try_auxkc;
11993 		}
11994 		/*
11995 		 * Even if the AuxKC fails to load, we still want to send
11996 		 * the System KC personalities to the catalog for matching
11997 		 */
11998 		start_matching = true;
11999 	} else if (pageable_filepath != NULL) {
12000 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
12001 		    "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy());
12002 		ret = kOSKextReturnUnsupported;
12003 	}
12004 
12005 try_auxkc:
12006 	akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
12007 	if (akc_mh) {
12008 		/*
12009 		 * If we try to load a deferred AuxKC, then don't ever attempt
12010 		 * a filesystem map of a file
12011 		 */
12012 		allow_fileset_load = false;
12013 
12014 		/*
12015 		 * This function is only called once per boot, so we haven't
12016 		 * yet loaded an AuxKC. If we have registered the AuxKC mach
12017 		 * header, that means that the kext collection has been placed
12018 		 * in memory for us by the booter, and is waiting for us to
12019 		 * process it.  Grab the deferred XML plist of info
12020 		 * dictionaries and add all the kexts.
12021 		 */
12022 		OSSharedPtr<OSObject>  parsedXML;
12023 		OSSharedPtr<OSData>    loaded_kcUUID;
12024 		OSDictionary          *infoDict;
12025 		parsedXML = consumeDeferredKextCollection(KCKindAuxiliary);
12026 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
12027 #if !defined(VM_MAPPED_KEXTS)
12028 		/*
12029 		 * On platforms where we don't dynamically wire-down / page-in
12030 		 * kext memory, we need to maintain the invariant that if the
12031 		 * AuxKC in memory does not contain a kext receipt, then we
12032 		 * should not load any of the kexts.
12033 		 */
12034 		size_t receipt_sz = 0;
12035 		if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) {
12036 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12037 			    "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt");
12038 			ret = kOSKextReturnKCLoadFailure;
12039 			goto try_codeless;
12040 		}
12041 #endif
12042 		if (infoDict) {
12043 			bool added;
12044 			printf("KextLog: Adding kexts from in-memory AuxKC\n");
12045 			added = OSKext::addKextsFromKextCollection(akc_mh, infoDict,
12046 			    kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary);
12047 			if (!loaded_kcUUID) {
12048 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12049 				    "KextLog: WARNING: did not find UUID in deferred Aux KC!");
12050 			} else if (!added) {
12051 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12052 				    "KextLog: WARNING: Failed to load AuxKC from memory.");
12053 			}
12054 			/* only return success if the pageable load (above) was successful */
12055 			if (ret != kOSKextReturnKCLoadFailure) {
12056 				ret = kOSReturnSuccess;
12057 			}
12058 			/* the registration of the AuxKC parsed out the KC's UUID already */
12059 		} else {
12060 			if (daemon_ready) {
12061 				/*
12062 				 * Complain, but don't return an error if this isn't the first time the
12063 				 * IOKit daemon is checking in. If the daemon ever restarts, we will
12064 				 * hit this case because we've already consumed the deferred personalities.
12065 				 * We return success here so that a call to this function from a restarted
12066 				 * daemon with no codeless kexts will succeed.
12067 				 */
12068 				OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
12069 				    "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart");
12070 				if (ret != kOSKextReturnKCLoadFailure) {
12071 					ret = kOSReturnSuccess;
12072 				}
12073 			} else {
12074 				/* this is a real error case */
12075 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12076 				    "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary");
12077 				printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n");
12078 				ret = kOSKextReturnKCLoadFailure;
12079 				kcerr |= kOSKextReturnKCLoadFailureAuxKC;
12080 			}
12081 		}
12082 	}
12083 
12084 	aux_filepath = OSDynamicCast(OSString,
12085 	    requestArgs->getObject(kKextRequestArgumentAuxKCFilename));
12086 	if (allow_fileset_load && aux_filepath != NULL) {
12087 		printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy());
12088 
12089 		ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary);
12090 		if (ret) {
12091 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12092 			    "KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
12093 
12094 			printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
12095 			ret = kOSKextReturnKCLoadFailure;
12096 			kcerr |= kOSKextReturnKCLoadFailureAuxKC;
12097 			goto try_codeless;
12098 		}
12099 		start_matching = true;
12100 	} else if (aux_filepath != NULL) {
12101 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
12102 		    "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy());
12103 		if (ret != kOSKextReturnKCLoadFailure) {
12104 			ret = kOSKextReturnUnsupported;
12105 		}
12106 	}
12107 
12108 try_codeless:
12109 	/*
12110 	 * Load codeless kexts last so that there is no possibilty of a
12111 	 * codeless kext bundle ID preventing a kext in the system KC from
12112 	 * loading
12113 	 */
12114 	codeless_kexts = OSDynamicCast(OSArray,
12115 	    requestArgs->getObject(kKextRequestArgumentCodelessPersonalities));
12116 	if (codeless_kexts != NULL) {
12117 		uint32_t count = codeless_kexts->getCount();
12118 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12119 		    "KextLog: loading %d codeless kexts/dexts", count);
12120 		for (uint32_t i = 0; i < count; i++) {
12121 			OSDictionary *infoDict;
12122 			infoDict = OSDynamicCast(OSDictionary,
12123 			    codeless_kexts->getObject(i));
12124 			if (!infoDict) {
12125 				continue;
12126 			}
12127 			// instantiate a new kext, and don't hold a reference
12128 			// (the kext subsystem will hold one implicitly)
12129 			OSKext::withCodelessInfo(infoDict);
12130 		}
12131 		/* ignore errors that are not KC load failures */
12132 		if (ret != kOSKextReturnKCLoadFailure) {
12133 			ret = kOSReturnSuccess;
12134 		}
12135 		start_matching = true;
12136 	}
12137 
12138 	enable_dk_shared_region = OSDynamicCast(OSNumber,
12139 	    requestArgs->getObject(kKextRequestEnableDriverKitSharedRegionKey));
12140 	if (enable_dk_shared_region != NULL && enable_dk_shared_region->unsigned64BitValue() == 1) {
12141 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12142 		    "KextLog: Enabling DriverKit shared region.");
12143 		vm_enable_driverkit_shared_region = 1;
12144 	}
12145 
12146 	/* send personalities to the IOCatalog once */
12147 	if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) {
12148 		OSKext::sendAllKextPersonalitiesToCatalog(true);
12149 		/*
12150 		 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark
12151 		 * things as active and start all the delayed matching: the
12152 		 * dext and codeless kext personalities should have all been
12153 		 * delivered via this one call.
12154 		 */
12155 		if (!daemon_ready) {
12156 			OSKext::setIOKitDaemonActive();
12157 			OSKext::setDeferredLoadSucceeded(TRUE);
12158 			IOService::iokitDaemonLaunched();
12159 		}
12160 		if (sOSKextWasResetAfterUserspaceReboot) {
12161 			sOSKextWasResetAfterUserspaceReboot = false;
12162 			OSKext::setIOKitDaemonActive();
12163 			IOService::startDeferredMatches();
12164 		}
12165 	}
12166 
12167 	if (ret == kOSKextReturnKCLoadFailure) {
12168 		ret |= kcerr;
12169 	}
12170 
12171 	/*
12172 	 * Only allow this function to attempt to load the pageable and
12173 	 * aux KCs once per boot.
12174 	 */
12175 	daemon_ready = true;
12176 
12177 	IORecursiveLockUnlock(sKextLock);
12178 
12179 	return ret;
12180 }
12181 
12182 OSReturn
12183 OSKext::resetMutableSegments(void)
12184 {
12185 	kernel_segment_command_t *seg = NULL;
12186 	kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
12187 	u_int index = 0;
12188 	OSKextSavedMutableSegment *savedSegment = NULL;
12189 	uintptr_t kext_slide = PE_get_kc_slide(kc_type);
12190 	OSReturn err;
12191 
12192 	if (!savedMutableSegments) {
12193 		OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
12194 		    "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString());
12195 		err = kOSKextReturnInternalError;
12196 		goto finish;
12197 	}
12198 
12199 	for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) {
12200 		if (!segmentIsMutable(seg)) {
12201 			continue;
12202 		}
12203 		uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
12204 		uint64_t vmsize = seg->vmsize;
12205 		err = kOSKextReturnInternalError;
12206 		for (index = 0; index < savedMutableSegments->getCount(); index++) {
12207 			savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index));
12208 			assert(savedSegment);
12209 			if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) {
12210 				OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
12211 				    "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12212 				err = savedSegment->restoreContents(seg);
12213 				if (err != kOSReturnSuccess) {
12214 					panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12215 				}
12216 			}
12217 		}
12218 		if (err != kOSReturnSuccess) {
12219 			panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12220 		}
12221 	}
12222 	err = kOSReturnSuccess;
12223 finish:
12224 	return err;
12225 }
12226 
12227 
12228 /*********************************************************************
12229 * Assumes sKextLock is held.
12230 *********************************************************************/
12231 /* static */
12232 OSReturn
12233 OSKext::loadKCFileSet(
12234 	const char *filepath,
12235 	kc_kind_t   type)
12236 {
12237 #if VM_MAPPED_KEXTS
12238 	/* we only need to load filesets on systems that support VM_MAPPED kexts */
12239 	OSReturn err;
12240 	struct vnode *vp = NULL;
12241 	void *fileset_control;
12242 	off_t fsize;
12243 	bool pageable = (type == KCKindPageable);
12244 
12245 	if ((pageable && pageableKCloaded) ||
12246 	    (!pageable && auxKCloaded)) {
12247 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12248 		    "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux"));
12249 
12250 		return kOSKextReturnInvalidArgument;
12251 	}
12252 
12253 	/* Do not allow AuxKC to load if Pageable KC is not loaded */
12254 	if (!pageable && !pageableKCloaded) {
12255 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12256 		    "Trying to load the Aux KC without loading the Pageable KC");
12257 		return kOSKextReturnInvalidArgument;
12258 	}
12259 
12260 	fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize);
12261 
12262 	if (fileset_control == NULL) {
12263 		printf("Could not get memory control object for file %s", filepath);
12264 
12265 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12266 		    "Could not get memory control object for file %s", filepath);
12267 		return kOSKextReturnInvalidArgument;
12268 	}
12269 	if (vp == NULL) {
12270 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12271 		    "Could not find vnode for file %s", filepath);
12272 		return kOSKextReturnInvalidArgument;
12273 	}
12274 
12275 	kernel_mach_header_t *mh = NULL;
12276 	uintptr_t slide = 0;
12277 
12278 #if CONFIG_CSR
12279 	/*
12280 	 * When SIP is enabled, the KC we map must be SIP-protected
12281 	 */
12282 	if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) {
12283 		struct vnode_attr va;
12284 		int error;
12285 		VATTR_INIT(&va);
12286 		VATTR_WANTED(&va, va_flags);
12287 		error = vnode_getattr(vp, &va, vfs_context_current());
12288 		if (error) {
12289 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12290 			    "vnode_getattr(%s) failed (error=%d)", filepath, error);
12291 			err = kOSKextReturnInternalError;
12292 			goto finish;
12293 		}
12294 		if (!(va.va_flags & SF_RESTRICTED)) {
12295 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12296 			    "Path to KC '%s' is not SIP-protected", filepath);
12297 			err = kOSKextReturnInvalidArgument;
12298 			goto finish;
12299 		}
12300 	}
12301 #endif
12302 
12303 	err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL);
12304 	if (err) {
12305 		printf("KextLog: mapKCFileSet returned %d\n", err);
12306 
12307 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12308 		    "mapKCFileSet returned %d\n", err);
12309 
12310 		err = kOSKextReturnInvalidArgument;
12311 	}
12312 
12313 #if CONFIG_CSR
12314 finish:
12315 #endif
12316 	/* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */
12317 	assert(vp != NULL);
12318 	if (err == kOSReturnSuccess) {
12319 		PE_set_kc_vp(type, vp);
12320 		if (pageable) {
12321 			pageableKCloaded = true;
12322 		} else {
12323 			auxKCloaded = true;
12324 		}
12325 	} else {
12326 		vnode_put(vp);
12327 	}
12328 
12329 	return err;
12330 #else
12331 	(void)filepath;
12332 	(void)type;
12333 	return kOSKextReturnUnsupported;
12334 #endif // VM_MAPPED_KEXTS
12335 }
12336 
12337 #if defined(__x86_64__) || defined(__i386__)
12338 /*********************************************************************
12339 * Assumes sKextLock is held.
12340 *********************************************************************/
12341 /* static */
12342 OSReturn
12343 OSKext::mapKCFileSet(
12344 	void                 *control,
12345 	vm_size_t            fsize,
12346 	kernel_mach_header_t **mhp,
12347 	off_t                file_offset,
12348 	uintptr_t            *slidep,
12349 	bool                 pageable,
12350 	void                 *map_entry_list)
12351 {
12352 	bool fileset_load = false;
12353 	kern_return_t ret;
12354 	OSReturn err;
12355 	kernel_section_t *infoPlistSection = NULL;
12356 	OSDictionary *infoDict = NULL;
12357 
12358 	OSSharedPtr<OSObject> parsedXML;
12359 	OSSharedPtr<OSString> errorString;
12360 	OSSharedPtr<OSData> loaded_kcUUID;
12361 
12362 	/* Check if initial load for file set */
12363 	if (*mhp == NULL) {
12364 		fileset_load = true;
12365 
12366 		/* Get a page aligned address from kext map to map the file */
12367 		vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize);
12368 		if (pagealigned_addr == 0) {
12369 			return kOSKextReturnNoMemory;
12370 		}
12371 
12372 		*mhp = (kernel_mach_header_t *)pagealigned_addr;
12373 
12374 		/* Allocate memory for bailout mechanism */
12375 		map_entry_list = allocate_kcfileset_map_entry_list();
12376 		if (map_entry_list == NULL) {
12377 			return kOSKextReturnNoMemory;
12378 		}
12379 	}
12380 
12381 	uintptr_t *slideptr = fileset_load ? slidep : NULL;
12382 	err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list);
12383 	/* mhp and slideptr are updated by mapKCTextSegment */
12384 	if (err) {
12385 		if (fileset_load) {
12386 			deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12387 		}
12388 		return err;
12389 	}
12390 
12391 	/* Initialize the kc header globals */
12392 	if (fileset_load) {
12393 		if (pageable) {
12394 			PE_set_kc_header(KCKindPageable, *mhp, *slidep);
12395 		} else {
12396 			PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep);
12397 		}
12398 	}
12399 
12400 	/* Iterate through all the segments and map necessary segments */
12401 	struct load_command *lcp = (struct load_command *) (*mhp + 1);
12402 	for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) {
12403 		vm_map_offset_t start;
12404 		kernel_mach_header_t *k_mh = NULL;
12405 		kernel_segment_command_t * seg = NULL;
12406 		struct fileset_entry_command *fse = NULL;
12407 
12408 		if (lcp->cmd == LC_SEGMENT_KERNEL) {
12409 			seg = (kernel_segment_command_t *)lcp;
12410 			start = ((uintptr_t)(seg->vmaddr)) + *slidep;
12411 		} else if (lcp->cmd == LC_FILESET_ENTRY) {
12412 			fse = (struct fileset_entry_command *)lcp;
12413 			k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep);
12414 
12415 			/* Map the segments of the mach-o binary */
12416 			err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list);
12417 			if (err) {
12418 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12419 				return kOSKextReturnInvalidArgument;
12420 			}
12421 			continue;
12422 		} else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) {
12423 			/* Check if the Aux KC is built pageable style */
12424 			if (!pageable && !fileset_load && !auxKCloaded) {
12425 				resetAuxKCSegmentOnUnload = true;
12426 			}
12427 			continue;
12428 		} else {
12429 			continue;
12430 		}
12431 
12432 		if (fileset_load) {
12433 			if (seg->vmsize == 0) {
12434 				continue;
12435 			}
12436 
12437 			/* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */
12438 			if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 &&
12439 			    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 &&
12440 			    strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 &&
12441 			    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) {
12442 				continue;
12443 			}
12444 		} else {
12445 			if (seg->vmsize == 0) {
12446 				continue;
12447 			}
12448 
12449 			/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
12450 			if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
12451 			    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
12452 			    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
12453 				continue;
12454 			}
12455 		}
12456 
12457 		ret = vm_map_kcfileset_segment(
12458 			&start, seg->vmsize,
12459 			(memory_object_control_t)control, seg->fileoff, seg->maxprot);
12460 
12461 		if (ret != KERN_SUCCESS) {
12462 			if (fileset_load) {
12463 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12464 			}
12465 			return kOSKextReturnInvalidArgument;
12466 		}
12467 		add_kcfileset_map_entry(map_entry_list, start, seg->vmsize);
12468 	}
12469 
12470 	/* Return if regular mach-o */
12471 	if (!fileset_load) {
12472 		return 0;
12473 	}
12474 
12475 	/*
12476 	 * Fixup for the Pageable KC and the Aux KC is done by
12477 	 * i386_slide_kext_collection_mh_addrs, but it differs in
12478 	 * following ways:
12479 	 *
12480 	 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands.
12481 	 * The fixup of kext segments and kext load commands are done at kext
12482 	 * load time by calling i386_slide_individual_kext.
12483 	 *
12484 	 * AuxKC old style: Fixup all the segments and all the load commands.
12485 	 *
12486 	 * AuxKC pageable style: Same as the Pageable KC.
12487 	 */
12488 	bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false));
12489 	ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header);
12490 	if (ret != KERN_SUCCESS) {
12491 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12492 		return kOSKextReturnInvalidArgument;
12493 	}
12494 
12495 	/* Get the prelink info dictionary */
12496 	infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection);
12497 	parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
12498 	if (parsedXML) {
12499 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
12500 	}
12501 
12502 	if (!infoDict) {
12503 		const char *errorCString = "(unknown error)";
12504 
12505 		if (errorString && errorString->getCStringNoCopy()) {
12506 			errorCString = errorString->getCStringNoCopy();
12507 		} else if (parsedXML) {
12508 			errorCString = "not a dictionary";
12509 		}
12510 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12511 		    "Error unserializing kext info plist section: %s.", errorCString);
12512 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12513 		return kOSKextReturnInvalidArgument;
12514 	}
12515 
12516 	/* Validate that the Kext Collection is prelinked to the loaded KC */
12517 	err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary);
12518 	if (err) {
12519 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12520 		return kOSKextReturnInvalidArgument;
12521 	}
12522 
12523 	/* Set Protection of Segments */
12524 	OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary);
12525 
12526 	OSKext::addKextsFromKextCollection(*mhp,
12527 	    infoDict, kPrelinkTextSegment,
12528 	    loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary);
12529 
12530 	/* Copy in the KC UUID */
12531 	if (!loaded_kcUUID) {
12532 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12533 		    "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux");
12534 	} else if (pageable) {
12535 		pageablekc_uuid_valid = TRUE;
12536 		memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
12537 		uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string);
12538 	} else {
12539 		auxkc_uuid_valid = TRUE;
12540 		memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
12541 		uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
12542 	}
12543 
12544 	deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable);
12545 
12546 	return 0;
12547 }
12548 
12549 /*********************************************************************
12550 * Assumes sKextLock is held.
12551 *********************************************************************/
12552 /* static */
12553 OSReturn
12554 OSKext::mapKCTextSegment(
12555 	void                 *control,
12556 	kernel_mach_header_t **mhp,
12557 	off_t                file_offset,
12558 	uintptr_t            *slidep,
12559 	void                 *map_entry_list)
12560 {
12561 	kern_return_t ret;
12562 	vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t),
12563 	    PAGE_MASK);
12564 	vm_map_offset_t load_command_map_size = 0;
12565 	kernel_mach_header_t *base_mh = *mhp;
12566 
12567 	/* Map the mach header at start of fileset for now (vmaddr = 0) */
12568 	ret = vm_map_kcfileset_segment(
12569 		(vm_map_offset_t *)&base_mh, mach_header_map_size,
12570 		(memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE));
12571 
12572 	if (ret != KERN_SUCCESS) {
12573 		printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret);
12574 
12575 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12576 		    "Failed to map mach header of kc fileset with error %d", ret);
12577 		return kOSKextReturnInvalidArgument;
12578 	}
12579 
12580 	if (slidep) {
12581 		/* Verify that it's an MH_FILESET */
12582 		if (base_mh->filetype != MH_FILESET) {
12583 			printf("Kext Log: mapKCTextSegment mach header filetype"
12584 			    " is not an MH_FILESET, it is %x", base_mh->filetype);
12585 
12586 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12587 			    "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype);
12588 
12589 			/* Unmap the mach header */
12590 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12591 			return kOSKextReturnInvalidArgument;
12592 		}
12593 	}
12594 
12595 	/* Map the remaining pages of load commands */
12596 	if (base_mh->sizeofcmds > mach_header_map_size) {
12597 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
12598 		load_command_map_size = base_mh->sizeofcmds - mach_header_map_size;
12599 
12600 		/* Map the load commands */
12601 		ret = vm_map_kcfileset_segment(
12602 			&load_command_addr, load_command_map_size,
12603 			(memory_object_control_t)control, file_offset + mach_header_map_size,
12604 			(VM_PROT_READ | VM_PROT_WRITE));
12605 
12606 		if (ret != KERN_SUCCESS) {
12607 			printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret);
12608 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12609 			    "Failed to map load commands of kc fileset with error %d", ret);
12610 
12611 			/* Unmap the mach header */
12612 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12613 			return kOSKextReturnInvalidArgument;
12614 		}
12615 	}
12616 
12617 	kernel_segment_command_t *text_seg;
12618 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT);
12619 
12620 	/* Calculate the slide and vm addr of mach header */
12621 	if (slidep) {
12622 		*mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr);
12623 		*slidep = ((uintptr_t)*mhp) - text_seg->vmaddr;
12624 	}
12625 
12626 	/* Cache the text segment size and file offset before unmapping */
12627 	vm_map_offset_t text_segment_size = text_seg->vmsize;
12628 	vm_object_offset_t text_segment_fileoff = text_seg->fileoff;
12629 	vm_prot_t text_maxprot = text_seg->maxprot;
12630 
12631 	/* Unmap the first page and loadcommands and map the text segment */
12632 	ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12633 	assert(ret == KERN_SUCCESS);
12634 
12635 	if (load_command_map_size) {
12636 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
12637 		ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size);
12638 		assert(ret == KERN_SUCCESS);
12639 	}
12640 
12641 	/* Map the text segment at actual vm addr specified in fileset */
12642 	ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size,
12643 	    (memory_object_control_t)control, text_segment_fileoff, text_maxprot);
12644 	if (ret != KERN_SUCCESS) {
12645 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12646 		    "Failed to map Text segment of kc fileset with error %d", ret);
12647 		return kOSKextReturnInvalidArgument;
12648 	}
12649 
12650 	add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size);
12651 	return 0;
12652 }
12653 
12654 /*********************************************************************
12655 * Assumes sKextLock is held.
12656 *********************************************************************/
12657 /* static */
12658 OSReturn
12659 OSKext::protectKCFileSet(
12660 	kernel_mach_header_t *mh,
12661 	kc_kind_t            type)
12662 {
12663 	vm_map_t                    kext_map        = g_kext_map;
12664 	kernel_segment_command_t  * seg             = NULL;
12665 	vm_map_offset_t             start           = 0;
12666 	vm_map_offset_t             end             = 0;
12667 	OSReturn                    ret             = 0;
12668 
12669 	/* Set VM permissions */
12670 	seg = firstsegfromheader((kernel_mach_header_t *)mh);
12671 	while (seg) {
12672 		start = round_page(seg->vmaddr);
12673 		end = trunc_page(seg->vmaddr + seg->vmsize);
12674 
12675 		/*
12676 		 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS
12677 		 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT
12678 		 * for the Aux KC as well.
12679 		 */
12680 		if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 ||
12681 		    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 ||
12682 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 ||
12683 		    (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload &&
12684 		    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) {
12685 			ret = OSKext_protect((kernel_mach_header_t *)mh,
12686 			    kext_map, start, end, seg->maxprot, TRUE, type);
12687 			if (ret != KERN_SUCCESS) {
12688 				printf("OSKext protect failed with error %d", ret);
12689 				return kOSKextReturnInvalidArgument;
12690 			}
12691 
12692 			ret = OSKext_protect((kernel_mach_header_t *)mh,
12693 			    kext_map, start, end, seg->initprot, FALSE, type);
12694 			if (ret != KERN_SUCCESS) {
12695 				printf("OSKext protect failed with error %d", ret);
12696 				return kOSKextReturnInvalidArgument;
12697 			}
12698 
12699 			ret = OSKext_wire((kernel_mach_header_t *)mh,
12700 			    kext_map, start, end, seg->initprot, FALSE, type);
12701 			if (ret != KERN_SUCCESS) {
12702 				printf("OSKext wire failed with error %d", ret);
12703 				return kOSKextReturnInvalidArgument;
12704 			}
12705 		}
12706 
12707 		seg = nextsegfromheader((kernel_mach_header_t *) mh, seg);
12708 	}
12709 
12710 	return 0;
12711 }
12712 
12713 /*********************************************************************
12714 * Assumes sKextLock is held.
12715 *********************************************************************/
12716 /* static */
12717 void
12718 OSKext::freeKCFileSetcontrol(void)
12719 {
12720 	PE_reset_all_kc_vp();
12721 }
12722 
12723 /*********************************************************************
12724 * Assumes sKextLock is held.
12725 *
12726 * resetKCFileSetSegments: Kext start function expects data segment to
12727 * be pristine on every load, unmap the dirty segments on unload and
12728 * remap them from FileSet on disk. Remap all segments of kext since
12729 * fixups are done per kext and not per segment.
12730 *********************************************************************/
12731 OSReturn
12732 OSKext::resetKCFileSetSegments(void)
12733 {
12734 	kernel_segment_command_t *seg = NULL;
12735 	kernel_segment_command_t *text_seg;
12736 	uint32_t text_fileoff;
12737 	kernel_mach_header_t *k_mh = NULL;
12738 	uintptr_t slide;
12739 	struct vnode *vp = NULL;
12740 	void *fileset_control = NULL;
12741 	bool pageable = (kc_type == KCKindPageable);
12742 	OSReturn err;
12743 	kern_return_t kr;
12744 
12745 	/* Check the vnode reference is still available */
12746 	vp = (struct vnode *)PE_get_kc_vp(kc_type);
12747 	if (vp == NULL) {
12748 		OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
12749 		    "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString());
12750 		return kOSKextReturnInternalError;
12751 	}
12752 
12753 	fileset_control = ubc_getobject(vp, 0);
12754 	assert(fileset_control != NULL);
12755 
12756 	OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
12757 	    "Kext %s resetting all segments", getIdentifierCString());
12758 
12759 	k_mh = (kernel_mach_header_t *)kmod_info->address;
12760 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT);
12761 	text_fileoff = text_seg->fileoff;
12762 	slide = PE_get_kc_slide(kc_type);
12763 
12764 	seg = firstsegfromheader((kernel_mach_header_t *)k_mh);
12765 	while (seg) {
12766 		if (seg->vmsize == 0) {
12767 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12768 			continue;
12769 		}
12770 
12771 		/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
12772 		if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
12773 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
12774 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
12775 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12776 			continue;
12777 		}
12778 
12779 		kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize);
12780 		assert(kr == KERN_SUCCESS);
12781 		seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12782 	}
12783 
12784 	/* Unmap the text segment */
12785 	kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize);
12786 	assert(kr == KERN_SUCCESS);
12787 
12788 	/* Map all the segments of the kext */
12789 	err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL);
12790 	if (err) {
12791 		panic("Could not reset segments of a mapped kext, error %x", err);
12792 	}
12793 
12794 	/* Update address in kmod_info, since it has been reset */
12795 	if (kmod_info->address) {
12796 		kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide);
12797 	}
12798 
12799 	return 0;
12800 }
12801 
12802 /*********************************************************************
12803 * Mechanism to track all segment mapping while mapping KC fileset.
12804 *********************************************************************/
12805 
12806 struct kcfileset_map_entry {
12807 	vm_map_offset_t me_start;
12808 	vm_map_offset_t me_size;
12809 };
12810 
12811 struct kcfileset_map_entry_list {
12812 	int                        kme_list_count;
12813 	int                        kme_list_index;
12814 	struct kcfileset_map_entry kme_list[];
12815 };
12816 
12817 #define KCFILESET_MAP_ENTRY_MAX (16380)
12818 
12819 static void *
12820 allocate_kcfileset_map_entry_list(void)
12821 {
12822 	struct kcfileset_map_entry_list *entry_list;
12823 
12824 	entry_list = kalloc_type(struct kcfileset_map_entry_list,
12825 	    struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO);
12826 
12827 	entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX;
12828 	entry_list->kme_list_index = 0;
12829 	return entry_list;
12830 }
12831 
12832 static void
12833 add_kcfileset_map_entry(
12834 	void            *map_entry_list,
12835 	vm_map_offset_t start,
12836 	vm_map_offset_t size)
12837 {
12838 	if (map_entry_list == NULL) {
12839 		return;
12840 	}
12841 
12842 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
12843 
12844 	if (entry_list->kme_list_index >= entry_list->kme_list_count) {
12845 		panic("Ran out of map kc fileset list");
12846 	}
12847 
12848 	entry_list->kme_list[entry_list->kme_list_index].me_start = start;
12849 	entry_list->kme_list[entry_list->kme_list_index].me_size = size;
12850 
12851 	entry_list->kme_list_index++;
12852 }
12853 
12854 static void
12855 deallocate_kcfileset_map_entry_list_and_unmap_entries(
12856 	void      *map_entry_list,
12857 	boolean_t unmap_entries,
12858 	bool      pageable)
12859 {
12860 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
12861 
12862 	if (unmap_entries) {
12863 		for (int i = 0; i < entry_list->kme_list_index; i++) {
12864 			kern_return_t ret;
12865 			ret = vm_unmap_kcfileset_segment(
12866 				&(entry_list->kme_list[i].me_start),
12867 				entry_list->kme_list[i].me_size);
12868 			assert(ret == KERN_SUCCESS);
12869 		}
12870 
12871 		PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary);
12872 	}
12873 
12874 	kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry,
12875 	    KCFILESET_MAP_ENTRY_MAX, entry_list);
12876 }
12877 
12878 /*********************************************************************
12879 * Mechanism to map kext segment.
12880 *********************************************************************/
12881 
12882 kern_return_t
12883 vm_map_kcfileset_segment(
12884 	vm_map_offset_t    *start,
12885 	vm_map_offset_t    size,
12886 	void               *control,
12887 	vm_object_offset_t fileoffset,
12888 	vm_prot_t          max_prot)
12889 {
12890 	vm_map_kernel_flags_t vmk_flags;
12891 	vmk_flags.vmkf_no_copy_on_read = 1;
12892 	vmk_flags.vmkf_cs_enforcement = 0;
12893 	vmk_flags.vmkf_cs_enforcement_override = 1;
12894 	kern_return_t ret;
12895 
12896 	/* Add Write to max prot to allow fixups */
12897 	max_prot = max_prot | VM_PROT_WRITE;
12898 
12899 	/*
12900 	 * Map the segments from file as COPY mappings to
12901 	 * make sure changes on disk to the file does not affect
12902 	 * mapped segments.
12903 	 */
12904 	ret = vm_map_enter_mem_object_control(
12905 		g_kext_map,
12906 		start,
12907 		size,
12908 		(mach_vm_offset_t)0,
12909 		VM_FLAGS_FIXED,
12910 		vmk_flags,
12911 		VM_KERN_MEMORY_OSKEXT,
12912 		(memory_object_control_t)control,
12913 		fileoffset,
12914 		TRUE,         /* copy */
12915 		(VM_PROT_READ | VM_PROT_WRITE), max_prot,
12916 		VM_INHERIT_NONE);
12917 
12918 	return ret;
12919 }
12920 
12921 kern_return_t
12922 vm_unmap_kcfileset_segment(
12923 	vm_map_offset_t    *start,
12924 	vm_map_offset_t    size)
12925 {
12926 	return mach_vm_deallocate(g_kext_map, *start, size);
12927 }
12928 
12929 #endif //(__x86_64__) || defined(__i386__)
12930 
12931 /*********************************************************************
12932 * Assumes sKextLock is held.
12933 *********************************************************************/
12934 /* static */
12935 OSReturn
12936 OSKext::validateKCFileSetUUID(
12937 	OSDictionary         *infoDict,
12938 	kc_kind_t            type)
12939 {
12940 	OSReturn ret           = kOSReturnSuccess;
12941 
12942 	if (!kernelcache_uuid_valid) {
12943 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12944 		    "validateKCFileSetUUID Boot KC UUID was not set at boot.");
12945 		ret = kOSKextReturnInvalidArgument;
12946 		goto finish;
12947 	}
12948 	ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey);
12949 	if (ret != 0) {
12950 		goto finish;
12951 	}
12952 
12953 #if defined(__x86_64__) || defined(__i386__)
12954 	/* Check if the Aux KC is prelinked to correct Pageable KC */
12955 	if (type == KCKindAuxiliary) {
12956 		if (!pageablekc_uuid_valid) {
12957 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12958 			    "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC.");
12959 			ret = kOSKextReturnInvalidArgument;
12960 			goto finish;
12961 		}
12962 		ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey);
12963 		if (ret != 0) {
12964 			goto finish;
12965 		}
12966 	}
12967 #endif //(__x86_64__) || defined(__i386__)
12968 
12969 	printf("KextLog: Collection UUID matches with loaded KCs.\n");
12970 finish:
12971 	return ret;
12972 }
12973 
12974 /*********************************************************************
12975 * Assumes sKextLock is held.
12976 *********************************************************************/
12977 /* static */
12978 OSReturn
12979 OSKext::validateKCUUIDfromPrelinkInfo(
12980 	uuid_t               *loaded_kcuuid,
12981 	kc_kind_t             type,
12982 	OSDictionary         *infoDict,
12983 	const char           *uuid_key)
12984 {
12985 	/* extract the UUID from the dictionary */
12986 	OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key));
12987 	if (!prelinkinfoKCUUID) {
12988 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12989 		    "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key);
12990 		return kOSKextReturnInvalidArgument;
12991 	}
12992 
12993 	if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) {
12994 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12995 		    "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength());
12996 		return kOSKextReturnInvalidArgument;
12997 	}
12998 
12999 	if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(),
13000 	    prelinkinfoKCUUID->getLength())) {
13001 		OSData       *info_dict_uuid;
13002 		uuid_string_t info_dict_uuid_str = {};
13003 		uuid_string_t expected_uuid_str = {};
13004 		uuid_string_t given_uuid_str = {};
13005 		uuid_t        given_uuid;
13006 
13007 		/* extract the KC UUID from the dictionary */
13008 		info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
13009 		if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) {
13010 			uuid_t tmp_uuid;
13011 			memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid));
13012 			uuid_unparse(tmp_uuid, info_dict_uuid_str);
13013 		}
13014 
13015 		uuid_unparse(*loaded_kcuuid, expected_uuid_str);
13016 		memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid));
13017 		uuid_unparse(given_uuid, given_uuid_str);
13018 
13019 		printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
13020 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
13021 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13022 		    "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
13023 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
13024 		if (type == KCKindPageable && sPanicOnKCMismatch) {
13025 			panic("System KC UUID %s linked against %s, but %s is loaded",
13026 			    info_dict_uuid_str, given_uuid_str, expected_uuid_str);
13027 		}
13028 		return kOSKextReturnInvalidArgument;
13029 	}
13030 
13031 	return 0;
13032 }
13033 
13034 /*********************************************************************
13035 * Assumes sKextLock is held.
13036 *********************************************************************/
13037 /* static */
13038 OSReturn
13039 OSKext::dispatchResource(OSDictionary * requestDict)
13040 {
13041 	OSReturn                        result          = kOSReturnError;
13042 	OSSharedPtr<OSDictionary>       callbackRecord;
13043 	OSNumber                      * requestTag      = NULL;        // do not release
13044 	OSNumber                      * requestResult   = NULL;        // do not release
13045 	OSData                        * dataObj         = NULL;        // do not release
13046 	uint32_t                        dataLength      = 0;
13047 	const void                    * dataPtr         = NULL;        // do not free
13048 	OSData                        * callbackWrapper = NULL;        // do not release
13049 	OSKextRequestResourceCallback   callback        = NULL;
13050 	OSData                        * contextWrapper  = NULL;        // do not release
13051 	void                          * context         = NULL;        // do not free
13052 	OSSharedPtr<OSKext>             callbackKext;
13053 
13054 	/* Get the args from the request. Right now we need the tag
13055 	 * to look up the callback record, and the result for invoking the callback.
13056 	 */
13057 	requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
13058 	    kKextRequestArgumentRequestTagKey));
13059 	requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
13060 	    kKextRequestArgumentResultKey));
13061 	if (!requestTag || !requestResult) {
13062 		result = kOSKextReturnInvalidArgument;
13063 		goto finish;
13064 	}
13065 
13066 	/* Look for a callback record matching this request's tag.
13067 	 */
13068 	result = dequeueCallbackForRequestTag(requestTag, callbackRecord);
13069 	if (result != kOSReturnSuccess) {
13070 		goto finish;
13071 	}
13072 
13073 	/*****
13074 	 * Get the context pointer of the callback record (if there is one).
13075 	 */
13076 	contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord.get(),
13077 	    kKextRequestArgumentContextKey));
13078 	context = _OSKextExtractPointer(contextWrapper);
13079 	if (contextWrapper && !context) {
13080 		goto finish;
13081 	}
13082 
13083 	callbackWrapper = OSDynamicCast(OSData,
13084 	    _OSKextGetRequestArgument(callbackRecord.get(),
13085 	    kKextRequestArgumentCallbackKey));
13086 	callback = _OSKextExtractCallbackPointer(callbackWrapper);
13087 	if (!callback) {
13088 		goto finish;
13089 	}
13090 
13091 	/* Check for a data obj. We might not have one and that's ok, that means
13092 	 * we didn't find the requested resource, and we still have to tell the
13093 	 * caller that via the callback.
13094 	 */
13095 	dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
13096 	    kKextRequestArgumentValueKey));
13097 	if (dataObj) {
13098 		dataPtr = dataObj->getBytesNoCopy();
13099 		dataLength = dataObj->getLength();
13100 	}
13101 
13102 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
13103 	if (!callbackKext) {
13104 		OSKextLog(/* kext */ NULL,
13105 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13106 		    "Can't invoke callback for resource request; ");
13107 		goto finish;
13108 	}
13109 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
13110 		OSKextLog(/* kext */ NULL,
13111 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13112 		    "Can't invoke kext resource callback; ");
13113 		goto finish;
13114 	}
13115 
13116 	(void)callback(requestTag->unsigned32BitValue(),
13117 	    (OSReturn)requestResult->unsigned32BitValue(),
13118 	    dataPtr, dataLength, context);
13119 
13120 	result = kOSReturnSuccess;
13121 
13122 finish:
13123 	return result;
13124 }
13125 
13126 /*********************************************************************
13127 * Assumes sKextLock is held.
13128 *********************************************************************/
13129 /* static */
13130 OSReturn
13131 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict)
13132 {
13133 	OSSharedPtr<OSDictionary> missingIDs;
13134 	OSArray *bundleIDList     = NULL; // do not release
13135 
13136 	bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
13137 		    requestDict, kKextRequestArgumentMissingBundleIDs));
13138 	if (!bundleIDList) {
13139 		return kOSKextReturnInvalidArgument;
13140 	}
13141 
13142 	missingIDs = OSDictionary::withCapacity(bundleIDList->getCount());
13143 	if (!missingIDs) {
13144 		return kOSKextReturnNoMemory;
13145 	}
13146 
13147 	uint32_t count, i;
13148 	count = bundleIDList->getCount();
13149 	for (i = 0; i < count; i++) {
13150 		OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i));
13151 		if (thisID) {
13152 			missingIDs->setObject(thisID, kOSBooleanFalse);
13153 		}
13154 	}
13155 
13156 	sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain);
13157 
13158 	return kOSReturnSuccess;
13159 }
13160 
13161 /*********************************************************************
13162 * Assumes sKextLock is held.
13163 *********************************************************************/
13164 /* static */
13165 OSReturn
13166 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict)
13167 {
13168 	bool loadable = true;
13169 	if (!kextIdentifier) {
13170 		return kOSKextReturnInvalidArgument;
13171 	}
13172 
13173 	if (requestDict) {
13174 		OSBoolean *loadableArg;
13175 		loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
13176 			    requestDict, kKextRequestArgumentBundleAvailability));
13177 		/* If we find the "Bundle Available" arg, and it's false, then
13178 		 * mark the bundle ID as _not_ loadable
13179 		 */
13180 		if (loadableArg && !loadableArg->getValue()) {
13181 			loadable = false;
13182 		}
13183 	}
13184 
13185 	if (!sNonLoadableKextsByID) {
13186 		sNonLoadableKextsByID = OSDictionary::withCapacity(1);
13187 	}
13188 
13189 	sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable));
13190 
13191 	OSKextLog(/* kext */ NULL,
13192 	    kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13193 	    "KextLog: AuxKC bundle %s marked as %s",
13194 	    kextIdentifier->getCStringNoCopy(),
13195 	    (loadable ? "loadable" : "NOT loadable"));
13196 
13197 	return kOSReturnSuccess;
13198 }
13199 
13200 /*********************************************************************
13201 *********************************************************************/
13202 /* static */
13203 void
13204 OSKext::invokeRequestCallback(
13205 	OSDictionary * callbackRecord,
13206 	OSReturn       callbackResult)
13207 {
13208 	OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
13209 	OSSharedPtr<OSNumber> resultNum;
13210 
13211 	if (!predicate) {
13212 		goto finish;
13213 	}
13214 
13215 	resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
13216 	    8 * sizeof(callbackResult));
13217 	if (!resultNum) {
13218 		goto finish;
13219 	}
13220 
13221 	/* Insert the result into the callback record and dispatch it as if it
13222 	 * were the reply coming down from user space.
13223 	 */
13224 	_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
13225 	    resultNum.get());
13226 
13227 	if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
13228 		/* This removes the pending callback record.
13229 		 */
13230 		OSKext::dispatchResource(callbackRecord);
13231 	}
13232 
13233 finish:
13234 	return;
13235 }
13236 
13237 /*********************************************************************
13238 * Assumes sKextLock is held.
13239 *********************************************************************/
13240 /* static */
13241 OSReturn
13242 OSKext::cancelRequest(
13243 	OSKextRequestTag    requestTag,
13244 	void             ** contextOut)
13245 {
13246 	OSReturn       result         = kOSKextReturnNoMemory;
13247 	OSSharedPtr<OSDictionary> callbackRecord;
13248 	OSData       * contextWrapper = NULL;        // do not release
13249 
13250 	IORecursiveLockLock(sKextLock);
13251 	result = OSKext::dequeueCallbackForRequestTag(requestTag,
13252 	    callbackRecord);
13253 	IORecursiveLockUnlock(sKextLock);
13254 
13255 	if (result == kOSReturnSuccess && contextOut) {
13256 		contextWrapper = OSDynamicCast(OSData,
13257 		    _OSKextGetRequestArgument(callbackRecord.get(),
13258 		    kKextRequestArgumentContextKey));
13259 		*contextOut = _OSKextExtractPointer(contextWrapper);
13260 	}
13261 
13262 	return result;
13263 }
13264 
13265 /*********************************************************************
13266 * Assumes sKextLock is held.
13267 *********************************************************************/
13268 void
13269 OSKext::invokeOrCancelRequestCallbacks(
13270 	OSReturn callbackResult,
13271 	bool     invokeFlag)
13272 {
13273 	unsigned int count, i;
13274 
13275 	count = sRequestCallbackRecords->getCount();
13276 	if (!count) {
13277 		goto finish;
13278 	}
13279 
13280 	i = count - 1;
13281 	do {
13282 		OSDictionary * request = OSDynamicCast(OSDictionary,
13283 		    sRequestCallbackRecords->getObject(i));
13284 
13285 		if (!request) {
13286 			continue;
13287 		}
13288 		OSData * callbackWrapper = OSDynamicCast(OSData,
13289 		    _OSKextGetRequestArgument(request,
13290 		    kKextRequestArgumentCallbackKey));
13291 
13292 		if (!callbackWrapper) {
13293 			sRequestCallbackRecords->removeObject(i);
13294 			continue;
13295 		}
13296 
13297 		vm_address_t callbackAddress = (vm_address_t)
13298 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
13299 
13300 		if ((kmod_info->address <= callbackAddress) &&
13301 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
13302 			if (invokeFlag) {
13303 				/* This removes the callback record.
13304 				 */
13305 				invokeRequestCallback(request, callbackResult);
13306 			} else {
13307 				sRequestCallbackRecords->removeObject(i);
13308 			}
13309 		}
13310 	} while (i--);
13311 
13312 finish:
13313 	return;
13314 }
13315 
13316 /*********************************************************************
13317 * Assumes sKextLock is held.
13318 *********************************************************************/
13319 uint32_t
13320 OSKext::countRequestCallbacks(void)
13321 {
13322 	uint32_t     result = 0;
13323 	unsigned int count, i;
13324 
13325 	count = sRequestCallbackRecords->getCount();
13326 	if (!count) {
13327 		goto finish;
13328 	}
13329 
13330 	i = count - 1;
13331 	do {
13332 		OSDictionary * request = OSDynamicCast(OSDictionary,
13333 		    sRequestCallbackRecords->getObject(i));
13334 
13335 		if (!request) {
13336 			continue;
13337 		}
13338 		OSData * callbackWrapper = OSDynamicCast(OSData,
13339 		    _OSKextGetRequestArgument(request,
13340 		    kKextRequestArgumentCallbackKey));
13341 
13342 		if (!callbackWrapper) {
13343 			continue;
13344 		}
13345 
13346 		vm_address_t callbackAddress = (vm_address_t)
13347 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
13348 
13349 		if ((kmod_info->address <= callbackAddress) &&
13350 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
13351 			result++;
13352 		}
13353 	} while (i--);
13354 
13355 finish:
13356 	return result;
13357 }
13358 
13359 /*********************************************************************
13360 *********************************************************************/
13361 static OSReturn
13362 _OSKextCreateRequest(
13363 	const char    * predicate,
13364 	OSSharedPtr<OSDictionary> & requestR)
13365 {
13366 	OSReturn result = kOSKextReturnNoMemory;
13367 	OSSharedPtr<OSDictionary> request;
13368 
13369 	request = OSDictionary::withCapacity(2);
13370 	if (!request) {
13371 		goto finish;
13372 	}
13373 	result = _OSDictionarySetCStringValue(request.get(),
13374 	    kKextRequestPredicateKey, predicate);
13375 	if (result != kOSReturnSuccess) {
13376 		goto finish;
13377 	}
13378 	result = kOSReturnSuccess;
13379 
13380 finish:
13381 	if (result == kOSReturnSuccess) {
13382 		requestR = os::move(request);
13383 	}
13384 
13385 	return result;
13386 }
13387 
13388 /*********************************************************************
13389 *********************************************************************/
13390 static OSString *
13391 _OSKextGetRequestPredicate(OSDictionary * requestDict)
13392 {
13393 	return OSDynamicCast(OSString,
13394 	           requestDict->getObject(kKextRequestPredicateKey));
13395 }
13396 
13397 /*********************************************************************
13398 *********************************************************************/
13399 static OSObject *
13400 _OSKextGetRequestArgument(
13401 	OSDictionary * requestDict,
13402 	const char   * argName)
13403 {
13404 	OSDictionary * args = OSDynamicCast(OSDictionary,
13405 	    requestDict->getObject(kKextRequestArgumentsKey));
13406 	if (args) {
13407 		return args->getObject(argName);
13408 	}
13409 	return NULL;
13410 }
13411 
13412 /*********************************************************************
13413 *********************************************************************/
13414 static bool
13415 _OSKextSetRequestArgument(
13416 	OSDictionary * requestDict,
13417 	const char   * argName,
13418 	OSObject     * value)
13419 {
13420 	OSDictionary * args = OSDynamicCast(OSDictionary,
13421 	    requestDict->getObject(kKextRequestArgumentsKey));
13422 	OSSharedPtr<OSDictionary> newArgs;
13423 	if (!args) {
13424 		newArgs = OSDictionary::withCapacity(2);
13425 		args = newArgs.get();
13426 		if (!args) {
13427 			goto finish;
13428 		}
13429 		requestDict->setObject(kKextRequestArgumentsKey, args);
13430 	}
13431 	if (args) {
13432 		return args->setObject(argName, value);
13433 	}
13434 finish:
13435 	return false;
13436 }
13437 
13438 /*********************************************************************
13439 *********************************************************************/
13440 static void *
13441 _OSKextExtractPointer(OSData * wrapper)
13442 {
13443 	void       * result = NULL;
13444 	const void * resultPtr = NULL;
13445 
13446 	if (!wrapper) {
13447 		goto finish;
13448 	}
13449 	resultPtr = wrapper->getBytesNoCopy();
13450 	result = *(void **)resultPtr;
13451 finish:
13452 	return result;
13453 }
13454 
13455 /*********************************************************************
13456 *********************************************************************/
13457 static OSKextRequestResourceCallback
13458 _OSKextExtractCallbackPointer(OSData * wrapper)
13459 {
13460 	OSKextRequestResourceCallback       result = NULL;
13461 	const void * resultPtr = NULL;
13462 
13463 	if (!wrapper) {
13464 		goto finish;
13465 	}
13466 	resultPtr = wrapper->getBytesNoCopy();
13467 	result = *(OSKextRequestResourceCallback *)resultPtr;
13468 finish:
13469 	return result;
13470 }
13471 
13472 
13473 /*********************************************************************
13474 *********************************************************************/
13475 static OSReturn
13476 _OSDictionarySetCStringValue(
13477 	OSDictionary * dict,
13478 	const char   * cKey,
13479 	const char   * cValue)
13480 {
13481 	OSReturn result = kOSKextReturnNoMemory;
13482 	OSSharedPtr<const OSSymbol> key;
13483 	OSSharedPtr<OSString> value;
13484 
13485 	key = OSSymbol::withCString(cKey);
13486 	value = OSString::withCString(cValue);
13487 	if (!key || !value) {
13488 		goto finish;
13489 	}
13490 	if (dict->setObject(key.get(), value.get())) {
13491 		result = kOSReturnSuccess;
13492 	}
13493 
13494 finish:
13495 	return result;
13496 }
13497 
13498 /*********************************************************************
13499 *********************************************************************/
13500 static bool
13501 _OSArrayContainsCString(
13502 	OSArray    * array,
13503 	const char * cString)
13504 {
13505 	bool             result = false;
13506 	OSSharedPtr<const OSSymbol> symbol;
13507 	uint32_t         count, i;
13508 
13509 	if (!array || !cString) {
13510 		goto finish;
13511 	}
13512 
13513 	symbol = OSSymbol::withCStringNoCopy(cString);
13514 	if (!symbol) {
13515 		goto finish;
13516 	}
13517 
13518 	count = array->getCount();
13519 	for (i = 0; i < count; i++) {
13520 		OSObject * thisObject = array->getObject(i);
13521 		if (symbol->isEqualTo(thisObject)) {
13522 			result = true;
13523 			goto finish;
13524 		}
13525 	}
13526 
13527 finish:
13528 	return result;
13529 }
13530 
13531 #if CONFIG_KXLD
13532 /*********************************************************************
13533 * We really only care about boot / system start up related kexts.
13534 * We return true if we're less than REBUILD_MAX_TIME since start up,
13535 * otherwise return false.
13536 *********************************************************************/
13537 bool
13538 _OSKextInPrelinkRebuildWindow(void)
13539 {
13540 	static bool     outside_the_window = false;
13541 	AbsoluteTime    my_abstime;
13542 	UInt64          my_ns;
13543 	SInt32          my_secs;
13544 
13545 	if (outside_the_window) {
13546 		return false;
13547 	}
13548 	clock_get_uptime(&my_abstime);
13549 	absolutetime_to_nanoseconds(my_abstime, &my_ns);
13550 	my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
13551 	if (my_secs > REBUILD_MAX_TIME) {
13552 		outside_the_window = true;
13553 		return false;
13554 	}
13555 	return true;
13556 }
13557 #endif /* CONFIG_KXLD */
13558 
13559 /*********************************************************************
13560 *********************************************************************/
13561 bool
13562 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
13563 {
13564 	int unLoadedCount, i;
13565 	bool result = false;
13566 
13567 	IORecursiveLockLock(sKextLock);
13568 
13569 	if (sUnloadedPrelinkedKexts == NULL) {
13570 		goto finish;
13571 	}
13572 	unLoadedCount = sUnloadedPrelinkedKexts->getCount();
13573 	if (unLoadedCount == 0) {
13574 		goto finish;
13575 	}
13576 
13577 	for (i = 0; i < unLoadedCount; i++) {
13578 		const OSSymbol *    myBundleID;        // do not release
13579 
13580 		myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
13581 		if (!myBundleID) {
13582 			continue;
13583 		}
13584 		if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
13585 			result = true;
13586 			break;
13587 		}
13588 	}
13589 finish:
13590 	IORecursiveLockUnlock(sKextLock);
13591 	return result;
13592 }
13593 
13594 #if PRAGMA_MARK
13595 #pragma mark Personalities (IOKit Drivers)
13596 #endif
13597 /*********************************************************************
13598 *********************************************************************/
13599 /* static */
13600 OSSharedPtr<OSArray>
13601 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
13602 {
13603 	OSSharedPtr<OSArray>              result;
13604 	OSSharedPtr<OSCollectionIterator> kextIterator;
13605 	OSSharedPtr<OSArray>              personalities;
13606 
13607 	OSString             * kextID                = NULL;        // do not release
13608 	OSKext               * theKext               = NULL;        // do not release
13609 
13610 	IORecursiveLockLock(sKextLock);
13611 
13612 	/* Let's conservatively guess that any given kext has around 3
13613 	 * personalities for now.
13614 	 */
13615 	result = OSArray::withCapacity(sKextsByID->getCount() * 3);
13616 	if (!result) {
13617 		goto finish;
13618 	}
13619 
13620 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
13621 	if (!kextIterator) {
13622 		goto finish;
13623 	}
13624 
13625 	while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
13626 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
13627 		if (theKext->flags.requireExplicitLoad) {
13628 			OSKextLog(theKext,
13629 			    kOSKextLogDebugLevel |
13630 			    kOSKextLogLoadFlag,
13631 			    "Kext %s requires an explicit kextload; "
13632 			    "omitting its personalities.",
13633 			    theKext->getIdentifierCString());
13634 		} else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
13635 			personalities = theKext->copyPersonalitiesArray();
13636 			if (!personalities) {
13637 				continue;
13638 			}
13639 			result->merge(personalities.get());
13640 		} else {
13641 			// xxx - check for better place to put this log msg
13642 			OSKextLog(theKext,
13643 			    kOSKextLogWarningLevel |
13644 			    kOSKextLogLoadFlag,
13645 			    "Kext %s is not loadable during safe boot; "
13646 			    "omitting its personalities.",
13647 			    theKext->getIdentifierCString());
13648 		}
13649 	}
13650 
13651 finish:
13652 	IORecursiveLockUnlock(sKextLock);
13653 
13654 	return result;
13655 }
13656 
13657 /*********************************************************************
13658 *********************************************************************/
13659 /* static */
13660 void
13661 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
13662 {
13663 	int numPersonalities = 0;
13664 
13665 	OSKextLog(/* kext */ NULL,
13666 	    kOSKextLogStepLevel |
13667 	    kOSKextLogLoadFlag,
13668 	    "Sending all eligible registered kexts' personalities "
13669 	    "to the IOCatalogue %s.",
13670 	    startMatching ? "and starting matching" : "but not starting matching");
13671 
13672 	OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities(
13673 		/* filterSafeBootFlag */ true);
13674 
13675 	if (personalities) {
13676 		gIOCatalogue->addDrivers(personalities.get(), startMatching);
13677 		numPersonalities = personalities->getCount();
13678 	}
13679 
13680 	OSKextLog(/* kext */ NULL,
13681 	    kOSKextLogStepLevel |
13682 	    kOSKextLogLoadFlag,
13683 	    "%d kext personalit%s sent to the IOCatalogue; %s.",
13684 	    numPersonalities, numPersonalities > 0 ? "ies" : "y",
13685 	    startMatching ? "matching started" : "matching not started");
13686 	return;
13687 }
13688 
13689 /*********************************************************************
13690 * Do not make a deep copy, just convert the IOKitPersonalities dict
13691 * to an array for sending to the IOCatalogue.
13692 *********************************************************************/
13693 OSSharedPtr<OSArray>
13694 OSKext::copyPersonalitiesArray(void)
13695 {
13696 	OSSharedPtr<OSArray>              result;
13697 	OSDictionary         * personalities               = NULL;        // do not release
13698 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
13699 
13700 	OSString             * personalityName             = NULL;        // do not release
13701 	OSString             * personalityBundleIdentifier = NULL;        // do not release
13702 
13703 	personalities = OSDynamicCast(OSDictionary,
13704 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
13705 	if (!personalities) {
13706 		goto finish;
13707 	}
13708 
13709 	result = OSArray::withCapacity(personalities->getCount());
13710 	if (!result) {
13711 		goto finish;
13712 	}
13713 
13714 	personalitiesIterator =
13715 	    OSCollectionIterator::withCollection(personalities);
13716 	if (!personalitiesIterator) {
13717 		goto finish;
13718 	}
13719 	while ((personalityName = OSDynamicCast(OSString,
13720 	    personalitiesIterator->getNextObject()))) {
13721 		OSDictionary * personality = OSDynamicCast(OSDictionary,
13722 		    personalities->getObject(personalityName));
13723 
13724 		/******
13725 		 * If the personality doesn't have a CFBundleIdentifier, or if it
13726 		 * differs from the kext's, insert the kext's ID so we can find it.
13727 		 * The publisher ID is used to remove personalities from bundles
13728 		 * correctly.
13729 		 */
13730 		personalityBundleIdentifier = OSDynamicCast(OSString,
13731 		    personality->getObject(kCFBundleIdentifierKey));
13732 
13733 		if (!personalityBundleIdentifier) {
13734 			personality->setObject(kCFBundleIdentifierKey, bundleID.get());
13735 		} else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) {
13736 			personality->setObject(kIOPersonalityPublisherKey, bundleID.get());
13737 		}
13738 
13739 		result->setObject(personality);
13740 	}
13741 
13742 finish:
13743 	return result;
13744 }
13745 
13746 /*********************************************************************
13747 *   Might want to change this to a bool return?
13748 *********************************************************************/
13749 OSReturn
13750 OSKext::sendPersonalitiesToCatalog(
13751 	bool      startMatching,
13752 	OSArray * personalityNames)
13753 {
13754 	OSReturn       result              = kOSReturnSuccess;
13755 	OSSharedPtr<OSArray> personalitiesToSend;
13756 	OSDictionary * kextPersonalities   = NULL;        // do not release
13757 	int            count, i;
13758 
13759 	if (!sLoadEnabled) {
13760 		OSKextLog(this,
13761 		    kOSKextLogErrorLevel |
13762 		    kOSKextLogLoadFlag,
13763 		    "Kext loading is disabled (attempt to start matching for kext %s).",
13764 		    getIdentifierCString());
13765 		result = kOSKextReturnDisabled;
13766 		goto finish;
13767 	}
13768 
13769 	if (sSafeBoot && !isLoadableInSafeBoot()) {
13770 		OSKextLog(this,
13771 		    kOSKextLogErrorLevel |
13772 		    kOSKextLogLoadFlag,
13773 		    "Kext %s is not loadable during safe boot; "
13774 		    "not sending personalities to the IOCatalogue.",
13775 		    getIdentifierCString());
13776 		result = kOSKextReturnNotLoadable;
13777 		goto finish;
13778 	}
13779 
13780 	if (!personalityNames || !personalityNames->getCount()) {
13781 		personalitiesToSend = copyPersonalitiesArray();
13782 	} else {
13783 		kextPersonalities = OSDynamicCast(OSDictionary,
13784 		    getPropertyForHostArch(kIOKitPersonalitiesKey));
13785 		if (!kextPersonalities || !kextPersonalities->getCount()) {
13786 			// not an error
13787 			goto finish;
13788 		}
13789 		personalitiesToSend = OSArray::withCapacity(0);
13790 		if (!personalitiesToSend) {
13791 			result = kOSKextReturnNoMemory;
13792 			goto finish;
13793 		}
13794 		count = personalityNames->getCount();
13795 		for (i = 0; i < count; i++) {
13796 			OSString * name = OSDynamicCast(OSString,
13797 			    personalityNames->getObject(i));
13798 			if (!name) {
13799 				continue;
13800 			}
13801 			OSDictionary * personality = OSDynamicCast(OSDictionary,
13802 			    kextPersonalities->getObject(name));
13803 			if (personality) {
13804 				personalitiesToSend->setObject(personality);
13805 			}
13806 		}
13807 	}
13808 	if (personalitiesToSend) {
13809 		unsigned numPersonalities = personalitiesToSend->getCount();
13810 		OSKextLog(this,
13811 		    kOSKextLogStepLevel |
13812 		    kOSKextLogLoadFlag,
13813 		    "Kext %s sending %d personalit%s to the IOCatalogue%s.",
13814 		    getIdentifierCString(),
13815 		    numPersonalities,
13816 		    numPersonalities > 1 ? "ies" : "y",
13817 		    startMatching ? " and starting matching" : " but not starting matching");
13818 		gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching);
13819 	}
13820 finish:
13821 	return result;
13822 }
13823 
13824 /*********************************************************************
13825 * xxx - We should allow removing the kext's declared personalities,
13826 * xxx - even with other bundle identifiers.
13827 *********************************************************************/
13828 void
13829 OSKext::removePersonalitiesFromCatalog(void)
13830 {
13831 	OSSharedPtr<OSDictionary> personality;
13832 
13833 	personality = OSDictionary::withCapacity(1);
13834 	if (!personality) {
13835 		goto finish;
13836 	}
13837 	personality->setObject(kCFBundleIdentifierKey, getIdentifier());
13838 
13839 	OSKextLog(this,
13840 	    kOSKextLogStepLevel |
13841 	    kOSKextLogLoadFlag,
13842 	    "Kext %s removing all personalities naming it from the IOCatalogue.",
13843 	    getIdentifierCString());
13844 
13845 	/* Have the IOCatalog remove all personalities matching this kext's
13846 	 * bundle ID and trigger matching anew.
13847 	 */
13848 	gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true);
13849 
13850 finish:
13851 	return;
13852 }
13853 
13854 
13855 #if PRAGMA_MARK
13856 #pragma mark Logging
13857 #endif
13858 /*********************************************************************
13859 * Do not call any function that takes sKextLock here!
13860 *********************************************************************/
13861 /* static */
13862 OSKextLogSpec
13863 OSKext::setUserSpaceLogFilter(
13864 	OSKextLogSpec   newUserLogFilter,
13865 	bool            captureFlag)
13866 {
13867 	OSKextLogSpec result;
13868 	bool          allocError = false;
13869 
13870 	/* Do not call any function that takes sKextLoggingLock during
13871 	 * this critical block. That means do logging after.
13872 	 */
13873 	IOLockLock(sKextLoggingLock);
13874 
13875 	result = sUserSpaceKextLogFilter;
13876 	sUserSpaceKextLogFilter = newUserLogFilter;
13877 
13878 	if (newUserLogFilter && captureFlag &&
13879 	    !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
13880 		// xxx - do some measurements for a good initial capacity?
13881 		sUserSpaceLogSpecArray = OSArray::withCapacity(0);
13882 		sUserSpaceLogMessageArray = OSArray::withCapacity(0);
13883 
13884 		if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
13885 			allocError = true;
13886 		}
13887 	}
13888 
13889 	IOLockUnlock(sKextLoggingLock);
13890 
13891 	/* If the config flag itself is changing, log the state change
13892 	 * going both ways, before setting up the user-space log arrays,
13893 	 * so that this is only logged in the kernel.
13894 	 */
13895 	if (result != newUserLogFilter) {
13896 		OSKextLog(/* kext */ NULL,
13897 		    kOSKextLogDebugLevel |
13898 		    kOSKextLogGeneralFlag,
13899 		    "User-space log flags changed from 0x%x to 0x%x.",
13900 		    result, newUserLogFilter);
13901 	}
13902 	if (allocError) {
13903 		OSKextLog(/* kext */ NULL,
13904 		    kOSKextLogErrorLevel |
13905 		    kOSKextLogGeneralFlag,
13906 		    "Failed to allocate user-space log message arrays.");
13907 	}
13908 
13909 	return result;
13910 }
13911 
13912 /*********************************************************************
13913 * Do not call any function that takes sKextLock here!
13914 *********************************************************************/
13915 /* static */
13916 OSSharedPtr<OSArray>
13917 OSKext::clearUserSpaceLogFilter(void)
13918 {
13919 	OSSharedPtr<OSArray>       result;
13920 	OSKextLogSpec   oldLogFilter;
13921 	OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
13922 
13923 	/* Do not call any function that takes sKextLoggingLock during
13924 	 * this critical block. That means do logging after.
13925 	 */
13926 	IOLockLock(sKextLoggingLock);
13927 
13928 	result = OSArray::withCapacity(2);
13929 	if (result) {
13930 		result->setObject(sUserSpaceLogSpecArray.get());
13931 		result->setObject(sUserSpaceLogMessageArray.get());
13932 	}
13933 	sUserSpaceLogSpecArray.reset();
13934 	sUserSpaceLogMessageArray.reset();
13935 
13936 	oldLogFilter = sUserSpaceKextLogFilter;
13937 	sUserSpaceKextLogFilter = newLogFilter;
13938 
13939 	IOLockUnlock(sKextLoggingLock);
13940 
13941 	/* If the config flag itself is changing, log the state change
13942 	 * going both ways, after tearing down the user-space log
13943 	 * arrays, so this is only logged within the kernel.
13944 	 */
13945 	if (oldLogFilter != newLogFilter) {
13946 		OSKextLog(/* kext */ NULL,
13947 		    kOSKextLogDebugLevel |
13948 		    kOSKextLogGeneralFlag,
13949 		    "User-space log flags changed from 0x%x to 0x%x.",
13950 		    oldLogFilter, newLogFilter);
13951 	}
13952 
13953 	return result;
13954 }
13955 
13956 
13957 /*********************************************************************
13958 * Do not call any function that takes sKextLock here!
13959 *********************************************************************/
13960 /* static */
13961 OSKextLogSpec
13962 OSKext::getUserSpaceLogFilter(void)
13963 {
13964 	OSKextLogSpec result;
13965 
13966 	IOLockLock(sKextLoggingLock);
13967 	result = sUserSpaceKextLogFilter;
13968 	IOLockUnlock(sKextLoggingLock);
13969 
13970 	return result;
13971 }
13972 
13973 /*********************************************************************
13974 * This function is called by OSMetaClass during kernel C++ setup.
13975 * Be careful what you access here; assume only OSKext::initialize()
13976 * has been called.
13977 *
13978 * Do not call any function that takes sKextLock here!
13979 *********************************************************************/
13980 #define VTRESET   "\033[0m"
13981 
13982 #define VTBOLD    "\033[1m"
13983 #define VTUNDER   "\033[4m"
13984 
13985 #define VTRED     "\033[31m"
13986 #define VTGREEN   "\033[32m"
13987 #define VTYELLOW  "\033[33m"
13988 #define VTBLUE    "\033[34m"
13989 #define VTMAGENTA "\033[35m"
13990 #define VTCYAN    "\033[36m"
13991 
13992 inline const char *
13993 colorForFlags(OSKextLogSpec flags)
13994 {
13995 	OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
13996 
13997 	switch (logLevel) {
13998 	case kOSKextLogErrorLevel:
13999 		return VTRED VTBOLD;
14000 	case kOSKextLogWarningLevel:
14001 		return VTRED;
14002 	case kOSKextLogBasicLevel:
14003 		return VTYELLOW VTUNDER;
14004 	case kOSKextLogProgressLevel:
14005 		return VTYELLOW;
14006 	case kOSKextLogStepLevel:
14007 		return VTGREEN;
14008 	case kOSKextLogDetailLevel:
14009 		return VTCYAN;
14010 	case kOSKextLogDebugLevel:
14011 		return VTMAGENTA;
14012 	default:
14013 		return "";         // white
14014 	}
14015 }
14016 
14017 inline bool
14018 logSpecMatch(
14019 	OSKextLogSpec msgLogSpec,
14020 	OSKextLogSpec logFilter)
14021 {
14022 	OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
14023 	OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
14024 	OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
14025 
14026 	OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
14027 	OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
14028 	OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
14029 
14030 	/* Explicit messages always get logged.
14031 	 */
14032 	if (msgLevel == kOSKextLogExplicitLevel) {
14033 		return true;
14034 	}
14035 
14036 	/* Warnings and errors are logged regardless of the flags.
14037 	 */
14038 	if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
14039 		return true;
14040 	}
14041 
14042 	/* A verbose message that isn't for a logging-enabled kext and isn't global
14043 	 * does *not* get logged.
14044 	 */
14045 	if (!msgKextGlobal && !filterKextGlobal) {
14046 		return false;
14047 	}
14048 
14049 	/* Warnings and errors are logged regardless of the flags.
14050 	 * All other messages must fit the flags and
14051 	 * have a level at or below the filter.
14052 	 *
14053 	 */
14054 	if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
14055 		return true;
14056 	}
14057 	return false;
14058 }
14059 
14060 extern "C" {
14061 void
14062 OSKextLog(
14063 	OSKext         * aKext,
14064 	OSKextLogSpec    msgLogSpec,
14065 	const char     * format, ...)
14066 {
14067 	va_list argList;
14068 
14069 	va_start(argList, format);
14070 	OSKextVLog(aKext, msgLogSpec, format, argList);
14071 	va_end(argList);
14072 }
14073 
14074 void
14075 OSKextVLog(
14076 	OSKext         * aKext,
14077 	OSKextLogSpec    msgLogSpec,
14078 	const char     * format,
14079 	va_list          srcArgList)
14080 {
14081 	extern int       disableConsoleOutput;
14082 
14083 	bool             logForKernel       = false;
14084 	bool             logForUser         = false;
14085 	va_list          argList;
14086 	char             stackBuffer[120];
14087 	uint32_t         length            = 0;
14088 	char           * allocBuffer       = NULL;        // must kfree
14089 	OSSharedPtr<OSNumber> logSpecNum;
14090 	OSSharedPtr<OSString> logString;
14091 	char           * buffer            = stackBuffer;        // do not free
14092 
14093 	IOLockLock(sKextLoggingLock);
14094 
14095 	/* Set the kext/global bit in the message spec if we have no
14096 	 * kext or if the kext requests logging.
14097 	 */
14098 	if (!aKext || aKext->flags.loggingEnabled) {
14099 		msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
14100 	}
14101 
14102 	logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
14103 	if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
14104 		logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
14105 	}
14106 
14107 	if (!(logForKernel || logForUser)) {
14108 		goto finish;
14109 	}
14110 
14111 	/* No goto from here until past va_end()!
14112 	 */
14113 	va_copy(argList, srcArgList);
14114 	length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
14115 	va_end(argList);
14116 
14117 	if (length + 1 >= sizeof(stackBuffer)) {
14118 		allocBuffer = (char *)kalloc_data_tag(length + 1,
14119 		    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
14120 		if (!allocBuffer) {
14121 			goto finish;
14122 		}
14123 
14124 		/* No goto from here until past va_end()!
14125 		 */
14126 		va_copy(argList, srcArgList);
14127 		vsnprintf(allocBuffer, length + 1, format, argList);
14128 		va_end(argList);
14129 
14130 		buffer = allocBuffer;
14131 	}
14132 
14133 	/* If user space wants the log message, queue it up.
14134 	 */
14135 	if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
14136 		logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
14137 		logString = OSString::withCString(buffer);
14138 		if (logSpecNum && logString) {
14139 			sUserSpaceLogSpecArray->setObject(logSpecNum.get());
14140 			sUserSpaceLogMessageArray->setObject(logString.get());
14141 		}
14142 	}
14143 
14144 	/* Always log messages from the kernel according to the kernel's
14145 	 * log flags.
14146 	 */
14147 	if (logForKernel) {
14148 		/* If we are in console mode and have a custom log filter,
14149 		 * colorize the log message.
14150 		 */
14151 		if (!disableConsoleOutput && sBootArgLogFilterFound) {
14152 			const char * color = "";         // do not free
14153 			color = colorForFlags(msgLogSpec);
14154 			printf("%s%s%s\n", colorForFlags(msgLogSpec),
14155 			    buffer, color[0] ? VTRESET : "");
14156 		} else {
14157 			printf("%s\n", buffer);
14158 		}
14159 	}
14160 
14161 finish:
14162 	IOLockUnlock(sKextLoggingLock);
14163 
14164 	if (allocBuffer) {
14165 		kfree_data(allocBuffer, length + 1);
14166 	}
14167 	return;
14168 }
14169 
14170 #if KASLR_IOREG_DEBUG
14171 
14172 #define IOLOG_INDENT( the_indention ) \
14173 { \
14174     int     i; \
14175     for ( i = 0; i < (the_indention); i++ ) { \
14176 	IOLog(" "); \
14177     } \
14178 }
14179 
14180 extern vm_offset_t       vm_kernel_stext;
14181 extern vm_offset_t       vm_kernel_etext;
14182 extern mach_vm_offset_t kext_alloc_base;
14183 extern mach_vm_offset_t kext_alloc_max;
14184 
14185 bool ScanForAddrInObject(OSObject * theObject,
14186     int indent );
14187 
14188 bool
14189 ScanForAddrInObject(OSObject * theObject,
14190     int indent)
14191 {
14192 	const OSMetaClass *     myTypeID;
14193 	OSSharedPtr<OSCollectionIterator>  myIter;
14194 	OSSymbol *              myKey;
14195 	OSObject *              myValue;
14196 	bool                    myResult = false;
14197 
14198 	if (theObject == NULL) {
14199 		IOLog("%s: theObject is NULL \n",
14200 		    __FUNCTION__);
14201 		return myResult;
14202 	}
14203 
14204 	myTypeID = OSTypeIDInst(theObject);
14205 
14206 	if (myTypeID == OSTypeID(OSDictionary)) {
14207 		OSDictionary *      myDictionary;
14208 
14209 		myDictionary = OSDynamicCast(OSDictionary, theObject);
14210 		myIter = OSCollectionIterator::withCollection( myDictionary );
14211 		if (myIter == NULL) {
14212 			return myResult;
14213 		}
14214 
14215 		// !! reset the iterator
14216 		myIter->reset();
14217 
14218 		while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
14219 			bool    myTempResult;
14220 
14221 			myValue = myDictionary->getObject(myKey);
14222 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
14223 			if (myTempResult) {
14224 				// if we ever get a true result return true
14225 				myResult = true;
14226 				IOLOG_INDENT(indent);
14227 				IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
14228 			}
14229 		}
14230 
14231 		// !! release the iterator
14232 		myIter.reset();
14233 	} else if (myTypeID == OSTypeID(OSArray)) {
14234 		OSArray *   myArray;
14235 
14236 		myArray = OSDynamicCast(OSArray, theObject);
14237 		myIter = OSCollectionIterator::withCollection(myArray);
14238 		if (myIter == NULL) {
14239 			return myResult;
14240 		}
14241 		// !! reset the iterator
14242 		myIter->reset();
14243 
14244 		while ((myValue = myIter->getNextObject())) {
14245 			bool        myTempResult;
14246 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
14247 			if (myTempResult) {
14248 				// if we ever get a true result return true
14249 				myResult = true;
14250 				IOLOG_INDENT(indent);
14251 				IOLog("OSArray: \n");
14252 			}
14253 		}
14254 		// !! release the iterator
14255 		myIter.reset();
14256 	} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
14257 		// should we look for addresses in strings?
14258 	} else if (myTypeID == OSTypeID(OSData)) {
14259 		void * *        myPtrPtr;
14260 		unsigned int    myLen;
14261 		OSData *        myDataObj;
14262 
14263 		myDataObj =    OSDynamicCast(OSData, theObject);
14264 		myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
14265 		myLen = myDataObj->getLength();
14266 
14267 		if (myPtrPtr && myLen && myLen > 7) {
14268 			int     i;
14269 			int     myPtrCount = (myLen / sizeof(void *));
14270 
14271 			for (i = 0; i < myPtrCount; i++) {
14272 				UInt64 numberValue = (UInt64) * (myPtrPtr);
14273 
14274 				if (kext_alloc_max != 0 &&
14275 				    numberValue >= kext_alloc_base &&
14276 				    numberValue < kext_alloc_max) {
14277 					OSSharedPtr<OSKext> myKext;
14278 					// IOLog("found OSData %p in kext map %p to %p  \n",
14279 					//       *(myPtrPtr),
14280 					//       (void *) kext_alloc_base,
14281 					//       (void *) kext_alloc_max);
14282 
14283 					myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
14284 					if (myKext) {
14285 						IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
14286 						    *(myPtrPtr),
14287 						    myKext->getIdentifierCString());
14288 					}
14289 					myResult = true;
14290 				}
14291 				if (vm_kernel_etext != 0 &&
14292 				    numberValue >= vm_kernel_stext &&
14293 				    numberValue < vm_kernel_etext) {
14294 					IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
14295 					    *(myPtrPtr),
14296 					    (void *) vm_kernel_stext,
14297 					    (void *) vm_kernel_etext);
14298 					myResult = true;
14299 				}
14300 				myPtrPtr++;
14301 			}
14302 		}
14303 	} else if (myTypeID == OSTypeID(OSBoolean)) {
14304 		// do nothing here...
14305 	} else if (myTypeID == OSTypeID(OSNumber)) {
14306 		OSNumber * number = OSDynamicCast(OSNumber, theObject);
14307 
14308 		UInt64 numberValue = number->unsigned64BitValue();
14309 
14310 		if (kext_alloc_max != 0 &&
14311 		    numberValue >= kext_alloc_base &&
14312 		    numberValue < kext_alloc_max) {
14313 			OSSharedPtr<OSKext> myKext;
14314 			IOLog("found OSNumber in kext map %p to %p  \n",
14315 			    (void *) kext_alloc_base,
14316 			    (void *) kext_alloc_max);
14317 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
14318 
14319 			myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
14320 			if (myKext) {
14321 				IOLog("found in kext \"%s\"  \n",
14322 				    myKext->getIdentifierCString());
14323 			}
14324 
14325 			myResult = true;
14326 		}
14327 		if (vm_kernel_etext != 0 &&
14328 		    numberValue >= vm_kernel_stext &&
14329 		    numberValue < vm_kernel_etext) {
14330 			IOLog("found OSNumber in kernel text segment %p to %p  \n",
14331 			    (void *) vm_kernel_stext,
14332 			    (void *) vm_kernel_etext);
14333 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
14334 			myResult = true;
14335 		}
14336 	}
14337 #if 0
14338 	else {
14339 		const OSMetaClass* myMetaClass = NULL;
14340 
14341 		myMetaClass = theObject->getMetaClass();
14342 		if (myMetaClass) {
14343 			IOLog("class %s \n", myMetaClass->getClassName());
14344 		} else {
14345 			IOLog("Unknown object \n" );
14346 		}
14347 	}
14348 #endif
14349 
14350 	return myResult;
14351 }
14352 #endif // KASLR_KEXT_DEBUG
14353 };         /* extern "C" */
14354 
14355 #if PRAGMA_MARK
14356 #pragma mark Backtrace Dump & kmod_get_info() support
14357 #endif
14358 /*********************************************************************
14359 * This function must be safe to call in panic context.
14360 *********************************************************************/
14361 /* static */
14362 void
14363 OSKext::printKextsInBacktrace(
14364 	vm_offset_t  * addr __unused,
14365 	unsigned int   cnt __unused,
14366 	int         (* printf_func)(const char *fmt, ...) __unused,
14367 	uint32_t       flags __unused)
14368 {
14369 	addr64_t    summary_page = 0;
14370 	addr64_t    last_summary_page = 0;
14371 	bool        found_kmod = false;
14372 	u_int       i = 0;
14373 
14374 	if (kPrintKextsLock & flags) {
14375 		if (!sKextSummariesLock) {
14376 			return;
14377 		}
14378 		IOLockLock(sKextSummariesLock);
14379 	}
14380 
14381 	if (!gLoadedKextSummaries) {
14382 		(*printf_func)("         can't perform kext scan: no kext summary");
14383 		goto finish;
14384 	}
14385 
14386 	summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
14387 	last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
14388 	for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
14389 		if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
14390 			(*printf_func)("         can't perform kext scan: "
14391 			    "missing kext summary page %p", summary_page);
14392 			goto finish;
14393 		}
14394 	}
14395 
14396 	for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14397 		OSKextLoadedKextSummary * summary;
14398 
14399 		summary = gLoadedKextSummaries->summaries + i;
14400 		if (!summary->address) {
14401 			continue;
14402 		}
14403 
14404 		if (!summaryIsInBacktrace(summary, addr, cnt)) {
14405 			continue;
14406 		}
14407 
14408 		if (!found_kmod) {
14409 			if (!(kPrintKextsTerse & flags)) {
14410 				(*printf_func)("      Kernel Extensions in backtrace:\n");
14411 			}
14412 			found_kmod = true;
14413 		}
14414 
14415 		printSummary(summary, printf_func, flags);
14416 	}
14417 
14418 finish:
14419 	if (kPrintKextsLock & flags) {
14420 		IOLockUnlock(sKextSummariesLock);
14421 	}
14422 
14423 	return;
14424 }
14425 
14426 /*********************************************************************
14427 * This function must be safe to call in panic context.
14428 *********************************************************************/
14429 /* static */
14430 boolean_t
14431 OSKext::summaryIsInBacktrace(
14432 	OSKextLoadedKextSummary   * summary,
14433 	vm_offset_t               * addr,
14434 	unsigned int                cnt)
14435 {
14436 	u_int i = 0;
14437 
14438 	for (i = 0; i < cnt; i++) {
14439 		vm_offset_t kscan_addr = addr[i];
14440 #if  __has_feature(ptrauth_calls)
14441 		kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr);
14442 #endif /*  __has_feature(ptrauth_calls) */
14443 		if ((kscan_addr >= summary->text_exec_address) &&
14444 		    (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) {
14445 			return TRUE;
14446 		}
14447 	}
14448 
14449 	return FALSE;
14450 }
14451 
14452 /*
14453  * Get the kext summary object for the kext where 'addr' lies. Must be called with
14454  * sKextSummariesLock held.
14455  */
14456 OSKextLoadedKextSummary *
14457 OSKext::summaryForAddress(uintptr_t addr)
14458 {
14459 #if  __has_feature(ptrauth_calls)
14460 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
14461 #endif /*  __has_feature(ptrauth_calls) */
14462 	for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14463 		OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
14464 		if (!summary->address) {
14465 			continue;
14466 		}
14467 
14468 #if VM_MAPPED_KEXTS
14469 		/* On our platforms that use VM_MAPPED_KEXTS, we currently do not
14470 		 * support split kexts, but we also may unmap the kexts, which can
14471 		 * race with the above codepath (see OSKext::unload).  As such,
14472 		 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
14473 		 */
14474 		if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
14475 			return summary;
14476 		}
14477 #else
14478 		kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
14479 		kernel_segment_command_t *seg;
14480 
14481 		for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
14482 			if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
14483 				return summary;
14484 			}
14485 		}
14486 #endif
14487 	}
14488 
14489 	/* addr did not map to any kext */
14490 	return NULL;
14491 }
14492 
14493 /* static */
14494 void *
14495 OSKext::kextForAddress(const void *address)
14496 {
14497 	void                * image = NULL;
14498 	OSKextActiveAccount * active;
14499 	OSKext              * kext = NULL;
14500 	uint32_t              baseIdx;
14501 	uint32_t              lim;
14502 	uintptr_t             addr = (uintptr_t) address;
14503 	size_t                i;
14504 
14505 	if (!addr) {
14506 		return NULL;
14507 	}
14508 #if  __has_feature(ptrauth_calls)
14509 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
14510 #endif /*  __has_feature(ptrauth_calls) */
14511 
14512 	if (sKextAccountsCount) {
14513 		IOSimpleLockLock(sKextAccountsLock);
14514 		// bsearch sKextAccounts list
14515 		for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
14516 			active = &sKextAccounts[baseIdx + (lim >> 1)];
14517 			if ((addr >= active->address) && (addr < active->address_end)) {
14518 				kext = active->account->kext;
14519 				if (kext && kext->kmod_info) {
14520 					image = (void *) kext->kmod_info->address;
14521 				}
14522 				break;
14523 			} else if (addr > active->address) {
14524 				// move right
14525 				baseIdx += (lim >> 1) + 1;
14526 				lim--;
14527 			}
14528 			// else move left
14529 		}
14530 		IOSimpleLockUnlock(sKextAccountsLock);
14531 	}
14532 	if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) {
14533 		image = (void *) &_mh_execute_header;
14534 	}
14535 	if (!image && gLoadedKextSummaries) {
14536 		IOLockLock(sKextSummariesLock);
14537 		for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) {
14538 			OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
14539 			if (addr >= summary->address && addr < summary->address + summary->size) {
14540 				image = (void *)summary->address;
14541 			}
14542 		}
14543 		IOLockUnlock(sKextSummariesLock);
14544 	}
14545 
14546 	return image;
14547 }
14548 
14549 /*
14550  * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t *
14551  * Safe to call in panic context.
14552  */
14553 static OSKextLoadedKextSummary *
14554 findSummary(uint32_t tagID)
14555 {
14556 	OSKextLoadedKextSummary * summary;
14557 	for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14558 		summary = gLoadedKextSummaries->summaries + i;
14559 		if (summary->loadTag == tagID) {
14560 			return summary;
14561 		}
14562 	}
14563 	return NULL;
14564 }
14565 
14566 /*********************************************************************
14567 * This function must be safe to call in panic context.
14568 *********************************************************************/
14569 void
14570 OSKext::printSummary(
14571 	OSKextLoadedKextSummary * summary,
14572 	int                    (* printf_func)(const char *fmt, ...),
14573 	uint32_t                  flags)
14574 {
14575 	kmod_reference_t * kmod_ref = NULL;
14576 	uuid_string_t uuid;
14577 	char version[kOSKextVersionMaxLength];
14578 	uint64_t tmpAddr;
14579 	uint64_t tmpSize;
14580 	OSKextLoadedKextSummary *dependencySummary;
14581 
14582 	if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
14583 		strlcpy(version, "unknown version", sizeof(version));
14584 	}
14585 	(void) uuid_unparse(summary->uuid, uuid);
14586 
14587 #if defined(__arm__) || defined(__arm64__)
14588 	tmpAddr = summary->text_exec_address;
14589 	tmpSize = summary->text_exec_size;
14590 #else
14591 	tmpAddr = summary->address;
14592 	tmpSize = summary->size;
14593 #endif
14594 	if (kPrintKextsUnslide & flags) {
14595 		tmpAddr = ml_static_unslide(tmpAddr);
14596 	}
14597 	(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
14598 	    (kPrintKextsTerse & flags) ? "" : "         ",
14599 	    summary->name, version, uuid,
14600 	    tmpAddr, tmpAddr + tmpSize - 1);
14601 
14602 	if (kPrintKextsTerse & flags) {
14603 		return;
14604 	}
14605 
14606 	/* print dependency info */
14607 	for (kmod_ref = (kmod_reference_t *) summary->reference_list;
14608 	    kmod_ref;
14609 	    kmod_ref = kmod_ref->next) {
14610 		kmod_info_t * rinfo;
14611 
14612 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
14613 			(*printf_func)("            kmod dependency scan stopped "
14614 			    "due to missing dependency page: %p\n",
14615 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
14616 			break;
14617 		}
14618 		rinfo = kmod_ref->info;
14619 
14620 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
14621 			(*printf_func)("            kmod dependency scan stopped "
14622 			    "due to missing kmod page: %p\n",
14623 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
14624 			break;
14625 		}
14626 
14627 		if (!rinfo->address) {
14628 			continue;         // skip fake entries for built-ins
14629 		}
14630 
14631 		dependencySummary = findSummary(rinfo->id);
14632 		uuid[0] = 0x00;
14633 		tmpAddr = rinfo->address;
14634 		tmpSize = rinfo->size;
14635 		if (dependencySummary) {
14636 			(void) uuid_unparse(dependencySummary->uuid, uuid);
14637 #if defined(__arm__) || defined(__arm64__)
14638 			tmpAddr = dependencySummary->text_exec_address;
14639 			tmpSize = dependencySummary->text_exec_size;
14640 #endif
14641 		}
14642 
14643 		if (kPrintKextsUnslide & flags) {
14644 			tmpAddr = ml_static_unslide(tmpAddr);
14645 		}
14646 		(*printf_func)("            dependency: %s(%s)[%s]@%p->%p\n",
14647 		    rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1);
14648 	}
14649 	return;
14650 }
14651 
14652 
14653 #if !defined(__arm__) && !defined(__arm64__)
14654 /*******************************************************************************
14655 * substitute() looks at an input string (a pointer within a larger buffer)
14656 * for a match to a substring, and on match it writes the marker & substitution
14657 * character to an output string, updating the scan (from) and
14658 * output (to) indexes as appropriate.
14659 *******************************************************************************/
14660 static int substitute(
14661 	const char * scan_string,
14662 	char       * string_out,
14663 	uint32_t   * to_index,
14664 	uint32_t   * from_index,
14665 	const char * substring,
14666 	char         marker,
14667 	char         substitution);
14668 
14669 /* string_out must be at least KMOD_MAX_NAME bytes.
14670  */
14671 static int
14672 substitute(
14673 	const char * scan_string,
14674 	char       * string_out,
14675 	uint32_t   * to_index,
14676 	uint32_t   * from_index,
14677 	const char * substring,
14678 	char         marker,
14679 	char         substitution)
14680 {
14681 	size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
14682 
14683 	/* On a substring match, append the marker (if there is one) and then
14684 	 * the substitution character, updating the output (to) index accordingly.
14685 	 * Then update the input (from) length by the length of the substring
14686 	 * that got replaced.
14687 	 */
14688 	if (!strncmp(scan_string, substring, substring_length)) {
14689 		if (marker) {
14690 			string_out[(*to_index)++] = marker;
14691 		}
14692 		string_out[(*to_index)++] = substitution;
14693 		(*from_index) += substring_length;
14694 		return 1;
14695 	}
14696 	return 0;
14697 }
14698 
14699 /*******************************************************************************
14700 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
14701 * KMOD_MAX_NAME characters and performs various substitutions of common
14702 * prefixes & substrings as defined by tables in kext_panic_report.h.
14703 *******************************************************************************/
14704 static void compactIdentifier(
14705 	const char * identifier,
14706 	char       * identifier_out,
14707 	char      ** identifier_out_end);
14708 
14709 static void
14710 compactIdentifier(
14711 	const char * identifier,
14712 	char       * identifier_out,
14713 	char      ** identifier_out_end)
14714 {
14715 	uint32_t       from_index, to_index;
14716 	uint32_t       scan_from_index = 0;
14717 	uint32_t       scan_to_index   = 0;
14718 	subs_entry_t * subs_entry    = NULL;
14719 	int            did_sub       = 0;
14720 
14721 	from_index = to_index = 0;
14722 	identifier_out[0] = '\0';
14723 
14724 	/* Replace certain identifier prefixes with shorter @+character sequences.
14725 	 * Check the return value of substitute() so we only replace the prefix.
14726 	 */
14727 	for (subs_entry = &kext_identifier_prefix_subs[0];
14728 	    subs_entry->substring && !did_sub;
14729 	    subs_entry++) {
14730 		did_sub = substitute(identifier, identifier_out,
14731 		    &scan_to_index, &scan_from_index,
14732 		    subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
14733 	}
14734 	did_sub = 0;
14735 
14736 	/* Now scan through the identifier looking for the common substrings
14737 	 * and replacing them with shorter !+character sequences via substitute().
14738 	 */
14739 	for (/* see above */;
14740 	    scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
14741 	    /* see loop */) {
14742 		const char   * scan_string = &identifier[scan_from_index];
14743 
14744 		did_sub = 0;
14745 
14746 		if (scan_from_index) {
14747 			for (subs_entry = &kext_identifier_substring_subs[0];
14748 			    subs_entry->substring && !did_sub;
14749 			    subs_entry++) {
14750 				did_sub = substitute(scan_string, identifier_out,
14751 				    &scan_to_index, &scan_from_index,
14752 				    subs_entry->substring, '!', subs_entry->substitute);
14753 			}
14754 		}
14755 
14756 		/* If we didn't substitute, copy the input character to the output.
14757 		 */
14758 		if (!did_sub) {
14759 			identifier_out[scan_to_index++] = identifier[scan_from_index++];
14760 		}
14761 	}
14762 
14763 	identifier_out[scan_to_index] = '\0';
14764 	if (identifier_out_end) {
14765 		*identifier_out_end = &identifier_out[scan_to_index];
14766 	}
14767 
14768 	return;
14769 }
14770 #endif /* !defined(__arm__) && !defined(__arm64__) */
14771 
14772 /*******************************************************************************
14773 * assemble_identifier_and_version() adds to a string buffer a compacted
14774 * bundle identifier followed by a version string.
14775 *******************************************************************************/
14776 
14777 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
14778  */
14779 static size_t assemble_identifier_and_version(
14780 	kmod_info_t * kmod_info,
14781 	char        * identPlusVers,
14782 	size_t        bufSize);
14783 
14784 static size_t
14785 assemble_identifier_and_version(
14786 	kmod_info_t * kmod_info,
14787 	char        * identPlusVers,
14788 	size_t        bufSize)
14789 {
14790 	size_t result = 0;
14791 
14792 #if defined(__arm__) || defined(__arm64__)
14793 	result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME);
14794 #else
14795 	compactIdentifier(kmod_info->name, identPlusVers, NULL);
14796 	result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
14797 #endif
14798 	identPlusVers[result++] = '\t';         // increment for real char
14799 	identPlusVers[result] = '\0';         // don't increment for nul char
14800 	result = strlcat(identPlusVers, kmod_info->version, bufSize);
14801 	if (result >= bufSize) {
14802 		identPlusVers[bufSize - 1] = '\0';
14803 		result = bufSize - 1;
14804 	}
14805 
14806 	return result;
14807 }
14808 
14809 /*******************************************************************************
14810 * Assumes sKextLock is held.
14811 *******************************************************************************/
14812 /* static */
14813 int
14814 OSKext::saveLoadedKextPanicListTyped(
14815 	const char * prefix,
14816 	int          invertFlag,
14817 	int          libsFlag,
14818 	char       * paniclist,
14819 	uint32_t     list_size)
14820 {
14821 	int             result = -1;
14822 	unsigned int    count, i;
14823 
14824 	count = sLoadedKexts->getCount();
14825 	if (!count) {
14826 		goto finish;
14827 	}
14828 
14829 	i = count - 1;
14830 	do {
14831 		OSObject    * rawKext = sLoadedKexts->getObject(i);
14832 		OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
14833 		int           match;
14834 		size_t        identPlusVersLength;
14835 		size_t        tempLen;
14836 		char          identPlusVers[2 * KMOD_MAX_NAME];
14837 
14838 		if (!rawKext) {
14839 			printf("OSKext::saveLoadedKextPanicListTyped - "
14840 			    "NULL kext in loaded kext list; continuing\n");
14841 			continue;
14842 		}
14843 
14844 		if (!theKext) {
14845 			printf("OSKext::saveLoadedKextPanicListTyped - "
14846 			    "Kext type cast failed in loaded kext list; continuing\n");
14847 			continue;
14848 		}
14849 
14850 		/* Skip all built-in kexts.
14851 		 */
14852 		if (theKext->isKernelComponent()) {
14853 			continue;
14854 		}
14855 
14856 		kmod_info_t * kmod_info = theKext->kmod_info;
14857 
14858 		/* Filter for kmod name (bundle identifier).
14859 		 */
14860 		match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
14861 		if ((match && invertFlag) || (!match && !invertFlag)) {
14862 			continue;
14863 		}
14864 
14865 		/* Filter for libraries (kexts that have a compatible version).
14866 		 */
14867 		if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
14868 		    (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
14869 			continue;
14870 		}
14871 
14872 		if (!kmod_info ||
14873 		    !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
14874 			printf("kext scan stopped due to missing kmod_info page: %p\n",
14875 			    kmod_info);
14876 			goto finish;
14877 		}
14878 
14879 		identPlusVersLength = assemble_identifier_and_version(kmod_info,
14880 		    identPlusVers,
14881 		    sizeof(identPlusVers));
14882 		if (!identPlusVersLength) {
14883 			printf("error saving loaded kext info\n");
14884 			goto finish;
14885 		}
14886 
14887 		/* make sure everything fits and we null terminate.
14888 		 */
14889 		tempLen = strlcat(paniclist, identPlusVers, list_size);
14890 		if (tempLen >= list_size) {
14891 			// panic list is full, keep it and null terminate
14892 			paniclist[list_size - 1] = 0x00;
14893 			result = 0;
14894 			goto finish;
14895 		}
14896 		tempLen = strlcat(paniclist, "\n", list_size);
14897 		if (tempLen >= list_size) {
14898 			// panic list is full, keep it and null terminate
14899 			paniclist[list_size - 1] = 0x00;
14900 			result = 0;
14901 			goto finish;
14902 		}
14903 	} while (i--);
14904 
14905 	result = 0;
14906 finish:
14907 
14908 	return result;
14909 }
14910 
14911 /*********************************************************************
14912 *********************************************************************/
14913 /* static */
14914 void
14915 OSKext::saveLoadedKextPanicList(void)
14916 {
14917 	char     * newlist        = NULL;
14918 	uint32_t   newlist_size   = 0;
14919 
14920 	newlist_size = KEXT_PANICLIST_SIZE;
14921 	newlist = (char *)kalloc_data_tag(newlist_size,
14922 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
14923 
14924 	if (!newlist) {
14925 		OSKextLog(/* kext */ NULL,
14926 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
14927 		    "Couldn't allocate kext panic log buffer.");
14928 		goto finish;
14929 	}
14930 
14931 	newlist[0] = '\0';
14932 
14933 	// non-"com.apple." kexts
14934 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
14935 	    /* libs? */ -1, newlist, newlist_size) != 0) {
14936 		goto finish;
14937 	}
14938 	// "com.apple." nonlibrary kexts
14939 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
14940 	    /* libs? */ 0, newlist, newlist_size) != 0) {
14941 		goto finish;
14942 	}
14943 	// "com.apple." library kexts
14944 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
14945 	    /* libs? */ 1, newlist, newlist_size) != 0) {
14946 		goto finish;
14947 	}
14948 
14949 	if (loaded_kext_paniclist) {
14950 		kheap_free(KHEAP_DATA_BUFFERS, loaded_kext_paniclist,
14951 		    loaded_kext_paniclist_size);
14952 	}
14953 	loaded_kext_paniclist = newlist;
14954 	newlist = NULL;
14955 	loaded_kext_paniclist_size = newlist_size;
14956 
14957 finish:
14958 	if (newlist) {
14959 		kfree_data(newlist, newlist_size);
14960 	}
14961 	return;
14962 }
14963 
14964 /*********************************************************************
14965 * Assumes sKextLock is held.
14966 *********************************************************************/
14967 void
14968 OSKext::savePanicString(bool isLoading)
14969 {
14970 	u_long len;
14971 
14972 	if (!kmod_info) {
14973 		return;         // do not goto finish here b/c of lock
14974 	}
14975 
14976 	len = assemble_identifier_and_version( kmod_info,
14977 	    (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
14978 	    (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
14979 	if (!len) {
14980 		printf("error saving unloaded kext info\n");
14981 		goto finish;
14982 	}
14983 
14984 	if (isLoading) {
14985 		last_loaded_strlen = len;
14986 		last_loaded_address = (void *)kmod_info->address;
14987 		last_loaded_size = kmod_info->size;
14988 		clock_get_uptime(&last_loaded_timestamp);
14989 	} else {
14990 		last_unloaded_strlen = len;
14991 		last_unloaded_address = (void *)kmod_info->address;
14992 		last_unloaded_size = kmod_info->size;
14993 		clock_get_uptime(&last_unloaded_timestamp);
14994 	}
14995 
14996 finish:
14997 	return;
14998 }
14999 
15000 /*********************************************************************
15001 *********************************************************************/
15002 /* static */
15003 void
15004 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
15005 {
15006 	if (last_loaded_strlen) {
15007 		printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n",
15008 		    AbsoluteTime_to_scalar(&last_loaded_timestamp),
15009 		    last_loaded_strlen, last_loaded_str_buf,
15010 		    last_loaded_address, last_loaded_size);
15011 	}
15012 
15013 	if (last_unloaded_strlen) {
15014 		printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n",
15015 		    AbsoluteTime_to_scalar(&last_unloaded_timestamp),
15016 		    last_unloaded_strlen, last_unloaded_str_buf,
15017 		    last_unloaded_address, last_unloaded_size);
15018 	}
15019 
15020 	printf_func("loaded kexts:\n");
15021 	if (loaded_kext_paniclist &&
15022 	    pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
15023 	    loaded_kext_paniclist[0]) {
15024 		printf_func("%.*s",
15025 		    strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
15026 		    loaded_kext_paniclist);
15027 	} else {
15028 		printf_func("(none)\n");
15029 	}
15030 	return;
15031 }
15032 
15033 /*********************************************************************
15034 * Assumes sKextLock is held.
15035 *********************************************************************/
15036 /* static */
15037 void
15038 OSKext::updateLoadedKextSummaries(void)
15039 {
15040 	kern_return_t result = KERN_FAILURE;
15041 	OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
15042 	OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
15043 	OSKext *aKext;
15044 	vm_map_offset_t start, end;
15045 	size_t summarySize = 0;
15046 	size_t size;
15047 	u_int count;
15048 	u_int maxKexts;
15049 	u_int i, j;
15050 	OSKextActiveAccount * accountingList;
15051 	OSKextActiveAccount * prevAccountingList;
15052 	uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
15053 
15054 	prevAccountingList = NULL;
15055 	prevAccountingListCount = 0;
15056 
15057 #if DEVELOPMENT || DEBUG
15058 	if (IORecursiveLockHaveLock(sKextLock) == false) {
15059 		panic("sKextLock must be held");
15060 	}
15061 #endif
15062 
15063 	IOLockLock(sKextSummariesLock);
15064 
15065 	count = sLoadedKexts->getCount();
15066 	for (i = 0, maxKexts = 0; i < count; ++i) {
15067 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
15068 		maxKexts += (aKext && aKext->isExecutable());
15069 	}
15070 
15071 	if (!maxKexts) {
15072 		goto finish;
15073 	}
15074 	if (maxKexts < kOSKextTypicalLoadCount) {
15075 		maxKexts = kOSKextTypicalLoadCount;
15076 	}
15077 
15078 	/* Calculate the size needed for the new summary headers.
15079 	 */
15080 
15081 	size = sizeof(*gLoadedKextSummaries);
15082 	size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
15083 	size = round_page(size);
15084 
15085 	if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
15086 		if (gLoadedKextSummaries) {
15087 			kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
15088 			gLoadedKextSummaries = NULL;
15089 			gLoadedKextSummariesTimestamp = mach_absolute_time();
15090 			sLoadedKextSummariesAllocSize = 0;
15091 		}
15092 		result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, VM_KERN_MEMORY_OSKEXT);
15093 		if (result != KERN_SUCCESS) {
15094 			goto finish;
15095 		}
15096 		summaryHeader = summaryHeaderAlloc;
15097 		summarySize = size;
15098 	} else {
15099 		summaryHeader = gLoadedKextSummaries;
15100 		summarySize = sLoadedKextSummariesAllocSize;
15101 
15102 		start = (vm_map_offset_t) summaryHeader;
15103 		end = start + summarySize;
15104 		result = vm_map_protect(kernel_map,
15105 		    start,
15106 		    end,
15107 		    VM_PROT_DEFAULT,
15108 		    FALSE);
15109 		if (result != KERN_SUCCESS) {
15110 			goto finish;
15111 		}
15112 	}
15113 
15114 	/* Populate the summary header.
15115 	 */
15116 
15117 	bzero(summaryHeader, summarySize);
15118 	summaryHeader->version = kOSKextLoadedKextSummaryVersion;
15119 	summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
15120 
15121 	/* Populate each kext summary.
15122 	 */
15123 
15124 	count = sLoadedKexts->getCount();
15125 	accountingListAlloc = 0;
15126 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
15127 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
15128 		if (!aKext || !aKext->isExecutable()) {
15129 			continue;
15130 		}
15131 
15132 		aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
15133 		summaryHeader->numSummaries++;
15134 		accountingListAlloc++;
15135 	}
15136 
15137 	accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
15138 	accountingListCount = 0;
15139 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
15140 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
15141 		if (!aKext || !aKext->isExecutable()) {
15142 			continue;
15143 		}
15144 
15145 		OSKextActiveAccount activeAccount;
15146 		aKext->updateActiveAccount(&activeAccount);
15147 		// order by address
15148 		for (idx = 0; idx < accountingListCount; idx++) {
15149 			if (activeAccount.address < accountingList[idx].address) {
15150 				break;
15151 			}
15152 		}
15153 		bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
15154 		accountingList[idx] = activeAccount;
15155 		accountingListCount++;
15156 	}
15157 	assert(accountingListCount == accountingListAlloc);
15158 	/* Write protect the buffer and move it into place.
15159 	 */
15160 
15161 	start = (vm_map_offset_t) summaryHeader;
15162 	end = start + summarySize;
15163 
15164 	result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
15165 	if (result != KERN_SUCCESS) {
15166 		goto finish;
15167 	}
15168 
15169 	gLoadedKextSummaries = summaryHeader;
15170 	gLoadedKextSummariesTimestamp = mach_absolute_time();
15171 	sLoadedKextSummariesAllocSize = summarySize;
15172 	summaryHeaderAlloc = NULL;
15173 
15174 	/* Call the magic breakpoint function through a static function pointer so
15175 	 * the compiler can't optimize the function away.
15176 	 */
15177 	if (sLoadedKextSummariesUpdated) {
15178 		(*sLoadedKextSummariesUpdated)();
15179 	}
15180 
15181 	IOSimpleLockLock(sKextAccountsLock);
15182 	prevAccountingList      = sKextAccounts;
15183 	prevAccountingListCount = sKextAccountsCount;
15184 	sKextAccounts           = accountingList;
15185 	sKextAccountsCount      = accountingListCount;
15186 	IOSimpleLockUnlock(sKextAccountsLock);
15187 
15188 finish:
15189 	IOLockUnlock(sKextSummariesLock);
15190 
15191 	/* If we had to allocate a new buffer but failed to generate the summaries,
15192 	 * free that now.
15193 	 */
15194 	if (summaryHeaderAlloc) {
15195 		kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
15196 	}
15197 	if (prevAccountingList) {
15198 		IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
15199 	}
15200 
15201 	return;
15202 }
15203 
15204 /*********************************************************************
15205 *********************************************************************/
15206 void
15207 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
15208 {
15209 	OSSharedPtr<OSData> uuid;
15210 
15211 	strlcpy(summary->name, getIdentifierCString(),
15212 	    sizeof(summary->name));
15213 
15214 	uuid = copyUUID();
15215 	if (uuid) {
15216 		memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
15217 	}
15218 
15219 	if (flags.builtin) {
15220 //      this value will stop lldb from parsing the mach-o header
15221 //      summary->address = UINT64_MAX;
15222 //      summary->size = 0;
15223 		summary->address = kmod_info->address;
15224 		summary->size = kmod_info->size;
15225 	} else {
15226 		summary->address = kmod_info->address;
15227 		summary->size = kmod_info->size;
15228 	}
15229 	summary->version = getVersion();
15230 	summary->loadTag = kmod_info->id;
15231 	summary->flags = 0;
15232 	summary->reference_list = (uint64_t) kmod_info->reference_list;
15233 
15234 	summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size);
15235 	if (summary->text_exec_address == 0) {
15236 		// Fallback to __TEXT
15237 		summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size);
15238 	}
15239 	return;
15240 }
15241 
15242 /*********************************************************************
15243 *********************************************************************/
15244 
15245 void
15246 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
15247 {
15248 	kernel_mach_header_t     *hdr = NULL;
15249 	kernel_segment_command_t *seg = NULL;
15250 
15251 	bzero(accountp, sizeof(*accountp));
15252 
15253 	hdr = (kernel_mach_header_t *)kmod_info->address;
15254 	if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) {
15255 		/*
15256 		 * If this kext supports split segments (or is in a new
15257 		 * MH_FILESET kext collection), use the first
15258 		 * executable segment as the range for instructions
15259 		 * (and thus for backtracing.
15260 		 */
15261 		for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
15262 			if (seg->initprot & VM_PROT_EXECUTE) {
15263 				break;
15264 			}
15265 		}
15266 	}
15267 	if (seg) {
15268 		accountp->address = seg->vmaddr;
15269 		if (accountp->address) {
15270 			accountp->address_end = seg->vmaddr + seg->vmsize;
15271 		}
15272 	} else {
15273 		/* For non-split kexts and for kexts without executable
15274 		 * segments, just use the kmod_info range (as the kext
15275 		 * is either all in one range or should not show up in
15276 		 * instruction backtraces).
15277 		 */
15278 		accountp->address = kmod_info->address;
15279 		if (accountp->address) {
15280 			accountp->address_end = kmod_info->address + kmod_info->size;
15281 		}
15282 	}
15283 
15284 	accountp->account = this->account;
15285 }
15286 
15287 bool
15288 OSKext::isDriverKit(void)
15289 {
15290 	OSString *bundleType;
15291 
15292 	if (infoDict) {
15293 		bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
15294 		if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
15295 			return TRUE;
15296 		}
15297 	}
15298 	return FALSE;
15299 }
15300 
15301 bool
15302 OSKext::isInFileset(void)
15303 {
15304 	if (!kmod_info) {
15305 		goto check_prelinked;
15306 	}
15307 
15308 	if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) {
15309 		return true;
15310 	}
15311 
15312 check_prelinked:
15313 	if (isPrelinked()) {
15314 		/*
15315 		 * If we haven't setup kmod_info yet, but we know
15316 		 * we're loading a prelinked kext in an MH_FILESET KC,
15317 		 * then return true
15318 		 */
15319 		kc_format_t kc_format;
15320 		if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
15321 			return true;
15322 		}
15323 	}
15324 	return false;
15325 }
15326 
15327 bool
15328 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg)
15329 {
15330 	kern_return_t result;
15331 	if (!super::init()) {
15332 		return false;
15333 	}
15334 	if (seg == nullptr) {
15335 		return false;
15336 	}
15337 	result = kmem_alloc_pageable(kernel_map, (vm_offset_t *)&data, seg->vmsize, VM_KERN_MEMORY_KEXT);
15338 	if (result != KERN_SUCCESS) {
15339 		return false;
15340 	}
15341 	memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize);
15342 	savedSegment = seg;
15343 	vmsize = seg->vmsize;
15344 	vmaddr = seg->vmaddr;
15345 	return true;
15346 }
15347 
15348 OSSharedPtr<OSKextSavedMutableSegment>
15349 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg)
15350 {
15351 	OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>();
15352 	if (me && !me->initWithSegment(seg)) {
15353 		return nullptr;
15354 	}
15355 	return me;
15356 }
15357 
15358 void
15359 OSKextSavedMutableSegment::free(void)
15360 {
15361 	if (data) {
15362 		kmem_free(kernel_map, (vm_offset_t)data, vmsize);
15363 	}
15364 }
15365 
15366 vm_offset_t
15367 OSKextSavedMutableSegment::getVMAddr() const
15368 {
15369 	return vmaddr;
15370 }
15371 
15372 vm_offset_t
15373 OSKextSavedMutableSegment::getVMSize() const
15374 {
15375 	return vmsize;
15376 }
15377 
15378 OSReturn
15379 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg)
15380 {
15381 	if (seg != savedSegment) {
15382 		return kOSKextReturnInvalidArgument;
15383 	}
15384 	if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) {
15385 		return kOSKextReturnInvalidArgument;
15386 	}
15387 	memcpy((void *)seg->vmaddr, data, vmsize);
15388 	return kOSReturnSuccess;
15389 }
15390 
15391 extern "C" kern_return_t
15392 OSKextSetReceiptQueried(void)
15393 {
15394 	OSKextLog(/* kext */ NULL,
15395 	    kOSKextLogStepLevel | kOSKextLogGeneralFlag,
15396 	    "Setting kext receipt as queried");
15397 
15398 	IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue);
15399 	return KERN_SUCCESS;
15400 }
15401 
15402 extern "C" const vm_allocation_site_t *
15403 OSKextGetAllocationSiteForCaller(uintptr_t address)
15404 {
15405 	OSKextActiveAccount *  active;
15406 	vm_allocation_site_t * site;
15407 	vm_allocation_site_t * releasesite;
15408 
15409 	uint32_t baseIdx;
15410 	uint32_t lim;
15411 #if  __has_feature(ptrauth_calls)
15412 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
15413 #endif /*  __has_feature(ptrauth_calls) */
15414 
15415 	IOSimpleLockLock(sKextAccountsLock);
15416 	site = releasesite = NULL;
15417 
15418 	// bsearch sKextAccounts list
15419 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15420 		active = &sKextAccounts[baseIdx + (lim >> 1)];
15421 		if ((address >= active->address) && (address < active->address_end)) {
15422 			site = &active->account->site;
15423 			if (!site->tag) {
15424 				vm_tag_alloc_locked(site, &releasesite);
15425 			}
15426 			break;
15427 		} else if (address > active->address) {
15428 			// move right
15429 			baseIdx += (lim >> 1) + 1;
15430 			lim--;
15431 		}
15432 		// else move left
15433 	}
15434 	IOSimpleLockUnlock(sKextAccountsLock);
15435 	if (releasesite) {
15436 		kern_allocation_name_release(releasesite);
15437 	}
15438 
15439 	return site;
15440 }
15441 
15442 #if DEVELOPMENT || DEBUG
15443 extern "C" void
15444 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *))
15445 {
15446 	OSKextActiveAccount *  active;
15447 
15448 	uint32_t baseIdx;
15449 	uint32_t lim;
15450 #if  __has_feature(ptrauth_calls)
15451 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
15452 #endif /*  __has_feature(ptrauth_calls) */
15453 
15454 	IOSimpleLockLock(sKextAccountsLock);
15455 
15456 	// bsearch sKextAccounts list
15457 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15458 		active = &sKextAccounts[baseIdx + (lim >> 1)];
15459 		if ((address >= active->address) && (address < active->address_end)) {
15460 			cb(&active->account->task_refgrp);
15461 			break;
15462 		} else if (address > active->address) {
15463 			// move right
15464 			baseIdx += (lim >> 1) + 1;
15465 			lim--;
15466 		}
15467 		// else move left
15468 	}
15469 	IOSimpleLockUnlock(sKextAccountsLock);
15470 }
15471 #endif /* DEVELOPMENT || DEBUG */
15472 
15473 extern "C" uint32_t
15474 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
15475 {
15476 	OSKextAccount * account = (typeof(account))site;
15477 	const char    * kname;
15478 
15479 	if (name) {
15480 		if (account->kext) {
15481 			kname = account->kext->getIdentifierCString();
15482 		} else {
15483 			kname = "<>";
15484 		}
15485 		strlcpy(name, kname, namelen);
15486 	}
15487 
15488 	return account->loadTag;
15489 }
15490 
15491 extern "C" void
15492 OSKextFreeSite(vm_allocation_site_t * site)
15493 {
15494 	OSKextAccount * freeAccount = (typeof(freeAccount))site;
15495 	IOFreeType(freeAccount, OSKextAccount);
15496 }
15497 
15498 /*********************************************************************
15499 *********************************************************************/
15500 
15501 #if CONFIG_IMAGEBOOT
15502 int
15503 OSKextGetUUIDForName(const char *name, uuid_t uuid)
15504 {
15505 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name);
15506 	if (!kext) {
15507 		return 1;
15508 	}
15509 
15510 	OSSharedPtr<OSData> uuid_data = kext->copyUUID();
15511 	if (uuid_data) {
15512 		memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
15513 		return 0;
15514 	}
15515 
15516 	return 1;
15517 }
15518 #endif
15519 
15520 static int
15521 sysctl_willuserspacereboot
15522 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
15523 {
15524 	int new_value = 0, old_value = 0, changed = 0;
15525 	int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
15526 	if (error) {
15527 		return error;
15528 	}
15529 	if (changed) {
15530 		OSKext::willUserspaceReboot();
15531 	}
15532 	return 0;
15533 }
15534 
15535 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot,
15536     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
15537     NULL, 0, sysctl_willuserspacereboot, "I", "");
15538