xref: /xnu-11215/libkern/c++/OSKext.cpp (revision bb611c8f)
1 /*
2  * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #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_kern.h>
40 #include <vm/vm_map.h>
41 #include <kextd/kextd_mach.h>
42 #include <libkern/kernel_mach_header.h>
43 #include <libkern/kext_panic_report.h>
44 #include <libkern/kext_request_keys.h>
45 #include <libkern/mkext.h>
46 #include <libkern/prelink.h>
47 #include <libkern/version.h>
48 #include <libkern/zlib.h>
49 #include <mach/host_special_ports.h>
50 #include <mach/mach_vm.h>
51 #include <mach/mach_time.h>
52 #include <sys/sysctl.h>
53 #include <uuid/uuid.h>
54 #include <sys/random.h>
55 #include <pexpert/pexpert.h>
56 
57 #include <sys/pgo.h>
58 
59 #if CONFIG_MACF
60 #include <sys/kauth.h>
61 #include <security/mac_framework.h>
62 #endif
63 
64 #if CONFIG_CSR
65 #include <sys/csr.h>
66 #include <sys/stat.h>
67 #include <sys/vnode.h>
68 #endif /* CONFIG_CSR */
69 };
70 
71 #include <os/cpp_util.h>
72 
73 #include <libkern/OSKextLibPrivate.h>
74 #include <libkern/c++/OSKext.h>
75 #include <libkern/c++/OSLib.h>
76 
77 #include <IOKit/IOLib.h>
78 #include <IOKit/IOCatalogue.h>
79 #include <IOKit/IORegistryEntry.h>
80 #include <IOKit/IOService.h>
81 #include <IOKit/IOUserServer.h>
82 
83 #include <IOKit/IOStatisticsPrivate.h>
84 #include <IOKit/IOBSD.h>
85 #include <IOKit/IOPlatformExpert.h>
86 
87 #include <san/kasan.h>
88 
89 #if PRAGMA_MARK
90 #pragma mark External & Internal Function Protos
91 #endif
92 /*********************************************************************
93 *********************************************************************/
94 extern "C" {
95 extern int  IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
96 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
97 
98 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
99 extern int dtrace_keep_kernel_symbols(void);
100 
101 #if defined(__x86_64__) || defined(__i386__)
102 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide);
103 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers);
104 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size);
105 static void *allocate_kcfileset_map_entry_list(void);
106 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size);
107 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable);
108 int vnode_put(struct vnode *vp);
109 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size,
110     void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot);
111 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size);
112 void * ubc_getobject(struct vnode *vp, __unused int flags);
113 #endif //(__x86_64__) || defined(__i386__)
114 }
115 
116 extern unsigned long gVirtBase;
117 extern unsigned long gPhysBase;
118 extern vm_map_t g_kext_map;
119 
120 bool pageableKCloaded = false;
121 bool auxKCloaded = false;
122 bool resetAuxKCSegmentOnUnload = false;
123 
124 extern boolean_t pageablekc_uuid_valid;
125 extern uuid_t pageablekc_uuid;
126 extern uuid_string_t pageablekc_uuid_string;
127 
128 extern boolean_t auxkc_uuid_valid;
129 extern uuid_t auxkc_uuid;
130 extern uuid_string_t auxkc_uuid_string;
131 
132 static OSReturn _OSKextCreateRequest(
133 	const char    * predicate,
134 	OSSharedPtr<OSDictionary> & requestP);
135 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
136 static OSObject * _OSKextGetRequestArgument(
137 	OSDictionary * requestDict,
138 	const char   * argName);
139 static bool _OSKextSetRequestArgument(
140 	OSDictionary * requestDict,
141 	const char   * argName,
142 	OSObject     * value);
143 static void * _OSKextExtractPointer(OSData * wrapper);
144 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSData * wrapper);
145 static OSReturn _OSDictionarySetCStringValue(
146 	OSDictionary * dict,
147 	const char   * key,
148 	const char   * value);
149 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
150 #if CONFIG_KXLD
151 static bool _OSKextInPrelinkRebuildWindow(void);
152 #endif
153 
154 // We really should add containsObject() & containsCString to OSCollection & subclasses.
155 // So few pad slots, though....
156 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
157 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
158 
159 /* Prelinked arm kexts do not have VM entries because the method we use to
160  * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
161  * not work on ARM.  To get around that, we must free prelinked kext
162  * executables with ml_static_mfree() instead of kext_free().
163  */
164 #if __i386__ || __x86_64__
165 #define VM_MAPPED_KEXTS 1
166 #define KASLR_KEXT_DEBUG 0
167 #define KASLR_IOREG_DEBUG 0
168 #elif __arm__ || __arm64__
169 #define VM_MAPPED_KEXTS 0
170 #define KASLR_KEXT_DEBUG 0
171 #else
172 #error Unsupported architecture
173 #endif
174 
175 #if PRAGMA_MARK
176 #pragma mark Constants & Macros
177 #endif
178 /*********************************************************************
179 * Constants & Macros
180 *********************************************************************/
181 
182 /* Use this number to create containers.
183  */
184 #define kOSKextTypicalLoadCount      (150)
185 
186 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
187  * A loaded kext will no dependents or external retains will have 2 retains.
188  */
189 #define kOSKextMinRetainCount        (1)
190 #define kOSKextMinLoadedRetainCount  (2)
191 
192 /**********
193  * Strings and substrings used in dependency resolution.
194  */
195 #define APPLE_KEXT_PREFIX            "com.apple."
196 #define KERNEL_LIB                   "com.apple.kernel"
197 
198 #define PRIVATE_KPI                  "com.apple.kpi.private"
199 
200 /* Version for compatbility pseudokexts (com.apple.kernel.*),
201  * compatible back to v6.0.
202  */
203 #define KERNEL6_LIB                  "com.apple.kernel.6.0"
204 #define KERNEL6_VERSION              "7.9.9"
205 
206 #define KERNEL_LIB_PREFIX            "com.apple.kernel."
207 #define KPI_LIB_PREFIX               "com.apple.kpi."
208 
209 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0)
210 
211 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
212 #define MINIMUM_WAKEUP_SECONDS (30)
213 
214 /*********************************************************************
215 * infoDict keys for internally-stored data. Saves on ivar slots for
216 * objects we don't keep around past boot time or during active load.
217 *********************************************************************/
218 
219 /* A usable, uncompressed file is stored under this key.
220  */
221 #define _kOSKextExecutableKey                "_OSKextExecutable"
222 
223 /* An indirect reference to the executable file from an mkext
224  * is stored under this key.
225  */
226 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference"
227 
228 /* If the file is contained in a larger buffer laid down by the booter or
229  * sent from user space, the OSKext stores that OSData under this key so that
230  * references are properly tracked. This is always an mkext, right now.
231  */
232 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData"
233 
234 #define OS_LOG_HDR_VERSION  1
235 #define NUM_OS_LOG_SECTIONS 2
236 
237 #define OS_LOG_SECT_IDX     0
238 #define CSTRING_SECT_IDX    1
239 
240 #if PRAGMA_MARK
241 #pragma mark Typedefs
242 #endif
243 /*********************************************************************
244 * Typedefs
245 *********************************************************************/
246 
247 /*********************************************************************
248 * osLogDataHeaderRef describes the header information of an OSData
249 * object that is returned when querying for kOSBundleLogStringsKey.
250 * We currently return information regarding 2 sections - os_log and
251 * cstring. In the case that the os_log section doesn't exist, we just
252 * return an offset and length of 0 for that section.
253 *********************************************************************/
254 typedef struct osLogDataHeader {
255 	uint32_t version;
256 	uint32_t sect_count;
257 	struct {
258 		uint32_t sect_offset;
259 		uint32_t sect_size;
260 	} sections[0];
261 } osLogDataHeaderRef;
262 
263 /*********************************************************************
264 * MkextEntryRef describes the contents of an OSData object
265 * referencing a file entry from an mkext so that we can uncompress
266 * (if necessary) and extract it on demand.
267 *
268 * It contains the mkextVersion in case we ever wind up supporting
269 * multiple mkext formats. Mkext format 1 is officially retired as of
270 * Snow Leopard.
271 *********************************************************************/
272 typedef struct MkextEntryRef {
273 	mkext_basic_header * mkext; // beginning of whole mkext file
274 	void               * fileinfo;// mkext2_file_entry or equiv; see mkext.h
275 } MkextEntryRef;
276 
277 #if PRAGMA_MARK
278 #pragma mark Global and static Module Variables
279 #endif
280 /*********************************************************************
281 * Global & static variables, used to keep track of kexts.
282 *********************************************************************/
283 
284 static  bool                sPrelinkBoot               = false;
285 static  bool                sSafeBoot                  = false;
286 static  bool                sKeepSymbols               = false;
287 static  bool                sPanicOnKCMismatch         = false;
288 static  bool                sOSKextWasResetAfterUserspaceReboot = false;
289 
290 /*********************************************************************
291  * sKextLock is the principal lock for OSKext, and guards all static
292  * and global variables not owned by other locks (declared further
293  * below). It must be taken by any entry-point method or function,
294  * including internal functions called on scheduled threads.
295  *
296  * sKextLock and sKextInnerLock are recursive due to multiple functions
297  * that are called both externally and internally. The other locks are
298  * nonrecursive.
299  *
300  * Which locks are taken depends on what they protect, but if more than
301  * one must be taken, they must always be locked in this order
302  * (and unlocked in reverse order) to prevent deadlocks:
303  *
304  *    1. sKextLock
305  *    2. sKextInnerLock
306  *    3. sKextSummariesLock
307  *    4. sKextLoggingLock
308  */
309 static IORecursiveLock    * sKextLock                  = NULL;
310 
311 static OSSharedPtr<OSDictionary>   sKextsByID;
312 static OSSharedPtr<OSDictionary>   sExcludeListByID;
313 static OSKextVersion               sExcludeListVersion        = 0;
314 static OSSharedPtr<OSArray>        sLoadedKexts;
315 static OSSharedPtr<OSDictionary>   sNonLoadableKextsByID;
316 static OSSharedPtr<OSArray>        sUnloadedPrelinkedKexts;
317 static OSSharedPtr<OSArray>        sLoadedDriverKitKexts;
318 
319 // Requests to the IOKit daemon waiting to be picked up.
320 static OSSharedPtr<OSArray>        sKernelRequests;
321 // Identifier of kext load requests in sKernelRequests
322 static OSSharedPtr<OSSet>          sPostedKextLoadIdentifiers;
323 static OSSharedPtr<OSArray>        sRequestCallbackRecords;
324 
325 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
326 static OSSharedPtr<OSSet>          sAllKextLoadIdentifiers;
327 #if CONFIG_KXLD
328 static KXLDContext        * sKxldContext               = NULL;
329 #endif
330 static uint32_t             sNextLoadTag               = 0;
331 static uint32_t             sNextRequestTag            = 0;
332 
333 static bool                 sUserLoadsActive           = false;
334 static bool                 sIOKitDaemonActive         = false;
335 static bool                 sDeferredLoadSucceeded     = false;
336 static bool                 sConsiderUnloadsExecuted   = false;
337 
338 #if NO_KEXTD
339 static bool                 sKernelRequestsEnabled     = false;
340 #else
341 static bool                 sKernelRequestsEnabled     = true;
342 #endif
343 static bool                 sLoadEnabled               = true;
344 static bool                 sUnloadEnabled             = true;
345 
346 /*********************************************************************
347  * Stuff for the OSKext representing the kernel itself.
348  **********/
349 static OSKext          * sKernelKext             = NULL;
350 
351 /* Set up a fake kmod_info struct for the kernel.
352  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
353  * before OSKext is initialized; that call only needs the name
354  * and address to be set correctly.
355  *
356  * We don't do much else with the kerne's kmod_info; we never
357  * put it into the kmod list, never adjust the reference count,
358  * and never have kernel components reference it.
359  * For that matter, we don't do much with kmod_info structs
360  * at all anymore! We just keep them filled in for gdb and
361  * binary compability.
362  */
363 kmod_info_t g_kernel_kmod_info = {
364 	.next =            NULL,
365 	.info_version =    KMOD_INFO_VERSION,
366 	.id =              0,             // loadTag: kernel is always 0
367 	.name =            kOSKextKernelIdentifier,// bundle identifier
368 	.version =         "0",           // filled in in OSKext::initialize()
369 	.reference_count = -1,            // never adjusted; kernel never unloads
370 	.reference_list =  NULL,
371 	.address =         0,
372 	.size =            0,             // filled in in OSKext::initialize()
373 	.hdr_size =        0,
374 	.start =           NULL,
375 	.stop =            NULL
376 };
377 
378 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
379 
380 kmod_info_t invalid_kmod_info = {
381 	.next =            NULL,
382 	.info_version =    KMOD_INFO_VERSION,
383 	.id =              UINT32_MAX,
384 	.name =            "invalid",
385 	.version =         "0",
386 	.reference_count = -1,
387 	.reference_list =  NULL,
388 	.address =         0,
389 	.size =            0,
390 	.hdr_size =        0,
391 	.start =           NULL,
392 	.stop =            NULL
393 };
394 
395 extern "C" {
396 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
397 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
398 // misc_protos.h, db_low_trace.c, kgmacros
399 // 'kmod' is a holdover from the old kmod system, we can't rename it.
400 kmod_info_t * kmod = NULL;
401 
402 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE)
403 
404 
405 static char     * loaded_kext_paniclist         = NULL;
406 static uint32_t   loaded_kext_paniclist_size    = 0;
407 
408 AbsoluteTime      last_loaded_timestamp;
409 static char       last_loaded_str_buf[2 * KMOD_MAX_NAME];
410 static u_long     last_loaded_strlen            = 0;
411 static void     * last_loaded_address           = NULL;
412 static u_long     last_loaded_size              = 0;
413 
414 AbsoluteTime      last_unloaded_timestamp;
415 static char       last_unloaded_str_buf[2 * KMOD_MAX_NAME];
416 static u_long     last_unloaded_strlen          = 0;
417 static void     * last_unloaded_address         = NULL;
418 static u_long     last_unloaded_size            = 0;
419 
420 // Statically linked kmods described by several mach-o sections:
421 //
422 // kPrelinkInfoSegment:kBuiltinInfoSection
423 // Array of pointers to kmod_info_t structs.
424 //
425 // kPrelinkInfoSegment:kBuiltinInfoSection
426 // Array of pointers to an embedded mach-o header.
427 //
428 // __DATA:kBuiltinInitSection, kBuiltinTermSection
429 // Structors for all kmods. Has to be filtered by proc address.
430 //
431 
432 static uint32_t gBuiltinKmodsCount;
433 static kernel_section_t * gBuiltinKmodsSectionInfo;
434 static kernel_section_t * gBuiltinKmodsSectionStart;
435 
436 const OSSymbol              * gIOSurfaceIdentifier;
437 vm_tag_t                      gIOSurfaceTag;
438 
439 /*********************************************************************
440  * sKextInnerLock protects against cross-calls with IOService and
441  * IOCatalogue, and owns the variables declared immediately below.
442  *
443  * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
444  *
445  * When both sKextLock and sKextInnerLock need to be taken,
446  * always lock sKextLock first and unlock it second. Never take both
447  * locks in an entry point to OSKext; if you need to do so, you must
448  * spawn an independent thread to avoid potential deadlocks for threads
449  * calling into OSKext.
450  **********/
451 static IORecursiveLock *    sKextInnerLock             = NULL;
452 
453 static bool                 sAutounloadEnabled         = true;
454 static bool                 sConsiderUnloadsCalled     = false;
455 static bool                 sConsiderUnloadsPending    = false;
456 
457 static unsigned int         sConsiderUnloadDelay       = 60;     // seconds
458 static thread_call_t        sUnloadCallout             = NULL;
459 #if CONFIG_KXLD
460 static thread_call_t        sDestroyLinkContextThread  = NULL;   // one-shot, one-at-a-time thread
461 #endif // CONFIG_KXLD
462 static bool                 sSystemSleep               = false;  // true when system going to sleep
463 static AbsoluteTime         sLastWakeTime;                       // last time we woke up
464 
465 /*********************************************************************
466  * Backtraces can be printed at various times so we need a tight lock
467  * on data used for that. sKextSummariesLock protects the variables
468  * declared immediately below.
469  *
470  * gLoadedKextSummaries is accessed by other modules, but only during
471  * a panic so the lock isn't needed then.
472  *
473  * gLoadedKextSummaries has the "used" attribute in order to ensure
474  * that it remains visible even when we are performing extremely
475  * aggressive optimizations, as it is needed to allow the debugger
476  * to automatically parse the list of loaded kexts.
477  **********/
478 static IOLock                 * sKextSummariesLock                = NULL;
479 extern "C" lck_spin_t           vm_allocation_sites_lock;
480 static IOSimpleLock           * sKextAccountsLock = &vm_allocation_sites_lock;
481 
482 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
483 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
484 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
485 static size_t sLoadedKextSummariesAllocSize = 0;
486 
487 static OSKextActiveAccount    * sKextAccounts;
488 static uint32_t                 sKextAccountsCount;
489 };
490 
491 /*********************************************************************
492  * sKextLoggingLock protects the logging variables declared immediately below.
493  **********/
494 static IOLock                 * sKextLoggingLock           = NULL;
495 
496 static  const OSKextLogSpec     kDefaultKernelLogFilter    = kOSKextLogBasicLevel |
497     kOSKextLogVerboseFlagsMask;
498 static  OSKextLogSpec           sKernelLogFilter           = kDefaultKernelLogFilter;
499 static  bool                    sBootArgLogFilterFound     = false;
500 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
501     0, "kernel kext logging");
502 
503 static  OSKextLogSpec           sUserSpaceKextLogFilter    = kOSKextLogSilentFilter;
504 static  OSSharedPtr<OSArray>    sUserSpaceLogSpecArray;
505 static  OSSharedPtr<OSArray>    sUserSpaceLogMessageArray;
506 
507 /*********
508  * End scope for sKextInnerLock-protected variables.
509  *********************************************************************/
510 
511 
512 /*********************************************************************
513  *  helper function used for collecting PGO data upon unload of a kext
514  */
515 
516 static int OSKextGrabPgoDataLocked(OSKext *kext,
517     bool metadata,
518     uuid_t instance_uuid,
519     uint64_t *pSize,
520     char *pBuffer,
521     uint64_t bufferSize);
522 
523 /**********************************************************************/
524 
525 
526 
527 #if PRAGMA_MARK
528 #pragma mark OSData callbacks (need to move to OSData)
529 #endif
530 /*********************************************************************
531 * C functions used for callbacks.
532 *********************************************************************/
533 extern "C" {
534 void
535 osdata_kmem_free(void * ptr, unsigned int length)
536 {
537 	kmem_free(kernel_map, (vm_address_t)ptr, length);
538 	return;
539 }
540 
541 void
542 osdata_phys_free(void * ptr, unsigned int length)
543 {
544 	ml_static_mfree((vm_offset_t)ptr, length);
545 	return;
546 }
547 
548 void
549 osdata_vm_deallocate(void * ptr, unsigned int length)
550 {
551 	(void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
552 	return;
553 }
554 
555 void
556 osdata_kext_free(void * ptr, unsigned int length)
557 {
558 	(void)kext_free((vm_offset_t)ptr, length);
559 }
560 };
561 
562 #if PRAGMA_MARK
563 #pragma mark KXLD Allocation Callback
564 #endif
565 #if CONFIG_KXLD
566 /*********************************************************************
567 * KXLD Allocation Callback
568 *********************************************************************/
569 kxld_addr_t
570 kern_allocate(
571 	u_long              size,
572 	KXLDAllocateFlags * flags,
573 	void              * user_data)
574 {
575 	vm_address_t  result       = 0; // returned
576 	kern_return_t mach_result  = KERN_FAILURE;
577 	bool          success      = false;
578 	OSKext      * theKext      = (OSKext *)user_data;
579 	unsigned int  roundSize    = 0;
580 	OSSharedPtr<OSData>      linkBuffer;
581 
582 	if (round_page(size) > UINT_MAX) {
583 		OSKextLog(theKext,
584 		    kOSKextLogErrorLevel |
585 		    kOSKextLogGeneralFlag,
586 		    "%s: Requested memory size is greater than UINT_MAX.",
587 		    theKext->getIdentifierCString());
588 		goto finish;
589 	}
590 
591 	roundSize = (unsigned int)round_page(size);
592 
593 	mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
594 	if (mach_result != KERN_SUCCESS) {
595 		OSKextLog(theKext,
596 		    kOSKextLogErrorLevel |
597 		    kOSKextLogGeneralFlag,
598 		    "Can't allocate kernel memory to link %s.",
599 		    theKext->getIdentifierCString());
600 		goto finish;
601 	}
602 
603 	/* Create an OSData wrapper for the allocated buffer.
604 	 */
605 	linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
606 	if (!linkBuffer) {
607 		OSKextLog(theKext,
608 		    kOSKextLogErrorLevel |
609 		    kOSKextLogGeneralFlag,
610 		    "Can't allocate linked executable wrapper for %s.",
611 		    theKext->getIdentifierCString());
612 		goto finish;
613 	}
614 	linkBuffer->setDeallocFunction(osdata_kext_free);
615 	OSKextLog(theKext,
616 	    kOSKextLogProgressLevel |
617 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
618 	    "Allocated link buffer for kext %s at %p (%lu bytes).",
619 	    theKext->getIdentifierCString(),
620 	    (void *)result, (unsigned long)roundSize);
621 
622 	theKext->setLinkedExecutable(linkBuffer.get());
623 
624 	*flags = kKxldAllocateWritable;
625 	success = true;
626 
627 finish:
628 	if (!success && result) {
629 		kext_free(result, roundSize);
630 		result = 0;
631 	}
632 
633 	return (kxld_addr_t)result;
634 }
635 
636 /*********************************************************************
637 *********************************************************************/
638 void
639 kxld_log_callback(
640 	KXLDLogSubsystem    subsystem,
641 	KXLDLogLevel        level,
642 	const char        * format,
643 	va_list             argList,
644 	void              * user_data)
645 {
646 	OSKext *theKext = (OSKext *) user_data;
647 	OSKextLogSpec logSpec = 0;
648 
649 	switch (subsystem) {
650 	case kKxldLogLinking:
651 		logSpec |= kOSKextLogLinkFlag;
652 		break;
653 	case kKxldLogPatching:
654 		logSpec |= kOSKextLogPatchFlag;
655 		break;
656 	}
657 
658 	switch (level) {
659 	case kKxldLogExplicit:
660 		logSpec |= kOSKextLogExplicitLevel;
661 		break;
662 	case kKxldLogErr:
663 		logSpec |= kOSKextLogErrorLevel;
664 		break;
665 	case kKxldLogWarn:
666 		logSpec |= kOSKextLogWarningLevel;
667 		break;
668 	case kKxldLogBasic:
669 		logSpec |= kOSKextLogProgressLevel;
670 		break;
671 	case kKxldLogDetail:
672 		logSpec |= kOSKextLogDetailLevel;
673 		break;
674 	case kKxldLogDebug:
675 		logSpec |= kOSKextLogDebugLevel;
676 		break;
677 	}
678 
679 	OSKextVLog(theKext, logSpec, format, argList);
680 }
681 #endif // CONFIG_KXLD
682 
683 #if PRAGMA_MARK
684 #pragma mark IOStatistics defines
685 #endif
686 
687 #if IOKITSTATS
688 
689 #define notifyKextLoadObservers(kext, kmod_info) \
690 do { \
691     IOStatistics::onKextLoad(kext, kmod_info); \
692 } while (0)
693 
694 #define notifyKextUnloadObservers(kext) \
695 do { \
696     IOStatistics::onKextUnload(kext); \
697 } while (0)
698 
699 #define notifyAddClassObservers(kext, addedClass, flags) \
700 do { \
701     IOStatistics::onClassAdded(kext, addedClass); \
702 } while (0)
703 
704 #define notifyRemoveClassObservers(kext, removedClass, flags) \
705 do { \
706     IOStatistics::onClassRemoved(kext, removedClass); \
707 } while (0)
708 
709 #else
710 
711 #define notifyKextLoadObservers(kext, kmod_info)
712 #define notifyKextUnloadObservers(kext)
713 #define notifyAddClassObservers(kext, addedClass, flags)
714 #define notifyRemoveClassObservers(kext, removedClass, flags)
715 
716 #endif /* IOKITSTATS */
717 
718 #if PRAGMA_MARK
719 #pragma mark Module Config (Startup & Shutdown)
720 #endif
721 /*********************************************************************
722 * Module Config (Class Definition & Class Methods)
723 *********************************************************************/
724 #define super OSObject
725 OSDefineMetaClassAndStructors(OSKext, OSObject)
726 
727 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject);
728 
729 /*********************************************************************
730 *********************************************************************/
731 /* static */
732 void
733 OSKext::initialize(void)
734 {
735 	OSSharedPtr<OSData>     kernelExecutable   = NULL;// do not release
736 	u_char          * kernelStart        = NULL;// do not free
737 	size_t            kernelLength       = 0;
738 	IORegistryEntry * registryRoot       = NULL;// do not release
739 	OSSharedPtr<OSNumber> kernelCPUType;
740 	OSSharedPtr<OSNumber> kernelCPUSubtype;
741 	OSKextLogSpec     bootLogFilter      = kOSKextLogSilentFilter;
742 	bool              setResult          = false;
743 	uint64_t        * timestamp          = NULL;
744 	__unused char     bootArgBuffer[16];// for PE_parse_boot_argn w/strings
745 
746 	/* This must be the first thing allocated. Everything else grabs this lock.
747 	 */
748 	sKextLock = IORecursiveLockAlloc();
749 	sKextInnerLock = IORecursiveLockAlloc();
750 	sKextSummariesLock = IOLockAlloc();
751 	sKextLoggingLock = IOLockAlloc();
752 	assert(sKextLock);
753 	assert(sKextInnerLock);
754 	assert(sKextSummariesLock);
755 	assert(sKextLoggingLock);
756 
757 	sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
758 	sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
759 	sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
760 	sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
761 	sKernelRequests = OSArray::withCapacity(0);
762 	sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
763 	sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
764 	sRequestCallbackRecords = OSArray::withCapacity(0);
765 	assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
766 	    sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
767 	    sRequestCallbackRecords && sUnloadedPrelinkedKexts);
768 
769 	/* Read the log flag boot-args and set the log flags.
770 	 */
771 	if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
772 		sBootArgLogFilterFound = true;
773 		sKernelLogFilter = bootLogFilter;
774 		// log this if any flags are set
775 		OSKextLog(/* kext */ NULL,
776 		    kOSKextLogBasicLevel |
777 		    kOSKextLogFlagsMask,
778 		    "Kernel kext log filter 0x%x per kextlog boot arg.",
779 		    (unsigned)sKernelLogFilter);
780 	}
781 
782 #if !defined(__arm__) && !defined(__arm64__)
783 	/*
784 	 * On our ARM targets, the kernelcache/boot kernel collection contains
785 	 * the set of kexts required to boot, as specified by KCB.  Safeboot is
786 	 * either unsupported, or is supported by the bootloader only loading
787 	 * the boot kernel collection; as a result OSKext has no role to play
788 	 * in safeboot policy on ARM.
789 	 */
790 	sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
791 	    sizeof(bootArgBuffer)) ? true : false;
792 #endif /* defined(__arm__) && defined(__arm64__) */
793 
794 	if (sSafeBoot) {
795 		OSKextLog(/* kext */ NULL,
796 		    kOSKextLogWarningLevel |
797 		    kOSKextLogGeneralFlag,
798 		    "SAFE BOOT DETECTED - "
799 		    "only valid OSBundleRequired kexts will be loaded.");
800 	}
801 
802 	PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
803 #if CONFIG_DTRACE
804 	if (dtrace_keep_kernel_symbols()) {
805 		sKeepSymbols = true;
806 	}
807 #endif /* CONFIG_DTRACE */
808 #if KASAN_DYNAMIC_BLACKLIST
809 	/* needed for function lookup */
810 	sKeepSymbols = true;
811 #endif
812 
813 	/*
814 	 * Should we panic when the SystemKC is not linked against the
815 	 * BootKC that was loaded by the booter? By default: yes, if the
816 	 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic
817 	 * on mis-match and instead just print an error and continue.
818 	 */
819 	sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer,
820 	    sizeof(bootArgBuffer)) ? false : true;
821 
822 	/* Set up an OSKext instance to represent the kernel itself.
823 	 */
824 	sKernelKext = new OSKext;
825 	assert(sKernelKext);
826 
827 	kernelStart = (u_char *)&_mh_execute_header;
828 	kernelLength = getlastaddr() - (vm_offset_t)kernelStart;
829 	assert(kernelLength <= UINT_MAX);
830 	kernelExecutable = OSData::withBytesNoCopy(
831 		kernelStart, (unsigned int)kernelLength);
832 	assert(kernelExecutable);
833 
834 #if KASLR_KEXT_DEBUG
835 	IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %lu (0x%016lx) \n",
836 	    (unsigned long)kernelStart,
837 	    (unsigned long)getlastaddr(),
838 	    kernelLength,
839 	    (unsigned long)vm_kernel_slide,
840 	    (unsigned long)vm_kernel_slide);
841 #endif
842 
843 	sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0
844 	sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier);
845 
846 	sKernelKext->version = OSKextParseVersionString(osrelease);
847 	sKernelKext->compatibleVersion = sKernelKext->version;
848 	sKernelKext->linkedExecutable = os::move(kernelExecutable);
849 	sKernelKext->interfaceUUID = sKernelKext->copyUUID();
850 
851 	sKernelKext->flags.hasAllDependencies = 1;
852 	sKernelKext->flags.kernelComponent = 1;
853 	sKernelKext->flags.prelinked = 0;
854 	sKernelKext->flags.loaded = 1;
855 	sKernelKext->flags.started = 1;
856 	sKernelKext->flags.CPPInitialized = 0;
857 	sKernelKext->flags.jettisonLinkeditSeg = 0;
858 
859 	sKernelKext->kmod_info = &g_kernel_kmod_info;
860 	strlcpy(g_kernel_kmod_info.version, osrelease,
861 	    sizeof(g_kernel_kmod_info.version));
862 	g_kernel_kmod_info.size = kernelLength;
863 	g_kernel_kmod_info.id = sKernelKext->loadTag;
864 
865 	/* Cons up an info dict, so we don't have to have special-case
866 	 * checking all over.
867 	 */
868 	sKernelKext->infoDict = OSDictionary::withCapacity(5);
869 	assert(sKernelKext->infoDict);
870 	setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey,
871 	    sKernelKext->bundleID.get());
872 	assert(setResult);
873 	setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey,
874 	    kOSBooleanTrue);
875 	assert(setResult);
876 
877 	{
878 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease));
879 		assert(scratchString);
880 		setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey,
881 		    scratchString.get());
882 		assert(setResult);
883 	}
884 
885 	{
886 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy("mach_kernel"));
887 		assert(scratchString);
888 		setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey,
889 		    scratchString.get());
890 		assert(setResult);
891 	}
892 
893 	/* Add the kernel kext to the bookkeeping dictionaries. Note that
894 	 * the kernel kext doesn't have a kmod_info struct. copyInfo()
895 	 * gathers info from other places anyhow.
896 	 */
897 	setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext);
898 	assert(setResult);
899 	setResult = sLoadedKexts->setObject(sKernelKext);
900 	assert(setResult);
901 
902 	// XXX: better way with OSSharedPtr?
903 	// sKernelKext remains a valid pointer even after the decref
904 	sKernelKext->release();
905 
906 	registryRoot = IORegistryEntry::getRegistryRoot();
907 	kernelCPUType = OSNumber::withNumber(
908 		(long long unsigned int)_mh_execute_header.cputype,
909 		8 * sizeof(_mh_execute_header.cputype));
910 	kernelCPUSubtype = OSNumber::withNumber(
911 		(long long unsigned int)_mh_execute_header.cpusubtype,
912 		8 * sizeof(_mh_execute_header.cpusubtype));
913 	assert(registryRoot && kernelCPUSubtype && kernelCPUType);
914 
915 	registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get());
916 	registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get());
917 
918 	gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
919 	if (gBuiltinKmodsSectionInfo) {
920 		uint32_t count;
921 
922 		assert(gBuiltinKmodsSectionInfo->addr);
923 		assert(gBuiltinKmodsSectionInfo->size);
924 		assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX);
925 		gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
926 
927 		gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
928 		assert(gBuiltinKmodsSectionStart);
929 		assert(gBuiltinKmodsSectionStart->addr);
930 		assert(gBuiltinKmodsSectionStart->size);
931 		assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX);
932 		count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
933 		// one extra pointer for the end of last kmod
934 		assert(count == (gBuiltinKmodsCount + 1));
935 
936 		vm_kernel_builtinkmod_text     = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
937 		vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
938 	}
939 
940 	// Don't track this object -- it's never released
941 	gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach();
942 
943 	timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
944 	*timestamp = 0;
945 	timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
946 	*timestamp = 0;
947 	timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
948 	*timestamp = 0;
949 
950 	OSKextLog(/* kext */ NULL,
951 	    kOSKextLogProgressLevel |
952 	    kOSKextLogGeneralFlag,
953 	    "Kext system initialized.");
954 
955 	notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
956 
957 	return;
958 }
959 
960 /*********************************************************************
961 * This is expected to be called exactly once, from exactly one thread
962 * context, during kernel bootstrap.
963 *********************************************************************/
964 /* static */
965 OSReturn
966 OSKext::removeKextBootstrap(void)
967 {
968 	OSReturn                   result                = kOSReturnError;
969 
970 	const char               * dt_kernel_header_name = "Kernel-__HEADER";
971 	const char               * dt_kernel_symtab_name = "Kernel-__SYMTAB";
972 	kernel_mach_header_t     * dt_mach_header        = NULL;
973 	int                        dt_mach_header_size   = 0;
974 	struct symtab_command    * dt_symtab             = NULL;
975 	int                        dt_symtab_size        = 0;
976 	int                        dt_result             = 0;
977 
978 	kernel_segment_command_t * seg_to_remove         = NULL;
979 
980 	const char __unused      * dt_segment_name       = NULL;
981 	void       __unused      * segment_paddress      = NULL;
982 	int        __unused        segment_size          = 0;
983 
984 	OSKextLog(/* kext */ NULL,
985 	    kOSKextLogProgressLevel |
986 	    kOSKextLogGeneralFlag,
987 	    "Jettisoning kext bootstrap segments.");
988 
989 	/*
990 	 * keep the linkedit segment around when booted from a new MH_FILESET
991 	 * KC because all the kexts shared a linkedit segment.
992 	 */
993 	kc_format_t kc_format;
994 	if (!PE_get_primary_kc_format(&kc_format)) {
995 		OSKextLog(/* kext */ NULL,
996 		    kOSKextLogErrorLevel |
997 		    kOSKextLogGeneralFlag,
998 		    "Unable to determine primary KC format");
999 	}
1000 
1001 	/*****
1002 	 * Dispose of unnecessary stuff that the booter didn't need to load.
1003 	 */
1004 	dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
1005 	    (void **)&dt_mach_header, &dt_mach_header_size);
1006 	if (dt_result == 0 && dt_mach_header) {
1007 		IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
1008 		    round_page_32(dt_mach_header_size));
1009 	}
1010 	dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
1011 	    (void **)&dt_symtab, &dt_symtab_size);
1012 	if (dt_result == 0 && dt_symtab) {
1013 		IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
1014 		    round_page_32(dt_symtab_size));
1015 	}
1016 
1017 	/*****
1018 	 * KLD bootstrap segment.
1019 	 */
1020 	// xxx - should rename KLD segment
1021 	seg_to_remove = getsegbyname("__KLD");
1022 	if (seg_to_remove) {
1023 		OSRuntimeUnloadCPPForSegment(seg_to_remove);
1024 	}
1025 
1026 #if __arm__ || __arm64__
1027 	/* Free the memory that was set up by bootx.
1028 	 */
1029 	dt_segment_name = "Kernel-__KLD";
1030 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1031 		/* We cannot free this with KTRR enabled, as we cannot
1032 		 * update the permissions on the KLD range this late
1033 		 * in the boot process.
1034 		 */
1035 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1036 		    (int)segment_size);
1037 	}
1038 #elif __i386__ || __x86_64__
1039 	/* On x86, use the mapping data from the segment load command to
1040 	 * unload KLD directly.
1041 	 * This may invalidate any assumptions about  "avail_start"
1042 	 * defining the lower bound for valid physical addresses.
1043 	 */
1044 	if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) {
1045 		bzero((void *)seg_to_remove->vmaddr, seg_to_remove->vmsize);
1046 		ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize);
1047 	}
1048 #else
1049 #error arch
1050 #endif
1051 
1052 	seg_to_remove = NULL;
1053 
1054 	/*****
1055 	 * Prelinked kernel's symtab (if there is one).
1056 	 */
1057 	if (kc_format != KCFormatFileset) {
1058 		kernel_section_t * sect;
1059 		sect = getsectbyname("__PRELINK", "__symtab");
1060 		if (sect && sect->addr && sect->size) {
1061 			ml_static_mfree(sect->addr, sect->size);
1062 		}
1063 	}
1064 
1065 	seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
1066 
1067 	/* kxld always needs the kernel's __LINKEDIT segment, but we can make it
1068 	 * pageable, unless keepsyms is set.  To do that, we have to copy it from
1069 	 * its booter-allocated memory, free the booter memory, reallocate proper
1070 	 * managed memory, then copy the segment back in.
1071 	 *
1072 	 * NOTE: This optimization is not valid for fileset KCs because each
1073 	 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment
1074 	 * that points to one fileset-global LINKEDIT segment. This
1075 	 * optimization is also only valid for platforms that support vm
1076 	 * mapped kexts or mapped kext collections (pageable KCs)
1077 	 */
1078 #if VM_MAPPED_KEXTS
1079 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1080 		kern_return_t mem_result;
1081 		void *seg_copy = NULL;
1082 		void *seg_data = NULL;
1083 		vm_map_offset_t seg_offset = 0;
1084 		vm_map_offset_t seg_copy_offset = 0;
1085 		vm_map_size_t seg_length = 0;
1086 
1087 		seg_data = (void *) seg_to_remove->vmaddr;
1088 		seg_offset = (vm_map_offset_t) seg_to_remove->vmaddr;
1089 		seg_length = (vm_map_size_t) seg_to_remove->vmsize;
1090 
1091 		/* Allocate space for the LINKEDIT copy.
1092 		 */
1093 		mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
1094 		    seg_length, VM_KERN_MEMORY_KEXT);
1095 		if (mem_result != KERN_SUCCESS) {
1096 			OSKextLog(/* kext */ NULL,
1097 			    kOSKextLogErrorLevel |
1098 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1099 			    "Can't copy __LINKEDIT segment for VM reassign.");
1100 			return result;
1101 		}
1102 		seg_copy_offset = (vm_map_offset_t) seg_copy;
1103 
1104 		/* Copy it out.
1105 		 */
1106 		memcpy(seg_copy, seg_data, seg_length);
1107 
1108 		/* Dump the booter memory.
1109 		 */
1110 		ml_static_mfree(seg_offset, seg_length);
1111 
1112 		/* Set up the VM region.
1113 		 */
1114 		mem_result = vm_map_enter_mem_object(
1115 			kernel_map,
1116 			&seg_offset,
1117 			seg_length, /* mask */ 0,
1118 			VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
1119 			VM_MAP_KERNEL_FLAGS_NONE,
1120 			VM_KERN_MEMORY_NONE,
1121 			(ipc_port_t)NULL,
1122 			(vm_object_offset_t) 0,
1123 			/* copy */ FALSE,
1124 			/* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1125 			/* max_protection */ VM_PROT_ALL,
1126 			/* inheritance */ VM_INHERIT_DEFAULT);
1127 		if ((mem_result != KERN_SUCCESS) ||
1128 		    (seg_offset != (vm_map_offset_t) seg_data)) {
1129 			OSKextLog(/* kext */ NULL,
1130 			    kOSKextLogErrorLevel |
1131 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1132 			    "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1133 			    seg_data, seg_length, mem_result);
1134 			return result;
1135 		}
1136 
1137 		/* And copy it back.
1138 		 */
1139 		memcpy(seg_data, seg_copy, seg_length);
1140 
1141 		/* Free the copy.
1142 		 */
1143 		kmem_free(kernel_map, seg_copy_offset, seg_length);
1144 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1145 		/* Remove the linkedit segment of the Boot KC */
1146 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1147 		OSKext::jettisonFileSetLinkeditSegment(mh);
1148 	}
1149 #else // !VM_MAPPED_KEXTS
1150 	/*****
1151 	 * Dump the LINKEDIT segment, unless keepsyms is set.
1152 	 */
1153 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1154 		dt_segment_name = "Kernel-__LINKEDIT";
1155 		if (0 == IODTGetLoaderInfo(dt_segment_name,
1156 		    &segment_paddress, &segment_size)) {
1157 #ifdef SECURE_KERNEL
1158 			vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1159 			bzero((void*)vmaddr, segment_size);
1160 #endif
1161 			IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1162 			    (int)segment_size);
1163 		}
1164 	} else {
1165 		OSKextLog(/* kext */ NULL,
1166 		    kOSKextLogBasicLevel |
1167 		    kOSKextLogGeneralFlag,
1168 		    "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1169 	}
1170 #endif // VM_MAPPED_KEXTS
1171 
1172 	seg_to_remove = NULL;
1173 
1174 	result = kOSReturnSuccess;
1175 
1176 	return result;
1177 }
1178 
1179 #if CONFIG_KXLD
1180 /*********************************************************************
1181 *********************************************************************/
1182 void
1183 OSKext::flushNonloadedKexts(
1184 	Boolean flushPrelinkedKexts)
1185 {
1186 	OSSharedPtr<OSSet>                keepKexts;
1187 
1188 	/* TODO: make this more efficient with MH_FILESET kexts */
1189 
1190 	// Do not unload prelinked kexts on arm because the kernelcache is not
1191 	// structured in a way that allows them to be unmapped
1192 #if !defined(__x86_64__)
1193 	flushPrelinkedKexts = false;
1194 #endif /* defined(__x86_64__) */
1195 
1196 	IORecursiveLockLock(sKextLock);
1197 
1198 	OSKextLog(/* kext */ NULL,
1199 	    kOSKextLogProgressLevel |
1200 	    kOSKextLogKextBookkeepingFlag,
1201 	    "Flushing nonloaded kexts and other unused data.");
1202 
1203 	OSKext::considerDestroyingLinkContext();
1204 
1205 	/* If we aren't flushing unused prelinked kexts, we have to put them
1206 	 * aside while we flush everything else so make a container for them.
1207 	 */
1208 	keepKexts = OSSet::withCapacity(16);
1209 	if (!keepKexts) {
1210 		goto finish;
1211 	}
1212 
1213 	/* Set aside prelinked kexts (in-use or not) and break
1214 	 * any lingering inter-kext references for nonloaded kexts
1215 	 * so they have min. retain counts.
1216 	 */
1217 	{
1218 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1219 			OSKext * thisKext = OSDynamicCast(OSKext, obj);
1220 			if (!thisKext) {
1221 			        return false;
1222 			}
1223 			if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
1224 			        keepKexts->setObject(thisKext);
1225 			} else if (!thisKext->declaresExecutable()) {
1226 			        /*
1227 			         * Don't unload codeless kexts, because they never appear in the loadedKexts array.
1228 			         * Requesting one from the IOKit daemon will load it and then immediately remove it by calling
1229 			         * flushNonloadedKexts().
1230 			         * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
1231 			         */
1232 			        keepKexts->setObject(thisKext);
1233 			} else if (thisKext->isInFileset()) {
1234 			        /* keep all kexts in the new MH_FILESET KC */
1235 			        keepKexts->setObject(thisKext);
1236 			}
1237 
1238 			thisKext->flushDependencies(/* forceIfLoaded */ false);
1239 			return false;
1240 		});
1241 	}
1242 	/* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1243 	 */
1244 	sKextsByID->flushCollection();
1245 
1246 	/* Now put the loaded kexts back into the ID dictionary.
1247 	 */
1248 	sLoadedKexts->iterateObjects(^bool (OSObject * obj) {
1249 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1250 		if (!thisKext) {
1251 		        return false;
1252 		}
1253 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1254 		return false;
1255 	});
1256 
1257 	/* Finally, put back the kept kexts if we saved any.
1258 	 */
1259 	keepKexts->iterateObjects(^bool (OSObject * obj) {
1260 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1261 		if (!thisKext) {
1262 		        return false;
1263 		}
1264 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1265 		return false;
1266 	});
1267 
1268 finish:
1269 	IORecursiveLockUnlock(sKextLock);
1270 	return;
1271 }
1272 #else /* !CONFIG_KXLD */
1273 
1274 void
1275 OSKext::flushNonloadedKexts(
1276 	Boolean flushPrelinkedKexts __unused)
1277 {
1278 	IORecursiveLockLock(sKextLock);
1279 
1280 	OSKextLog(/* kext */ NULL,
1281 	    kOSKextLogProgressLevel |
1282 	    kOSKextLogKextBookkeepingFlag,
1283 	    "Flushing dependency info for non-loaded kexts.");
1284 
1285 	/*
1286 	 * In a world where we don't dynamically link kexts, they all come
1287 	 * from a kext collection that's either in wired memory, or
1288 	 * wire-on-demand. We don't need to mess around with moving kexts in
1289 	 * and out of the sKextsByID array - they can all just stay there.
1290 	 * Here we just flush the dependency list for kexts that are not
1291 	 * loaded.
1292 	 */
1293 	sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1294 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1295 		if (!thisKext) {
1296 		        return false;
1297 		}
1298 		thisKext->flushDependencies(/* forceIfLoaded */ false);
1299 		return false;
1300 	});
1301 
1302 	IORecursiveLockUnlock(sKextLock);
1303 	return;
1304 }
1305 
1306 #endif /* CONFIG_KXLD */
1307 
1308 /*********************************************************************
1309 *********************************************************************/
1310 /* static */
1311 void
1312 OSKext::setIOKitDaemonActive(bool active)
1313 {
1314 	IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
1315 	IORecursiveLockLock(sKextLock);
1316 	sIOKitDaemonActive = active;
1317 	if (sKernelRequests->getCount()) {
1318 		OSKext::pingIOKitDaemon();
1319 	}
1320 	IORecursiveLockUnlock(sKextLock);
1321 
1322 	return;
1323 }
1324 
1325 /*********************************************************************
1326 * OSKextLib.cpp might need access to this someday but for now it's
1327 * private.
1328 *********************************************************************/
1329 extern "C" {
1330 extern void ipc_port_release_send(ipc_port_t);
1331 };
1332 
1333 /* static */
1334 OSReturn
1335 OSKext::pingIOKitDaemon(void)
1336 {
1337 	OSReturn    result     = kOSReturnError;
1338 #if !NO_KEXTD
1339 	mach_port_t kextd_port = IPC_PORT_NULL;
1340 
1341 	if (!sIOKitDaemonActive) {
1342 		result = kOSKextReturnDisabled; // basically unavailable
1343 		goto finish;
1344 	}
1345 
1346 	result = host_get_kextd_port(host_priv_self(), &kextd_port);
1347 	if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1348 		OSKextLog(/* kext */ NULL,
1349 		    kOSKextLogErrorLevel |
1350 		    kOSKextLogIPCFlag,
1351 		    "Can't get " kIOKitDaemonName " port.");
1352 		goto finish;
1353 	}
1354 
1355 	result = kextd_ping(kextd_port);
1356 	if (result != KERN_SUCCESS) {
1357 		OSKextLog(/* kext */ NULL,
1358 		    kOSKextLogErrorLevel |
1359 		    kOSKextLogIPCFlag,
1360 		    kIOKitDaemonName " ping failed (0x%x).", (int)result);
1361 		goto finish;
1362 	}
1363 
1364 finish:
1365 	if (IPC_PORT_VALID(kextd_port)) {
1366 		ipc_port_release_send(kextd_port);
1367 	}
1368 #endif
1369 
1370 	return result;
1371 }
1372 
1373 /*********************************************************************
1374 *********************************************************************/
1375 /* static */
1376 void
1377 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1378 {
1379 	IORecursiveLockLock(sKextLock);
1380 	sDeferredLoadSucceeded = succeeded;
1381 	IORecursiveLockUnlock(sKextLock);
1382 
1383 	return;
1384 }
1385 
1386 /*********************************************************************
1387 * Called from IOSystemShutdownNotification.
1388 *********************************************************************/
1389 /* static */
1390 void
1391 OSKext::willShutdown(void)
1392 {
1393 #if !NO_KEXTD
1394 	OSReturn       checkResult = kOSReturnError;
1395 #endif
1396 	OSSharedPtr<OSDictionary> exitRequest;
1397 
1398 	IORecursiveLockLock(sKextLock);
1399 
1400 	OSKext::setLoadEnabled(false);
1401 	OSKext::setUnloadEnabled(false);
1402 	OSKext::setAutounloadsEnabled(false);
1403 	OSKext::setKernelRequestsEnabled(false);
1404 
1405 #if defined(__x86_64__) || defined(__i386__)
1406 	if (IOPMRootDomainGetWillShutdown()) {
1407 		OSKext::freeKCFileSetcontrol();
1408 	}
1409 #endif // (__x86_64__) || defined(__i386__)
1410 
1411 #if !NO_KEXTD
1412 	OSKextLog(/* kext */ NULL,
1413 	    kOSKextLogProgressLevel |
1414 	    kOSKextLogGeneralFlag,
1415 	    "System shutdown; requesting immediate " kIOKitDaemonName " exit.");
1416 
1417 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit,
1418 	    exitRequest);
1419 	if (checkResult != kOSReturnSuccess) {
1420 		goto finish;
1421 	}
1422 	if (!sKernelRequests->setObject(exitRequest.get())) {
1423 		goto finish;
1424 	}
1425 
1426 	OSKext::pingIOKitDaemon();
1427 
1428 finish:
1429 #endif
1430 
1431 	IORecursiveLockUnlock(sKextLock);
1432 	return;
1433 }
1434 
1435 void
1436 OSKext::willUserspaceReboot(void)
1437 {
1438 	OSKext::willShutdown();
1439 	IOService::userSpaceWillReboot();
1440 	gIOCatalogue->terminateDriversForUserspaceReboot();
1441 }
1442 
1443 void
1444 OSKext::resetAfterUserspaceReboot(void)
1445 {
1446 	OSSharedPtr<OSArray> arr = OSArray::withCapacity(1);
1447 	IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */);
1448 
1449 	IORecursiveLockLock(sKextLock);
1450 	gIOCatalogue->resetAfterUserspaceReboot();
1451 	IOService::userSpaceDidReboot();
1452 	OSKext::setLoadEnabled(true);
1453 	OSKext::setUnloadEnabled(true);
1454 	OSKext::setAutounloadsEnabled(true);
1455 	OSKext::setKernelRequestsEnabled(true);
1456 	sOSKextWasResetAfterUserspaceReboot = true;
1457 	IORecursiveLockUnlock(sKextLock);
1458 }
1459 
1460 extern "C" void
1461 OSKextResetAfterUserspaceReboot(void)
1462 {
1463 	OSKext::resetAfterUserspaceReboot();
1464 }
1465 
1466 /*********************************************************************
1467 *********************************************************************/
1468 /* static */
1469 bool
1470 OSKext::getLoadEnabled(void)
1471 {
1472 	bool result;
1473 
1474 	IORecursiveLockLock(sKextLock);
1475 	result = sLoadEnabled;
1476 	IORecursiveLockUnlock(sKextLock);
1477 	return result;
1478 }
1479 
1480 /*********************************************************************
1481 *********************************************************************/
1482 /* static */
1483 bool
1484 OSKext::setLoadEnabled(bool flag)
1485 {
1486 	bool result;
1487 
1488 	IORecursiveLockLock(sKextLock);
1489 	result = sLoadEnabled;
1490 	sLoadEnabled = (flag ? true : false);
1491 
1492 	if (sLoadEnabled != result) {
1493 		OSKextLog(/* kext */ NULL,
1494 		    kOSKextLogBasicLevel |
1495 		    kOSKextLogLoadFlag,
1496 		    "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1497 	}
1498 
1499 	IORecursiveLockUnlock(sKextLock);
1500 
1501 	return result;
1502 }
1503 
1504 /*********************************************************************
1505 *********************************************************************/
1506 /* static */
1507 bool
1508 OSKext::getUnloadEnabled(void)
1509 {
1510 	bool result;
1511 
1512 	IORecursiveLockLock(sKextLock);
1513 	result = sUnloadEnabled;
1514 	IORecursiveLockUnlock(sKextLock);
1515 	return result;
1516 }
1517 
1518 /*********************************************************************
1519 *********************************************************************/
1520 /* static */
1521 bool
1522 OSKext::setUnloadEnabled(bool flag)
1523 {
1524 	bool result;
1525 
1526 	IORecursiveLockLock(sKextLock);
1527 	result = sUnloadEnabled;
1528 	sUnloadEnabled = (flag ? true : false);
1529 	IORecursiveLockUnlock(sKextLock);
1530 
1531 	if (sUnloadEnabled != result) {
1532 		OSKextLog(/* kext */ NULL,
1533 		    kOSKextLogBasicLevel |
1534 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1535 		    "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1536 	}
1537 
1538 	return result;
1539 }
1540 
1541 /*********************************************************************
1542 * Do not call any function that takes sKextLock here!
1543 *********************************************************************/
1544 /* static */
1545 bool
1546 OSKext::getAutounloadEnabled(void)
1547 {
1548 	bool result;
1549 
1550 	IORecursiveLockLock(sKextInnerLock);
1551 	result = sAutounloadEnabled ? true : false;
1552 	IORecursiveLockUnlock(sKextInnerLock);
1553 	return result;
1554 }
1555 
1556 /*********************************************************************
1557 * Do not call any function that takes sKextLock here!
1558 *********************************************************************/
1559 /* static */
1560 bool
1561 OSKext::setAutounloadsEnabled(bool flag)
1562 {
1563 	bool result;
1564 
1565 	IORecursiveLockLock(sKextInnerLock);
1566 
1567 	result = sAutounloadEnabled;
1568 	sAutounloadEnabled = (flag ? true : false);
1569 	if (!sAutounloadEnabled && sUnloadCallout) {
1570 		thread_call_cancel(sUnloadCallout);
1571 	}
1572 
1573 	if (sAutounloadEnabled != result) {
1574 		OSKextLog(/* kext */ NULL,
1575 		    kOSKextLogBasicLevel |
1576 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1577 		    "Kext autounloading now %sabled.",
1578 		    sAutounloadEnabled ? "en" : "dis");
1579 	}
1580 
1581 	IORecursiveLockUnlock(sKextInnerLock);
1582 
1583 	return result;
1584 }
1585 
1586 /*********************************************************************
1587 *********************************************************************/
1588 /* instance method operating on OSKext field */
1589 bool
1590 OSKext::setAutounloadEnabled(bool flag)
1591 {
1592 	bool result = flags.autounloadEnabled ? true : false;
1593 	flags.autounloadEnabled = flag ? 1 : 0;
1594 
1595 	if (result != (flag ? true : false)) {
1596 		OSKextLog(this,
1597 		    kOSKextLogProgressLevel |
1598 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1599 		    "Autounloading for kext %s now %sabled.",
1600 		    getIdentifierCString(),
1601 		    flags.autounloadEnabled ? "en" : "dis");
1602 	}
1603 	return result;
1604 }
1605 
1606 /*********************************************************************
1607 *********************************************************************/
1608 /* static */
1609 bool
1610 OSKext::setKernelRequestsEnabled(bool flag)
1611 {
1612 	bool result;
1613 
1614 	IORecursiveLockLock(sKextLock);
1615 	result = sKernelRequestsEnabled;
1616 	sKernelRequestsEnabled = flag ? true : false;
1617 
1618 	if (sKernelRequestsEnabled != result) {
1619 		OSKextLog(/* kext */ NULL,
1620 		    kOSKextLogBasicLevel |
1621 		    kOSKextLogGeneralFlag,
1622 		    "Kernel requests now %sabled.",
1623 		    sKernelRequestsEnabled ? "en" : "dis");
1624 	}
1625 	IORecursiveLockUnlock(sKextLock);
1626 	return result;
1627 }
1628 
1629 /*********************************************************************
1630 *********************************************************************/
1631 /* static */
1632 bool
1633 OSKext::getKernelRequestsEnabled(void)
1634 {
1635 	bool result;
1636 
1637 	IORecursiveLockLock(sKextLock);
1638 	result = sKernelRequestsEnabled;
1639 	IORecursiveLockUnlock(sKextLock);
1640 	return result;
1641 }
1642 
1643 static bool
1644 segmentIsMutable(kernel_segment_command_t *seg)
1645 {
1646 	/* Mutable segments have to have VM_PROT_WRITE */
1647 	if ((seg->maxprot & VM_PROT_WRITE) == 0) {
1648 		return false;
1649 	}
1650 	/* Exclude the __DATA_CONST segment */
1651 	if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) {
1652 		return false;
1653 	}
1654 	/* Exclude __LINKEDIT */
1655 	if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) {
1656 		return false;
1657 	}
1658 	return true;
1659 }
1660 
1661 #if PRAGMA_MARK
1662 #pragma mark Kext Life Cycle
1663 #endif
1664 /*********************************************************************
1665 *********************************************************************/
1666 OSSharedPtr<OSKext>
1667 OSKext::withPrelinkedInfoDict(
1668 	OSDictionary * anInfoDict,
1669 	bool doCoalescedSlides,
1670 	kc_kind_t type)
1671 {
1672 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
1673 
1674 	if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) {
1675 		return NULL;
1676 	}
1677 
1678 	return newKext;
1679 }
1680 
1681 /*********************************************************************
1682 *********************************************************************/
1683 bool
1684 OSKext::initWithPrelinkedInfoDict(
1685 	OSDictionary * anInfoDict,
1686 	bool doCoalescedSlides,
1687 	kc_kind_t type)
1688 {
1689 	bool            result              = false;
1690 	OSString      * kextPath            = NULL;                // do not release
1691 	OSNumber      * addressNum          = NULL;                // reused; do not release
1692 	OSNumber      * lengthNum           = NULL;                // reused; do not release
1693 	OSBoolean     * scratchBool         = NULL;                // do not release
1694 	void          * data                = NULL;                // do not free
1695 	void          * srcData             = NULL;                // do not free
1696 	OSSharedPtr<OSData>        prelinkedExecutable;
1697 	uint32_t        length              = 0;                // reused
1698 	uintptr_t       kext_slide          = PE_get_kc_slide(type);
1699 	bool            shouldSaveSegments  = false;
1700 
1701 	if (!super::init()) {
1702 		goto finish;
1703 	}
1704 
1705 	/* Get the path. Don't look for an arch-specific path property.
1706 	 */
1707 	kextPath = OSDynamicCast(OSString,
1708 	    anInfoDict->getObject(kPrelinkBundlePathKey));
1709 
1710 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1711 		goto finish;
1712 	}
1713 
1714 #if KASLR_KEXT_DEBUG
1715 	IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString());
1716 #endif
1717 
1718 	/* Also get the executable's bundle-relative path if present.
1719 	 * Don't look for an arch-specific path property.
1720 	 */
1721 	executableRelPath.reset(OSDynamicCast(OSString,
1722 	    anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain);
1723 	userExecutableRelPath.reset(OSDynamicCast(OSString,
1724 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
1725 
1726 	/* Don't need the paths to be in the info dictionary any more.
1727 	 */
1728 	anInfoDict->removeObject(kPrelinkBundlePathKey);
1729 	anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1730 
1731 	scratchBool = OSDynamicCast(OSBoolean,
1732 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
1733 	if (scratchBool == kOSBooleanTrue) {
1734 		flags.requireExplicitLoad = 1;
1735 	}
1736 
1737 	/* Create an OSData wrapper around the linked executable.
1738 	 */
1739 	addressNum = OSDynamicCast(OSNumber,
1740 	    anInfoDict->getObject(kPrelinkExecutableLoadKey));
1741 	if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) {
1742 		lengthNum = OSDynamicCast(OSNumber,
1743 		    anInfoDict->getObject(kPrelinkExecutableSizeKey));
1744 		if (!lengthNum) {
1745 			OSKextLog(this,
1746 			    kOSKextLogErrorLevel |
1747 			    kOSKextLogArchiveFlag,
1748 			    "Kext %s can't find prelinked kext executable size.",
1749 			    getIdentifierCString());
1750 			return result;
1751 		}
1752 
1753 		data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1754 		length = (uint32_t) (lengthNum->unsigned32BitValue());
1755 
1756 #if KASLR_KEXT_DEBUG
1757 		IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1758 		    (unsigned long)ml_static_unslide((vm_offset_t)data),
1759 		    (unsigned long)data,
1760 		    length);
1761 #endif
1762 
1763 		anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1764 		anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1765 
1766 		/* If the kext's load address differs from its source address, allocate
1767 		 * space in the kext map at the load address and copy the kext over.
1768 		 */
1769 		addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1770 		if (addressNum) {
1771 			srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1772 
1773 #if KASLR_KEXT_DEBUG
1774 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1775 			    (unsigned long)ml_static_unslide((vm_offset_t)srcData),
1776 			    (unsigned long)srcData);
1777 #endif
1778 
1779 			if (data != srcData) {
1780 #if __LP64__
1781 				kern_return_t alloc_result;
1782 
1783 				alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
1784 				if (alloc_result != KERN_SUCCESS) {
1785 					OSKextLog(this,
1786 					    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1787 					    "Failed to allocate space for prelinked kext %s.",
1788 					    getIdentifierCString());
1789 					goto finish;
1790 				}
1791 				memcpy(data, srcData, length);
1792 #else
1793 				OSKextLog(this,
1794 				    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1795 				    "Error: prelinked kext %s - source and load addresses "
1796 				    "differ on ILP32 architecture.",
1797 				    getIdentifierCString());
1798 				goto finish;
1799 #endif /* __LP64__ */
1800 			}
1801 
1802 			anInfoDict->removeObject(kPrelinkExecutableSourceKey);
1803 		}
1804 
1805 		prelinkedExecutable = OSData::withBytesNoCopy(data, length);
1806 		if (!prelinkedExecutable) {
1807 			OSKextLog(this,
1808 			    kOSKextLogErrorLevel |
1809 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1810 			    "Kext %s failed to create executable wrapper.",
1811 			    getIdentifierCString());
1812 			goto finish;
1813 		}
1814 
1815 #if VM_MAPPED_KEXTS
1816 		prelinkedExecutable->setDeallocFunction(osdata_kext_free);
1817 #else
1818 		prelinkedExecutable->setDeallocFunction(osdata_phys_free);
1819 #endif
1820 		setLinkedExecutable(prelinkedExecutable.get());
1821 		addressNum = OSDynamicCast(OSNumber,
1822 		    anInfoDict->getObject(kPrelinkKmodInfoKey));
1823 		if (!addressNum) {
1824 			OSKextLog(this,
1825 			    kOSKextLogErrorLevel |
1826 			    kOSKextLogArchiveFlag,
1827 			    "Kext %s can't find prelinked kext kmod_info address.",
1828 			    getIdentifierCString());
1829 			goto finish;
1830 		}
1831 
1832 		if (addressNum->unsigned64BitValue() != 0) {
1833 			kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1834 			if (kmod_info->address) {
1835 				kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide);
1836 			} else {
1837 				kmod_info->address = (uintptr_t)data;
1838 				kmod_info->size = length;
1839 			}
1840 #if KASLR_KEXT_DEBUG
1841 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1842 			    (unsigned long)((vm_offset_t)kmod_info) - kext_slide,
1843 			    (unsigned long)kmod_info);
1844 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1845 			    (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide,
1846 			    (unsigned long)kmod_info->address);
1847  #endif
1848 		}
1849 
1850 		anInfoDict->removeObject(kPrelinkKmodInfoKey);
1851 	}
1852 
1853 	if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
1854 		uintptr_t builtinTextStart;
1855 		uintptr_t builtinTextEnd;
1856 
1857 		flags.builtin = true;
1858 		builtinKmodIdx = addressNum->unsigned32BitValue();
1859 		assert(builtinKmodIdx < gBuiltinKmodsCount);
1860 
1861 		builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
1862 		builtinTextEnd   = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
1863 
1864 		kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
1865 		kmod_info->address = builtinTextStart;
1866 		kmod_info->size    = builtinTextEnd - builtinTextStart;
1867 	}
1868 
1869 	/* If the plist has a UUID for an interface, save that off.
1870 	 */
1871 	if (isInterface()) {
1872 		interfaceUUID.reset(OSDynamicCast(OSData,
1873 		    anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain);
1874 		if (interfaceUUID) {
1875 			anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
1876 		}
1877 	}
1878 
1879 	result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides));
1880 	if (!result) {
1881 		goto finish;
1882 	}
1883 
1884 	kc_type = type;
1885 	/* Exclude builtin and codeless kexts */
1886 	if (prelinkedExecutable && kmod_info) {
1887 		switch (kc_type) {
1888 		case KCKindPrimary:
1889 			shouldSaveSegments = (
1890 				getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue ||
1891 				getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue);
1892 			if (shouldSaveSegments) {
1893 				flags.resetSegmentsFromImmutableCopy = 1;
1894 			}
1895 			break;
1896 		case KCKindPageable:
1897 			flags.resetSegmentsFromVnode = 1;
1898 			break;
1899 		case KCKindAuxiliary:
1900 			if (!pageableKCloaded) {
1901 				flags.resetSegmentsFromImmutableCopy = 1;
1902 			} else if (resetAuxKCSegmentOnUnload) {
1903 				flags.resetSegmentsFromVnode = 1;
1904 			}
1905 			break;
1906 		default:
1907 			break;
1908 		}
1909 	}
1910 
1911 	if (flags.resetSegmentsFromImmutableCopy) {
1912 		/* Save a pristine copy of the mutable segments */
1913 		kernel_segment_command_t *seg = NULL;
1914 		kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
1915 
1916 		savedMutableSegments = OSArray::withCapacity(0);
1917 
1918 		for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) {
1919 			if (!segmentIsMutable(seg)) {
1920 				continue;
1921 			}
1922 			uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
1923 			uint64_t vmsize = seg->vmsize;
1924 			OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
1925 			    "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
1926 			OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg);
1927 			if (!savedSegment) {
1928 				OSKextLog(this,
1929 				    kOSKextLogErrorLevel |
1930 				    kOSKextLogGeneralFlag,
1931 				    "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
1932 				result = kOSKextReturnInternalError;
1933 				goto finish;
1934 			}
1935 			savedMutableSegments->setObject(savedSegment);
1936 		}
1937 	}
1938 
1939 	if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) {
1940 		/*
1941 		 * set VM protections now, wire pages for the old style Aux KC now,
1942 		 * wire pages for the rest of the KC types at load time.
1943 		 */
1944 		result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false));
1945 		if (!result) {
1946 			goto finish;
1947 		}
1948 	}
1949 
1950 	flags.prelinked = true;
1951 
1952 	/* If we created a kext from prelink info,
1953 	 * we must be booting from a prelinked kernel.
1954 	 */
1955 	sPrelinkBoot = true;
1956 
1957 	result = registerIdentifier();
1958 
1959 finish:
1960 	return result;
1961 }
1962 
1963 /*********************************************************************
1964 *********************************************************************/
1965 /* static */
1966 OSSharedPtr<OSKext>
1967 OSKext::withCodelessInfo(OSDictionary * anInfoDict)
1968 {
1969 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
1970 
1971 	if (newKext && !newKext->initWithCodelessInfo(anInfoDict)) {
1972 		return NULL;
1973 	}
1974 
1975 	return newKext;
1976 }
1977 
1978 /*********************************************************************
1979 *********************************************************************/
1980 bool
1981 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict)
1982 {
1983 	bool        result      = false;
1984 	OSString  * kextPath    = NULL;        // do not release
1985 	OSBoolean * scratchBool = NULL;        // do not release
1986 
1987 	if (anInfoDict == NULL || !super::init()) {
1988 		goto finish;
1989 	}
1990 
1991 	/*
1992 	 * Get the path. Don't look for an arch-specific path property.
1993 	 */
1994 	kextPath = OSDynamicCast(OSString,
1995 	    anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey));
1996 	if (!kextPath) {
1997 		OSKextLog(NULL,
1998 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
1999 		    "Requested codeless kext dictionary does not contain the '%s' key",
2000 		    kKextRequestArgumentCodelessInfoBundlePathKey);
2001 		goto finish;
2002 	}
2003 
2004 	uniquePersonalityProperties(anInfoDict);
2005 
2006 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2007 		goto finish;
2008 	}
2009 
2010 	/*
2011 	 * This path is meant to initialize codeless kexts only. Refuse
2012 	 * anything that looks like it has an executable and/or declares
2013 	 * itself as a kernel component.
2014 	 */
2015 	if (declaresExecutable() || isKernelComponent()) {
2016 		OSKextLog(NULL,
2017 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2018 		    "Refusing to register codeless kext that declares an executable/kernel component: %s",
2019 		    getIdentifierCString());
2020 		goto finish;
2021 	}
2022 
2023 	if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
2024 		boolean_t updated = updateExcludeList(infoDict.get());
2025 		if (updated) {
2026 			OSKextLog(this,
2027 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2028 			    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
2029 		}
2030 	}
2031 
2032 	kc_type = KCKindNone;
2033 
2034 	scratchBool = OSDynamicCast(OSBoolean,
2035 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
2036 	if (scratchBool == kOSBooleanTrue) {
2037 		flags.requireExplicitLoad = 1;
2038 	}
2039 
2040 	/* Also get the executable's bundle-relative path if present.
2041 	 * Don't look for an arch-specific path property.
2042 	 */
2043 	userExecutableRelPath.reset(OSDynamicCast(OSString,
2044 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
2045 
2046 	/* remove unnecessary paths from the info dict */
2047 	anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey);
2048 
2049 	result = registerIdentifier();
2050 
2051 finish:
2052 	return result;
2053 }
2054 
2055 /*********************************************************************
2056 *********************************************************************/
2057 /* static */
2058 void
2059 OSKext::setAllVMAttributes(void)
2060 {
2061 	OSSharedPtr<OSCollectionIterator> kextIterator;
2062 	const OSSymbol * thisID                 = NULL;        // do not release
2063 
2064 	IORecursiveLockLock(sKextLock);
2065 
2066 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
2067 	if (!kextIterator) {
2068 		goto finish;
2069 	}
2070 
2071 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
2072 		OSKext *    thisKext;        // do not release
2073 
2074 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
2075 		if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
2076 			continue;
2077 		}
2078 
2079 		if (!thisKext->flags.resetSegmentsFromVnode) {
2080 			/*
2081 			 * set VM protections now, wire pages for the old style Aux KC now,
2082 			 * wire pages for the rest of the KC types at load time.
2083 			 */
2084 			thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false);
2085 		}
2086 	}
2087 
2088 finish:
2089 	IORecursiveLockUnlock(sKextLock);
2090 
2091 	return;
2092 }
2093 
2094 /*********************************************************************
2095 *********************************************************************/
2096 OSSharedPtr<OSKext>
2097 OSKext::withBooterData(
2098 	OSString * deviceTreeName,
2099 	OSData   * booterData)
2100 {
2101 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
2102 
2103 	if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
2104 		return NULL;
2105 	}
2106 
2107 	return newKext;
2108 }
2109 
2110 /*********************************************************************
2111 *********************************************************************/
2112 typedef struct _BooterKextFileInfo {
2113 	uint32_t  infoDictPhysAddr;
2114 	uint32_t  infoDictLength;
2115 	uint32_t  executablePhysAddr;
2116 	uint32_t  executableLength;
2117 	uint32_t  bundlePathPhysAddr;
2118 	uint32_t  bundlePathLength;
2119 } _BooterKextFileInfo;
2120 
2121 bool
2122 OSKext::initWithBooterData(
2123 	OSString * deviceTreeName,
2124 	OSData   * booterData)
2125 {
2126 	bool                  result         = false;
2127 	_BooterKextFileInfo * kextFileInfo   = NULL;        // do not free
2128 	char                * infoDictAddr   = NULL;        // do not free
2129 	void                * executableAddr = NULL;        // do not free
2130 	char                * bundlePathAddr = NULL;        // do not free
2131 
2132 	OSDictionary        * theInfoDict    = NULL;        // do not release
2133 	OSSharedPtr<OSObject> parsedXML;
2134 	OSSharedPtr<OSString> kextPath;
2135 
2136 	OSSharedPtr<OSString> errorString;
2137 	OSSharedPtr<OSData>   executable;
2138 
2139 	if (!super::init()) {
2140 		goto finish;
2141 	}
2142 
2143 	kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
2144 	if (!kextFileInfo) {
2145 		OSKextLog(this,
2146 		    kOSKextLogErrorLevel |
2147 		    kOSKextLogGeneralFlag,
2148 		    "No booter-provided data for kext device tree entry %s.",
2149 		    deviceTreeName->getCStringNoCopy());
2150 		goto finish;
2151 	}
2152 
2153 	/* The info plist must exist or we can't read the kext.
2154 	 */
2155 	if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
2156 		OSKextLog(this,
2157 		    kOSKextLogErrorLevel |
2158 		    kOSKextLogGeneralFlag,
2159 		    "No kext info dictionary for booter device tree entry %s.",
2160 		    deviceTreeName->getCStringNoCopy());
2161 		goto finish;
2162 	}
2163 
2164 	infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
2165 	if (!infoDictAddr) {
2166 		OSKextLog(this,
2167 		    kOSKextLogErrorLevel |
2168 		    kOSKextLogGeneralFlag,
2169 		    "Can't translate physical address 0x%x of kext info dictionary "
2170 		    "for device tree entry %s.",
2171 		    (int)kextFileInfo->infoDictPhysAddr,
2172 		    deviceTreeName->getCStringNoCopy());
2173 		goto finish;
2174 	}
2175 
2176 	parsedXML = OSUnserializeXML(infoDictAddr, errorString);
2177 	if (parsedXML) {
2178 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
2179 	}
2180 	if (!theInfoDict) {
2181 		const char * errorCString = "(unknown error)";
2182 
2183 		if (errorString && errorString->getCStringNoCopy()) {
2184 			errorCString = errorString->getCStringNoCopy();
2185 		} else if (parsedXML) {
2186 			errorCString = "not a dictionary";
2187 		}
2188 		OSKextLog(this,
2189 		    kOSKextLogErrorLevel |
2190 		    kOSKextLogGeneralFlag,
2191 		    "Error unserializing info dictionary for device tree entry %s: %s.",
2192 		    deviceTreeName->getCStringNoCopy(), errorCString);
2193 		goto finish;
2194 	}
2195 
2196 	/* A bundle path is not mandatory.
2197 	 */
2198 	if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
2199 		bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
2200 		if (!bundlePathAddr) {
2201 			OSKextLog(this,
2202 			    kOSKextLogErrorLevel |
2203 			    kOSKextLogGeneralFlag,
2204 			    "Can't translate physical address 0x%x of kext bundle path "
2205 			    "for device tree entry %s.",
2206 			    (int)kextFileInfo->bundlePathPhysAddr,
2207 			    deviceTreeName->getCStringNoCopy());
2208 			goto finish;
2209 		}
2210 		bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0';         // just in case!
2211 
2212 		kextPath = OSString::withCString(bundlePathAddr);
2213 		if (!kextPath) {
2214 			OSKextLog(this,
2215 			    kOSKextLogErrorLevel |
2216 			    kOSKextLogGeneralFlag,
2217 			    "Failed to create wrapper for device tree entry %s kext path %s.",
2218 			    deviceTreeName->getCStringNoCopy(), bundlePathAddr);
2219 			goto finish;
2220 		}
2221 	}
2222 
2223 	if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) {
2224 		goto finish;
2225 	}
2226 
2227 	/* An executable is not mandatory.
2228 	 */
2229 	if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
2230 		executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
2231 		if (!executableAddr) {
2232 			OSKextLog(this,
2233 			    kOSKextLogErrorLevel |
2234 			    kOSKextLogGeneralFlag,
2235 			    "Can't translate physical address 0x%x of kext executable "
2236 			    "for device tree entry %s.",
2237 			    (int)kextFileInfo->executablePhysAddr,
2238 			    deviceTreeName->getCStringNoCopy());
2239 			goto finish;
2240 		}
2241 
2242 		executable = OSData::withBytesNoCopy(executableAddr,
2243 		    kextFileInfo->executableLength);
2244 		if (!executable) {
2245 			OSKextLog(this,
2246 			    kOSKextLogErrorLevel |
2247 			    kOSKextLogGeneralFlag,
2248 			    "Failed to create executable wrapper for device tree entry %s.",
2249 			    deviceTreeName->getCStringNoCopy());
2250 			goto finish;
2251 		}
2252 
2253 		/* A kext with an executable needs to retain the whole booterData
2254 		 * object to keep the executable in memory.
2255 		 */
2256 		if (!setExecutable(executable.get(), booterData)) {
2257 			OSKextLog(this,
2258 			    kOSKextLogErrorLevel |
2259 			    kOSKextLogGeneralFlag,
2260 			    "Failed to set kext executable for device tree entry %s.",
2261 			    deviceTreeName->getCStringNoCopy());
2262 			goto finish;
2263 		}
2264 	}
2265 
2266 	result = registerIdentifier();
2267 
2268 finish:
2269 	return result;
2270 }
2271 
2272 /*********************************************************************
2273 *********************************************************************/
2274 bool
2275 OSKext::registerIdentifier(void)
2276 {
2277 	bool            result              = false;
2278 	OSKext        * existingKext        = NULL;        // do not release
2279 	bool            existingIsLoaded    = false;
2280 	bool            existingIsPrelinked = false;
2281 	bool            existingIsCodeless  = false;
2282 	bool            existingIsDext      = false;
2283 	OSKextVersion   newVersion          = -1;
2284 	OSKextVersion   existingVersion     = -1;
2285 	char            newVersionCString[kOSKextVersionMaxLength];
2286 	char            existingVersionCString[kOSKextVersionMaxLength];
2287 	OSSharedPtr<OSData> newUUID;
2288 	OSSharedPtr<OSData> existingUUID;
2289 
2290 	IORecursiveLockLock(sKextLock);
2291 
2292 	/* Get the new kext's version for checks & log messages.
2293 	 */
2294 	newVersion = getVersion();
2295 	OSKextVersionGetString(newVersion, newVersionCString,
2296 	    kOSKextVersionMaxLength);
2297 
2298 	/* If we don't have an existing kext with this identifier,
2299 	 * just record the new kext and we're done!
2300 	 */
2301 	existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get()));
2302 	if (!existingKext) {
2303 		sKextsByID->setObject(bundleID.get(), this);
2304 		result = true;
2305 		goto finish;
2306 	}
2307 
2308 	/* Get the existing kext's version for checks & log messages.
2309 	 */
2310 	existingVersion = existingKext->getVersion();
2311 	OSKextVersionGetString(existingVersion,
2312 	    existingVersionCString, kOSKextVersionMaxLength);
2313 
2314 	existingIsLoaded = existingKext->isLoaded();
2315 	existingIsPrelinked = existingKext->isPrelinked();
2316 	existingIsDext = existingKext->isDriverKit();
2317 	existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext;
2318 
2319 	/* If we have a non-codeless kext with this identifier that's already
2320 	 * loaded/prelinked, we can't use the new one, but let's be really
2321 	 * thorough and check how the two are related for a precise diagnostic
2322 	 * log message.
2323 	 *
2324 	 * This check is valid for kexts that declare an executable and for
2325 	 * dexts, but not for codeless kexts - we can just replace those.
2326 	 */
2327 	if ((!existingIsCodeless || existingIsDext) &&
2328 	    (existingIsLoaded || existingIsPrelinked)) {
2329 		bool sameVersion = (newVersion == existingVersion);
2330 		bool sameExecutable = true;         // assume true unless we have UUIDs
2331 
2332 		/* Only get the UUID if the existing kext is loaded. Doing so
2333 		 * might have to uncompress an mkext executable and we shouldn't
2334 		 * take that hit when neither kext is loaded.
2335 		 *
2336 		 * Note: there is no decompression that happens when all kexts
2337 		 * are loaded from kext collecitons.
2338 		 */
2339 		newUUID = copyUUID();
2340 		existingUUID = existingKext->copyUUID();
2341 
2342 		if (existingIsDext && !isDriverKit()) {
2343 			OSKextLog(this,
2344 			    kOSKextLogWarningLevel |
2345 			    kOSKextLogKextBookkeepingFlag,
2346 			    "Notice - new kext %s, v%s matches a %s dext"
2347 			    "with the same bundle ID, v%s.",
2348 			    getIdentifierCString(), newVersionCString,
2349 			    (existingIsLoaded ? "loaded" : "prelinked"),
2350 			    existingVersionCString);
2351 			goto finish;
2352 		}
2353 
2354 		/* I'm entirely too paranoid about checking equivalence of executables,
2355 		 * but I remember nasty problems with it in the past.
2356 		 *
2357 		 * - If we have UUIDs for both kexts, compare them.
2358 		 * - If only one kext has a UUID, they're definitely different.
2359 		 */
2360 		if (newUUID && existingUUID) {
2361 			sameExecutable = newUUID->isEqualTo(existingUUID.get());
2362 		} else if (newUUID || existingUUID) {
2363 			sameExecutable = false;
2364 		}
2365 
2366 		if (!newUUID && !existingUUID) {
2367 			/* If there are no UUIDs, we can't really tell that the executables
2368 			 * are *different* without a lot of work; the loaded kext's
2369 			 * unrelocated executable is no longer around (and we never had it
2370 			 * in-kernel for a prelinked kext). We certainly don't want to do
2371 			 * a whole fake link for the new kext just to compare, either.
2372 			 */
2373 			OSKextLog(this,
2374 			    kOSKextLogWarningLevel |
2375 			    kOSKextLogKextBookkeepingFlag,
2376 			    "Notice - new kext %s, v%s matches %s kext "
2377 			    "but can't determine if executables are the same (no UUIDs).",
2378 			    getIdentifierCString(),
2379 			    newVersionCString,
2380 			    (existingIsLoaded ? "loaded" : "prelinked"));
2381 		}
2382 
2383 		if (sameVersion && sameExecutable) {
2384 			OSKextLog(this,
2385 			    (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2386 			    kOSKextLogKextBookkeepingFlag,
2387 			    "Refusing new kext %s, v%s: a %s copy is already present "
2388 			    "(same version and executable).",
2389 			    getIdentifierCString(), newVersionCString,
2390 			    (existingIsLoaded ? "loaded" : "prelinked"));
2391 		} else {
2392 			if (!sameVersion) {
2393 				/* This condition is significant so log it under warnings.
2394 				 */
2395 				OSKextLog(this,
2396 				    kOSKextLogWarningLevel |
2397 				    kOSKextLogKextBookkeepingFlag,
2398 				    "Refusing new kext %s, v%s: already have %s v%s.",
2399 				    getIdentifierCString(),
2400 				    newVersionCString,
2401 				    (existingIsLoaded ? "loaded" : "prelinked"),
2402 				    existingVersionCString);
2403 			} else {
2404 				/* This condition is significant so log it under warnings.
2405 				 */
2406 				OSKextLog(this,
2407 				    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2408 				    "Refusing new kext %s, v%s: a %s copy with a different "
2409 				    "executable UUID is already present.",
2410 				    getIdentifierCString(), newVersionCString,
2411 				    (existingIsLoaded ? "loaded" : "prelinked"));
2412 			}
2413 		}
2414 		goto finish;
2415 	} /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */
2416 
2417 	/* Refuse to allow an existing loaded codeless kext be replaced by a
2418 	 * normal kext with the same bundle ID.
2419 	 */
2420 	if (existingIsCodeless && declaresExecutable()) {
2421 		OSKextLog(this,
2422 		    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2423 		    "Refusing new kext %s, v%s: a codeless copy is already %s",
2424 		    getIdentifierCString(), newVersionCString,
2425 		    (existingIsLoaded ? "loaded" : "prelinked"));
2426 		goto finish;
2427 	}
2428 
2429 	/* Dexts packaged in the BootKC will be protected against replacement
2430 	 * by non-dexts by the logic above which checks if they are prelinked.
2431 	 * Dexts which are prelinked into the System KC will be registered
2432 	 * before any other kexts in the AuxKC are registered, and we never
2433 	 * put dexts in the AuxKC. Therefore, there is no need to check if an
2434 	 * existing object is a dext and is being replaced by a non-dext.
2435 	 * The scenario cannot happen by construction.
2436 	 *
2437 	 * See: OSKext::loadFileSetKexts()
2438 	 */
2439 
2440 	/* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2441 	 * user loads are happening or if we're still in early boot. User agents are
2442 	 * supposed to resolve dependencies topside and include only the exact
2443 	 * kexts needed; so we always accept the new kext (in fact we should never
2444 	 * see an older unloaded copy hanging around).
2445 	 */
2446 	if (sUserLoadsActive) {
2447 		sKextsByID->setObject(bundleID.get(), this);
2448 		result = true;
2449 
2450 		OSKextLog(this,
2451 		    kOSKextLogStepLevel |
2452 		    kOSKextLogKextBookkeepingFlag,
2453 		    "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2454 		    getIdentifierCString(),
2455 		    existingVersionCString,
2456 		    newVersionCString);
2457 
2458 		goto finish;
2459 	}
2460 
2461 	/* During early boot, the kext with the highest version always wins out.
2462 	 * Prelinked kernels will never hit this, but mkexts and booter-read
2463 	 * kexts might have duplicates.
2464 	 */
2465 	if (newVersion > existingVersion) {
2466 		sKextsByID->setObject(bundleID.get(), this);
2467 		result = true;
2468 
2469 		OSKextLog(this,
2470 		    kOSKextLogStepLevel |
2471 		    kOSKextLogKextBookkeepingFlag,
2472 		    "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2473 		    existingVersionCString,
2474 		    getIdentifierCString(),
2475 		    newVersionCString);
2476 	} else {
2477 		OSKextLog(this,
2478 		    kOSKextLogStepLevel |
2479 		    kOSKextLogKextBookkeepingFlag,
2480 		    "Kext %s is already registered with a higher/same version (v%s); "
2481 		    "dropping newly-added (v%s).",
2482 		    getIdentifierCString(),
2483 		    existingVersionCString,
2484 		    newVersionCString);
2485 	}
2486 
2487 	/* result has been set appropriately by now. */
2488 
2489 finish:
2490 
2491 	IORecursiveLockUnlock(sKextLock);
2492 
2493 	if (result) {
2494 		OSKextLog(this,
2495 		    kOSKextLogStepLevel |
2496 		    kOSKextLogKextBookkeepingFlag,
2497 		    "Kext %s, v%s registered and available for loading.",
2498 		    getIdentifierCString(), newVersionCString);
2499 	}
2500 
2501 	return result;
2502 }
2503 
2504 /*********************************************************************
2505  * Does the bare minimum validation to look up a kext.
2506  * All other validation is done on the spot as needed.
2507  **********************************************************************/
2508 bool
2509 OSKext::setInfoDictionaryAndPath(
2510 	OSDictionary * aDictionary,
2511 	OSString     * aPath)
2512 {
2513 	bool           result                   = false;
2514 	OSString     * bundleIDString           = NULL;        // do not release
2515 	OSString     * versionString            = NULL;        // do not release
2516 	OSString     * compatibleVersionString  = NULL;        // do not release
2517 	const char   * versionCString           = NULL;        // do not free
2518 	const char   * compatibleVersionCString = NULL;        // do not free
2519 	OSBoolean    * scratchBool              = NULL;        // do not release
2520 	OSDictionary * scratchDict              = NULL;        // do not release
2521 
2522 	if (infoDict) {
2523 		panic("Attempt to set info dictionary on a kext "
2524 		    "that already has one (%s).",
2525 		    getIdentifierCString());
2526 	}
2527 
2528 	if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
2529 		goto finish;
2530 	}
2531 
2532 	infoDict.reset(aDictionary, OSRetain);
2533 
2534 	/* Check right away if the info dictionary has any log flags.
2535 	 */
2536 	scratchBool = OSDynamicCast(OSBoolean,
2537 	    getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
2538 	if (scratchBool == kOSBooleanTrue) {
2539 		flags.loggingEnabled = 1;
2540 	}
2541 
2542 	/* The very next thing to get is the bundle identifier. Unlike
2543 	 * in user space, a kext with no bundle identifier gets axed
2544 	 * immediately.
2545 	 */
2546 	bundleIDString = OSDynamicCast(OSString,
2547 	    getPropertyForHostArch(kCFBundleIdentifierKey));
2548 	if (!bundleIDString) {
2549 		OSKextLog(this,
2550 		    kOSKextLogErrorLevel |
2551 		    kOSKextLogValidationFlag,
2552 		    "CFBundleIdentifier missing/invalid type in kext %s.",
2553 		    aPath ? aPath->getCStringNoCopy() : "(unknown)");
2554 		goto finish;
2555 	}
2556 	bundleID = OSSymbol::withString(bundleIDString);
2557 	if (!bundleID) {
2558 		OSKextLog(this,
2559 		    kOSKextLogErrorLevel |
2560 		    kOSKextLogValidationFlag,
2561 		    "Can't copy bundle identifier as symbol for kext %s.",
2562 		    bundleIDString->getCStringNoCopy());
2563 		goto finish;
2564 	}
2565 
2566 	/* Save the path if we got one (it should always be available but it's
2567 	 * just something nice to have for bookkeeping).
2568 	 */
2569 	if (aPath) {
2570 		path.reset(aPath, OSRetain);
2571 	}
2572 
2573 	/*****
2574 	 * Minimal validation to initialize. We'll do other validation on the spot.
2575 	 */
2576 	if (bundleID->getLength() >= KMOD_MAX_NAME) {
2577 		OSKextLog(this,
2578 		    kOSKextLogErrorLevel |
2579 		    kOSKextLogValidationFlag,
2580 		    "Kext %s error - CFBundleIdentifier over max length %d.",
2581 		    getIdentifierCString(), KMOD_MAX_NAME - 1);
2582 		goto finish;
2583 	}
2584 
2585 	version = compatibleVersion = -1;
2586 
2587 	versionString = OSDynamicCast(OSString,
2588 	    getPropertyForHostArch(kCFBundleVersionKey));
2589 	if (!versionString) {
2590 		OSKextLog(this,
2591 		    kOSKextLogErrorLevel |
2592 		    kOSKextLogValidationFlag,
2593 		    "Kext %s error - CFBundleVersion missing/invalid type.",
2594 		    getIdentifierCString());
2595 		goto finish;
2596 	}
2597 	versionCString = versionString->getCStringNoCopy();
2598 	version = OSKextParseVersionString(versionCString);
2599 	if (version < 0) {
2600 		OSKextLog(this,
2601 		    kOSKextLogErrorLevel |
2602 		    kOSKextLogValidationFlag,
2603 		    "Kext %s error - CFBundleVersion bad value '%s'.",
2604 		    getIdentifierCString(), versionCString);
2605 		goto finish;
2606 	}
2607 
2608 	compatibleVersion = -1;         // set to illegal value for kexts that don't have
2609 
2610 	compatibleVersionString = OSDynamicCast(OSString,
2611 	    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2612 	if (compatibleVersionString) {
2613 		compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2614 		compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2615 		if (compatibleVersion < 0) {
2616 			OSKextLog(this,
2617 			    kOSKextLogErrorLevel |
2618 			    kOSKextLogValidationFlag,
2619 			    "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2620 			    getIdentifierCString(), compatibleVersionCString);
2621 			goto finish;
2622 		}
2623 
2624 		if (compatibleVersion > version) {
2625 			OSKextLog(this,
2626 			    kOSKextLogErrorLevel |
2627 			    kOSKextLogValidationFlag,
2628 			    "Kext %s error - %s %s > %s %s (must be <=).",
2629 			    getIdentifierCString(),
2630 			    kOSBundleCompatibleVersionKey, compatibleVersionCString,
2631 			    kCFBundleVersionKey, versionCString);
2632 			goto finish;
2633 		}
2634 	}
2635 
2636 	/* Check to see if this kext is in exclude list */
2637 	if (isInExcludeList()) {
2638 		OSKextLog(this,
2639 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2640 		    "Kext %s is in exclude list, not loadable",
2641 		    getIdentifierCString());
2642 		goto finish;
2643 	}
2644 
2645 	/* Set flags for later use if the infoDict gets flushed. We only
2646 	 * check for true values, not false ones(!)
2647 	 */
2648 	scratchBool = OSDynamicCast(OSBoolean,
2649 	    getPropertyForHostArch(kOSBundleIsInterfaceKey));
2650 	if (scratchBool == kOSBooleanTrue) {
2651 		flags.interface = 1;
2652 	}
2653 
2654 	scratchBool = OSDynamicCast(OSBoolean,
2655 	    getPropertyForHostArch(kOSKernelResourceKey));
2656 	if (scratchBool == kOSBooleanTrue) {
2657 		flags.kernelComponent = 1;
2658 		flags.interface = 1;         // xxx - hm. the kernel itself isn't an interface...
2659 		flags.started = 1;
2660 
2661 		/* A kernel component has one implicit dependency on the kernel.
2662 		 */
2663 		flags.hasAllDependencies = 1;
2664 	}
2665 
2666 	/* Make sure common string values in personalities are uniqued to OSSymbols.
2667 	 */
2668 	scratchDict = OSDynamicCast(OSDictionary,
2669 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
2670 	if (scratchDict) {
2671 		uniquePersonalityProperties(scratchDict);
2672 	}
2673 
2674 	result = true;
2675 
2676 finish:
2677 
2678 	return result;
2679 }
2680 
2681 /*********************************************************************
2682 * Not used for prelinked kernel boot as there is no unrelocated
2683 * executable.
2684 *********************************************************************/
2685 bool
2686 OSKext::setExecutable(
2687 	OSData * anExecutable,
2688 	OSData * externalData,
2689 	bool     externalDataIsMkext)
2690 {
2691 	bool         result        = false;
2692 	const char * executableKey = NULL;         // do not free
2693 
2694 	if (!anExecutable) {
2695 		infoDict->removeObject(_kOSKextExecutableKey);
2696 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
2697 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
2698 		result = true;
2699 		goto finish;
2700 	}
2701 
2702 	if (infoDict->getObject(_kOSKextExecutableKey) ||
2703 	    infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
2704 		panic("Attempt to set an executable on a kext "
2705 		    "that already has one (%s).",
2706 		    getIdentifierCString());
2707 		goto finish;
2708 	}
2709 
2710 	if (externalDataIsMkext) {
2711 		executableKey = _kOSKextMkextExecutableReferenceKey;
2712 	} else {
2713 		executableKey = _kOSKextExecutableKey;
2714 	}
2715 
2716 	if (anExecutable) {
2717 		infoDict->setObject(executableKey, anExecutable);
2718 		if (externalData) {
2719 			infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
2720 		}
2721 	}
2722 
2723 	result = true;
2724 
2725 finish:
2726 	return result;
2727 }
2728 
2729 /*********************************************************************
2730 *********************************************************************/
2731 static void
2732 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
2733 {
2734 	OSObject       * value       = NULL;        // do not release
2735 	OSString       * stringValue = NULL;        // do not release
2736 	OSSharedPtr<const OSSymbol> symbolValue;
2737 
2738 	value = dict->getObject(key);
2739 	if (!value) {
2740 		goto finish;
2741 	}
2742 	if (OSDynamicCast(OSSymbol, value)) {
2743 		/* this is already an OSSymbol: we're good */
2744 		goto finish;
2745 	}
2746 
2747 	stringValue = OSDynamicCast(OSString, value);
2748 	if (!stringValue) {
2749 		goto finish;
2750 	}
2751 
2752 	symbolValue = OSSymbol::withString(stringValue);
2753 	if (!symbolValue) {
2754 		goto finish;
2755 	}
2756 
2757 	dict->setObject(key, symbolValue.get());
2758 
2759 finish:
2760 	return;
2761 }
2762 
2763 /*********************************************************************
2764 *********************************************************************/
2765 static void
2766 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
2767 {
2768 	OSObject       * value       = NULL;        // do not release
2769 	OSString       * stringValue = NULL;        // do not release
2770 	OSSharedPtr<const OSSymbol> symbolValue;
2771 
2772 	value = dict->getObject(key);
2773 	if (!value) {
2774 		goto finish;
2775 	}
2776 	if (OSDynamicCast(OSSymbol, value)) {
2777 		/* this is already an OSSymbol: we're good */
2778 		goto finish;
2779 	}
2780 
2781 	stringValue = OSDynamicCast(OSString, value);
2782 	if (!stringValue) {
2783 		goto finish;
2784 	}
2785 
2786 	symbolValue = OSSymbol::withString(stringValue);
2787 	if (!symbolValue) {
2788 		goto finish;
2789 	}
2790 
2791 	dict->setObject(key, symbolValue.get());
2792 
2793 finish:
2794 	return;
2795 }
2796 
2797 void
2798 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
2799 {
2800 	OSKext::uniquePersonalityProperties(personalityDict, true);
2801 }
2802 
2803 /*********************************************************************
2804 * Replace common personality property values with uniqued instances
2805 * to save on wired memory.
2806 *********************************************************************/
2807 /* static */
2808 void
2809 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier)
2810 {
2811 	/* Properties every personality has.
2812 	 */
2813 	uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
2814 	uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
2815 	uniqueStringPlistProperty(personalityDict, gIOClassKey.get());
2816 	if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
2817 		uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
2818 	} else if (defaultAddKernelBundleIdentifier) {
2819 		personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
2820 	}
2821 
2822 	/* Other commonly used properties.
2823 	 */
2824 	uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
2825 	uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
2826 	uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
2827 
2828 	uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
2829 	uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
2830 	uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
2831 	uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
2832 	uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
2833 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
2834 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
2835 	uniqueStringPlistProperty(personalityDict, "Vendor");
2836 	uniqueStringPlistProperty(personalityDict, "Vendor Identification");
2837 	uniqueStringPlistProperty(personalityDict, "Vendor Name");
2838 	uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
2839 	uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
2840 	uniqueStringPlistProperty(personalityDict, "idProduct");
2841 
2842 	return;
2843 }
2844 
2845 /*********************************************************************
2846 *********************************************************************/
2847 void
2848 OSKext::free(void)
2849 {
2850 	if (isLoaded()) {
2851 		panic("Attempt to free loaded kext %s.", getIdentifierCString());
2852 	}
2853 
2854 	infoDict.reset();
2855 	bundleID.reset();
2856 	path.reset();
2857 	executableRelPath.reset();
2858 	userExecutableRelPath.reset();
2859 	dependencies.reset();
2860 	linkedExecutable.reset();
2861 	metaClasses.reset();
2862 	interfaceUUID.reset();
2863 	driverKitUUID.reset();
2864 
2865 	if (isInterface() && kmod_info) {
2866 		kfree(kmod_info, sizeof(kmod_info_t));
2867 	}
2868 
2869 	super::free();
2870 	return;
2871 }
2872 
2873 #if PRAGMA_MARK
2874 #pragma mark Mkext files
2875 #endif
2876 
2877 #if CONFIG_KXLD
2878 /*
2879  * mkext archives are really only relevant on kxld-enabled kernels.
2880  * Without a dynamic kernel linker, we don't need to support any mkexts.
2881  */
2882 
2883 /*********************************************************************
2884 *********************************************************************/
2885 OSReturn
2886 OSKext::readMkextArchive(OSData * mkextData,
2887     uint32_t * checksumPtr)
2888 {
2889 	OSReturn       result       = kOSKextReturnBadData;
2890 	uint32_t       mkextLength  = 0;
2891 	mkext_header * mkextHeader  = NULL;        // do not free
2892 	uint32_t       mkextVersion = 0;
2893 
2894 	/* Note default return of kOSKextReturnBadData above.
2895 	 */
2896 	mkextLength = mkextData->getLength();
2897 	if (mkextLength < sizeof(mkext_basic_header)) {
2898 		OSKextLog(/* kext */ NULL,
2899 		    kOSKextLogErrorLevel |
2900 		    kOSKextLogArchiveFlag,
2901 		    "Mkext archive too small to be valid.");
2902 		goto finish;
2903 	}
2904 
2905 	mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
2906 
2907 	if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
2908 	    MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
2909 		OSKextLog(/* kext */ NULL,
2910 		    kOSKextLogErrorLevel |
2911 		    kOSKextLogArchiveFlag,
2912 		    "Mkext archive has invalid magic or signature.");
2913 		goto finish;
2914 	}
2915 
2916 	if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
2917 		OSKextLog(/* kext */ NULL,
2918 		    kOSKextLogErrorLevel |
2919 		    kOSKextLogArchiveFlag,
2920 		    "Mkext archive recorded length doesn't match actual file length.");
2921 		goto finish;
2922 	}
2923 
2924 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2925 
2926 	if (mkextVersion == MKEXT_VERS_2) {
2927 		result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
2928 	} else {
2929 		OSKextLog(/* kext */ NULL,
2930 		    kOSKextLogErrorLevel |
2931 		    kOSKextLogArchiveFlag,
2932 		    "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
2933 		result = kOSKextReturnUnsupported;
2934 	}
2935 
2936 finish:
2937 	return result;
2938 }
2939 
2940 /*********************************************************************
2941 * Assumes magic, signature, version, length have been checked.
2942 * xxx - need to add further bounds checking for each file entry
2943 *
2944 * Should keep track of all kexts created so far, and if we hit a
2945 * fatal error halfway through, remove those kexts. If we've dropped
2946 * an older version that had already been read, whoops! Might want to
2947 * add a level of buffering?
2948 *********************************************************************/
2949 /* static */
2950 OSReturn
2951 OSKext::readMkext2Archive(
2952 	OSData        * mkextData,
2953 	OSDictionary ** mkextPlistOut,
2954 	uint32_t      * checksumPtr)
2955 {
2956 	OSReturn        result                     = kOSReturnError;
2957 	uint32_t        mkextLength;
2958 	mkext2_header * mkextHeader                = NULL;        // do not free
2959 	void          * mkextEnd                   = NULL;        // do not free
2960 	uint32_t        mkextVersion;
2961 	uint8_t       * crc_address                = NULL;
2962 	size_t          crc_buffer_size            = 0;
2963 	uint32_t        checksum;
2964 	uint32_t        mkextPlistOffset;
2965 	uint32_t        mkextPlistCompressedSize;
2966 	char          * mkextPlistEnd              = NULL;        // do not free
2967 	uint32_t        mkextPlistFullSize;
2968 	OSSharedPtr<OSString>     errorString;
2969 	OSSharedPtr<OSData>       mkextPlistUncompressedData;
2970 	const char    * mkextPlistDataBuffer       = NULL;        // do not free
2971 	OSSharedPtr<OSObject>      parsedXML;
2972 	OSDictionary  * mkextPlist                 = NULL;        // do not release
2973 	OSArray       * mkextInfoDictArray         = NULL;        // do not release
2974 	uint32_t        count, i;
2975 	kc_format_t kc_format;
2976 
2977 	if (!PE_get_primary_kc_format(&kc_format)) {
2978 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2979 		    "Unable to determine primary KC format");
2980 		goto finish;
2981 	}
2982 
2983 	mkextLength = mkextData->getLength();
2984 	mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
2985 	mkextEnd = (char *)mkextHeader + mkextLength;
2986 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2987 
2988 	crc_address = (u_int8_t *)&mkextHeader->version;
2989 	crc_buffer_size = (uintptr_t)mkextHeader +
2990 	    MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address;
2991 	if (crc_buffer_size > INT32_MAX) {
2992 		OSKextLog(/* kext */ NULL,
2993 		    kOSKextLogErrorLevel |
2994 		    kOSKextLogArchiveFlag,
2995 		    "Mkext archive size is too large (%lu > INT32_MAX).",
2996 		    crc_buffer_size);
2997 		result = kOSKextReturnBadData;
2998 		goto finish;
2999 	}
3000 	checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size);
3001 
3002 	if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
3003 		OSKextLog(/* kext */ NULL,
3004 		    kOSKextLogErrorLevel |
3005 		    kOSKextLogArchiveFlag,
3006 		    "Mkext archive has bad checksum.");
3007 		result = kOSKextReturnBadData;
3008 		goto finish;
3009 	}
3010 
3011 	if (checksumPtr) {
3012 		*checksumPtr = checksum;
3013 	}
3014 
3015 	/* Check that the CPU type & subtype match that of the running kernel. */
3016 	if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
3017 		OSKextLog(/* kext */ NULL,
3018 		    kOSKextLogErrorLevel |
3019 		    kOSKextLogArchiveFlag,
3020 		    "Mkext archive must have a specific CPU type.");
3021 		result = kOSKextReturnBadData;
3022 		goto finish;
3023 	} else {
3024 		if ((UInt32)_mh_execute_header.cputype !=
3025 		    MKEXT_GET_CPUTYPE(mkextHeader)) {
3026 			OSKextLog(/* kext */ NULL,
3027 			    kOSKextLogErrorLevel |
3028 			    kOSKextLogArchiveFlag,
3029 			    "Mkext archive does not match the running kernel's CPU type.");
3030 			result = kOSKextReturnArchNotFound;
3031 			goto finish;
3032 		}
3033 	}
3034 
3035 	mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
3036 	mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
3037 	mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
3038 	    mkextPlistCompressedSize;
3039 	if (mkextPlistEnd > mkextEnd) {
3040 		OSKextLog(/* kext */ NULL,
3041 		    kOSKextLogErrorLevel |
3042 		    kOSKextLogArchiveFlag,
3043 		    "Mkext archive file overrun.");
3044 		result = kOSKextReturnBadData;
3045 	}
3046 
3047 	mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
3048 	if (mkextPlistCompressedSize) {
3049 		mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
3050 			(UInt8 *)mkextHeader + mkextPlistOffset,
3051 			"plist",
3052 			mkextPlistCompressedSize, mkextPlistFullSize);
3053 		if (!mkextPlistUncompressedData) {
3054 			goto finish;
3055 		}
3056 		mkextPlistDataBuffer = (const char *)
3057 		    mkextPlistUncompressedData->getBytesNoCopy();
3058 	} else {
3059 		mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
3060 	}
3061 
3062 	/* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
3063 	 */
3064 	parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString);
3065 	if (parsedXML) {
3066 		mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get());
3067 	}
3068 	if (!mkextPlist) {
3069 		const char * errorCString = "(unknown error)";
3070 
3071 		if (errorString && errorString->getCStringNoCopy()) {
3072 			errorCString = errorString->getCStringNoCopy();
3073 		} else if (parsedXML) {
3074 			errorCString = "not a dictionary";
3075 		}
3076 		OSKextLog(/* kext */ NULL,
3077 		    kOSKextLogErrorLevel |
3078 		    kOSKextLogArchiveFlag,
3079 		    "Error unserializing mkext plist: %s.", errorCString);
3080 		goto finish;
3081 	}
3082 
3083 	mkextInfoDictArray = OSDynamicCast(OSArray,
3084 	    mkextPlist->getObject(kMKEXTInfoDictionariesKey));
3085 	if (!mkextInfoDictArray) {
3086 		OSKextLog(/* kext */ NULL,
3087 		    kOSKextLogErrorLevel |
3088 		    kOSKextLogArchiveFlag,
3089 		    "Mkext archive contains no kext info dictionaries.");
3090 		goto finish;
3091 	}
3092 
3093 	count = mkextInfoDictArray->getCount();
3094 	for (i = 0; i < count; i++) {
3095 		OSDictionary * infoDict;
3096 
3097 
3098 		infoDict = OSDynamicCast(OSDictionary,
3099 		    mkextInfoDictArray->getObject(i));
3100 
3101 		/* Create the kext for the entry, then release it, because the
3102 		 * kext system keeps them around until explicitly removed.
3103 		 * Any creation/registration failures are already logged for us.
3104 		 */
3105 		if (infoDict) {
3106 			OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData);
3107 
3108 			/* Fail dynamic loading of a kext when booted from MH_FILESET */
3109 			if (kc_format == KCFormatFileset &&
3110 			    newKext &&
3111 			    !(newKext->isPrelinked()) &&
3112 			    newKext->declaresExecutable()) {
3113 				result = kOSReturnError;
3114 				printf("Kext LOG: Dynamic loading of kext denied for kext %s\n",
3115 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3116 
3117 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
3118 				    "Dynamic loading of kext denied for kext %s\n",
3119 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3120 				goto finish;
3121 			}
3122 		}
3123 	}
3124 
3125 	/* If the caller needs the plist, hand them back our copy
3126 	 */
3127 	if (mkextPlistOut) {
3128 		*mkextPlistOut = mkextPlist;
3129 		parsedXML.detach();
3130 	}
3131 
3132 	/* Even if we didn't keep any kexts from the mkext, we may have a load
3133 	 * request to process, so we are successful (no errors occurred).
3134 	 */
3135 	result = kOSReturnSuccess;
3136 
3137 finish:
3138 	return result;
3139 }
3140 
3141 /* static */
3142 OSReturn
3143 OSKext::readMkext2Archive(
3144 	OSData        * mkextData,
3145 	OSSharedPtr<OSDictionary> &mkextPlistOut,
3146 	uint32_t      * checksumPtr)
3147 {
3148 	OSDictionary * mkextPlist = NULL;
3149 	OSReturn ret;
3150 
3151 	if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData,
3152 	    &mkextPlist,
3153 	    checksumPtr))) {
3154 		mkextPlistOut.reset(mkextPlist, OSNoRetain);
3155 	}
3156 	return ret;
3157 }
3158 
3159 /*********************************************************************
3160 *********************************************************************/
3161 /* static */
3162 OSSharedPtr<OSKext>
3163 OSKext::withMkext2Info(
3164 	OSDictionary * anInfoDict,
3165 	OSData       * mkextData)
3166 {
3167 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
3168 
3169 	if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
3170 		return NULL;
3171 	}
3172 
3173 	return newKext;
3174 }
3175 
3176 /*********************************************************************
3177 *********************************************************************/
3178 bool
3179 OSKext::initWithMkext2Info(
3180 	OSDictionary * anInfoDict,
3181 	OSData       * mkextData)
3182 {
3183 	bool                   result              = false;
3184 	OSString             * kextPath            = NULL;        // do not release
3185 	OSNumber             * executableOffsetNum = NULL;        // do not release
3186 	OSSharedPtr<OSData>               executable;
3187 
3188 	if (anInfoDict == NULL || !super::init()) {
3189 		goto finish;
3190 	}
3191 
3192 	/* Get the path. Don't look for an arch-specific path property.
3193 	 */
3194 	kextPath = OSDynamicCast(OSString,
3195 	    anInfoDict->getObject(kMKEXTBundlePathKey));
3196 
3197 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
3198 		goto finish;
3199 	}
3200 
3201 	/* If we have a path to the executable, save it.
3202 	 */
3203 	executableRelPath.reset(OSDynamicCast(OSString,
3204 	    anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain);
3205 
3206 	/* Don't need the paths to be in the info dictionary any more.
3207 	 */
3208 	anInfoDict->removeObject(kMKEXTBundlePathKey);
3209 	anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
3210 
3211 	executableOffsetNum = OSDynamicCast(OSNumber,
3212 	    infoDict->getObject(kMKEXTExecutableKey));
3213 	if (executableOffsetNum) {
3214 		executable = createMkext2FileEntry(mkextData,
3215 		    executableOffsetNum, "executable");
3216 		infoDict->removeObject(kMKEXTExecutableKey);
3217 		if (!executable) {
3218 			goto finish;
3219 		}
3220 		if (!setExecutable(executable.get(), mkextData, true)) {
3221 			goto finish;
3222 		}
3223 	}
3224 
3225 	result = registerIdentifier();
3226 
3227 finish:
3228 	return result;
3229 }
3230 
3231 /*********************************************************************
3232 *********************************************************************/
3233 OSSharedPtr<OSData>
3234 OSKext::createMkext2FileEntry(
3235 	OSData     * mkextData,
3236 	OSNumber   * offsetNum,
3237 	const char * name)
3238 {
3239 	OSSharedPtr<OSData> result;
3240 	MkextEntryRef   entryRef;
3241 	uint8_t       * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
3242 	uint32_t        entryOffset = offsetNum->unsigned32BitValue();
3243 
3244 	result = OSData::withCapacity(sizeof(entryRef));
3245 	if (!result) {
3246 		goto finish;
3247 	}
3248 
3249 	entryRef.mkext = (mkext_basic_header *)mkextBuffer;
3250 	entryRef.fileinfo = mkextBuffer + entryOffset;
3251 	if (!result->appendBytes(&entryRef, sizeof(entryRef))) {
3252 		result.reset();
3253 		goto finish;
3254 	}
3255 
3256 finish:
3257 	if (!result) {
3258 		OSKextLog(this,
3259 		    kOSKextLogErrorLevel |
3260 		    kOSKextLogArchiveFlag,
3261 		    "Can't create wrapper for mkext file entry '%s' of kext %s.",
3262 		    name, getIdentifierCString());
3263 	}
3264 	return result;
3265 }
3266 
3267 /*********************************************************************
3268 *********************************************************************/
3269 extern "C" {
3270 static void * z_alloc(void *, u_int items, u_int size);
3271 static void   z_free(void *, void *ptr);
3272 
3273 typedef struct z_mem {
3274 	uint32_t alloc_size;
3275 	uint8_t  data[0];
3276 } z_mem;
3277 
3278 /*
3279  * Space allocation and freeing routines for use by zlib routines.
3280  */
3281 void *
3282 z_alloc(void * notused __unused, u_int num_items, u_int size)
3283 {
3284 	void     * result = NULL;
3285 	z_mem    * zmem = NULL;
3286 
3287 	uint64_t   total = ((uint64_t)num_items) * ((uint64_t)size);
3288 	//Check for overflow due to multiplication
3289 	if (total > UINT32_MAX) {
3290 		panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
3291 		    notused, num_items, size, num_items, size);
3292 	}
3293 
3294 	uint64_t   allocSize64 =  total + ((uint64_t)sizeof(zmem));
3295 	//Check for overflow due to addition
3296 	if (allocSize64 > UINT32_MAX) {
3297 		panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
3298 		    notused, num_items, size, (uint32_t)total, sizeof(zmem));
3299 	}
3300 	uint32_t allocSize = (uint32_t)allocSize64;
3301 
3302 	zmem = (z_mem *)kheap_alloc_tag(KHEAP_DATA_BUFFERS, allocSize,
3303 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
3304 	if (!zmem) {
3305 		goto finish;
3306 	}
3307 	zmem->alloc_size = allocSize;
3308 	result = (void *)&(zmem->data);
3309 finish:
3310 	return result;
3311 }
3312 
3313 void
3314 z_free(void * notused __unused, void * ptr)
3315 {
3316 	uint32_t * skipper = (uint32_t *)ptr - 1;
3317 	z_mem    * zmem = (z_mem *)skipper;
3318 	kheap_free(KHEAP_DATA_BUFFERS, zmem, zmem->alloc_size);
3319 	return;
3320 }
3321 };
3322 
3323 OSSharedPtr<OSData>
3324 OSKext::extractMkext2FileData(
3325 	UInt8      * data,
3326 	const char * name,
3327 	uint32_t     compressedSize,
3328 	uint32_t     fullSize)
3329 {
3330 	OSSharedPtr<OSData>      result;
3331 	OSSharedPtr<OSData>      uncompressedData;        // release on error
3332 
3333 	uint8_t     * uncompressedDataBuffer = NULL;        // do not free
3334 	unsigned long uncompressedSize;
3335 	z_stream      zstream;
3336 	bool          zstream_inited = false;
3337 	int           zlib_result;
3338 
3339 	/* If the file isn't compressed, we want to make a copy
3340 	 * so that we don't have the tie to the larger mkext file buffer any more.
3341 	 */
3342 	if (!compressedSize) {
3343 		uncompressedData = OSData::withBytes(data, fullSize);
3344 		// xxx - no check for failure?
3345 		result = uncompressedData;
3346 		goto finish;
3347 	}
3348 
3349 	if (KERN_SUCCESS != kmem_alloc(kernel_map,
3350 	    (vm_offset_t*)&uncompressedDataBuffer, fullSize, VM_KERN_MEMORY_OSKEXT)) {
3351 		/* How's this for cheesy? The kernel is only asked to extract
3352 		 * kext plists so we tailor the log messages.
3353 		 */
3354 		if (isKernel()) {
3355 			OSKextLog(this,
3356 			    kOSKextLogErrorLevel |
3357 			    kOSKextLogArchiveFlag,
3358 			    "Allocation failure extracting %s from mkext.", name);
3359 		} else {
3360 			OSKextLog(this,
3361 			    kOSKextLogErrorLevel |
3362 			    kOSKextLogArchiveFlag,
3363 			    "Allocation failure extracting %s from mkext for kext %s.",
3364 			    name, getIdentifierCString());
3365 		}
3366 
3367 		goto finish;
3368 	}
3369 	uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3370 	if (!uncompressedData) {
3371 		if (isKernel()) {
3372 			OSKextLog(this,
3373 			    kOSKextLogErrorLevel |
3374 			    kOSKextLogArchiveFlag,
3375 			    "Allocation failure extracting %s from mkext.", name);
3376 		} else {
3377 			OSKextLog(this,
3378 			    kOSKextLogErrorLevel |
3379 			    kOSKextLogArchiveFlag,
3380 			    "Allocation failure extracting %s from mkext for kext %s.",
3381 			    name, getIdentifierCString());
3382 		}
3383 		goto finish;
3384 	}
3385 	uncompressedData->setDeallocFunction(&osdata_kmem_free);
3386 
3387 	if (isKernel()) {
3388 		OSKextLog(this,
3389 		    kOSKextLogDetailLevel |
3390 		    kOSKextLogArchiveFlag,
3391 		    "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3392 		    name, compressedSize, fullSize);
3393 	} else {
3394 		OSKextLog(this,
3395 		    kOSKextLogDetailLevel |
3396 		    kOSKextLogArchiveFlag,
3397 		    "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3398 		    getIdentifierCString(), name, compressedSize, fullSize);
3399 	}
3400 
3401 	bzero(&zstream, sizeof(zstream));
3402 	zstream.next_in   = (UInt8 *)data;
3403 	zstream.avail_in  = compressedSize;
3404 
3405 	zstream.next_out  = uncompressedDataBuffer;
3406 	zstream.avail_out = fullSize;
3407 
3408 	zstream.zalloc    = z_alloc;
3409 	zstream.zfree     = z_free;
3410 
3411 	zlib_result = inflateInit(&zstream);
3412 	if (Z_OK != zlib_result) {
3413 		if (isKernel()) {
3414 			OSKextLog(this,
3415 			    kOSKextLogErrorLevel |
3416 			    kOSKextLogArchiveFlag,
3417 			    "Mkext error; zlib inflateInit failed (%d) for %s.",
3418 			    zlib_result, name);
3419 		} else {
3420 			OSKextLog(this,
3421 			    kOSKextLogErrorLevel |
3422 			    kOSKextLogArchiveFlag,
3423 			    "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3424 			    getIdentifierCString(), zlib_result, name);
3425 		}
3426 		goto finish;
3427 	} else {
3428 		zstream_inited = true;
3429 	}
3430 
3431 	zlib_result = inflate(&zstream, Z_FINISH);
3432 
3433 	if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3434 		uncompressedSize = zstream.total_out;
3435 	} else {
3436 		if (isKernel()) {
3437 			OSKextLog(this,
3438 			    kOSKextLogErrorLevel |
3439 			    kOSKextLogArchiveFlag,
3440 			    "Mkext error; zlib inflate failed (%d) for %s.",
3441 			    zlib_result, name);
3442 		} else {
3443 			OSKextLog(this,
3444 			    kOSKextLogErrorLevel |
3445 			    kOSKextLogArchiveFlag,
3446 			    "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3447 			    getIdentifierCString(), zlib_result, name);
3448 		}
3449 		if (zstream.msg) {
3450 			OSKextLog(this,
3451 			    kOSKextLogErrorLevel |
3452 			    kOSKextLogArchiveFlag,
3453 			    "zlib error: %s.", zstream.msg);
3454 		}
3455 		goto finish;
3456 	}
3457 
3458 	if (uncompressedSize != fullSize) {
3459 		if (isKernel()) {
3460 			OSKextLog(this,
3461 			    kOSKextLogErrorLevel |
3462 			    kOSKextLogArchiveFlag,
3463 			    "Mkext error; zlib inflate discrepancy for %s, "
3464 			    "uncompressed size != original size.", name);
3465 		} else {
3466 			OSKextLog(this,
3467 			    kOSKextLogErrorLevel |
3468 			    kOSKextLogArchiveFlag,
3469 			    "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3470 			    "uncompressed size != original size.",
3471 			    getIdentifierCString(), name);
3472 		}
3473 		goto finish;
3474 	}
3475 
3476 	result = os::move(uncompressedData);
3477 
3478 finish:
3479 	/* Don't bother checking return, nothing we can do on fail.
3480 	 */
3481 	if (zstream_inited) {
3482 		inflateEnd(&zstream);
3483 	}
3484 
3485 	return result;
3486 }
3487 
3488 /*********************************************************************
3489 *********************************************************************/
3490 /* static */
3491 OSReturn
3492 OSKext::loadFromMkext(
3493 	OSKextLogSpec   clientLogFilter,
3494 	char          * mkextBuffer,
3495 	uint32_t        mkextBufferLength,
3496 	char         ** logInfoOut,
3497 	uint32_t      * logInfoLengthOut)
3498 {
3499 	OSReturn         result                      = kOSReturnError;
3500 	OSReturn         tempResult                  = kOSReturnError;
3501 
3502 	OSSharedPtr<OSData>        mkextData;
3503 	OSSharedPtr<OSDictionary>  mkextPlist;
3504 
3505 	OSSharedPtr<OSArray>       logInfoArray;
3506 	OSSharedPtr<OSSerialize>   serializer;
3507 
3508 	OSString       * predicate                   = NULL;        // do not release
3509 	OSDictionary   * requestArgs                 = NULL;        // do not release
3510 
3511 	OSString       * kextIdentifier              = NULL;        // do not release
3512 	OSNumber       * startKextExcludeNum         = NULL;        // do not release
3513 	OSNumber       * startMatchingExcludeNum     = NULL;        // do not release
3514 	OSBoolean      * delayAutounloadBool         = NULL;        // do not release
3515 	OSArray        * personalityNames            = NULL;        // do not release
3516 
3517 	/* Default values for these two options: regular autounload behavior,
3518 	 * load all kexts, send no personalities.
3519 	 */
3520 	Boolean            delayAutounload           = false;
3521 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
3522 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3523 
3524 	IORecursiveLockLock(sKextLock);
3525 
3526 	if (logInfoOut) {
3527 		*logInfoOut = NULL;
3528 		*logInfoLengthOut = 0;
3529 	}
3530 
3531 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3532 
3533 	OSKextLog(/* kext */ NULL,
3534 	    kOSKextLogDebugLevel |
3535 	    kOSKextLogIPCFlag,
3536 	    "Received kext load request from user space.");
3537 
3538 	/* Regardless of processing, the fact that we have gotten here means some
3539 	 * user-space program is up and talking to us, so we'll switch our kext
3540 	 * registration to reflect that.
3541 	 */
3542 	if (!sUserLoadsActive) {
3543 		OSKextLog(/* kext */ NULL,
3544 		    kOSKextLogProgressLevel |
3545 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3546 		    "Switching to late startup (user-space) kext loading policy.");
3547 
3548 		sUserLoadsActive = true;
3549 	}
3550 
3551 	if (!sLoadEnabled) {
3552 		OSKextLog(/* kext */ NULL,
3553 		    kOSKextLogErrorLevel |
3554 		    kOSKextLogLoadFlag,
3555 		    "Kext loading is disabled.");
3556 		result = kOSKextReturnDisabled;
3557 		goto finish;
3558 	}
3559 
3560 	/* Note that we do not set a dealloc function on this OSData
3561 	 * object! No references to it can remain after the loadFromMkext()
3562 	 * call since we are in a MIG function, and will vm_deallocate()
3563 	 * the buffer.
3564 	 */
3565 	mkextData = OSData::withBytesNoCopy(mkextBuffer,
3566 	    mkextBufferLength);
3567 	if (!mkextData) {
3568 		OSKextLog(/* kext */ NULL,
3569 		    kOSKextLogErrorLevel |
3570 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3571 		    "Failed to create wrapper for kext load request.");
3572 		result = kOSKextReturnNoMemory;
3573 		goto finish;
3574 	}
3575 
3576 	result = readMkext2Archive(mkextData.get(), mkextPlist, NULL);
3577 	if (result != kOSReturnSuccess) {
3578 		OSKextLog(/* kext */ NULL,
3579 		    kOSKextLogErrorLevel |
3580 		    kOSKextLogLoadFlag,
3581 		    "Failed to read kext load request.");
3582 		goto finish;
3583 	}
3584 
3585 	predicate = _OSKextGetRequestPredicate(mkextPlist.get());
3586 	if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3587 		OSKextLog(/* kext */ NULL,
3588 		    kOSKextLogErrorLevel |
3589 		    kOSKextLogLoadFlag,
3590 		    "Received kext load request with no predicate; skipping.");
3591 		result = kOSKextReturnInvalidArgument;
3592 		goto finish;
3593 	}
3594 
3595 	requestArgs = OSDynamicCast(OSDictionary,
3596 	    mkextPlist->getObject(kKextRequestArgumentsKey));
3597 	if (!requestArgs || !requestArgs->getCount()) {
3598 		OSKextLog(/* kext */ NULL,
3599 		    kOSKextLogErrorLevel |
3600 		    kOSKextLogLoadFlag,
3601 		    "Received kext load request with no arguments.");
3602 		result = kOSKextReturnInvalidArgument;
3603 		goto finish;
3604 	}
3605 
3606 	kextIdentifier = OSDynamicCast(OSString,
3607 	    requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3608 
3609 	if (!kextIdentifier) {
3610 		OSKextLog(/* kext */ NULL,
3611 		    kOSKextLogErrorLevel |
3612 		    kOSKextLogLoadFlag,
3613 		    "Received kext load request with no kext identifier.");
3614 		result = kOSKextReturnInvalidArgument;
3615 		goto finish;
3616 	}
3617 
3618 	startKextExcludeNum = OSDynamicCast(OSNumber,
3619 	    requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3620 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
3621 	    requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3622 	delayAutounloadBool = OSDynamicCast(OSBoolean,
3623 	    requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3624 	personalityNames = OSDynamicCast(OSArray,
3625 	    requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3626 
3627 	if (delayAutounloadBool) {
3628 		delayAutounload = delayAutounloadBool->getValue();
3629 	}
3630 	if (startKextExcludeNum) {
3631 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3632 	}
3633 	if (startMatchingExcludeNum) {
3634 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3635 	}
3636 
3637 	OSKextLog(/* kext */ NULL,
3638 	    kOSKextLogProgressLevel |
3639 	    kOSKextLogIPCFlag,
3640 	    "Received request from user space to load kext %s.",
3641 	    kextIdentifier->getCStringNoCopy());
3642 
3643 	/* Load the kext, with no deferral, since this is a load from outside
3644 	 * the kernel.
3645 	 * xxx - Would like a better way to handle the default values for the
3646 	 * xxx - start/match opt args.
3647 	 */
3648 	result = OSKext::loadKextWithIdentifier(
3649 		kextIdentifier,
3650 		/* kextRef */ NULL,
3651 		/* allowDefer */ false,
3652 		delayAutounload,
3653 		startKextExcludeLevel,
3654 		startMatchingExcludeLevel,
3655 		personalityNames);
3656 	if (result != kOSReturnSuccess) {
3657 		goto finish;
3658 	}
3659 	/* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue
3660 	 * for matching via a separate IOKit calldown.
3661 	 */
3662 
3663 finish:
3664 
3665 	/* Gather up the collected log messages for user space. Any
3666 	 * error messages past this call will not make it up as log messages
3667 	 * but will be in the system log.
3668 	 */
3669 	logInfoArray = OSKext::clearUserSpaceLogFilter();
3670 
3671 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
3672 		tempResult = OSKext::serializeLogInfo(logInfoArray.get(),
3673 		    logInfoOut, logInfoLengthOut);
3674 		if (tempResult != kOSReturnSuccess) {
3675 			result = tempResult;
3676 		}
3677 	}
3678 
3679 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3680 
3681 	IORecursiveLockUnlock(sKextLock);
3682 
3683 	/* Note: mkextDataObject will have been retained by every kext w/an
3684 	 * executable in it. That should all have been flushed out at the
3685 	 * and of the load operation, but you never know....
3686 	 */
3687 	if (mkextData && mkextData->getRetainCount() > 1) {
3688 		OSKextLog(/* kext */ NULL,
3689 		    kOSKextLogErrorLevel |
3690 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3691 		    "Kext load request buffer from user space still retained by a kext; "
3692 		    "probable memory leak.");
3693 	}
3694 
3695 	return result;
3696 }
3697 
3698 #endif // CONFIG_KXLD
3699 
3700 /*********************************************************************
3701 *********************************************************************/
3702 /* static */
3703 OSReturn
3704 OSKext::serializeLogInfo(
3705 	OSArray   * logInfoArray,
3706 	char     ** logInfoOut,
3707 	uint32_t  * logInfoLengthOut)
3708 {
3709 	OSReturn        result      = kOSReturnError;
3710 	char          * buffer      = NULL;
3711 	kern_return_t   kmem_result = KERN_FAILURE;
3712 	OSSharedPtr<OSSerialize>  serializer;
3713 	char         * logInfo            = NULL;        // returned by reference
3714 	uint32_t       logInfoLength      = 0;
3715 
3716 	if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
3717 		OSKextLog(/* kext */ NULL,
3718 		    kOSKextLogErrorLevel |
3719 		    kOSKextLogIPCFlag,
3720 		    "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3721 		/* Bad programmer. */
3722 		result = kOSKextReturnInvalidArgument;
3723 		goto finish;
3724 	}
3725 
3726 	serializer = OSSerialize::withCapacity(0);
3727 	if (!serializer) {
3728 		OSKextLog(/* kext */ NULL,
3729 		    kOSKextLogErrorLevel |
3730 		    kOSKextLogIPCFlag,
3731 		    "Failed to create serializer on log info for request from user space.");
3732 		/* Incidental error; we're going to (try to) allow the request
3733 		 * itself to succeed. */
3734 	}
3735 
3736 	if (!logInfoArray->serialize(serializer.get())) {
3737 		OSKextLog(/* kext */ NULL,
3738 		    kOSKextLogErrorLevel |
3739 		    kOSKextLogIPCFlag,
3740 		    "Failed to serialize log info for request from user space.");
3741 		/* Incidental error; we're going to (try to) allow the request
3742 		 * itself to succeed. */
3743 	} else {
3744 		logInfo = serializer->text();
3745 		logInfoLength = serializer->getLength();
3746 
3747 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT);
3748 		if (kmem_result != KERN_SUCCESS) {
3749 			OSKextLog(/* kext */ NULL,
3750 			    kOSKextLogErrorLevel |
3751 			    kOSKextLogIPCFlag,
3752 			    "Failed to copy log info for request from user space.");
3753 			/* Incidental error; we're going to (try to) allow the request
3754 			 * to succeed. */
3755 		} else {
3756 			/* 11981737 - clear uninitialized data in last page */
3757 			bzero((void *)(buffer + logInfoLength),
3758 			    (round_page(logInfoLength) - logInfoLength));
3759 			memcpy(buffer, logInfo, logInfoLength);
3760 			*logInfoOut = buffer;
3761 			*logInfoLengthOut = logInfoLength;
3762 		}
3763 	}
3764 
3765 	result = kOSReturnSuccess;
3766 finish:
3767 	return result;
3768 }
3769 
3770 #if PRAGMA_MARK
3771 #pragma mark Instance Management Methods
3772 #endif
3773 /*********************************************************************
3774 *********************************************************************/
3775 OSSharedPtr<OSKext>
3776 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
3777 {
3778 	OSSharedPtr<OSKext> foundKext;
3779 
3780 	IORecursiveLockLock(sKextLock);
3781 	foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain);
3782 	IORecursiveLockUnlock(sKextLock);
3783 
3784 	return foundKext;
3785 }
3786 
3787 /*********************************************************************
3788 *********************************************************************/
3789 OSSharedPtr<OSKext>
3790 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
3791 {
3792 	return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
3793 }
3794 
3795 /*********************************************************************
3796 *********************************************************************/
3797 OSSharedPtr<OSKext>
3798 OSKext::lookupKextWithLoadTag(uint32_t aTag)
3799 {
3800 	OSSharedPtr<OSKext> foundKext;             // returned
3801 	uint32_t i, j;
3802 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
3803 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3804 
3805 	IORecursiveLockLock(sKextLock);
3806 
3807 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3808 		for (i = 0; i < count[j]; i++) {
3809 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3810 			if (thisKext->getLoadTag() == aTag) {
3811 				foundKext.reset(thisKext, OSRetain);
3812 				goto finish;
3813 			}
3814 		}
3815 	}
3816 
3817 finish:
3818 	IORecursiveLockUnlock(sKextLock);
3819 
3820 	return foundKext;
3821 }
3822 
3823 /*********************************************************************
3824 *********************************************************************/
3825 OSSharedPtr<OSKext>
3826 OSKext::lookupKextWithAddress(vm_address_t address)
3827 {
3828 	OSSharedPtr<OSKext> foundKext;             // returned
3829 	uint32_t count, i;
3830 	kmod_info_t *kmod_info;
3831 #if defined(__arm64__)
3832 	uint64_t   textExecBase;
3833 	size_t     textExecSize;
3834 #endif /* defined(__arm64__) */
3835 
3836 #if  __has_feature(ptrauth_calls)
3837 	address = (vm_address_t)VM_KERNEL_STRIP_PTR(address);
3838 #endif /*  __has_feature(ptrauth_calls) */
3839 
3840 	IORecursiveLockLock(sKextLock);
3841 
3842 	count = sLoadedKexts->getCount();
3843 	for (i = 0; i < count; i++) {
3844 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3845 		if (thisKext == sKernelKext) {
3846 			continue;
3847 		}
3848 		if (thisKext->kmod_info && thisKext->kmod_info->address) {
3849 			kmod_info = thisKext->kmod_info;
3850 			vm_address_t kext_start = kmod_info->address;
3851 			vm_address_t kext_end = kext_start + kmod_info->size;
3852 			if ((kext_start <= address) && (address < kext_end)) {
3853 				foundKext.reset(thisKext, OSRetain);
3854 				goto finish;
3855 			}
3856 #if defined(__arm64__)
3857 			textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize);
3858 			if ((textExecBase <= address) && (address < textExecBase + textExecSize)) {
3859 				foundKext.reset(thisKext, OSRetain);
3860 				goto finish;
3861 			}
3862 #endif /* defined (__arm64__) */
3863 		}
3864 	}
3865 	if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) {
3866 		foundKext.reset(sKernelKext, OSRetain);
3867 		goto finish;
3868 	}
3869 	/*
3870 	 * DriverKit userspace executables do not have a kernel linkedExecutable,
3871 	 * so we "fake" their address range with the LoadTag.
3872 	 *
3873 	 * This is supposed to be used for logging reasons only. When logd
3874 	 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
3875 	 * remove it here before checking it against the LoadTag.
3876 	 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
3877 	 */
3878 
3879 	address = address & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
3880 	count = sLoadedDriverKitKexts->getCount();
3881 	for (i = 0; i < count; i++) {
3882 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
3883 		if (thisKext->getLoadTag() == address) {
3884 			foundKext.reset(thisKext, OSRetain);
3885 		}
3886 	}
3887 
3888 finish:
3889 	IORecursiveLockUnlock(sKextLock);
3890 
3891 	return foundKext;
3892 }
3893 
3894 OSSharedPtr<OSData>
3895 OSKext::copyKextUUIDForAddress(OSNumber *address)
3896 {
3897 	OSSharedPtr<OSData>   uuid;
3898 	OSSharedPtr<OSKext>   kext;
3899 
3900 	if (!address) {
3901 		return NULL;
3902 	}
3903 
3904 	uintptr_t addr = ml_static_slide((uintptr_t)address->unsigned64BitValue());
3905 	if (addr == 0) {
3906 		return NULL;
3907 	}
3908 #if  __has_feature(ptrauth_calls)
3909 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
3910 #endif /*  __has_feature(ptrauth_calls) */
3911 
3912 #if CONFIG_MACF
3913 	/* Is the calling process allowed to query kext info? */
3914 	if (current_task() != kernel_task) {
3915 		int macCheckResult = 0;
3916 		kauth_cred_t cred = NULL;
3917 
3918 		cred = kauth_cred_get_with_ref();
3919 		macCheckResult = mac_kext_check_query(cred);
3920 		kauth_cred_unref(&cred);
3921 
3922 		if (macCheckResult != 0) {
3923 			OSKextLog(/* kext */ NULL,
3924 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
3925 			    "Failed to query kext UUID (MAC policy error 0x%x).",
3926 			    macCheckResult);
3927 			return NULL;
3928 		}
3929 	}
3930 #endif
3931 	kext = lookupKextWithAddress(addr);
3932 	if (kext) {
3933 		uuid = kext->copyTextUUID();
3934 	}
3935 	return uuid;
3936 }
3937 
3938 /*********************************************************************
3939 *********************************************************************/
3940 OSSharedPtr<OSKext>
3941 OSKext::lookupKextWithUUID(uuid_t wanted)
3942 {
3943 	OSSharedPtr<OSKext> foundKext;             // returned
3944 	uint32_t j, i;
3945 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
3946 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3947 
3948 
3949 	IORecursiveLockLock(sKextLock);
3950 
3951 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3952 		for (i = 0; i < count[j]; i++) {
3953 			OSKext   * thisKext     = NULL;
3954 
3955 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3956 			if (!thisKext) {
3957 				continue;
3958 			}
3959 
3960 			OSSharedPtr<OSData> uuid_data = thisKext->copyUUID();
3961 			if (!uuid_data) {
3962 				continue;
3963 			}
3964 
3965 			uuid_t uuid;
3966 			memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
3967 
3968 			if (0 == uuid_compare(wanted, uuid)) {
3969 				foundKext.reset(thisKext, OSRetain);
3970 				goto finish;
3971 			}
3972 		}
3973 	}
3974 finish:
3975 	IORecursiveLockUnlock(sKextLock);
3976 
3977 	return foundKext;
3978 }
3979 
3980 
3981 
3982 
3983 /*********************************************************************
3984 *********************************************************************/
3985 /* static */
3986 bool
3987 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
3988 {
3989 	bool result = false;
3990 	OSKext * foundKext = NULL;             // returned
3991 
3992 	IORecursiveLockLock(sKextLock);
3993 
3994 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3995 	if (foundKext && foundKext->isLoaded()) {
3996 		result = true;
3997 	}
3998 
3999 	IORecursiveLockUnlock(sKextLock);
4000 
4001 	return result;
4002 }
4003 
4004 /*********************************************************************
4005 * xxx - should spawn a separate thread so a kext can safely have
4006 * xxx - itself unloaded.
4007 *********************************************************************/
4008 /* static */
4009 OSReturn
4010 OSKext::removeKext(
4011 	OSKext * aKext,
4012 #if CONFIG_EMBEDDED
4013 	__unused
4014 #endif
4015 	bool     terminateServicesAndRemovePersonalitiesFlag)
4016 {
4017 #if CONFIG_EMBEDDED
4018 	OSKextLog(aKext,
4019 	    kOSKextLogErrorLevel |
4020 	    kOSKextLogKextBookkeepingFlag,
4021 	    "removeKext() called for %s, not supported on embedded",
4022 	    aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
4023 
4024 	return kOSReturnSuccess;
4025 #else /* CONFIG_EMBEDDED */
4026 
4027 	OSReturn result    = kOSKextReturnInUse;
4028 	OSKext * checkKext = NULL;         // do not release
4029 #if CONFIG_MACF
4030 	int macCheckResult = 0;
4031 	kauth_cred_t cred  = NULL;
4032 #endif
4033 
4034 	IORecursiveLockLock(sKextLock);
4035 
4036 	/* If the kext has no identifier, it failed to init
4037 	 * so isn't in sKextsByID and it isn't loaded.
4038 	 */
4039 	if (!aKext->getIdentifier()) {
4040 		result = kOSReturnSuccess;
4041 		goto finish;
4042 	}
4043 
4044 	checkKext = OSDynamicCast(OSKext,
4045 	    sKextsByID->getObject(aKext->getIdentifier()));
4046 	if (checkKext != aKext) {
4047 		result = kOSKextReturnNotFound;
4048 		goto finish;
4049 	}
4050 
4051 	if (aKext->isLoaded()) {
4052 #if CONFIG_MACF
4053 		if (current_task() != kernel_task) {
4054 			cred = kauth_cred_get_with_ref();
4055 			macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
4056 			kauth_cred_unref(&cred);
4057 		}
4058 
4059 		if (macCheckResult != 0) {
4060 			result = kOSReturnError;
4061 			OSKextLog(aKext,
4062 			    kOSKextLogErrorLevel |
4063 			    kOSKextLogKextBookkeepingFlag,
4064 			    "Failed to remove kext %s (MAC policy error 0x%x).",
4065 			    aKext->getIdentifierCString(), macCheckResult);
4066 			goto finish;
4067 		}
4068 #endif
4069 
4070 		/* make sure there are no resource requests in flight - 17187548 */
4071 		if (aKext->countRequestCallbacks()) {
4072 			goto finish;
4073 		}
4074 
4075 		/* If we are terminating, send the request to the IOCatalogue
4076 		 * (which will actually call us right back but that's ok we have
4077 		 * a recursive lock don't you know) but do not ask the IOCatalogue
4078 		 * to call back with an unload, we'll do that right here.
4079 		 */
4080 		if (terminateServicesAndRemovePersonalitiesFlag) {
4081 			result = gIOCatalogue->terminateDriversForModule(
4082 				aKext->getIdentifierCString(), /* unload */ false);
4083 			if (result != kOSReturnSuccess) {
4084 				OSKextLog(aKext,
4085 				    kOSKextLogErrorLevel |
4086 				    kOSKextLogKextBookkeepingFlag,
4087 				    "Can't remove kext %s; services failed to terminate - 0x%x.",
4088 				    aKext->getIdentifierCString(), result);
4089 				goto finish;
4090 			}
4091 		}
4092 
4093 		result = aKext->unload();
4094 		if (result != kOSReturnSuccess) {
4095 			goto finish;
4096 		}
4097 	}
4098 
4099 	/* Remove personalities as requested. This is a bit redundant for a loaded
4100 	 * kext as IOCatalogue::terminateDriversForModule() removes driver
4101 	 * personalities, but it doesn't restart matching, which we always want
4102 	 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
4103 	 * that happens.
4104 	 */
4105 	if (terminateServicesAndRemovePersonalitiesFlag) {
4106 		aKext->removePersonalitiesFromCatalog();
4107 	}
4108 
4109 	if (aKext->isInFileset()) {
4110 		OSKextLog(aKext,
4111 		    kOSKextLogProgressLevel |
4112 		    kOSKextLogKextBookkeepingFlag,
4113 		    "Fileset kext %s unloaded.",
4114 		    aKext->getIdentifierCString());
4115 	} else {
4116 		OSKextLog(aKext,
4117 		    kOSKextLogProgressLevel |
4118 		    kOSKextLogKextBookkeepingFlag,
4119 		    "Removing kext %s.",
4120 		    aKext->getIdentifierCString());
4121 
4122 		sKextsByID->removeObject(aKext->getIdentifier());
4123 	}
4124 	result = kOSReturnSuccess;
4125 
4126 finish:
4127 	IORecursiveLockUnlock(sKextLock);
4128 	return result;
4129 #endif /* CONFIG_EMBEDDED */
4130 }
4131 
4132 /*********************************************************************
4133 *********************************************************************/
4134 /* static */
4135 OSReturn
4136 OSKext::removeKextWithIdentifier(
4137 	const char * kextIdentifier,
4138 	bool         terminateServicesAndRemovePersonalitiesFlag)
4139 {
4140 	OSReturn result = kOSReturnError;
4141 
4142 	IORecursiveLockLock(sKextLock);
4143 
4144 	OSKext * aKext = OSDynamicCast(OSKext,
4145 	    sKextsByID->getObject(kextIdentifier));
4146 	if (!aKext) {
4147 		result = kOSKextReturnNotFound;
4148 		OSKextLog(/* kext */ NULL,
4149 		    kOSKextLogErrorLevel |
4150 		    kOSKextLogKextBookkeepingFlag,
4151 		    "Can't remove kext %s - not found.",
4152 		    kextIdentifier);
4153 		goto finish;
4154 	}
4155 
4156 	result = OSKext::removeKext(aKext,
4157 	    terminateServicesAndRemovePersonalitiesFlag);
4158 
4159 finish:
4160 	IORecursiveLockUnlock(sKextLock);
4161 
4162 	return result;
4163 }
4164 
4165 /*********************************************************************
4166 *********************************************************************/
4167 /* static */
4168 OSReturn
4169 OSKext::removeKextWithLoadTag(
4170 	OSKextLoadTag loadTag,
4171 	bool          terminateServicesAndRemovePersonalitiesFlag)
4172 {
4173 	OSReturn result    = kOSReturnError;
4174 	OSKext * foundKext = NULL;
4175 	uint32_t i, j;
4176 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4177 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4178 
4179 
4180 	IORecursiveLockLock(sKextLock);
4181 
4182 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4183 		for (i = 0; i < count[j]; i++) {
4184 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4185 			if (thisKext->loadTag == loadTag) {
4186 				foundKext = thisKext;
4187 				break;
4188 			}
4189 		}
4190 	}
4191 
4192 	if (!foundKext) {
4193 		result = kOSKextReturnNotFound;
4194 		OSKextLog(/* kext */ NULL,
4195 		    kOSKextLogErrorLevel |
4196 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4197 		    "Can't remove kext with load tag %d - not found.",
4198 		    loadTag);
4199 		goto finish;
4200 	}
4201 
4202 	result = OSKext::removeKext(foundKext,
4203 	    terminateServicesAndRemovePersonalitiesFlag);
4204 
4205 finish:
4206 	IORecursiveLockUnlock(sKextLock);
4207 
4208 	return result;
4209 }
4210 
4211 /*********************************************************************
4212 *********************************************************************/
4213 OSSharedPtr<OSDictionary>
4214 OSKext::copyKexts(void)
4215 {
4216 	OSSharedPtr<OSDictionary> result;
4217 
4218 	IORecursiveLockLock(sKextLock);
4219 	result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection());
4220 	IORecursiveLockUnlock(sKextLock);
4221 
4222 	return result;
4223 }
4224 
4225 /*********************************************************************
4226 *********************************************************************/
4227 #define BOOTER_KEXT_PREFIX   "Driver-"
4228 
4229 typedef struct _DeviceTreeBuffer {
4230 	uint32_t paddr;
4231 	uint32_t length;
4232 } _DeviceTreeBuffer;
4233 
4234 /*********************************************************************
4235 * Create a dictionary of excluded kexts from the given booter data.
4236 *********************************************************************/
4237 /* static */
4238 void
4239 OSKext::createExcludeListFromBooterData(
4240 	OSDictionary *          theDictionary,
4241 	OSCollectionIterator *  theIterator )
4242 {
4243 	OSString                  * deviceTreeName      = NULL;        // do not release
4244 	const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;        // do not release
4245 	char                      * booterDataPtr       = NULL;        // do not release
4246 	_BooterKextFileInfo       * kextFileInfo        = NULL;        // do not release
4247 	char                      * infoDictAddr        = NULL;        // do not release
4248 	OSSharedPtr<OSObject>       parsedXML;
4249 	OSDictionary              * theInfoDict         = NULL;        // do not release
4250 
4251 	theIterator->reset();
4252 
4253 	/* look for AppleKextExcludeList.kext */
4254 	while ((deviceTreeName =
4255 	    OSDynamicCast(OSString, theIterator->getNextObject()))) {
4256 		const char *    devTreeNameCString;
4257 		OSData *        deviceTreeEntry;        // do not release
4258 		OSString *      myBundleID;        // do not release
4259 
4260 		deviceTreeEntry =
4261 		    OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
4262 		if (!deviceTreeEntry) {
4263 			continue;
4264 		}
4265 
4266 		/* Make sure it is a kext */
4267 		devTreeNameCString = deviceTreeName->getCStringNoCopy();
4268 		if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
4269 		    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
4270 			OSKextLog(NULL,
4271 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4272 			    "\"%s\" not a kext",
4273 			    devTreeNameCString);
4274 			continue;
4275 		}
4276 
4277 		deviceTreeBuffer = (const _DeviceTreeBuffer *)
4278 		    deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
4279 		if (!deviceTreeBuffer) {
4280 			continue;
4281 		}
4282 
4283 		booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
4284 		if (!booterDataPtr) {
4285 			continue;
4286 		}
4287 
4288 		kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
4289 		if (!kextFileInfo->infoDictPhysAddr ||
4290 		    !kextFileInfo->infoDictLength) {
4291 			continue;
4292 		}
4293 
4294 		infoDictAddr = (char *)
4295 		    ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
4296 		if (!infoDictAddr) {
4297 			continue;
4298 		}
4299 
4300 		parsedXML = OSUnserializeXML(infoDictAddr);
4301 		if (!parsedXML) {
4302 			continue;
4303 		}
4304 
4305 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
4306 		if (!theInfoDict) {
4307 			continue;
4308 		}
4309 
4310 		myBundleID =
4311 		    OSDynamicCast(OSString,
4312 		    theInfoDict->getObject(kCFBundleIdentifierKey));
4313 		if (myBundleID &&
4314 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4315 			boolean_t updated = updateExcludeList(theInfoDict);
4316 			if (!updated) {
4317 				/* 25322874 */
4318 				panic("Missing OSKextExcludeList dictionary\n");
4319 			}
4320 			break;
4321 		}
4322 	}         // while ( (deviceTreeName = ...) )
4323 
4324 	return;
4325 }
4326 
4327 /*********************************************************************
4328 * Create a dictionary of excluded kexts from the given prelink
4329 * info (kernelcache).
4330 *********************************************************************/
4331 /* static */
4332 void
4333 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
4334 {
4335 	OSDictionary *  myInfoDict = NULL;        // do not release
4336 	OSString *      myBundleID;        // do not release
4337 	u_int           i;
4338 
4339 	/* Find the Apple Kext Exclude List. */
4340 	for (i = 0; i < theInfoArray->getCount(); i++) {
4341 		myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
4342 		if (!myInfoDict) {
4343 			continue;
4344 		}
4345 		myBundleID =
4346 		    OSDynamicCast(OSString,
4347 		    myInfoDict->getObject(kCFBundleIdentifierKey));
4348 		if (myBundleID &&
4349 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4350 			boolean_t updated = updateExcludeList(myInfoDict);
4351 			if (!updated) {
4352 				/* 25322874 */
4353 				panic("Missing OSKextExcludeList dictionary\n");
4354 			}
4355 			break;
4356 		}
4357 	}         // for (i = 0; i < theInfoArray->getCount()...
4358 
4359 	return;
4360 }
4361 
4362 /* static */
4363 boolean_t
4364 OSKext::updateExcludeList(OSDictionary *infoDict)
4365 {
4366 	OSDictionary *myTempDict = NULL;         // do not free
4367 	OSString     *myTempString = NULL;        // do not free
4368 	OSKextVersion newVersion = 0;
4369 	boolean_t updated = false;
4370 
4371 	if (!infoDict) {
4372 		return false;
4373 	}
4374 
4375 	myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
4376 	if (!myTempDict) {
4377 		return false;
4378 	}
4379 
4380 	myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
4381 	if (!myTempString) {
4382 		return false;
4383 	}
4384 
4385 	newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
4386 	if (newVersion == 0) {
4387 		return false;
4388 	}
4389 
4390 	IORecursiveLockLock(sKextLock);
4391 
4392 	if (newVersion > sExcludeListVersion) {
4393 		sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
4394 		sExcludeListVersion = newVersion;
4395 		updated = true;
4396 	}
4397 
4398 	IORecursiveLockUnlock(sKextLock);
4399 	return updated;
4400 }
4401 
4402 #if PRAGMA_MARK
4403 #pragma mark Accessors
4404 #endif
4405 /*********************************************************************
4406 *********************************************************************/
4407 const OSSymbol *
4408 OSKext::getIdentifier(void)
4409 {
4410 	return bundleID.get();
4411 }
4412 
4413 /*********************************************************************
4414 * A kext must have a bundle identifier to even survive initialization;
4415 * this is guaranteed to exist past then.
4416 *********************************************************************/
4417 const char *
4418 OSKext::getIdentifierCString(void)
4419 {
4420 	return bundleID->getCStringNoCopy();
4421 }
4422 
4423 /*********************************************************************
4424 *********************************************************************/
4425 OSKextVersion
4426 OSKext::getVersion(void)
4427 {
4428 	return version;
4429 }
4430 
4431 /*********************************************************************
4432 *********************************************************************/
4433 OSKextVersion
4434 OSKext::getCompatibleVersion(void)
4435 {
4436 	return compatibleVersion;
4437 }
4438 
4439 /*********************************************************************
4440 *********************************************************************/
4441 bool
4442 OSKext::isLibrary(void)
4443 {
4444 	return getCompatibleVersion() > 0;
4445 }
4446 
4447 /*********************************************************************
4448 *********************************************************************/
4449 bool
4450 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
4451 {
4452 	if ((compatibleVersion > -1 && version > -1) &&
4453 	    (compatibleVersion <= version && aVersion <= version)) {
4454 		return true;
4455 	}
4456 	return false;
4457 }
4458 
4459 /*********************************************************************
4460 *********************************************************************/
4461 bool
4462 OSKext::declaresExecutable(void)
4463 {
4464 	if (isDriverKit()) {
4465 		return false;
4466 	}
4467 	return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
4468 }
4469 
4470 /*********************************************************************
4471 *********************************************************************/
4472 OSData *
4473 OSKext::getExecutable(void)
4474 {
4475 	OSData * result              = NULL;
4476 	OSSharedPtr<OSData> extractedExecutable;
4477 
4478 	if (flags.builtin) {
4479 		return sKernelKext->linkedExecutable.get();
4480 	}
4481 
4482 	result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
4483 	if (result) {
4484 		return result;
4485 	}
4486 
4487 #if CONFIG_KXLD
4488 	OSData * mkextExecutableRef  = NULL;        // do not release
4489 	mkextExecutableRef = OSDynamicCast(OSData,
4490 	    getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
4491 
4492 	if (mkextExecutableRef) {
4493 		MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
4494 		    mkextExecutableRef->getBytesNoCopy();
4495 		uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
4496 		if (mkextVersion == MKEXT_VERS_2) {
4497 			mkext2_file_entry * fileinfo =
4498 			    (mkext2_file_entry *)mkextEntryRef->fileinfo;
4499 			uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
4500 			uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
4501 			extractedExecutable = extractMkext2FileData(
4502 				MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
4503 				compressedSize, fullSize);
4504 		} else {
4505 			OSKextLog(this, kOSKextLogErrorLevel |
4506 			    kOSKextLogArchiveFlag,
4507 			    "Kext %s - unknown mkext version 0x%x for executable.",
4508 			    getIdentifierCString(), mkextVersion);
4509 		}
4510 
4511 		/* Regardless of success, remove the mkext executable,
4512 		 * and drop one reference on the mkext.  (setExecutable() does not
4513 		 * replace, it removes, or panics if asked to replace.)
4514 		 */
4515 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4516 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4517 
4518 		if (extractedExecutable && extractedExecutable->getLength()) {
4519 			if (!setExecutable(extractedExecutable.get())) {
4520 				goto finish;
4521 			}
4522 			result = extractedExecutable.get();
4523 		} else {
4524 			goto finish;
4525 		}
4526 	}
4527 
4528 finish:
4529 #endif // CONFIG_KXLD
4530 	return result;
4531 }
4532 
4533 /*********************************************************************
4534 *********************************************************************/
4535 bool
4536 OSKext::isInterface(void)
4537 {
4538 	return flags.interface;
4539 }
4540 
4541 /*********************************************************************
4542 *********************************************************************/
4543 bool
4544 OSKext::isKernel(void)
4545 {
4546 	return this == sKernelKext;
4547 }
4548 
4549 /*********************************************************************
4550 *********************************************************************/
4551 bool
4552 OSKext::isKernelComponent(void)
4553 {
4554 	return flags.kernelComponent ? true : false;
4555 }
4556 
4557 /*********************************************************************
4558 *********************************************************************/
4559 bool
4560 OSKext::isExecutable(void)
4561 {
4562 	return !isKernel() && !isInterface() && declaresExecutable();
4563 }
4564 
4565 /*********************************************************************
4566 * We might want to check this recursively for all dependencies,
4567 * since a subtree of dependencies could get loaded before we hit
4568 * a dependency that isn't safe-boot-loadable.
4569 *
4570 * xxx - Might want to return false if OSBundleEnableKextLogging or
4571 * OSBundleDebugLevel
4572 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4573 * the point except it's usually development drivers, which might
4574 * cause panics on startup, that have those properties). Heh; could
4575 * use a "kx" boot-arg!
4576 *********************************************************************/
4577 bool
4578 OSKext::isLoadableInSafeBoot(void)
4579 {
4580 	bool       result   = false;
4581 	OSString * required = NULL;         // do not release
4582 
4583 	if (isKernel()) {
4584 		result = true;
4585 		goto finish;
4586 	}
4587 
4588 	if (isDriverKit()) {
4589 		result = true;
4590 		goto finish;
4591 	}
4592 
4593 	required = OSDynamicCast(OSString,
4594 	    getPropertyForHostArch(kOSBundleRequiredKey));
4595 	if (!required) {
4596 		goto finish;
4597 	}
4598 	if (required->isEqualTo(kOSBundleRequiredRoot) ||
4599 	    required->isEqualTo(kOSBundleRequiredLocalRoot) ||
4600 	    required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
4601 	    required->isEqualTo(kOSBundleRequiredSafeBoot) ||
4602 	    required->isEqualTo(kOSBundleRequiredConsole)) {
4603 		result = true;
4604 	}
4605 
4606 finish:
4607 	return result;
4608 }
4609 
4610 /*********************************************************************
4611 *********************************************************************/
4612 bool
4613 OSKext::isPrelinked(void)
4614 {
4615 	return flags.prelinked ? true : false;
4616 }
4617 
4618 /*********************************************************************
4619 *********************************************************************/
4620 bool
4621 OSKext::isLoaded(void)
4622 {
4623 	return flags.loaded ? true : false;
4624 }
4625 
4626 /*********************************************************************
4627 *********************************************************************/
4628 bool
4629 OSKext::isStarted(void)
4630 {
4631 	return flags.started ? true : false;
4632 }
4633 
4634 /*********************************************************************
4635 *********************************************************************/
4636 bool
4637 OSKext::isCPPInitialized(void)
4638 {
4639 	return flags.CPPInitialized;
4640 }
4641 
4642 /*********************************************************************
4643 *********************************************************************/
4644 void
4645 OSKext::setCPPInitialized(bool initialized)
4646 {
4647 	flags.CPPInitialized = initialized;
4648 }
4649 
4650 /*********************************************************************
4651 *********************************************************************/
4652 uint32_t
4653 OSKext::getLoadTag(void)
4654 {
4655 	return loadTag;
4656 }
4657 
4658 /*********************************************************************
4659 *********************************************************************/
4660 void
4661 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
4662 {
4663 	if (linkedExecutable) {
4664 		*loadSize = linkedExecutable->getLength();
4665 
4666 		/* If we have a kmod_info struct, calculated the wired size
4667 		 * from that. Otherwise it's the full load size.
4668 		 */
4669 		if (kmod_info) {
4670 			*wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size;
4671 		} else {
4672 			*wiredSize = *loadSize;
4673 		}
4674 	} else {
4675 		*wiredSize = 0;
4676 		*loadSize = 0;
4677 	}
4678 }
4679 
4680 /*********************************************************************
4681 *********************************************************************/
4682 OSSharedPtr<OSData>
4683 OSKext::copyUUID(void)
4684 {
4685 	OSSharedPtr<OSData>          result;
4686 	OSData                     * theExecutable = NULL;        // do not release
4687 	const kernel_mach_header_t * header;
4688 
4689 	/* An interface kext doesn't have a linked executable with an LC_UUID,
4690 	 * we create one when it's linked.
4691 	 */
4692 	if (interfaceUUID) {
4693 		result = interfaceUUID;
4694 		goto finish;
4695 	}
4696 
4697 	if (flags.builtin || isInterface()) {
4698 		return sKernelKext->copyUUID();
4699 	}
4700 
4701 	if (isDriverKit() && infoDict) {
4702 		return driverKitUUID;
4703 	}
4704 
4705 	/* For real kexts, try to get the UUID from the linked executable,
4706 	 * or if is hasn't been linked yet, the unrelocated executable.
4707 	 */
4708 	theExecutable = linkedExecutable.get();
4709 	if (!theExecutable) {
4710 		theExecutable = getExecutable();
4711 	}
4712 
4713 	if (!theExecutable) {
4714 		goto finish;
4715 	}
4716 
4717 	header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
4718 	result = copyMachoUUID(header);
4719 
4720 finish:
4721 	return result;
4722 }
4723 
4724 /*********************************************************************
4725 *********************************************************************/
4726 OSSharedPtr<OSData>
4727 OSKext::copyTextUUID(void)
4728 {
4729 	if (flags.builtin) {
4730 		return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
4731 	}
4732 	return copyUUID();
4733 }
4734 
4735 /*********************************************************************
4736 *********************************************************************/
4737 OSSharedPtr<OSData>
4738 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
4739 {
4740 	OSSharedPtr<OSData>                     result;
4741 	const struct load_command  * load_cmd      = NULL;
4742 	const struct uuid_command  * uuid_cmd      = NULL;
4743 	uint32_t                     i;
4744 
4745 	load_cmd = (const struct load_command *)&header[1];
4746 
4747 	if (header->magic != MH_MAGIC_KERNEL) {
4748 		OSKextLog(NULL,
4749 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4750 		    "%s: bad header %p",
4751 		    __func__,
4752 		    header);
4753 		goto finish;
4754 	}
4755 
4756 	for (i = 0; i < header->ncmds; i++) {
4757 		if (load_cmd->cmd == LC_UUID) {
4758 			uuid_cmd = (struct uuid_command *)load_cmd;
4759 			result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid));
4760 			goto finish;
4761 		}
4762 		load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
4763 	}
4764 
4765 finish:
4766 	return result;
4767 }
4768 
4769 void
4770 OSKext::setDriverKitUUID(OSData *uuid)
4771 {
4772 	if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
4773 		OSSafeReleaseNULL(uuid);
4774 	}
4775 }
4776 
4777 /*********************************************************************
4778 *********************************************************************/
4779 #if defined (__arm__)
4780 #include <arm/arch.h>
4781 #endif
4782 
4783 #if   defined (__x86_64__)
4784 #define ARCHNAME "x86_64"
4785 #elif defined (__arm64__)
4786 #define ARCHNAME "arm64"
4787 #elif defined (__arm__)
4788 
4789 #if defined (__ARM_ARCH_7S__)
4790 #define ARCHNAME "armv7s"
4791 #elif defined (__ARM_ARCH_7F__)
4792 #define ARCHNAME "armv7f"
4793 #elif defined (__ARM_ARCH_7K__)
4794 #define ARCHNAME "armv7k"
4795 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
4796 #define ARCHNAME "armv7"
4797 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
4798 #define ARCHNAME "armv6"
4799 #endif
4800 
4801 #elif defined (__arm64__)
4802 #define ARCHNAME "arm64"
4803 #else
4804 #error architecture not supported
4805 #endif
4806 
4807 #define ARCH_SEPARATOR_CHAR  '_'
4808 
4809 static char *
4810 makeHostArchKey(const char * key, size_t * keySizeOut)
4811 {
4812 	char     * result = NULL;
4813 	size_t     keyLength = strlen(key);
4814 	size_t     keySize;
4815 
4816 	/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4817 	 */
4818 	keySize = 1 + 1 + keyLength + strlen(ARCHNAME);
4819 	result = (char *)kheap_alloc_tag(KHEAP_TEMP, keySize,
4820 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
4821 
4822 	if (!result) {
4823 		goto finish;
4824 	}
4825 	strlcpy(result, key, keySize);
4826 	result[keyLength++] = ARCH_SEPARATOR_CHAR;
4827 	result[keyLength] = '\0';
4828 	strlcat(result, ARCHNAME, keySize);
4829 	*keySizeOut = keySize;
4830 
4831 finish:
4832 	return result;
4833 }
4834 
4835 /*********************************************************************
4836 *********************************************************************/
4837 OSObject *
4838 OSKext::getPropertyForHostArch(const char * key)
4839 {
4840 	OSObject * result           = NULL;// do not release
4841 	size_t     hostArchKeySize  = 0;
4842 	char     * hostArchKey      = NULL;// must kfree
4843 
4844 	if (!key || !infoDict) {
4845 		goto finish;
4846 	}
4847 
4848 	/* Some properties are not allowed to be arch-variant:
4849 	 * - Any CFBundle... property.
4850 	 * - OSBundleIsInterface.
4851 	 * - OSKernelResource.
4852 	 */
4853 	if (STRING_HAS_PREFIX(key, "OS") ||
4854 	    STRING_HAS_PREFIX(key, "IO")) {
4855 		hostArchKey = makeHostArchKey(key, &hostArchKeySize);
4856 		if (!hostArchKey) {
4857 			OSKextLog(/* kext (this isn't about a kext) */ NULL,
4858 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4859 			    "Allocation failure.");
4860 			goto finish;
4861 		}
4862 		result = infoDict->getObject(hostArchKey);
4863 	}
4864 
4865 	if (!result) {
4866 		result = infoDict->getObject(key);
4867 	}
4868 
4869 finish:
4870 	if (hostArchKey) {
4871 		kheap_free(KHEAP_TEMP, hostArchKey, hostArchKeySize);
4872 	}
4873 	return result;
4874 }
4875 
4876 #if PRAGMA_MARK
4877 #pragma mark Load/Start/Stop/Unload
4878 #endif
4879 
4880 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4881 
4882 /*********************************************************************
4883 * sExcludeListByID is a dictionary with keys / values of:
4884 *  key = bundleID string of kext we will not allow to load
4885 *  value = version string(s) of the kext that is to be denied loading.
4886 *      The version strings can be comma delimited.  For example if kext
4887 *      com.foocompany.fookext has two versions that we want to deny
4888 *      loading then the version strings might look like:
4889 *      1.0.0, 1.0.1
4890 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4891 *      not load the kext.
4892 *
4893 *      Value may also be in the form of "LE 2.0.0" (version numbers
4894 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4895 *      number less than 2.0.0 will not load)
4896 *
4897 *      NOTE - we cannot use the characters "<=" or "<" because we have code
4898 *      that serializes plists and treats '<' as a special character.
4899 *********************************************************************/
4900 bool
4901 OSKext::isInExcludeList(void)
4902 {
4903 	OSString *      versionString           = NULL;        // do not release
4904 	char *          versionCString          = NULL;        // do not free
4905 	size_t          i;
4906 	boolean_t       wantLessThan = false;
4907 	boolean_t       wantLessThanEqualTo = false;
4908 	boolean_t       isInExcludeList = true;
4909 	char            myBuffer[32];
4910 
4911 	IORecursiveLockLock(sKextLock);
4912 
4913 	if (!sExcludeListByID) {
4914 		isInExcludeList = false;
4915 	} else {
4916 		/* look up by bundleID in our exclude list and if found get version
4917 		 * string (or strings) that we will not allow to load
4918 		 */
4919 		versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get()));
4920 		if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
4921 			isInExcludeList = false;
4922 		}
4923 	}
4924 
4925 	IORecursiveLockUnlock(sKextLock);
4926 
4927 	if (!isInExcludeList) {
4928 		return false;
4929 	}
4930 
4931 	/* parse version strings */
4932 	versionCString = (char *) versionString->getCStringNoCopy();
4933 
4934 	/* look for "LT" or "LE" form of version string, must be in first two
4935 	 * positions.
4936 	 */
4937 	if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
4938 		wantLessThan = true;
4939 		versionCString += 2;
4940 	} else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
4941 		wantLessThanEqualTo = true;
4942 		versionCString += 2;
4943 	}
4944 
4945 	for (i = 0; *versionCString != 0x00; versionCString++) {
4946 		/* skip whitespace */
4947 		if (isWhiteSpace(*versionCString)) {
4948 			continue;
4949 		}
4950 
4951 		/* peek ahead for version string separator or null terminator */
4952 		if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
4953 			/* OK, we have a version string */
4954 			myBuffer[i++] = *versionCString;
4955 			myBuffer[i] = 0x00;
4956 
4957 			OSKextVersion excludeVers;
4958 			excludeVers = OSKextParseVersionString(myBuffer);
4959 
4960 			if (wantLessThanEqualTo) {
4961 				if (version <= excludeVers) {
4962 					return true;
4963 				}
4964 			} else if (wantLessThan) {
4965 				if (version < excludeVers) {
4966 					return true;
4967 				}
4968 			} else if (version == excludeVers) {
4969 				return true;
4970 			}
4971 
4972 			/* reset for the next (if any) version string */
4973 			i = 0;
4974 			wantLessThan = false;
4975 			wantLessThanEqualTo = false;
4976 		} else {
4977 			/* save valid version character */
4978 			myBuffer[i++] = *versionCString;
4979 
4980 			/* make sure bogus version string doesn't overrun local buffer */
4981 			if (i >= sizeof(myBuffer)) {
4982 				break;
4983 			}
4984 		}
4985 	}
4986 
4987 	return false;
4988 }
4989 
4990 /*********************************************************************
4991 * sNonLoadableKextsByID is a dictionary with keys / values of:
4992 *  key = bundleID string of kext we will not allow to load
4993 *  value = boolean (true == loadable, false == not loadable)
4994 *
4995 *  Only kexts which are in the AuxKC will be marked as "not loadble,"
4996 *  i.e., the value for the kext's bundleID will be false. All kexts in
4997 *  the primary and system KCs will always be marked as "loadable."
4998 *
4999 *  This list ultimately comes from kexts which have been uninstalled
5000 *  in user space by deleting the kext from disk, but which have not
5001 *  yet been removed from the AuxKC. Because the user could choose to
5002 *  re-install the exact same version of the kext, we need to keep
5003 *  a dictionary of boolean values so that user space only needs to
5004 *  keep a simple list of "uninstalled" or "missing" bundles. When
5005 *  a bundle is re-installed, the iokit daemon can use the
5006 *  AucKCBundleAvailable  predicate to set the individual kext's
5007 *  availability to true.
5008 *********************************************************************/
5009 bool
5010 OSKext::isLoadable(void)
5011 {
5012 	bool isLoadable = true;
5013 
5014 	if (kc_type != KCKindAuxiliary) {
5015 		/* this filtering only applies to kexts in the auxkc */
5016 		return true;
5017 	}
5018 
5019 	IORecursiveLockLock(sKextLock);
5020 
5021 	if (sNonLoadableKextsByID) {
5022 		/* look up by bundleID in our exclude list and if found get version
5023 		 * string (or strings) that we will not allow to load
5024 		 */
5025 		OSBoolean *loadableVal;
5026 		loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get()));
5027 		if (loadableVal && !loadableVal->getValue()) {
5028 			isLoadable = false;
5029 		}
5030 	}
5031 	IORecursiveLockUnlock(sKextLock);
5032 
5033 	return isLoadable;
5034 }
5035 
5036 /*********************************************************************
5037 *********************************************************************/
5038 /* static */
5039 OSReturn
5040 OSKext::loadKextWithIdentifier(
5041 	const char       * kextIdentifierCString,
5042 	Boolean            allowDeferFlag,
5043 	Boolean            delayAutounloadFlag,
5044 	OSKextExcludeLevel startOpt,
5045 	OSKextExcludeLevel startMatchingOpt,
5046 	OSArray          * personalityNames)
5047 {
5048 	OSReturn   result         = kOSReturnError;
5049 	OSSharedPtr<OSString> kextIdentifier;
5050 
5051 	kextIdentifier = OSString::withCString(kextIdentifierCString);
5052 	if (!kextIdentifier) {
5053 		result = kOSKextReturnNoMemory;
5054 		goto finish;
5055 	}
5056 	result = OSKext::loadKextWithIdentifier(kextIdentifier.get(),
5057 	    NULL /* kextRef */,
5058 	    allowDeferFlag, delayAutounloadFlag,
5059 	    startOpt, startMatchingOpt, personalityNames);
5060 
5061 finish:
5062 	return result;
5063 }
5064 
5065 OSReturn
5066 OSKext::loadKextWithIdentifier(
5067 	OSString          * kextIdentifier,
5068 	OSSharedPtr<OSObject>         &kextRef,
5069 	Boolean             allowDeferFlag,
5070 	Boolean             delayAutounloadFlag,
5071 	OSKextExcludeLevel  startOpt,
5072 	OSKextExcludeLevel  startMatchingOpt,
5073 	OSArray           * personalityNames)
5074 {
5075 	OSObject * kextRefRaw = NULL;
5076 	OSReturn result;
5077 
5078 	result = loadKextWithIdentifier(kextIdentifier,
5079 	    &kextRefRaw,
5080 	    allowDeferFlag,
5081 	    delayAutounloadFlag,
5082 	    startOpt,
5083 	    startMatchingOpt,
5084 	    personalityNames);
5085 	if ((kOSReturnSuccess == result) && kextRefRaw) {
5086 		kextRef.reset(kextRefRaw, OSNoRetain);
5087 	}
5088 	return result;
5089 }
5090 
5091 /*********************************************************************
5092 *********************************************************************/
5093 OSReturn
5094 OSKext::loadKextWithIdentifier(
5095 	OSString          * kextIdentifier,
5096 	OSObject         ** kextRef,
5097 	Boolean             allowDeferFlag,
5098 	Boolean             delayAutounloadFlag,
5099 	OSKextExcludeLevel  startOpt,
5100 	OSKextExcludeLevel  startMatchingOpt,
5101 	OSArray           * personalityNames)
5102 {
5103 	OSReturn          result               = kOSReturnError;
5104 	OSReturn          pingResult           = kOSReturnError;
5105 	OSKext          * theKext              = NULL;        // do not release
5106 	OSSharedPtr<OSDictionary>   loadRequest;
5107 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5108 
5109 	if (kextRef) {
5110 		*kextRef = NULL;
5111 	}
5112 
5113 	IORecursiveLockLock(sKextLock);
5114 
5115 	if (!kextIdentifier) {
5116 		result = kOSKextReturnInvalidArgument;
5117 		goto finish;
5118 	}
5119 
5120 	OSKext::recordIdentifierRequest(kextIdentifier);
5121 
5122 	theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
5123 	if (!theKext) {
5124 		if (!allowDeferFlag) {
5125 			OSKextLog(/* kext */ NULL,
5126 			    kOSKextLogErrorLevel |
5127 			    kOSKextLogLoadFlag,
5128 			    "Can't load kext %s - not found.",
5129 			    kextIdentifier->getCStringNoCopy());
5130 			goto finish;
5131 		}
5132 
5133 		if (!sKernelRequestsEnabled) {
5134 			OSKextLog(theKext,
5135 			    kOSKextLogErrorLevel |
5136 			    kOSKextLogLoadFlag,
5137 			    "Can't load kext %s - requests to user space are disabled.",
5138 			    kextIdentifier->getCStringNoCopy());
5139 			result = kOSKextReturnDisabled;
5140 			goto finish;
5141 		}
5142 
5143 		/* Create a new request unless one is already sitting
5144 		 * in sKernelRequests for this bundle identifier
5145 		 */
5146 		kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5147 		if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5148 			result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
5149 			    loadRequest);
5150 			if (result != kOSReturnSuccess) {
5151 				goto finish;
5152 			}
5153 			if (!_OSKextSetRequestArgument(loadRequest.get(),
5154 			    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
5155 				result = kOSKextReturnNoMemory;
5156 				goto finish;
5157 			}
5158 			if (!sKernelRequests->setObject(loadRequest.get())) {
5159 				result = kOSKextReturnNoMemory;
5160 				goto finish;
5161 			}
5162 
5163 			if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
5164 				result = kOSKextReturnNoMemory;
5165 				goto finish;
5166 			}
5167 
5168 			OSKextLog(theKext,
5169 			    kOSKextLogDebugLevel |
5170 			    kOSKextLogLoadFlag,
5171 			    "Kext %s not found; queued load request to user space.",
5172 			    kextIdentifier->getCStringNoCopy());
5173 		}
5174 
5175 		pingResult = OSKext::pingIOKitDaemon();
5176 		if (pingResult == kOSKextReturnDisabled) {
5177 			OSKextLog(/* kext */ NULL,
5178 			    ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
5179 			    kOSKextLogLoadFlag,
5180 			    "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.",
5181 			    kextIdentifier->getCStringNoCopy());
5182 		}
5183 
5184 		result = kOSKextReturnDeferred;
5185 		goto finish;
5186 	}
5187 
5188 	result = theKext->load(startOpt, startMatchingOpt, personalityNames);
5189 
5190 	if (result != kOSReturnSuccess) {
5191 		OSKextLog(theKext,
5192 		    kOSKextLogErrorLevel |
5193 		    kOSKextLogLoadFlag,
5194 		    "Failed to load kext %s (error 0x%x).",
5195 		    kextIdentifier->getCStringNoCopy(), (int)result);
5196 
5197 		if (theKext->kc_type == KCKindUnknown) {
5198 			OSKext::removeKext(theKext,
5199 			    /* terminateService/removePersonalities */ true);
5200 		}
5201 		goto finish;
5202 	}
5203 
5204 	if (delayAutounloadFlag) {
5205 		OSKextLog(theKext,
5206 		    kOSKextLogProgressLevel |
5207 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5208 		    "Setting delayed autounload for %s.",
5209 		    kextIdentifier->getCStringNoCopy());
5210 		theKext->flags.delayAutounload = 1;
5211 	}
5212 
5213 finish:
5214 	if ((kOSReturnSuccess == result) && kextRef) {
5215 		*kextRef = theKext;
5216 		theKext->matchingRefCount++;
5217 		theKext->retain();
5218 	}
5219 
5220 	IORecursiveLockUnlock(sKextLock);
5221 
5222 	return result;
5223 }
5224 
5225 /*********************************************************************
5226 *********************************************************************/
5227 /* static */
5228 OSReturn
5229 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict)
5230 {
5231 	OSReturn  result = kOSReturnError;
5232 
5233 	OSBoolean *delayAutounloadBool     = NULL; // do not release
5234 	OSNumber  *startKextExcludeNum     = NULL; // do not release
5235 	OSNumber  *startMatchingExcludeNum = NULL; // do not release
5236 	OSArray   *personalityNames        = NULL; // do not release
5237 
5238 	/*
5239 	 * Default values for these options:
5240 	 *      regular autounload behavior
5241 	 *      start the kext
5242 	 *      send all personalities to the catalog
5243 	 */
5244 	Boolean            delayAutounload           = false;
5245 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
5246 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone;
5247 
5248 	IORecursiveLockLock(sKextLock);
5249 
5250 	OSKextLog(/* kext */ NULL,
5251 	    kOSKextLogDebugLevel |
5252 	    kOSKextLogIPCFlag,
5253 	    "Received kext KC load request from user space.");
5254 
5255 	/* Regardless of processing, the fact that we have gotten here means some
5256 	 * user-space program is up and talking to us, so we'll switch our kext
5257 	 * registration to reflect that.
5258 	 */
5259 	if (!sUserLoadsActive) {
5260 		OSKextLog(/* kext */ NULL,
5261 		    kOSKextLogProgressLevel |
5262 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5263 		    "Switching to late startup (user-space) kext loading policy.");
5264 		sUserLoadsActive = true;
5265 	}
5266 
5267 	delayAutounloadBool = OSDynamicCast(OSBoolean,
5268 	    _OSKextGetRequestArgument(requestDict,
5269 	    kKextRequestArgumentDelayAutounloadKey));
5270 	startKextExcludeNum = OSDynamicCast(OSNumber,
5271 	    _OSKextGetRequestArgument(requestDict,
5272 	    kKextRequestArgumentStartExcludeKey));
5273 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
5274 	    _OSKextGetRequestArgument(requestDict,
5275 	    kKextRequestArgumentStartMatchingExcludeKey));
5276 	personalityNames = OSDynamicCast(OSArray,
5277 	    _OSKextGetRequestArgument(requestDict,
5278 	    kKextRequestArgumentPersonalityNamesKey));
5279 
5280 	if (delayAutounloadBool) {
5281 		delayAutounload = delayAutounloadBool->getValue();
5282 	}
5283 	if (startKextExcludeNum) {
5284 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
5285 	}
5286 	if (startMatchingExcludeNum) {
5287 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
5288 	}
5289 
5290 	OSKextLog(/* kext */ NULL,
5291 	    kOSKextLogProgressLevel |
5292 	    kOSKextLogIPCFlag,
5293 	    "Received request from user space to load KC kext %s.",
5294 	    theKext->getIdentifierCString());
5295 
5296 	/* this could be in the Auxiliary KC, so record the load request */
5297 	OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier()));
5298 
5299 	/*
5300 	 * Load the kext
5301 	 */
5302 	result = theKext->load(startKextExcludeLevel,
5303 	    startMatchingExcludeLevel, personalityNames);
5304 
5305 	if (result != kOSReturnSuccess) {
5306 		OSKextLog(theKext,
5307 		    kOSKextLogErrorLevel |
5308 		    kOSKextLogLoadFlag,
5309 		    "Failed to load kext %s (error 0x%x).",
5310 		    theKext->getIdentifierCString(), (int)result);
5311 
5312 		OSKext::removeKext(theKext,
5313 		    /* terminateService/removePersonalities */ true);
5314 		goto finish;
5315 	} else {
5316 		OSKextLog(theKext,
5317 		    kOSKextLogProgressLevel |
5318 		    kOSKextLogLoadFlag,
5319 		    "Kext %s Loaded successfully from %s KC",
5320 		    theKext->getIdentifierCString(), theKext->getKCTypeString());
5321 	}
5322 
5323 	if (delayAutounload) {
5324 		OSKextLog(theKext,
5325 		    kOSKextLogProgressLevel |
5326 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5327 		    "Setting delayed autounload for %s.",
5328 		    theKext->getIdentifierCString());
5329 		theKext->flags.delayAutounload = 1;
5330 	}
5331 
5332 finish:
5333 	IORecursiveLockUnlock(sKextLock);
5334 
5335 	return result;
5336 }
5337 
5338 /*********************************************************************
5339 *********************************************************************/
5340 /* static */
5341 OSReturn
5342 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict)
5343 {
5344 	OSReturn  result = kOSReturnError;
5345 	OSDictionary *anInfoDict = NULL; // do not release
5346 
5347 	anInfoDict = OSDynamicCast(OSDictionary,
5348 	    _OSKextGetRequestArgument(requestDict,
5349 	    kKextRequestArgumentCodelessInfoKey));
5350 	if (anInfoDict == NULL) {
5351 		OSKextLog(/* kext */ NULL,
5352 		    kOSKextLogErrorLevel |
5353 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5354 		    "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.",
5355 		    kextIdentifier->getCStringNoCopy());
5356 		return kOSKextReturnInvalidArgument;
5357 	}
5358 
5359 	IORecursiveLockLock(sKextLock);
5360 
5361 	OSKextLog(/* kext */ NULL,
5362 	    kOSKextLogProgressLevel |
5363 	    kOSKextLogIPCFlag,
5364 	    "Received request from user space to load codeless kext %s.",
5365 	    kextIdentifier->getCStringNoCopy());
5366 
5367 	{
5368 		// instantiate a new kext, and don't hold a reference
5369 		// (the kext subsystem will hold one implicitly)
5370 		OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict);
5371 		if (!newKext) {
5372 			OSKextLog(/* kext */ NULL,
5373 			    kOSKextLogErrorLevel |
5374 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5375 			    "Could not instantiate codeless kext.");
5376 			result = kOSKextReturnNotLoadable;
5377 			goto finish;
5378 		}
5379 		if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) {
5380 			OSKextLog(/* kext */ NULL,
5381 			    kOSKextLogErrorLevel |
5382 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5383 			    "Codeless kext identifiers don't match '%s' != '%s'",
5384 			    kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString());
5385 
5386 			OSKext::removeKext(newKext.get(), false);
5387 			result = kOSKextReturnInvalidArgument;
5388 			goto finish;
5389 		}
5390 
5391 		/* Record the request for the codeless kext */
5392 		OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier()));
5393 
5394 		result = kOSReturnSuccess;
5395 		/* send the kext's personalities to the IOCatalog */
5396 		if (!newKext->flags.requireExplicitLoad) {
5397 			result = newKext->sendPersonalitiesToCatalog(true, NULL);
5398 		}
5399 	}
5400 
5401 finish:
5402 	IORecursiveLockUnlock(sKextLock);
5403 
5404 	return result;
5405 }
5406 
5407 /*********************************************************************
5408 *********************************************************************/
5409 /* static */
5410 void
5411 OSKext::dropMatchingReferences(
5412 	OSSet * kexts)
5413 {
5414 	IORecursiveLockLock(sKextLock);
5415 	kexts->iterateObjects(^bool (OSObject * obj) {
5416 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
5417 		if (!thisKext) {
5418 		        return false;
5419 		}
5420 		thisKext->matchingRefCount--;
5421 		return false;
5422 	});
5423 	IORecursiveLockUnlock(sKextLock);
5424 }
5425 
5426 /*********************************************************************
5427 *********************************************************************/
5428 /* static */
5429 void
5430 OSKext::recordIdentifierRequest(
5431 	OSString * kextIdentifier)
5432 {
5433 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5434 	bool             fail                 = false;
5435 
5436 	if (!sAllKextLoadIdentifiers || !kextIdentifier) {
5437 		goto finish;
5438 	}
5439 
5440 	kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5441 	if (!kextIdentifierSymbol) {
5442 		// xxx - this is really a basic alloc failure
5443 		fail = true;
5444 		goto finish;
5445 	}
5446 
5447 	IORecursiveLockLock(sKextLock);
5448 	if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5449 		if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
5450 			fail = true;
5451 		} else {
5452 			// xxx - need to find a way to associate this whole func w/the kext
5453 			OSKextLog(/* kext */ NULL,
5454 			    // xxx - check level
5455 			    kOSKextLogStepLevel |
5456 			    kOSKextLogArchiveFlag,
5457 			    "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
5458 			    kextIdentifier->getCStringNoCopy());
5459 		}
5460 	}
5461 	IORecursiveLockUnlock(sKextLock);
5462 
5463 finish:
5464 
5465 	if (fail) {
5466 		OSKextLog(/* kext */ NULL,
5467 		    kOSKextLogErrorLevel |
5468 		    kOSKextLogArchiveFlag,
5469 		    "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
5470 		    kextIdentifier->getCStringNoCopy());
5471 	}
5472 	return;
5473 }
5474 
5475 /*********************************************************************
5476 *********************************************************************/
5477 OSReturn
5478 OSKext::load(
5479 	OSKextExcludeLevel   startOpt,
5480 	OSKextExcludeLevel   startMatchingOpt,
5481 	OSArray            * personalityNames)
5482 {
5483 	OSReturn             result                       = kOSReturnError;
5484 	OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
5485 	OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
5486 	unsigned int         i, count;
5487 	Boolean              alreadyLoaded                = false;
5488 	OSKext             * lastLoadedKext               = NULL;        // do not release
5489 
5490 	if (isInExcludeList()) {
5491 		OSKextLog(this,
5492 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
5493 		    kOSKextLogLoadFlag,
5494 		    "Kext %s is in exclude list, not loadable",
5495 		    getIdentifierCString());
5496 
5497 		result = kOSKextReturnNotLoadable;
5498 		goto finish;
5499 	}
5500 	if (!isLoadable()) {
5501 		OSKextLog(this,
5502 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
5503 		    kOSKextLogLoadFlag,
5504 		    "Kext %s is not loadable",
5505 		    getIdentifierCString());
5506 
5507 		result = kOSKextReturnNotLoadable;
5508 		goto finish;
5509 	}
5510 
5511 	if (isLoaded()) {
5512 		alreadyLoaded = true;
5513 		result = kOSReturnSuccess;
5514 
5515 		OSKextLog(this,
5516 		    kOSKextLogDebugLevel |
5517 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5518 		    "Kext %s is already loaded.",
5519 		    getIdentifierCString());
5520 		goto loaded;
5521 	}
5522 
5523 #if CONFIG_MACF && XNU_TARGET_OS_OSX
5524 #if CONFIG_KXLD
5525 	if (current_task() != kernel_task) {
5526 #else
5527 	/*
5528 	 * On non-kxld systems, only check the mac-hook for kexts in the
5529 	 * Pageable and Aux KCs. This means on Apple silicon devices that
5530 	 * the mac hook will only be useful to block 3rd party kexts.
5531 	 *
5532 	 * Note that this should _not_ be called on kexts loaded from the
5533 	 * kernel bootstrap thread as the kernel proc's cred struct is not
5534 	 * yet initialized! This won't happen on macOS because all the kexts
5535 	 * in the BootKC are self-contained and their kc_type = KCKindPrimary.
5536 	 */
5537 	if (kc_type != KCKindPrimary && kc_type != KCKindUnknown) {
5538 #endif /* CONFIG_KXLD */
5539 		int                 macCheckResult      = 0;
5540 		kauth_cred_t        cred                = NULL;
5541 
5542 		cred = kauth_cred_get_with_ref();
5543 		macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
5544 		kauth_cred_unref(&cred);
5545 
5546 		if (macCheckResult != 0) {
5547 			result = kOSReturnError;
5548 			OSKextLog(this,
5549 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5550 			    "Failed to load kext %s (MAC policy error 0x%x).",
5551 			    getIdentifierCString(), macCheckResult);
5552 			goto finish;
5553 		}
5554 	}
5555 #endif
5556 
5557 	if (!sLoadEnabled) {
5558 		OSKextLog(this,
5559 		    kOSKextLogErrorLevel |
5560 		    kOSKextLogLoadFlag,
5561 		    "Kext loading is disabled (attempt to load kext %s).",
5562 		    getIdentifierCString());
5563 		result = kOSKextReturnDisabled;
5564 		goto finish;
5565 	}
5566 
5567 	/* If we've pushed the next available load tag to the invalid value,
5568 	 * we can't load any more kexts.
5569 	 */
5570 	if (sNextLoadTag == kOSKextInvalidLoadTag) {
5571 		OSKextLog(this,
5572 		    kOSKextLogErrorLevel |
5573 		    kOSKextLogLoadFlag,
5574 		    "Can't load kext %s - no more load tags to assign.",
5575 		    getIdentifierCString());
5576 		result = kOSKextReturnNoResources;
5577 		goto finish;
5578 	}
5579 
5580 	/* This is a bit of a hack, because we shouldn't be handling
5581 	 * personalities within the load function.
5582 	 */
5583 	if (!declaresExecutable()) {
5584 		/* There is a special case where a non-executable kext can be loaded: the
5585 		 * AppleKextExcludeList.  Detect that special kext by bundle identifier and
5586 		 * load its metadata into the global data structures, if appropriate
5587 		 */
5588 		if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
5589 			boolean_t updated = updateExcludeList(infoDict.get());
5590 			if (updated) {
5591 				OSKextLog(this,
5592 				    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
5593 				    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
5594 			}
5595 		}
5596 
5597 		if (isDriverKit()) {
5598 			if (loadTag == 0) {
5599 				sLoadedDriverKitKexts->setObject(this);
5600 				loadTag = sNextLoadTag++;
5601 			}
5602 		}
5603 		result = kOSReturnSuccess;
5604 		goto loaded;
5605 	}
5606 
5607 	/* Are we in safe boot?
5608 	 */
5609 	if (sSafeBoot && !isLoadableInSafeBoot()) {
5610 		OSKextLog(this,
5611 		    kOSKextLogErrorLevel |
5612 		    kOSKextLogLoadFlag,
5613 		    "Can't load kext %s - not loadable during safe boot.",
5614 		    getIdentifierCString());
5615 		result = kOSKextReturnBootLevel;
5616 		goto finish;
5617 	}
5618 
5619 	OSKextLog(this,
5620 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5621 	    "Loading kext %s.",
5622 	    getIdentifierCString());
5623 
5624 #if !VM_MAPPED_KEXTS
5625 	if (isPrelinked() == false) {
5626 		OSKextLog(this,
5627 		    kOSKextLogErrorLevel |
5628 		    kOSKextLogLoadFlag,
5629 		    "Can't load kext %s - not in a kext collection.",
5630 		    getIdentifierCString());
5631 		result = kOSKextReturnDisabled;
5632 		goto finish;
5633 	}
5634 #endif /* defined(__x86_64__) */
5635 
5636 #if CONFIG_KXLD
5637 	if (!sKxldContext) {
5638 		kern_return_t kxldResult;
5639 		kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
5640 		    &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
5641 		    /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
5642 		if (kxldResult) {
5643 			OSKextLog(this,
5644 			    kOSKextLogErrorLevel |
5645 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5646 			    "Can't load kext %s - failed to create link context.",
5647 			    getIdentifierCString());
5648 			result = kOSKextReturnNoMemory;
5649 			goto finish;
5650 		}
5651 	}
5652 #endif // CONFIG_KXLD
5653 
5654 	/* We only need to resolve dependencies once for the whole graph, but
5655 	 * resolveDependencies will just return if there's no work to do, so it's
5656 	 * safe to call it more than once.
5657 	 */
5658 	if (!resolveDependencies()) {
5659 		// xxx - check resolveDependencies() for log msg
5660 		OSKextLog(this,
5661 		    kOSKextLogErrorLevel |
5662 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5663 		    "Can't load kext %s - failed to resolve library dependencies.",
5664 		    getIdentifierCString());
5665 		result = kOSKextReturnDependencies;
5666 		goto finish;
5667 	}
5668 
5669 	/* If we are excluding just the kext being loaded now (and not its
5670 	 * dependencies), drop the exclusion level to none so dependencies
5671 	 * start and/or add their personalities.
5672 	 */
5673 	if (dependenciesStartOpt == kOSKextExcludeKext) {
5674 		dependenciesStartOpt = kOSKextExcludeNone;
5675 	}
5676 
5677 	if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
5678 		dependenciesStartMatchingOpt = kOSKextExcludeNone;
5679 	}
5680 
5681 	/* Load the dependencies, recursively.
5682 	 */
5683 	count = getNumDependencies();
5684 	for (i = 0; i < count; i++) {
5685 		OSKext * dependency = OSDynamicCast(OSKext,
5686 		    dependencies->getObject(i));
5687 		if (dependency == NULL) {
5688 			OSKextLog(this,
5689 			    kOSKextLogErrorLevel |
5690 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5691 			    "Internal error loading kext %s; dependency disappeared.",
5692 			    getIdentifierCString());
5693 			result = kOSKextReturnInternalError;
5694 			goto finish;
5695 		}
5696 
5697 		/* Dependencies must be started accorting to the opt,
5698 		 * but not given the personality names of the main kext.
5699 		 */
5700 		result = dependency->load(dependenciesStartOpt,
5701 		    dependenciesStartMatchingOpt,
5702 		    /* personalityNames */ NULL);
5703 		if (result != KERN_SUCCESS) {
5704 			OSKextLog(this,
5705 			    kOSKextLogErrorLevel |
5706 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5707 			    "Dependency %s of kext %s failed to load.",
5708 			    dependency->getIdentifierCString(),
5709 			    getIdentifierCString());
5710 
5711 			OSKext::removeKext(dependency,
5712 			    /* terminateService/removePersonalities */ true);
5713 			result = kOSKextReturnDependencyLoadError;
5714 
5715 			goto finish;
5716 		}
5717 	}
5718 
5719 	result = loadExecutable();
5720 	if (result != KERN_SUCCESS) {
5721 		goto finish;
5722 	}
5723 
5724 	pendingPgoHead.next = &pendingPgoHead;
5725 	pendingPgoHead.prev = &pendingPgoHead;
5726 
5727 	// The kernel PRNG is not initialized when the first kext is
5728 	// loaded, so use early random
5729 	uuid_generate_early_random(instance_uuid);
5730 	account = IONew(OSKextAccount, 1);
5731 	if (!account) {
5732 		result = KERN_MEMORY_ERROR;
5733 		goto finish;
5734 	}
5735 	bzero(account, sizeof(*account));
5736 	account->loadTag = kmod_info->id;
5737 	account->site.refcount = 0;
5738 	account->site.flags = VM_TAG_KMOD;
5739 	account->kext = this;
5740 	if (gIOSurfaceIdentifier == bundleID) {
5741 		vm_tag_alloc(&account->site);
5742 		gIOSurfaceTag = account->site.tag;
5743 	}
5744 
5745 	flags.loaded = true;
5746 
5747 	/* Add the kext to the list of loaded kexts and update the kmod_info
5748 	 * struct to point to that of the last loaded kext (which is the way
5749 	 * it's always been done, though I'd rather do them in order now).
5750 	 */
5751 	lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
5752 	sLoadedKexts->setObject(this);
5753 
5754 	/* Keep the kernel itself out of the kmod list.
5755 	 */
5756 	if (lastLoadedKext->isKernel()) {
5757 		lastLoadedKext = NULL;
5758 	}
5759 
5760 	if (lastLoadedKext) {
5761 		kmod_info->next = lastLoadedKext->kmod_info;
5762 	}
5763 
5764 	notifyKextLoadObservers(this, kmod_info);
5765 
5766 	/* Make the global kmod list point at the just-loaded kext. Note that the
5767 	 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
5768 	 * although we do report it in kextstat these days by using the newer
5769 	 * OSArray of loaded kexts, which does contain it.
5770 	 *
5771 	 * (The OSKext object representing the kernel doesn't even have a kmod_info
5772 	 * struct, though I suppose we could stick a pointer to it from the
5773 	 * static struct in OSRuntime.cpp.)
5774 	 */
5775 	kmod = kmod_info;
5776 
5777 	/* Save the list of loaded kexts in case we panic.
5778 	 */
5779 	OSKext::saveLoadedKextPanicList();
5780 
5781 	if (isExecutable()) {
5782 		OSKext::updateLoadedKextSummaries();
5783 		savePanicString(/* isLoading */ true);
5784 
5785 #if CONFIG_DTRACE
5786 		registerWithDTrace();
5787 #else
5788 		jettisonLinkeditSegment();
5789 #endif /* CONFIG_DTRACE */
5790 
5791 #if !VM_MAPPED_KEXTS
5792 		/* If there is a page (or more) worth of padding after the end
5793 		 * of the last data section but before the end of the data segment
5794 		 * then free it in the same manner the LinkeditSegment is freed
5795 		 */
5796 		jettisonDATASegmentPadding();
5797 #endif
5798 	}
5799 
5800 loaded:
5801 	if (isExecutable() && !flags.started) {
5802 		if (startOpt == kOSKextExcludeNone) {
5803 			result = start();
5804 			if (result != kOSReturnSuccess) {
5805 				OSKextLog(this,
5806 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5807 				    "Kext %s start failed (result 0x%x).",
5808 				    getIdentifierCString(), result);
5809 				result = kOSKextReturnStartStopError;
5810 			}
5811 		}
5812 	}
5813 
5814 	/* If not excluding matching, send the personalities to the kernel.
5815 	 * This never affects the result of the load operation.
5816 	 * This is a bit of a hack, because we shouldn't be handling
5817 	 * personalities within the load function.
5818 	 */
5819 	if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
5820 		result = sendPersonalitiesToCatalog(true, personalityNames);
5821 	}
5822 
5823 finish:
5824 
5825 	if (result != kOSReturnSuccess) {
5826 		OSKextLog(this,
5827 		    kOSKextLogErrorLevel |
5828 		    kOSKextLogLoadFlag,
5829 		    "Kext %s failed to load (0x%x).",
5830 		    getIdentifierCString(), (int)result);
5831 	} else if (!alreadyLoaded) {
5832 		OSKextLog(this,
5833 		    kOSKextLogProgressLevel |
5834 		    kOSKextLogLoadFlag,
5835 		    "Kext %s loaded.",
5836 		    getIdentifierCString());
5837 
5838 		queueKextNotification(kKextRequestPredicateLoadNotification,
5839 		    OSDynamicCast(OSString, bundleID.get()));
5840 	}
5841 	return result;
5842 }
5843 
5844 #if CONFIG_KXLD
5845 /*********************************************************************
5846 *
5847 *********************************************************************/
5848 static char *
5849 strdup(const char * string)
5850 {
5851 	char * result = NULL;
5852 	size_t size;
5853 
5854 	if (!string) {
5855 		goto finish;
5856 	}
5857 
5858 	size = 1 + strlen(string);
5859 	result = (char *)kheap_alloc_tag(KHEAP_DATA_BUFFERS, size,
5860 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
5861 	if (!result) {
5862 		goto finish;
5863 	}
5864 
5865 	memcpy(result, string, size);
5866 
5867 finish:
5868 	return result;
5869 }
5870 #endif // CONFIG_KXLD
5871 
5872 /*********************************************************************
5873 *
5874 *********************************************************************/
5875 
5876 kernel_section_t *
5877 OSKext::lookupSection(const char *segname, const char *secname)
5878 {
5879 	kernel_section_t         * found_section = NULL;
5880 	kernel_mach_header_t     * mh            = NULL;
5881 	kernel_segment_command_t * seg           = NULL;
5882 	kernel_section_t         * sec           = NULL;
5883 
5884 	if (!linkedExecutable) {
5885 		return NULL;
5886 	}
5887 
5888 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5889 
5890 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5891 		if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
5892 			continue;
5893 		}
5894 
5895 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5896 			if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
5897 				found_section = sec;
5898 				goto out;
5899 			}
5900 		}
5901 	}
5902 
5903 out:
5904 	return found_section;
5905 }
5906 
5907 /*********************************************************************
5908 *
5909 *********************************************************************/
5910 
5911 OSReturn
5912 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides)
5913 {
5914 	OSReturn                       result           = kOSKextReturnBadData;
5915 	kernel_mach_header_t         * mh               = NULL;
5916 	kernel_segment_command_t     * seg              = NULL;
5917 	kernel_segment_command_t     * linkeditSeg      = NULL;
5918 	kernel_section_t             * sec              = NULL;
5919 	char                         * linkeditBase     = NULL;
5920 	bool                           haveLinkeditBase = false;
5921 	char                         * relocBase        = NULL;
5922 	bool                           haveRelocBase    = false;
5923 	struct dysymtab_command      * dysymtab         = NULL;
5924 	struct linkedit_data_command * segmentSplitInfo = NULL;
5925 	struct symtab_command        * symtab           = NULL;
5926 	kernel_nlist_t               * sym              = NULL;
5927 	struct relocation_info       * reloc            = NULL;
5928 	uint32_t                       i                = 0;
5929 	int                            reloc_size;
5930 	vm_offset_t                    new_kextsize;
5931 
5932 	if (linkedExecutable == NULL || flags.builtin) {
5933 		result = kOSReturnSuccess;
5934 		goto finish;
5935 	}
5936 
5937 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5938 	if (kernel_mach_header_is_in_fileset(mh)) {
5939 		// kexts in filesets are slid as part of collection sliding
5940 		result = kOSReturnSuccess;
5941 		goto finish;
5942 	}
5943 
5944 	segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
5945 
5946 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5947 		if (!seg->vmaddr) {
5948 			continue;
5949 		}
5950 
5951 		seg->vmaddr = ml_static_slide(seg->vmaddr);
5952 
5953 #if KASLR_KEXT_DEBUG
5954 		IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
5955 		    seg->segname,
5956 		    (unsigned long)ml_static_unslide(seg->vmaddr),
5957 		    (unsigned long)seg->vmaddr);
5958 #endif
5959 
5960 		if (!haveRelocBase) {
5961 			relocBase = (char *) seg->vmaddr;
5962 			haveRelocBase = true;
5963 		}
5964 		if (!strcmp(seg->segname, "__LINKEDIT")) {
5965 			linkeditBase = (char *) seg->vmaddr - seg->fileoff;
5966 			haveLinkeditBase = true;
5967 			linkeditSeg = seg;
5968 		}
5969 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5970 			sec->addr = ml_static_slide(sec->addr);
5971 
5972 #if KASLR_KEXT_DEBUG
5973 			IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
5974 			    sec->sectname,
5975 			    (unsigned long)ml_static_unslide(sec->addr),
5976 			    (unsigned long)sec->addr);
5977 #endif
5978 		}
5979 	}
5980 
5981 	dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
5982 
5983 	symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
5984 
5985 	if (symtab != NULL && doCoalescedSlides == false) {
5986 		/* Some pseudo-kexts have symbol tables without segments.
5987 		 * Ignore them. */
5988 		if (symtab->nsyms > 0 && haveLinkeditBase) {
5989 			sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
5990 			for (i = 0; i < symtab->nsyms; i++) {
5991 				if (sym[i].n_type & N_STAB) {
5992 					continue;
5993 				}
5994 				sym[i].n_value = ml_static_slide(sym[i].n_value);
5995 
5996 #if KASLR_KEXT_DEBUG
5997 #define MAX_SYMS_TO_LOG 5
5998 				if (i < MAX_SYMS_TO_LOG) {
5999 					IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
6000 					    (unsigned long)ml_static_unslide(sym[i].n_value),
6001 					    (unsigned long)sym[i].n_value);
6002 				}
6003 #endif
6004 			}
6005 		}
6006 	}
6007 
6008 	if (dysymtab != NULL && doCoalescedSlides == false) {
6009 		if (dysymtab->nextrel > 0) {
6010 			OSKextLog(this,
6011 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6012 			    kOSKextLogLinkFlag,
6013 			    "Sliding kext %s: External relocations found.",
6014 			    getIdentifierCString());
6015 			goto finish;
6016 		}
6017 
6018 		if (dysymtab->nlocrel > 0) {
6019 			if (!haveLinkeditBase) {
6020 				OSKextLog(this,
6021 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6022 				    kOSKextLogLinkFlag,
6023 				    "Sliding kext %s: No linkedit segment.",
6024 				    getIdentifierCString());
6025 				goto finish;
6026 			}
6027 
6028 			if (!haveRelocBase) {
6029 				OSKextLog(this,
6030 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6031 				    kOSKextLogLinkFlag,
6032 #if __x86_64__
6033 				    "Sliding kext %s: No writable segments.",
6034 #else
6035 				    "Sliding kext %s: No segments.",
6036 #endif
6037 				    getIdentifierCString());
6038 				goto finish;
6039 			}
6040 
6041 			reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
6042 			reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
6043 
6044 			for (i = 0; i < dysymtab->nlocrel; i++) {
6045 				if (reloc[i].r_extern != 0
6046 				    || reloc[i].r_type != 0
6047 				    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
6048 				    ) {
6049 					OSKextLog(this,
6050 					    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6051 					    kOSKextLogLinkFlag,
6052 					    "Sliding kext %s: Unexpected relocation found.",
6053 					    getIdentifierCString());
6054 					goto finish;
6055 				}
6056 				if (reloc[i].r_pcrel != 0) {
6057 					continue;
6058 				}
6059 				uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
6060 				*relocAddr = ml_static_slide(*relocAddr);
6061 
6062 #if KASLR_KEXT_DEBUG
6063 #define MAX_DYSYMS_TO_LOG 5
6064 				if (i < MAX_DYSYMS_TO_LOG) {
6065 					IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
6066 					    (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
6067 					    (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
6068 				}
6069 #endif
6070 			}
6071 
6072 			/* We should free these relocations, not just delete the reference to them.
6073 			 * <rdar://problem/10535549> Free relocations from PIE kexts.
6074 			 *
6075 			 * For now, we do not free LINKEDIT for kexts with split segments.
6076 			 */
6077 			new_kextsize = round_page(kmod_info->size - reloc_size);
6078 			if (new_kextsize > UINT_MAX) {
6079 				OSKextLog(this,
6080 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6081 				    kOSKextLogLinkFlag,
6082 				    "Kext %s: new kext size is too large.",
6083 				    getIdentifierCString());
6084 				goto finish;
6085 			}
6086 			if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
6087 				vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
6088 				vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
6089 				vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
6090 				size_t          bytes_remaining = endofkext - endofrelocInfo;
6091 				OSSharedPtr<OSData>        new_osdata;
6092 
6093 				/* fix up symbol offsets if they are after the dsymtab local relocs */
6094 				if (symtab) {
6095 					if (dysymtab->locreloff < symtab->symoff) {
6096 						symtab->symoff -= reloc_size;
6097 					}
6098 					if (dysymtab->locreloff < symtab->stroff) {
6099 						symtab->stroff -= reloc_size;
6100 					}
6101 				}
6102 				if (dysymtab->locreloff < dysymtab->extreloff) {
6103 					dysymtab->extreloff -= reloc_size;
6104 				}
6105 
6106 				/* move data behind reloc info down to new offset */
6107 				if (endofrelocInfo < endofkext) {
6108 					memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
6109 				}
6110 
6111 				/* Create a new OSData for the smaller kext object and reflect
6112 				 * new linkedit segment size.
6113 				 */
6114 				linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
6115 				linkeditSeg->filesize = linkeditSeg->vmsize;
6116 
6117 				new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize);
6118 				if (new_osdata) {
6119 					/* Fix up kmod info and linkedExecutable.
6120 					 */
6121 					kmod_info->size = new_kextsize;
6122 #if VM_MAPPED_KEXTS
6123 					new_osdata->setDeallocFunction(osdata_kext_free);
6124 #else
6125 					new_osdata->setDeallocFunction(osdata_phys_free);
6126 #endif
6127 					linkedExecutable->setDeallocFunction(NULL);
6128 					linkedExecutable = os::move(new_osdata);
6129 
6130 #if VM_MAPPED_KEXTS
6131 					kext_free(new_endofkext, (endofkext - new_endofkext));
6132 #else
6133 					ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
6134 #endif
6135 				}
6136 			}
6137 			dysymtab->nlocrel = 0;
6138 			dysymtab->locreloff = 0;
6139 		}
6140 	}
6141 
6142 	result = kOSReturnSuccess;
6143 finish:
6144 	return result;
6145 }
6146 
6147 /*********************************************************************
6148 * called only by load()
6149 *********************************************************************/
6150 OSReturn
6151 OSKext::loadExecutable()
6152 {
6153 	OSReturn              result             = kOSReturnError;
6154 	OSSharedPtr<OSArray>  linkDependencies;
6155 	uint32_t              num_kmod_refs      = 0;
6156 	OSData              * theExecutable      = NULL;        // do not release
6157 	OSString            * versString         = NULL;        // do not release
6158 	const char          * versCString        = NULL;        // do not free
6159 	const char          * string             = NULL;        // do not free
6160 
6161 #if CONFIG_KXLD
6162 	unsigned int          i;
6163 	uint32_t              numDirectDependencies   = 0;
6164 	kern_return_t         kxldResult;
6165 	KXLDDependency     *  kxlddeps           = NULL;        // must kfree
6166 	uint32_t              num_kxlddeps       = 0;
6167 	struct mach_header ** kxldHeaderPtr      = NULL;        // do not free
6168 	struct mach_header  * kxld_header        = NULL;        // xxx - need to free here?
6169 #endif // CONFIG_KXLD
6170 
6171 	/* We need the version string for a variety of bits below.
6172 	 */
6173 	versString = OSDynamicCast(OSString,
6174 	    getPropertyForHostArch(kCFBundleVersionKey));
6175 	if (!versString) {
6176 		goto finish;
6177 	}
6178 	versCString = versString->getCStringNoCopy();
6179 
6180 	if (isKernelComponent()) {
6181 		if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
6182 			if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
6183 				OSKextLog(this,
6184 				    kOSKextLogErrorLevel |
6185 				    kOSKextLogLoadFlag,
6186 				    "Kernel component %s has incorrect version %s; "
6187 				    "expected %s.",
6188 				    getIdentifierCString(),
6189 				    versCString, KERNEL6_VERSION);
6190 				result = kOSKextReturnInternalError;
6191 				goto finish;
6192 			} else if (strcmp(versCString, osrelease)) {
6193 				OSKextLog(this,
6194 				    kOSKextLogErrorLevel |
6195 				    kOSKextLogLoadFlag,
6196 				    "Kernel component %s has incorrect version %s; "
6197 				    "expected %s.",
6198 				    getIdentifierCString(),
6199 				    versCString, osrelease);
6200 				result = kOSKextReturnInternalError;
6201 				goto finish;
6202 			}
6203 		}
6204 	}
6205 
6206 #if defined(__x86_64__) || defined(__i386__)
6207 	if (flags.resetSegmentsFromVnode) {
6208 		/* Fixup the chains and slide the mach headers */
6209 		kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address;
6210 
6211 		if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) {
6212 			result = kOSKextReturnValidation;
6213 			goto finish;
6214 		}
6215 	}
6216 #endif //(__x86_64__) || defined(__i386__)
6217 
6218 	if (isPrelinked()) {
6219 		goto register_kmod;
6220 	}
6221 
6222 	/* <rdar://problem/21444003> all callers must be entitled */
6223 	if (FALSE == IOTaskHasEntitlement(current_task(), kOSKextCollectionManagementEntitlement)) {
6224 		OSKextLog(this,
6225 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6226 		    "Not entitled to link kext '%s'",
6227 		    getIdentifierCString());
6228 		result = kOSKextReturnNotPrivileged;
6229 		goto finish;
6230 	}
6231 
6232 	theExecutable = getExecutable();
6233 	if (!theExecutable) {
6234 		if (declaresExecutable()) {
6235 			OSKextLog(this,
6236 			    kOSKextLogErrorLevel |
6237 			    kOSKextLogLoadFlag,
6238 			    "Can't load kext %s - executable is missing.",
6239 			    getIdentifierCString());
6240 			result = kOSKextReturnValidation;
6241 			goto finish;
6242 		}
6243 		goto register_kmod;
6244 	}
6245 
6246 	if (isInterface()) {
6247 		OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable);
6248 		if (executableCopy) {
6249 			setLinkedExecutable(executableCopy.get());
6250 		}
6251 		goto register_kmod;
6252 	}
6253 
6254 #if CONFIG_KXLD
6255 	numDirectDependencies = getNumDependencies();
6256 
6257 	if (flags.hasBleedthrough) {
6258 		linkDependencies = dependencies;
6259 	} else {
6260 		linkDependencies = OSArray::withArray(dependencies.get());
6261 		if (!linkDependencies) {
6262 			OSKextLog(this,
6263 			    kOSKextLogErrorLevel |
6264 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6265 			    "Can't allocate link dependencies to load kext %s.",
6266 			    getIdentifierCString());
6267 			goto finish;
6268 		}
6269 
6270 		for (i = 0; i < numDirectDependencies; ++i) {
6271 			OSKext * dependencyKext = OSDynamicCast(OSKext,
6272 			    dependencies->getObject(i));
6273 			dependencyKext->addBleedthroughDependencies(linkDependencies.get());
6274 		}
6275 	}
6276 
6277 	num_kxlddeps = linkDependencies->getCount();
6278 	if (!num_kxlddeps) {
6279 		OSKextLog(this,
6280 		    kOSKextLogErrorLevel |
6281 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6282 		    "Can't load kext %s - it has no library dependencies.",
6283 		    getIdentifierCString());
6284 		goto finish;
6285 	}
6286 
6287 	kxlddeps = (KXLDDependency *)kalloc_tag(num_kxlddeps * sizeof(*kxlddeps), VM_KERN_MEMORY_OSKEXT);
6288 	if (!kxlddeps) {
6289 		OSKextLog(this,
6290 		    kOSKextLogErrorLevel |
6291 		    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6292 		    "Can't allocate link context to load kext %s.",
6293 		    getIdentifierCString());
6294 		goto finish;
6295 	}
6296 	bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
6297 
6298 	for (i = 0; i < num_kxlddeps; ++i) {
6299 		OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
6300 
6301 		if (dependency->isInterface()) {
6302 			OSKext *interfaceTargetKext = NULL;        //do not release
6303 			OSData * interfaceTarget = NULL;        //do not release
6304 
6305 			if (dependency->isKernelComponent()) {
6306 				interfaceTargetKext = sKernelKext;
6307 				interfaceTarget = sKernelKext->linkedExecutable.get();
6308 			} else {
6309 				interfaceTargetKext = OSDynamicCast(OSKext,
6310 				    dependency->dependencies->getObject(0));
6311 
6312 				interfaceTarget = interfaceTargetKext->linkedExecutable.get();
6313 			}
6314 
6315 			if (!interfaceTarget) {
6316 				// panic?
6317 				goto finish;
6318 			}
6319 
6320 			/* The names set here aren't actually logged yet <rdar://problem/7941514>,
6321 			 * it will be useful to have them in the debugger.
6322 			 * strdup() failing isn't critical right here so we don't check that.
6323 			 */
6324 			kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
6325 			kxlddeps[i].kext_size = interfaceTarget->getLength();
6326 			kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
6327 
6328 			if (dependency->linkedExecutable != NULL) {
6329 				kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
6330 				kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
6331 			} else {
6332 				kxlddeps[i].interface = (u_char *) NULL;
6333 				kxlddeps[i].interface_size = 0;
6334 			}
6335 			kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
6336 		} else {
6337 			kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
6338 			kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
6339 			kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
6340 		}
6341 
6342 		kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
6343 	}
6344 
6345 	kxldHeaderPtr = &kxld_header;
6346 
6347 #if DEBUG
6348 	OSKextLog(this,
6349 	    kOSKextLogExplicitLevel |
6350 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6351 	    "Kext %s - calling kxld_link_file:\n"
6352 	    "    kxld_context: %p\n"
6353 	    "    executable: %p    executable_length: %d\n"
6354 	    "    user_data: %p\n"
6355 	    "    kxld_dependencies: %p    num_dependencies: %d\n"
6356 	    "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
6357 	    getIdentifierCString(), sKxldContext,
6358 	    theExecutable->getBytesNoCopy(), theExecutable->getLength(),
6359 	    this, kxlddeps, num_kxlddeps,
6360 	    kxldHeaderPtr, &kmod_info);
6361 #endif
6362 
6363 	/* After this call, the linkedExecutable instance variable
6364 	 * should exist.
6365 	 */
6366 	kxldResult = kxld_link_file(sKxldContext,
6367 	    (u_char *)theExecutable->getBytesNoCopy(),
6368 	    theExecutable->getLength(),
6369 	    getIdentifierCString(), this, kxlddeps, num_kxlddeps,
6370 	    (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
6371 
6372 	if (kxldResult != KERN_SUCCESS) {
6373 		// xxx - add kxldResult here?
6374 		OSKextLog(this,
6375 		    kOSKextLogErrorLevel |
6376 		    kOSKextLogLoadFlag,
6377 		    "Can't load kext %s - link failed.",
6378 		    getIdentifierCString());
6379 		result = kOSKextReturnLinkError;
6380 		goto finish;
6381 	}
6382 
6383 	/* We've written data & instructions into kernel memory, so flush the data
6384 	 * cache and invalidate the instruction cache.
6385 	 * I/D caches are coherent on x86
6386 	 */
6387 #if !defined(__i386__) && !defined(__x86_64__)
6388 	flush_dcache(kmod_info->address, kmod_info->size, false);
6389 	invalidate_icache(kmod_info->address, kmod_info->size, false);
6390 #endif
6391 
6392 #else // !CONFIG_KXLD
6393 	OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6394 	    "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString());
6395 	result = kOSKextReturnLinkError;
6396 	goto finish;
6397 #endif // CONFIG_KXLD
6398 
6399 register_kmod:
6400 
6401 	if (isInterface()) {
6402 		/* Whip up a fake kmod_info entry for the interface kext.
6403 		 */
6404 		kmod_info = (kmod_info_t *)kalloc_tag(sizeof(kmod_info_t), VM_KERN_MEMORY_OSKEXT);
6405 		if (!kmod_info) {
6406 			result = KERN_MEMORY_ERROR;
6407 			goto finish;
6408 		}
6409 
6410 		/* A pseudokext has almost nothing in its kmod_info struct.
6411 		 */
6412 		bzero(kmod_info, sizeof(kmod_info_t));
6413 
6414 		kmod_info->info_version = KMOD_INFO_VERSION;
6415 
6416 		/* An interface kext doesn't have a linkedExecutable, so save a
6417 		 * copy of the UUID out of the original executable via copyUUID()
6418 		 * while we still have the original executable.
6419 		 */
6420 		interfaceUUID = copyUUID();
6421 	}
6422 
6423 	kmod_info->id = loadTag = sNextLoadTag++;
6424 	kmod_info->reference_count = 0;         // KMOD_DECL... sets it to -1 (invalid).
6425 
6426 	/* Stamp the bundle ID and version from the OSKext over anything
6427 	 * resident inside the kmod_info.
6428 	 */
6429 	string = getIdentifierCString();
6430 	strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
6431 
6432 	string = versCString;
6433 	strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
6434 
6435 	/* Add the dependencies' kmod_info structs as kmod_references.
6436 	 */
6437 	num_kmod_refs = getNumDependencies();
6438 	if (num_kmod_refs) {
6439 		kmod_info->reference_list = (kmod_reference_t *)kalloc_tag(
6440 			num_kmod_refs * sizeof(kmod_reference_t), VM_KERN_MEMORY_OSKEXT);
6441 		if (!kmod_info->reference_list) {
6442 			result = KERN_MEMORY_ERROR;
6443 			goto finish;
6444 		}
6445 		bzero(kmod_info->reference_list,
6446 		    num_kmod_refs * sizeof(kmod_reference_t));
6447 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
6448 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
6449 			OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
6450 			ref->info = refKext->kmod_info;
6451 			ref->info->reference_count++;
6452 
6453 			if (refIndex + 1 < num_kmod_refs) {
6454 				ref->next = kmod_info->reference_list + refIndex + 1;
6455 			}
6456 		}
6457 	}
6458 
6459 	if (kmod_info->hdr_size > UINT32_MAX) {
6460 		OSKextLog(this,
6461 		    kOSKextLogErrorLevel |
6462 		    kOSKextLogLoadFlag,
6463 #if __LP64__
6464 		    "Kext %s header size is too large (%lu > UINT32_MAX).",
6465 #else
6466 		    "Kext %s header size is too large (%u > UINT32_MAX).",
6467 #endif
6468 		    kmod_info->name,
6469 		    kmod_info->hdr_size);
6470 		result = KERN_FAILURE;
6471 		goto finish;
6472 	}
6473 
6474 	if (kmod_info->size > UINT32_MAX) {
6475 		OSKextLog(this,
6476 		    kOSKextLogErrorLevel |
6477 		    kOSKextLogLoadFlag,
6478 #if __LP64__
6479 		    "Kext %s size is too large (%lu > UINT32_MAX).",
6480 #else
6481 		    "Kext %s size is too large (%u > UINT32_MAX).",
6482 #endif
6483 		    kmod_info->name,
6484 		    kmod_info->size);
6485 		result = KERN_FAILURE;
6486 		goto finish;
6487 	}
6488 
6489 	if (!isInterface() && linkedExecutable) {
6490 		OSKextLog(this,
6491 		    kOSKextLogProgressLevel |
6492 		    kOSKextLogLoadFlag,
6493 		    "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
6494 		    kmod_info->name,
6495 		    (unsigned)kmod_info->size / PAGE_SIZE,
6496 		    (unsigned long)ml_static_unslide(kmod_info->address),
6497 		    (unsigned)kmod_info->id);
6498 	}
6499 
6500 	/* VM protections and wiring for the Aux KC are done at collection loading time */
6501 	if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) {
6502 		/* if prelinked and primary KC, VM protections are already set */
6503 		result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true);
6504 		if (result != KERN_SUCCESS) {
6505 			goto finish;
6506 		}
6507 	}
6508 
6509 #if KASAN
6510 	if (linkedExecutable) {
6511 		kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
6512 		    linkedExecutable->getLength(), getIdentifierCString());
6513 	}
6514 #else
6515 	if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
6516 		OSKextLog(this,
6517 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6518 		    "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
6519 		    getIdentifierCString()
6520 		    );
6521 		result = KERN_FAILURE;
6522 		goto finish;
6523 	}
6524 #endif
6525 
6526 	result = kOSReturnSuccess;
6527 
6528 finish:
6529 
6530 #if CONFIG_KXLD
6531 	/* Clear up locally allocated dependency info.
6532 	 */
6533 	for (i = 0; i < num_kxlddeps; ++i) {
6534 		size_t size;
6535 
6536 		if (kxlddeps[i].kext_name) {
6537 			size = 1 + strlen(kxlddeps[i].kext_name);
6538 			kheap_free(KHEAP_DATA_BUFFERS, kxlddeps[i].kext_name, size);
6539 		}
6540 		if (kxlddeps[i].interface_name) {
6541 			size = 1 + strlen(kxlddeps[i].interface_name);
6542 			kheap_free(KHEAP_DATA_BUFFERS, kxlddeps[i].interface_name, size);
6543 		}
6544 	}
6545 	if (kxlddeps) {
6546 		kfree(kxlddeps, (num_kxlddeps * sizeof(*kxlddeps)));
6547 	}
6548 #endif // CONFIG_KXLD
6549 
6550 	/* We no longer need the unrelocated executable (which the linker
6551 	 * has altered anyhow).
6552 	 */
6553 	setExecutable(NULL);
6554 
6555 	if (result != kOSReturnSuccess) {
6556 		OSKextLog(this,
6557 		    kOSKextLogErrorLevel |
6558 		    kOSKextLogLoadFlag,
6559 		    "Failed to load executable for kext %s.",
6560 		    getIdentifierCString());
6561 
6562 		if (kmod_info && kmod_info->reference_list) {
6563 			kfree(kmod_info->reference_list,
6564 			    num_kmod_refs * sizeof(kmod_reference_t));
6565 		}
6566 		if (isInterface()) {
6567 			kfree(kmod_info, sizeof(kmod_info_t));
6568 			kmod_info = NULL;
6569 		}
6570 		if (kc_type == KCKindUnknown) {
6571 			kmod_info = NULL;
6572 			if (linkedExecutable) {
6573 				linkedExecutable.reset();
6574 			}
6575 		}
6576 	}
6577 
6578 	return result;
6579 }
6580 
6581 #if VM_MAPPED_KEXTS
6582 /* static */
6583 void
6584 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh)
6585 {
6586 	kernel_segment_command_t *linkeditseg = NULL;
6587 
6588 	linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT);
6589 	assert(linkeditseg != NULL);
6590 
6591 	/* BootKC on x86_64 is not vm mapped */
6592 	ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize);
6593 
6594 	OSKextLog(/* kext */ NULL,
6595 	    kOSKextLogProgressLevel |
6596 	    kOSKextLogGeneralFlag,
6597 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
6598 	    linkeditseg->vmaddr, linkeditseg->vmsize);
6599 }
6600 #endif /* VM_MAPPED_KEXTS */
6601 
6602 /*********************************************************************
6603 * The linkedit segment is used by the kext linker for dependency
6604 * resolution, and by dtrace for probe initialization. We can free it
6605 * for non-library kexts, since no kexts depend on non-library kexts
6606 * by definition, once dtrace has been initialized.
6607 *********************************************************************/
6608 void
6609 OSKext::jettisonLinkeditSegment(void)
6610 {
6611 	kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
6612 	kernel_segment_command_t * linkedit = NULL;
6613 	vm_offset_t                start;
6614 	vm_size_t                  linkeditsize, kextsize;
6615 	OSSharedPtr<OSData>        data;
6616 
6617 	if (isInFileset()) {
6618 		return;
6619 	}
6620 
6621 #if NO_KEXTD
6622 	/* We can free symbol tables for all embedded kexts because we don't
6623 	 * support runtime kext linking.
6624 	 */
6625 	if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
6626 #else
6627 	if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
6628 #endif
6629 		goto finish;
6630 	}
6631 
6632 	/* Find the linkedit segment.  If it's not the last segment, then freeing
6633 	 * it will fragment the kext into multiple VM regions, which OSKext is not
6634 	 * designed to handle, so we'll have to skip it.
6635 	 */
6636 	linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
6637 	if (!linkedit) {
6638 		goto finish;
6639 	}
6640 
6641 	if (round_page(kmod_info->address + kmod_info->size) !=
6642 	    round_page(linkedit->vmaddr + linkedit->vmsize)) {
6643 		goto finish;
6644 	}
6645 
6646 	/* Create a new OSData for the smaller kext object.
6647 	 */
6648 	linkeditsize = round_page(linkedit->vmsize);
6649 	kextsize = kmod_info->size - linkeditsize;
6650 	start = linkedit->vmaddr;
6651 
6652 	if (kextsize > UINT_MAX) {
6653 		goto finish;
6654 	}
6655 	data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize);
6656 	if (!data) {
6657 		goto finish;
6658 	}
6659 
6660 	/* Fix the kmod info and linkedExecutable.
6661 	 */
6662 	kmod_info->size = kextsize;
6663 
6664 #if VM_MAPPED_KEXTS
6665 	data->setDeallocFunction(osdata_kext_free);
6666 #else
6667 	data->setDeallocFunction(osdata_phys_free);
6668 #endif
6669 	linkedExecutable->setDeallocFunction(NULL);
6670 	linkedExecutable = os::move(data);
6671 	flags.jettisonLinkeditSeg = 1;
6672 
6673 	/* Free the linkedit segment.
6674 	 */
6675 #if VM_MAPPED_KEXTS
6676 	kext_free(start, linkeditsize);
6677 #else
6678 	ml_static_mfree(start, linkeditsize);
6679 #endif
6680 
6681 finish:
6682 	return;
6683 }
6684 
6685 /*********************************************************************
6686 * If there are whole pages that are unused betweem the last section
6687 * of the DATA segment and the end of the DATA segment then we can free
6688 * them
6689 *********************************************************************/
6690 void
6691 OSKext::jettisonDATASegmentPadding(void)
6692 {
6693 	kernel_mach_header_t * mh;
6694 	kernel_segment_command_t * dataSeg;
6695 	kernel_section_t * sec, * lastSec;
6696 	vm_offset_t dataSegEnd, lastSecEnd;
6697 	vm_size_t padSize;
6698 
6699 	if (flags.builtin) {
6700 		return;
6701 	}
6702 	mh = (kernel_mach_header_t *)kmod_info->address;
6703 
6704 	if (isInFileset()) {
6705 		return;
6706 	}
6707 
6708 	dataSeg = getsegbynamefromheader(mh, SEG_DATA);
6709 	if (dataSeg == NULL) {
6710 		return;
6711 	}
6712 
6713 	lastSec = NULL;
6714 	sec = firstsect(dataSeg);
6715 	while (sec != NULL) {
6716 		lastSec = sec;
6717 		sec = nextsect(dataSeg, sec);
6718 	}
6719 
6720 	if (lastSec == NULL) {
6721 		return;
6722 	}
6723 
6724 	if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
6725 	    (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
6726 		return;
6727 	}
6728 
6729 	dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
6730 	lastSecEnd = round_page(lastSec->addr + lastSec->size);
6731 
6732 	if (dataSegEnd <= lastSecEnd) {
6733 		return;
6734 	}
6735 
6736 	padSize = dataSegEnd - lastSecEnd;
6737 
6738 	if (padSize >= PAGE_SIZE) {
6739 #if VM_MAPPED_KEXTS
6740 		kext_free(lastSecEnd, padSize);
6741 #else
6742 		ml_static_mfree(lastSecEnd, padSize);
6743 #endif
6744 	}
6745 }
6746 
6747 /*********************************************************************
6748 *********************************************************************/
6749 void
6750 OSKext::setLinkedExecutable(OSData * anExecutable)
6751 {
6752 	if (linkedExecutable) {
6753 		panic("Attempt to set linked executable on kext "
6754 		    "that already has one (%s).\n",
6755 		    getIdentifierCString());
6756 	}
6757 	linkedExecutable.reset(anExecutable, OSRetain);
6758 	return;
6759 }
6760 
6761 #if CONFIG_DTRACE
6762 /*********************************************************************
6763 * Go through all loaded kexts and tell them to register with dtrace.
6764 * The instance method only registers if necessary.
6765 *********************************************************************/
6766 /* static */
6767 void
6768 OSKext::registerKextsWithDTrace(void)
6769 {
6770 	uint32_t count = sLoadedKexts->getCount();
6771 	uint32_t i;
6772 
6773 	IORecursiveLockLock(sKextLock);
6774 
6775 	for (i = 0; i < count; i++) {
6776 		OSKext   * thisKext     = NULL;        // do not release
6777 
6778 		thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
6779 		if (!thisKext || !thisKext->isExecutable()) {
6780 			continue;
6781 		}
6782 
6783 		thisKext->registerWithDTrace();
6784 	}
6785 
6786 	IORecursiveLockUnlock(sKextLock);
6787 
6788 	return;
6789 }
6790 
6791 extern "C" {
6792 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
6793 extern int (*dtrace_modunload)(struct kmod_info *);
6794 };
6795 
6796 /*********************************************************************
6797 *********************************************************************/
6798 void
6799 OSKext::registerWithDTrace(void)
6800 {
6801 	/* Register kext with dtrace. A dtrace_modload failure should not
6802 	 * prevent a kext from loading, so we ignore the return code.
6803 	 */
6804 	if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
6805 		uint32_t modflag = 0;
6806 		OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
6807 
6808 #if VM_MAPPED_KEXTS
6809 		if (!sKeepSymbols && kc_type == KCKindPrimary) {
6810 			if (forceInit == kOSBooleanTrue) {
6811 				/* Make sure the kext is not from the Boot KC */
6812 				panic("OSBundleForceDTraceInit key specified for the Boot KC kext : %s", getIdentifierCString());
6813 			} else {
6814 				/* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */
6815 				modflag |= KMOD_DTRACE_NO_KERNEL_SYMS;
6816 			}
6817 		}
6818 #endif /* VM_MAPPED_KEXTS */
6819 		if (forceInit == kOSBooleanTrue) {
6820 			modflag |= KMOD_DTRACE_FORCE_INIT;
6821 		}
6822 		if (flags.builtin) {
6823 			modflag |= KMOD_DTRACE_STATIC_KEXT;
6824 		}
6825 
6826 		(void)(*dtrace_modload)(kmod_info, modflag);
6827 		flags.dtraceInitialized = true;
6828 		jettisonLinkeditSegment();
6829 	}
6830 	return;
6831 }
6832 /*********************************************************************
6833 *********************************************************************/
6834 void
6835 OSKext::unregisterWithDTrace(void)
6836 {
6837 	/* Unregister kext with dtrace. A dtrace_modunload failure should not
6838 	 * prevent a kext from loading, so we ignore the return code.
6839 	 */
6840 	if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
6841 		(void)(*dtrace_modunload)(kmod_info);
6842 		flags.dtraceInitialized = false;
6843 	}
6844 	return;
6845 }
6846 #endif /* CONFIG_DTRACE */
6847 
6848 
6849 /*********************************************************************
6850 * called only by loadExecutable()
6851 *********************************************************************/
6852 #if !VM_MAPPED_KEXTS
6853 #if defined(__arm__) || defined(__arm64__)
6854 static inline kern_return_t
6855 OSKext_protect(
6856 	kernel_mach_header_t *kext_mh,
6857 	vm_map_t   map,
6858 	vm_map_offset_t    start,
6859 	vm_map_offset_t    end,
6860 	vm_prot_t  new_prot,
6861 	boolean_t  set_max,
6862 	kc_kind_t  kc_type)
6863 {
6864 #pragma unused(kext_mh,map,kc_type)
6865 	assert(map == kernel_map);         // we can handle KEXTs arising from the PRELINK segment and no others
6866 	assert(start <= end);
6867 	if (start >= end) {
6868 		return KERN_SUCCESS;         // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
6869 	} else if (set_max) {
6870 		return KERN_SUCCESS;         // Punt set_max, as there's no mechanism to record that state
6871 	} else {
6872 		return ml_static_protect(start, end - start, new_prot);
6873 	}
6874 }
6875 
6876 static inline kern_return_t
6877 OSKext_wire(
6878 	kernel_mach_header_t *kext_mh,
6879 	vm_map_t   map,
6880 	vm_map_offset_t    start,
6881 	vm_map_offset_t    end,
6882 	vm_prot_t  access_type,
6883 	boolean_t       user_wire,
6884 	kc_kind_t       kc_type)
6885 {
6886 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type)
6887 	return KERN_SUCCESS;         // No-op as PRELINK kexts are cemented into physical memory at boot
6888 }
6889 #else
6890 #error Unrecognized architecture
6891 #endif
6892 #else
6893 static inline kern_return_t
6894 OSKext_protect(
6895 	kernel_mach_header_t *kext_mh,
6896 	vm_map_t   map,
6897 	vm_map_offset_t    start,
6898 	vm_map_offset_t    end,
6899 	vm_prot_t  new_prot,
6900 	boolean_t  set_max,
6901 	kc_kind_t  kc_type)
6902 {
6903 	if (start == end) {         // 10538581
6904 		return KERN_SUCCESS;
6905 	}
6906 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
6907 		/*
6908 		 * XXX: This will probably need to be different for AuxKC and
6909 		 * pageableKC!
6910 		 */
6911 		return ml_static_protect(start, end - start, new_prot);
6912 	}
6913 	return vm_map_protect(map, start, end, new_prot, set_max);
6914 }
6915 
6916 static inline kern_return_t
6917 OSKext_wire(
6918 	kernel_mach_header_t *kext_mh,
6919 	vm_map_t   map,
6920 	vm_map_offset_t    start,
6921 	vm_map_offset_t    end,
6922 	vm_prot_t  access_type,
6923 	boolean_t       user_wire,
6924 	kc_kind_t       kc_type)
6925 {
6926 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
6927 		/* TODO: we may need to hook this for the pageableKC */
6928 		return KERN_SUCCESS;
6929 	}
6930 	return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
6931 }
6932 #endif
6933 
6934 OSReturn
6935 OSKext::setVMAttributes(bool protect, bool wire)
6936 {
6937 	vm_map_t                    kext_map        = NULL;
6938 	kernel_segment_command_t  * seg             = NULL;
6939 	vm_map_offset_t             start_protect   = 0;
6940 	vm_map_offset_t             start_wire      = 0;
6941 	vm_map_offset_t             end_protect     = 0;
6942 	vm_map_offset_t             end_wire        = 0;
6943 	OSReturn                    result          = kOSReturnError;
6944 
6945 	if (isInterface() || !declaresExecutable() || flags.builtin) {
6946 		result = kOSReturnSuccess;
6947 		goto finish;
6948 	}
6949 
6950 	/* Get the kext's vm map */
6951 	kext_map = kext_get_vm_map(kmod_info);
6952 	if (!kext_map) {
6953 		result = KERN_MEMORY_ERROR;
6954 		goto finish;
6955 	}
6956 
6957 #if !VM_MAPPED_KEXTS
6958 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
6959 		/* This is a split kext in a prelinked kernelcache; we'll let the
6960 		 * platform code take care of protecting it.  It is already wired.
6961 		 */
6962 		/* TODO: Should this still allow protections for the first segment
6963 		 * to go through, in the event that we have a mix of split and
6964 		 * unsplit kexts?
6965 		 */
6966 		result = KERN_SUCCESS;
6967 		goto finish;
6968 	}
6969 
6970 	if (isInFileset() && kc_type != KCKindPageable) {
6971 		// kexts in filesets have protections setup as part of collection loading
6972 		result = KERN_SUCCESS;
6973 		goto finish;
6974 	}
6975 #endif
6976 
6977 	/* Protect the headers as read-only; they do not need to be wired */
6978 	result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address,
6979 	    kext_map, kmod_info->address,
6980 	    kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type)
6981 	    : KERN_SUCCESS;
6982 	if (result != KERN_SUCCESS) {
6983 		goto finish;
6984 	}
6985 
6986 	/* Set the VM protections and wire down each of the segments */
6987 	seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6988 	while (seg) {
6989 #if __arm__
6990 		/* We build all ARM kexts, so we can ensure they are aligned */
6991 		assert((seg->vmaddr & PAGE_MASK) == 0);
6992 		assert((seg->vmsize & PAGE_MASK) == 0);
6993 #endif
6994 
6995 		/*
6996 		 * For the non page aligned segments, the range calculation for protection
6997 		 * and wiring differ as follows:
6998 		 *
6999 		 * Protection: The non page aligned data at the start or at the end of the
7000 		 * segment is excluded from the protection. This exclusion is needed to make
7001 		 * sure OSKext_protect is not called twice on same page, if the page is shared
7002 		 * between two segments.
7003 		 *
7004 		 * Wiring: The non page aligned data at the start or at the end of the
7005 		 * segment is included in the wiring range, this inclusion is needed to make sure
7006 		 * all the data of the segment is wired.
7007 		 */
7008 		start_protect = round_page(seg->vmaddr);
7009 		end_protect = trunc_page(seg->vmaddr + seg->vmsize);
7010 
7011 		start_wire = trunc_page(seg->vmaddr);
7012 		end_wire = round_page(seg->vmaddr + seg->vmsize);
7013 
7014 		/*
7015 		 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared
7016 		 * across kexts and data from kexts is not page aligned
7017 		 */
7018 		if (protect && (end_protect > start_protect) &&
7019 		    ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 &&
7020 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) ||
7021 		    (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) {
7022 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7023 			    kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type);
7024 			if (result != KERN_SUCCESS) {
7025 				OSKextLog(this,
7026 				    kOSKextLogErrorLevel |
7027 				    kOSKextLogLoadFlag,
7028 				    "Kext %s failed to set maximum VM protections "
7029 				    "for segment %s - 0x%x.",
7030 				    getIdentifierCString(), seg->segname, (int)result);
7031 				goto finish;
7032 			}
7033 
7034 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7035 			    kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type);
7036 			if (result != KERN_SUCCESS) {
7037 				OSKextLog(this,
7038 				    kOSKextLogErrorLevel |
7039 				    kOSKextLogLoadFlag,
7040 				    "Kext %s failed to set initial VM protections "
7041 				    "for segment %s - 0x%x.",
7042 				    getIdentifierCString(), seg->segname, (int)result);
7043 				goto finish;
7044 			}
7045 		}
7046 
7047 		if (segmentShouldBeWired(seg) && wire) {
7048 			result = OSKext_wire((kernel_mach_header_t *)kmod_info->address,
7049 			    kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type);
7050 			if (result != KERN_SUCCESS) {
7051 				goto finish;
7052 			}
7053 		}
7054 
7055 		seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7056 	}
7057 
7058 finish:
7059 	return result;
7060 }
7061 
7062 /*********************************************************************
7063 *********************************************************************/
7064 boolean_t
7065 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
7066 {
7067 	return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) &&
7068 	       strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)));
7069 }
7070 
7071 /*********************************************************************
7072 *********************************************************************/
7073 OSReturn
7074 OSKext::validateKextMapping(bool startFlag)
7075 {
7076 	OSReturn                              result      = kOSReturnError;
7077 	const char                          * whichOp = startFlag ? "start" : "stop";
7078 	kern_return_t                         kern_result = 0;
7079 	vm_map_t                              kext_map    = NULL;
7080 	kernel_segment_command_t            * seg         = NULL;
7081 	mach_vm_address_t                     address     = 0;
7082 	mach_vm_size_t                        size        = 0;
7083 	uint32_t                              depth       = 0;
7084 	uint64_t                              kext_segbase = 0;
7085 	uint64_t                              kext_segsize = 0;
7086 	mach_msg_type_number_t                count;
7087 	vm_region_submap_short_info_data_64_t info;
7088 	uintptr_t                             kext_slide = PE_get_kc_slide(kc_type);
7089 
7090 	if (flags.builtin) {
7091 		return kOSReturnSuccess;
7092 	}
7093 
7094 	count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
7095 	bzero(&info, sizeof(info));
7096 
7097 	// xxx - do we need a distinct OSReturn value for these or is "bad data"
7098 	// xxx - sufficient?
7099 
7100 	/* Verify that the kmod_info and start/stop pointers are non-NULL.
7101 	 */
7102 	if (!kmod_info) {
7103 		OSKextLog(this,
7104 		    kOSKextLogErrorLevel |
7105 		    kOSKextLogLoadFlag,
7106 		    "Kext %s - NULL kmod_info pointer.",
7107 		    getIdentifierCString());
7108 		result = kOSKextReturnBadData;
7109 		goto finish;
7110 	}
7111 
7112 	if (startFlag) {
7113 		address = (mach_vm_address_t)kmod_info->start;
7114 	} else {
7115 		address = (mach_vm_address_t)kmod_info->stop;
7116 	}
7117 
7118 	if (!address) {
7119 		OSKextLog(this,
7120 		    kOSKextLogErrorLevel |
7121 		    kOSKextLogLoadFlag,
7122 		    "Kext %s - NULL module %s pointer.",
7123 		    getIdentifierCString(), whichOp);
7124 		result = kOSKextReturnBadData;
7125 		goto finish;
7126 	}
7127 
7128 	kext_map = kext_get_vm_map(kmod_info);
7129 	depth = (kernel_map == kext_map) ? 1 : 2;
7130 	if (isInFileset()) {
7131 #if defined(HAS_APPLE_PAC)
7132 		address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0);
7133 #endif /* defined(HAS_APPLE_PAC) */
7134 	}
7135 
7136 	/* Verify that the start/stop function lies within the kext's address range.
7137 	 */
7138 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) ||
7139 	    isInFileset()) {
7140 		/* This will likely be how we deal with split kexts; walk the segments to
7141 		 * check that the function lies inside one of the segments of this kext.
7142 		 */
7143 		for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7144 		    seg != NULL;
7145 		    seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
7146 			if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
7147 				kext_segbase = seg->vmaddr;
7148 				kext_segsize = seg->vmsize;
7149 				break;
7150 			}
7151 		}
7152 
7153 		if (!seg) {
7154 			OSKextLog(this,
7155 			    kOSKextLogErrorLevel |
7156 			    kOSKextLogLoadFlag,
7157 			    "Kext %s module %s pointer is outside of kext range "
7158 			    "(%s %p - kext starts at %p).",
7159 			    getIdentifierCString(),
7160 			    whichOp,
7161 			    whichOp,
7162 			    (void *)(((uintptr_t)address) - kext_slide),
7163 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide));
7164 			result = kOSKextReturnBadData;
7165 			goto finish;
7166 		}
7167 
7168 		seg = NULL;
7169 	} else {
7170 		if (address < kmod_info->address + kmod_info->hdr_size ||
7171 		    kmod_info->address + kmod_info->size <= address) {
7172 			OSKextLog(this,
7173 			    kOSKextLogErrorLevel |
7174 			    kOSKextLogLoadFlag,
7175 			    "Kext %s module %s pointer is outside of kext range "
7176 			    "(%s %p - kext at %p-%p).",
7177 			    getIdentifierCString(),
7178 			    whichOp,
7179 			    whichOp,
7180 			    (void *)(((uintptr_t)address) - kext_slide),
7181 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide),
7182 			    (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size));
7183 			result = kOSKextReturnBadData;
7184 			goto finish;
7185 		}
7186 	}
7187 
7188 	/* Only do these checks before calling the start function;
7189 	 * If anything goes wrong with the mapping while the kext is running,
7190 	 * we'll likely have panicked well before any attempt to stop the kext.
7191 	 */
7192 	if (startFlag) {
7193 		if (!isInFileset() || kc_type != KCKindPrimary) {
7194 			/*
7195 			 * Verify that the start/stop function is executable.
7196 			 */
7197 			kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
7198 			    (vm_region_recurse_info_t)&info, &count);
7199 			if (kern_result != KERN_SUCCESS) {
7200 				OSKextLog(this,
7201 				    kOSKextLogErrorLevel |
7202 				    kOSKextLogLoadFlag,
7203 				    "Kext %s - bad %s pointer %p.",
7204 				    getIdentifierCString(),
7205 				    whichOp, (void *)ml_static_unslide(address));
7206 				result = kOSKextReturnBadData;
7207 				goto finish;
7208 			}
7209 		} else {
7210 			/*
7211 			 * Since kexts loaded from the primary KC are held in memory
7212 			 * allocated by efiboot, we cannot use mach_vm_region_recurse() to
7213 			 * discover that memory's protection flags.  Instead, we need to
7214 			 * get that information from the kernel pmap itself.  Above, we
7215 			 * (potentially) saved the size of the segment in which the address
7216 			 * in question was located.  If we have a non-zero size, verify
7217 			 * that all pages in the (address, address + kext_segsize) range
7218 			 * are marked executable.  If we somehow did not record the size
7219 			 * (or the base) just verify the single page that includes the address.
7220 			 */
7221 			if (kext_segbase == 0 || kext_segsize == 0) {
7222 				kext_segbase = address & ~(uint64_t)PAGE_MASK;
7223 				kext_segsize = PAGE_SIZE;
7224 			}
7225 		}
7226 
7227 #if VM_MAPPED_KEXTS
7228 		if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) ||
7229 		    ((isInFileset() && kc_type == KCKindPrimary) &&
7230 		    ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) {
7231 			OSKextLog(this,
7232 			    kOSKextLogErrorLevel |
7233 			    kOSKextLogLoadFlag,
7234 			    "Kext %s - memory region containing module %s function "
7235 			    "is not executable.",
7236 			    getIdentifierCString(), whichOp);
7237 			result = kOSKextReturnBadData;
7238 			goto finish;
7239 		}
7240 #endif
7241 
7242 		/* Verify that the kext's segments are backed by physical memory.
7243 		 */
7244 		seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7245 		while (seg) {
7246 			if (!verifySegmentMapping(seg)) {
7247 				result = kOSKextReturnBadData;
7248 				goto finish;
7249 			}
7250 
7251 			seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7252 		}
7253 	}
7254 
7255 	result = kOSReturnSuccess;
7256 finish:
7257 	return result;
7258 }
7259 
7260 /*********************************************************************
7261 *********************************************************************/
7262 boolean_t
7263 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
7264 {
7265 	mach_vm_address_t address = 0;
7266 
7267 	if (seg->vmsize > UINT32_MAX) {
7268 		return false;
7269 	}
7270 
7271 	if (!segmentShouldBeWired(seg)) {
7272 		return true;
7273 	}
7274 
7275 	for (address = seg->vmaddr;
7276 	    address < round_page(seg->vmaddr + seg->vmsize);
7277 	    address += PAGE_SIZE) {
7278 		if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
7279 			OSKextLog(this,
7280 			    kOSKextLogErrorLevel |
7281 			    kOSKextLogLoadFlag,
7282 			    "Kext %s - page %p is not backed by physical memory.",
7283 			    getIdentifierCString(),
7284 			    (void *)address);
7285 			return false;
7286 		}
7287 	}
7288 
7289 	return true;
7290 }
7291 
7292 /*********************************************************************
7293 *********************************************************************/
7294 static void
7295 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
7296 {
7297 	uint64_t                            stamp = 0;
7298 	firehose_tracepoint_id_u            trace_id;
7299 	struct firehose_trace_uuid_info_s   uuid_info_s;
7300 	firehose_trace_uuid_info_t          uuid_info = &uuid_info_s;
7301 	size_t                              uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
7302 	OSSharedPtr<OSData>                 uuid_data;
7303 
7304 	stamp = firehose_tracepoint_time(firehose_activity_flags_default);
7305 	trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
7306 
7307 	uuid_data = aKext->copyTextUUID();
7308 	if (uuid_data) {
7309 		memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
7310 	}
7311 
7312 	uuid_info->ftui_size    = size;
7313 	if (aKext->isDriverKit()) {
7314 		uuid_info->ftui_address = address;
7315 	} else {
7316 		uuid_info->ftui_address = ml_static_unslide(address);
7317 	}
7318 	firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
7319 	return;
7320 }
7321 
7322 void
7323 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
7324 {
7325 	OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
7326 }
7327 
7328 /*********************************************************************
7329 *********************************************************************/
7330 OSReturn
7331 OSKext::start(bool startDependenciesFlag)
7332 {
7333 	OSReturn                            result = kOSReturnError;
7334 	kern_return_t                       (* startfunc)(kmod_info_t *, void *);
7335 	unsigned int                        i, count;
7336 	void                              * kmodStartData = NULL;
7337 
7338 	if (isStarted() || isInterface() || isKernelComponent()) {
7339 		result = kOSReturnSuccess;
7340 		goto finish;
7341 	}
7342 
7343 	if (!isLoaded()) {
7344 		OSKextLog(this,
7345 		    kOSKextLogErrorLevel |
7346 		    kOSKextLogLoadFlag,
7347 		    "Attempt to start nonloaded kext %s.",
7348 		    getIdentifierCString());
7349 		result = kOSKextReturnInvalidArgument;
7350 		goto finish;
7351 	}
7352 
7353 	if (!sLoadEnabled) {
7354 		OSKextLog(this,
7355 		    kOSKextLogErrorLevel |
7356 		    kOSKextLogLoadFlag,
7357 		    "Kext loading is disabled (attempt to start kext %s).",
7358 		    getIdentifierCString());
7359 		result = kOSKextReturnDisabled;
7360 		goto finish;
7361 	}
7362 
7363 	result = validateKextMapping(/* start? */ true);
7364 	if (result != kOSReturnSuccess) {
7365 		goto finish;
7366 	}
7367 
7368 	startfunc = kmod_info->start;
7369 
7370 	count = getNumDependencies();
7371 	for (i = 0; i < count; i++) {
7372 		OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
7373 		if (dependency == NULL) {
7374 			OSKextLog(this,
7375 			    kOSKextLogErrorLevel |
7376 			    kOSKextLogLoadFlag,
7377 			    "Kext %s start - internal error, dependency disappeared.",
7378 			    getIdentifierCString());
7379 			goto finish;
7380 		}
7381 		if (!dependency->isStarted()) {
7382 			if (startDependenciesFlag) {
7383 				OSReturn dependencyResult =
7384 				    dependency->start(startDependenciesFlag);
7385 				if (dependencyResult != KERN_SUCCESS) {
7386 					OSKextLog(this,
7387 					    kOSKextLogErrorLevel |
7388 					    kOSKextLogLoadFlag,
7389 					    "Kext %s start - dependency %s failed to start (error 0x%x).",
7390 					    getIdentifierCString(),
7391 					    dependency->getIdentifierCString(),
7392 					    dependencyResult);
7393 					goto finish;
7394 				}
7395 			} else {
7396 				OSKextLog(this,
7397 				    kOSKextLogErrorLevel |
7398 				    kOSKextLogLoadFlag,
7399 				    "Not starting %s - dependency %s not started yet.",
7400 				    getIdentifierCString(),
7401 				    dependency->getIdentifierCString());
7402 				result = kOSKextReturnStartStopError;         // xxx - make new return?
7403 				goto finish;
7404 			}
7405 		}
7406 	}
7407 
7408 	OSKextLog(this,
7409 	    kOSKextLogDetailLevel |
7410 	    kOSKextLogLoadFlag,
7411 	    "Kext %s calling module start function.",
7412 	    getIdentifierCString());
7413 
7414 	flags.starting = 1;
7415 
7416 	// Drop a log message so logd can grab the needed information to decode this kext
7417 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
7418 	result = OSRuntimeInitializeCPP(this);
7419 	if (result == KERN_SUCCESS) {
7420 		result = startfunc(kmod_info, kmodStartData);
7421 	}
7422 
7423 	flags.starting = 0;
7424 
7425 	/* On success overlap the setting of started/starting. On failure just
7426 	 * clear starting.
7427 	 */
7428 	if (result == KERN_SUCCESS) {
7429 		flags.started = 1;
7430 
7431 		// xxx - log start error from kernel?
7432 		OSKextLog(this,
7433 		    kOSKextLogProgressLevel |
7434 		    kOSKextLogLoadFlag,
7435 		    "Kext %s is now started.",
7436 		    getIdentifierCString());
7437 	} else {
7438 		invokeOrCancelRequestCallbacks(
7439 			/* result not actually used */ kOSKextReturnStartStopError,
7440 			/* invokeFlag */ false);
7441 		OSKextLog(this,
7442 		    kOSKextLogWarningLevel |
7443 		    kOSKextLogLoadFlag,
7444 		    "Kext %s did not start (return code 0x%x).",
7445 		    getIdentifierCString(), result);
7446 	}
7447 
7448 finish:
7449 	return result;
7450 }
7451 
7452 /*********************************************************************
7453 *********************************************************************/
7454 /* static */
7455 bool
7456 OSKext::canUnloadKextWithIdentifier(
7457 	OSString * kextIdentifier,
7458 	bool       checkClassesFlag)
7459 {
7460 	bool     result = false;
7461 	OSKext * aKext  = NULL;        // do not release
7462 
7463 	IORecursiveLockLock(sKextLock);
7464 
7465 	aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
7466 
7467 	if (!aKext) {
7468 		goto finish;         // can't unload what's not loaded
7469 	}
7470 
7471 	if (aKext->isLoaded()) {
7472 		if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
7473 			goto finish;
7474 		}
7475 		if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
7476 			goto finish;
7477 		}
7478 	}
7479 
7480 	result = true;
7481 
7482 finish:
7483 	IORecursiveLockUnlock(sKextLock);
7484 	return result;
7485 }
7486 
7487 /*********************************************************************
7488 *********************************************************************/
7489 OSReturn
7490 OSKext::stop(void)
7491 {
7492 	OSReturn result = kOSReturnError;
7493 	kern_return_t (*stopfunc)(kmod_info_t *, void *);
7494 
7495 	if (!isStarted() || isInterface()) {
7496 		result = kOSReturnSuccess;
7497 		goto finish;
7498 	}
7499 
7500 	if (!isLoaded()) {
7501 		OSKextLog(this,
7502 		    kOSKextLogErrorLevel |
7503 		    kOSKextLogLoadFlag,
7504 		    "Attempt to stop nonloaded kext %s.",
7505 		    getIdentifierCString());
7506 		result = kOSKextReturnInvalidArgument;
7507 		goto finish;
7508 	}
7509 
7510 	/* Refuse to stop if we have clients or instances. It is up to
7511 	 * the caller to make sure those aren't true.
7512 	 */
7513 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7514 		OSKextLog(this,
7515 		    kOSKextLogErrorLevel |
7516 		    kOSKextLogLoadFlag,
7517 		    "Kext %s - C++ instances; can't stop.",
7518 		    getIdentifierCString());
7519 		result = kOSKextReturnInUse;
7520 		goto finish;
7521 	}
7522 
7523 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7524 		OSKextLog(this,
7525 		    kOSKextLogErrorLevel |
7526 		    kOSKextLogLoadFlag,
7527 		    "Kext %s - has references (linkage or tracking object); "
7528 		    "can't stop.",
7529 		    getIdentifierCString());
7530 		result = kOSKextReturnInUse;
7531 		goto finish;
7532 	}
7533 
7534 	/* Note: If validateKextMapping fails on the stop & unload path,
7535 	 * we are in serious trouble and a kernel panic is likely whether
7536 	 * we stop & unload the kext or not.
7537 	 */
7538 	result = validateKextMapping(/* start? */ false);
7539 	if (result != kOSReturnSuccess) {
7540 		goto finish;
7541 	}
7542 
7543 	stopfunc = kmod_info->stop;
7544 	if (stopfunc) {
7545 		OSKextLog(this,
7546 		    kOSKextLogDetailLevel |
7547 		    kOSKextLogLoadFlag,
7548 		    "Kext %s calling module stop function.",
7549 		    getIdentifierCString());
7550 
7551 		flags.stopping = 1;
7552 
7553 		result = stopfunc(kmod_info, /* userData */ NULL);
7554 		if (result == KERN_SUCCESS) {
7555 			result = OSRuntimeFinalizeCPP(this);
7556 		}
7557 
7558 		flags.stopping = 0;
7559 
7560 		if (result == KERN_SUCCESS) {
7561 			flags.started = 0;
7562 
7563 			OSKextLog(this,
7564 			    kOSKextLogDetailLevel |
7565 			    kOSKextLogLoadFlag,
7566 			    "Kext %s is now stopped and ready to unload.",
7567 			    getIdentifierCString());
7568 		} else {
7569 			OSKextLog(this,
7570 			    kOSKextLogErrorLevel |
7571 			    kOSKextLogLoadFlag,
7572 			    "Kext %s did not stop (return code 0x%x).",
7573 			    getIdentifierCString(), result);
7574 			result = kOSKextReturnStartStopError;
7575 		}
7576 	}
7577 
7578 finish:
7579 	// Drop a log message so logd can update this kext's metadata
7580 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
7581 	return result;
7582 }
7583 
7584 /*********************************************************************
7585 *********************************************************************/
7586 OSReturn
7587 OSKext::unload(void)
7588 {
7589 	OSReturn        result = kOSReturnError;
7590 	unsigned int    index;
7591 	uint32_t        num_kmod_refs = 0;
7592 	OSKextAccount * freeAccount;
7593 	bool            in_fileset = false;
7594 
7595 	if (!sUnloadEnabled) {
7596 		OSKextLog(this,
7597 		    kOSKextLogErrorLevel |
7598 		    kOSKextLogLoadFlag,
7599 		    "Kext unloading is disabled (%s).",
7600 		    this->getIdentifierCString());
7601 
7602 		result = kOSKextReturnDisabled;
7603 		goto finish;
7604 	}
7605 
7606 	// cache this result so we don't need to access the kmod_info after
7607 	// it's been potentially free'd
7608 	in_fileset = isInFileset();
7609 
7610 	/* Refuse to unload if we have clients or instances. It is up to
7611 	 * the caller to make sure those aren't true.
7612 	 */
7613 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7614 		// xxx - Don't log under errors? this is more of an info thing
7615 		OSKextLog(this,
7616 		    kOSKextLogErrorLevel |
7617 		    kOSKextLogKextBookkeepingFlag,
7618 		    "Can't unload kext %s; outstanding references (linkage or tracking object).",
7619 		    getIdentifierCString());
7620 		result = kOSKextReturnInUse;
7621 		goto finish;
7622 	}
7623 
7624 	if (isDriverKit()) {
7625 		index = sLoadedKexts->getNextIndexOfObject(this, 0);
7626 		if (index != (unsigned int)-1) {
7627 			sLoadedDriverKitKexts->removeObject(index);
7628 			OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
7629 			loadTag = 0;
7630 		}
7631 	}
7632 
7633 	if (!isLoaded()) {
7634 		result = kOSReturnSuccess;
7635 		goto finish;
7636 	}
7637 
7638 	if (isKernelComponent()) {
7639 		result = kOSKextReturnInvalidArgument;
7640 		goto finish;
7641 	}
7642 
7643 	if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) {
7644 		OSKextLog(this,
7645 		    kOSKextLogErrorLevel |
7646 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
7647 		    "Can't unload kext %s; classes have instances:",
7648 		    getIdentifierCString());
7649 		reportOSMetaClassInstances(kOSKextLogErrorLevel |
7650 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
7651 		result = kOSKextReturnInUse;
7652 		goto finish;
7653 	}
7654 
7655 	/* Note that the kext is unloading before running any code that
7656 	 * might be in the kext (request callbacks, module stop function).
7657 	 * We will deny certain requests made against a kext in the process
7658 	 * of unloading.
7659 	 */
7660 	flags.unloading = 1;
7661 
7662 	/* Update the string describing the last kext to unload in case we panic.
7663 	 */
7664 	savePanicString(/* isLoading */ false);
7665 
7666 	if (isStarted()) {
7667 		result = stop();
7668 		if (result != KERN_SUCCESS) {
7669 			OSKextLog(this,
7670 			    kOSKextLogErrorLevel |
7671 			    kOSKextLogLoadFlag,
7672 			    "Kext %s can't unload - module stop returned 0x%x.",
7673 			    getIdentifierCString(), (unsigned)result);
7674 			result = kOSKextReturnStartStopError;
7675 			goto finish;
7676 		}
7677 	}
7678 
7679 	OSKextLog(this,
7680 	    kOSKextLogProgressLevel |
7681 	    kOSKextLogLoadFlag,
7682 	    "Kext %s unloading.",
7683 	    getIdentifierCString());
7684 
7685 	{
7686 		struct list_head *p;
7687 		struct list_head *prev;
7688 		struct list_head *next;
7689 		for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
7690 			OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
7691 			s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
7692 			prev = p->prev;
7693 			next = p->next;
7694 			prev->next = next;
7695 			next->prev = prev;
7696 			p->prev = p;
7697 			p->next = p;
7698 			IORecursiveLockWakeup(sKextLock, s, false);
7699 		}
7700 	}
7701 
7702 
7703 	/* Even if we don't call the stop function, we want to be sure we
7704 	 * have no OSMetaClass references before unloading the kext executable
7705 	 * from memory. OSMetaClasses may have pointers into the kext executable
7706 	 * and that would cause a panic on OSKext::free() when metaClasses is freed.
7707 	 */
7708 	if (metaClasses) {
7709 		metaClasses->flushCollection();
7710 	}
7711 	(void) OSRuntimeFinalizeCPP(this);
7712 
7713 	/* Remove the kext from the list of loaded kexts, patch the gap
7714 	 * in the kmod_info_t linked list, and reset "kmod" to point to the
7715 	 * last loaded kext that isn't the fake kernel kext (sKernelKext).
7716 	 */
7717 	index = sLoadedKexts->getNextIndexOfObject(this, 0);
7718 	if (index != (unsigned int)-1) {
7719 		sLoadedKexts->removeObject(index);
7720 
7721 		OSKext * nextKext = OSDynamicCast(OSKext,
7722 		    sLoadedKexts->getObject(index));
7723 
7724 		if (nextKext) {
7725 			if (index > 0) {
7726 				OSKext * gapKext = OSDynamicCast(OSKext,
7727 				    sLoadedKexts->getObject(index - 1));
7728 
7729 				nextKext->kmod_info->next = gapKext->kmod_info;
7730 			} else {         /* index == 0 */
7731 				nextKext->kmod_info->next = NULL;
7732 			}
7733 		}
7734 
7735 		OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
7736 		if (lastKext && !lastKext->isKernel()) {
7737 			kmod = lastKext->kmod_info;
7738 		} else {
7739 			kmod = NULL;         // clear the global kmod variable
7740 		}
7741 	}
7742 
7743 	/* Clear out the kmod references that we're keeping for compatibility
7744 	 * with current panic backtrace code & kgmacros.
7745 	 * xxx - will want to update those bits sometime and remove this.
7746 	 */
7747 	num_kmod_refs = getNumDependencies();
7748 	if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
7749 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
7750 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
7751 			ref->info->reference_count--;
7752 		}
7753 		kfree(kmod_info->reference_list,
7754 		    num_kmod_refs * sizeof(kmod_reference_t));
7755 	}
7756 
7757 #if CONFIG_DTRACE
7758 	unregisterWithDTrace();
7759 #endif /* CONFIG_DTRACE */
7760 
7761 	notifyKextUnloadObservers(this);
7762 
7763 	freeAccount = NULL;
7764 	IOSimpleLockLock(sKextAccountsLock);
7765 	account->kext = NULL;
7766 	if (account->site.tag) {
7767 		account->site.flags |= VM_TAG_UNLOAD;
7768 	} else {
7769 		freeAccount = account;
7770 	}
7771 	IOSimpleLockUnlock(sKextAccountsLock);
7772 	if (freeAccount) {
7773 		IODelete(freeAccount, OSKextAccount, 1);
7774 	}
7775 
7776 	/* Unwire and free the linked executable.
7777 	 */
7778 	if (linkedExecutable) {
7779 #if KASAN
7780 		kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
7781 #endif
7782 
7783 #if VM_MAPPED_KEXTS
7784 		if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) {
7785 			kernel_segment_command_t *seg = NULL;
7786 			vm_map_t kext_map = kext_get_vm_map(kmod_info);
7787 
7788 			if (!kext_map) {
7789 				OSKextLog(this,
7790 				    kOSKextLogErrorLevel |
7791 				    kOSKextLogLoadFlag,
7792 				    "Failed to free kext %s; couldn't find the kext map.",
7793 				    getIdentifierCString());
7794 				result = kOSKextReturnInternalError;
7795 				goto finish;
7796 			}
7797 
7798 			OSKextLog(this,
7799 			    kOSKextLogProgressLevel |
7800 			    kOSKextLogLoadFlag,
7801 			    "Kext %s unwiring and unmapping linked executable.",
7802 			    getIdentifierCString());
7803 
7804 			seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7805 			while (seg) {
7806 				if (segmentShouldBeWired(seg)) {
7807 					vm_map_offset_t start_wire = trunc_page(seg->vmaddr);
7808 					vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize);
7809 
7810 					result = vm_map_unwire(kext_map, start_wire,
7811 					    end_wire, FALSE);
7812 					if (result != KERN_SUCCESS) {
7813 						OSKextLog(this,
7814 						    kOSKextLogErrorLevel |
7815 						    kOSKextLogLoadFlag,
7816 						    "Failed to unwire kext %s.",
7817 						    getIdentifierCString());
7818 						result = kOSKextReturnInternalError;
7819 						goto finish;
7820 					}
7821 				}
7822 
7823 				seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7824 			}
7825 #if defined(__x86_64__) || defined(__i386__)
7826 			if (in_fileset && flags.resetSegmentsFromVnode) {
7827 				IORecursiveLockLock(sKextLock);
7828 				resetKCFileSetSegments();
7829 				IORecursiveLockUnlock(sKextLock);
7830 			}
7831 #endif // (__x86_64__) || defined(__i386__)
7832 		}
7833 #endif /* VM_MAPPED_KEXTS */
7834 		if (flags.resetSegmentsFromImmutableCopy) {
7835 			result = resetMutableSegments();
7836 			if (result != kOSReturnSuccess) {
7837 				OSKextLog(this,
7838 				    kOSKextLogErrorLevel |
7839 				    kOSKextLogLoadFlag,
7840 				    "Failed to reset kext %s.",
7841 				    getIdentifierCString());
7842 				result = kOSKextReturnInternalError;
7843 				goto finish;
7844 			}
7845 		}
7846 		if (kc_type == KCKindUnknown) {
7847 			linkedExecutable.reset();
7848 		}
7849 	}
7850 
7851 	/* An interface kext has a fake kmod_info that was allocated,
7852 	 * so we have to free it.
7853 	 */
7854 	if (isInterface()) {
7855 		kfree(kmod_info, sizeof(kmod_info_t));
7856 		kmod_info = NULL;
7857 	}
7858 
7859 	if (!in_fileset) {
7860 		kmod_info = NULL;
7861 	}
7862 
7863 	flags.loaded = false;
7864 	flushDependencies();
7865 
7866 	/* save a copy of the bundle ID for us to check when deciding to
7867 	 * rebuild the kernel cache file.  If a kext was already in the kernel
7868 	 * cache and unloaded then later loaded we do not need to rebuild the
7869 	 * kernel cache.  9055303
7870 	 */
7871 	if (isPrelinked()) {
7872 		if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) {
7873 			IORecursiveLockLock(sKextLock);
7874 			if (sUnloadedPrelinkedKexts) {
7875 				sUnloadedPrelinkedKexts->setObject(bundleID.get());
7876 			}
7877 			IORecursiveLockUnlock(sKextLock);
7878 		}
7879 	}
7880 
7881 	OSKextLog(this,
7882 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
7883 	    "Kext %s unloaded.", getIdentifierCString());
7884 
7885 	queueKextNotification(kKextRequestPredicateUnloadNotification,
7886 	    OSDynamicCast(OSString, bundleID.get()));
7887 
7888 finish:
7889 	OSKext::saveLoadedKextPanicList();
7890 	OSKext::updateLoadedKextSummaries();
7891 
7892 	flags.unloading = 0;
7893 	return result;
7894 }
7895 
7896 /*********************************************************************
7897 * Assumes sKextLock is held.
7898 *********************************************************************/
7899 /* static */
7900 OSReturn
7901 OSKext::queueKextNotification(
7902 	const char * notificationName,
7903 	OSString   * kextIdentifier)
7904 {
7905 	OSReturn          result               = kOSReturnError;
7906 	OSSharedPtr<OSDictionary>    loadRequest;
7907 
7908 	if (!kextIdentifier) {
7909 		result = kOSKextReturnInvalidArgument;
7910 		goto finish;
7911 	}
7912 
7913 	/* Create a new request unless one is already sitting
7914 	 * in sKernelRequests for this bundle identifier
7915 	 */
7916 	result = _OSKextCreateRequest(notificationName, loadRequest);
7917 	if (result != kOSReturnSuccess) {
7918 		goto finish;
7919 	}
7920 	if (!_OSKextSetRequestArgument(loadRequest.get(),
7921 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
7922 		result = kOSKextReturnNoMemory;
7923 		goto finish;
7924 	}
7925 	if (!sKernelRequests->setObject(loadRequest.get())) {
7926 		result = kOSKextReturnNoMemory;
7927 		goto finish;
7928 	}
7929 
7930 	/* We might want to only queue the notification if the IOKit daemon is active,
7931 	 * but that wouldn't work for embedded. Note that we don't care if
7932 	 * the ping immediately succeeds here so don't do anything with the
7933 	 * result of this call.
7934 	 */
7935 	OSKext::pingIOKitDaemon();
7936 
7937 	result = kOSReturnSuccess;
7938 
7939 finish:
7940 	return result;
7941 }
7942 
7943 
7944 #if CONFIG_KXLD
7945 /*********************************************************************
7946 *********************************************************************/
7947 static void
7948 _OSKextConsiderDestroyingLinkContext(
7949 	__unused thread_call_param_t p0,
7950 	__unused thread_call_param_t p1)
7951 {
7952 	/* Take multiple locks in the correct order.
7953 	 */
7954 	IORecursiveLockLock(sKextLock);
7955 	IORecursiveLockLock(sKextInnerLock);
7956 
7957 	/* The first time we destroy the kxldContext is in the first
7958 	 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
7959 	 * before calling this function. Thereafter any call to this function
7960 	 * will actually destroy the context.
7961 	 */
7962 	if (sConsiderUnloadsCalled && sKxldContext) {
7963 		kxld_destroy_context(sKxldContext);
7964 		sKxldContext = NULL;
7965 	}
7966 
7967 	/* Free the thread_call that was allocated to execute this function.
7968 	 */
7969 	if (sDestroyLinkContextThread) {
7970 		if (!thread_call_free(sDestroyLinkContextThread)) {
7971 			OSKextLog(/* kext */ NULL,
7972 			    kOSKextLogErrorLevel |
7973 			    kOSKextLogGeneralFlag,
7974 			    "thread_call_free() failed for kext link context.");
7975 		}
7976 		sDestroyLinkContextThread = NULL;
7977 	}
7978 
7979 	IORecursiveLockUnlock(sKextInnerLock);
7980 	IORecursiveLockUnlock(sKextLock);
7981 
7982 	return;
7983 }
7984 
7985 /*********************************************************************
7986 * Destroying the kxldContext requires checking variables under both
7987 * sKextInnerLock and sKextLock, so we do it on a separate thread
7988 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
7989 * call relationship.
7990 *
7991 * This function must be invoked with sKextInnerLock held.
7992 * Do not call any function that takes sKextLock here!
7993 *********************************************************************/
7994 /* static */
7995 void
7996 OSKext::considerDestroyingLinkContext(void)
7997 {
7998 	IORecursiveLockLock(sKextInnerLock);
7999 
8000 	/* If we have already queued a thread to destroy the link context,
8001 	 * don't bother resetting; that thread will take care of it.
8002 	 */
8003 	if (sDestroyLinkContextThread) {
8004 		goto finish;
8005 	}
8006 
8007 	/* The function to be invoked in the thread will deallocate
8008 	 * this thread_call, so don't share it around.
8009 	 */
8010 	sDestroyLinkContextThread = thread_call_allocate(
8011 		&_OSKextConsiderDestroyingLinkContext, NULL);
8012 	if (!sDestroyLinkContextThread) {
8013 		OSKextLog(/* kext */ NULL,
8014 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
8015 		    "Can't create thread to destroy kext link context.");
8016 		goto finish;
8017 	}
8018 
8019 	thread_call_enter(sDestroyLinkContextThread);
8020 
8021 finish:
8022 	IORecursiveLockUnlock(sKextInnerLock);
8023 	return;
8024 }
8025 
8026 #else // !CONFIG_KXLD
8027 
8028 /* static */
8029 void
8030 OSKext::considerDestroyingLinkContext(void)
8031 {
8032 	return;
8033 }
8034 
8035 #endif // CONFIG_KXLD
8036 
8037 #if PRAGMA_MARK
8038 #pragma mark Autounload
8039 #endif
8040 /*********************************************************************
8041 * This is a static method because the kext will be deallocated if it
8042 * does unload!
8043 *********************************************************************/
8044 /* static */
8045 OSReturn
8046 OSKext::autounloadKext(OSKext * aKext)
8047 {
8048 	OSReturn result = kOSKextReturnInUse;
8049 
8050 #if NO_KEXTD
8051 	/*
8052 	 * Do not unload prelinked kexts on platforms that do not have an
8053 	 * IOKit daemon as there is no way to reload the kext or restart
8054 	 * matching.
8055 	 */
8056 	if (aKext->isPrelinked()) {
8057 		goto finish;
8058 	}
8059 #endif /* defined(__x86_64__) */
8060 
8061 	/* Check for external references to this kext (usu. dependents),
8062 	 * instances of defined classes (or classes derived from them),
8063 	 * outstanding requests.
8064 	 */
8065 	if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
8066 	    !aKext->flags.autounloadEnabled ||
8067 	    aKext->isKernelComponent()) {
8068 		goto finish;
8069 	}
8070 
8071 	/* Skip a delay-autounload kext, once.
8072 	 */
8073 	if (aKext->flags.delayAutounload) {
8074 		OSKextLog(aKext,
8075 		    kOSKextLogProgressLevel |
8076 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8077 		    "Kext %s has delayed autounload set; skipping and clearing flag.",
8078 		    aKext->getIdentifierCString());
8079 		aKext->flags.delayAutounload = 0;
8080 		goto finish;
8081 	}
8082 
8083 	if (aKext->hasOSMetaClassInstances() ||
8084 	    aKext->countRequestCallbacks()) {
8085 		goto finish;
8086 	}
8087 
8088 	result = OSKext::removeKext(aKext);
8089 
8090 finish:
8091 	return result;
8092 }
8093 
8094 /*********************************************************************
8095 *********************************************************************/
8096 void
8097 _OSKextConsiderUnloads(
8098 	__unused thread_call_param_t p0,
8099 	__unused thread_call_param_t p1)
8100 {
8101 	bool         didUnload = false;
8102 	unsigned int count, i;
8103 
8104 	/* Take multiple locks in the correct order
8105 	 * (note also sKextSummaries lock further down).
8106 	 */
8107 	IORecursiveLockLock(sKextLock);
8108 	IORecursiveLockLock(sKextInnerLock);
8109 
8110 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
8111 
8112 	/* If the system is powering down, don't try to unload anything.
8113 	 */
8114 	if (sSystemSleep) {
8115 		goto finish;
8116 	}
8117 
8118 	OSKextLog(/* kext */ NULL,
8119 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8120 	    "Checking for unused kexts to autounload.");
8121 
8122 	/*****
8123 	 * Remove any request callbacks marked as stale,
8124 	 * and mark as stale any currently in flight.
8125 	 */
8126 	count = sRequestCallbackRecords->getCount();
8127 	if (count) {
8128 		i = count - 1;
8129 		do {
8130 			OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
8131 			    sRequestCallbackRecords->getObject(i));
8132 			OSBoolean * stale = OSDynamicCast(OSBoolean,
8133 			    callbackRecord->getObject(kKextRequestStaleKey));
8134 
8135 			if (stale == kOSBooleanTrue) {
8136 				OSKext::invokeRequestCallback(callbackRecord,
8137 				    kOSKextReturnTimeout);
8138 			} else {
8139 				callbackRecord->setObject(kKextRequestStaleKey,
8140 				    kOSBooleanTrue);
8141 			}
8142 		} while (i--);
8143 	}
8144 
8145 	/*****
8146 	 * Make multiple passes through the array of loaded kexts until
8147 	 * we don't unload any. This handles unwinding of dependency
8148 	 * chains. We have to go *backwards* through the array because
8149 	 * kexts are removed from it when unloaded, and we cannot make
8150 	 * a copy or we'll mess up the retain counts we rely on to
8151 	 * check whether a kext will unload. If only we could have
8152 	 * nonretaining collections like CF has....
8153 	 */
8154 	do {
8155 		didUnload = false;
8156 
8157 		count = sLoadedKexts->getCount();
8158 		if (count) {
8159 			i = count - 1;
8160 			do {
8161 				OSKext * thisKext = OSDynamicCast(OSKext,
8162 				    sLoadedKexts->getObject(i));
8163 				didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
8164 			} while (i--);
8165 		}
8166 	} while (didUnload);
8167 
8168 finish:
8169 	sConsiderUnloadsPending = false;
8170 	sConsiderUnloadsExecuted = true;
8171 
8172 	(void) OSKext::considerRebuildOfPrelinkedKernel();
8173 
8174 	IORecursiveLockUnlock(sKextInnerLock);
8175 	IORecursiveLockUnlock(sKextLock);
8176 
8177 	return;
8178 }
8179 
8180 /*********************************************************************
8181 * Do not call any function that takes sKextLock here!
8182 *********************************************************************/
8183 void
8184 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
8185 {
8186 	AbsoluteTime when;
8187 
8188 	IORecursiveLockLock(sKextInnerLock);
8189 
8190 	if (!sUnloadCallout) {
8191 		sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
8192 	}
8193 
8194 	/* we only reset delay value for unloading if we already have something
8195 	 * pending.  rescheduleOnlyFlag should not start the count down.
8196 	 */
8197 	if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
8198 		goto finish;
8199 	}
8200 
8201 	thread_call_cancel(sUnloadCallout);
8202 	if (OSKext::getAutounloadEnabled() && !sSystemSleep
8203 #if !NO_KEXTD
8204 	    && sIOKitDaemonActive
8205 #endif
8206 	    ) {
8207 		clock_interval_to_deadline(sConsiderUnloadDelay,
8208 		    1000 * 1000 * 1000, &when);
8209 
8210 		OSKextLog(/* kext */ NULL,
8211 		    kOSKextLogProgressLevel |
8212 		    kOSKextLogLoadFlag,
8213 		    "%scheduling %sscan for unused kexts in %lu seconds.",
8214 		    sConsiderUnloadsPending ? "Res" : "S",
8215 		    sConsiderUnloadsCalled ? "" : "initial ",
8216 		    (unsigned long)sConsiderUnloadDelay);
8217 
8218 		sConsiderUnloadsPending = true;
8219 		thread_call_enter_delayed(sUnloadCallout, when);
8220 	}
8221 
8222 finish:
8223 	/* The kxld context should be reused throughout boot.  We mark the end of
8224 	 * period as the first time considerUnloads() is called, and we destroy
8225 	 * the first kxld context in that function.  Afterwards, it will be
8226 	 * destroyed in flushNonloadedKexts.
8227 	 */
8228 	if (!sConsiderUnloadsCalled) {
8229 		sConsiderUnloadsCalled = true;
8230 		OSKext::considerDestroyingLinkContext();
8231 	}
8232 
8233 	IORecursiveLockUnlock(sKextInnerLock);
8234 	return;
8235 }
8236 
8237 /*********************************************************************
8238 * Do not call any function that takes sKextLock here!
8239 *********************************************************************/
8240 extern "C" {
8241 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
8242 IOReturn
8243 OSKextSystemSleepOrWake(UInt32 messageType)
8244 {
8245 	IORecursiveLockLock(sKextInnerLock);
8246 
8247 	/* If the system is going to sleep, cancel the reaper thread timer,
8248 	 * and note that we're in a sleep state in case it just fired but hasn't
8249 	 * taken the lock yet. If we are coming back from sleep, just
8250 	 * clear the sleep flag; IOService's normal operation will cause
8251 	 * unloads to be considered soon enough.
8252 	 */
8253 	if (messageType == kIOMessageSystemWillSleep) {
8254 		if (sUnloadCallout) {
8255 			thread_call_cancel(sUnloadCallout);
8256 		}
8257 		sSystemSleep = true;
8258 		AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
8259 	} else if (messageType == kIOMessageSystemHasPoweredOn) {
8260 		sSystemSleep = false;
8261 		clock_get_uptime(&sLastWakeTime);
8262 	}
8263 	IORecursiveLockUnlock(sKextInnerLock);
8264 
8265 	return kIOReturnSuccess;
8266 }
8267 };
8268 
8269 
8270 #if PRAGMA_MARK
8271 #pragma mark Prelinked Kernel
8272 #endif
8273 
8274 #ifdef CONFIG_KXLD
8275 /*********************************************************************
8276 * Do not access sConsiderUnloads... variables other than
8277 * sConsiderUnloadsExecuted in this function. They are guarded by a
8278 * different lock.
8279 *********************************************************************/
8280 /* static */
8281 void
8282 OSKext::considerRebuildOfPrelinkedKernel(void)
8283 {
8284 	static bool     requestedPrelink        = false;
8285 	OSReturn        checkResult             = kOSReturnError;
8286 	OSSharedPtr<OSDictionary>         prelinkRequest;
8287 	OSSharedPtr<OSCollectionIterator> kextIterator;
8288 	const OSSymbol * thisID                 = NULL;        // do not release
8289 	bool            doRebuild               = false;
8290 	AbsoluteTime    my_abstime;
8291 	UInt64          my_ns;
8292 	SInt32          delta_secs;
8293 
8294 	/* Only one auto rebuild per boot and only on boot from prelinked kernel */
8295 	if (requestedPrelink || !sPrelinkBoot) {
8296 		return;
8297 	}
8298 
8299 	/* no direct return from this point */
8300 	IORecursiveLockLock(sKextLock);
8301 
8302 	/* We need to wait for the IOKit daemon to get up and running with unloads already done
8303 	 * and any new startup kexts loaded.
8304 	 */
8305 	if (!sConsiderUnloadsExecuted ||
8306 	    !sDeferredLoadSucceeded) {
8307 		goto finish;
8308 	}
8309 
8310 	/* we really only care about boot / system start up related kexts so bail
8311 	 * if we're here after REBUILD_MAX_TIME.
8312 	 */
8313 	if (!_OSKextInPrelinkRebuildWindow()) {
8314 		OSKextLog(/* kext */ NULL,
8315 		    kOSKextLogArchiveFlag,
8316 		    "%s prebuild rebuild has expired",
8317 		    __FUNCTION__);
8318 		requestedPrelink = true;
8319 		goto finish;
8320 	}
8321 
8322 	/* we do not want to trigger a rebuild if we get here too close to waking
8323 	 * up.  (see radar 10233768)
8324 	 */
8325 	IORecursiveLockLock(sKextInnerLock);
8326 
8327 	clock_get_uptime(&my_abstime);
8328 	delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
8329 	if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
8330 		SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
8331 		absolutetime_to_nanoseconds(my_abstime, &my_ns);
8332 		delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
8333 	}
8334 	IORecursiveLockUnlock(sKextInnerLock);
8335 
8336 	if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
8337 		/* too close to time of last wake from sleep */
8338 		goto finish;
8339 	}
8340 	requestedPrelink = true;
8341 
8342 	/* Now it's time to see if we have a reason to rebuild.  We may have done
8343 	 * some loads and unloads but the kernel cache didn't actually change.
8344 	 * We will rebuild if any kext is not marked prelinked AND is not in our
8345 	 * list of prelinked kexts that got unloaded.  (see radar 9055303)
8346 	 */
8347 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
8348 	if (!kextIterator) {
8349 		goto finish;
8350 	}
8351 
8352 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
8353 		OSKext *    thisKext;        // do not release
8354 
8355 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
8356 		if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
8357 			continue;
8358 		}
8359 
8360 		if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) {
8361 			continue;
8362 		}
8363 		/* kext is loaded and was not in current kernel cache so let's rebuild
8364 		 */
8365 		doRebuild = true;
8366 		OSKextLog(/* kext */ NULL,
8367 		    kOSKextLogArchiveFlag,
8368 		    "considerRebuildOfPrelinkedKernel %s triggered rebuild",
8369 		    thisKext->bundleID->getCStringNoCopy());
8370 		break;
8371 	}
8372 	sUnloadedPrelinkedKexts->flushCollection();
8373 
8374 	if (!doRebuild) {
8375 		goto finish;
8376 	}
8377 
8378 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
8379 	    prelinkRequest);
8380 	if (checkResult != kOSReturnSuccess) {
8381 		goto finish;
8382 	}
8383 
8384 	if (!sKernelRequests->setObject(prelinkRequest.get())) {
8385 		goto finish;
8386 	}
8387 
8388 	OSKext::pingIOKitDaemon();
8389 
8390 finish:
8391 	IORecursiveLockUnlock(sKextLock);
8392 
8393 	return;
8394 }
8395 
8396 #else /* !CONFIG_KXLD */
8397 
8398 void
8399 OSKext::considerRebuildOfPrelinkedKernel(void)
8400 {
8401 	/* in a non-dynamic kext loading world, there is never a reason to rebuild */
8402 	return;
8403 }
8404 
8405 #endif /* CONFIG_KXLD */
8406 
8407 #if PRAGMA_MARK
8408 #pragma mark Dependencies
8409 #endif
8410 /*********************************************************************
8411 *********************************************************************/
8412 bool
8413 OSKext::resolveDependencies(
8414 	OSArray * loopStack)
8415 {
8416 	bool                   result                   = false;
8417 	OSSharedPtr<OSArray>   localLoopStack;
8418 	bool                   addedToLoopStack         = false;
8419 	OSDictionary         * libraries                = NULL;        // do not release
8420 	OSSharedPtr<OSCollectionIterator> libraryIterator;
8421 	OSString             * libraryID                = NULL;        // do not release
8422 	OSKext               * libraryKext              = NULL;        // do not release
8423 	bool                   hasRawKernelDependency   = false;
8424 	bool                   hasKernelDependency      = false;
8425 	bool                   hasKPIDependency         = false;
8426 	bool                   hasPrivateKPIDependency  = false;
8427 	unsigned int           count;
8428 
8429 #if CONFIG_KXLD
8430 	OSString             * infoString               = NULL;        // do not release
8431 	OSString             * readableString           = NULL;        // do not release
8432 #endif // CONFIG_KXLD
8433 
8434 	/* A kernel component will automatically have this flag set,
8435 	 * and a loaded kext should also have it set (as should all its
8436 	 * loaded dependencies).
8437 	 */
8438 	if (flags.hasAllDependencies) {
8439 		result = true;
8440 		goto finish;
8441 	}
8442 
8443 	/* Check for loops in the dependency graph.
8444 	 */
8445 	if (loopStack) {
8446 		if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
8447 			OSKextLog(this,
8448 			    kOSKextLogErrorLevel |
8449 			    kOSKextLogDependenciesFlag,
8450 			    "Kext %s has a dependency loop; can't resolve dependencies.",
8451 			    getIdentifierCString());
8452 			goto finish;
8453 		}
8454 	} else {
8455 		OSKextLog(this,
8456 		    kOSKextLogStepLevel |
8457 		    kOSKextLogDependenciesFlag,
8458 		    "Kext %s resolving dependencies.",
8459 		    getIdentifierCString());
8460 
8461 		localLoopStack = OSArray::withCapacity(6);         // any small capacity will do
8462 		if (!localLoopStack) {
8463 			OSKextLog(this,
8464 			    kOSKextLogErrorLevel |
8465 			    kOSKextLogDependenciesFlag,
8466 			    "Kext %s can't create bookkeeping stack to resolve dependencies.",
8467 			    getIdentifierCString());
8468 			goto finish;
8469 		}
8470 		loopStack = localLoopStack.get();
8471 	}
8472 	if (!loopStack->setObject(this)) {
8473 		OSKextLog(this,
8474 		    kOSKextLogErrorLevel |
8475 		    kOSKextLogDependenciesFlag,
8476 		    "Kext %s - internal error resolving dependencies.",
8477 		    getIdentifierCString());
8478 		goto finish;
8479 	}
8480 	addedToLoopStack = true;
8481 
8482 	/* Purge any existing kexts in the dependency list and start over.
8483 	 */
8484 	flushDependencies();
8485 	if (dependencies) {
8486 		OSKextLog(this,
8487 		    kOSKextLogErrorLevel |
8488 		    kOSKextLogDependenciesFlag,
8489 		    "Kext %s - internal error resolving dependencies.",
8490 		    getIdentifierCString());
8491 	}
8492 
8493 	libraries = OSDynamicCast(OSDictionary,
8494 	    getPropertyForHostArch(kOSBundleLibrariesKey));
8495 	if (libraries == NULL || libraries->getCount() == 0) {
8496 		OSKextLog(this,
8497 		    kOSKextLogErrorLevel |
8498 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8499 		    "Kext %s - can't resolve dependencies; %s missing/invalid type.",
8500 		    getIdentifierCString(), kOSBundleLibrariesKey);
8501 		goto finish;
8502 	}
8503 
8504 	/* Make a new array to hold the dependencies (flush freed the old one).
8505 	 */
8506 	dependencies = OSArray::withCapacity(libraries->getCount());
8507 	if (!dependencies) {
8508 		OSKextLog(this,
8509 		    kOSKextLogErrorLevel |
8510 		    kOSKextLogDependenciesFlag,
8511 		    "Kext %s - can't allocate dependencies array.",
8512 		    getIdentifierCString());
8513 		goto finish;
8514 	}
8515 
8516 	// xxx - compat: We used to add an implicit dependency on kernel 6.0
8517 	// xxx - compat: if none were declared.
8518 
8519 	libraryIterator = OSCollectionIterator::withCollection(libraries);
8520 	if (!libraryIterator) {
8521 		OSKextLog(this,
8522 		    kOSKextLogErrorLevel |
8523 		    kOSKextLogDependenciesFlag,
8524 		    "Kext %s - can't allocate dependencies iterator.",
8525 		    getIdentifierCString());
8526 		goto finish;
8527 	}
8528 
8529 	while ((libraryID = OSDynamicCast(OSString,
8530 	    libraryIterator->getNextObject()))) {
8531 		const char * library_id = libraryID->getCStringNoCopy();
8532 
8533 		OSString * libraryVersion = OSDynamicCast(OSString,
8534 		    libraries->getObject(libraryID));
8535 		if (libraryVersion == NULL) {
8536 			OSKextLog(this,
8537 			    kOSKextLogErrorLevel |
8538 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8539 			    "Kext %s - illegal type in OSBundleLibraries.",
8540 			    getIdentifierCString());
8541 			goto finish;
8542 		}
8543 
8544 		OSKextVersion libraryVers =
8545 		    OSKextParseVersionString(libraryVersion->getCStringNoCopy());
8546 		if (libraryVers == -1) {
8547 			OSKextLog(this,
8548 			    kOSKextLogErrorLevel |
8549 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8550 			    "Kext %s - invalid library version %s.",
8551 			    getIdentifierCString(),
8552 			    libraryVersion->getCStringNoCopy());
8553 			goto finish;
8554 		}
8555 
8556 		libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
8557 		if (libraryKext == NULL) {
8558 			OSKextLog(this,
8559 			    kOSKextLogErrorLevel |
8560 			    kOSKextLogDependenciesFlag,
8561 			    "Kext %s - library kext %s not found.",
8562 			    getIdentifierCString(), library_id);
8563 			goto finish;
8564 		}
8565 
8566 		if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
8567 			OSKextLog(this,
8568 			    kOSKextLogErrorLevel |
8569 			    kOSKextLogDependenciesFlag,
8570 			    "Kext %s - library kext %s not compatible "
8571 			    "with requested version %s.",
8572 			    getIdentifierCString(), library_id,
8573 			    libraryVersion->getCStringNoCopy());
8574 			goto finish;
8575 		}
8576 
8577 		/* If a nonprelinked library somehow got into the mix for a
8578 		 * prelinked kext, at any point in the chain, we must fail
8579 		 * because the prelinked relocs for the library will be all wrong.
8580 		 */
8581 		if (this->isPrelinked() &&
8582 		    libraryKext->declaresExecutable() &&
8583 		    !libraryKext->isPrelinked()) {
8584 			OSKextLog(this,
8585 			    kOSKextLogErrorLevel |
8586 			    kOSKextLogDependenciesFlag,
8587 			    "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
8588 			    getIdentifierCString(), library_id,
8589 			    libraryVersion->getCStringNoCopy());
8590 			goto finish;
8591 		}
8592 
8593 		if (!libraryKext->resolveDependencies(loopStack)) {
8594 			goto finish;
8595 		}
8596 
8597 		/* Add the library directly only if it has an executable to link.
8598 		 * Otherwise it's just used to collect other dependencies, so put
8599 		 * *its* dependencies on the list for this kext.
8600 		 */
8601 		// xxx - We are losing info here; would like to make fake entries or
8602 		// xxx - keep these in the dependency graph for loaded kexts.
8603 		// xxx - I really want to make kernel components not a special case!
8604 		if (libraryKext->declaresExecutable() ||
8605 		    libraryKext->isInterface()) {
8606 			if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
8607 				dependencies->setObject(libraryKext);
8608 
8609 				OSKextLog(this,
8610 				    kOSKextLogDetailLevel |
8611 				    kOSKextLogDependenciesFlag,
8612 				    "Kext %s added dependency %s.",
8613 				    getIdentifierCString(),
8614 				    libraryKext->getIdentifierCString());
8615 			}
8616 		} else {
8617 			int       numLibDependencies  = libraryKext->getNumDependencies();
8618 			OSArray * libraryDependencies = libraryKext->getDependencies();
8619 			int       index;
8620 
8621 			if (numLibDependencies) {
8622 				// xxx - this msg level should be 1 lower than the per-kext one
8623 				OSKextLog(this,
8624 				    kOSKextLogDetailLevel |
8625 				    kOSKextLogDependenciesFlag,
8626 				    "Kext %s pulling %d dependencies from codeless library %s.",
8627 				    getIdentifierCString(),
8628 				    numLibDependencies,
8629 				    libraryKext->getIdentifierCString());
8630 			}
8631 			for (index = 0; index < numLibDependencies; index++) {
8632 				OSKext * thisLibDependency = OSDynamicCast(OSKext,
8633 				    libraryDependencies->getObject(index));
8634 				if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
8635 					dependencies->setObject(thisLibDependency);
8636 					OSKextLog(this,
8637 					    kOSKextLogDetailLevel |
8638 					    kOSKextLogDependenciesFlag,
8639 					    "Kext %s added dependency %s from codeless library %s.",
8640 					    getIdentifierCString(),
8641 					    thisLibDependency->getIdentifierCString(),
8642 					    libraryKext->getIdentifierCString());
8643 				}
8644 			}
8645 		}
8646 
8647 		if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
8648 		    0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
8649 			hasRawKernelDependency = true;
8650 		} else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
8651 			hasKernelDependency = true;
8652 		} else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
8653 			hasKPIDependency = true;
8654 			if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
8655 				hasPrivateKPIDependency = true;
8656 			}
8657 		}
8658 	}
8659 
8660 	if (hasRawKernelDependency) {
8661 		OSKextLog(this,
8662 		    kOSKextLogErrorLevel |
8663 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8664 		    "Error - kext %s declares a dependency on %s, which is not permitted.",
8665 		    getIdentifierCString(), KERNEL_LIB);
8666 		goto finish;
8667 	}
8668 #if __LP64__
8669 	if (hasKernelDependency) {
8670 		OSKextLog(this,
8671 		    kOSKextLogErrorLevel |
8672 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8673 		    "Error - kext %s declares %s dependencies. "
8674 		    "Only %s* dependencies are supported for 64-bit kexts.",
8675 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
8676 		goto finish;
8677 	}
8678 	if (!hasKPIDependency) {
8679 		OSKextLog(this,
8680 		    kOSKextLogWarningLevel |
8681 		    kOSKextLogDependenciesFlag,
8682 		    "Warning - kext %s declares no %s* dependencies. "
8683 		    "If it uses any KPIs, the link may fail with undefined symbols.",
8684 		    getIdentifierCString(), KPI_LIB_PREFIX);
8685 	}
8686 #else /* __LP64__ */
8687 	// xxx - will change to flatly disallow "kernel" dependencies at some point
8688 	// xxx - is it invalid to do both "com.apple.kernel" and any
8689 	// xxx - "com.apple.kernel.*"?
8690 
8691 	if (hasKernelDependency && hasKPIDependency) {
8692 		OSKextLog(this,
8693 		    kOSKextLogWarningLevel |
8694 		    kOSKextLogDependenciesFlag,
8695 		    "Warning - kext %s has immediate dependencies on both "
8696 		    "%s* and %s* components; use only one style.",
8697 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
8698 	}
8699 
8700 	if (!hasKernelDependency && !hasKPIDependency) {
8701 		// xxx - do we want to use validation flag for these too?
8702 		OSKextLog(this,
8703 		    kOSKextLogWarningLevel |
8704 		    kOSKextLogDependenciesFlag,
8705 		    "Warning - %s declares no kernel dependencies; using %s.",
8706 		    getIdentifierCString(), KERNEL6_LIB);
8707 		OSKext * kernelKext = OSDynamicCast(OSKext,
8708 		    sKextsByID->getObject(KERNEL6_LIB));
8709 		if (kernelKext) {
8710 			dependencies->setObject(kernelKext);
8711 		} else {
8712 			OSKextLog(this,
8713 			    kOSKextLogErrorLevel |
8714 			    kOSKextLogDependenciesFlag,
8715 			    "Error - Library %s not found for %s.",
8716 			    KERNEL6_LIB, getIdentifierCString());
8717 		}
8718 	}
8719 
8720 	/* If the kext doesn't have a raw kernel or KPI dependency, then add all of
8721 	 * its indirect dependencies to simulate old-style linking.  XXX - Should
8722 	 * check for duplicates.
8723 	 */
8724 	if (!hasKPIDependency) {
8725 		unsigned int i;
8726 
8727 		flags.hasBleedthrough = true;
8728 
8729 		count = getNumDependencies();
8730 
8731 		/* We add to the dependencies array in this loop, but do not iterate
8732 		 * past its original count.
8733 		 */
8734 		for (i = 0; i < count; i++) {
8735 			OSKext * dependencyKext = OSDynamicCast(OSKext,
8736 			    dependencies->getObject(i));
8737 			dependencyKext->addBleedthroughDependencies(dependencies.get());
8738 		}
8739 	}
8740 #endif /* __LP64__ */
8741 
8742 #if CONFIG_KXLD
8743 	/*
8744 	 * If we're not dynamically linking kexts, then we don't need to check
8745 	 * copyright strings. The linker in user space has already done this.
8746 	 */
8747 	if (hasPrivateKPIDependency) {
8748 		bool hasApplePrefix = false;
8749 		bool infoCopyrightIsValid = false;
8750 		bool readableCopyrightIsValid = false;
8751 
8752 		hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
8753 		    APPLE_KEXT_PREFIX);
8754 
8755 		infoString = OSDynamicCast(OSString,
8756 		    getPropertyForHostArch("CFBundleGetInfoString"));
8757 		if (infoString) {
8758 			infoCopyrightIsValid =
8759 			    kxld_validate_copyright_string(infoString->getCStringNoCopy());
8760 		}
8761 
8762 		readableString = OSDynamicCast(OSString,
8763 		    getPropertyForHostArch("NSHumanReadableCopyright"));
8764 		if (readableString) {
8765 			readableCopyrightIsValid =
8766 			    kxld_validate_copyright_string(readableString->getCStringNoCopy());
8767 		}
8768 
8769 		if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
8770 			OSKextLog(this,
8771 			    kOSKextLogErrorLevel |
8772 			    kOSKextLogDependenciesFlag,
8773 			    "Error - kext %s declares a dependency on %s. "
8774 			    "Only Apple kexts may declare a dependency on %s.",
8775 			    getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
8776 			goto finish;
8777 		}
8778 	}
8779 #endif // CONFIG_KXLD
8780 
8781 	result = true;
8782 	flags.hasAllDependencies = 1;
8783 
8784 finish:
8785 
8786 	if (addedToLoopStack) {
8787 		count = loopStack->getCount();
8788 		if (count > 0 && (this == loopStack->getObject(count - 1))) {
8789 			loopStack->removeObject(count - 1);
8790 		} else {
8791 			OSKextLog(this,
8792 			    kOSKextLogErrorLevel |
8793 			    kOSKextLogDependenciesFlag,
8794 			    "Kext %s - internal error resolving dependencies.",
8795 			    getIdentifierCString());
8796 		}
8797 	}
8798 
8799 	if (result && localLoopStack) {
8800 		OSKextLog(this,
8801 		    kOSKextLogStepLevel |
8802 		    kOSKextLogDependenciesFlag,
8803 		    "Kext %s successfully resolved dependencies.",
8804 		    getIdentifierCString());
8805 	}
8806 
8807 	return result;
8808 }
8809 
8810 /*********************************************************************
8811 *********************************************************************/
8812 bool
8813 OSKext::addBleedthroughDependencies(OSArray * anArray)
8814 {
8815 	bool result = false;
8816 	unsigned int dependencyIndex, dependencyCount;
8817 
8818 	dependencyCount = getNumDependencies();
8819 
8820 	for (dependencyIndex = 0;
8821 	    dependencyIndex < dependencyCount;
8822 	    dependencyIndex++) {
8823 		OSKext * dependency = OSDynamicCast(OSKext,
8824 		    dependencies->getObject(dependencyIndex));
8825 		if (!dependency) {
8826 			OSKextLog(this,
8827 			    kOSKextLogErrorLevel |
8828 			    kOSKextLogDependenciesFlag,
8829 			    "Kext %s - internal error propagating compatibility dependencies.",
8830 			    getIdentifierCString());
8831 			goto finish;
8832 		}
8833 		if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
8834 			anArray->setObject(dependency);
8835 		}
8836 		dependency->addBleedthroughDependencies(anArray);
8837 	}
8838 
8839 	result = true;
8840 
8841 finish:
8842 	return result;
8843 }
8844 
8845 /*********************************************************************
8846 *********************************************************************/
8847 bool
8848 OSKext::flushDependencies(bool forceFlag)
8849 {
8850 	bool result = false;
8851 
8852 	/* Only clear the dependencies if the kext isn't loaded;
8853 	 * we need the info for loaded kexts to track references.
8854 	 */
8855 	if (!isLoaded() || forceFlag) {
8856 		if (dependencies) {
8857 			// xxx - check level
8858 			OSKextLog(this,
8859 			    kOSKextLogProgressLevel |
8860 			    kOSKextLogDependenciesFlag,
8861 			    "Kext %s flushing dependencies.",
8862 			    getIdentifierCString());
8863 			dependencies.reset();
8864 		}
8865 		if (!isKernelComponent()) {
8866 			flags.hasAllDependencies = 0;
8867 		}
8868 		result = true;
8869 	}
8870 
8871 	return result;
8872 }
8873 
8874 /*********************************************************************
8875 *********************************************************************/
8876 uint32_t
8877 OSKext::getNumDependencies(void)
8878 {
8879 	if (!dependencies) {
8880 		return 0;
8881 	}
8882 	return dependencies->getCount();
8883 }
8884 
8885 /*********************************************************************
8886 *********************************************************************/
8887 OSArray *
8888 OSKext::getDependencies(void)
8889 {
8890 	return dependencies.get();
8891 }
8892 
8893 bool
8894 OSKext::hasDependency(const OSSymbol * depID)
8895 {
8896 	bool result __block;
8897 
8898 	if (depID == getIdentifier()) {
8899 		return true;
8900 	}
8901 	if (!dependencies) {
8902 		return false;
8903 	}
8904 	result = false;
8905 	dependencies->iterateObjects(^bool (OSObject * obj) {
8906 		OSKext * kext;
8907 		kext = OSDynamicCast(OSKext, obj);
8908 		if (!kext) {
8909 		        return false;
8910 		}
8911 		result = (depID == kext->getIdentifier());
8912 		return result;
8913 	});
8914 	return result;
8915 }
8916 
8917 #if PRAGMA_MARK
8918 #pragma mark OSMetaClass Support
8919 #endif
8920 /*********************************************************************
8921 *********************************************************************/
8922 OSReturn
8923 OSKext::addClass(
8924 	OSMetaClass * aClass,
8925 	uint32_t      numClasses)
8926 {
8927 	OSReturn result = kOSMetaClassNoInsKModSet;
8928 
8929 	if (!metaClasses) {
8930 		metaClasses = OSSet::withCapacity(numClasses);
8931 		if (!metaClasses) {
8932 			goto finish;
8933 		}
8934 	}
8935 
8936 	if (metaClasses->containsObject(aClass)) {
8937 		OSKextLog(this,
8938 		    kOSKextLogWarningLevel |
8939 		    kOSKextLogLoadFlag,
8940 		    "Notice - kext %s has already registered class %s.",
8941 		    getIdentifierCString(),
8942 		    aClass->getClassName());
8943 		result = kOSReturnSuccess;
8944 		goto finish;
8945 	}
8946 
8947 	if (!metaClasses->setObject(aClass)) {
8948 		goto finish;
8949 	} else {
8950 		OSKextLog(this,
8951 		    kOSKextLogDetailLevel |
8952 		    kOSKextLogLoadFlag,
8953 		    "Kext %s registered class %s.",
8954 		    getIdentifierCString(),
8955 		    aClass->getClassName());
8956 	}
8957 
8958 	if (!flags.autounloadEnabled) {
8959 		const OSMetaClass * metaScan  = NULL;        // do not release
8960 
8961 		for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
8962 			if (metaScan == OSTypeID(IOService)) {
8963 				OSKextLog(this,
8964 				    kOSKextLogProgressLevel |
8965 				    kOSKextLogLoadFlag,
8966 				    "Kext %s has IOService subclass %s; enabling autounload.",
8967 				    getIdentifierCString(),
8968 				    aClass->getClassName());
8969 
8970 				flags.autounloadEnabled = 1;
8971 				break;
8972 			}
8973 		}
8974 	}
8975 
8976 	notifyAddClassObservers(this, aClass, flags);
8977 
8978 	result = kOSReturnSuccess;
8979 
8980 finish:
8981 	if (result != kOSReturnSuccess) {
8982 		OSKextLog(this,
8983 		    kOSKextLogErrorLevel |
8984 		    kOSKextLogLoadFlag,
8985 		    "Kext %s failed to register class %s.",
8986 		    getIdentifierCString(),
8987 		    aClass->getClassName());
8988 	}
8989 
8990 	return result;
8991 }
8992 
8993 /*********************************************************************
8994 *********************************************************************/
8995 OSReturn
8996 OSKext::removeClass(
8997 	OSMetaClass * aClass)
8998 {
8999 	OSReturn result = kOSMetaClassNoKModSet;
9000 
9001 	if (!metaClasses) {
9002 		goto finish;
9003 	}
9004 
9005 	if (!metaClasses->containsObject(aClass)) {
9006 		OSKextLog(this,
9007 		    kOSKextLogWarningLevel |
9008 		    kOSKextLogLoadFlag,
9009 		    "Notice - kext %s asked to unregister unknown class %s.",
9010 		    getIdentifierCString(),
9011 		    aClass->getClassName());
9012 		result = kOSReturnSuccess;
9013 		goto finish;
9014 	}
9015 
9016 	OSKextLog(this,
9017 	    kOSKextLogDetailLevel |
9018 	    kOSKextLogLoadFlag,
9019 	    "Kext %s unregistering class %s.",
9020 	    getIdentifierCString(),
9021 	    aClass->getClassName());
9022 
9023 	metaClasses->removeObject(aClass);
9024 
9025 	notifyRemoveClassObservers(this, aClass, flags);
9026 
9027 	result = kOSReturnSuccess;
9028 
9029 finish:
9030 	if (result != kOSReturnSuccess) {
9031 		OSKextLog(this,
9032 		    kOSKextLogErrorLevel |
9033 		    kOSKextLogLoadFlag,
9034 		    "Failed to unregister kext %s class %s.",
9035 		    getIdentifierCString(),
9036 		    aClass->getClassName());
9037 	}
9038 	return result;
9039 }
9040 
9041 /*********************************************************************
9042 *********************************************************************/
9043 OSSet *
9044 OSKext::getMetaClasses(void)
9045 {
9046 	return metaClasses.get();
9047 }
9048 
9049 /*********************************************************************
9050 *********************************************************************/
9051 bool
9052 OSKext::hasOSMetaClassInstances(void)
9053 {
9054 	bool                   result        = false;
9055 	OSSharedPtr<OSCollectionIterator> classIterator;
9056 	OSMetaClass          * checkClass    = NULL;        // do not release
9057 
9058 	if (!metaClasses) {
9059 		goto finish;
9060 	}
9061 
9062 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9063 	if (!classIterator) {
9064 		// xxx - log alloc failure?
9065 		goto finish;
9066 	}
9067 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9068 		if (checkClass->getInstanceCount()) {
9069 			result = true;
9070 			goto finish;
9071 		}
9072 	}
9073 
9074 finish:
9075 	return result;
9076 }
9077 
9078 /*********************************************************************
9079 *********************************************************************/
9080 /* static */
9081 void
9082 OSKext::reportOSMetaClassInstances(
9083 	const char     * kextIdentifier,
9084 	OSKextLogSpec    msgLogSpec)
9085 {
9086 	OSSharedPtr<OSKext> theKext;
9087 
9088 	theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
9089 	if (!theKext) {
9090 		goto finish;
9091 	}
9092 
9093 	theKext->reportOSMetaClassInstances(msgLogSpec);
9094 finish:
9095 	return;
9096 }
9097 
9098 /*********************************************************************
9099 *********************************************************************/
9100 void
9101 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
9102 {
9103 	OSSharedPtr<OSCollectionIterator> classIterator;
9104 	OSMetaClass          * checkClass    = NULL;        // do not release
9105 
9106 	if (!metaClasses) {
9107 		goto finish;
9108 	}
9109 
9110 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9111 	if (!classIterator) {
9112 		goto finish;
9113 	}
9114 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9115 		if (checkClass->getInstanceCount()) {
9116 			OSKextLog(this,
9117 			    msgLogSpec,
9118 			    "    Kext %s class %s has %d instance%s.",
9119 			    getIdentifierCString(),
9120 			    checkClass->getClassName(),
9121 			    checkClass->getInstanceCount(),
9122 			    checkClass->getInstanceCount() == 1 ? "" : "s");
9123 		}
9124 	}
9125 
9126 finish:
9127 	return;
9128 }
9129 
9130 #if PRAGMA_MARK
9131 #pragma mark User-Space Requests
9132 #endif
9133 
9134 static kern_return_t
9135 patchDextLaunchRequests(task_t calling_task, OSArray *requests)
9136 {
9137 	OSReturn result = kOSReturnSuccess;
9138 	for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) {
9139 		OSDictionary * request = NULL;         //do not release
9140 		IOUserServerCheckInToken * token = NULL;         //do not release
9141 		OSString * requestPredicate = NULL;         //do not release
9142 		OSSharedPtr<OSNumber> portNameNumber;
9143 		mach_port_name_t portName = 0;
9144 		request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex));
9145 		if (!request) {
9146 			OSKextLog(/* kext */ NULL,
9147 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9148 			    "Elements of request should be of type OSDictionary");
9149 			result = kOSKextReturnInternalError;
9150 			goto finish;
9151 		}
9152 		requestPredicate = _OSKextGetRequestPredicate(request);
9153 		if (!requestPredicate) {
9154 			OSKextLog(/* kext */ NULL,
9155 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9156 			    "Failed to get request predicate");
9157 			result = kOSKextReturnInternalError;
9158 			goto finish;
9159 		}
9160 		// is this a dext launch?
9161 		if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) {
9162 			token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken));
9163 			if (!token) {
9164 				OSKextLog(/* kext */ NULL,
9165 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9166 				    "Could not find a IOUserServerCheckInToken in daemon launch request.");
9167 				result = kOSKextReturnInternalError;
9168 				goto finish;
9169 			}
9170 			portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT);
9171 			if (portName == 0 || portName == MACH_PORT_DEAD) {
9172 				OSKextLog(/* kext */ NULL,
9173 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9174 				    "Could not create send right for object.");
9175 				result = kOSKextReturnInternalError;
9176 				goto finish;
9177 			}
9178 			// Store the mach port name as a OSNumber
9179 			portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName));
9180 			if (!portNameNumber) {
9181 				OSKextLog(/* kext */ NULL,
9182 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9183 				    "Could not create OSNumber object.");
9184 				result = kOSKextReturnNoMemory;
9185 				goto finish;
9186 			}
9187 			if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) {
9188 				OSKextLog(/* kext */ NULL,
9189 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9190 				    "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken);
9191 				result = kOSKextReturnNoMemory;
9192 				goto finish;
9193 			}
9194 		}
9195 finish:
9196 		if (result != kOSReturnSuccess) {
9197 			break;
9198 		}
9199 	}
9200 	return result;
9201 }
9202 
9203 /*********************************************************************
9204 * XXX - this function is a big ugly mess
9205 *********************************************************************/
9206 /* static */
9207 OSReturn
9208 OSKext::handleRequest(
9209 	host_priv_t     hostPriv,
9210 	OSKextLogSpec   clientLogFilter,
9211 	char          * requestBuffer,
9212 	uint32_t        requestLength,
9213 	char         ** responseOut,
9214 	uint32_t      * responseLengthOut,
9215 	char         ** logInfoOut,
9216 	uint32_t      * logInfoLengthOut)
9217 {
9218 	OSReturn       result             = kOSReturnError;
9219 	kern_return_t  kmem_result        = KERN_FAILURE;
9220 
9221 	char         * response           = NULL;        // returned by reference
9222 	uint32_t       responseLength     = 0;
9223 
9224 	bool           taskCanManageAllKCs   = false;
9225 	bool           taskOnlyManagesBootKC = false;
9226 
9227 	OSSharedPtr<OSObject>     parsedXML;
9228 	OSDictionary            * requestDict    = NULL;        // do not release
9229 	OSSharedPtr<OSString>     errorString;
9230 
9231 	OSSharedPtr<OSObject>     responseObject;
9232 
9233 	OSSharedPtr<OSSerialize>  serializer;
9234 
9235 	OSSharedPtr<OSArray>      logInfoArray;
9236 
9237 	OSString     * predicate          = NULL;        // do not release
9238 	OSString     * kextIdentifier     = NULL;        // do not release
9239 	OSArray      * kextIdentifiers    = NULL;        // do not release
9240 	OSKext       * theKext            = NULL;        // do not release
9241 	OSBoolean    * boolArg            = NULL;        // do not release
9242 
9243 	IORecursiveLockLock(sKextLock);
9244 
9245 	if (responseOut) {
9246 		*responseOut = NULL;
9247 		*responseLengthOut = 0;
9248 	}
9249 	if (logInfoOut) {
9250 		*logInfoOut = NULL;
9251 		*logInfoLengthOut = 0;
9252 	}
9253 
9254 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
9255 
9256 	/* XML must be nul-terminated.
9257 	 */
9258 	if (requestBuffer[requestLength - 1] != '\0') {
9259 		OSKextLog(/* kext */ NULL,
9260 		    kOSKextLogErrorLevel |
9261 		    kOSKextLogIPCFlag,
9262 		    "Invalid request from user space (not nul-terminated).");
9263 		result = kOSKextReturnBadData;
9264 		goto finish;
9265 	}
9266 	parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString);
9267 	if (parsedXML) {
9268 		requestDict = OSDynamicCast(OSDictionary, parsedXML.get());
9269 	}
9270 	if (!requestDict) {
9271 		const char * errorCString = "(unknown error)";
9272 
9273 		if (errorString && errorString->getCStringNoCopy()) {
9274 			errorCString = errorString->getCStringNoCopy();
9275 		} else if (parsedXML) {
9276 			errorCString = "not a dictionary";
9277 		}
9278 		OSKextLog(/* kext */ NULL,
9279 		    kOSKextLogErrorLevel |
9280 		    kOSKextLogIPCFlag,
9281 		    "Error unserializing request from user space: %s.",
9282 		    errorCString);
9283 		result = kOSKextReturnSerialization;
9284 		goto finish;
9285 	}
9286 
9287 	predicate = _OSKextGetRequestPredicate(requestDict);
9288 	if (!predicate) {
9289 		OSKextLog(/* kext */ NULL,
9290 		    kOSKextLogErrorLevel |
9291 		    kOSKextLogIPCFlag,
9292 		    "Recieved kext request from user space with no predicate.");
9293 		result = kOSKextReturnInvalidArgument;
9294 		goto finish;
9295 	}
9296 
9297 	OSKextLog(/* kext */ NULL,
9298 	    kOSKextLogDebugLevel |
9299 	    kOSKextLogIPCFlag,
9300 	    "Received '%s' request from user space.",
9301 	    predicate->getCStringNoCopy());
9302 
9303 	/*
9304 	 * All management of file sets requires an entitlement
9305 	 */
9306 	result = kOSKextReturnNotPrivileged;
9307 	if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
9308 	    predicate->isEqualTo(kKextRequestPredicateStart) ||
9309 	    predicate->isEqualTo(kKextRequestPredicateStop) ||
9310 	    predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
9311 	    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
9312 	    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
9313 	    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
9314 	    predicate->isEqualTo(kKextRequestPredicateLoadFromKC) ||
9315 	    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
9316 	    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
9317 	    predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
9318 		if (hostPriv == HOST_PRIV_NULL) {
9319 			OSKextLog(/* kext */ NULL,
9320 			    kOSKextLogErrorLevel |
9321 			    kOSKextLogIPCFlag,
9322 			    "Access Failure - must be root user.");
9323 			goto finish;
9324 		}
9325 		taskCanManageAllKCs = IOTaskHasEntitlement(current_task(), kOSKextCollectionManagementEntitlement) == TRUE;
9326 		taskOnlyManagesBootKC = IOTaskHasEntitlement(current_task(), kOSKextOnlyBootKCManagementEntitlement) == TRUE;
9327 
9328 		if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) {
9329 			OSKextLog(/* kext */ NULL,
9330 			    kOSKextLogErrorLevel |
9331 			    kOSKextLogIPCFlag,
9332 			    "Access Failure - client not entitled to manage file sets.");
9333 			goto finish;
9334 		}
9335 
9336 		/*
9337 		 * The OnlyBootKC entitlement restricts the
9338 		 * collection-management entitlement to only managing kexts in
9339 		 * the BootKC. All other predicates that alter global state or
9340 		 * add new KCs are disallowed.
9341 		 */
9342 		if (taskOnlyManagesBootKC &&
9343 		    (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
9344 		    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
9345 		    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
9346 		    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
9347 		    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
9348 		    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
9349 		    predicate->isEqualTo(kKextRequestPredicateDaemonReady))) {
9350 			OSKextLog(/* kext */ NULL,
9351 			    kOSKextLogErrorLevel |
9352 			    kOSKextLogIPCFlag,
9353 			    "Access Failure - client not entitled to manage non-primary KCs");
9354 			goto finish;
9355 		}
9356 
9357 		/*
9358 		 * If we get here, then the process either has the full KC
9359 		 * management entitlement, or it has the BootKC-only
9360 		 * entitlement and the request is about the BootKC.
9361 		 */
9362 	}
9363 
9364 	/* Get common args in anticipation of use.
9365 	 */
9366 	kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
9367 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
9368 	kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
9369 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
9370 	if (kextIdentifier) {
9371 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
9372 	}
9373 	boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
9374 		    requestDict, kKextRequestArgumentValueKey));
9375 
9376 	if (taskOnlyManagesBootKC &&
9377 	    theKext &&
9378 	    theKext->isInFileset() &&
9379 	    theKext->kc_type != KCKindPrimary) {
9380 		OSKextLog(/* kext */ NULL,
9381 		    kOSKextLogErrorLevel |
9382 		    kOSKextLogIPCFlag,
9383 		    "Access Failure - client not entitled to manage kext in non-primary KC");
9384 		result = kOSKextReturnNotPrivileged;
9385 		goto finish;
9386 	}
9387 
9388 	result = kOSKextReturnInvalidArgument;
9389 
9390 	if (predicate->isEqualTo(kKextRequestPredicateStart)) {
9391 		if (!kextIdentifier) {
9392 			OSKextLog(/* kext */ NULL,
9393 			    kOSKextLogErrorLevel |
9394 			    kOSKextLogIPCFlag,
9395 			    "Invalid arguments to kext start request.");
9396 		} else if (!theKext) {
9397 			OSKextLog(/* kext */ NULL,
9398 			    kOSKextLogErrorLevel |
9399 			    kOSKextLogIPCFlag,
9400 			    "Kext %s not found for start request.",
9401 			    kextIdentifier->getCStringNoCopy());
9402 			result = kOSKextReturnNotFound;
9403 		} else {
9404 			result = theKext->start();
9405 		}
9406 	} else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
9407 		if (!kextIdentifier) {
9408 			OSKextLog(/* kext */ NULL,
9409 			    kOSKextLogErrorLevel |
9410 			    kOSKextLogIPCFlag,
9411 			    "Invalid arguments to kext stop request.");
9412 		} else if (!theKext) {
9413 			OSKextLog(/* kext */ NULL,
9414 			    kOSKextLogErrorLevel |
9415 			    kOSKextLogIPCFlag,
9416 			    "Kext %s not found for stop request.",
9417 			    kextIdentifier->getCStringNoCopy());
9418 			result = kOSKextReturnNotFound;
9419 		} else {
9420 			result = theKext->stop();
9421 		}
9422 	} else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) {
9423 		result = OSKext::setMissingAuxKCBundles(requestDict);
9424 	} else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) {
9425 		if (!kextIdentifier) {
9426 			OSKextLog(/* kext */ NULL,
9427 			    kOSKextLogErrorLevel |
9428 			    kOSKextLogIPCFlag,
9429 			    "Invalid arguments to AuxKC Bundle Available request.");
9430 		} else {
9431 			result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict);
9432 		}
9433 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) {
9434 		if (!kextIdentifier) {
9435 			OSKextLog(/* kext */ NULL,
9436 			    kOSKextLogErrorLevel |
9437 			    kOSKextLogIPCFlag,
9438 			    "Invalid arguments to kext load from KC request.");
9439 		} else if (!theKext) {
9440 			OSKextLog(/* kext */ NULL,
9441 			    kOSKextLogErrorLevel |
9442 			    kOSKextLogIPCFlag,
9443 			    "Kext %s not found for load from KC request.",
9444 			    kextIdentifier->getCStringNoCopy());
9445 			result = kOSKextReturnNotFound;
9446 		} else if (!theKext->isInFileset()) {
9447 			OSKextLog(/* kext */ NULL,
9448 			    kOSKextLogErrorLevel |
9449 			    kOSKextLogIPCFlag,
9450 			    "Kext %s does not exist in a KC: refusing to load.",
9451 			    kextIdentifier->getCStringNoCopy());
9452 			result = kOSKextReturnNotLoadable;
9453 		} else {
9454 			result = OSKext::loadKextFromKC(theKext, requestDict);
9455 		}
9456 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) {
9457 		if (!kextIdentifier) {
9458 			OSKextLog(/* kext */ NULL,
9459 			    kOSKextLogErrorLevel |
9460 			    kOSKextLogIPCFlag,
9461 			    "Invalid arguments to codeless kext load interface (missing identifier).");
9462 		} else {
9463 			result = OSKext::loadCodelessKext(kextIdentifier, requestDict);
9464 		}
9465 	} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
9466 		if (!kextIdentifier) {
9467 			OSKextLog(/* kext */ NULL,
9468 			    kOSKextLogErrorLevel |
9469 			    kOSKextLogIPCFlag,
9470 			    "Invalid arguments to kext unload request.");
9471 		} else if (!theKext) {
9472 			OSKextLog(/* kext */ NULL,
9473 			    kOSKextLogErrorLevel |
9474 			    kOSKextLogIPCFlag,
9475 			    "Kext %s not found for unload request.",
9476 			    kextIdentifier->getCStringNoCopy());
9477 			result = kOSKextReturnNotFound;
9478 		} else {
9479 			OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
9480 			    _OSKextGetRequestArgument(requestDict,
9481 			    kKextRequestArgumentTerminateIOServicesKey));
9482 			result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
9483 		}
9484 	} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
9485 		result = OSKext::dispatchResource(requestDict);
9486 	} else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
9487 		OSNumber     *lookupNum   = NULL;
9488 		lookupNum = OSDynamicCast(OSNumber,
9489 		    _OSKextGetRequestArgument(requestDict,
9490 		    kKextRequestArgumentLookupAddressKey));
9491 
9492 		responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
9493 		if (responseObject) {
9494 			result = kOSReturnSuccess;
9495 		} else {
9496 			goto finish;
9497 		}
9498 	} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
9499 	    predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) ||
9500 	    predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
9501 		OSBoolean    * delayAutounloadBool = NULL;
9502 		OSObject     * infoKeysRaw         = NULL;
9503 		OSArray      * infoKeys            = NULL;
9504 		uint32_t       infoKeysCount       = 0;
9505 
9506 		delayAutounloadBool = OSDynamicCast(OSBoolean,
9507 		    _OSKextGetRequestArgument(requestDict,
9508 		    kKextRequestArgumentDelayAutounloadKey));
9509 
9510 		/* If asked to delay autounload, reset the timer if it's currently set.
9511 		 * (That is, don't schedule an unload if one isn't already pending.
9512 		 */
9513 		if (delayAutounloadBool == kOSBooleanTrue) {
9514 			OSKext::considerUnloads(/* rescheduleOnly? */ true);
9515 		}
9516 
9517 		infoKeysRaw = _OSKextGetRequestArgument(requestDict,
9518 		    kKextRequestArgumentInfoKeysKey);
9519 		infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
9520 		if (infoKeysRaw && !infoKeys) {
9521 			OSKextLog(/* kext */ NULL,
9522 			    kOSKextLogErrorLevel |
9523 			    kOSKextLogIPCFlag,
9524 			    "Invalid arguments to kext info request.");
9525 			goto finish;
9526 		}
9527 
9528 		if (infoKeys) {
9529 			infoKeysCount = infoKeys->getCount();
9530 			for (uint32_t i = 0; i < infoKeysCount; i++) {
9531 				if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
9532 					OSKextLog(/* kext */ NULL,
9533 					    kOSKextLogErrorLevel |
9534 					    kOSKextLogIPCFlag,
9535 					    "Invalid arguments to kext info request.");
9536 					goto finish;
9537 				}
9538 			}
9539 		}
9540 
9541 		if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
9542 			responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
9543 		} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
9544 			responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
9545 		} else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
9546 			responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys);
9547 		}
9548 
9549 		if (!responseObject) {
9550 			result = kOSKextReturnInternalError;
9551 		} else {
9552 			OSKextLog(/* kext */ NULL,
9553 			    kOSKextLogDebugLevel |
9554 			    kOSKextLogIPCFlag,
9555 			    "Returning loaded kext info.");
9556 			result = kOSReturnSuccess;
9557 		}
9558 	} else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
9559 		/* Hand the current sKernelRequests array to the caller
9560 		 * (who must release it), and make a new one.
9561 		 */
9562 		responseObject = os::move(sKernelRequests);
9563 		sKernelRequests = OSArray::withCapacity(0);
9564 		sPostedKextLoadIdentifiers->flushCollection();
9565 		OSKextLog(/* kext */ NULL,
9566 		    kOSKextLogDebugLevel |
9567 		    kOSKextLogIPCFlag,
9568 		    "Returning kernel requests.");
9569 		result = kOSReturnSuccess;
9570 	} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
9571 		/* Return the set of all requested bundle identifiers */
9572 		responseObject = sAllKextLoadIdentifiers;
9573 		OSKextLog(/* kext */ NULL,
9574 		    kOSKextLogDebugLevel |
9575 		    kOSKextLogIPCFlag,
9576 		    "Returning load requests.");
9577 		result = kOSReturnSuccess;
9578 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) {
9579 		printf("KextLog: Loading FileSet KC(s)\n");
9580 		result = OSKext::loadFileSetKexts(requestDict);
9581 	} else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
9582 		printf("KextLog: " kIOKitDaemonName " is %s\n", sIOKitDaemonActive ? "active" : "not active");
9583 		result = (sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot) ? kOSReturnSuccess : kIOReturnNotReady;
9584 	} else {
9585 		OSKextLog(/* kext */ NULL,
9586 		    kOSKextLogDebugLevel |
9587 		    kOSKextLogIPCFlag,
9588 		    "Received '%s' invalid request from user space.",
9589 		    predicate->getCStringNoCopy());
9590 		goto finish;
9591 	}
9592 
9593 	/**********
9594 	 * Now we have handle the request, or not. Gather up the response & logging
9595 	 * info to ship to user space.
9596 	 *********/
9597 
9598 	/* Note: Nothing in OSKext is supposed to retain requestDict,
9599 	 * but you never know....
9600 	 */
9601 	if (requestDict->getRetainCount() > 1) {
9602 		OSKextLog(/* kext */ NULL,
9603 		    kOSKextLogWarningLevel |
9604 		    kOSKextLogIPCFlag,
9605 		    "Request from user space still retained by a kext; "
9606 		    "probable memory leak.");
9607 	}
9608 
9609 	if (responseOut && responseObject) {
9610 		serializer = OSSerialize::withCapacity(0);
9611 		if (!serializer) {
9612 			result = kOSKextReturnNoMemory;
9613 			goto finish;
9614 		}
9615 		/*
9616 		 * Before serializing the kernel requests, patch the dext launch requests so
9617 		 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the
9618 		 * IOUserServerCheckInToken kernel object.
9619 		 */
9620 		if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
9621 			OSArray * requests = OSDynamicCast(OSArray, responseObject.get());
9622 			task_t calling_task = current_task();
9623 			if (!requests) {
9624 				OSKextLog(/* kext */ NULL,
9625 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9626 				    "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests);
9627 				result = kOSKextReturnInternalError;
9628 				goto finish;
9629 			}
9630 			result = patchDextLaunchRequests(calling_task, requests);
9631 			if (result != kOSReturnSuccess) {
9632 				OSKextLog(/* kext */ NULL,
9633 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9634 				    "Failed to patch dext launch requests.");
9635 				goto finish;
9636 			}
9637 		}
9638 
9639 		if (!responseObject->serialize(serializer.get())) {
9640 			OSKextLog(/* kext */ NULL,
9641 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9642 			    "Failed to serialize response to request from user space.");
9643 			result = kOSKextReturnSerialization;
9644 			goto finish;
9645 		}
9646 
9647 		response = (char *)serializer->text();
9648 		responseLength = serializer->getLength();
9649 	}
9650 
9651 	if (responseOut && response) {
9652 		char * buffer;
9653 
9654 		/* This kmem_alloc sets the return value of the function.
9655 		 */
9656 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
9657 		    round_page(responseLength), VM_KERN_MEMORY_OSKEXT);
9658 		if (kmem_result != KERN_SUCCESS) {
9659 			OSKextLog(/* kext */ NULL,
9660 			    kOSKextLogErrorLevel |
9661 			    kOSKextLogIPCFlag,
9662 			    "Failed to copy response to request from user space.");
9663 			result = kmem_result;
9664 			goto finish;
9665 		} else {
9666 			/* 11981737 - clear uninitialized data in last page */
9667 			bzero((void *)(buffer + responseLength),
9668 			    (round_page(responseLength) - responseLength));
9669 			memcpy(buffer, response, responseLength);
9670 			*responseOut = buffer;
9671 			*responseLengthOut = responseLength;
9672 		}
9673 	}
9674 
9675 finish:
9676 
9677 	/* Gather up the collected log messages for user space. Any messages
9678 	 * messages past this call will not make it up as log messages but
9679 	 * will be in the system log. Note that we ignore the return of the
9680 	 * serialize; it has no bearing on the operation at hand even if we
9681 	 * fail to get the log messages.
9682 	 */
9683 	logInfoArray = OSKext::clearUserSpaceLogFilter();
9684 
9685 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
9686 		(void)OSKext::serializeLogInfo(logInfoArray.get(),
9687 		    logInfoOut, logInfoLengthOut);
9688 	}
9689 
9690 	IORecursiveLockUnlock(sKextLock);
9691 
9692 	return result;
9693 }
9694 
9695 #if PRAGMA_MARK
9696 #pragma mark Linked Kext Collection Support
9697 #endif
9698 
9699 static int
9700 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount)
9701 {
9702 	for (int i = 0; i < segCount; i++) {
9703 		vm_offset_t segStart = segAddrs[i];
9704 		vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i];
9705 
9706 		if (theAddr >= segStart && theAddr < segEnd) {
9707 			return i;
9708 		}
9709 	}
9710 	return -1;
9711 }
9712 
9713 static void
9714 __slideOldKaslrOffsets(kernel_mach_header_t *mh,
9715     kernel_segment_command_t *kextTextSeg,
9716     OSData *kaslrOffsets)
9717 {
9718 	static const char *plk_segNames[] = {
9719 		"__TEXT",
9720 		"__TEXT_EXEC",
9721 		"__DATA",
9722 		"__DATA_CONST",
9723 		"__LINKEDIT",
9724 		"__PRELINK_TEXT",
9725 		"__PLK_TEXT_EXEC",
9726 		"__PRELINK_DATA",
9727 		"__PLK_DATA_CONST",
9728 		"__PLK_LLVM_COV",
9729 		"__PLK_LINKEDIT",
9730 		"__PRELINK_INFO"
9731 	};
9732 	static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0]));
9733 
9734 	unsigned long plk_segSizes[num_plk_seg];
9735 	vm_offset_t   plk_segAddrs[num_plk_seg];
9736 
9737 	for (size_t i = 0; i < num_plk_seg; i++) {
9738 		plk_segSizes[i] = 0;
9739 		plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]);
9740 	}
9741 
9742 	uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr;
9743 
9744 	int slidKextAddrCount = 0;
9745 	int badSlideAddr = 0;
9746 	int badSlideTarget = 0;
9747 
9748 	struct kaslrPackedOffsets {
9749 		uint32_t    count;          /* number of offsets */
9750 		uint32_t    offsetsArray[];        /* offsets to slide */
9751 	};
9752 	const struct kaslrPackedOffsets *myOffsets = NULL;
9753 	myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy();
9754 
9755 	for (uint32_t j = 0; j < myOffsets->count; j++) {
9756 		uint64_t   slideOffset = (uint64_t)myOffsets->offsetsArray[j];
9757 		vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset);
9758 		int        slideAddrSegIndex = -1;
9759 		int        addrToSlideSegIndex = -1;
9760 
9761 		slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
9762 		if (slideAddrSegIndex >= 0) {
9763 			addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
9764 			if (addrToSlideSegIndex < 0) {
9765 				badSlideTarget++;
9766 				continue;
9767 			}
9768 		} else {
9769 			badSlideAddr++;
9770 			continue;
9771 		}
9772 
9773 		slidKextAddrCount++;
9774 		*slideAddr = ml_static_slide(*slideAddr);
9775 	}         // for ...
9776 }
9777 
9778 
9779 
9780 /********************************************************************
9781 * addKextsFromKextCollection
9782 *
9783 * Input: MachO header of kext collection. The MachO is assumed to
9784 *        have a section named 'info_seg_name,info_sect_name' that
9785 *        contains a serialized XML info dictionary. This dictionary
9786 *        contains a UUID, possibly a set of relocations (for older
9787 *        kxld-built binaries), and an array of kext personalities.
9788 *
9789 ********************************************************************/
9790 bool
9791 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
9792     OSDictionary *infoDict, const char *text_seg_name,
9793     OSData **kcUUID, kc_kind_t type)
9794 {
9795 	bool result = false;
9796 
9797 	OSArray *kextArray     = NULL;        // do not release
9798 	OSData *infoDictKCUUID = NULL;         // do not release
9799 	OSData *kaslrOffsets   = NULL;        // do not release
9800 
9801 	IORegistryEntry *registryRoot = NULL;         // do not release
9802 	OSSharedPtr<OSNumber> kcKextCount;
9803 
9804 	/* extract the KC UUID from the dictionary */
9805 	infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
9806 	if (infoDictKCUUID) {
9807 		if (infoDictKCUUID->getLength() != sizeof(uuid_t)) {
9808 			panic("kcUUID length is %d, expected %lu",
9809 			    infoDictKCUUID->getLength(), sizeof(uuid_t));
9810 		}
9811 	}
9812 
9813 	/* locate the array of kext dictionaries */
9814 	kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey));
9815 	if (!kextArray) {
9816 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9817 		    "The given KC has no kext info dictionaries");
9818 		goto finish;
9819 	}
9820 
9821 	/*
9822 	 * old-style KASLR offsets may be present in the info dictionary. If
9823 	 * we find them, use them and eventually slide them.
9824 	 */
9825 	kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey));
9826 
9827 	/*
9828 	 * Before processing any kexts, locate the special kext bundle which
9829 	 * contains a list of kexts that we are to prevent from loading.
9830 	 */
9831 	createExcludeListFromPrelinkInfo(kextArray);
9832 
9833 	/*
9834 	 * Create OSKext objects for each kext we find in the array of kext
9835 	 * info plist dictionaries.
9836 	 */
9837 	for (int i = 0; i < (int)kextArray->getCount(); ++i) {
9838 		OSDictionary *kextDict = NULL;
9839 		kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i));
9840 		if (!kextDict) {
9841 			OSKextLog(/* kext */ NULL,
9842 			    kOSKextLogErrorLevel |
9843 			    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
9844 			    "Kext info dictionary for kext #%d isn't a dictionary?", i);
9845 			continue;
9846 		}
9847 
9848 		/*
9849 		 * Create the kext for the entry, then release it, because the
9850 		 * kext system keeps a reference around until the kext is
9851 		 * explicitly removed.  Any creation/registration failures are
9852 		 * already logged for us.
9853 		 */
9854 		withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type);
9855 	}
9856 
9857 	/*
9858 	 * slide old-style kxld relocations
9859 	 * NOTE: this is still used on embedded KCs built with kcgen
9860 	 * TODO: Remove this once we use the new kext linker everywhere!
9861 	 */
9862 	if (kaslrOffsets && vm_kernel_slide > 0) {
9863 		kernel_segment_command_t *text_segment = NULL;
9864 		text_segment = getsegbynamefromheader(mh, text_seg_name);
9865 		if (!text_segment) {
9866 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9867 			    "Can't find a TEXT segment named '%s' in macho header", text_seg_name);
9868 			goto finish;
9869 		}
9870 
9871 		__slideOldKaslrOffsets(mh, text_segment, kaslrOffsets);
9872 		/* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */
9873 		setAllVMAttributes();
9874 	}
9875 
9876 	/* Store the number of prelinked kexts in the registry so we can tell
9877 	 * when the system has been started from a prelinked kernel.
9878 	 */
9879 	registryRoot = IORegistryEntry::getRegistryRoot();
9880 	assert(registryRoot);
9881 
9882 	kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t));
9883 	assert(kcKextCount);
9884 	if (kcKextCount) {
9885 		OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey);
9886 		OSNumber *num;
9887 		num = OSDynamicCast(OSNumber, prop.get());
9888 		if (num) {
9889 			kcKextCount->addValue(num->unsigned64BitValue());
9890 		}
9891 		registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get());
9892 	}
9893 
9894 	OSKextLog(/* kext */ NULL,
9895 	    kOSKextLogProgressLevel |
9896 	    kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
9897 	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
9898 	    "%u prelinked kexts", infoDict->getCount());
9899 
9900 
9901 	if (kcUUID && infoDictKCUUID) {
9902 		*kcUUID = OSData::withData(infoDictKCUUID).detach();
9903 	}
9904 
9905 	result = true;
9906 
9907 finish:
9908 	return result;
9909 }
9910 
9911 bool
9912 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
9913     OSDictionary *infoDict, const char *text_seg_name,
9914     OSSharedPtr<OSData> &kcUUID, kc_kind_t type)
9915 {
9916 	OSData  *result = NULL;
9917 	bool success = addKextsFromKextCollection(mh,
9918 	    infoDict,
9919 	    text_seg_name,
9920 	    &result,
9921 	    type);
9922 	if (success) {
9923 		kcUUID.reset(result, OSNoRetain);
9924 	}
9925 	return success;
9926 }
9927 
9928 static OSSharedPtr<OSObject> deferredAuxKCXML;
9929 bool
9930 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh,
9931     OSSharedPtr<OSObject> &parsedXML, kc_kind_t type)
9932 {
9933 	if (type != KCKindAuxiliary) {
9934 		return false;
9935 	}
9936 
9937 	kernel_mach_header_t *_mh;
9938 	_mh = (kernel_mach_header_t*)PE_get_kc_header(type);
9939 	if (!_mh || _mh != mh) {
9940 		return false;
9941 	}
9942 
9943 	if (deferredAuxKCXML) {
9944 		/* only allow this to be called once */
9945 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9946 		    "An Aux KC has already been registered for deferred processing.");
9947 		return false;
9948 	}
9949 
9950 	OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
9951 	if (!infoDict) {
9952 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9953 		    "The Aux KC has info dictionary");
9954 		return false;
9955 	}
9956 
9957 	OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
9958 	if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) {
9959 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9960 		    "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey);
9961 		return false;
9962 	}
9963 
9964 	/*
9965 	 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid
9966 	 * sysctl can return the UUID to user space which will check this
9967 	 * value for errors.
9968 	 */
9969 	memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(),
9970 	    kcUUID->getLength());
9971 	uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
9972 	auxkc_uuid_valid = TRUE;
9973 
9974 	deferredAuxKCXML = parsedXML;
9975 
9976 	return true;
9977 }
9978 
9979 OSSharedPtr<OSObject>
9980 OSKext::consumeDeferredKextCollection(kc_kind_t type)
9981 {
9982 	if (type != KCKindAuxiliary || !deferredAuxKCXML) {
9983 		return NULL;
9984 	}
9985 
9986 	return os::move(deferredAuxKCXML);
9987 }
9988 
9989 #if PRAGMA_MARK
9990 #pragma mark Profile-Guided-Optimization Support
9991 #endif
9992 
9993 // #include <InstrProfiling.h>
9994 extern "C" {
9995 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
9996     const char *DataEnd,
9997     const char *CountersBegin,
9998     const char *CountersEnd,
9999     const char *NamesBegin,
10000     const char *NamesEnd);
10001 int __llvm_profile_write_buffer_internal(char *Buffer,
10002     const char *DataBegin,
10003     const char *DataEnd,
10004     const char *CountersBegin,
10005     const char *CountersEnd,
10006     const char *NamesBegin,
10007     const char *NamesEnd);
10008 }
10009 
10010 
10011 static
10012 void
10013 OSKextPgoMetadataPut(char *pBuffer,
10014     size_t *position,
10015     size_t bufferSize,
10016     uint32_t *num_pairs,
10017     const char *key,
10018     const char *value)
10019 {
10020 	size_t strlen_key = strlen(key);
10021 	size_t strlen_value = strlen(value);
10022 	size_t len = strlen(key) + 1 + strlen(value) + 1;
10023 	char *pos = pBuffer + *position;
10024 	*position += len;
10025 	if (pBuffer && bufferSize && *position <= bufferSize) {
10026 		memcpy(pos, key, strlen_key); pos += strlen_key;
10027 		*(pos++) = '=';
10028 		memcpy(pos, value, strlen_value); pos += strlen_value;
10029 		*(pos++) = 0;
10030 		if (num_pairs) {
10031 			(*num_pairs)++;
10032 		}
10033 	}
10034 }
10035 
10036 
10037 static
10038 void
10039 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
10040 {
10041 	*position += strlen(key) + 1 + value_max + 1;
10042 }
10043 
10044 
10045 static
10046 void
10047 OSKextPgoMetadataPutAll(OSKext *kext,
10048     uuid_t instance_uuid,
10049     char *pBuffer,
10050     size_t *position,
10051     size_t bufferSize,
10052     uint32_t *num_pairs)
10053 {
10054 	_static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
10055 	//log_10 2^16 ≈ 4.82
10056 	const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
10057 	const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
10058 
10059 	if (!pBuffer) {
10060 		OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
10061 		OSKextPgoMetadataPutMax(position, "UUID", 36);
10062 		OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
10063 	} else {
10064 		uuid_string_t instance_uuid_string;
10065 		uuid_unparse(instance_uuid, instance_uuid_string);
10066 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10067 		    "INSTANCE", instance_uuid_string);
10068 
10069 		OSSharedPtr<OSData> uuid_data;
10070 		uuid_t uuid;
10071 		uuid_string_t uuid_string;
10072 		uuid_data = kext->copyUUID();
10073 		if (uuid_data) {
10074 			memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
10075 			uuid_unparse(uuid, uuid_string);
10076 			OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10077 			    "UUID", uuid_string);
10078 		}
10079 
10080 		clock_sec_t secs;
10081 		clock_usec_t usecs;
10082 		clock_get_calendar_microtime(&secs, &usecs);
10083 		assert(usecs < 1000000);
10084 		char timestamp[max_timestamp_string_size + 1];
10085 		_static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
10086 		snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
10087 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10088 		    "TIMESTAMP", timestamp);
10089 	}
10090 
10091 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10092 	    "NAME", kext->getIdentifierCString());
10093 
10094 	char versionCString[kOSKextVersionMaxLength];
10095 	OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
10096 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10097 	    "VERSION", versionCString);
10098 }
10099 
10100 static
10101 size_t
10102 OSKextPgoMetadataSize(OSKext *kext)
10103 {
10104 	size_t position = 0;
10105 	uuid_t fakeuuid = {};
10106 	OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
10107 	return position;
10108 }
10109 
10110 int
10111 OSKextGrabPgoDataLocked(OSKext *kext,
10112     bool metadata,
10113     uuid_t instance_uuid,
10114     uint64_t *pSize,
10115     char *pBuffer,
10116     uint64_t bufferSize)
10117 {
10118 	int err = 0;
10119 
10120 	kernel_section_t *sect_prf_data = NULL;
10121 	kernel_section_t *sect_prf_name = NULL;
10122 	kernel_section_t *sect_prf_cnts = NULL;
10123 	uint64_t size;
10124 	size_t metadata_size = 0;
10125 	size_t offset_to_pairs = 0;
10126 
10127 	sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
10128 	sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
10129 	if (!sect_prf_name) {
10130 		// kextcache sometimes truncates the section name to 15 chars
10131 		// <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
10132 		sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
10133 	}
10134 	sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
10135 
10136 	if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
10137 		err = ENOTSUP;
10138 		goto out;
10139 	}
10140 
10141 	size = __llvm_profile_get_size_for_buffer_internal(
10142 		(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
10143 		(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
10144 		(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
10145 
10146 	if (metadata) {
10147 		metadata_size = OSKextPgoMetadataSize(kext);
10148 		size += metadata_size;
10149 		size += sizeof(pgo_metadata_footer);
10150 	}
10151 
10152 
10153 	if (pSize) {
10154 		*pSize = size;
10155 	}
10156 
10157 	if (pBuffer && bufferSize) {
10158 		if (bufferSize < size) {
10159 			err = ERANGE;
10160 			goto out;
10161 		}
10162 
10163 		err = __llvm_profile_write_buffer_internal(
10164 			pBuffer,
10165 			(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
10166 			(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
10167 			(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
10168 
10169 		if (err) {
10170 			err = EIO;
10171 			goto out;
10172 		}
10173 
10174 		if (metadata) {
10175 			offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size;
10176 			if (offset_to_pairs > UINT32_MAX) {
10177 				err = E2BIG;
10178 				goto out;
10179 			}
10180 
10181 			char *end_of_buffer = pBuffer + size;
10182 			struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
10183 			char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
10184 
10185 			size_t metadata_position = 0;
10186 			uint32_t num_pairs = 0;
10187 			OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
10188 			while (metadata_position < metadata_size) {
10189 				metadata_buffer[metadata_position++] = 0;
10190 			}
10191 
10192 			struct pgo_metadata_footer footer;
10193 			footer.magic = htonl(0x6d657461);
10194 			footer.number_of_pairs = htonl( num_pairs );
10195 			footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs );
10196 			memcpy(footerp, &footer, sizeof(footer));
10197 		}
10198 	}
10199 
10200 out:
10201 	return err;
10202 }
10203 
10204 
10205 int
10206 OSKextGrabPgoData(uuid_t uuid,
10207     uint64_t *pSize,
10208     char *pBuffer,
10209     uint64_t bufferSize,
10210     int wait_for_unload,
10211     int metadata)
10212 {
10213 	int err = 0;
10214 	OSSharedPtr<OSKext> kext;
10215 
10216 
10217 	IORecursiveLockLock(sKextLock);
10218 
10219 	kext = OSKext::lookupKextWithUUID(uuid);
10220 	if (!kext) {
10221 		err = ENOENT;
10222 		goto out;
10223 	}
10224 
10225 	if (wait_for_unload) {
10226 		OSKextGrabPgoStruct s;
10227 
10228 		s.metadata = metadata;
10229 		s.pSize = pSize;
10230 		s.pBuffer = pBuffer;
10231 		s.bufferSize = bufferSize;
10232 		s.err = EINTR;
10233 
10234 		struct list_head *prev = &kext->pendingPgoHead;
10235 		struct list_head *next = kext->pendingPgoHead.next;
10236 
10237 		s.list_head.prev = prev;
10238 		s.list_head.next = next;
10239 
10240 		prev->next = &s.list_head;
10241 		next->prev = &s.list_head;
10242 
10243 		kext.reset();
10244 
10245 		IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
10246 
10247 		prev = s.list_head.prev;
10248 		next = s.list_head.next;
10249 
10250 		prev->next = next;
10251 		next->prev = prev;
10252 
10253 		err = s.err;
10254 	} else {
10255 		err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
10256 	}
10257 
10258 out:
10259 
10260 	IORecursiveLockUnlock(sKextLock);
10261 
10262 	return err;
10263 }
10264 
10265 void
10266 OSKextResetPgoCountersLock()
10267 {
10268 	IORecursiveLockLock(sKextLock);
10269 }
10270 
10271 void
10272 OSKextResetPgoCountersUnlock()
10273 {
10274 	IORecursiveLockUnlock(sKextLock);
10275 }
10276 
10277 
10278 extern unsigned int not_in_kdp;
10279 
10280 void
10281 OSKextResetPgoCounters()
10282 {
10283 	assert(!not_in_kdp);
10284 	uint32_t count = sLoadedKexts->getCount();
10285 	for (uint32_t i = 0; i < count; i++) {
10286 		OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
10287 		kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
10288 		if (!sect_prf_cnts) {
10289 			continue;
10290 		}
10291 		memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
10292 	}
10293 }
10294 
10295 OSSharedPtr<OSDictionary>
10296 OSKext::copyLoadedKextInfoByUUID(
10297 	OSArray * kextIdentifiers,
10298 	OSArray * infoKeys)
10299 {
10300 	OSSharedPtr<OSDictionary> result;
10301 	OSSharedPtr<OSDictionary> kextInfo;
10302 	uint32_t       max_count, i, j;
10303 	uint32_t       idCount = 0;
10304 	uint32_t       idIndex = 0;
10305 	IORecursiveLockLock(sKextLock);
10306 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
10307 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
10308 
10309 #if CONFIG_MACF
10310 	/* Is the calling process allowed to query kext info? */
10311 	if (current_task() != kernel_task) {
10312 		int                 macCheckResult      = 0;
10313 		kauth_cred_t        cred                = NULL;
10314 
10315 		cred = kauth_cred_get_with_ref();
10316 		macCheckResult = mac_kext_check_query(cred);
10317 		kauth_cred_unref(&cred);
10318 
10319 		if (macCheckResult != 0) {
10320 			OSKextLog(/* kext */ NULL,
10321 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10322 			    "Failed to query kext info (MAC policy error 0x%x).",
10323 			    macCheckResult);
10324 			goto finish;
10325 		}
10326 	}
10327 #endif
10328 
10329 	/* Empty list of UUIDs is equivalent to no list (get all).
10330 	 */
10331 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
10332 		kextIdentifiers = NULL;
10333 	} else if (kextIdentifiers) {
10334 		idCount = kextIdentifiers->getCount();
10335 	}
10336 
10337 	/* Same for keys.
10338 	 */
10339 	if (infoKeys && !infoKeys->getCount()) {
10340 		infoKeys = NULL;
10341 	}
10342 
10343 	max_count = count[0] + count[1];
10344 	result = OSDictionary::withCapacity(max_count);
10345 	if (!result) {
10346 		goto finish;
10347 	}
10348 
10349 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
10350 		for (i = 0; i < count[j]; i++) {
10351 			OSKext       *thisKext     = NULL;        // do not release
10352 			Boolean       includeThis  = true;
10353 			uuid_t        thisKextUUID;
10354 			uuid_t        thisKextTextUUID;
10355 			OSSharedPtr<OSData> uuid_data;
10356 			uuid_string_t uuid_key;
10357 
10358 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
10359 			if (!thisKext) {
10360 				continue;
10361 			}
10362 
10363 			uuid_data = thisKext->copyUUID();
10364 			if (!uuid_data) {
10365 				continue;
10366 			}
10367 
10368 			memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
10369 
10370 			uuid_unparse(thisKextUUID, uuid_key);
10371 
10372 			uuid_data = thisKext->copyTextUUID();
10373 			if (!uuid_data) {
10374 				continue;
10375 			}
10376 			memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
10377 
10378 			/* Skip current kext if we have a list of UUIDs and
10379 			 * it isn't in the list.
10380 			 */
10381 			if (kextIdentifiers) {
10382 				includeThis = false;
10383 
10384 				for (idIndex = 0; idIndex < idCount; idIndex++) {
10385 					const OSString* wantedUUID = OSDynamicCast(OSString,
10386 					    kextIdentifiers->getObject(idIndex));
10387 
10388 					uuid_t uuid;
10389 					uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
10390 
10391 					if ((0 == uuid_compare(uuid, thisKextUUID))
10392 					    || (0 == uuid_compare(uuid, thisKextTextUUID))) {
10393 						includeThis = true;
10394 						/* Only need to find the first kext if multiple match,
10395 						 * ie. asking for the kernel uuid does not need to find
10396 						 * interface kexts or builtin static kexts.
10397 						 */
10398 						kextIdentifiers->removeObject(idIndex);
10399 						uuid_unparse(uuid, uuid_key);
10400 						break;
10401 					}
10402 				}
10403 			}
10404 
10405 			if (!includeThis) {
10406 				continue;
10407 			}
10408 
10409 			kextInfo = thisKext->copyInfo(infoKeys);
10410 			if (kextInfo) {
10411 				result->setObject(uuid_key, kextInfo.get());
10412 			}
10413 
10414 			if (kextIdentifiers && !kextIdentifiers->getCount()) {
10415 				goto finish;
10416 			}
10417 		}
10418 	}
10419 
10420 finish:
10421 	IORecursiveLockUnlock(sKextLock);
10422 
10423 	return result;
10424 }
10425 
10426 /*********************************************************************
10427 *********************************************************************/
10428 /* static */
10429 OSSharedPtr<OSDictionary>
10430 OSKext::copyKextCollectionInfo(
10431 	OSDictionary *requestDict,
10432 	OSArray  *infoKeys)
10433 {
10434 	OSSharedPtr<OSDictionary> result;
10435 	OSString *collectionType = NULL;
10436 	OSObject *rawLoadedState = NULL;
10437 	OSString *loadedState    = NULL;
10438 
10439 	kc_kind_t kc_request_kind = KCKindUnknown;
10440 	bool onlyLoaded = false;
10441 	bool onlyUnloaded = false;
10442 
10443 #if CONFIG_MACF
10444 	/* Is the calling process allowed to query kext info? */
10445 	if (current_task() != kernel_task) {
10446 		int                 macCheckResult      = 0;
10447 		kauth_cred_t        cred                = NULL;
10448 
10449 		cred = kauth_cred_get_with_ref();
10450 		macCheckResult = mac_kext_check_query(cred);
10451 		kauth_cred_unref(&cred);
10452 
10453 		if (macCheckResult != 0) {
10454 			OSKextLog(/* kext */ NULL,
10455 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10456 			    "Failed to query kext info (MAC policy error 0x%x).",
10457 			    macCheckResult);
10458 			goto finish;
10459 		}
10460 	}
10461 #endif
10462 
10463 	if (infoKeys && !infoKeys->getCount()) {
10464 		infoKeys = NULL;
10465 	}
10466 
10467 	collectionType = OSDynamicCast(OSString,
10468 	    _OSKextGetRequestArgument(requestDict,
10469 	    kKextRequestArgumentCollectionTypeKey));
10470 	if (!collectionType) {
10471 		OSKextLog(/* kext */ NULL,
10472 		    kOSKextLogErrorLevel |
10473 		    kOSKextLogIPCFlag,
10474 		    "Invalid '%s' argument to kext collection info request.",
10475 		    kKextRequestArgumentCollectionTypeKey);
10476 		goto finish;
10477 	}
10478 	if (collectionType->isEqualTo(kKCTypePrimary)) {
10479 		kc_request_kind = KCKindPrimary;
10480 	} else if (collectionType->isEqualTo(kKCTypeSystem)) {
10481 		kc_request_kind = KCKindPageable;
10482 	} else if (collectionType->isEqualTo(kKCTypeAuxiliary)) {
10483 		kc_request_kind = KCKindAuxiliary;
10484 	} else if (collectionType->isEqualTo(kKCTypeCodeless)) {
10485 		kc_request_kind = KCKindNone;
10486 	} else if (!collectionType->isEqualTo(kKCTypeAny)) {
10487 		OSKextLog(/* kext */ NULL,
10488 		    kOSKextLogErrorLevel |
10489 		    kOSKextLogIPCFlag,
10490 		    "Invalid '%s' argument value '%s' to kext collection info request.",
10491 		    kKextRequestArgumentCollectionTypeKey,
10492 		    collectionType->getCStringNoCopy());
10493 		goto finish;
10494 	}
10495 
10496 	rawLoadedState = _OSKextGetRequestArgument(requestDict,
10497 	    kKextRequestArgumentLoadedStateKey);
10498 	if (rawLoadedState) {
10499 		loadedState = OSDynamicCast(OSString, rawLoadedState);
10500 		if (!loadedState) {
10501 			OSKextLog(/* kext */ NULL,
10502 			    kOSKextLogErrorLevel |
10503 			    kOSKextLogIPCFlag,
10504 			    "Invalid '%s' argument to kext collection info request.",
10505 			    kKextRequestArgumentLoadedStateKey);
10506 			goto finish;
10507 		}
10508 	}
10509 	if (loadedState) {
10510 		if (loadedState->isEqualTo("Loaded")) {
10511 			onlyLoaded = true;
10512 		} else if (loadedState->isEqualTo("Unloaded")) {
10513 			onlyUnloaded = true;
10514 		} else if (!loadedState->isEqualTo("Any")) {
10515 			OSKextLog(/* kext */ NULL,
10516 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10517 			    "Invalid '%s' argument value '%s' for '%s' collection info",
10518 			    kKextRequestArgumentLoadedStateKey,
10519 			    loadedState->getCStringNoCopy(),
10520 			    collectionType->getCStringNoCopy());
10521 			goto finish;
10522 		}
10523 	}
10524 
10525 	result = OSDictionary::withCapacity(sKextsByID->getCount());
10526 	if (!result) {
10527 		goto finish;
10528 	}
10529 
10530 	IORecursiveLockLock(sKextLock);
10531 	{         // start block scope
10532 		sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
10533 		{
10534 			OSKext       *thisKext    = NULL;  // do not release
10535 			OSSharedPtr<OSDictionary> kextInfo;
10536 
10537 			(void)thisKextID;
10538 
10539 			thisKext = OSDynamicCast(OSKext, obj);
10540 			if (!thisKext) {
10541 			        return false;;
10542 			}
10543 
10544 			/*
10545 			 * skip the kext if it came from the wrong collection type
10546 			 * (and the caller requested a specific type)
10547 			 */
10548 			if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) {
10549 			        return false;
10550 			}
10551 
10552 			/*
10553 			 * respect the caller's desire to find only loaded or
10554 			 * unloaded kexts
10555 			 */
10556 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10557 			        return false;
10558 			}
10559 			if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10560 			        return false;
10561 			}
10562 
10563 			kextInfo = thisKext->copyInfo(infoKeys);
10564 			if (kextInfo) {
10565 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
10566 			}
10567 			return false;
10568 		});
10569 	} // end block scope
10570 	IORecursiveLockUnlock(sKextLock);
10571 
10572 finish:
10573 	return result;
10574 }
10575 
10576 /*********************************************************************
10577 *********************************************************************/
10578 /* static */
10579 OSSharedPtr<OSDictionary>
10580 OSKext::copyLoadedKextInfo(
10581 	OSArray * kextIdentifiers,
10582 	OSArray * infoKeys)
10583 {
10584 	OSSharedPtr<OSDictionary> result;
10585 	uint32_t       idCount = 0;
10586 	bool           onlyLoaded;
10587 
10588 	IORecursiveLockLock(sKextLock);
10589 
10590 #if CONFIG_MACF
10591 	/* Is the calling process allowed to query kext info? */
10592 	if (current_task() != kernel_task) {
10593 		int                 macCheckResult      = 0;
10594 		kauth_cred_t        cred                = NULL;
10595 
10596 		cred = kauth_cred_get_with_ref();
10597 		macCheckResult = mac_kext_check_query(cred);
10598 		kauth_cred_unref(&cred);
10599 
10600 		if (macCheckResult != 0) {
10601 			OSKextLog(/* kext */ NULL,
10602 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10603 			    "Failed to query kext info (MAC policy error 0x%x).",
10604 			    macCheckResult);
10605 			goto finish;
10606 		}
10607 	}
10608 #endif
10609 
10610 	/* Empty list of bundle ids is equivalent to no list (get all).
10611 	 */
10612 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
10613 		kextIdentifiers = NULL;
10614 	} else if (kextIdentifiers) {
10615 		idCount = kextIdentifiers->getCount();
10616 	}
10617 
10618 	/* Same for keys.
10619 	 */
10620 	if (infoKeys && !infoKeys->getCount()) {
10621 		infoKeys = NULL;
10622 	}
10623 
10624 	onlyLoaded =  (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
10625 
10626 	result = OSDictionary::withCapacity(128);
10627 	if (!result) {
10628 		goto finish;
10629 	}
10630 
10631 #if 0
10632 	OSKextLog(/* kext */ NULL,
10633 	    kOSKextLogErrorLevel |
10634 	    kOSKextLogGeneralFlag,
10635 	    "kaslr: vm_kernel_slide 0x%lx \n",
10636 	    vm_kernel_slide);
10637 	OSKextLog(/* kext */ NULL,
10638 	    kOSKextLogErrorLevel |
10639 	    kOSKextLogGeneralFlag,
10640 	    "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
10641 	    vm_kernel_stext, vm_kernel_etext);
10642 	OSKextLog(/* kext */ NULL,
10643 	    kOSKextLogErrorLevel |
10644 	    kOSKextLogGeneralFlag,
10645 	    "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
10646 	    vm_kernel_base, vm_kernel_top);
10647 	OSKextLog(/* kext */ NULL,
10648 	    kOSKextLogErrorLevel |
10649 	    kOSKextLogGeneralFlag,
10650 	    "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
10651 	    vm_kext_base, vm_kext_top);
10652 	OSKextLog(/* kext */ NULL,
10653 	    kOSKextLogErrorLevel |
10654 	    kOSKextLogGeneralFlag,
10655 	    "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
10656 	    vm_prelink_stext, vm_prelink_etext);
10657 	OSKextLog(/* kext */ NULL,
10658 	    kOSKextLogErrorLevel |
10659 	    kOSKextLogGeneralFlag,
10660 	    "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
10661 	    vm_prelink_sinfo, vm_prelink_einfo);
10662 	OSKextLog(/* kext */ NULL,
10663 	    kOSKextLogErrorLevel |
10664 	    kOSKextLogGeneralFlag,
10665 	    "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
10666 	    vm_slinkedit, vm_elinkedit);
10667 #endif
10668 	{         // start block scope
10669 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
10670 		{
10671 			OSKext       * thisKext     = NULL;        // do not release
10672 			Boolean        includeThis  = true;
10673 			OSSharedPtr<OSDictionary> kextInfo;
10674 
10675 			thisKext = OSDynamicCast(OSKext, obj);
10676 			if (!thisKext) {
10677 			        return false;;
10678 			}
10679 
10680 			/* Skip current kext if not yet started and caller didn't request all.
10681 			 */
10682 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10683 			        return false;;
10684 			}
10685 
10686 			/* Skip current kext if we have a list of bundle IDs and
10687 			 * it isn't in the list.
10688 			 */
10689 			if (kextIdentifiers) {
10690 			        includeThis = false;
10691 
10692 			        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
10693 			                const OSString * thisRequestID = OSDynamicCast(OSString,
10694 			                kextIdentifiers->getObject(idIndex));
10695 			                if (thisKextID->isEqualTo(thisRequestID)) {
10696 			                        includeThis = true;
10697 			                        break;
10698 					}
10699 				}
10700 			}
10701 
10702 			if (!includeThis) {
10703 			        return false;
10704 			}
10705 
10706 			kextInfo = thisKext->copyInfo(infoKeys);
10707 			if (kextInfo) {
10708 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
10709 			}
10710 			return false;
10711 		});
10712 	}         // end block scope
10713 
10714 finish:
10715 	IORecursiveLockUnlock(sKextLock);
10716 
10717 	return result;
10718 }
10719 
10720 /*********************************************************************
10721 * Any info that needs to do allocations must goto finish on alloc
10722 * failure. Info that is just a lookup should just not set the object
10723 * if the info does not exist.
10724 *********************************************************************/
10725 #define _OSKextLoadInfoDictCapacity   (12)
10726 
10727 OSSharedPtr<OSDictionary>
10728 OSKext::copyInfo(OSArray * infoKeys)
10729 {
10730 	OSSharedPtr<OSDictionary>  result;
10731 	bool                       success                     = false;
10732 	OSSharedPtr<OSData>        headerData;
10733 	OSSharedPtr<OSData>        logData;
10734 	OSSharedPtr<OSNumber>      cpuTypeNumber;
10735 	OSSharedPtr<OSNumber>      cpuSubtypeNumber;
10736 	OSString                 * versionString               = NULL;        // do not release
10737 	OSString                 * bundleType                  = NULL;        // do not release
10738 	uint32_t                   executablePathCStringSize   = 0;
10739 	char                     * executablePathCString       = NULL;        // must kfree
10740 	OSSharedPtr<OSString>      executablePathString;
10741 	OSSharedPtr<OSData>        uuid;
10742 	OSSharedPtr<OSArray>       dependencyLoadTags;
10743 	OSSharedPtr<OSCollectionIterator>      metaClassIterator;
10744 	OSSharedPtr<OSArray>       metaClassInfo;
10745 	OSSharedPtr<OSDictionary>  metaClassDict;
10746 	OSMetaClass              * thisMetaClass               = NULL;        // do not release
10747 	OSSharedPtr<OSString>      metaClassName;
10748 	OSSharedPtr<OSString>      superclassName;
10749 	kc_format_t                kcformat;
10750 	uint32_t                   count, i;
10751 
10752 	result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
10753 	if (!result) {
10754 		goto finish;
10755 	}
10756 
10757 
10758 	/* Empty keys means no keys, but NULL is quicker to check.
10759 	 */
10760 	if (infoKeys && !infoKeys->getCount()) {
10761 		infoKeys = NULL;
10762 	}
10763 
10764 	if (!PE_get_primary_kc_format(&kcformat)) {
10765 		goto finish;
10766 	}
10767 
10768 	/* Headers, CPU type, and CPU subtype.
10769 	 */
10770 	if (!infoKeys ||
10771 	    _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
10772 	    _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
10773 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
10774 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
10775 		if (linkedExecutable && !isInterface()) {
10776 			kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
10777 			    linkedExecutable->getBytesNoCopy();
10778 
10779 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX
10780 			// do not return macho header info on shipping embedded - 19095897
10781 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
10782 				kernel_mach_header_t *  temp_kext_mach_hdr;
10783 				struct load_command *   lcp;
10784 
10785 				headerData = OSData::withBytes(kext_mach_hdr,
10786 				    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
10787 				if (!headerData) {
10788 					goto finish;
10789 				}
10790 
10791 				// unslide any vmaddrs we return to userspace - 10726716
10792 				temp_kext_mach_hdr = (kernel_mach_header_t *)
10793 				    headerData->getBytesNoCopy();
10794 				if (temp_kext_mach_hdr == NULL) {
10795 					goto finish;
10796 				}
10797 
10798 				lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
10799 				for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
10800 					if (lcp->cmd == LC_SEGMENT_KERNEL) {
10801 						kernel_segment_command_t *  segp;
10802 						kernel_section_t *          secp;
10803 
10804 						segp = (kernel_segment_command_t *) lcp;
10805 						// 10543468 - if we jettisoned __LINKEDIT clear size info
10806 						if (flags.jettisonLinkeditSeg) {
10807 							if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
10808 								segp->vmsize = 0;
10809 								segp->fileoff = 0;
10810 								segp->filesize = 0;
10811 							}
10812 						}
10813 
10814 #if __arm__ || __arm64__
10815 						// iBoot disregards zero-size segments, just set their addresses to gVirtBase
10816 						// and unslide them to avoid vm assertion failures / kernel logging breakage.
10817 						if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) {
10818 							segp->vmaddr = gVirtBase;
10819 							for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
10820 								secp->size = 0; // paranoia :)
10821 								secp->addr = gVirtBase;
10822 							}
10823 						}
10824 #endif
10825 
10826 #if 0
10827 						OSKextLog(/* kext */ NULL,
10828 						    kOSKextLogErrorLevel |
10829 						    kOSKextLogGeneralFlag,
10830 						    "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
10831 						    __FUNCTION__, segp->segname, segp->vmaddr,
10832 						    VM_KERNEL_UNSLIDE(segp->vmaddr),
10833 						    segp->vmsize, segp->nsects);
10834 						if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
10835 						    (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
10836 						    (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
10837 						    (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
10838 						    (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
10839 							OSKextLog(/* kext */ NULL,
10840 							    kOSKextLogErrorLevel |
10841 							    kOSKextLogGeneralFlag,
10842 							    "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
10843 							    __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
10844 						}
10845 #endif
10846 						segp->vmaddr = ml_static_unslide(segp->vmaddr);
10847 
10848 						for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
10849 							secp->addr = ml_static_unslide(secp->addr);
10850 						}
10851 					}
10852 					lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
10853 				}
10854 				result->setObject(kOSBundleMachOHeadersKey, headerData.get());
10855 			}
10856 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX
10857 
10858 			if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
10859 				osLogDataHeaderRef *header;
10860 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
10861 
10862 				void *os_log_data          = NULL;
10863 				void *cstring_data         = NULL;
10864 				unsigned long os_log_size  = 0;
10865 				unsigned long cstring_size = 0;
10866 				uint32_t os_log_offset     = 0;
10867 				uint32_t cstring_offset    = 0;
10868 				bool res;
10869 
10870 				os_log_data       = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
10871 				os_log_offset     = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr;
10872 				cstring_data      = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
10873 				cstring_offset    = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr;
10874 
10875 				header             = (osLogDataHeaderRef *) headerBytes;
10876 				header->version    = OS_LOG_HDR_VERSION;
10877 				header->sect_count = NUM_OS_LOG_SECTIONS;
10878 				header->sections[OS_LOG_SECT_IDX].sect_offset  = os_log_offset;
10879 				header->sections[OS_LOG_SECT_IDX].sect_size    = (uint32_t) os_log_size;
10880 				header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset;
10881 				header->sections[CSTRING_SECT_IDX].sect_size   = (uint32_t) cstring_size;
10882 
10883 
10884 				logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
10885 				if (!logData) {
10886 					goto finish;
10887 				}
10888 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
10889 				if (!res) {
10890 					goto finish;
10891 				}
10892 				if (os_log_data) {
10893 					res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
10894 					if (!res) {
10895 						goto finish;
10896 					}
10897 				}
10898 				if (cstring_data) {
10899 					res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
10900 					if (!res) {
10901 						goto finish;
10902 					}
10903 				}
10904 				result->setObject(kOSBundleLogStringsKey, logData.get());
10905 			}
10906 
10907 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
10908 				cpuTypeNumber = OSNumber::withNumber(
10909 					(uint64_t) kext_mach_hdr->cputype,
10910 					8 * sizeof(kext_mach_hdr->cputype));
10911 				if (!cpuTypeNumber) {
10912 					goto finish;
10913 				}
10914 				result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get());
10915 			}
10916 
10917 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
10918 				cpuSubtypeNumber = OSNumber::withNumber(
10919 					(uint64_t) kext_mach_hdr->cpusubtype,
10920 					8 * sizeof(kext_mach_hdr->cpusubtype));
10921 				if (!cpuSubtypeNumber) {
10922 					goto finish;
10923 				}
10924 				result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get());
10925 			}
10926 		} else {
10927 			if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
10928 				osLogDataHeaderRef *header;
10929 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
10930 				bool res;
10931 
10932 				header             = (osLogDataHeaderRef *) headerBytes;
10933 				header->version    = OS_LOG_HDR_VERSION;
10934 				header->sect_count = NUM_OS_LOG_SECTIONS;
10935 				header->sections[OS_LOG_SECT_IDX].sect_offset  = 0;
10936 				header->sections[OS_LOG_SECT_IDX].sect_size    = (uint32_t) 0;
10937 				header->sections[CSTRING_SECT_IDX].sect_offset = 0;
10938 				header->sections[CSTRING_SECT_IDX].sect_size   = (uint32_t) 0;
10939 
10940 				logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
10941 				if (!logData) {
10942 					goto finish;
10943 				}
10944 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
10945 				if (!res) {
10946 					goto finish;
10947 				}
10948 				result->setObject(kOSBundleLogStringsKey, logData.get());
10949 			}
10950 		}
10951 	}
10952 
10953 	/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
10954 	 */
10955 	result->setObject(kCFBundleIdentifierKey, bundleID.get());
10956 
10957 	/* CFBundlePackageType
10958 	 */
10959 	bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL;
10960 	if (bundleType) {
10961 		result->setObject(kCFBundlePackageTypeKey, bundleType);
10962 	}
10963 
10964 	/* CFBundleVersion.
10965 	 */
10966 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
10967 		versionString = OSDynamicCast(OSString,
10968 		    getPropertyForHostArch(kCFBundleVersionKey));
10969 		if (versionString) {
10970 			result->setObject(kCFBundleVersionKey, versionString);
10971 		}
10972 	}
10973 
10974 	/* OSBundleCompatibleVersion.
10975 	 */
10976 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
10977 		versionString = OSDynamicCast(OSString,
10978 		    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
10979 		if (versionString) {
10980 			result->setObject(kOSBundleCompatibleVersionKey, versionString);
10981 		}
10982 	}
10983 
10984 	/* Path.
10985 	 */
10986 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
10987 		if (path) {
10988 			result->setObject(kOSBundlePathKey, path.get());
10989 		}
10990 	}
10991 
10992 
10993 	/* OSBundleExecutablePath.
10994 	 */
10995 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
10996 		if (path && executableRelPath) {
10997 			uint32_t pathLength = path->getLength();         // gets incremented below
10998 
10999 			// +1 for slash, +1 for \0
11000 			executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
11001 
11002 			executablePathCString = (char *)kheap_alloc_tag(KHEAP_TEMP,
11003 			    executablePathCStringSize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);         // +1 for \0
11004 			if (!executablePathCString) {
11005 				goto finish;
11006 			}
11007 			strlcpy(executablePathCString, path->getCStringNoCopy(),
11008 			    executablePathCStringSize);
11009 			executablePathCString[pathLength++] = '/';
11010 			executablePathCString[pathLength++] = '\0';
11011 			strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
11012 			    executablePathCStringSize);
11013 
11014 			executablePathString = OSString::withCString(executablePathCString);
11015 
11016 			if (!executablePathString) {
11017 				goto finish;
11018 			}
11019 
11020 			result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
11021 		} else if (flags.builtin) {
11022 			result->setObject(kOSBundleExecutablePathKey, bundleID.get());
11023 		} else if (isDriverKit()) {
11024 			if (path) {
11025 				// +1 for slash, +1 for \0
11026 				uint32_t pathLength = path->getLength();
11027 				executablePathCStringSize = pathLength + 2;
11028 
11029 				executablePathCString = (char *)kheap_alloc_tag(KHEAP_TEMP,
11030 				    executablePathCStringSize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
11031 				if (!executablePathCString) {
11032 					goto finish;
11033 				}
11034 				strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
11035 				executablePathCString[pathLength++] = '/';
11036 				executablePathCString[pathLength++] = '\0';
11037 
11038 				executablePathString = OSString::withCString(executablePathCString);
11039 
11040 				if (!executablePathString) {
11041 					goto finish;
11042 				}
11043 
11044 				result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
11045 			}
11046 		}
11047 	}
11048 
11049 	/* UUID, if the kext has one.
11050 	 */
11051 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
11052 		uuid = copyUUID();
11053 		if (uuid) {
11054 			result->setObject(kOSBundleUUIDKey, uuid.get());
11055 		}
11056 	}
11057 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
11058 		uuid = copyTextUUID();
11059 		if (uuid) {
11060 			result->setObject(kOSBundleTextUUIDKey, uuid.get());
11061 		}
11062 	}
11063 
11064 	/*
11065 	 * Info.plist digest
11066 	 */
11067 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) {
11068 		OSData *digest;
11069 		digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL;
11070 		if (digest) {
11071 			result->setObject(kOSKextInfoPlistDigestKey, digest);
11072 		}
11073 	}
11074 
11075 	/*
11076 	 * Collection type
11077 	 */
11078 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) {
11079 		result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString()));
11080 	}
11081 
11082 	/*
11083 	 * Collection availability
11084 	 */
11085 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) {
11086 		result->setObject(kOSKextAuxKCAvailabilityKey,
11087 		    isLoadable() ? kOSBooleanTrue : kOSBooleanFalse);
11088 	}
11089 
11090 	/*
11091 	 * Allows user load
11092 	 */
11093 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) {
11094 		OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey));
11095 		if (allowUserLoad) {
11096 			result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad);
11097 		}
11098 	}
11099 
11100 	/*
11101 	 * Bundle Dependencies (OSBundleLibraries)
11102 	 */
11103 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) {
11104 		OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey));
11105 		if (libraries) {
11106 			result->setObject(kOSBundleLibrariesKey, libraries);
11107 		}
11108 	}
11109 
11110 	/*****
11111 	 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
11112 	 */
11113 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
11114 		result->setObject(kOSKernelResourceKey,
11115 		    isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
11116 	}
11117 
11118 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
11119 		result->setObject(kOSBundleIsInterfaceKey,
11120 		    isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
11121 	}
11122 
11123 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
11124 		result->setObject(kOSBundlePrelinkedKey,
11125 		    isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
11126 	}
11127 
11128 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
11129 		result->setObject(kOSBundleStartedKey,
11130 		    isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
11131 	}
11132 
11133 	/* LoadTag (Index).
11134 	 */
11135 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
11136 		OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
11137 		    /* numBits */ 8 * sizeof(loadTag));
11138 		if (!scratchNumber) {
11139 			goto finish;
11140 		}
11141 		result->setObject(kOSBundleLoadTagKey, scratchNumber.get());
11142 	}
11143 
11144 	/* LoadAddress, LoadSize.
11145 	 */
11146 	if (!infoKeys ||
11147 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
11148 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
11149 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
11150 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
11151 	    _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
11152 		bool is_dext = isDriverKit();
11153 		if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
11154 			/* These go to userspace via serialization, so we don't want any doubts
11155 			 * about their size.
11156 			 */
11157 			uint64_t    loadAddress     = 0;
11158 			uint32_t    loadSize        = 0;
11159 			uint32_t    wiredSize       = 0;
11160 			uint64_t    execLoadAddress = 0;
11161 			uint32_t    execLoadSize    = 0;
11162 
11163 			/* Interfaces always report 0 load address & size.
11164 			 * Just the way they roll.
11165 			 *
11166 			 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
11167 			 * xxx - shouldn't have one!
11168 			 */
11169 
11170 			if (flags.builtin || linkedExecutable) {
11171 				kernel_mach_header_t     *mh  = NULL;
11172 				kernel_segment_command_t *seg = NULL;
11173 
11174 				if (flags.builtin) {
11175 					loadAddress = kmod_info->address;
11176 					loadSize    = (uint32_t)kmod_info->size;
11177 				} else {
11178 					loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
11179 					loadSize = linkedExecutable->getLength();
11180 				}
11181 				mh = (kernel_mach_header_t *)loadAddress;
11182 				loadAddress = ml_static_unslide(loadAddress);
11183 
11184 				/* Walk through the kext, looking for the first executable
11185 				 * segment in case we were asked for its size/address.
11186 				 */
11187 				for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
11188 					if (seg->initprot & VM_PROT_EXECUTE) {
11189 						execLoadAddress = ml_static_unslide(seg->vmaddr);
11190 						execLoadSize = (uint32_t)seg->vmsize;
11191 						break;
11192 					}
11193 				}
11194 
11195 				/* If we have a kmod_info struct, calculated the wired size
11196 				 * from that. Otherwise it's the full load size.
11197 				 */
11198 				if (kmod_info) {
11199 					wiredSize = loadSize - (uint32_t)kmod_info->hdr_size;
11200 				} else {
11201 					wiredSize = loadSize;
11202 				}
11203 			} else if (is_dext) {
11204 				/*
11205 				 * DriverKit userspace executables do not have a kernel linkedExecutable,
11206 				 * so we "fake" their address range with the LoadTag.
11207 				 */
11208 				if (loadTag) {
11209 					loadAddress = execLoadAddress = loadTag;
11210 					loadSize = execLoadSize = 1;
11211 				}
11212 			}
11213 
11214 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
11215 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11216 					(unsigned long long)(loadAddress),
11217 					/* numBits */ 8 * sizeof(loadAddress));
11218 				if (!scratchNumber) {
11219 					goto finish;
11220 				}
11221 				result->setObject(kOSBundleLoadAddressKey, scratchNumber.get());
11222 			}
11223 			if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) {
11224 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
11225 				    && loadAddress && loadSize) {
11226 					void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary);
11227 					if (!baseAddress) {
11228 						goto finish;
11229 					}
11230 
11231 					OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11232 						(unsigned long long)ml_static_unslide((vm_offset_t)baseAddress),
11233 						/* numBits */ 8 * sizeof(loadAddress));
11234 					if (!scratchNumber) {
11235 						goto finish;
11236 					}
11237 					result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get());
11238 				}
11239 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
11240 				    && (this == sKernelKext) && gBuiltinKmodsCount) {
11241 					result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
11242 				}
11243 			}
11244 
11245 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
11246 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11247 					(unsigned long long)(execLoadAddress),
11248 					/* numBits */ 8 * sizeof(execLoadAddress));
11249 				if (!scratchNumber) {
11250 					goto finish;
11251 				}
11252 				result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get());
11253 			}
11254 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
11255 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11256 					(unsigned long long)(loadSize),
11257 					/* numBits */ 8 * sizeof(loadSize));
11258 				if (!scratchNumber) {
11259 					goto finish;
11260 				}
11261 				result->setObject(kOSBundleLoadSizeKey, scratchNumber.get());
11262 			}
11263 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
11264 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11265 					(unsigned long long)(execLoadSize),
11266 					/* numBits */ 8 * sizeof(execLoadSize));
11267 				if (!scratchNumber) {
11268 					goto finish;
11269 				}
11270 				result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get());
11271 			}
11272 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
11273 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11274 					(unsigned long long)(wiredSize),
11275 					/* numBits */ 8 * sizeof(wiredSize));
11276 				if (!scratchNumber) {
11277 					goto finish;
11278 				}
11279 				result->setObject(kOSBundleWiredSizeKey, scratchNumber.get());
11280 			}
11281 		}
11282 	}
11283 
11284 	/* OSBundleDependencies. In descending order for
11285 	 * easy compatibility with kextstat(8).
11286 	 */
11287 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
11288 		if ((count = getNumDependencies())) {
11289 			dependencyLoadTags = OSArray::withCapacity(count);
11290 			result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get());
11291 
11292 			i = count - 1;
11293 			do {
11294 				OSKext * dependency = OSDynamicCast(OSKext,
11295 				    dependencies->getObject(i));
11296 
11297 				if (!dependency) {
11298 					continue;
11299 				}
11300 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11301 					(unsigned long long)dependency->getLoadTag(),
11302 					/* numBits*/ 8 * sizeof(loadTag));
11303 				if (!scratchNumber) {
11304 					goto finish;
11305 				}
11306 				dependencyLoadTags->setObject(scratchNumber.get());
11307 			} while (i--);
11308 		}
11309 	}
11310 
11311 	/* OSBundleMetaClasses.
11312 	 */
11313 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
11314 		if (metaClasses && metaClasses->getCount()) {
11315 			metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get());
11316 			metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
11317 			if (!metaClassIterator || !metaClassInfo) {
11318 				goto finish;
11319 			}
11320 			result->setObject(kOSBundleClassesKey, metaClassInfo.get());
11321 
11322 			while ((thisMetaClass = OSDynamicCast(OSMetaClass,
11323 			    metaClassIterator->getNextObject()))) {
11324 				metaClassDict = OSDictionary::withCapacity(3);
11325 				if (!metaClassDict) {
11326 					goto finish;
11327 				}
11328 
11329 				metaClassName = OSString::withCString(thisMetaClass->getClassName());
11330 				if (thisMetaClass->getSuperClass()) {
11331 					superclassName = OSString::withCString(
11332 						thisMetaClass->getSuperClass()->getClassName());
11333 				}
11334 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
11335 				    8 * sizeof(unsigned int));
11336 
11337 				/* Bail if any of the essentials is missing. The root class lacks a superclass,
11338 				 * of course.
11339 				 */
11340 				if (!metaClassDict || !metaClassName || !scratchNumber) {
11341 					goto finish;
11342 				}
11343 
11344 				metaClassInfo->setObject(metaClassDict.get());
11345 				metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get());
11346 				if (superclassName) {
11347 					metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get());
11348 				}
11349 				metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get());
11350 			}
11351 		}
11352 	}
11353 
11354 	/* OSBundleRetainCount.
11355 	 */
11356 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
11357 		{
11358 			int kextRetainCount = getRetainCount() - 1;
11359 			if (isLoaded()) {
11360 				kextRetainCount--;
11361 			}
11362 			OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11363 				(int)kextRetainCount,
11364 				/* numBits*/ 8 * sizeof(int));
11365 			if (scratchNumber) {
11366 				result->setObject(kOSBundleRetainCountKey, scratchNumber.get());
11367 			}
11368 		}
11369 	}
11370 
11371 	success = true;
11372 
11373 finish:
11374 	if (executablePathCString) {
11375 		kheap_free(KHEAP_TEMP, executablePathCString, executablePathCStringSize);
11376 	}
11377 	if (!success) {
11378 		result.reset();
11379 	}
11380 	return result;
11381 }
11382 
11383 /*********************************************************************
11384 *********************************************************************/
11385 /* static */
11386 bool
11387 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
11388 {
11389 	bool ok;
11390 	OSSharedPtr<OSKext> kext;
11391 
11392 	IORecursiveLockLock(sKextLock);
11393 	kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain);
11394 	IORecursiveLockUnlock(sKextLock);
11395 
11396 	if (!kext || !kext->path || !kext->userExecutableRelPath) {
11397 		return false;
11398 	}
11399 	snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
11400 	    kext->path->getCStringNoCopy(),
11401 	    kext->userExecutableRelPath->getCStringNoCopy());
11402 	ok = true;
11403 
11404 	return ok;
11405 }
11406 
11407 /*********************************************************************
11408 *********************************************************************/
11409 /* static */
11410 OSReturn
11411 OSKext::requestResource(
11412 	const char                    * kextIdentifierCString,
11413 	const char                    * resourceNameCString,
11414 	OSKextRequestResourceCallback   callback,
11415 	void                          * context,
11416 	OSKextRequestTag              * requestTagOut)
11417 {
11418 	OSReturn                        result = kOSReturnError;
11419 	OSSharedPtr<OSKext>             callbackKext;        // looked up
11420 
11421 	OSKextRequestTag   requestTag      = -1;
11422 	OSSharedPtr<OSNumber>           requestTagNum;
11423 	OSSharedPtr<OSDictionary>       requestDict;
11424 	OSSharedPtr<OSString>           kextIdentifier;
11425 	OSSharedPtr<OSString>           resourceName;
11426 
11427 	OSSharedPtr<OSDictionary>       callbackRecord;
11428 	OSSharedPtr<OSData>             callbackWrapper;
11429 
11430 	OSSharedPtr<OSData>             contextWrapper;
11431 
11432 	IORecursiveLockLock(sKextLock);
11433 
11434 	if (requestTagOut) {
11435 		*requestTagOut = kOSKextRequestTagInvalid;
11436 	}
11437 
11438 	/* If requests to user space are disabled, don't go any further */
11439 	if (!sKernelRequestsEnabled) {
11440 		OSKextLog(/* kext */ NULL,
11441 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11442 		    "Can't request resource %s for %s - requests to user space are disabled.",
11443 		    resourceNameCString,
11444 		    kextIdentifierCString);
11445 		result = kOSKextReturnDisabled;
11446 		goto finish;
11447 	}
11448 
11449 	if (!kextIdentifierCString || !resourceNameCString || !callback) {
11450 		result = kOSKextReturnInvalidArgument;
11451 		goto finish;
11452 	}
11453 
11454 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
11455 	if (!callbackKext) {
11456 		OSKextLog(/* kext */ NULL,
11457 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11458 		    "Resource request has bad callback address.");
11459 		result = kOSKextReturnInvalidArgument;
11460 		goto finish;
11461 	}
11462 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
11463 		OSKextLog(/* kext */ NULL,
11464 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11465 		    "Resource request callback is in a kext that is not started.");
11466 		result = kOSKextReturnInvalidArgument;
11467 		goto finish;
11468 	}
11469 
11470 	/* Do not allow any new requests to be made on a kext that is unloading.
11471 	 */
11472 	if (callbackKext->flags.stopping) {
11473 		result = kOSKextReturnStopping;
11474 		goto finish;
11475 	}
11476 
11477 	/* If we're wrapped the next available request tag around to the negative
11478 	 * numbers, we can't service any more requests.
11479 	 */
11480 	if (sNextRequestTag == kOSKextRequestTagInvalid) {
11481 		OSKextLog(/* kext */ NULL,
11482 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11483 		    "No more request tags available; restart required.");
11484 		result = kOSKextReturnNoResources;
11485 		goto finish;
11486 	}
11487 	requestTag = sNextRequestTag++;
11488 
11489 	result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
11490 	    requestDict);
11491 	if (result != kOSReturnSuccess) {
11492 		goto finish;
11493 	}
11494 
11495 	kextIdentifier = OSString::withCString(kextIdentifierCString);
11496 	resourceName   = OSString::withCString(resourceNameCString);
11497 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
11498 	    8 * sizeof(requestTag));
11499 	if (!kextIdentifier ||
11500 	    !resourceName ||
11501 	    !requestTagNum ||
11502 	    !_OSKextSetRequestArgument(requestDict.get(),
11503 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) ||
11504 	    !_OSKextSetRequestArgument(requestDict.get(),
11505 	    kKextRequestArgumentNameKey, resourceName.get()) ||
11506 	    !_OSKextSetRequestArgument(requestDict.get(),
11507 	    kKextRequestArgumentRequestTagKey, requestTagNum.get())) {
11508 		result = kOSKextReturnNoMemory;
11509 		goto finish;
11510 	}
11511 
11512 	callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection());
11513 	if (!callbackRecord) {
11514 		result = kOSKextReturnNoMemory;
11515 		goto finish;
11516 	}
11517 	// we validate callback address at call time
11518 	callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *));
11519 	if (context) {
11520 		contextWrapper = OSData::withBytes((void *)&context, sizeof(void *));
11521 	}
11522 	if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
11523 	    kKextRequestArgumentCallbackKey, callbackWrapper.get())) {
11524 		result = kOSKextReturnNoMemory;
11525 		goto finish;
11526 	}
11527 
11528 	if (context) {
11529 		if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
11530 		    kKextRequestArgumentContextKey, contextWrapper.get())) {
11531 			result = kOSKextReturnNoMemory;
11532 			goto finish;
11533 		}
11534 	}
11535 
11536 	/* Only post the requests after all the other potential failure points
11537 	 * have been passed.
11538 	 */
11539 	if (!sKernelRequests->setObject(requestDict.get()) ||
11540 	    !sRequestCallbackRecords->setObject(callbackRecord.get())) {
11541 		result = kOSKextReturnNoMemory;
11542 		goto finish;
11543 	}
11544 
11545 	OSKext::pingIOKitDaemon();
11546 
11547 	result = kOSReturnSuccess;
11548 	if (requestTagOut) {
11549 		*requestTagOut = requestTag;
11550 	}
11551 
11552 finish:
11553 
11554 	/* If we didn't succeed, yank the request & callback
11555 	 * from their holding arrays.
11556 	 */
11557 	if (result != kOSReturnSuccess) {
11558 		unsigned int index;
11559 
11560 		index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0);
11561 		if (index != (unsigned int)-1) {
11562 			sKernelRequests->removeObject(index);
11563 		}
11564 		index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0);
11565 		if (index != (unsigned int)-1) {
11566 			sRequestCallbackRecords->removeObject(index);
11567 		}
11568 	}
11569 
11570 	OSKext::considerUnloads(/* rescheduleOnly? */ true);
11571 
11572 	IORecursiveLockUnlock(sKextLock);
11573 
11574 	return result;
11575 }
11576 
11577 OSReturn
11578 OSKext::requestDaemonLaunch(
11579 	OSString *kextIdentifier,
11580 	OSString *serverName,
11581 	OSNumber *serverTag,
11582 	OSSharedPtr<IOUserServerCheckInToken> &checkInToken)
11583 {
11584 	OSReturn result;
11585 	IOUserServerCheckInToken * checkInTokenRaw = NULL;
11586 
11587 	result = requestDaemonLaunch(kextIdentifier, serverName,
11588 	    serverTag, &checkInTokenRaw);
11589 
11590 	if (kOSReturnSuccess == result) {
11591 		checkInToken.reset(checkInTokenRaw, OSNoRetain);
11592 	}
11593 
11594 	return result;
11595 }
11596 
11597 OSReturn
11598 OSKext::requestDaemonLaunch(
11599 	OSString *kextIdentifier,
11600 	OSString *serverName,
11601 	OSNumber *serverTag,
11602 	IOUserServerCheckInToken ** checkInToken)
11603 {
11604 	OSReturn       result        = kOSReturnError;
11605 	OSSharedPtr<OSDictionary> requestDict;
11606 	OSSharedPtr<IOUserServerCheckInToken> token;
11607 
11608 	if (!kextIdentifier || !serverName || !serverTag) {
11609 		result = kOSKextReturnInvalidArgument;
11610 		goto finish;
11611 	}
11612 
11613 	IORecursiveLockLock(sKextLock);
11614 
11615 	OSKextLog(/* kext */ NULL,
11616 	    kOSKextLogDebugLevel |
11617 	    kOSKextLogGeneralFlag,
11618 	    "Requesting daemon launch for %s with serverName %s and tag %llu",
11619 	    kextIdentifier->getCStringNoCopy(),
11620 	    serverName->getCStringNoCopy(),
11621 	    serverTag->unsigned64BitValue()
11622 	    );
11623 
11624 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict);
11625 	if (result != kOSReturnSuccess) {
11626 		goto finish;
11627 	}
11628 
11629 	token.reset(IOUserServerCheckInToken::create(), OSNoRetain);
11630 	if (!token) {
11631 		result = kOSKextReturnNoMemory;
11632 		goto finish;
11633 	}
11634 
11635 	if (!_OSKextSetRequestArgument(requestDict.get(),
11636 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
11637 	    !_OSKextSetRequestArgument(requestDict.get(),
11638 	    kKextRequestArgumentDriverExtensionServerName, serverName) ||
11639 	    !_OSKextSetRequestArgument(requestDict.get(),
11640 	    kKextRequestArgumentDriverExtensionServerTag, serverTag) ||
11641 	    !_OSKextSetRequestArgument(requestDict.get(),
11642 	    kKextRequestArgumentCheckInToken, token.get())) {
11643 		result = kOSKextReturnNoMemory;
11644 		goto finish;
11645 	}
11646 
11647 	/* Only post the requests after all the other potential failure points
11648 	 * have been passed.
11649 	 */
11650 	if (!sKernelRequests->setObject(requestDict.get())) {
11651 		result = kOSKextReturnNoMemory;
11652 		goto finish;
11653 	}
11654 	*checkInToken = token.detach();
11655 	OSKext::pingIOKitDaemon();
11656 
11657 	result = kOSReturnSuccess;
11658 finish:
11659 	IORecursiveLockUnlock(sKextLock);
11660 	return result;
11661 }
11662 
11663 /*********************************************************************
11664 * Assumes sKextLock is held.
11665 *********************************************************************/
11666 /* static */
11667 OSReturn
11668 OSKext::dequeueCallbackForRequestTag(
11669 	OSKextRequestTag    requestTag,
11670 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
11671 {
11672 	OSDictionary * callbackRecordOutRaw = NULL;
11673 	OSReturn result;
11674 
11675 	result = dequeueCallbackForRequestTag(requestTag,
11676 	    &callbackRecordOutRaw);
11677 
11678 	if (kOSReturnSuccess == result) {
11679 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
11680 	}
11681 
11682 	return result;
11683 }
11684 OSReturn
11685 OSKext::dequeueCallbackForRequestTag(
11686 	OSKextRequestTag    requestTag,
11687 	OSDictionary     ** callbackRecordOut)
11688 {
11689 	OSReturn   result = kOSReturnError;
11690 	OSSharedPtr<OSNumber> requestTagNum;
11691 
11692 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
11693 	    8 * sizeof(requestTag));
11694 	if (!requestTagNum) {
11695 		goto finish;
11696 	}
11697 
11698 	result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(),
11699 	    callbackRecordOut);
11700 
11701 finish:
11702 	return result;
11703 }
11704 
11705 /*********************************************************************
11706 * Assumes sKextLock is held.
11707 *********************************************************************/
11708 /* static */
11709 OSReturn
11710 OSKext::dequeueCallbackForRequestTag(
11711 	OSNumber     *    requestTagNum,
11712 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
11713 {
11714 	OSDictionary * callbackRecordOutRaw = NULL;
11715 	OSReturn result;
11716 
11717 	result = dequeueCallbackForRequestTag(requestTagNum,
11718 	    &callbackRecordOutRaw);
11719 
11720 	if (kOSReturnSuccess == result) {
11721 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
11722 	}
11723 
11724 	return result;
11725 }
11726 OSReturn
11727 OSKext::dequeueCallbackForRequestTag(
11728 	OSNumber     *    requestTagNum,
11729 	OSDictionary ** callbackRecordOut)
11730 {
11731 	OSReturn        result          = kOSKextReturnInvalidArgument;
11732 	OSDictionary  * callbackRecord  = NULL;        // retain if matched!
11733 	OSNumber      * callbackTagNum  = NULL;        // do not release
11734 	unsigned int    count, i;
11735 
11736 	result = kOSReturnError;
11737 	count = sRequestCallbackRecords->getCount();
11738 	for (i = 0; i < count; i++) {
11739 		callbackRecord = OSDynamicCast(OSDictionary,
11740 		    sRequestCallbackRecords->getObject(i));
11741 		if (!callbackRecord) {
11742 			goto finish;
11743 		}
11744 
11745 		/* If we don't find a tag, we basically have a leak here. Maybe
11746 		 * we should just remove it.
11747 		 */
11748 		callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
11749 			    callbackRecord, kKextRequestArgumentRequestTagKey));
11750 		if (!callbackTagNum) {
11751 			goto finish;
11752 		}
11753 
11754 		/* We could be even more paranoid and check that all the incoming
11755 		 * args match what's in the callback record.
11756 		 */
11757 		if (callbackTagNum->isEqualTo(requestTagNum)) {
11758 			if (callbackRecordOut) {
11759 				*callbackRecordOut = callbackRecord;
11760 				callbackRecord->retain();
11761 			}
11762 			sRequestCallbackRecords->removeObject(i);
11763 			result = kOSReturnSuccess;
11764 			goto finish;
11765 		}
11766 	}
11767 	result = kOSKextReturnNotFound;
11768 
11769 finish:
11770 	return result;
11771 }
11772 
11773 
11774 /*********************************************************************
11775 * Busy timeout triage
11776 *********************************************************************/
11777 /* static */
11778 bool
11779 OSKext::pendingIOKitDaemonRequests(void)
11780 {
11781 	return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
11782 }
11783 
11784 /*********************************************************************
11785 * Acquires and releases sKextLock
11786 *
11787 * This function is designed to be called exactly once on boot by
11788 * the IOKit management daemon, kernelmanagerd. It gathers all codeless
11789 * kext and dext personalities, and then attempts to map a System
11790 * (pageable) KC and an Auxiliary (aux) KC.
11791 *
11792 * Even if the pageable or aux KC fail to load - this function will
11793 * not allow a second call. This avoids security issues where
11794 * kernelmanagerd has been compromised or the pageable kc has been
11795 * tampered with and the attacker attempts to re-load a malicious
11796 * variant.
11797 *
11798 * Return: if a KC fails to load the return value will contain:
11799 *         kOSKextReturnKCLoadFailure. If the pageable KC fails,
11800 *         the return value will contain kOSKextReturnKCLoadFailureSystemKC.
11801 *         Similarly, if the aux kc load fails, the return value will
11802 *         contain kOSKextReturnKCLoadFailureAuxKC. The two values
11803 *         compose with each other and with kOSKextReturnKCLoadFailure.
11804 *********************************************************************/
11805 /* static */
11806 OSReturn
11807 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused)
11808 {
11809 	static bool daemon_ready = false;
11810 
11811 	OSReturn ret = kOSKextReturnInvalidArgument;
11812 	OSReturn kcerr = 0;
11813 	bool start_matching = false;
11814 
11815 	bool allow_fileset_load = !daemon_ready;
11816 #if !(defined(__x86_64__) || defined(__i386__))
11817 	/* never allow KCs full of kexts on non-x86 machines */
11818 	allow_fileset_load = false;
11819 #endif
11820 
11821 	/*
11822 	 * Get the args from the request. Right now we need the file
11823 	 * name for the pageable and the aux kext collection file sets.
11824 	 */
11825 	OSDictionary * requestArgs                = NULL;        // do not release
11826 	OSString     * pageable_filepath          = NULL;        // do not release
11827 	OSString     * aux_filepath               = NULL;        // do not release
11828 	OSArray      * codeless_kexts             = NULL;        // do not release
11829 
11830 	kernel_mach_header_t *akc_mh              = NULL;
11831 
11832 	requestArgs = OSDynamicCast(OSDictionary,
11833 	    requestDict->getObject(kKextRequestArgumentsKey));
11834 
11835 	if (requestArgs == NULL) {
11836 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
11837 		    "KextLog: No arguments in plist for loading fileset kext\n");
11838 		printf("KextLog: No arguments in plist for loading fileset kext\n");
11839 		return ret;
11840 	}
11841 
11842 	ret = kOSKextReturnDisabled;
11843 
11844 	IORecursiveLockLock(sKextLock);
11845 
11846 	pageable_filepath = OSDynamicCast(OSString,
11847 	    requestArgs->getObject(kKextRequestArgumentPageableKCFilename));
11848 
11849 	if (allow_fileset_load && pageable_filepath != NULL) {
11850 		printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy());
11851 
11852 		ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable);
11853 		if (ret) {
11854 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
11855 			    "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
11856 
11857 			printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
11858 			ret = kOSKextReturnKCLoadFailure;
11859 			kcerr |= kOSKextReturnKCLoadFailureSystemKC;
11860 			goto try_auxkc;
11861 		}
11862 		/*
11863 		 * Even if the AuxKC fails to load, we still want to send
11864 		 * the System KC personalities to the catalog for matching
11865 		 */
11866 		start_matching = true;
11867 	} else if (pageable_filepath != NULL) {
11868 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
11869 		    "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy());
11870 		ret = kOSKextReturnUnsupported;
11871 	}
11872 
11873 try_auxkc:
11874 	akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
11875 	if (akc_mh) {
11876 		/*
11877 		 * If we try to load a deferred AuxKC, then don't ever attempt
11878 		 * a filesystem map of a file
11879 		 */
11880 		allow_fileset_load = false;
11881 
11882 		/*
11883 		 * This function is only called once per boot, so we haven't
11884 		 * yet loaded an AuxKC. If we have registered the AuxKC mach
11885 		 * header, that means that the kext collection has been placed
11886 		 * in memory for us by the booter, and is waiting for us to
11887 		 * process it.  Grab the deferred XML plist of info
11888 		 * dictionaries and add all the kexts.
11889 		 */
11890 		OSSharedPtr<OSObject>  parsedXML;
11891 		OSSharedPtr<OSData>    loaded_kcUUID;
11892 		OSDictionary          *infoDict;
11893 		parsedXML = consumeDeferredKextCollection(KCKindAuxiliary);
11894 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
11895 		if (infoDict) {
11896 			bool added;
11897 			printf("KextLog: Adding kexts from in-memory AuxKC\n");
11898 			added = OSKext::addKextsFromKextCollection(akc_mh, infoDict,
11899 			    kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary);
11900 			if (!loaded_kcUUID) {
11901 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
11902 				    "KextLog: WARNING: did not find UUID in deferred Aux KC!");
11903 			} else if (!added) {
11904 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
11905 				    "KextLog: WARNING: Failed to load AuxKC from memory.");
11906 			}
11907 			/* only return success if the pageable load (above) was successful */
11908 			if (ret != kOSKextReturnKCLoadFailure) {
11909 				ret = kOSReturnSuccess;
11910 			}
11911 			/* the registration of the AuxKC parsed out the KC's UUID already */
11912 		} else {
11913 			if (daemon_ready) {
11914 				/*
11915 				 * Complain, but don't return an error if this isn't the first time the
11916 				 * IOKit daemon is checking in. If the daemon ever restarts, we will
11917 				 * hit this case because we've already consumed the deferred personalities.
11918 				 * We return success here so that a call to this function from a restarted
11919 				 * daemon with no codeless kexts will succeed.
11920 				 */
11921 				OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
11922 				    "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart");
11923 				if (ret != kOSKextReturnKCLoadFailure) {
11924 					ret = kOSReturnSuccess;
11925 				}
11926 			} else {
11927 				/* this is a real error case */
11928 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11929 				    "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary");
11930 				printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n");
11931 				ret = kOSKextReturnKCLoadFailure;
11932 				kcerr |= kOSKextReturnKCLoadFailureAuxKC;
11933 			}
11934 		}
11935 	}
11936 
11937 	aux_filepath = OSDynamicCast(OSString,
11938 	    requestArgs->getObject(kKextRequestArgumentAuxKCFilename));
11939 	if (allow_fileset_load && aux_filepath != NULL) {
11940 		printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy());
11941 
11942 		ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary);
11943 		if (ret) {
11944 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
11945 			    "KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
11946 
11947 			printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
11948 			ret = kOSKextReturnKCLoadFailure;
11949 			kcerr |= kOSKextReturnKCLoadFailureAuxKC;
11950 			goto try_codeless;
11951 		}
11952 		start_matching = true;
11953 	} else if (aux_filepath != NULL) {
11954 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
11955 		    "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy());
11956 		if (ret != kOSKextReturnKCLoadFailure) {
11957 			ret = kOSKextReturnUnsupported;
11958 		}
11959 	}
11960 
11961 try_codeless:
11962 	/*
11963 	 * Load codeless kexts last so that there is no possibilty of a
11964 	 * codeless kext bundle ID preventing a kext in the system KC from
11965 	 * loading
11966 	 */
11967 	codeless_kexts = OSDynamicCast(OSArray,
11968 	    requestArgs->getObject(kKextRequestArgumentCodelessPersonalities));
11969 	if (codeless_kexts != NULL) {
11970 		uint32_t count = codeless_kexts->getCount();
11971 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
11972 		    "KextLog: loading %d codeless kexts/dexts", count);
11973 		for (uint32_t i = 0; i < count; i++) {
11974 			OSDictionary *infoDict;
11975 			infoDict = OSDynamicCast(OSDictionary,
11976 			    codeless_kexts->getObject(i));
11977 			if (!infoDict) {
11978 				continue;
11979 			}
11980 			// instantiate a new kext, and don't hold a reference
11981 			// (the kext subsystem will hold one implicitly)
11982 			OSKext::withCodelessInfo(infoDict);
11983 		}
11984 		/* ignore errors that are not KC load failures */
11985 		if (ret != kOSKextReturnKCLoadFailure) {
11986 			ret = kOSReturnSuccess;
11987 		}
11988 		start_matching = true;
11989 	}
11990 
11991 	/* send personalities to the IOCatalog once */
11992 	if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) {
11993 		OSKext::sendAllKextPersonalitiesToCatalog(true);
11994 		/*
11995 		 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark
11996 		 * things as active and start all the delayed matching: the
11997 		 * dext and codeless kext personalities should have all been
11998 		 * delivered via this one call.
11999 		 */
12000 		if (!daemon_ready) {
12001 			OSKext::setIOKitDaemonActive();
12002 			OSKext::setDeferredLoadSucceeded(TRUE);
12003 			IOService::iokitDaemonLaunched();
12004 		}
12005 		if (sOSKextWasResetAfterUserspaceReboot) {
12006 			sOSKextWasResetAfterUserspaceReboot = false;
12007 			OSKext::setIOKitDaemonActive();
12008 			IOService::startDeferredMatches();
12009 		}
12010 	}
12011 
12012 	if (ret == kOSKextReturnKCLoadFailure) {
12013 		ret |= kcerr;
12014 	}
12015 
12016 	/*
12017 	 * Only allow this function to attempt to load the pageable and
12018 	 * aux KCs once per boot.
12019 	 */
12020 	daemon_ready = true;
12021 
12022 	IORecursiveLockUnlock(sKextLock);
12023 
12024 	return ret;
12025 }
12026 
12027 OSReturn
12028 OSKext::resetMutableSegments(void)
12029 {
12030 	kernel_segment_command_t *seg = NULL;
12031 	kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
12032 	u_int index = 0;
12033 	OSKextSavedMutableSegment *savedSegment = NULL;
12034 	uintptr_t kext_slide = PE_get_kc_slide(kc_type);
12035 	OSReturn err;
12036 
12037 	if (!savedMutableSegments) {
12038 		OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
12039 		    "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString());
12040 		err = kOSKextReturnInternalError;
12041 		goto finish;
12042 	}
12043 
12044 	for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) {
12045 		if (!segmentIsMutable(seg)) {
12046 			continue;
12047 		}
12048 		uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
12049 		uint64_t vmsize = seg->vmsize;
12050 		err = kOSKextReturnInternalError;
12051 		for (index = 0; index < savedMutableSegments->getCount(); index++) {
12052 			savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index));
12053 			assert(savedSegment);
12054 			if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) {
12055 				OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
12056 				    "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12057 				err = savedSegment->restoreContents(seg);
12058 				if (err != kOSReturnSuccess) {
12059 					panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12060 				}
12061 			}
12062 		}
12063 		if (err != kOSReturnSuccess) {
12064 			panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12065 		}
12066 	}
12067 	err = kOSReturnSuccess;
12068 finish:
12069 	return err;
12070 }
12071 
12072 
12073 /*********************************************************************
12074 * Assumes sKextLock is held.
12075 *********************************************************************/
12076 /* static */
12077 OSReturn
12078 OSKext::loadKCFileSet(
12079 	const char *filepath,
12080 	kc_kind_t   type)
12081 {
12082 #if VM_MAPPED_KEXTS
12083 	/* we only need to load filesets on systems that support VM_MAPPED kexts */
12084 	OSReturn err;
12085 	struct vnode *vp = NULL;
12086 	void *fileset_control;
12087 	off_t fsize;
12088 	bool pageable = (type == KCKindPageable);
12089 
12090 	if ((pageable && pageableKCloaded) ||
12091 	    (!pageable && auxKCloaded)) {
12092 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12093 		    "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux"));
12094 
12095 		return kOSKextReturnInvalidArgument;
12096 	}
12097 
12098 	/* Do not allow AuxKC to load if Pageable KC is not loaded */
12099 	if (!pageable && !pageableKCloaded) {
12100 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12101 		    "Trying to load the Aux KC without loading the Pageable KC");
12102 		return kOSKextReturnInvalidArgument;
12103 	}
12104 
12105 	fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize);
12106 
12107 	if (fileset_control == NULL) {
12108 		printf("Could not get memory control object for file %s", filepath);
12109 
12110 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12111 		    "Could not get memory control object for file %s", filepath);
12112 		return kOSKextReturnInvalidArgument;
12113 	}
12114 	if (vp == NULL) {
12115 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12116 		    "Could not find vnode for file %s", filepath);
12117 		return kOSKextReturnInvalidArgument;
12118 	}
12119 
12120 	kernel_mach_header_t *mh = NULL;
12121 	uintptr_t slide = 0;
12122 
12123 #if CONFIG_CSR
12124 	/*
12125 	 * When SIP is enabled, the KC we map must be SIP-protected
12126 	 */
12127 	if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) {
12128 		struct vnode_attr va;
12129 		int error;
12130 		VATTR_INIT(&va);
12131 		VATTR_WANTED(&va, va_flags);
12132 		error = vnode_getattr(vp, &va, vfs_context_current());
12133 		if (error) {
12134 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12135 			    "vnode_getattr(%s) failed (error=%d)", filepath, error);
12136 			err = kOSKextReturnInternalError;
12137 			goto finish;
12138 		}
12139 		if (!(va.va_flags & SF_RESTRICTED)) {
12140 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12141 			    "Path to KC '%s' is not SIP-protected", filepath);
12142 			err = kOSKextReturnInvalidArgument;
12143 			goto finish;
12144 		}
12145 	}
12146 #endif
12147 
12148 	err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL);
12149 	if (err) {
12150 		printf("KextLog: mapKCFileSet returned %d\n", err);
12151 
12152 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12153 		    "mapKCFileSet returned %d\n", err);
12154 
12155 		err = kOSKextReturnInvalidArgument;
12156 	}
12157 
12158 #if CONFIG_CSR
12159 finish:
12160 #endif
12161 	/* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */
12162 	assert(vp != NULL);
12163 	if (err == kOSReturnSuccess) {
12164 		PE_set_kc_vp(type, vp);
12165 		if (pageable) {
12166 			pageableKCloaded = true;
12167 		} else {
12168 			auxKCloaded = true;
12169 		}
12170 	} else {
12171 		vnode_put(vp);
12172 	}
12173 
12174 	return err;
12175 #else
12176 	(void)filepath;
12177 	(void)type;
12178 	return kOSKextReturnUnsupported;
12179 #endif // VM_MAPPED_KEXTS
12180 }
12181 
12182 #if defined(__x86_64__) || defined(__i386__)
12183 /*********************************************************************
12184 * Assumes sKextLock is held.
12185 *********************************************************************/
12186 /* static */
12187 OSReturn
12188 OSKext::mapKCFileSet(
12189 	void                 *control,
12190 	vm_size_t            fsize,
12191 	kernel_mach_header_t **mhp,
12192 	off_t                file_offset,
12193 	uintptr_t            *slidep,
12194 	bool                 pageable,
12195 	void                 *map_entry_list)
12196 {
12197 	bool fileset_load = false;
12198 	kern_return_t ret;
12199 	OSReturn err;
12200 	kernel_section_t *infoPlistSection = NULL;
12201 	OSDictionary *infoDict = NULL;
12202 
12203 	OSSharedPtr<OSObject> parsedXML;
12204 	OSSharedPtr<OSString> errorString;
12205 	OSSharedPtr<OSData> loaded_kcUUID;
12206 
12207 	/* Check if initial load for file set */
12208 	if (*mhp == NULL) {
12209 		fileset_load = true;
12210 
12211 		/* Get a page aligned address from kext map to map the file */
12212 		vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize);
12213 		if (pagealigned_addr == 0) {
12214 			return kOSKextReturnNoMemory;
12215 		}
12216 
12217 		*mhp = (kernel_mach_header_t *)pagealigned_addr;
12218 
12219 		/* Allocate memory for bailout mechanism */
12220 		map_entry_list = allocate_kcfileset_map_entry_list();
12221 		if (map_entry_list == NULL) {
12222 			return kOSKextReturnNoMemory;
12223 		}
12224 	}
12225 
12226 	uintptr_t *slideptr = fileset_load ? slidep : NULL;
12227 	err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list);
12228 	/* mhp and slideptr are updated by mapKCTextSegment */
12229 	if (err) {
12230 		if (fileset_load) {
12231 			deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12232 		}
12233 		return err;
12234 	}
12235 
12236 	/* Initialize the kc header globals */
12237 	if (fileset_load) {
12238 		if (pageable) {
12239 			PE_set_kc_header(KCKindPageable, *mhp, *slidep);
12240 		} else {
12241 			PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep);
12242 		}
12243 	}
12244 
12245 	/* Iterate through all the segments and map necessary segments */
12246 	struct load_command *lcp = (struct load_command *) (*mhp + 1);
12247 	for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) {
12248 		vm_map_offset_t start;
12249 		kernel_mach_header_t *k_mh = NULL;
12250 		kernel_segment_command_t * seg = NULL;
12251 		struct fileset_entry_command *fse = NULL;
12252 
12253 		if (lcp->cmd == LC_SEGMENT_KERNEL) {
12254 			seg = (kernel_segment_command_t *)lcp;
12255 			start = ((uintptr_t)(seg->vmaddr)) + *slidep;
12256 		} else if (lcp->cmd == LC_FILESET_ENTRY) {
12257 			fse = (struct fileset_entry_command *)lcp;
12258 			k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep);
12259 
12260 			/* Map the segments of the mach-o binary */
12261 			err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list);
12262 			if (err) {
12263 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12264 				return kOSKextReturnInvalidArgument;
12265 			}
12266 			continue;
12267 		} else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) {
12268 			/* Check if the Aux KC is built pageable style */
12269 			if (!pageable && !fileset_load && !auxKCloaded) {
12270 				resetAuxKCSegmentOnUnload = true;
12271 			}
12272 			continue;
12273 		} else {
12274 			continue;
12275 		}
12276 
12277 		if (fileset_load) {
12278 			if (seg->vmsize == 0) {
12279 				continue;
12280 			}
12281 
12282 			/* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */
12283 			if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 &&
12284 			    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 &&
12285 			    strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 &&
12286 			    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) {
12287 				continue;
12288 			}
12289 		} else {
12290 			if (seg->vmsize == 0) {
12291 				continue;
12292 			}
12293 
12294 			/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
12295 			if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
12296 			    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
12297 			    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
12298 				continue;
12299 			}
12300 		}
12301 
12302 		ret = vm_map_kcfileset_segment(
12303 			&start, seg->vmsize,
12304 			(memory_object_control_t)control, seg->fileoff, seg->maxprot);
12305 
12306 		if (ret != KERN_SUCCESS) {
12307 			if (fileset_load) {
12308 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12309 			}
12310 			return kOSKextReturnInvalidArgument;
12311 		}
12312 		add_kcfileset_map_entry(map_entry_list, start, seg->vmsize);
12313 	}
12314 
12315 	/* Return if regular mach-o */
12316 	if (!fileset_load) {
12317 		return 0;
12318 	}
12319 
12320 	/*
12321 	 * Fixup for the Pageable KC and the Aux KC is done by
12322 	 * i386_slide_kext_collection_mh_addrs, but it differs in
12323 	 * following ways:
12324 	 *
12325 	 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands.
12326 	 * The fixup of kext segments and kext load commands are done at kext
12327 	 * load time by calling i386_slide_individual_kext.
12328 	 *
12329 	 * AuxKC old style: Fixup all the segments and all the load commands.
12330 	 *
12331 	 * AuxKC pageable style: Same as the Pageable KC.
12332 	 */
12333 	bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false));
12334 	ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header);
12335 	if (ret != KERN_SUCCESS) {
12336 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12337 		return kOSKextReturnInvalidArgument;
12338 	}
12339 
12340 	/* Get the prelink info dictionary */
12341 	infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection);
12342 	parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
12343 	if (parsedXML) {
12344 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
12345 	}
12346 
12347 	if (!infoDict) {
12348 		const char *errorCString = "(unknown error)";
12349 
12350 		if (errorString && errorString->getCStringNoCopy()) {
12351 			errorCString = errorString->getCStringNoCopy();
12352 		} else if (parsedXML) {
12353 			errorCString = "not a dictionary";
12354 		}
12355 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12356 		    "Error unserializing kext info plist section: %s.", errorCString);
12357 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12358 		return kOSKextReturnInvalidArgument;
12359 	}
12360 
12361 	/* Validate that the Kext Collection is prelinked to the loaded KC */
12362 	err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary);
12363 	if (err) {
12364 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12365 		return kOSKextReturnInvalidArgument;
12366 	}
12367 
12368 	/* Set Protection of Segments */
12369 	OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary);
12370 
12371 	OSKext::addKextsFromKextCollection(*mhp,
12372 	    infoDict, kPrelinkTextSegment,
12373 	    loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary);
12374 
12375 	/* Copy in the KC UUID */
12376 	if (!loaded_kcUUID) {
12377 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12378 		    "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux");
12379 	} else if (pageable) {
12380 		pageablekc_uuid_valid = TRUE;
12381 		memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
12382 		uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string);
12383 	} else {
12384 		auxkc_uuid_valid = TRUE;
12385 		memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
12386 		uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
12387 	}
12388 
12389 	deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable);
12390 
12391 	return 0;
12392 }
12393 
12394 /*********************************************************************
12395 * Assumes sKextLock is held.
12396 *********************************************************************/
12397 /* static */
12398 OSReturn
12399 OSKext::mapKCTextSegment(
12400 	void                 *control,
12401 	kernel_mach_header_t **mhp,
12402 	off_t                file_offset,
12403 	uintptr_t            *slidep,
12404 	void                 *map_entry_list)
12405 {
12406 	kern_return_t ret;
12407 	vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t),
12408 	    PAGE_MASK);
12409 	vm_map_offset_t load_command_map_size = 0;
12410 	kernel_mach_header_t *base_mh = *mhp;
12411 
12412 	/* Map the mach header at start of fileset for now (vmaddr = 0) */
12413 	ret = vm_map_kcfileset_segment(
12414 		(vm_map_offset_t *)&base_mh, mach_header_map_size,
12415 		(memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE));
12416 
12417 	if (ret != KERN_SUCCESS) {
12418 		printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret);
12419 
12420 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12421 		    "Failed to map mach header of kc fileset with error %d", ret);
12422 		return kOSKextReturnInvalidArgument;
12423 	}
12424 
12425 	if (slidep) {
12426 		/* Verify that it's an MH_FILESET */
12427 		if (base_mh->filetype != MH_FILESET) {
12428 			printf("Kext Log: mapKCTextSegment mach header filetype"
12429 			    " is not an MH_FILESET, it is %x", base_mh->filetype);
12430 
12431 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12432 			    "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype);
12433 
12434 			/* Unmap the mach header */
12435 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12436 			return kOSKextReturnInvalidArgument;
12437 		}
12438 	}
12439 
12440 	/* Map the remaining pages of load commands */
12441 	if (base_mh->sizeofcmds > mach_header_map_size) {
12442 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
12443 		load_command_map_size = base_mh->sizeofcmds - mach_header_map_size;
12444 
12445 		/* Map the load commands */
12446 		ret = vm_map_kcfileset_segment(
12447 			&load_command_addr, load_command_map_size,
12448 			(memory_object_control_t)control, file_offset + mach_header_map_size,
12449 			(VM_PROT_READ | VM_PROT_WRITE));
12450 
12451 		if (ret != KERN_SUCCESS) {
12452 			printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret);
12453 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12454 			    "Failed to map load commands of kc fileset with error %d", ret);
12455 
12456 			/* Unmap the mach header */
12457 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12458 			return kOSKextReturnInvalidArgument;
12459 		}
12460 	}
12461 
12462 	kernel_segment_command_t *text_seg;
12463 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT);
12464 
12465 	/* Calculate the slide and vm addr of mach header */
12466 	if (slidep) {
12467 		*mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr);
12468 		*slidep = ((uintptr_t)*mhp) - text_seg->vmaddr;
12469 	}
12470 
12471 	/* Cache the text segment size and file offset before unmapping */
12472 	vm_map_offset_t text_segment_size = text_seg->vmsize;
12473 	vm_object_offset_t text_segment_fileoff = text_seg->fileoff;
12474 	vm_prot_t text_maxprot = text_seg->maxprot;
12475 
12476 	/* Unmap the first page and loadcommands and map the text segment */
12477 	ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12478 	assert(ret == KERN_SUCCESS);
12479 
12480 	if (load_command_map_size) {
12481 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
12482 		ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size);
12483 		assert(ret == KERN_SUCCESS);
12484 	}
12485 
12486 	/* Map the text segment at actual vm addr specified in fileset */
12487 	ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size,
12488 	    (memory_object_control_t)control, text_segment_fileoff, text_maxprot);
12489 	if (ret != KERN_SUCCESS) {
12490 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12491 		    "Failed to map Text segment of kc fileset with error %d", ret);
12492 		return kOSKextReturnInvalidArgument;
12493 	}
12494 
12495 	add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size);
12496 	return 0;
12497 }
12498 
12499 /*********************************************************************
12500 * Assumes sKextLock is held.
12501 *********************************************************************/
12502 /* static */
12503 OSReturn
12504 OSKext::protectKCFileSet(
12505 	kernel_mach_header_t *mh,
12506 	kc_kind_t            type)
12507 {
12508 	vm_map_t                    kext_map        = g_kext_map;
12509 	kernel_segment_command_t  * seg             = NULL;
12510 	vm_map_offset_t             start           = 0;
12511 	vm_map_offset_t             end             = 0;
12512 	OSReturn                    ret             = 0;
12513 
12514 	/* Set VM permissions */
12515 	seg = firstsegfromheader((kernel_mach_header_t *)mh);
12516 	while (seg) {
12517 		start = round_page(seg->vmaddr);
12518 		end = trunc_page(seg->vmaddr + seg->vmsize);
12519 
12520 		/*
12521 		 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS
12522 		 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT
12523 		 * for the Aux KC as well.
12524 		 */
12525 		if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 ||
12526 		    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 ||
12527 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 ||
12528 		    (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload &&
12529 		    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) {
12530 			ret = OSKext_protect((kernel_mach_header_t *)mh,
12531 			    kext_map, start, end, seg->maxprot, TRUE, type);
12532 			if (ret != KERN_SUCCESS) {
12533 				printf("OSKext protect failed with error %d", ret);
12534 				return kOSKextReturnInvalidArgument;
12535 			}
12536 
12537 			ret = OSKext_protect((kernel_mach_header_t *)mh,
12538 			    kext_map, start, end, seg->initprot, FALSE, type);
12539 			if (ret != KERN_SUCCESS) {
12540 				printf("OSKext protect failed with error %d", ret);
12541 				return kOSKextReturnInvalidArgument;
12542 			}
12543 
12544 			ret = OSKext_wire((kernel_mach_header_t *)mh,
12545 			    kext_map, start, end, seg->initprot, FALSE, type);
12546 			if (ret != KERN_SUCCESS) {
12547 				printf("OSKext wire failed with error %d", ret);
12548 				return kOSKextReturnInvalidArgument;
12549 			}
12550 		}
12551 
12552 		seg = nextsegfromheader((kernel_mach_header_t *) mh, seg);
12553 	}
12554 
12555 	return 0;
12556 }
12557 
12558 /*********************************************************************
12559 * Assumes sKextLock is held.
12560 *********************************************************************/
12561 /* static */
12562 void
12563 OSKext::freeKCFileSetcontrol(void)
12564 {
12565 	PE_reset_all_kc_vp();
12566 }
12567 
12568 /*********************************************************************
12569 * Assumes sKextLock is held.
12570 *
12571 * resetKCFileSetSegments: Kext start function expects data segment to
12572 * be pristine on every load, unmap the dirty segments on unload and
12573 * remap them from FileSet on disk. Remap all segments of kext since
12574 * fixups are done per kext and not per segment.
12575 *********************************************************************/
12576 OSReturn
12577 OSKext::resetKCFileSetSegments(void)
12578 {
12579 	kernel_segment_command_t *seg = NULL;
12580 	kernel_segment_command_t *text_seg;
12581 	uint32_t text_fileoff;
12582 	kernel_mach_header_t *k_mh = NULL;
12583 	uintptr_t slide;
12584 	struct vnode *vp = NULL;
12585 	void *fileset_control = NULL;
12586 	bool pageable = (kc_type == KCKindPageable);
12587 	OSReturn err;
12588 	kern_return_t kr;
12589 
12590 	/* Check the vnode reference is still available */
12591 	vp = (struct vnode *)PE_get_kc_vp(kc_type);
12592 	if (vp == NULL) {
12593 		OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
12594 		    "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString());
12595 		return kOSKextReturnInternalError;
12596 	}
12597 
12598 	fileset_control = ubc_getobject(vp, 0);
12599 	assert(fileset_control != NULL);
12600 
12601 	OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
12602 	    "Kext %s resetting all segments", getIdentifierCString());
12603 
12604 	k_mh = (kernel_mach_header_t *)kmod_info->address;
12605 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT);
12606 	text_fileoff = text_seg->fileoff;
12607 	slide = PE_get_kc_slide(kc_type);
12608 
12609 	seg = firstsegfromheader((kernel_mach_header_t *)k_mh);
12610 	while (seg) {
12611 		if (seg->vmsize == 0) {
12612 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12613 			continue;
12614 		}
12615 
12616 		/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
12617 		if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
12618 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
12619 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
12620 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12621 			continue;
12622 		}
12623 
12624 		kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize);
12625 		assert(kr == KERN_SUCCESS);
12626 		seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12627 	}
12628 
12629 	/* Unmap the text segment */
12630 	kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize);
12631 	assert(kr == KERN_SUCCESS);
12632 
12633 	/* Map all the segments of the kext */
12634 	err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL);
12635 	if (err) {
12636 		panic("Could not reset segments of a mapped kext, error %x", err);
12637 	}
12638 
12639 	/* Update address in kmod_info, since it has been reset */
12640 	if (kmod_info->address) {
12641 		kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide);
12642 	}
12643 
12644 	return 0;
12645 }
12646 
12647 /*********************************************************************
12648 * Mechanism to track all segment mapping while mapping KC fileset.
12649 *********************************************************************/
12650 
12651 struct kcfileset_map_entry {
12652 	vm_map_offset_t me_start;
12653 	vm_map_offset_t me_size;
12654 };
12655 
12656 struct kcfileset_map_entry_list {
12657 	int                        kme_list_count;
12658 	int                        kme_list_index;
12659 	struct kcfileset_map_entry kme_list[];
12660 };
12661 
12662 #define KCFILESET_MAP_ENTRY_MAX (16380)
12663 
12664 static void *
12665 allocate_kcfileset_map_entry_list(void)
12666 {
12667 	struct kcfileset_map_entry_list *entry_list;
12668 
12669 	entry_list = (struct kcfileset_map_entry_list *)kalloc(sizeof(struct kcfileset_map_entry_list) +
12670 	    (sizeof(struct kcfileset_map_entry) * KCFILESET_MAP_ENTRY_MAX));
12671 
12672 	entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX;
12673 	entry_list->kme_list_index = 0;
12674 	return entry_list;
12675 }
12676 
12677 static void
12678 add_kcfileset_map_entry(
12679 	void            *map_entry_list,
12680 	vm_map_offset_t start,
12681 	vm_map_offset_t size)
12682 {
12683 	if (map_entry_list == NULL) {
12684 		return;
12685 	}
12686 
12687 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
12688 
12689 	if (entry_list->kme_list_index >= entry_list->kme_list_count) {
12690 		panic("Ran out of map kc fileset list\n");
12691 	}
12692 
12693 	entry_list->kme_list[entry_list->kme_list_index].me_start = start;
12694 	entry_list->kme_list[entry_list->kme_list_index].me_size = size;
12695 
12696 	entry_list->kme_list_index++;
12697 }
12698 
12699 static void
12700 deallocate_kcfileset_map_entry_list_and_unmap_entries(
12701 	void      *map_entry_list,
12702 	boolean_t unmap_entries,
12703 	bool      pageable)
12704 {
12705 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
12706 
12707 	if (unmap_entries) {
12708 		for (int i = 0; i < entry_list->kme_list_index; i++) {
12709 			kern_return_t ret;
12710 			ret = vm_unmap_kcfileset_segment(
12711 				&(entry_list->kme_list[i].me_start),
12712 				entry_list->kme_list[i].me_size);
12713 			assert(ret == KERN_SUCCESS);
12714 		}
12715 
12716 		PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary);
12717 	}
12718 
12719 	kfree(entry_list, sizeof(struct kcfileset_map_entry_list) +
12720 	    (sizeof(struct kcfileset_map_entry) * KCFILESET_MAP_ENTRY_MAX));
12721 }
12722 
12723 /*********************************************************************
12724 * Mechanism to map kext segment.
12725 *********************************************************************/
12726 
12727 kern_return_t
12728 vm_map_kcfileset_segment(
12729 	vm_map_offset_t    *start,
12730 	vm_map_offset_t    size,
12731 	void               *control,
12732 	vm_object_offset_t fileoffset,
12733 	vm_prot_t          max_prot)
12734 {
12735 	vm_map_kernel_flags_t vmk_flags;
12736 	vmk_flags.vmkf_no_copy_on_read = 1;
12737 	vmk_flags.vmkf_cs_enforcement = 0;
12738 	vmk_flags.vmkf_cs_enforcement_override = 1;
12739 	kern_return_t ret;
12740 
12741 	/* Add Write to max prot to allow fixups */
12742 	max_prot = max_prot | VM_PROT_WRITE;
12743 
12744 	/*
12745 	 * Map the segments from file as COPY mappings to
12746 	 * make sure changes on disk to the file does not affect
12747 	 * mapped segments.
12748 	 */
12749 	ret = vm_map_enter_mem_object_control(
12750 		g_kext_map,
12751 		start,
12752 		size,
12753 		(mach_vm_offset_t)0,
12754 		VM_FLAGS_FIXED,
12755 		vmk_flags,
12756 		VM_KERN_MEMORY_OSKEXT,
12757 		(memory_object_control_t)control,
12758 		fileoffset,
12759 		TRUE,         /* copy */
12760 		(VM_PROT_READ | VM_PROT_WRITE), max_prot,
12761 		VM_INHERIT_NONE);
12762 
12763 	return ret;
12764 }
12765 
12766 kern_return_t
12767 vm_unmap_kcfileset_segment(
12768 	vm_map_offset_t    *start,
12769 	vm_map_offset_t    size)
12770 {
12771 	return mach_vm_deallocate(g_kext_map, *start, size);
12772 }
12773 
12774 #endif //(__x86_64__) || defined(__i386__)
12775 
12776 /*********************************************************************
12777 * Assumes sKextLock is held.
12778 *********************************************************************/
12779 /* static */
12780 OSReturn
12781 OSKext::validateKCFileSetUUID(
12782 	OSDictionary         *infoDict,
12783 	kc_kind_t            type)
12784 {
12785 	OSReturn ret           = kOSReturnSuccess;
12786 
12787 	if (!kernelcache_uuid_valid) {
12788 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12789 		    "validateKCFileSetUUID Boot KC UUID was not set at boot.");
12790 		ret = kOSKextReturnInvalidArgument;
12791 		goto finish;
12792 	}
12793 	ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey);
12794 	if (ret != 0) {
12795 		goto finish;
12796 	}
12797 
12798 #if defined(__x86_64__) || defined(__i386__)
12799 	/* Check if the Aux KC is prelinked to correct Pageable KC */
12800 	if (type == KCKindAuxiliary) {
12801 		if (!pageablekc_uuid_valid) {
12802 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12803 			    "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC.");
12804 			ret = kOSKextReturnInvalidArgument;
12805 			goto finish;
12806 		}
12807 		ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey);
12808 		if (ret != 0) {
12809 			goto finish;
12810 		}
12811 	}
12812 #endif //(__x86_64__) || defined(__i386__)
12813 
12814 	printf("KextLog: Collection UUID matches with loaded KCs.\n");
12815 finish:
12816 	return ret;
12817 }
12818 
12819 /*********************************************************************
12820 * Assumes sKextLock is held.
12821 *********************************************************************/
12822 /* static */
12823 OSReturn
12824 OSKext::validateKCUUIDfromPrelinkInfo(
12825 	uuid_t               *loaded_kcuuid,
12826 	kc_kind_t             type,
12827 	OSDictionary         *infoDict,
12828 	const char           *uuid_key)
12829 {
12830 	/* extract the UUID from the dictionary */
12831 	OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key));
12832 	if (!prelinkinfoKCUUID) {
12833 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12834 		    "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key);
12835 		return kOSKextReturnInvalidArgument;
12836 	}
12837 
12838 	if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) {
12839 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12840 		    "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength());
12841 		return kOSKextReturnInvalidArgument;
12842 	}
12843 
12844 	if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(),
12845 	    prelinkinfoKCUUID->getLength())) {
12846 		OSData       *info_dict_uuid;
12847 		uuid_string_t info_dict_uuid_str = {};
12848 		uuid_string_t expected_uuid_str = {};
12849 		uuid_string_t given_uuid_str = {};
12850 		uuid_t        given_uuid;
12851 
12852 		/* extract the KC UUID from the dictionary */
12853 		info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
12854 		if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) {
12855 			uuid_t tmp_uuid;
12856 			memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid));
12857 			uuid_unparse(tmp_uuid, info_dict_uuid_str);
12858 		}
12859 
12860 		uuid_unparse(*loaded_kcuuid, expected_uuid_str);
12861 		memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid));
12862 		uuid_unparse(given_uuid, given_uuid_str);
12863 
12864 		printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
12865 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
12866 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12867 		    "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
12868 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
12869 		if (type == KCKindPageable && sPanicOnKCMismatch) {
12870 			panic("System KC UUID %s linked against %s, but %s is loaded",
12871 			    info_dict_uuid_str, given_uuid_str, expected_uuid_str);
12872 		}
12873 		return kOSKextReturnInvalidArgument;
12874 	}
12875 
12876 	return 0;
12877 }
12878 
12879 /*********************************************************************
12880 * Assumes sKextLock is held.
12881 *********************************************************************/
12882 /* static */
12883 OSReturn
12884 OSKext::dispatchResource(OSDictionary * requestDict)
12885 {
12886 	OSReturn                        result          = kOSReturnError;
12887 	OSSharedPtr<OSDictionary>       callbackRecord;
12888 	OSNumber                      * requestTag      = NULL;        // do not release
12889 	OSNumber                      * requestResult   = NULL;        // do not release
12890 	OSData                        * dataObj         = NULL;        // do not release
12891 	uint32_t                        dataLength      = 0;
12892 	const void                    * dataPtr         = NULL;        // do not free
12893 	OSData                        * callbackWrapper = NULL;        // do not release
12894 	OSKextRequestResourceCallback   callback        = NULL;
12895 	OSData                        * contextWrapper  = NULL;        // do not release
12896 	void                          * context         = NULL;        // do not free
12897 	OSSharedPtr<OSKext>             callbackKext;
12898 
12899 	/* Get the args from the request. Right now we need the tag
12900 	 * to look up the callback record, and the result for invoking the callback.
12901 	 */
12902 	requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
12903 	    kKextRequestArgumentRequestTagKey));
12904 	requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
12905 	    kKextRequestArgumentResultKey));
12906 	if (!requestTag || !requestResult) {
12907 		result = kOSKextReturnInvalidArgument;
12908 		goto finish;
12909 	}
12910 
12911 	/* Look for a callback record matching this request's tag.
12912 	 */
12913 	result = dequeueCallbackForRequestTag(requestTag, callbackRecord);
12914 	if (result != kOSReturnSuccess) {
12915 		goto finish;
12916 	}
12917 
12918 	/*****
12919 	 * Get the context pointer of the callback record (if there is one).
12920 	 */
12921 	contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord.get(),
12922 	    kKextRequestArgumentContextKey));
12923 	context = _OSKextExtractPointer(contextWrapper);
12924 	if (contextWrapper && !context) {
12925 		goto finish;
12926 	}
12927 
12928 	callbackWrapper = OSDynamicCast(OSData,
12929 	    _OSKextGetRequestArgument(callbackRecord.get(),
12930 	    kKextRequestArgumentCallbackKey));
12931 	callback = _OSKextExtractCallbackPointer(callbackWrapper);
12932 	if (!callback) {
12933 		goto finish;
12934 	}
12935 
12936 	/* Check for a data obj. We might not have one and that's ok, that means
12937 	 * we didn't find the requested resource, and we still have to tell the
12938 	 * caller that via the callback.
12939 	 */
12940 	dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
12941 	    kKextRequestArgumentValueKey));
12942 	if (dataObj) {
12943 		dataPtr = dataObj->getBytesNoCopy();
12944 		dataLength = dataObj->getLength();
12945 	}
12946 
12947 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
12948 	if (!callbackKext) {
12949 		OSKextLog(/* kext */ NULL,
12950 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12951 		    "Can't invoke callback for resource request; ");
12952 		goto finish;
12953 	}
12954 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
12955 		OSKextLog(/* kext */ NULL,
12956 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12957 		    "Can't invoke kext resource callback; ");
12958 		goto finish;
12959 	}
12960 
12961 	(void)callback(requestTag->unsigned32BitValue(),
12962 	    (OSReturn)requestResult->unsigned32BitValue(),
12963 	    dataPtr, dataLength, context);
12964 
12965 	result = kOSReturnSuccess;
12966 
12967 finish:
12968 	return result;
12969 }
12970 
12971 /*********************************************************************
12972 * Assumes sKextLock is held.
12973 *********************************************************************/
12974 /* static */
12975 OSReturn
12976 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict)
12977 {
12978 	OSSharedPtr<OSDictionary> missingIDs;
12979 	OSArray *bundleIDList     = NULL; // do not release
12980 
12981 	bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
12982 		    requestDict, kKextRequestArgumentMissingBundleIDs));
12983 	if (!bundleIDList) {
12984 		return kOSKextReturnInvalidArgument;
12985 	}
12986 
12987 	missingIDs = OSDictionary::withCapacity(bundleIDList->getCount());
12988 	if (!missingIDs) {
12989 		return kOSKextReturnNoMemory;
12990 	}
12991 
12992 	uint32_t count, i;
12993 	count = bundleIDList->getCount();
12994 	for (i = 0; i < count; i++) {
12995 		OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i));
12996 		if (thisID) {
12997 			missingIDs->setObject(thisID, kOSBooleanFalse);
12998 		}
12999 	}
13000 
13001 	sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain);
13002 
13003 	return kOSReturnSuccess;
13004 }
13005 
13006 /*********************************************************************
13007 * Assumes sKextLock is held.
13008 *********************************************************************/
13009 /* static */
13010 OSReturn
13011 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict)
13012 {
13013 	bool loadable = true;
13014 	if (!kextIdentifier) {
13015 		return kOSKextReturnInvalidArgument;
13016 	}
13017 
13018 	if (requestDict) {
13019 		OSBoolean *loadableArg;
13020 		loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
13021 			    requestDict, kKextRequestArgumentBundleAvailability));
13022 		/* If we find the "Bundle Available" arg, and it's false, then
13023 		 * mark the bundle ID as _not_ loadable
13024 		 */
13025 		if (loadableArg && !loadableArg->getValue()) {
13026 			loadable = false;
13027 		}
13028 	}
13029 
13030 	if (!sNonLoadableKextsByID) {
13031 		sNonLoadableKextsByID = OSDictionary::withCapacity(1);
13032 	}
13033 
13034 	sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable));
13035 
13036 	OSKextLog(/* kext */ NULL,
13037 	    kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13038 	    "KextLog: AuxKC bundle %s marked as %s",
13039 	    kextIdentifier->getCStringNoCopy(),
13040 	    (loadable ? "loadable" : "NOT loadable"));
13041 
13042 	return kOSReturnSuccess;
13043 }
13044 
13045 /*********************************************************************
13046 *********************************************************************/
13047 /* static */
13048 void
13049 OSKext::invokeRequestCallback(
13050 	OSDictionary * callbackRecord,
13051 	OSReturn       callbackResult)
13052 {
13053 	OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
13054 	OSSharedPtr<OSNumber> resultNum;
13055 
13056 	if (!predicate) {
13057 		goto finish;
13058 	}
13059 
13060 	resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
13061 	    8 * sizeof(callbackResult));
13062 	if (!resultNum) {
13063 		goto finish;
13064 	}
13065 
13066 	/* Insert the result into the callback record and dispatch it as if it
13067 	 * were the reply coming down from user space.
13068 	 */
13069 	_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
13070 	    resultNum.get());
13071 
13072 	if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
13073 		/* This removes the pending callback record.
13074 		 */
13075 		OSKext::dispatchResource(callbackRecord);
13076 	}
13077 
13078 finish:
13079 	return;
13080 }
13081 
13082 /*********************************************************************
13083 * Assumes sKextLock is held.
13084 *********************************************************************/
13085 /* static */
13086 OSReturn
13087 OSKext::cancelRequest(
13088 	OSKextRequestTag    requestTag,
13089 	void             ** contextOut)
13090 {
13091 	OSReturn       result         = kOSKextReturnNoMemory;
13092 	OSSharedPtr<OSDictionary> callbackRecord;
13093 	OSData       * contextWrapper = NULL;        // do not release
13094 
13095 	IORecursiveLockLock(sKextLock);
13096 	result = OSKext::dequeueCallbackForRequestTag(requestTag,
13097 	    callbackRecord);
13098 	IORecursiveLockUnlock(sKextLock);
13099 
13100 	if (result == kOSReturnSuccess && contextOut) {
13101 		contextWrapper = OSDynamicCast(OSData,
13102 		    _OSKextGetRequestArgument(callbackRecord.get(),
13103 		    kKextRequestArgumentContextKey));
13104 		*contextOut = _OSKextExtractPointer(contextWrapper);
13105 	}
13106 
13107 	return result;
13108 }
13109 
13110 /*********************************************************************
13111 * Assumes sKextLock is held.
13112 *********************************************************************/
13113 void
13114 OSKext::invokeOrCancelRequestCallbacks(
13115 	OSReturn callbackResult,
13116 	bool     invokeFlag)
13117 {
13118 	unsigned int count, i;
13119 
13120 	count = sRequestCallbackRecords->getCount();
13121 	if (!count) {
13122 		goto finish;
13123 	}
13124 
13125 	i = count - 1;
13126 	do {
13127 		OSDictionary * request = OSDynamicCast(OSDictionary,
13128 		    sRequestCallbackRecords->getObject(i));
13129 
13130 		if (!request) {
13131 			continue;
13132 		}
13133 		OSData * callbackWrapper = OSDynamicCast(OSData,
13134 		    _OSKextGetRequestArgument(request,
13135 		    kKextRequestArgumentCallbackKey));
13136 
13137 		if (!callbackWrapper) {
13138 			sRequestCallbackRecords->removeObject(i);
13139 			continue;
13140 		}
13141 
13142 		vm_address_t callbackAddress = (vm_address_t)
13143 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
13144 
13145 		if ((kmod_info->address <= callbackAddress) &&
13146 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
13147 			if (invokeFlag) {
13148 				/* This removes the callback record.
13149 				 */
13150 				invokeRequestCallback(request, callbackResult);
13151 			} else {
13152 				sRequestCallbackRecords->removeObject(i);
13153 			}
13154 		}
13155 	} while (i--);
13156 
13157 finish:
13158 	return;
13159 }
13160 
13161 /*********************************************************************
13162 * Assumes sKextLock is held.
13163 *********************************************************************/
13164 uint32_t
13165 OSKext::countRequestCallbacks(void)
13166 {
13167 	uint32_t     result = 0;
13168 	unsigned int count, i;
13169 
13170 	count = sRequestCallbackRecords->getCount();
13171 	if (!count) {
13172 		goto finish;
13173 	}
13174 
13175 	i = count - 1;
13176 	do {
13177 		OSDictionary * request = OSDynamicCast(OSDictionary,
13178 		    sRequestCallbackRecords->getObject(i));
13179 
13180 		if (!request) {
13181 			continue;
13182 		}
13183 		OSData * callbackWrapper = OSDynamicCast(OSData,
13184 		    _OSKextGetRequestArgument(request,
13185 		    kKextRequestArgumentCallbackKey));
13186 
13187 		if (!callbackWrapper) {
13188 			continue;
13189 		}
13190 
13191 		vm_address_t callbackAddress = (vm_address_t)
13192 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
13193 
13194 		if ((kmod_info->address <= callbackAddress) &&
13195 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
13196 			result++;
13197 		}
13198 	} while (i--);
13199 
13200 finish:
13201 	return result;
13202 }
13203 
13204 /*********************************************************************
13205 *********************************************************************/
13206 static OSReturn
13207 _OSKextCreateRequest(
13208 	const char    * predicate,
13209 	OSSharedPtr<OSDictionary> & requestR)
13210 {
13211 	OSReturn result = kOSKextReturnNoMemory;
13212 	OSSharedPtr<OSDictionary> request;
13213 
13214 	request = OSDictionary::withCapacity(2);
13215 	if (!request) {
13216 		goto finish;
13217 	}
13218 	result = _OSDictionarySetCStringValue(request.get(),
13219 	    kKextRequestPredicateKey, predicate);
13220 	if (result != kOSReturnSuccess) {
13221 		goto finish;
13222 	}
13223 	result = kOSReturnSuccess;
13224 
13225 finish:
13226 	if (result == kOSReturnSuccess) {
13227 		requestR = os::move(request);
13228 	}
13229 
13230 	return result;
13231 }
13232 
13233 /*********************************************************************
13234 *********************************************************************/
13235 static OSString *
13236 _OSKextGetRequestPredicate(OSDictionary * requestDict)
13237 {
13238 	return OSDynamicCast(OSString,
13239 	           requestDict->getObject(kKextRequestPredicateKey));
13240 }
13241 
13242 /*********************************************************************
13243 *********************************************************************/
13244 static OSObject *
13245 _OSKextGetRequestArgument(
13246 	OSDictionary * requestDict,
13247 	const char   * argName)
13248 {
13249 	OSDictionary * args = OSDynamicCast(OSDictionary,
13250 	    requestDict->getObject(kKextRequestArgumentsKey));
13251 	if (args) {
13252 		return args->getObject(argName);
13253 	}
13254 	return NULL;
13255 }
13256 
13257 /*********************************************************************
13258 *********************************************************************/
13259 static bool
13260 _OSKextSetRequestArgument(
13261 	OSDictionary * requestDict,
13262 	const char   * argName,
13263 	OSObject     * value)
13264 {
13265 	OSDictionary * args = OSDynamicCast(OSDictionary,
13266 	    requestDict->getObject(kKextRequestArgumentsKey));
13267 	OSSharedPtr<OSDictionary> newArgs;
13268 	if (!args) {
13269 		newArgs = OSDictionary::withCapacity(2);
13270 		args = newArgs.get();
13271 		if (!args) {
13272 			goto finish;
13273 		}
13274 		requestDict->setObject(kKextRequestArgumentsKey, args);
13275 	}
13276 	if (args) {
13277 		return args->setObject(argName, value);
13278 	}
13279 finish:
13280 	return false;
13281 }
13282 
13283 /*********************************************************************
13284 *********************************************************************/
13285 static void *
13286 _OSKextExtractPointer(OSData * wrapper)
13287 {
13288 	void       * result = NULL;
13289 	const void * resultPtr = NULL;
13290 
13291 	if (!wrapper) {
13292 		goto finish;
13293 	}
13294 	resultPtr = wrapper->getBytesNoCopy();
13295 	result = *(void **)resultPtr;
13296 finish:
13297 	return result;
13298 }
13299 
13300 /*********************************************************************
13301 *********************************************************************/
13302 static OSKextRequestResourceCallback
13303 _OSKextExtractCallbackPointer(OSData * wrapper)
13304 {
13305 	OSKextRequestResourceCallback       result = NULL;
13306 	const void * resultPtr = NULL;
13307 
13308 	if (!wrapper) {
13309 		goto finish;
13310 	}
13311 	resultPtr = wrapper->getBytesNoCopy();
13312 	result = *(OSKextRequestResourceCallback *)resultPtr;
13313 finish:
13314 	return result;
13315 }
13316 
13317 
13318 /*********************************************************************
13319 *********************************************************************/
13320 static OSReturn
13321 _OSDictionarySetCStringValue(
13322 	OSDictionary * dict,
13323 	const char   * cKey,
13324 	const char   * cValue)
13325 {
13326 	OSReturn result = kOSKextReturnNoMemory;
13327 	OSSharedPtr<const OSSymbol> key;
13328 	OSSharedPtr<OSString> value;
13329 
13330 	key = OSSymbol::withCString(cKey);
13331 	value = OSString::withCString(cValue);
13332 	if (!key || !value) {
13333 		goto finish;
13334 	}
13335 	if (dict->setObject(key.get(), value.get())) {
13336 		result = kOSReturnSuccess;
13337 	}
13338 
13339 finish:
13340 	return result;
13341 }
13342 
13343 /*********************************************************************
13344 *********************************************************************/
13345 static bool
13346 _OSArrayContainsCString(
13347 	OSArray    * array,
13348 	const char * cString)
13349 {
13350 	bool             result = false;
13351 	OSSharedPtr<const OSSymbol> symbol;
13352 	uint32_t         count, i;
13353 
13354 	if (!array || !cString) {
13355 		goto finish;
13356 	}
13357 
13358 	symbol = OSSymbol::withCStringNoCopy(cString);
13359 	if (!symbol) {
13360 		goto finish;
13361 	}
13362 
13363 	count = array->getCount();
13364 	for (i = 0; i < count; i++) {
13365 		OSObject * thisObject = array->getObject(i);
13366 		if (symbol->isEqualTo(thisObject)) {
13367 			result = true;
13368 			goto finish;
13369 		}
13370 	}
13371 
13372 finish:
13373 	return result;
13374 }
13375 
13376 #if CONFIG_KXLD
13377 /*********************************************************************
13378 * We really only care about boot / system start up related kexts.
13379 * We return true if we're less than REBUILD_MAX_TIME since start up,
13380 * otherwise return false.
13381 *********************************************************************/
13382 bool
13383 _OSKextInPrelinkRebuildWindow(void)
13384 {
13385 	static bool     outside_the_window = false;
13386 	AbsoluteTime    my_abstime;
13387 	UInt64          my_ns;
13388 	SInt32          my_secs;
13389 
13390 	if (outside_the_window) {
13391 		return false;
13392 	}
13393 	clock_get_uptime(&my_abstime);
13394 	absolutetime_to_nanoseconds(my_abstime, &my_ns);
13395 	my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
13396 	if (my_secs > REBUILD_MAX_TIME) {
13397 		outside_the_window = true;
13398 		return false;
13399 	}
13400 	return true;
13401 }
13402 #endif /* CONFIG_KXLD */
13403 
13404 /*********************************************************************
13405 *********************************************************************/
13406 bool
13407 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
13408 {
13409 	int unLoadedCount, i;
13410 	bool result = false;
13411 
13412 	IORecursiveLockLock(sKextLock);
13413 
13414 	if (sUnloadedPrelinkedKexts == NULL) {
13415 		goto finish;
13416 	}
13417 	unLoadedCount = sUnloadedPrelinkedKexts->getCount();
13418 	if (unLoadedCount == 0) {
13419 		goto finish;
13420 	}
13421 
13422 	for (i = 0; i < unLoadedCount; i++) {
13423 		const OSSymbol *    myBundleID;        // do not release
13424 
13425 		myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
13426 		if (!myBundleID) {
13427 			continue;
13428 		}
13429 		if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
13430 			result = true;
13431 			break;
13432 		}
13433 	}
13434 finish:
13435 	IORecursiveLockUnlock(sKextLock);
13436 	return result;
13437 }
13438 
13439 #if PRAGMA_MARK
13440 #pragma mark Personalities (IOKit Drivers)
13441 #endif
13442 /*********************************************************************
13443 *********************************************************************/
13444 /* static */
13445 OSSharedPtr<OSArray>
13446 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
13447 {
13448 	OSSharedPtr<OSArray>              result;
13449 	OSSharedPtr<OSCollectionIterator> kextIterator;
13450 	OSSharedPtr<OSArray>              personalities;
13451 
13452 	OSString             * kextID                = NULL;        // do not release
13453 	OSKext               * theKext               = NULL;        // do not release
13454 
13455 	IORecursiveLockLock(sKextLock);
13456 
13457 	/* Let's conservatively guess that any given kext has around 3
13458 	 * personalities for now.
13459 	 */
13460 	result = OSArray::withCapacity(sKextsByID->getCount() * 3);
13461 	if (!result) {
13462 		goto finish;
13463 	}
13464 
13465 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
13466 	if (!kextIterator) {
13467 		goto finish;
13468 	}
13469 
13470 	while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
13471 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
13472 		if (theKext->flags.requireExplicitLoad) {
13473 			OSKextLog(theKext,
13474 			    kOSKextLogDebugLevel |
13475 			    kOSKextLogLoadFlag,
13476 			    "Kext %s requires an explicit kextload; "
13477 			    "omitting its personalities.",
13478 			    theKext->getIdentifierCString());
13479 		} else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
13480 			personalities = theKext->copyPersonalitiesArray();
13481 			if (!personalities) {
13482 				continue;
13483 			}
13484 			result->merge(personalities.get());
13485 		} else {
13486 			// xxx - check for better place to put this log msg
13487 			OSKextLog(theKext,
13488 			    kOSKextLogWarningLevel |
13489 			    kOSKextLogLoadFlag,
13490 			    "Kext %s is not loadable during safe boot; "
13491 			    "omitting its personalities.",
13492 			    theKext->getIdentifierCString());
13493 		}
13494 	}
13495 
13496 finish:
13497 	IORecursiveLockUnlock(sKextLock);
13498 
13499 	return result;
13500 }
13501 
13502 /*********************************************************************
13503 *********************************************************************/
13504 /* static */
13505 void
13506 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
13507 {
13508 	int numPersonalities = 0;
13509 
13510 	OSKextLog(/* kext */ NULL,
13511 	    kOSKextLogStepLevel |
13512 	    kOSKextLogLoadFlag,
13513 	    "Sending all eligible registered kexts' personalities "
13514 	    "to the IOCatalogue %s.",
13515 	    startMatching ? "and starting matching" : "but not starting matching");
13516 
13517 	OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities(
13518 		/* filterSafeBootFlag */ true);
13519 
13520 	if (personalities) {
13521 		gIOCatalogue->addDrivers(personalities.get(), startMatching);
13522 		numPersonalities = personalities->getCount();
13523 	}
13524 
13525 	OSKextLog(/* kext */ NULL,
13526 	    kOSKextLogStepLevel |
13527 	    kOSKextLogLoadFlag,
13528 	    "%d kext personalit%s sent to the IOCatalogue; %s.",
13529 	    numPersonalities, numPersonalities > 0 ? "ies" : "y",
13530 	    startMatching ? "matching started" : "matching not started");
13531 	return;
13532 }
13533 
13534 /*********************************************************************
13535 * Do not make a deep copy, just convert the IOKitPersonalities dict
13536 * to an array for sending to the IOCatalogue.
13537 *********************************************************************/
13538 OSSharedPtr<OSArray>
13539 OSKext::copyPersonalitiesArray(void)
13540 {
13541 	OSSharedPtr<OSArray>              result;
13542 	OSDictionary         * personalities               = NULL;        // do not release
13543 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
13544 
13545 	OSString             * personalityName             = NULL;        // do not release
13546 	OSString             * personalityBundleIdentifier = NULL;        // do not release
13547 
13548 	personalities = OSDynamicCast(OSDictionary,
13549 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
13550 	if (!personalities) {
13551 		goto finish;
13552 	}
13553 
13554 	result = OSArray::withCapacity(personalities->getCount());
13555 	if (!result) {
13556 		goto finish;
13557 	}
13558 
13559 	personalitiesIterator =
13560 	    OSCollectionIterator::withCollection(personalities);
13561 	if (!personalitiesIterator) {
13562 		goto finish;
13563 	}
13564 	while ((personalityName = OSDynamicCast(OSString,
13565 	    personalitiesIterator->getNextObject()))) {
13566 		OSDictionary * personality = OSDynamicCast(OSDictionary,
13567 		    personalities->getObject(personalityName));
13568 
13569 		/******
13570 		 * If the personality doesn't have a CFBundleIdentifier, or if it
13571 		 * differs from the kext's, insert the kext's ID so we can find it.
13572 		 * The publisher ID is used to remove personalities from bundles
13573 		 * correctly.
13574 		 */
13575 		personalityBundleIdentifier = OSDynamicCast(OSString,
13576 		    personality->getObject(kCFBundleIdentifierKey));
13577 
13578 		if (!personalityBundleIdentifier) {
13579 			personality->setObject(kCFBundleIdentifierKey, bundleID.get());
13580 		} else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) {
13581 			personality->setObject(kIOPersonalityPublisherKey, bundleID.get());
13582 		}
13583 
13584 		result->setObject(personality);
13585 	}
13586 
13587 finish:
13588 	return result;
13589 }
13590 
13591 /*********************************************************************
13592 *   Might want to change this to a bool return?
13593 *********************************************************************/
13594 OSReturn
13595 OSKext::sendPersonalitiesToCatalog(
13596 	bool      startMatching,
13597 	OSArray * personalityNames)
13598 {
13599 	OSReturn       result              = kOSReturnSuccess;
13600 	OSSharedPtr<OSArray> personalitiesToSend;
13601 	OSDictionary * kextPersonalities   = NULL;        // do not release
13602 	int            count, i;
13603 
13604 	if (!sLoadEnabled) {
13605 		OSKextLog(this,
13606 		    kOSKextLogErrorLevel |
13607 		    kOSKextLogLoadFlag,
13608 		    "Kext loading is disabled (attempt to start matching for kext %s).",
13609 		    getIdentifierCString());
13610 		result = kOSKextReturnDisabled;
13611 		goto finish;
13612 	}
13613 
13614 	if (sSafeBoot && !isLoadableInSafeBoot()) {
13615 		OSKextLog(this,
13616 		    kOSKextLogErrorLevel |
13617 		    kOSKextLogLoadFlag,
13618 		    "Kext %s is not loadable during safe boot; "
13619 		    "not sending personalities to the IOCatalogue.",
13620 		    getIdentifierCString());
13621 		result = kOSKextReturnNotLoadable;
13622 		goto finish;
13623 	}
13624 
13625 	if (!personalityNames || !personalityNames->getCount()) {
13626 		personalitiesToSend = copyPersonalitiesArray();
13627 	} else {
13628 		kextPersonalities = OSDynamicCast(OSDictionary,
13629 		    getPropertyForHostArch(kIOKitPersonalitiesKey));
13630 		if (!kextPersonalities || !kextPersonalities->getCount()) {
13631 			// not an error
13632 			goto finish;
13633 		}
13634 		personalitiesToSend = OSArray::withCapacity(0);
13635 		if (!personalitiesToSend) {
13636 			result = kOSKextReturnNoMemory;
13637 			goto finish;
13638 		}
13639 		count = personalityNames->getCount();
13640 		for (i = 0; i < count; i++) {
13641 			OSString * name = OSDynamicCast(OSString,
13642 			    personalityNames->getObject(i));
13643 			if (!name) {
13644 				continue;
13645 			}
13646 			OSDictionary * personality = OSDynamicCast(OSDictionary,
13647 			    kextPersonalities->getObject(name));
13648 			if (personality) {
13649 				personalitiesToSend->setObject(personality);
13650 			}
13651 		}
13652 	}
13653 	if (personalitiesToSend) {
13654 		unsigned numPersonalities = personalitiesToSend->getCount();
13655 		OSKextLog(this,
13656 		    kOSKextLogStepLevel |
13657 		    kOSKextLogLoadFlag,
13658 		    "Kext %s sending %d personalit%s to the IOCatalogue%s.",
13659 		    getIdentifierCString(),
13660 		    numPersonalities,
13661 		    numPersonalities > 1 ? "ies" : "y",
13662 		    startMatching ? " and starting matching" : " but not starting matching");
13663 		gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching);
13664 	}
13665 finish:
13666 	return result;
13667 }
13668 
13669 /*********************************************************************
13670 * xxx - We should allow removing the kext's declared personalities,
13671 * xxx - even with other bundle identifiers.
13672 *********************************************************************/
13673 void
13674 OSKext::removePersonalitiesFromCatalog(void)
13675 {
13676 	OSSharedPtr<OSDictionary> personality;
13677 
13678 	personality = OSDictionary::withCapacity(1);
13679 	if (!personality) {
13680 		goto finish;
13681 	}
13682 	personality->setObject(kCFBundleIdentifierKey, getIdentifier());
13683 
13684 	OSKextLog(this,
13685 	    kOSKextLogStepLevel |
13686 	    kOSKextLogLoadFlag,
13687 	    "Kext %s removing all personalities naming it from the IOCatalogue.",
13688 	    getIdentifierCString());
13689 
13690 	/* Have the IOCatalog remove all personalities matching this kext's
13691 	 * bundle ID and trigger matching anew.
13692 	 */
13693 	gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true);
13694 
13695 finish:
13696 	return;
13697 }
13698 
13699 
13700 #if PRAGMA_MARK
13701 #pragma mark Logging
13702 #endif
13703 /*********************************************************************
13704 * Do not call any function that takes sKextLock here!
13705 *********************************************************************/
13706 /* static */
13707 OSKextLogSpec
13708 OSKext::setUserSpaceLogFilter(
13709 	OSKextLogSpec   newUserLogFilter,
13710 	bool            captureFlag)
13711 {
13712 	OSKextLogSpec result;
13713 	bool          allocError = false;
13714 
13715 	/* Do not call any function that takes sKextLoggingLock during
13716 	 * this critical block. That means do logging after.
13717 	 */
13718 	IOLockLock(sKextLoggingLock);
13719 
13720 	result = sUserSpaceKextLogFilter;
13721 	sUserSpaceKextLogFilter = newUserLogFilter;
13722 
13723 	if (newUserLogFilter && captureFlag &&
13724 	    !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
13725 		// xxx - do some measurements for a good initial capacity?
13726 		sUserSpaceLogSpecArray = OSArray::withCapacity(0);
13727 		sUserSpaceLogMessageArray = OSArray::withCapacity(0);
13728 
13729 		if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
13730 			allocError = true;
13731 		}
13732 	}
13733 
13734 	IOLockUnlock(sKextLoggingLock);
13735 
13736 	/* If the config flag itself is changing, log the state change
13737 	 * going both ways, before setting up the user-space log arrays,
13738 	 * so that this is only logged in the kernel.
13739 	 */
13740 	if (result != newUserLogFilter) {
13741 		OSKextLog(/* kext */ NULL,
13742 		    kOSKextLogDebugLevel |
13743 		    kOSKextLogGeneralFlag,
13744 		    "User-space log flags changed from 0x%x to 0x%x.",
13745 		    result, newUserLogFilter);
13746 	}
13747 	if (allocError) {
13748 		OSKextLog(/* kext */ NULL,
13749 		    kOSKextLogErrorLevel |
13750 		    kOSKextLogGeneralFlag,
13751 		    "Failed to allocate user-space log message arrays.");
13752 	}
13753 
13754 	return result;
13755 }
13756 
13757 /*********************************************************************
13758 * Do not call any function that takes sKextLock here!
13759 *********************************************************************/
13760 /* static */
13761 OSSharedPtr<OSArray>
13762 OSKext::clearUserSpaceLogFilter(void)
13763 {
13764 	OSSharedPtr<OSArray>       result;
13765 	OSKextLogSpec   oldLogFilter;
13766 	OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
13767 
13768 	/* Do not call any function that takes sKextLoggingLock during
13769 	 * this critical block. That means do logging after.
13770 	 */
13771 	IOLockLock(sKextLoggingLock);
13772 
13773 	result = OSArray::withCapacity(2);
13774 	if (result) {
13775 		result->setObject(sUserSpaceLogSpecArray.get());
13776 		result->setObject(sUserSpaceLogMessageArray.get());
13777 	}
13778 	sUserSpaceLogSpecArray.reset();
13779 	sUserSpaceLogMessageArray.reset();
13780 
13781 	oldLogFilter = sUserSpaceKextLogFilter;
13782 	sUserSpaceKextLogFilter = newLogFilter;
13783 
13784 	IOLockUnlock(sKextLoggingLock);
13785 
13786 	/* If the config flag itself is changing, log the state change
13787 	 * going both ways, after tearing down the user-space log
13788 	 * arrays, so this is only logged within the kernel.
13789 	 */
13790 	if (oldLogFilter != newLogFilter) {
13791 		OSKextLog(/* kext */ NULL,
13792 		    kOSKextLogDebugLevel |
13793 		    kOSKextLogGeneralFlag,
13794 		    "User-space log flags changed from 0x%x to 0x%x.",
13795 		    oldLogFilter, newLogFilter);
13796 	}
13797 
13798 	return result;
13799 }
13800 
13801 
13802 /*********************************************************************
13803 * Do not call any function that takes sKextLock here!
13804 *********************************************************************/
13805 /* static */
13806 OSKextLogSpec
13807 OSKext::getUserSpaceLogFilter(void)
13808 {
13809 	OSKextLogSpec result;
13810 
13811 	IOLockLock(sKextLoggingLock);
13812 	result = sUserSpaceKextLogFilter;
13813 	IOLockUnlock(sKextLoggingLock);
13814 
13815 	return result;
13816 }
13817 
13818 /*********************************************************************
13819 * This function is called by OSMetaClass during kernel C++ setup.
13820 * Be careful what you access here; assume only OSKext::initialize()
13821 * has been called.
13822 *
13823 * Do not call any function that takes sKextLock here!
13824 *********************************************************************/
13825 #define VTRESET   "\033[0m"
13826 
13827 #define VTBOLD    "\033[1m"
13828 #define VTUNDER   "\033[4m"
13829 
13830 #define VTRED     "\033[31m"
13831 #define VTGREEN   "\033[32m"
13832 #define VTYELLOW  "\033[33m"
13833 #define VTBLUE    "\033[34m"
13834 #define VTMAGENTA "\033[35m"
13835 #define VTCYAN    "\033[36m"
13836 
13837 inline const char *
13838 colorForFlags(OSKextLogSpec flags)
13839 {
13840 	OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
13841 
13842 	switch (logLevel) {
13843 	case kOSKextLogErrorLevel:
13844 		return VTRED VTBOLD;
13845 	case kOSKextLogWarningLevel:
13846 		return VTRED;
13847 	case kOSKextLogBasicLevel:
13848 		return VTYELLOW VTUNDER;
13849 	case kOSKextLogProgressLevel:
13850 		return VTYELLOW;
13851 	case kOSKextLogStepLevel:
13852 		return VTGREEN;
13853 	case kOSKextLogDetailLevel:
13854 		return VTCYAN;
13855 	case kOSKextLogDebugLevel:
13856 		return VTMAGENTA;
13857 	default:
13858 		return "";         // white
13859 	}
13860 }
13861 
13862 inline bool
13863 logSpecMatch(
13864 	OSKextLogSpec msgLogSpec,
13865 	OSKextLogSpec logFilter)
13866 {
13867 	OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
13868 	OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
13869 	OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
13870 
13871 	OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
13872 	OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
13873 	OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
13874 
13875 	/* Explicit messages always get logged.
13876 	 */
13877 	if (msgLevel == kOSKextLogExplicitLevel) {
13878 		return true;
13879 	}
13880 
13881 	/* Warnings and errors are logged regardless of the flags.
13882 	 */
13883 	if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
13884 		return true;
13885 	}
13886 
13887 	/* A verbose message that isn't for a logging-enabled kext and isn't global
13888 	 * does *not* get logged.
13889 	 */
13890 	if (!msgKextGlobal && !filterKextGlobal) {
13891 		return false;
13892 	}
13893 
13894 	/* Warnings and errors are logged regardless of the flags.
13895 	 * All other messages must fit the flags and
13896 	 * have a level at or below the filter.
13897 	 *
13898 	 */
13899 	if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
13900 		return true;
13901 	}
13902 	return false;
13903 }
13904 
13905 extern "C" {
13906 void
13907 OSKextLog(
13908 	OSKext         * aKext,
13909 	OSKextLogSpec    msgLogSpec,
13910 	const char     * format, ...)
13911 {
13912 	va_list argList;
13913 
13914 	va_start(argList, format);
13915 	OSKextVLog(aKext, msgLogSpec, format, argList);
13916 	va_end(argList);
13917 }
13918 
13919 void
13920 OSKextVLog(
13921 	OSKext         * aKext,
13922 	OSKextLogSpec    msgLogSpec,
13923 	const char     * format,
13924 	va_list          srcArgList)
13925 {
13926 	extern int       disableConsoleOutput;
13927 
13928 	bool             logForKernel       = false;
13929 	bool             logForUser         = false;
13930 	va_list          argList;
13931 	char             stackBuffer[120];
13932 	uint32_t         length            = 0;
13933 	char           * allocBuffer       = NULL;        // must kfree
13934 	OSSharedPtr<OSNumber> logSpecNum;
13935 	OSSharedPtr<OSString> logString;
13936 	char           * buffer            = stackBuffer;        // do not free
13937 
13938 	IOLockLock(sKextLoggingLock);
13939 
13940 	/* Set the kext/global bit in the message spec if we have no
13941 	 * kext or if the kext requests logging.
13942 	 */
13943 	if (!aKext || aKext->flags.loggingEnabled) {
13944 		msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
13945 	}
13946 
13947 	logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
13948 	if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
13949 		logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
13950 	}
13951 
13952 	if (!(logForKernel || logForUser)) {
13953 		goto finish;
13954 	}
13955 
13956 	/* No goto from here until past va_end()!
13957 	 */
13958 	va_copy(argList, srcArgList);
13959 	length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
13960 	va_end(argList);
13961 
13962 	if (length + 1 >= sizeof(stackBuffer)) {
13963 		allocBuffer = (char *)kheap_alloc_tag(KHEAP_TEMP,
13964 		    length + 1, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
13965 		if (!allocBuffer) {
13966 			goto finish;
13967 		}
13968 
13969 		/* No goto from here until past va_end()!
13970 		 */
13971 		va_copy(argList, srcArgList);
13972 		vsnprintf(allocBuffer, length + 1, format, argList);
13973 		va_end(argList);
13974 
13975 		buffer = allocBuffer;
13976 	}
13977 
13978 	/* If user space wants the log message, queue it up.
13979 	 */
13980 	if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
13981 		logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
13982 		logString = OSString::withCString(buffer);
13983 		if (logSpecNum && logString) {
13984 			sUserSpaceLogSpecArray->setObject(logSpecNum.get());
13985 			sUserSpaceLogMessageArray->setObject(logString.get());
13986 		}
13987 	}
13988 
13989 	/* Always log messages from the kernel according to the kernel's
13990 	 * log flags.
13991 	 */
13992 	if (logForKernel) {
13993 		/* If we are in console mode and have a custom log filter,
13994 		 * colorize the log message.
13995 		 */
13996 		if (!disableConsoleOutput && sBootArgLogFilterFound) {
13997 			const char * color = "";         // do not free
13998 			color = colorForFlags(msgLogSpec);
13999 			printf("%s%s%s\n", colorForFlags(msgLogSpec),
14000 			    buffer, color[0] ? VTRESET : "");
14001 		} else {
14002 			printf("%s\n", buffer);
14003 		}
14004 	}
14005 
14006 finish:
14007 	IOLockUnlock(sKextLoggingLock);
14008 
14009 	if (allocBuffer) {
14010 		kheap_free(KHEAP_TEMP, allocBuffer, (length + 1) * sizeof(char));
14011 	}
14012 	return;
14013 }
14014 
14015 #if KASLR_IOREG_DEBUG
14016 
14017 #define IOLOG_INDENT( the_indention ) \
14018 { \
14019     int     i; \
14020     for ( i = 0; i < (the_indention); i++ ) { \
14021 	IOLog(" "); \
14022     } \
14023 }
14024 
14025 extern vm_offset_t       vm_kernel_stext;
14026 extern vm_offset_t       vm_kernel_etext;
14027 extern mach_vm_offset_t kext_alloc_base;
14028 extern mach_vm_offset_t kext_alloc_max;
14029 
14030 bool ScanForAddrInObject(OSObject * theObject,
14031     int indent );
14032 
14033 bool
14034 ScanForAddrInObject(OSObject * theObject,
14035     int indent)
14036 {
14037 	const OSMetaClass *     myTypeID;
14038 	OSSharedPtr<OSCollectionIterator>  myIter;
14039 	OSSymbol *              myKey;
14040 	OSObject *              myValue;
14041 	bool                    myResult = false;
14042 
14043 	if (theObject == NULL) {
14044 		IOLog("%s: theObject is NULL \n",
14045 		    __FUNCTION__);
14046 		return myResult;
14047 	}
14048 
14049 	myTypeID = OSTypeIDInst(theObject);
14050 
14051 	if (myTypeID == OSTypeID(OSDictionary)) {
14052 		OSDictionary *      myDictionary;
14053 
14054 		myDictionary = OSDynamicCast(OSDictionary, theObject);
14055 		myIter = OSCollectionIterator::withCollection( myDictionary );
14056 		if (myIter == NULL) {
14057 			return myResult;
14058 		}
14059 
14060 		// !! reset the iterator
14061 		myIter->reset();
14062 
14063 		while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
14064 			bool    myTempResult;
14065 
14066 			myValue = myDictionary->getObject(myKey);
14067 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
14068 			if (myTempResult) {
14069 				// if we ever get a true result return true
14070 				myResult = true;
14071 				IOLOG_INDENT(indent);
14072 				IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
14073 			}
14074 		}
14075 
14076 		// !! release the iterator
14077 		myIter.reset();
14078 	} else if (myTypeID == OSTypeID(OSArray)) {
14079 		OSArray *   myArray;
14080 
14081 		myArray = OSDynamicCast(OSArray, theObject);
14082 		myIter = OSCollectionIterator::withCollection(myArray);
14083 		if (myIter == NULL) {
14084 			return myResult;
14085 		}
14086 		// !! reset the iterator
14087 		myIter->reset();
14088 
14089 		while ((myValue = myIter->getNextObject())) {
14090 			bool        myTempResult;
14091 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
14092 			if (myTempResult) {
14093 				// if we ever get a true result return true
14094 				myResult = true;
14095 				IOLOG_INDENT(indent);
14096 				IOLog("OSArray: \n");
14097 			}
14098 		}
14099 		// !! release the iterator
14100 		myIter.reset();
14101 	} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
14102 		// should we look for addresses in strings?
14103 	} else if (myTypeID == OSTypeID(OSData)) {
14104 		void * *        myPtrPtr;
14105 		unsigned int    myLen;
14106 		OSData *        myDataObj;
14107 
14108 		myDataObj =    OSDynamicCast(OSData, theObject);
14109 		myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
14110 		myLen = myDataObj->getLength();
14111 
14112 		if (myPtrPtr && myLen && myLen > 7) {
14113 			int     i;
14114 			int     myPtrCount = (myLen / sizeof(void *));
14115 
14116 			for (i = 0; i < myPtrCount; i++) {
14117 				UInt64 numberValue = (UInt64) * (myPtrPtr);
14118 
14119 				if (kext_alloc_max != 0 &&
14120 				    numberValue >= kext_alloc_base &&
14121 				    numberValue < kext_alloc_max) {
14122 					OSSharedPtr<OSKext> myKext;
14123 					// IOLog("found OSData %p in kext map %p to %p  \n",
14124 					//       *(myPtrPtr),
14125 					//       (void *) kext_alloc_base,
14126 					//       (void *) kext_alloc_max);
14127 
14128 					myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
14129 					if (myKext) {
14130 						IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
14131 						    *(myPtrPtr),
14132 						    myKext->getIdentifierCString());
14133 					}
14134 					myResult = true;
14135 				}
14136 				if (vm_kernel_etext != 0 &&
14137 				    numberValue >= vm_kernel_stext &&
14138 				    numberValue < vm_kernel_etext) {
14139 					IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
14140 					    *(myPtrPtr),
14141 					    (void *) vm_kernel_stext,
14142 					    (void *) vm_kernel_etext);
14143 					myResult = true;
14144 				}
14145 				myPtrPtr++;
14146 			}
14147 		}
14148 	} else if (myTypeID == OSTypeID(OSBoolean)) {
14149 		// do nothing here...
14150 	} else if (myTypeID == OSTypeID(OSNumber)) {
14151 		OSNumber * number = OSDynamicCast(OSNumber, theObject);
14152 
14153 		UInt64 numberValue = number->unsigned64BitValue();
14154 
14155 		if (kext_alloc_max != 0 &&
14156 		    numberValue >= kext_alloc_base &&
14157 		    numberValue < kext_alloc_max) {
14158 			OSSharedPtr<OSKext> myKext;
14159 			IOLog("found OSNumber in kext map %p to %p  \n",
14160 			    (void *) kext_alloc_base,
14161 			    (void *) kext_alloc_max);
14162 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
14163 
14164 			myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
14165 			if (myKext) {
14166 				IOLog("found in kext \"%s\"  \n",
14167 				    myKext->getIdentifierCString());
14168 			}
14169 
14170 			myResult = true;
14171 		}
14172 		if (vm_kernel_etext != 0 &&
14173 		    numberValue >= vm_kernel_stext &&
14174 		    numberValue < vm_kernel_etext) {
14175 			IOLog("found OSNumber in kernel text segment %p to %p  \n",
14176 			    (void *) vm_kernel_stext,
14177 			    (void *) vm_kernel_etext);
14178 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
14179 			myResult = true;
14180 		}
14181 	}
14182 #if 0
14183 	else {
14184 		const OSMetaClass* myMetaClass = NULL;
14185 
14186 		myMetaClass = theObject->getMetaClass();
14187 		if (myMetaClass) {
14188 			IOLog("class %s \n", myMetaClass->getClassName());
14189 		} else {
14190 			IOLog("Unknown object \n" );
14191 		}
14192 	}
14193 #endif
14194 
14195 	return myResult;
14196 }
14197 #endif // KASLR_KEXT_DEBUG
14198 };         /* extern "C" */
14199 
14200 #if PRAGMA_MARK
14201 #pragma mark Backtrace Dump & kmod_get_info() support
14202 #endif
14203 /*********************************************************************
14204 * This function must be safe to call in panic context.
14205 *********************************************************************/
14206 /* static */
14207 void
14208 OSKext::printKextsInBacktrace(
14209 	vm_offset_t  * addr __unused,
14210 	unsigned int   cnt __unused,
14211 	int         (* printf_func)(const char *fmt, ...) __unused,
14212 	uint32_t       flags __unused)
14213 {
14214 	addr64_t    summary_page = 0;
14215 	addr64_t    last_summary_page = 0;
14216 	bool        found_kmod = false;
14217 	u_int       i = 0;
14218 
14219 	if (kPrintKextsLock & flags) {
14220 		if (!sKextSummariesLock) {
14221 			return;
14222 		}
14223 		IOLockLock(sKextSummariesLock);
14224 	}
14225 
14226 	if (!gLoadedKextSummaries) {
14227 		(*printf_func)("         can't perform kext scan: no kext summary");
14228 		goto finish;
14229 	}
14230 
14231 	summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
14232 	last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
14233 	for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
14234 		if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
14235 			(*printf_func)("         can't perform kext scan: "
14236 			    "missing kext summary page %p", summary_page);
14237 			goto finish;
14238 		}
14239 	}
14240 
14241 	for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14242 		OSKextLoadedKextSummary * summary;
14243 
14244 		summary = gLoadedKextSummaries->summaries + i;
14245 		if (!summary->address) {
14246 			continue;
14247 		}
14248 
14249 		if (!summaryIsInBacktrace(summary, addr, cnt)) {
14250 			continue;
14251 		}
14252 
14253 		if (!found_kmod) {
14254 			if (!(kPrintKextsTerse & flags)) {
14255 				(*printf_func)("      Kernel Extensions in backtrace:\n");
14256 			}
14257 			found_kmod = true;
14258 		}
14259 
14260 		printSummary(summary, printf_func, flags);
14261 	}
14262 
14263 finish:
14264 	if (kPrintKextsLock & flags) {
14265 		IOLockUnlock(sKextSummariesLock);
14266 	}
14267 
14268 	return;
14269 }
14270 
14271 /*********************************************************************
14272 * This function must be safe to call in panic context.
14273 *********************************************************************/
14274 /* static */
14275 boolean_t
14276 OSKext::summaryIsInBacktrace(
14277 	OSKextLoadedKextSummary   * summary,
14278 	vm_offset_t               * addr,
14279 	unsigned int                cnt)
14280 {
14281 	u_int i = 0;
14282 
14283 	for (i = 0; i < cnt; i++) {
14284 		vm_offset_t kscan_addr = addr[i];
14285 #if  __has_feature(ptrauth_calls)
14286 		kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr);
14287 #endif /*  __has_feature(ptrauth_calls) */
14288 		if ((kscan_addr >= summary->text_exec_address) &&
14289 		    (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) {
14290 			return TRUE;
14291 		}
14292 	}
14293 
14294 	return FALSE;
14295 }
14296 
14297 /*
14298  * Get the kext summary object for the kext where 'addr' lies. Must be called with
14299  * sKextSummariesLock held.
14300  */
14301 OSKextLoadedKextSummary *
14302 OSKext::summaryForAddress(uintptr_t addr)
14303 {
14304 #if  __has_feature(ptrauth_calls)
14305 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
14306 #endif /*  __has_feature(ptrauth_calls) */
14307 	for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14308 		OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
14309 		if (!summary->address) {
14310 			continue;
14311 		}
14312 
14313 #if VM_MAPPED_KEXTS
14314 		/* On our platforms that use VM_MAPPED_KEXTS, we currently do not
14315 		 * support split kexts, but we also may unmap the kexts, which can
14316 		 * race with the above codepath (see OSKext::unload).  As such,
14317 		 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
14318 		 */
14319 		if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
14320 			return summary;
14321 		}
14322 #else
14323 		kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
14324 		kernel_segment_command_t *seg;
14325 
14326 		for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
14327 			if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
14328 				return summary;
14329 			}
14330 		}
14331 #endif
14332 	}
14333 
14334 	/* addr did not map to any kext */
14335 	return NULL;
14336 }
14337 
14338 /* static */
14339 void *
14340 OSKext::kextForAddress(const void *address)
14341 {
14342 	void                * image = NULL;
14343 	OSKextActiveAccount * active;
14344 	OSKext              * kext = NULL;
14345 	uint32_t              baseIdx;
14346 	uint32_t              lim;
14347 	uintptr_t             addr = (uintptr_t) address;
14348 	size_t                i;
14349 
14350 	if (!addr) {
14351 		return NULL;
14352 	}
14353 #if  __has_feature(ptrauth_calls)
14354 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
14355 #endif /*  __has_feature(ptrauth_calls) */
14356 
14357 	if (sKextAccountsCount) {
14358 		IOSimpleLockLock(sKextAccountsLock);
14359 		// bsearch sKextAccounts list
14360 		for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
14361 			active = &sKextAccounts[baseIdx + (lim >> 1)];
14362 			if ((addr >= active->address) && (addr < active->address_end)) {
14363 				kext = active->account->kext;
14364 				if (kext && kext->kmod_info) {
14365 					image = (void *) kext->kmod_info->address;
14366 				}
14367 				break;
14368 			} else if (addr > active->address) {
14369 				// move right
14370 				baseIdx += (lim >> 1) + 1;
14371 				lim--;
14372 			}
14373 			// else move left
14374 		}
14375 		IOSimpleLockUnlock(sKextAccountsLock);
14376 	}
14377 	if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) {
14378 		image = (void *) &_mh_execute_header;
14379 	}
14380 	if (!image && gLoadedKextSummaries) {
14381 		IOLockLock(sKextSummariesLock);
14382 		for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) {
14383 			OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
14384 			if (addr >= summary->address && addr < summary->address + summary->size) {
14385 				image = (void *)summary->address;
14386 			}
14387 		}
14388 		IOLockUnlock(sKextSummariesLock);
14389 	}
14390 
14391 	return image;
14392 }
14393 
14394 /*
14395  * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t *
14396  * Safe to call in panic context.
14397  */
14398 static OSKextLoadedKextSummary *
14399 findSummary(uint32_t tagID)
14400 {
14401 	OSKextLoadedKextSummary * summary;
14402 	for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14403 		summary = gLoadedKextSummaries->summaries + i;
14404 		if (summary->loadTag == tagID) {
14405 			return summary;
14406 		}
14407 	}
14408 	return NULL;
14409 }
14410 
14411 /*********************************************************************
14412 * This function must be safe to call in panic context.
14413 *********************************************************************/
14414 void
14415 OSKext::printSummary(
14416 	OSKextLoadedKextSummary * summary,
14417 	int                    (* printf_func)(const char *fmt, ...),
14418 	uint32_t                  flags)
14419 {
14420 	kmod_reference_t * kmod_ref = NULL;
14421 	uuid_string_t uuid;
14422 	char version[kOSKextVersionMaxLength];
14423 	uint64_t tmpAddr;
14424 	uint64_t tmpSize;
14425 	OSKextLoadedKextSummary *dependencySummary;
14426 
14427 	if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
14428 		strlcpy(version, "unknown version", sizeof(version));
14429 	}
14430 	(void) uuid_unparse(summary->uuid, uuid);
14431 
14432 #if defined(__arm__) || defined(__arm64__)
14433 	tmpAddr = summary->text_exec_address;
14434 	tmpSize = summary->text_exec_size;
14435 #else
14436 	tmpAddr = summary->address;
14437 	tmpSize = summary->size;
14438 #endif
14439 	if (kPrintKextsUnslide & flags) {
14440 		tmpAddr = ml_static_unslide(tmpAddr);
14441 	}
14442 	(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
14443 	    (kPrintKextsTerse & flags) ? "" : "         ",
14444 	    summary->name, version, uuid,
14445 	    tmpAddr, tmpAddr + tmpSize - 1);
14446 
14447 	if (kPrintKextsTerse & flags) {
14448 		return;
14449 	}
14450 
14451 	/* print dependency info */
14452 	for (kmod_ref = (kmod_reference_t *) summary->reference_list;
14453 	    kmod_ref;
14454 	    kmod_ref = kmod_ref->next) {
14455 		kmod_info_t * rinfo;
14456 
14457 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
14458 			(*printf_func)("            kmod dependency scan stopped "
14459 			    "due to missing dependency page: %p\n",
14460 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
14461 			break;
14462 		}
14463 		rinfo = kmod_ref->info;
14464 
14465 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
14466 			(*printf_func)("            kmod dependency scan stopped "
14467 			    "due to missing kmod page: %p\n",
14468 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
14469 			break;
14470 		}
14471 
14472 		if (!rinfo->address) {
14473 			continue;         // skip fake entries for built-ins
14474 		}
14475 
14476 		dependencySummary = findSummary(rinfo->id);
14477 		uuid[0] = 0x00;
14478 		tmpAddr = rinfo->address;
14479 		tmpSize = rinfo->size;
14480 		if (dependencySummary) {
14481 			(void) uuid_unparse(dependencySummary->uuid, uuid);
14482 #if defined(__arm__) || defined(__arm64__)
14483 			tmpAddr = dependencySummary->text_exec_address;
14484 			tmpSize = dependencySummary->text_exec_size;
14485 #endif
14486 		}
14487 
14488 		if (kPrintKextsUnslide & flags) {
14489 			tmpAddr = ml_static_unslide(tmpAddr);
14490 		}
14491 		(*printf_func)("            dependency: %s(%s)[%s]@%p->%p\n",
14492 		    rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1);
14493 	}
14494 	return;
14495 }
14496 
14497 
14498 #if !defined(__arm__) && !defined(__arm64__)
14499 /*******************************************************************************
14500 * substitute() looks at an input string (a pointer within a larger buffer)
14501 * for a match to a substring, and on match it writes the marker & substitution
14502 * character to an output string, updating the scan (from) and
14503 * output (to) indexes as appropriate.
14504 *******************************************************************************/
14505 static int substitute(
14506 	const char * scan_string,
14507 	char       * string_out,
14508 	uint32_t   * to_index,
14509 	uint32_t   * from_index,
14510 	const char * substring,
14511 	char         marker,
14512 	char         substitution);
14513 
14514 /* string_out must be at least KMOD_MAX_NAME bytes.
14515  */
14516 static int
14517 substitute(
14518 	const char * scan_string,
14519 	char       * string_out,
14520 	uint32_t   * to_index,
14521 	uint32_t   * from_index,
14522 	const char * substring,
14523 	char         marker,
14524 	char         substitution)
14525 {
14526 	size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
14527 
14528 	/* On a substring match, append the marker (if there is one) and then
14529 	 * the substitution character, updating the output (to) index accordingly.
14530 	 * Then update the input (from) length by the length of the substring
14531 	 * that got replaced.
14532 	 */
14533 	if (!strncmp(scan_string, substring, substring_length)) {
14534 		if (marker) {
14535 			string_out[(*to_index)++] = marker;
14536 		}
14537 		string_out[(*to_index)++] = substitution;
14538 		(*from_index) += substring_length;
14539 		return 1;
14540 	}
14541 	return 0;
14542 }
14543 
14544 /*******************************************************************************
14545 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
14546 * KMOD_MAX_NAME characters and performs various substitutions of common
14547 * prefixes & substrings as defined by tables in kext_panic_report.h.
14548 *******************************************************************************/
14549 static void compactIdentifier(
14550 	const char * identifier,
14551 	char       * identifier_out,
14552 	char      ** identifier_out_end);
14553 
14554 static void
14555 compactIdentifier(
14556 	const char * identifier,
14557 	char       * identifier_out,
14558 	char      ** identifier_out_end)
14559 {
14560 	uint32_t       from_index, to_index;
14561 	uint32_t       scan_from_index = 0;
14562 	uint32_t       scan_to_index   = 0;
14563 	subs_entry_t * subs_entry    = NULL;
14564 	int            did_sub       = 0;
14565 
14566 	from_index = to_index = 0;
14567 	identifier_out[0] = '\0';
14568 
14569 	/* Replace certain identifier prefixes with shorter @+character sequences.
14570 	 * Check the return value of substitute() so we only replace the prefix.
14571 	 */
14572 	for (subs_entry = &kext_identifier_prefix_subs[0];
14573 	    subs_entry->substring && !did_sub;
14574 	    subs_entry++) {
14575 		did_sub = substitute(identifier, identifier_out,
14576 		    &scan_to_index, &scan_from_index,
14577 		    subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
14578 	}
14579 	did_sub = 0;
14580 
14581 	/* Now scan through the identifier looking for the common substrings
14582 	 * and replacing them with shorter !+character sequences via substitute().
14583 	 */
14584 	for (/* see above */;
14585 	    scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
14586 	    /* see loop */) {
14587 		const char   * scan_string = &identifier[scan_from_index];
14588 
14589 		did_sub = 0;
14590 
14591 		if (scan_from_index) {
14592 			for (subs_entry = &kext_identifier_substring_subs[0];
14593 			    subs_entry->substring && !did_sub;
14594 			    subs_entry++) {
14595 				did_sub = substitute(scan_string, identifier_out,
14596 				    &scan_to_index, &scan_from_index,
14597 				    subs_entry->substring, '!', subs_entry->substitute);
14598 			}
14599 		}
14600 
14601 		/* If we didn't substitute, copy the input character to the output.
14602 		 */
14603 		if (!did_sub) {
14604 			identifier_out[scan_to_index++] = identifier[scan_from_index++];
14605 		}
14606 	}
14607 
14608 	identifier_out[scan_to_index] = '\0';
14609 	if (identifier_out_end) {
14610 		*identifier_out_end = &identifier_out[scan_to_index];
14611 	}
14612 
14613 	return;
14614 }
14615 #endif /* !defined(__arm__) && !defined(__arm64__) */
14616 
14617 /*******************************************************************************
14618 * assemble_identifier_and_version() adds to a string buffer a compacted
14619 * bundle identifier followed by a version string.
14620 *******************************************************************************/
14621 
14622 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
14623  */
14624 static size_t assemble_identifier_and_version(
14625 	kmod_info_t * kmod_info,
14626 	char        * identPlusVers,
14627 	size_t        bufSize);
14628 
14629 static size_t
14630 assemble_identifier_and_version(
14631 	kmod_info_t * kmod_info,
14632 	char        * identPlusVers,
14633 	size_t        bufSize)
14634 {
14635 	size_t result = 0;
14636 
14637 #if defined(__arm__) || defined(__arm64__)
14638 	result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME);
14639 #else
14640 	compactIdentifier(kmod_info->name, identPlusVers, NULL);
14641 	result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
14642 #endif
14643 	identPlusVers[result++] = '\t';         // increment for real char
14644 	identPlusVers[result] = '\0';         // don't increment for nul char
14645 	result = strlcat(identPlusVers, kmod_info->version, bufSize);
14646 	if (result >= bufSize) {
14647 		identPlusVers[bufSize - 1] = '\0';
14648 		result = bufSize - 1;
14649 	}
14650 
14651 	return result;
14652 }
14653 
14654 /*******************************************************************************
14655 * Assumes sKextLock is held.
14656 *******************************************************************************/
14657 /* static */
14658 int
14659 OSKext::saveLoadedKextPanicListTyped(
14660 	const char * prefix,
14661 	int          invertFlag,
14662 	int          libsFlag,
14663 	char       * paniclist,
14664 	uint32_t     list_size)
14665 {
14666 	int             result = -1;
14667 	unsigned int    count, i;
14668 
14669 	count = sLoadedKexts->getCount();
14670 	if (!count) {
14671 		goto finish;
14672 	}
14673 
14674 	i = count - 1;
14675 	do {
14676 		OSObject    * rawKext = sLoadedKexts->getObject(i);
14677 		OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
14678 		int           match;
14679 		size_t        identPlusVersLength;
14680 		size_t        tempLen;
14681 		char          identPlusVers[2 * KMOD_MAX_NAME];
14682 
14683 		if (!rawKext) {
14684 			printf("OSKext::saveLoadedKextPanicListTyped - "
14685 			    "NULL kext in loaded kext list; continuing\n");
14686 			continue;
14687 		}
14688 
14689 		if (!theKext) {
14690 			printf("OSKext::saveLoadedKextPanicListTyped - "
14691 			    "Kext type cast failed in loaded kext list; continuing\n");
14692 			continue;
14693 		}
14694 
14695 		/* Skip all built-in kexts.
14696 		 */
14697 		if (theKext->isKernelComponent()) {
14698 			continue;
14699 		}
14700 
14701 		kmod_info_t * kmod_info = theKext->kmod_info;
14702 
14703 		/* Filter for kmod name (bundle identifier).
14704 		 */
14705 		match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
14706 		if ((match && invertFlag) || (!match && !invertFlag)) {
14707 			continue;
14708 		}
14709 
14710 		/* Filter for libraries (kexts that have a compatible version).
14711 		 */
14712 		if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
14713 		    (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
14714 			continue;
14715 		}
14716 
14717 		if (!kmod_info ||
14718 		    !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
14719 			printf("kext scan stopped due to missing kmod_info page: %p\n",
14720 			    kmod_info);
14721 			goto finish;
14722 		}
14723 
14724 		identPlusVersLength = assemble_identifier_and_version(kmod_info,
14725 		    identPlusVers,
14726 		    sizeof(identPlusVers));
14727 		if (!identPlusVersLength) {
14728 			printf("error saving loaded kext info\n");
14729 			goto finish;
14730 		}
14731 
14732 		/* make sure everything fits and we null terminate.
14733 		 */
14734 		tempLen = strlcat(paniclist, identPlusVers, list_size);
14735 		if (tempLen >= list_size) {
14736 			// panic list is full, keep it and null terminate
14737 			paniclist[list_size - 1] = 0x00;
14738 			result = 0;
14739 			goto finish;
14740 		}
14741 		tempLen = strlcat(paniclist, "\n", list_size);
14742 		if (tempLen >= list_size) {
14743 			// panic list is full, keep it and null terminate
14744 			paniclist[list_size - 1] = 0x00;
14745 			result = 0;
14746 			goto finish;
14747 		}
14748 	} while (i--);
14749 
14750 	result = 0;
14751 finish:
14752 
14753 	return result;
14754 }
14755 
14756 /*********************************************************************
14757 *********************************************************************/
14758 /* static */
14759 void
14760 OSKext::saveLoadedKextPanicList(void)
14761 {
14762 	char     * newlist        = NULL;
14763 	uint32_t   newlist_size   = 0;
14764 
14765 	newlist_size = KEXT_PANICLIST_SIZE;
14766 	newlist = (char *)kheap_alloc_tag(KHEAP_DATA_BUFFERS, newlist_size,
14767 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
14768 
14769 	if (!newlist) {
14770 		OSKextLog(/* kext */ NULL,
14771 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
14772 		    "Couldn't allocate kext panic log buffer.");
14773 		goto finish;
14774 	}
14775 
14776 	newlist[0] = '\0';
14777 
14778 	// non-"com.apple." kexts
14779 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
14780 	    /* libs? */ -1, newlist, newlist_size) != 0) {
14781 		goto finish;
14782 	}
14783 	// "com.apple." nonlibrary kexts
14784 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
14785 	    /* libs? */ 0, newlist, newlist_size) != 0) {
14786 		goto finish;
14787 	}
14788 	// "com.apple." library kexts
14789 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
14790 	    /* libs? */ 1, newlist, newlist_size) != 0) {
14791 		goto finish;
14792 	}
14793 
14794 	if (loaded_kext_paniclist) {
14795 		kheap_free(KHEAP_DATA_BUFFERS, loaded_kext_paniclist,
14796 		    loaded_kext_paniclist_size);
14797 	}
14798 	loaded_kext_paniclist = newlist;
14799 	newlist = NULL;
14800 	loaded_kext_paniclist_size = newlist_size;
14801 
14802 finish:
14803 	if (newlist) {
14804 		kheap_free(KHEAP_TEMP, newlist, newlist_size);
14805 	}
14806 	return;
14807 }
14808 
14809 /*********************************************************************
14810 * Assumes sKextLock is held.
14811 *********************************************************************/
14812 void
14813 OSKext::savePanicString(bool isLoading)
14814 {
14815 	u_long len;
14816 
14817 	if (!kmod_info) {
14818 		return;         // do not goto finish here b/c of lock
14819 	}
14820 
14821 	len = assemble_identifier_and_version( kmod_info,
14822 	    (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
14823 	    (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
14824 	if (!len) {
14825 		printf("error saving unloaded kext info\n");
14826 		goto finish;
14827 	}
14828 
14829 	if (isLoading) {
14830 		last_loaded_strlen = len;
14831 		last_loaded_address = (void *)kmod_info->address;
14832 		last_loaded_size = kmod_info->size;
14833 		clock_get_uptime(&last_loaded_timestamp);
14834 	} else {
14835 		last_unloaded_strlen = len;
14836 		last_unloaded_address = (void *)kmod_info->address;
14837 		last_unloaded_size = kmod_info->size;
14838 		clock_get_uptime(&last_unloaded_timestamp);
14839 	}
14840 
14841 finish:
14842 	return;
14843 }
14844 
14845 /*********************************************************************
14846 *********************************************************************/
14847 /* static */
14848 void
14849 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
14850 {
14851 	if (last_loaded_strlen) {
14852 		printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n",
14853 		    AbsoluteTime_to_scalar(&last_loaded_timestamp),
14854 		    last_loaded_strlen, last_loaded_str_buf,
14855 		    last_loaded_address, last_loaded_size);
14856 	}
14857 
14858 	if (last_unloaded_strlen) {
14859 		printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n",
14860 		    AbsoluteTime_to_scalar(&last_unloaded_timestamp),
14861 		    last_unloaded_strlen, last_unloaded_str_buf,
14862 		    last_unloaded_address, last_unloaded_size);
14863 	}
14864 
14865 	printf_func("loaded kexts:\n");
14866 	if (loaded_kext_paniclist &&
14867 	    pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
14868 	    loaded_kext_paniclist[0]) {
14869 		printf_func("%.*s",
14870 		    strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
14871 		    loaded_kext_paniclist);
14872 	} else {
14873 		printf_func("(none)\n");
14874 	}
14875 	return;
14876 }
14877 
14878 /*********************************************************************
14879 * Assumes sKextLock is held.
14880 *********************************************************************/
14881 /* static */
14882 void
14883 OSKext::updateLoadedKextSummaries(void)
14884 {
14885 	kern_return_t result = KERN_FAILURE;
14886 	OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
14887 	OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
14888 	OSKext *aKext;
14889 	vm_map_offset_t start, end;
14890 	size_t summarySize = 0;
14891 	size_t size;
14892 	u_int count;
14893 	u_int maxKexts;
14894 	u_int i, j;
14895 	OSKextActiveAccount * accountingList;
14896 	OSKextActiveAccount * prevAccountingList;
14897 	uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
14898 
14899 	prevAccountingList = NULL;
14900 	prevAccountingListCount = 0;
14901 
14902 #if DEVELOPMENT || DEBUG
14903 	if (IORecursiveLockHaveLock(sKextLock) == false) {
14904 		panic("sKextLock must be held");
14905 	}
14906 #endif
14907 
14908 	IOLockLock(sKextSummariesLock);
14909 
14910 	count = sLoadedKexts->getCount();
14911 	for (i = 0, maxKexts = 0; i < count; ++i) {
14912 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
14913 		maxKexts += (aKext && aKext->isExecutable());
14914 	}
14915 
14916 	if (!maxKexts) {
14917 		goto finish;
14918 	}
14919 	if (maxKexts < kOSKextTypicalLoadCount) {
14920 		maxKexts = kOSKextTypicalLoadCount;
14921 	}
14922 
14923 	/* Calculate the size needed for the new summary headers.
14924 	 */
14925 
14926 	size = sizeof(*gLoadedKextSummaries);
14927 	size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
14928 	size = round_page(size);
14929 
14930 	if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
14931 		if (gLoadedKextSummaries) {
14932 			kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
14933 			gLoadedKextSummaries = NULL;
14934 			gLoadedKextSummariesTimestamp = mach_absolute_time();
14935 			sLoadedKextSummariesAllocSize = 0;
14936 		}
14937 		result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, VM_KERN_MEMORY_OSKEXT);
14938 		if (result != KERN_SUCCESS) {
14939 			goto finish;
14940 		}
14941 		summaryHeader = summaryHeaderAlloc;
14942 		summarySize = size;
14943 	} else {
14944 		summaryHeader = gLoadedKextSummaries;
14945 		summarySize = sLoadedKextSummariesAllocSize;
14946 
14947 		start = (vm_map_offset_t) summaryHeader;
14948 		end = start + summarySize;
14949 		result = vm_map_protect(kernel_map,
14950 		    start,
14951 		    end,
14952 		    VM_PROT_DEFAULT,
14953 		    FALSE);
14954 		if (result != KERN_SUCCESS) {
14955 			goto finish;
14956 		}
14957 	}
14958 
14959 	/* Populate the summary header.
14960 	 */
14961 
14962 	bzero(summaryHeader, summarySize);
14963 	summaryHeader->version = kOSKextLoadedKextSummaryVersion;
14964 	summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
14965 
14966 	/* Populate each kext summary.
14967 	 */
14968 
14969 	count = sLoadedKexts->getCount();
14970 	accountingListAlloc = 0;
14971 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
14972 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
14973 		if (!aKext || !aKext->isExecutable()) {
14974 			continue;
14975 		}
14976 
14977 		aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
14978 		summaryHeader->numSummaries++;
14979 		accountingListAlloc++;
14980 	}
14981 
14982 	accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
14983 	accountingListCount = 0;
14984 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
14985 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
14986 		if (!aKext || !aKext->isExecutable()) {
14987 			continue;
14988 		}
14989 
14990 		OSKextActiveAccount activeAccount;
14991 		aKext->updateActiveAccount(&activeAccount);
14992 		// order by address
14993 		for (idx = 0; idx < accountingListCount; idx++) {
14994 			if (activeAccount.address < accountingList[idx].address) {
14995 				break;
14996 			}
14997 		}
14998 		bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
14999 		accountingList[idx] = activeAccount;
15000 		accountingListCount++;
15001 	}
15002 	assert(accountingListCount == accountingListAlloc);
15003 	/* Write protect the buffer and move it into place.
15004 	 */
15005 
15006 	start = (vm_map_offset_t) summaryHeader;
15007 	end = start + summarySize;
15008 
15009 	result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
15010 	if (result != KERN_SUCCESS) {
15011 		goto finish;
15012 	}
15013 
15014 	gLoadedKextSummaries = summaryHeader;
15015 	gLoadedKextSummariesTimestamp = mach_absolute_time();
15016 	sLoadedKextSummariesAllocSize = summarySize;
15017 	summaryHeaderAlloc = NULL;
15018 
15019 	/* Call the magic breakpoint function through a static function pointer so
15020 	 * the compiler can't optimize the function away.
15021 	 */
15022 	if (sLoadedKextSummariesUpdated) {
15023 		(*sLoadedKextSummariesUpdated)();
15024 	}
15025 
15026 	IOSimpleLockLock(sKextAccountsLock);
15027 	prevAccountingList      = sKextAccounts;
15028 	prevAccountingListCount = sKextAccountsCount;
15029 	sKextAccounts           = accountingList;
15030 	sKextAccountsCount      = accountingListCount;
15031 	IOSimpleLockUnlock(sKextAccountsLock);
15032 
15033 finish:
15034 	IOLockUnlock(sKextSummariesLock);
15035 
15036 	/* If we had to allocate a new buffer but failed to generate the summaries,
15037 	 * free that now.
15038 	 */
15039 	if (summaryHeaderAlloc) {
15040 		kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
15041 	}
15042 	if (prevAccountingList) {
15043 		IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
15044 	}
15045 
15046 	return;
15047 }
15048 
15049 /*********************************************************************
15050 *********************************************************************/
15051 void
15052 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
15053 {
15054 	OSSharedPtr<OSData> uuid;
15055 
15056 	strlcpy(summary->name, getIdentifierCString(),
15057 	    sizeof(summary->name));
15058 
15059 	uuid = copyUUID();
15060 	if (uuid) {
15061 		memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
15062 	}
15063 
15064 	if (flags.builtin) {
15065 //      this value will stop lldb from parsing the mach-o header
15066 //      summary->address = UINT64_MAX;
15067 //      summary->size = 0;
15068 		summary->address = kmod_info->address;
15069 		summary->size = kmod_info->size;
15070 	} else {
15071 		summary->address = kmod_info->address;
15072 		summary->size = kmod_info->size;
15073 	}
15074 	summary->version = getVersion();
15075 	summary->loadTag = kmod_info->id;
15076 	summary->flags = 0;
15077 	summary->reference_list = (uint64_t) kmod_info->reference_list;
15078 
15079 	summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size);
15080 	if (summary->text_exec_address == 0) {
15081 		// Fallback to __TEXT
15082 		summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size);
15083 	}
15084 	return;
15085 }
15086 
15087 /*********************************************************************
15088 *********************************************************************/
15089 
15090 void
15091 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
15092 {
15093 	kernel_mach_header_t     *hdr = NULL;
15094 	kernel_segment_command_t *seg = NULL;
15095 
15096 	bzero(accountp, sizeof(*accountp));
15097 
15098 	hdr = (kernel_mach_header_t *)kmod_info->address;
15099 	if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) {
15100 		/*
15101 		 * If this kext supports split segments (or is in a new
15102 		 * MH_FILESET kext collection), use the first
15103 		 * executable segment as the range for instructions
15104 		 * (and thus for backtracing.
15105 		 */
15106 		for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
15107 			if (seg->initprot & VM_PROT_EXECUTE) {
15108 				break;
15109 			}
15110 		}
15111 	}
15112 	if (seg) {
15113 		accountp->address = seg->vmaddr;
15114 		if (accountp->address) {
15115 			accountp->address_end = seg->vmaddr + seg->vmsize;
15116 		}
15117 	} else {
15118 		/* For non-split kexts and for kexts without executable
15119 		 * segments, just use the kmod_info range (as the kext
15120 		 * is either all in one range or should not show up in
15121 		 * instruction backtraces).
15122 		 */
15123 		accountp->address = kmod_info->address;
15124 		if (accountp->address) {
15125 			accountp->address_end = kmod_info->address + kmod_info->size;
15126 		}
15127 	}
15128 
15129 	accountp->account = this->account;
15130 }
15131 
15132 bool
15133 OSKext::isDriverKit(void)
15134 {
15135 	OSString *bundleType;
15136 
15137 	if (infoDict) {
15138 		bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
15139 		if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
15140 			return TRUE;
15141 		}
15142 	}
15143 	return FALSE;
15144 }
15145 
15146 bool
15147 OSKext::isInFileset(void)
15148 {
15149 	if (!kmod_info) {
15150 		goto check_prelinked;
15151 	}
15152 
15153 	if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) {
15154 		return true;
15155 	}
15156 
15157 check_prelinked:
15158 	if (isPrelinked()) {
15159 		/*
15160 		 * If we haven't setup kmod_info yet, but we know
15161 		 * we're loading a prelinked kext in an MH_FILESET KC,
15162 		 * then return true
15163 		 */
15164 		kc_format_t kc_format;
15165 		if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
15166 			return true;
15167 		}
15168 	}
15169 	return false;
15170 }
15171 
15172 bool
15173 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg)
15174 {
15175 	kern_return_t result;
15176 	if (!super::init()) {
15177 		return false;
15178 	}
15179 	if (seg == nullptr) {
15180 		return false;
15181 	}
15182 	result = kmem_alloc_pageable(kernel_map, (vm_offset_t *)&data, seg->vmsize, VM_KERN_MEMORY_KEXT);
15183 	if (result != KERN_SUCCESS) {
15184 		return false;
15185 	}
15186 	memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize);
15187 	savedSegment = seg;
15188 	vmsize = seg->vmsize;
15189 	vmaddr = seg->vmaddr;
15190 	return true;
15191 }
15192 
15193 OSSharedPtr<OSKextSavedMutableSegment>
15194 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg)
15195 {
15196 	OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>();
15197 	if (me && !me->initWithSegment(seg)) {
15198 		return nullptr;
15199 	}
15200 	return me;
15201 }
15202 
15203 void
15204 OSKextSavedMutableSegment::free(void)
15205 {
15206 	if (data) {
15207 		kmem_free(kernel_map, (vm_offset_t)data, vmsize);
15208 	}
15209 }
15210 
15211 vm_offset_t
15212 OSKextSavedMutableSegment::getVMAddr() const
15213 {
15214 	return vmaddr;
15215 }
15216 
15217 vm_offset_t
15218 OSKextSavedMutableSegment::getVMSize() const
15219 {
15220 	return vmsize;
15221 }
15222 
15223 OSReturn
15224 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg)
15225 {
15226 	if (seg != savedSegment) {
15227 		return kOSKextReturnInvalidArgument;
15228 	}
15229 	if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) {
15230 		return kOSKextReturnInvalidArgument;
15231 	}
15232 	memcpy((void *)seg->vmaddr, data, vmsize);
15233 	return kOSReturnSuccess;
15234 }
15235 
15236 extern "C" const vm_allocation_site_t *
15237 OSKextGetAllocationSiteForCaller(uintptr_t address)
15238 {
15239 	OSKextActiveAccount *  active;
15240 	vm_allocation_site_t * site;
15241 	vm_allocation_site_t * releasesite;
15242 
15243 	uint32_t baseIdx;
15244 	uint32_t lim;
15245 #if  __has_feature(ptrauth_calls)
15246 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
15247 #endif /*  __has_feature(ptrauth_calls) */
15248 
15249 	IOSimpleLockLock(sKextAccountsLock);
15250 	site = releasesite = NULL;
15251 
15252 	// bsearch sKextAccounts list
15253 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15254 		active = &sKextAccounts[baseIdx + (lim >> 1)];
15255 		if ((address >= active->address) && (address < active->address_end)) {
15256 			site = &active->account->site;
15257 			if (!site->tag) {
15258 				vm_tag_alloc_locked(site, &releasesite);
15259 			}
15260 			break;
15261 		} else if (address > active->address) {
15262 			// move right
15263 			baseIdx += (lim >> 1) + 1;
15264 			lim--;
15265 		}
15266 		// else move left
15267 	}
15268 	IOSimpleLockUnlock(sKextAccountsLock);
15269 	if (releasesite) {
15270 		kern_allocation_name_release(releasesite);
15271 	}
15272 
15273 	return site;
15274 }
15275 
15276 extern "C" uint32_t
15277 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
15278 {
15279 	OSKextAccount * account = (typeof(account))site;
15280 	const char    * kname;
15281 
15282 	if (name) {
15283 		if (account->kext) {
15284 			kname = account->kext->getIdentifierCString();
15285 		} else {
15286 			kname = "<>";
15287 		}
15288 		strlcpy(name, kname, namelen);
15289 	}
15290 
15291 	return account->loadTag;
15292 }
15293 
15294 extern "C" void
15295 OSKextFreeSite(vm_allocation_site_t * site)
15296 {
15297 	OSKextAccount * freeAccount = (typeof(freeAccount))site;
15298 	IODelete(freeAccount, OSKextAccount, 1);
15299 }
15300 
15301 /*********************************************************************
15302 *********************************************************************/
15303 
15304 #if CONFIG_IMAGEBOOT
15305 int
15306 OSKextGetUUIDForName(const char *name, uuid_t uuid)
15307 {
15308 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name);
15309 	if (!kext) {
15310 		return 1;
15311 	}
15312 
15313 	OSSharedPtr<OSData> uuid_data = kext->copyUUID();
15314 	if (uuid_data) {
15315 		memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
15316 		return 0;
15317 	}
15318 
15319 	return 1;
15320 }
15321 #endif
15322 
15323 static int
15324 sysctl_willuserspacereboot
15325 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
15326 {
15327 	int new_value = 0, old_value = 0, changed = 0;
15328 	int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
15329 	if (error) {
15330 		return error;
15331 	}
15332 	if (changed) {
15333 		OSKext::willUserspaceReboot();
15334 	}
15335 	return 0;
15336 }
15337 
15338 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot,
15339     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
15340     NULL, 0, sysctl_willuserspacereboot, "I", "");
15341