xref: /xnu-11215/libkern/c++/OSKext.cpp (revision aca3beaa)
1 /*
2  * Copyright (c) 2008-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #define IOKIT_ENABLE_SHARED_PTR
30 
31 extern "C" {
32 #include <string.h>
33 #include <kern/clock.h>
34 #include <kern/host.h>
35 #include <kern/kext_alloc.h>
36 #include <firehose/tracepoint_private.h>
37 #include <firehose/chunk_private.h>
38 #include <os/firehose_buffer_private.h>
39 #include <vm/vm_map.h>
40 #include <kextd/kextd_mach.h>
41 #include <libkern/kernel_mach_header.h>
42 #include <libkern/kext_panic_report.h>
43 #include <libkern/kext_request_keys.h>
44 #include <libkern/mkext.h>
45 #include <libkern/prelink.h>
46 #include <libkern/version.h>
47 #include <libkern/zlib.h>
48 #include <mach/host_special_ports.h>
49 #include <mach/mach_vm.h>
50 #include <mach/mach_time.h>
51 #include <uuid/uuid.h>
52 #include <sys/random.h>
53 #include <pexpert/pexpert.h>
54 
55 #include <sys/pgo.h>
56 
57 #if CONFIG_CSR
58 #include <sys/csr.h>
59 #include <sys/stat.h>
60 #include <sys/vnode.h>
61 #endif /* CONFIG_CSR */
62 };
63 
64 #if CONFIG_MACF
65 #include <sys/kauth.h>
66 #include <security/mac_framework.h>
67 #endif
68 
69 #include <vm/vm_kern.h>
70 #include <sys/sysctl.h>
71 #include <kern/task.h>
72 #include <os/cpp_util.h>
73 
74 #include <libkern/OSKextLibPrivate.h>
75 #include <libkern/c++/OSKext.h>
76 #include <libkern/c++/OSLib.h>
77 
78 #include <IOKit/IOLib.h>
79 #include <IOKit/IOCatalogue.h>
80 #include <IOKit/IORegistryEntry.h>
81 #include <IOKit/IOService.h>
82 #include <IOKit/IOUserServer.h>
83 
84 #include <IOKit/IOStatisticsPrivate.h>
85 #include <IOKit/IOBSD.h>
86 #include <IOKit/IOPlatformExpert.h>
87 
88 #include <san/kasan.h>
89 
90 
91 #if PRAGMA_MARK
92 #pragma mark External & Internal Function Protos
93 #endif
94 /*********************************************************************
95 *********************************************************************/
96 extern "C" {
97 extern int  IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
98 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
99 
100 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
101 extern int dtrace_keep_kernel_symbols(void);
102 
103 #if defined(__x86_64__) || defined(__i386__)
104 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide);
105 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers);
106 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size);
107 static void *allocate_kcfileset_map_entry_list(void);
108 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size);
109 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable);
110 int vnode_put(struct vnode *vp);
111 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size,
112     void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot);
113 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size);
114 void * ubc_getobject(struct vnode *vp, __unused int flags);
115 #endif //(__x86_64__) || defined(__i386__)
116 }
117 
118 extern unsigned long gVirtBase;
119 extern unsigned long gPhysBase;
120 extern vm_map_t g_kext_map;
121 
122 bool pageableKCloaded = false;
123 bool auxKCloaded = false;
124 bool resetAuxKCSegmentOnUnload = false;
125 
126 extern boolean_t pageablekc_uuid_valid;
127 extern uuid_t pageablekc_uuid;
128 extern uuid_string_t pageablekc_uuid_string;
129 
130 extern boolean_t auxkc_uuid_valid;
131 extern uuid_t auxkc_uuid;
132 extern uuid_string_t auxkc_uuid_string;
133 
134 static OSReturn _OSKextCreateRequest(
135 	const char    * predicate,
136 	OSSharedPtr<OSDictionary> & requestP);
137 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
138 static OSObject * _OSKextGetRequestArgument(
139 	OSDictionary * requestDict,
140 	const char   * argName);
141 static bool _OSKextSetRequestArgument(
142 	OSDictionary    * requestDict,
143 	const char      * argName,
144 	OSMetaClassBase * value);
145 template <typename T>
146 static T * _OSKextExtractPointer(OSValueObject<T *> * wrapper);
147 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper);
148 static OSReturn _OSDictionarySetCStringValue(
149 	OSDictionary * dict,
150 	const char   * key,
151 	const char   * value);
152 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
153 #if CONFIG_KXLD
154 static bool _OSKextInPrelinkRebuildWindow(void);
155 #endif
156 
157 // We really should add containsObject() & containsCString to OSCollection & subclasses.
158 // So few pad slots, though....
159 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
160 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
161 
162 static const char *getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size);
163 
164 /* Prelinked arm kexts do not have VM entries because the method we use to
165  * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
166  * not work on ARM.  To get around that, we must free prelinked kext
167  * executables with ml_static_mfree() instead of kext_free().
168  */
169 #if __i386__ || __x86_64__
170 #define VM_MAPPED_KEXTS 1
171 #define KASLR_KEXT_DEBUG 0
172 #define KASLR_IOREG_DEBUG 0
173 #elif __arm__ || __arm64__
174 #define VM_MAPPED_KEXTS 0
175 #define KASLR_KEXT_DEBUG 0
176 #else
177 #error Unsupported architecture
178 #endif
179 
180 #if PRAGMA_MARK
181 #pragma mark Constants & Macros
182 #endif
183 /*********************************************************************
184 * Constants & Macros
185 *********************************************************************/
186 
187 /* Use this number to create containers.
188  */
189 #define kOSKextTypicalLoadCount      (150)
190 #define kOSKextTypicalUpgradeCount     (5)
191 
192 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
193  * A loaded kext will no dependents or external retains will have 2 retains.
194  */
195 #define kOSKextMinRetainCount        (1)
196 #define kOSKextMinLoadedRetainCount  (2)
197 
198 #define kOSKextMaxDextLaunchedCount  (~((uint32_t)0))
199 #define KOSBundleDextUniqueIdentifierMaxStringLength (KOSBundleDextUniqueIdentifierMaxLength * 2 +1)
200 
201 /**********
202  * Strings and substrings used in dependency resolution.
203  */
204 #define APPLE_KEXT_PREFIX            "com.apple."
205 #define KERNEL_LIB                   "com.apple.kernel"
206 
207 #define PRIVATE_KPI                  "com.apple.kpi.private"
208 
209 /* Version for compatbility pseudokexts (com.apple.kernel.*),
210  * compatible back to v6.0.
211  */
212 #define KERNEL6_LIB                  "com.apple.kernel.6.0"
213 #define KERNEL6_VERSION              "7.9.9"
214 
215 #define KERNEL_LIB_PREFIX            "com.apple.kernel."
216 #define KPI_LIB_PREFIX               "com.apple.kpi."
217 
218 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0)
219 
220 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
221 #define MINIMUM_WAKEUP_SECONDS (30)
222 
223 /*********************************************************************
224 * infoDict keys for internally-stored data. Saves on ivar slots for
225 * objects we don't keep around past boot time or during active load.
226 *********************************************************************/
227 
228 /* A usable, uncompressed file is stored under this key.
229  */
230 #define _kOSKextExecutableKey                "_OSKextExecutable"
231 
232 /* An indirect reference to the executable file from an mkext
233  * is stored under this key.
234  */
235 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference"
236 
237 /* If the file is contained in a larger buffer laid down by the booter or
238  * sent from user space, the OSKext stores that OSData under this key so that
239  * references are properly tracked. This is always an mkext, right now.
240  */
241 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData"
242 
243 #define OS_LOG_HDR_VERSION  1
244 #define NUM_OS_LOG_SECTIONS 3
245 
246 #define OS_LOG_SECT_IDX         0
247 #define CSTRING_SECT_IDX        1
248 #define ASAN_CSTRING_SECT_IDX   2
249 
250 #if PRAGMA_MARK
251 #pragma mark Typedefs
252 #endif
253 /*********************************************************************
254 * Typedefs
255 *********************************************************************/
256 
257 /*********************************************************************
258 * osLogDataHeaderRef describes the header information of an OSData
259 * object that is returned when querying for kOSBundleLogStringsKey.
260 * We currently return information regarding 2 sections - os_log and
261 * cstring. In the case that the os_log section doesn't exist, we just
262 * return an offset and length of 0 for that section.
263 *********************************************************************/
264 typedef struct osLogDataHeader {
265 	uint32_t version;
266 	uint32_t sect_count;
267 	struct {
268 		uint32_t sect_offset;
269 		uint32_t sect_size;
270 	} sections[0];
271 } osLogDataHeaderRef;
272 
273 /*********************************************************************
274 * MkextEntryRef describes the contents of an OSData object
275 * referencing a file entry from an mkext so that we can uncompress
276 * (if necessary) and extract it on demand.
277 *
278 * It contains the mkextVersion in case we ever wind up supporting
279 * multiple mkext formats. Mkext format 1 is officially retired as of
280 * Snow Leopard.
281 *********************************************************************/
282 typedef struct MkextEntryRef {
283 	mkext_basic_header * mkext; // beginning of whole mkext file
284 	void               * fileinfo;// mkext2_file_entry or equiv; see mkext.h
285 } MkextEntryRef;
286 
287 #if PRAGMA_MARK
288 #pragma mark Global and static Module Variables
289 #endif
290 /*********************************************************************
291 * Global & static variables, used to keep track of kexts.
292 *********************************************************************/
293 
294 static  bool                sPrelinkBoot               = false;
295 static  bool                sSafeBoot                  = false;
296 static  bool                sKeepSymbols               = false;
297 static  bool                sPanicOnKCMismatch         = false;
298 static  bool                sOSKextWasResetAfterUserspaceReboot = false;
299 
300 /*********************************************************************
301  * sKextLock is the principal lock for OSKext, and guards all static
302  * and global variables not owned by other locks (declared further
303  * below). It must be taken by any entry-point method or function,
304  * including internal functions called on scheduled threads.
305  *
306  * sKextLock and sKextInnerLock are recursive due to multiple functions
307  * that are called both externally and internally. The other locks are
308  * nonrecursive.
309  *
310  * Which locks are taken depends on what they protect, but if more than
311  * one must be taken, they must always be locked in this order
312  * (and unlocked in reverse order) to prevent deadlocks:
313  *
314  *    1. sKextLock
315  *    2. sKextInnerLock
316  *    3. sKextSummariesLock
317  *    4. sKextLoggingLock
318  */
319 static IORecursiveLock    * sKextLock                  = NULL;
320 
321 static OSSharedPtr<OSDictionary>   sKextsByID;
322 static OSSharedPtr<OSDictionary>   sExcludeListByID;
323 static OSKextVersion               sExcludeListVersion        = 0;
324 static OSSharedPtr<OSArray>        sLoadedKexts;
325 static OSSharedPtr<OSDictionary>   sNonLoadableKextsByID;
326 static OSSharedPtr<OSArray>        sUnloadedPrelinkedKexts;
327 static OSSharedPtr<OSArray>        sLoadedDriverKitKexts;
328 static OSSharedPtr<OSDictionary>   sDriverKitToUpgradeByID;
329 
330 // Requests to the IOKit daemon waiting to be picked up.
331 static OSSharedPtr<OSArray>        sKernelRequests;
332 // Identifier of kext load requests in sKernelRequests
333 static OSSharedPtr<OSSet>          sPostedKextLoadIdentifiers;
334 static OSSharedPtr<OSArray>        sRequestCallbackRecords;
335 
336 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
337 static OSSharedPtr<OSSet>          sAllKextLoadIdentifiers;
338 #if CONFIG_KXLD
339 static KXLDContext        * sKxldContext               = NULL;
340 #endif
341 static uint32_t             sNextLoadTag               = 0;
342 static uint32_t             sNextRequestTag            = 0;
343 
344 static bool                 sUserLoadsActive           = false;
345 static bool                 sIOKitDaemonActive         = false;
346 static bool                 sDeferredLoadSucceeded     = false;
347 static bool                 sConsiderUnloadsExecuted   = false;
348 
349 #if NO_KEXTD
350 static bool                 sKernelRequestsEnabled     = false;
351 #else
352 static bool                 sKernelRequestsEnabled     = true;
353 #endif
354 static bool                 sLoadEnabled               = true;
355 static bool                 sUnloadEnabled             = true;
356 
357 /*********************************************************************
358  * Stuff for the OSKext representing the kernel itself.
359  **********/
360 static OSKext          * sKernelKext             = NULL;
361 
362 /* Load Tag IDs used by statically loaded binaries (e.g, the kernel itself). */
363 enum : uint32_t {
364 	kOSKextKernelLoadTag = 0,
365 	kOSKextLoadTagCount
366 };
367 
368 /* Set up a fake kmod_info struct for the kernel.
369  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
370  * before OSKext is initialized; that call only needs the name
371  * and address to be set correctly.
372  *
373  * We don't do much else with the kerne's kmod_info; we never
374  * put it into the kmod list, never adjust the reference count,
375  * and never have kernel components reference it.
376  * For that matter, we don't do much with kmod_info structs
377  * at all anymore! We just keep them filled in for gdb and
378  * binary compability.
379  */
380 kmod_info_t g_kernel_kmod_info = {
381 	.next =            NULL,
382 	.info_version =    KMOD_INFO_VERSION,
383 	.id =              kOSKextKernelLoadTag,   // loadTag: kernel is always 0
384 	.name =            kOSKextKernelIdentifier,// bundle identifier
385 	.version =         "0",           // filled in in OSKext::initialize()
386 	.reference_count = -1,            // never adjusted; kernel never unloads
387 	.reference_list =  NULL,
388 	.address =         0,
389 	.size =            0,             // filled in in OSKext::initialize()
390 	.hdr_size =        0,
391 	.start =           NULL,
392 	.stop =            NULL
393 };
394 
395 
396 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
397 
398 kmod_info_t invalid_kmod_info = {
399 	.next =            NULL,
400 	.info_version =    KMOD_INFO_VERSION,
401 	.id =              UINT32_MAX,
402 	.name =            "invalid",
403 	.version =         "0",
404 	.reference_count = -1,
405 	.reference_list =  NULL,
406 	.address =         0,
407 	.size =            0,
408 	.hdr_size =        0,
409 	.start =           NULL,
410 	.stop =            NULL
411 };
412 
413 extern "C" {
414 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
415 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
416 // misc_protos.h, db_low_trace.c, kgmacros
417 // 'kmod' is a holdover from the old kmod system, we can't rename it.
418 kmod_info_t * kmod = NULL;
419 
420 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE)
421 
422 
423 static char     * loaded_kext_paniclist         = NULL;
424 static uint32_t   loaded_kext_paniclist_size    = 0;
425 
426 AbsoluteTime      last_loaded_timestamp;
427 static char       last_loaded_str_buf[2 * KMOD_MAX_NAME];
428 static u_long     last_loaded_strlen            = 0;
429 static void     * last_loaded_address           = NULL;
430 static u_long     last_loaded_size              = 0;
431 
432 AbsoluteTime      last_unloaded_timestamp;
433 static char       last_unloaded_str_buf[2 * KMOD_MAX_NAME];
434 static u_long     last_unloaded_strlen          = 0;
435 static void     * last_unloaded_address         = NULL;
436 static u_long     last_unloaded_size            = 0;
437 
438 // Statically linked kmods described by several mach-o sections:
439 //
440 // kPrelinkInfoSegment:kBuiltinInfoSection
441 // Array of pointers to kmod_info_t structs.
442 //
443 // kPrelinkInfoSegment:kBuiltinInfoSection
444 // Array of pointers to an embedded mach-o header.
445 //
446 // __DATA:kBuiltinInitSection, kBuiltinTermSection
447 // Structors for all kmods. Has to be filtered by proc address.
448 //
449 
450 static uint32_t gBuiltinKmodsCount;
451 static kernel_section_t * gBuiltinKmodsSectionInfo;
452 static kernel_section_t * gBuiltinKmodsSectionStart;
453 
454 const OSSymbol              * gIOSurfaceIdentifier;
455 vm_tag_t                      gIOSurfaceTag;
456 
457 /*********************************************************************
458  * sKextInnerLock protects against cross-calls with IOService and
459  * IOCatalogue, and owns the variables declared immediately below.
460  *
461  * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
462  *
463  * When both sKextLock and sKextInnerLock need to be taken,
464  * always lock sKextLock first and unlock it second. Never take both
465  * locks in an entry point to OSKext; if you need to do so, you must
466  * spawn an independent thread to avoid potential deadlocks for threads
467  * calling into OSKext.
468  **********/
469 static IORecursiveLock *    sKextInnerLock             = NULL;
470 
471 #if XNU_TARGET_OS_OSX
472 static bool                 sAutounloadEnabled         = true;
473 #endif
474 static bool                 sConsiderUnloadsCalled     = false;
475 static bool                 sConsiderUnloadsPending    = false;
476 
477 static unsigned int         sConsiderUnloadDelay       = 60;     // seconds
478 static thread_call_t        sUnloadCallout             = NULL;
479 #if CONFIG_KXLD
480 static thread_call_t        sDestroyLinkContextThread  = NULL;   // one-shot, one-at-a-time thread
481 #endif // CONFIG_KXLD
482 static bool                 sSystemSleep               = false;  // true when system going to sleep
483 static AbsoluteTime         sLastWakeTime;                       // last time we woke up
484 
485 /*********************************************************************
486  * Backtraces can be printed at various times so we need a tight lock
487  * on data used for that. sKextSummariesLock protects the variables
488  * declared immediately below.
489  *
490  * gLoadedKextSummaries is accessed by other modules, but only during
491  * a panic so the lock isn't needed then.
492  *
493  * gLoadedKextSummaries has the "used" attribute in order to ensure
494  * that it remains visible even when we are performing extremely
495  * aggressive optimizations, as it is needed to allow the debugger
496  * to automatically parse the list of loaded kexts.
497  **********/
498 static IOLock                 * sKextSummariesLock                = NULL;
499 extern "C" lck_ticket_t         vm_allocation_sites_lock;
500 extern "C" lck_grp_t            vm_page_lck_grp_bucket;
501 static lck_ticket_t           * sKextAccountsLock = &vm_allocation_sites_lock;
502 static lck_grp_t              * sKextAccountsLockGrp = &vm_page_lck_grp_bucket;
503 
504 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
505 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
506 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
507 static size_t sLoadedKextSummariesAllocSize = 0;
508 
509 static OSKextActiveAccount    * sKextAccounts;
510 static uint32_t                 sKextAccountsCount;
511 };
512 
513 /*********************************************************************
514  * sKextLoggingLock protects the logging variables declared immediately below.
515  **********/
516 static IOLock                 * sKextLoggingLock           = NULL;
517 
518 static  const OSKextLogSpec     kDefaultKernelLogFilter    = kOSKextLogBasicLevel |
519     kOSKextLogVerboseFlagsMask;
520 static  OSKextLogSpec           sKernelLogFilter           = kDefaultKernelLogFilter;
521 static  bool                    sBootArgLogFilterFound     = false;
522 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
523     0, "kernel kext logging");
524 
525 static  OSKextLogSpec           sUserSpaceKextLogFilter    = kOSKextLogSilentFilter;
526 static  OSSharedPtr<OSArray>    sUserSpaceLogSpecArray;
527 static  OSSharedPtr<OSArray>    sUserSpaceLogMessageArray;
528 
529 /*********
530  * End scope for sKextInnerLock-protected variables.
531  *********************************************************************/
532 
533 /*********************************************************************
534  * OSValueObject concrete type instantiations
535  **********/
536 OSDefineValueObjectForDependentType(void*)
537 OSDefineValueObjectForDependentType(OSKextRequestResourceCallback)
538 
539 
540 /**********************************************************************/
541 
542 TUNABLE(uint32_t, kMaxDextCrashesInOneDay, "daily_max_dext_crashes", kMaxDextCrashesInOneDayDefault);
543 
544 /*********************************************************************
545  *  helper function used for collecting PGO data upon unload of a kext
546  */
547 
548 static int OSKextGrabPgoDataLocked(OSKext *kext,
549     bool metadata,
550     uuid_t instance_uuid,
551     uint64_t *pSize,
552     char *pBuffer,
553     uint64_t bufferSize);
554 
555 /**********************************************************************/
556 
557 
558 
559 #if PRAGMA_MARK
560 #pragma mark OSData callbacks (need to move to OSData)
561 #endif
562 /*********************************************************************
563 * C functions used for callbacks.
564 *********************************************************************/
565 extern "C" {
566 void
567 osdata_kmem_free(void * ptr, unsigned int length)
568 {
569 	kmem_free(kernel_map, (vm_address_t)ptr, length);
570 	return;
571 }
572 
573 void
574 osdata_phys_free(void * ptr, unsigned int length)
575 {
576 	ml_static_mfree((vm_offset_t)ptr, length);
577 	return;
578 }
579 
580 void
581 osdata_vm_deallocate(void * ptr, unsigned int length)
582 {
583 	(void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
584 	return;
585 }
586 
587 void
588 osdata_kext_free(void * ptr, unsigned int length)
589 {
590 	(void)kext_free((vm_offset_t)ptr, length);
591 }
592 };
593 
594 #if PRAGMA_MARK
595 #pragma mark KXLD Allocation Callback
596 #endif
597 #if CONFIG_KXLD
598 /*********************************************************************
599 * KXLD Allocation Callback
600 *********************************************************************/
601 kxld_addr_t
602 kern_allocate(
603 	u_long              size,
604 	KXLDAllocateFlags * flags,
605 	void              * user_data)
606 {
607 	vm_address_t  result       = 0; // returned
608 	kern_return_t mach_result  = KERN_FAILURE;
609 	bool          success      = false;
610 	OSKext      * theKext      = (OSKext *)user_data;
611 	unsigned int  roundSize    = 0;
612 	OSSharedPtr<OSData>      linkBuffer;
613 
614 	if (round_page(size) > UINT_MAX) {
615 		OSKextLog(theKext,
616 		    kOSKextLogErrorLevel |
617 		    kOSKextLogGeneralFlag,
618 		    "%s: Requested memory size is greater than UINT_MAX.",
619 		    theKext->getIdentifierCString());
620 		goto finish;
621 	}
622 
623 	roundSize = (unsigned int)round_page(size);
624 
625 	mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
626 	if (mach_result != KERN_SUCCESS) {
627 		OSKextLog(theKext,
628 		    kOSKextLogErrorLevel |
629 		    kOSKextLogGeneralFlag,
630 		    "Can't allocate kernel memory to link %s.",
631 		    theKext->getIdentifierCString());
632 		goto finish;
633 	}
634 
635 	/* Create an OSData wrapper for the allocated buffer.
636 	 */
637 	linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
638 	if (!linkBuffer) {
639 		OSKextLog(theKext,
640 		    kOSKextLogErrorLevel |
641 		    kOSKextLogGeneralFlag,
642 		    "Can't allocate linked executable wrapper for %s.",
643 		    theKext->getIdentifierCString());
644 		goto finish;
645 	}
646 	linkBuffer->setDeallocFunction(osdata_kext_free);
647 	OSKextLog(theKext,
648 	    kOSKextLogProgressLevel |
649 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
650 	    "Allocated link buffer for kext %s at %p (%lu bytes).",
651 	    theKext->getIdentifierCString(),
652 	    (void *)result, (unsigned long)roundSize);
653 
654 	theKext->setLinkedExecutable(linkBuffer.get());
655 
656 	*flags = kKxldAllocateWritable;
657 	success = true;
658 
659 finish:
660 	if (!success && result) {
661 		kext_free(result, roundSize);
662 		result = 0;
663 	}
664 
665 	return (kxld_addr_t)result;
666 }
667 
668 /*********************************************************************
669 *********************************************************************/
670 void
671 kxld_log_callback(
672 	KXLDLogSubsystem    subsystem,
673 	KXLDLogLevel        level,
674 	const char        * format,
675 	va_list             argList,
676 	void              * user_data)
677 {
678 	OSKext *theKext = (OSKext *) user_data;
679 	OSKextLogSpec logSpec = 0;
680 
681 	switch (subsystem) {
682 	case kKxldLogLinking:
683 		logSpec |= kOSKextLogLinkFlag;
684 		break;
685 	case kKxldLogPatching:
686 		logSpec |= kOSKextLogPatchFlag;
687 		break;
688 	}
689 
690 	switch (level) {
691 	case kKxldLogExplicit:
692 		logSpec |= kOSKextLogExplicitLevel;
693 		break;
694 	case kKxldLogErr:
695 		logSpec |= kOSKextLogErrorLevel;
696 		break;
697 	case kKxldLogWarn:
698 		logSpec |= kOSKextLogWarningLevel;
699 		break;
700 	case kKxldLogBasic:
701 		logSpec |= kOSKextLogProgressLevel;
702 		break;
703 	case kKxldLogDetail:
704 		logSpec |= kOSKextLogDetailLevel;
705 		break;
706 	case kKxldLogDebug:
707 		logSpec |= kOSKextLogDebugLevel;
708 		break;
709 	}
710 
711 	OSKextVLog(theKext, logSpec, format, argList);
712 }
713 #endif // CONFIG_KXLD
714 
715 #if PRAGMA_MARK
716 #pragma mark IOStatistics defines
717 #endif
718 
719 #if IOKITSTATS
720 
721 #define notifyKextLoadObservers(kext, kmod_info) \
722 do { \
723     IOStatistics::onKextLoad(kext, kmod_info); \
724 } while (0)
725 
726 #define notifyKextUnloadObservers(kext) \
727 do { \
728     IOStatistics::onKextUnload(kext); \
729 } while (0)
730 
731 #define notifyAddClassObservers(kext, addedClass, flags) \
732 do { \
733     IOStatistics::onClassAdded(kext, addedClass); \
734 } while (0)
735 
736 #define notifyRemoveClassObservers(kext, removedClass, flags) \
737 do { \
738     IOStatistics::onClassRemoved(kext, removedClass); \
739 } while (0)
740 
741 #else
742 
743 #define notifyKextLoadObservers(kext, kmod_info)
744 #define notifyKextUnloadObservers(kext)
745 #define notifyAddClassObservers(kext, addedClass, flags)
746 #define notifyRemoveClassObservers(kext, removedClass, flags)
747 
748 #endif /* IOKITSTATS */
749 
750 #if PRAGMA_MARK
751 #pragma mark Module Config (Startup & Shutdown)
752 #endif
753 /*********************************************************************
754 * Module Config (Class Definition & Class Methods)
755 *********************************************************************/
756 #define super OSObject
757 OSDefineMetaClassAndStructors(OSKext, OSObject)
758 
759 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject);
760 
761 OSDefineMetaClassAndStructors(OSDextStatistics, OSObject);
762 
763 /*********************************************************************
764 *********************************************************************/
765 /**
766  * Allocate and intialize a fake/representative OSKext object for a statically
767  * loaded (by iBoot) binary (e.g., the XNU kernel itself).
768  *
769  * @param kmod_info Pointer to the kmod_info structure for the binary being
770  *                  setup. At least the "name" and "id" fields needs to already
771  *                  be set correctly.
772  *
773  * @return The allocated and initialized OSKext object.
774  */
775 /* static */
776 OSKext *
777 OSKext::allocAndInitFakeKext(kmod_info_t *kmod_info)
778 {
779 	vm_offset_t load_address = 0;
780 	const char *bundle_name = NULL;
781 	bool macho_is_unslid = false;
782 	bool set_custom_path = false;
783 	const char *executable_fallback_name = NULL;
784 
785 	if (kmod_info->id == kOSKextKernelLoadTag) {
786 		load_address = (vm_offset_t)&_mh_execute_header;
787 		bundle_name = "mach_kernel";
788 
789 		/* The kernel Mach-O header is fixed up to slide all of its addresses. */
790 		macho_is_unslid = false;
791 
792 		/**
793 		 * No path to the binary is set for the kernel in its OSKext object. The
794 		 * kernel binary is located in fixed directories depending on the OS.
795 		 */
796 		set_custom_path = false;
797 		executable_fallback_name = NULL;
798 	} else {
799 		panic("%s: Unsupported kmod_info->id (%d)", __func__, kmod_info->id);
800 	}
801 
802 	/* Set up an OSKext instance to represent the statically loaded binary. */
803 	OSKext *fakeKext = new OSKext;
804 	assert(fakeKext);
805 	assert(load_address != 0);
806 
807 	/*
808 	 * The start address is always a slid address whereas the last VA returned
809 	 * by getlastaddr() might be unslid depending on the Mach-O. If the address
810 	 * coming from the Mach-O is unslid, then unslide the start address before
811 	 * computing the length of the executable.
812 	 */
813 	size_t binaryLength = getlastaddr((kernel_mach_header_t*)load_address);
814 	binaryLength -= (macho_is_unslid) ? ml_static_unslide(load_address) : load_address;
815 	assert(binaryLength <= UINT_MAX);
816 
817 	/**
818 	 * The load address is always slid. That value will be unslid before being
819 	 * exposed to userspace.
820 	 */
821 	OSSharedPtr<OSData> executable = OSData::withBytesNoCopy(
822 		(void*)load_address, (unsigned int)binaryLength);
823 	assert(executable);
824 
825 	fakeKext->loadTag = sNextLoadTag++;
826 	fakeKext->bundleID = OSSymbol::withCString(kmod_info->name);
827 
828 	fakeKext->version = OSKextParseVersionString(osrelease);
829 	fakeKext->compatibleVersion = fakeKext->version;
830 	fakeKext->linkedExecutable = os::move(executable);
831 	fakeKext->interfaceUUID = fakeKext->copyUUID();
832 
833 	fakeKext->flags.hasAllDependencies = 1;
834 	fakeKext->flags.kernelComponent = 1;
835 	fakeKext->flags.prelinked = 0;
836 	fakeKext->flags.loaded = 1;
837 	fakeKext->flags.started = 1;
838 	fakeKext->flags.CPPInitialized = 0;
839 	fakeKext->flags.jettisonLinkeditSeg = 0;
840 	fakeKext->flags.unslidMachO = macho_is_unslid;
841 
842 
843 	fakeKext->kmod_info = kmod_info;
844 	strlcpy(kmod_info->version, osrelease,
845 	    sizeof(kmod_info->version));
846 	kmod_info->size = binaryLength;
847 	assert(kmod_info->id == fakeKext->loadTag);
848 
849 	/*
850 	 * Con up an info dict, so we don't have to have special-case checking all
851 	 * over.
852 	 */
853 	fakeKext->infoDict = OSDictionary::withCapacity(5);
854 	assert(fakeKext->infoDict);
855 	bool setResult = fakeKext->infoDict->setObject(kCFBundleIdentifierKey,
856 	    fakeKext->bundleID.get());
857 	assert(setResult);
858 	setResult = fakeKext->infoDict->setObject(kOSKernelResourceKey,
859 	    kOSBooleanTrue);
860 	assert(setResult);
861 
862 	{
863 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease));
864 		assert(scratchString);
865 		setResult = fakeKext->infoDict->setObject(kCFBundleVersionKey,
866 		    scratchString.get());
867 		assert(setResult);
868 	}
869 
870 	{
871 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(bundle_name));
872 		assert(scratchString);
873 		setResult = fakeKext->infoDict->setObject(kCFBundleNameKey,
874 		    scratchString.get());
875 		assert(setResult);
876 	}
877 
878 	return fakeKext;
879 }
880 
881 /* static */
882 void
883 OSKext::initialize(void)
884 {
885 	OSSharedPtr<OSData>     kernelExecutable   = NULL;// do not release
886 	IORegistryEntry * registryRoot       = NULL;// do not release
887 	OSSharedPtr<OSNumber> kernelCPUType;
888 	OSSharedPtr<OSNumber> kernelCPUSubtype;
889 	OSKextLogSpec     bootLogFilter      = kOSKextLogSilentFilter;
890 	bool              setResult          = false;
891 	uint64_t        * timestamp          = NULL;
892 	__unused char     bootArgBuffer[16];// for PE_parse_boot_argn w/strings
893 
894 	/* This must be the first thing allocated. Everything else grabs this lock.
895 	 */
896 	sKextLock = IORecursiveLockAlloc();
897 	sKextInnerLock = IORecursiveLockAlloc();
898 	sKextSummariesLock = IOLockAlloc();
899 	sKextLoggingLock = IOLockAlloc();
900 	assert(sKextLock);
901 	assert(sKextInnerLock);
902 	assert(sKextSummariesLock);
903 	assert(sKextLoggingLock);
904 
905 	sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
906 	sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
907 	sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
908 	sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
909 	sKernelRequests = OSArray::withCapacity(0);
910 	sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
911 	sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
912 	sRequestCallbackRecords = OSArray::withCapacity(0);
913 	sDriverKitToUpgradeByID = OSDictionary::withCapacity(kOSKextTypicalUpgradeCount);
914 
915 	assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
916 	    sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
917 	    sRequestCallbackRecords && sUnloadedPrelinkedKexts && sDriverKitToUpgradeByID);
918 
919 	/* Read the log flag boot-args and set the log flags.
920 	 */
921 	if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
922 		sBootArgLogFilterFound = true;
923 		sKernelLogFilter = bootLogFilter;
924 		// log this if any flags are set
925 		OSKextLog(/* kext */ NULL,
926 		    kOSKextLogBasicLevel |
927 		    kOSKextLogFlagsMask,
928 		    "Kernel kext log filter 0x%x per kextlog boot arg.",
929 		    (unsigned)sKernelLogFilter);
930 	}
931 
932 #if !defined(__arm__) && !defined(__arm64__)
933 	/*
934 	 * On our ARM targets, the kernelcache/boot kernel collection contains
935 	 * the set of kexts required to boot, as specified by KCB.  Safeboot is
936 	 * either unsupported, or is supported by the bootloader only loading
937 	 * the boot kernel collection; as a result OSKext has no role to play
938 	 * in safeboot policy on ARM.
939 	 */
940 	sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
941 	    sizeof(bootArgBuffer)) ? true : false;
942 #endif /* defined(__arm__) && defined(__arm64__) */
943 
944 	if (sSafeBoot) {
945 		OSKextLog(/* kext */ NULL,
946 		    kOSKextLogWarningLevel |
947 		    kOSKextLogGeneralFlag,
948 		    "SAFE BOOT DETECTED - "
949 		    "only valid OSBundleRequired kexts will be loaded.");
950 	}
951 
952 	PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
953 #if CONFIG_DTRACE
954 	if (dtrace_keep_kernel_symbols()) {
955 		sKeepSymbols = true;
956 	}
957 #endif /* CONFIG_DTRACE */
958 #if KASAN_DYNAMIC_BLACKLIST
959 	/* needed for function lookup */
960 	sKeepSymbols = true;
961 #endif
962 
963 	/*
964 	 * Should we panic when the SystemKC is not linked against the
965 	 * BootKC that was loaded by the booter? By default: yes, if the
966 	 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic
967 	 * on mis-match and instead just print an error and continue.
968 	 */
969 	sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer,
970 	    sizeof(bootArgBuffer)) ? false : true;
971 
972 	/* Set up an OSKext instance to represent the kernel itself. */
973 	sKernelKext = allocAndInitFakeKext(&g_kernel_kmod_info);
974 	assert(sKernelKext);
975 
976 
977 	/* Add the kernel kext to the bookkeeping dictionaries. Note that
978 	 * the kernel kext doesn't have a kmod_info struct. copyInfo()
979 	 * gathers info from other places anyhow.
980 	 */
981 	setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext);
982 	assert(setResult);
983 	setResult = sLoadedKexts->setObject(sKernelKext);
984 	assert(setResult);
985 
986 
987 	// XXX: better way with OSSharedPtr?
988 	// sKernelKext remains a valid pointer even after the decref
989 	sKernelKext->release();
990 
991 	registryRoot = IORegistryEntry::getRegistryRoot();
992 	kernelCPUType = OSNumber::withNumber(
993 		(long long unsigned int)_mh_execute_header.cputype,
994 		8 * sizeof(_mh_execute_header.cputype));
995 	kernelCPUSubtype = OSNumber::withNumber(
996 		(long long unsigned int)_mh_execute_header.cpusubtype,
997 		8 * sizeof(_mh_execute_header.cpusubtype));
998 	assert(registryRoot && kernelCPUSubtype && kernelCPUType);
999 
1000 	registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get());
1001 	registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get());
1002 
1003 	gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
1004 	if (gBuiltinKmodsSectionInfo) {
1005 		uint32_t count;
1006 
1007 		assert(gBuiltinKmodsSectionInfo->addr);
1008 		assert(gBuiltinKmodsSectionInfo->size);
1009 		assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX);
1010 		gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
1011 
1012 		gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
1013 		assert(gBuiltinKmodsSectionStart);
1014 		assert(gBuiltinKmodsSectionStart->addr);
1015 		assert(gBuiltinKmodsSectionStart->size);
1016 		assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX);
1017 		count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
1018 		// one extra pointer for the end of last kmod
1019 		assert(count == (gBuiltinKmodsCount + 1));
1020 
1021 		vm_kernel_builtinkmod_text     = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
1022 		vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
1023 	}
1024 
1025 	// Don't track this object -- it's never released
1026 	gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach();
1027 
1028 	timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
1029 	*timestamp = 0;
1030 	timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
1031 	*timestamp = 0;
1032 	timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
1033 	*timestamp = 0;
1034 
1035 	OSKextLog(/* kext */ NULL,
1036 	    kOSKextLogProgressLevel |
1037 	    kOSKextLogGeneralFlag,
1038 	    "Kext system initialized.");
1039 
1040 	notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
1041 
1042 	return;
1043 }
1044 
1045 /*********************************************************************
1046 * This is expected to be called exactly once, from exactly one thread
1047 * context, during kernel bootstrap.
1048 *********************************************************************/
1049 /* static */
1050 OSReturn
1051 OSKext::removeKextBootstrap(void)
1052 {
1053 	OSReturn                   result                = kOSReturnError;
1054 
1055 	const char               * dt_kernel_header_name = "Kernel-__HEADER";
1056 	const char               * dt_kernel_symtab_name = "Kernel-__SYMTAB";
1057 	kernel_mach_header_t     * dt_mach_header        = NULL;
1058 	int                        dt_mach_header_size   = 0;
1059 	struct symtab_command    * dt_symtab             = NULL;
1060 	int                        dt_symtab_size        = 0;
1061 	int                        dt_result             = 0;
1062 
1063 	kernel_segment_command_t * seg_kld               = NULL;
1064 	kernel_segment_command_t * seg_klddata           = NULL;
1065 	kernel_segment_command_t * seg_linkedit          = NULL;
1066 
1067 	const char __unused      * dt_segment_name       = NULL;
1068 	void       __unused      * segment_paddress      = NULL;
1069 	int        __unused        segment_size          = 0;
1070 
1071 	OSKextLog(/* kext */ NULL,
1072 	    kOSKextLogProgressLevel |
1073 	    kOSKextLogGeneralFlag,
1074 	    "Jettisoning kext bootstrap segments.");
1075 
1076 	/*
1077 	 * keep the linkedit segment around when booted from a new MH_FILESET
1078 	 * KC because all the kexts shared a linkedit segment.
1079 	 */
1080 	kc_format_t kc_format;
1081 	if (!PE_get_primary_kc_format(&kc_format)) {
1082 		OSKextLog(/* kext */ NULL,
1083 		    kOSKextLogErrorLevel |
1084 		    kOSKextLogGeneralFlag,
1085 		    "Unable to determine primary KC format");
1086 	}
1087 
1088 	/*****
1089 	 * Dispose of unnecessary stuff that the booter didn't need to load.
1090 	 */
1091 	dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
1092 	    (void **)&dt_mach_header, &dt_mach_header_size);
1093 	if (dt_result == 0 && dt_mach_header) {
1094 		IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
1095 		    round_page_32(dt_mach_header_size));
1096 	}
1097 	dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
1098 	    (void **)&dt_symtab, &dt_symtab_size);
1099 	if (dt_result == 0 && dt_symtab) {
1100 		IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
1101 		    round_page_32(dt_symtab_size));
1102 	}
1103 
1104 	/*****
1105 	 * KLD & KLDDATA bootstrap segments.
1106 	 */
1107 	// xxx - should rename KLD segment
1108 	seg_kld = getsegbyname("__KLD");
1109 	seg_klddata = getsegbyname("__KLDDATA");
1110 	if (seg_klddata) {
1111 		// __mod_term_func is part of __KLDDATA
1112 		OSRuntimeUnloadCPPForSegment(seg_klddata);
1113 	}
1114 
1115 #if __arm__ || __arm64__
1116 	/* Free the memory that was set up by iBoot.
1117 	 */
1118 #if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR)
1119 	/* We cannot free the KLD segment with CTRR enabled as it contains text and
1120 	 * is covered by the contiguous rorgn.
1121 	 */
1122 	dt_segment_name = "Kernel-__KLD";
1123 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1124 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1125 		    (int)segment_size); // calls ml_static_mfree
1126 	} else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1127 		/* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */
1128 		ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase),
1129 		    seg_kld->vmsize);
1130 	}
1131 #endif
1132 	dt_segment_name = "Kernel-__KLDDATA";
1133 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1134 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1135 		    (int)segment_size);  // calls ml_static_mfree
1136 	} else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1137 		/* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */
1138 		ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase),
1139 		    seg_klddata->vmsize);
1140 	}
1141 #elif __i386__ || __x86_64__
1142 	/* On x86, use the mapping data from the segment load command to
1143 	 * unload KLD & KLDDATA directly.
1144 	 * This may invalidate any assumptions about  "avail_start"
1145 	 * defining the lower bound for valid physical addresses.
1146 	 */
1147 	if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1148 		bzero((void *)seg_kld->vmaddr, seg_kld->vmsize);
1149 		ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
1150 	}
1151 	if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1152 		bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize);
1153 		ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
1154 	}
1155 #else
1156 #error arch
1157 #endif
1158 
1159 	/*****
1160 	 * Prelinked kernel's symtab (if there is one).
1161 	 */
1162 	if (kc_format != KCFormatFileset) {
1163 		kernel_section_t * sect;
1164 		sect = getsectbyname("__PRELINK", "__symtab");
1165 		if (sect && sect->addr && sect->size) {
1166 			ml_static_mfree(sect->addr, sect->size);
1167 		}
1168 	}
1169 
1170 	seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
1171 
1172 	/* kxld always needs the kernel's __LINKEDIT segment, but we can make it
1173 	 * pageable, unless keepsyms is set.  To do that, we have to copy it from
1174 	 * its booter-allocated memory, free the booter memory, reallocate proper
1175 	 * managed memory, then copy the segment back in.
1176 	 *
1177 	 * NOTE: This optimization is not valid for fileset KCs because each
1178 	 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment
1179 	 * that points to one fileset-global LINKEDIT segment. This
1180 	 * optimization is also only valid for platforms that support vm
1181 	 * mapped kexts or mapped kext collections (pageable KCs)
1182 	 */
1183 #if VM_MAPPED_KEXTS
1184 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1185 		kern_return_t mem_result;
1186 		void *seg_copy = NULL;
1187 		void *seg_data = NULL;
1188 		vm_map_offset_t seg_offset = 0;
1189 		vm_map_offset_t seg_copy_offset = 0;
1190 		vm_map_size_t seg_length = 0;
1191 
1192 		seg_data = (void *) seg_linkedit->vmaddr;
1193 		seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr;
1194 		seg_length = (vm_map_size_t) seg_linkedit->vmsize;
1195 
1196 		/* Allocate space for the LINKEDIT copy.
1197 		 */
1198 		mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
1199 		    seg_length, KMA_ZERO, VM_KERN_MEMORY_KEXT);
1200 		if (mem_result != KERN_SUCCESS) {
1201 			OSKextLog(/* kext */ NULL,
1202 			    kOSKextLogErrorLevel |
1203 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1204 			    "Can't copy __LINKEDIT segment for VM reassign.");
1205 			return result;
1206 		}
1207 		seg_copy_offset = (vm_map_offset_t) seg_copy;
1208 
1209 		/* Copy it out.
1210 		 */
1211 		memcpy(seg_copy, seg_data, seg_length);
1212 
1213 		/* Dump the booter memory.
1214 		 */
1215 		ml_static_mfree(seg_offset, seg_length);
1216 
1217 		/* Set up the VM region.
1218 		 */
1219 		mem_result = vm_map_enter_mem_object(
1220 			kernel_map,
1221 			&seg_offset,
1222 			seg_length, /* mask */ 0,
1223 			VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true),
1224 			(ipc_port_t)NULL,
1225 			(vm_object_offset_t) 0,
1226 			/* copy */ FALSE,
1227 			/* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1228 			/* max_protection */ VM_PROT_ALL,
1229 			/* inheritance */ VM_INHERIT_DEFAULT);
1230 		if ((mem_result != KERN_SUCCESS) ||
1231 		    (seg_offset != (vm_map_offset_t) seg_data)) {
1232 			OSKextLog(/* kext */ NULL,
1233 			    kOSKextLogErrorLevel |
1234 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1235 			    "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1236 			    seg_data, seg_length, mem_result);
1237 			return result;
1238 		}
1239 
1240 		/* And copy it back.
1241 		 */
1242 		memcpy(seg_data, seg_copy, seg_length);
1243 
1244 		/* Free the copy.
1245 		 */
1246 		kmem_free(kernel_map, seg_copy_offset, seg_length);
1247 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1248 		/* Remove the linkedit segment of the Boot KC */
1249 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1250 		OSKext::jettisonFileSetLinkeditSegment(mh);
1251 	}
1252 #else // !VM_MAPPED_KEXTS
1253 	/*****
1254 	 * Dump the LINKEDIT segment, unless keepsyms is set.
1255 	 */
1256 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1257 		dt_segment_name = "Kernel-__LINKEDIT";
1258 		if (0 == IODTGetLoaderInfo(dt_segment_name,
1259 		    &segment_paddress, &segment_size)) {
1260 #ifdef SECURE_KERNEL
1261 			vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1262 			bzero((void*)vmaddr, segment_size);
1263 #endif
1264 			IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1265 			    (int)segment_size);
1266 		}
1267 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1268 		/* Remove the linkedit segment of the Boot KC */
1269 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1270 		OSKext::jettisonFileSetLinkeditSegment(mh);
1271 	} else {
1272 		OSKextLog(/* kext */ NULL,
1273 		    kOSKextLogBasicLevel |
1274 		    kOSKextLogGeneralFlag,
1275 		    "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1276 	}
1277 #endif // VM_MAPPED_KEXTS
1278 
1279 	result = kOSReturnSuccess;
1280 
1281 	return result;
1282 }
1283 
1284 #if CONFIG_KXLD
1285 /*********************************************************************
1286 *********************************************************************/
1287 void
1288 OSKext::flushNonloadedKexts(
1289 	Boolean flushPrelinkedKexts)
1290 {
1291 	OSSharedPtr<OSSet>                keepKexts;
1292 
1293 	/* TODO: make this more efficient with MH_FILESET kexts */
1294 
1295 	// Do not unload prelinked kexts on arm because the kernelcache is not
1296 	// structured in a way that allows them to be unmapped
1297 #if !defined(__x86_64__)
1298 	flushPrelinkedKexts = false;
1299 #endif /* defined(__x86_64__) */
1300 
1301 	IORecursiveLockLock(sKextLock);
1302 
1303 	OSKextLog(/* kext */ NULL,
1304 	    kOSKextLogProgressLevel |
1305 	    kOSKextLogKextBookkeepingFlag,
1306 	    "Flushing nonloaded kexts and other unused data.");
1307 
1308 	OSKext::considerDestroyingLinkContext();
1309 
1310 	/* If we aren't flushing unused prelinked kexts, we have to put them
1311 	 * aside while we flush everything else so make a container for them.
1312 	 */
1313 	keepKexts = OSSet::withCapacity(16);
1314 	if (!keepKexts) {
1315 		goto finish;
1316 	}
1317 
1318 	/* Set aside prelinked kexts (in-use or not) and break
1319 	 * any lingering inter-kext references for nonloaded kexts
1320 	 * so they have min. retain counts.
1321 	 */
1322 	{
1323 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1324 			OSKext * thisKext = OSDynamicCast(OSKext, obj);
1325 			if (!thisKext) {
1326 			        return false;
1327 			}
1328 			if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
1329 			        keepKexts->setObject(thisKext);
1330 			} else if (!thisKext->declaresExecutable()) {
1331 			        /*
1332 			         * Don't unload codeless kexts, because they never appear in the loadedKexts array.
1333 			         * Requesting one from the IOKit daemon will load it and then immediately remove it by calling
1334 			         * flushNonloadedKexts().
1335 			         * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
1336 			         */
1337 			        keepKexts->setObject(thisKext);
1338 			} else if (thisKext->isInFileset()) {
1339 			        /* keep all kexts in the new MH_FILESET KC */
1340 			        keepKexts->setObject(thisKext);
1341 			}
1342 
1343 			thisKext->flushDependencies(/* forceIfLoaded */ false);
1344 			return false;
1345 		});
1346 	}
1347 	/* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1348 	 */
1349 	sKextsByID->flushCollection();
1350 
1351 	/* Now put the loaded kexts back into the ID dictionary.
1352 	 */
1353 	sLoadedKexts->iterateObjects(^bool (OSObject * obj) {
1354 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1355 		if (!thisKext) {
1356 		        return false;
1357 		}
1358 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1359 		return false;
1360 	});
1361 
1362 	/* Finally, put back the kept kexts if we saved any.
1363 	 */
1364 	keepKexts->iterateObjects(^bool (OSObject * obj) {
1365 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1366 		if (!thisKext) {
1367 		        return false;
1368 		}
1369 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1370 		return false;
1371 	});
1372 
1373 finish:
1374 	IORecursiveLockUnlock(sKextLock);
1375 	return;
1376 }
1377 #else /* !CONFIG_KXLD */
1378 
1379 void
1380 OSKext::flushNonloadedKexts(
1381 	Boolean flushPrelinkedKexts __unused)
1382 {
1383 	IORecursiveLockLock(sKextLock);
1384 
1385 	OSKextLog(/* kext */ NULL,
1386 	    kOSKextLogProgressLevel |
1387 	    kOSKextLogKextBookkeepingFlag,
1388 	    "Flushing dependency info for non-loaded kexts.");
1389 
1390 	/*
1391 	 * In a world where we don't dynamically link kexts, they all come
1392 	 * from a kext collection that's either in wired memory, or
1393 	 * wire-on-demand. We don't need to mess around with moving kexts in
1394 	 * and out of the sKextsByID array - they can all just stay there.
1395 	 * Here we just flush the dependency list for kexts that are not
1396 	 * loaded.
1397 	 */
1398 	sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1399 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1400 		if (!thisKext) {
1401 		        return false;
1402 		}
1403 		thisKext->flushDependencies(/* forceIfLoaded */ false);
1404 		return false;
1405 	});
1406 
1407 	IORecursiveLockUnlock(sKextLock);
1408 	return;
1409 }
1410 
1411 #endif /* CONFIG_KXLD */
1412 
1413 /*********************************************************************
1414 *********************************************************************/
1415 /* static */
1416 void
1417 OSKext::setIOKitDaemonActive(bool active)
1418 {
1419 	IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
1420 	IORecursiveLockLock(sKextLock);
1421 	sIOKitDaemonActive = active;
1422 	if (sKernelRequests->getCount()) {
1423 		OSKext::pingIOKitDaemon();
1424 	}
1425 	IORecursiveLockUnlock(sKextLock);
1426 
1427 	return;
1428 }
1429 
1430 /*********************************************************************
1431 * OSKextLib.cpp might need access to this someday but for now it's
1432 * private.
1433 *********************************************************************/
1434 extern "C" {
1435 extern void ipc_port_release_send(ipc_port_t);
1436 };
1437 
1438 /* static */
1439 OSReturn
1440 OSKext::pingIOKitDaemon(void)
1441 {
1442 	OSReturn    result     = kOSReturnError;
1443 #if !NO_KEXTD
1444 	mach_port_t kextd_port = IPC_PORT_NULL;
1445 
1446 	if (!sIOKitDaemonActive) {
1447 		result = kOSKextReturnDisabled; // basically unavailable
1448 		goto finish;
1449 	}
1450 
1451 	result = host_get_kextd_port(host_priv_self(), &kextd_port);
1452 	if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1453 		OSKextLog(/* kext */ NULL,
1454 		    kOSKextLogErrorLevel |
1455 		    kOSKextLogIPCFlag,
1456 		    "Can't get " kIOKitDaemonName " port.");
1457 		goto finish;
1458 	}
1459 
1460 	result = kextd_ping(kextd_port);
1461 	if (result != KERN_SUCCESS) {
1462 		OSKextLog(/* kext */ NULL,
1463 		    kOSKextLogErrorLevel |
1464 		    kOSKextLogIPCFlag,
1465 		    kIOKitDaemonName " ping failed (0x%x).", (int)result);
1466 		goto finish;
1467 	}
1468 
1469 finish:
1470 	if (IPC_PORT_VALID(kextd_port)) {
1471 		ipc_port_release_send(kextd_port);
1472 	}
1473 #endif
1474 
1475 	return result;
1476 }
1477 
1478 /*********************************************************************
1479 *********************************************************************/
1480 /* static */
1481 bool
1482 OSKext::iokitDaemonAvailable(void)
1483 {
1484 	int notused;
1485 	if (PE_parse_boot_argn("-restore", &notused, sizeof(notused))) {
1486 		return false;
1487 	}
1488 	return true;
1489 }
1490 
1491 /*********************************************************************
1492 *********************************************************************/
1493 /* static */
1494 void
1495 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1496 {
1497 	IORecursiveLockLock(sKextLock);
1498 	sDeferredLoadSucceeded = succeeded;
1499 	IORecursiveLockUnlock(sKextLock);
1500 
1501 	return;
1502 }
1503 
1504 /*********************************************************************
1505 * Called from IOSystemShutdownNotification.
1506 *********************************************************************/
1507 /* static */
1508 void
1509 OSKext::willShutdown(void)
1510 {
1511 #if !NO_KEXTD
1512 	OSReturn       checkResult = kOSReturnError;
1513 #endif
1514 	OSSharedPtr<OSDictionary> exitRequest;
1515 
1516 	IORecursiveLockLock(sKextLock);
1517 
1518 	OSKext::setLoadEnabled(false);
1519 	OSKext::setUnloadEnabled(false);
1520 	OSKext::setAutounloadsEnabled(false);
1521 	OSKext::setKernelRequestsEnabled(false);
1522 
1523 #if defined(__x86_64__) || defined(__i386__)
1524 	if (IOPMRootDomainGetWillShutdown()) {
1525 		OSKext::freeKCFileSetcontrol();
1526 	}
1527 #endif // (__x86_64__) || defined(__i386__)
1528 
1529 #if !NO_KEXTD
1530 	OSKextLog(/* kext */ NULL,
1531 	    kOSKextLogProgressLevel |
1532 	    kOSKextLogGeneralFlag,
1533 	    "System shutdown; requesting immediate " kIOKitDaemonName " exit.");
1534 
1535 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit,
1536 	    exitRequest);
1537 	if (checkResult != kOSReturnSuccess) {
1538 		goto finish;
1539 	}
1540 	if (!sKernelRequests->setObject(exitRequest.get())) {
1541 		goto finish;
1542 	}
1543 
1544 	OSKext::pingIOKitDaemon();
1545 
1546 finish:
1547 #endif
1548 
1549 	IORecursiveLockUnlock(sKextLock);
1550 	return;
1551 }
1552 
1553 void
1554 OSKext::willUserspaceReboot(void)
1555 {
1556 	OSKext::willShutdown();
1557 	IOService::userSpaceWillReboot();
1558 	gIOCatalogue->terminateDriversForUserspaceReboot();
1559 }
1560 
1561 void
1562 OSKext::resetAfterUserspaceReboot(void)
1563 {
1564 	OSSharedPtr<OSArray> arr = OSArray::withCapacity(1);
1565 	IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */);
1566 
1567 	IORecursiveLockLock(sKextLock);
1568 	gIOCatalogue->resetAfterUserspaceReboot();
1569 	IOService::userSpaceDidReboot();
1570 	OSKext::removeDaemonExitRequests();
1571 	OSKext::setLoadEnabled(true);
1572 	OSKext::setUnloadEnabled(true);
1573 	OSKext::setAutounloadsEnabled(true);
1574 	OSKext::setKernelRequestsEnabled(true);
1575 	sOSKextWasResetAfterUserspaceReboot = true;
1576 	IORecursiveLockUnlock(sKextLock);
1577 }
1578 
1579 extern "C" void
1580 OSKextResetAfterUserspaceReboot(void)
1581 {
1582 	OSKext::resetAfterUserspaceReboot();
1583 }
1584 
1585 /*
1586  * Remove daemon exit requests from sKernelRequests
1587  *
1588  * If we sent a daemon exit request during a userspace reboot and launchd
1589  * killed the IOKit daemon before it was able to dequeue the exit request, the
1590  * next time the daemon starts up it will immediately exit as it gets the old exit request.
1591  *
1592  * This removes exit requests so that this does not happen.
1593  */
1594 void
1595 OSKext::removeDaemonExitRequests(void)
1596 {
1597 	OSDictionary * current = NULL;
1598 	OSString     * predicate = NULL;
1599 	size_t         index     = 0;
1600 	OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey);
1601 
1602 	while (index < sKernelRequests->getCount()) {
1603 		current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index));
1604 		if (current) {
1605 			predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get()));
1606 			if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) {
1607 				sKernelRequests->removeObject(index);
1608 				continue;
1609 			}
1610 		}
1611 		index++;
1612 	}
1613 }
1614 
1615 /*********************************************************************
1616 *********************************************************************/
1617 /* static */
1618 bool
1619 OSKext::getLoadEnabled(void)
1620 {
1621 	bool result;
1622 
1623 	IORecursiveLockLock(sKextLock);
1624 	result = sLoadEnabled;
1625 	IORecursiveLockUnlock(sKextLock);
1626 	return result;
1627 }
1628 
1629 /*********************************************************************
1630 *********************************************************************/
1631 /* static */
1632 bool
1633 OSKext::setLoadEnabled(bool flag)
1634 {
1635 	bool result;
1636 
1637 	IORecursiveLockLock(sKextLock);
1638 	result = sLoadEnabled;
1639 	sLoadEnabled = (flag ? true : false);
1640 
1641 	if (sLoadEnabled != result) {
1642 		OSKextLog(/* kext */ NULL,
1643 		    kOSKextLogBasicLevel |
1644 		    kOSKextLogLoadFlag,
1645 		    "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1646 	}
1647 
1648 	IORecursiveLockUnlock(sKextLock);
1649 
1650 	return result;
1651 }
1652 
1653 /*********************************************************************
1654 *********************************************************************/
1655 /* static */
1656 bool
1657 OSKext::getUnloadEnabled(void)
1658 {
1659 	bool result;
1660 
1661 	IORecursiveLockLock(sKextLock);
1662 	result = sUnloadEnabled;
1663 	IORecursiveLockUnlock(sKextLock);
1664 	return result;
1665 }
1666 
1667 /*********************************************************************
1668 *********************************************************************/
1669 /* static */
1670 bool
1671 OSKext::setUnloadEnabled(bool flag)
1672 {
1673 	bool result;
1674 
1675 	IORecursiveLockLock(sKextLock);
1676 	result = sUnloadEnabled;
1677 	sUnloadEnabled = (flag ? true : false);
1678 	IORecursiveLockUnlock(sKextLock);
1679 
1680 	if (sUnloadEnabled != result) {
1681 		OSKextLog(/* kext */ NULL,
1682 		    kOSKextLogBasicLevel |
1683 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1684 		    "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1685 	}
1686 
1687 	return result;
1688 }
1689 
1690 /*********************************************************************
1691 * Do not call any function that takes sKextLock here!
1692 *********************************************************************/
1693 /* static */
1694 bool
1695 OSKext::getAutounloadEnabled(void)
1696 {
1697 #if XNU_TARGET_OS_OSX
1698 	bool result;
1699 
1700 	IORecursiveLockLock(sKextInnerLock);
1701 	result = sAutounloadEnabled ? true : false;
1702 	IORecursiveLockUnlock(sKextInnerLock);
1703 	return result;
1704 #else
1705 	return false;
1706 #endif /* XNU_TARGET_OS_OSX */
1707 }
1708 
1709 /*********************************************************************
1710 * Do not call any function that takes sKextLock here!
1711 *********************************************************************/
1712 /* static */
1713 bool
1714 OSKext::setAutounloadsEnabled(bool flag)
1715 {
1716 #if XNU_TARGET_OS_OSX
1717 	bool result;
1718 
1719 	IORecursiveLockLock(sKextInnerLock);
1720 
1721 	result = sAutounloadEnabled;
1722 	sAutounloadEnabled = (flag ? true : false);
1723 	if (!sAutounloadEnabled && sUnloadCallout) {
1724 		thread_call_cancel(sUnloadCallout);
1725 	}
1726 
1727 	if (sAutounloadEnabled != result) {
1728 		OSKextLog(/* kext */ NULL,
1729 		    kOSKextLogBasicLevel |
1730 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1731 		    "Kext autounloading now %sabled.",
1732 		    sAutounloadEnabled ? "en" : "dis");
1733 	}
1734 
1735 	IORecursiveLockUnlock(sKextInnerLock);
1736 
1737 	return result;
1738 #else
1739 	(void)flag;
1740 	return false;
1741 #endif /* XNU_TARGET_OS_OSX */
1742 }
1743 
1744 /*********************************************************************
1745 *********************************************************************/
1746 /* instance method operating on OSKext field */
1747 bool
1748 OSKext::setAutounloadEnabled(bool flag)
1749 {
1750 	bool result = flags.autounloadEnabled ? true : false;
1751 	flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0;
1752 
1753 	if (result != (flag ? true : false)) {
1754 		OSKextLog(this,
1755 		    kOSKextLogProgressLevel |
1756 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1757 		    "Autounloading for kext %s now %sabled.",
1758 		    getIdentifierCString(),
1759 		    flags.autounloadEnabled ? "en" : "dis");
1760 	}
1761 	return result;
1762 }
1763 
1764 /*********************************************************************
1765 *********************************************************************/
1766 /* static */
1767 bool
1768 OSKext::setKernelRequestsEnabled(bool flag)
1769 {
1770 	bool result;
1771 
1772 	IORecursiveLockLock(sKextLock);
1773 	result = sKernelRequestsEnabled;
1774 	sKernelRequestsEnabled = flag ? true : false;
1775 
1776 	if (sKernelRequestsEnabled != result) {
1777 		OSKextLog(/* kext */ NULL,
1778 		    kOSKextLogBasicLevel |
1779 		    kOSKextLogGeneralFlag,
1780 		    "Kernel requests now %sabled.",
1781 		    sKernelRequestsEnabled ? "en" : "dis");
1782 	}
1783 	IORecursiveLockUnlock(sKextLock);
1784 	return result;
1785 }
1786 
1787 /*********************************************************************
1788 *********************************************************************/
1789 /* static */
1790 bool
1791 OSKext::getKernelRequestsEnabled(void)
1792 {
1793 	bool result;
1794 
1795 	IORecursiveLockLock(sKextLock);
1796 	result = sKernelRequestsEnabled;
1797 	IORecursiveLockUnlock(sKextLock);
1798 	return result;
1799 }
1800 
1801 static bool
1802 segmentIsMutable(kernel_segment_command_t *seg)
1803 {
1804 	/* Mutable segments have to have VM_PROT_WRITE */
1805 	if ((seg->maxprot & VM_PROT_WRITE) == 0) {
1806 		return false;
1807 	}
1808 	/* Exclude the __DATA_CONST segment */
1809 	if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) {
1810 		return false;
1811 	}
1812 	/* Exclude __LINKEDIT */
1813 	if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) {
1814 		return false;
1815 	}
1816 	return true;
1817 }
1818 
1819 #if PRAGMA_MARK
1820 #pragma mark Kext Life Cycle
1821 #endif
1822 /*********************************************************************
1823 *********************************************************************/
1824 OSSharedPtr<OSKext>
1825 OSKext::withPrelinkedInfoDict(
1826 	OSDictionary * anInfoDict,
1827 	bool doCoalescedSlides,
1828 	kc_kind_t type)
1829 {
1830 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
1831 
1832 	if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) {
1833 		return NULL;
1834 	}
1835 
1836 	return newKext;
1837 }
1838 
1839 OSData *
1840 OSKext::parseDextUniqueID(
1841 	OSDictionary * anInfoDict,
1842 	const char *dextIDCS)
1843 {
1844 	OSData *ret = NULL;
1845 	OSData *data_duid = OSDynamicCast(OSData, anInfoDict->getObject(kOSBundleDextUniqueIdentifierKey));
1846 	if (data_duid != NULL) {
1847 		if (data_duid->getLength() > KOSBundleDextUniqueIdentifierMaxLength) {
1848 			OSKextLog(NULL,
1849 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
1850 			    "Dext %s DextUniqueIdentifier too long.",
1851 			    dextIDCS);
1852 		} else {
1853 			/*
1854 			 * If the DextUniqueID exists it should be
1855 			 * present also into the personalities.
1856 			 */
1857 			setDextUniqueIDInPersonalities(anInfoDict, data_duid);
1858 			ret = data_duid;
1859 		}
1860 	} else {
1861 		OSKextLog(NULL,
1862 		    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
1863 		    "Dext %s does not have a DextUniqueIdentifier",
1864 		    dextIDCS);
1865 	}
1866 	return ret;
1867 }
1868 
1869 void
1870 OSKext::setDextUniqueIDInPersonalities(
1871 	OSDictionary * anInfoDict,
1872 	OSData * dextUniqueID)
1873 {
1874 	OSDictionary * dextPersonalities = NULL;
1875 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
1876 	OSString * personalityName = NULL;
1877 
1878 	dextPersonalities = OSDynamicCast(OSDictionary,
1879 	    anInfoDict->getObject(kIOKitPersonalitiesKey));
1880 	if (!dextPersonalities || !dextPersonalities->getCount()) {
1881 		return;
1882 	}
1883 
1884 	personalitiesIterator =
1885 	    OSCollectionIterator::withCollection(dextPersonalities);
1886 	if (!personalitiesIterator) {
1887 		return;
1888 	}
1889 	while ((personalityName = OSDynamicCast(OSString,
1890 	    personalitiesIterator->getNextObject()))) {
1891 		OSDictionary * personality = OSDynamicCast(OSDictionary,
1892 		    dextPersonalities->getObject(personalityName));
1893 		if (personality) {
1894 			OSObject *duid = personality->getObject(kOSBundleDextUniqueIdentifierKey);
1895 			if (duid == NULL) {
1896 				personality->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID);
1897 			}
1898 		}
1899 	}
1900 }
1901 /*********************************************************************
1902 *********************************************************************/
1903 bool
1904 OSKext::initWithPrelinkedInfoDict(
1905 	OSDictionary * anInfoDict,
1906 	bool doCoalescedSlides,
1907 	kc_kind_t type)
1908 {
1909 	bool            result              = false;
1910 	OSString      * kextPath            = NULL;                // do not release
1911 	OSNumber      * addressNum          = NULL;                // reused; do not release
1912 	OSNumber      * lengthNum           = NULL;                // reused; do not release
1913 	OSBoolean     * scratchBool         = NULL;                // do not release
1914 	void          * data                = NULL;                // do not free
1915 	void          * srcData             = NULL;                // do not free
1916 	OSSharedPtr<OSData>        prelinkedExecutable;
1917 	uint32_t        length              = 0;                // reused
1918 	uintptr_t       kext_slide          = PE_get_kc_slide(type);
1919 	bool            shouldSaveSegments  = false;
1920 	kc_format     format                = KCFormatUnknown;
1921 
1922 	if (!super::init()) {
1923 		goto finish;
1924 	}
1925 
1926 	/* Get the path. Don't look for an arch-specific path property.
1927 	 */
1928 	kextPath = OSDynamicCast(OSString,
1929 	    anInfoDict->getObject(kPrelinkBundlePathKey));
1930 
1931 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1932 		goto finish;
1933 	}
1934 
1935 #if KASLR_KEXT_DEBUG
1936 	IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString());
1937 #endif
1938 
1939 	/* Also get the executable's bundle-relative path if present.
1940 	 * Don't look for an arch-specific path property.
1941 	 */
1942 	executableRelPath.reset(OSDynamicCast(OSString,
1943 	    anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain);
1944 	userExecutableRelPath.reset(OSDynamicCast(OSString,
1945 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
1946 
1947 	/* Don't need the paths to be in the info dictionary any more.
1948 	 */
1949 	anInfoDict->removeObject(kPrelinkBundlePathKey);
1950 	anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1951 
1952 	scratchBool = OSDynamicCast(OSBoolean,
1953 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
1954 	if (scratchBool == kOSBooleanTrue) {
1955 		flags.requireExplicitLoad = 1;
1956 	}
1957 
1958 	/* Create an OSData wrapper around the linked executable.
1959 	 */
1960 	addressNum = OSDynamicCast(OSNumber,
1961 	    anInfoDict->getObject(kPrelinkExecutableLoadKey));
1962 	if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) {
1963 		lengthNum = OSDynamicCast(OSNumber,
1964 		    anInfoDict->getObject(kPrelinkExecutableSizeKey));
1965 		if (!lengthNum) {
1966 			OSKextLog(this,
1967 			    kOSKextLogErrorLevel |
1968 			    kOSKextLogArchiveFlag,
1969 			    "Kext %s can't find prelinked kext executable size.",
1970 			    getIdentifierCString());
1971 			return result;
1972 		}
1973 
1974 		data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1975 		length = (uint32_t) (lengthNum->unsigned32BitValue());
1976 
1977 #if KASLR_KEXT_DEBUG
1978 		IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1979 		    (unsigned long)ml_static_unslide((vm_offset_t)data),
1980 		    (unsigned long)data,
1981 		    length);
1982 #endif
1983 
1984 		anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1985 		anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1986 
1987 		/* If the kext's load address differs from its source address, allocate
1988 		 * space in the kext map at the load address and copy the kext over.
1989 		 */
1990 		addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1991 		if (addressNum) {
1992 			srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1993 
1994 #if KASLR_KEXT_DEBUG
1995 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1996 			    (unsigned long)ml_static_unslide((vm_offset_t)srcData),
1997 			    (unsigned long)srcData);
1998 #endif
1999 
2000 			if (data != srcData) {
2001 #if __LP64__
2002 				kern_return_t alloc_result;
2003 
2004 				alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
2005 				if (alloc_result != KERN_SUCCESS) {
2006 					OSKextLog(this,
2007 					    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2008 					    "Failed to allocate space for prelinked kext %s.",
2009 					    getIdentifierCString());
2010 					goto finish;
2011 				}
2012 				memcpy(data, srcData, length);
2013 #else
2014 				OSKextLog(this,
2015 				    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2016 				    "Error: prelinked kext %s - source and load addresses "
2017 				    "differ on ILP32 architecture.",
2018 				    getIdentifierCString());
2019 				goto finish;
2020 #endif /* __LP64__ */
2021 			}
2022 
2023 			anInfoDict->removeObject(kPrelinkExecutableSourceKey);
2024 		}
2025 
2026 		prelinkedExecutable = OSData::withBytesNoCopy(data, length);
2027 		if (!prelinkedExecutable) {
2028 			OSKextLog(this,
2029 			    kOSKextLogErrorLevel |
2030 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
2031 			    "Kext %s failed to create executable wrapper.",
2032 			    getIdentifierCString());
2033 			goto finish;
2034 		}
2035 
2036 		/*
2037 		 * Fileset KCs are mapped as a whole by iBoot.
2038 		 * Individual kext executables should not be unmapped
2039 		 * by xnu.
2040 		 * Doing so may result in panics like rdar://85419651
2041 		 */
2042 		if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
2043 			prelinkedExecutable->setDeallocFunction(NULL);
2044 		} else { // Not from a Fileset KC
2045 #if VM_MAPPED_KEXTS
2046 			prelinkedExecutable->setDeallocFunction(osdata_kext_free);
2047 #else
2048 			prelinkedExecutable->setDeallocFunction(osdata_phys_free);
2049 #endif
2050 		}
2051 		setLinkedExecutable(prelinkedExecutable.get());
2052 		addressNum = OSDynamicCast(OSNumber,
2053 		    anInfoDict->getObject(kPrelinkKmodInfoKey));
2054 		if (!addressNum) {
2055 			OSKextLog(this,
2056 			    kOSKextLogErrorLevel |
2057 			    kOSKextLogArchiveFlag,
2058 			    "Kext %s can't find prelinked kext kmod_info address.",
2059 			    getIdentifierCString());
2060 			goto finish;
2061 		}
2062 
2063 		if (addressNum->unsigned64BitValue() != 0) {
2064 			kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
2065 			if (kmod_info->address) {
2066 				kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide);
2067 			} else {
2068 				kmod_info->address = (uintptr_t)data;
2069 				kmod_info->size = length;
2070 			}
2071 #if KASLR_KEXT_DEBUG
2072 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
2073 			    (unsigned long)((vm_offset_t)kmod_info) - kext_slide,
2074 			    (unsigned long)kmod_info);
2075 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
2076 			    (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide,
2077 			    (unsigned long)kmod_info->address);
2078  #endif
2079 		}
2080 
2081 		anInfoDict->removeObject(kPrelinkKmodInfoKey);
2082 	}
2083 
2084 	if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
2085 		uintptr_t builtinTextStart;
2086 		uintptr_t builtinTextEnd;
2087 
2088 		flags.builtin = true;
2089 		builtinKmodIdx = addressNum->unsigned32BitValue();
2090 		assert(builtinKmodIdx < gBuiltinKmodsCount);
2091 
2092 		builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
2093 		builtinTextEnd   = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
2094 
2095 		kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
2096 		kmod_info->address = builtinTextStart;
2097 		kmod_info->size    = builtinTextEnd - builtinTextStart;
2098 	}
2099 
2100 	/* If the plist has a UUID for an interface, save that off.
2101 	 */
2102 	if (isInterface()) {
2103 		interfaceUUID.reset(OSDynamicCast(OSData,
2104 		    anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain);
2105 		if (interfaceUUID) {
2106 			anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
2107 		}
2108 	}
2109 
2110 	result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides));
2111 	if (!result) {
2112 		goto finish;
2113 	}
2114 
2115 	kc_type = type;
2116 	/* Exclude builtin and codeless kexts */
2117 	if (prelinkedExecutable && kmod_info) {
2118 		switch (kc_type) {
2119 		case KCKindPrimary:
2120 			shouldSaveSegments = (
2121 				getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue ||
2122 				getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue);
2123 			if (shouldSaveSegments) {
2124 				flags.resetSegmentsFromImmutableCopy = 1;
2125 			} else {
2126 				flags.unloadUnsupported = 1;
2127 			}
2128 			break;
2129 		case KCKindPageable:
2130 			flags.resetSegmentsFromVnode = 1;
2131 			break;
2132 		case KCKindAuxiliary:
2133 			if (!pageableKCloaded) {
2134 				flags.resetSegmentsFromImmutableCopy = 1;
2135 			} else if (resetAuxKCSegmentOnUnload) {
2136 				flags.resetSegmentsFromVnode = 1;
2137 			} else {
2138 				flags.unloadUnsupported = 1;
2139 			}
2140 			break;
2141 		default:
2142 			break;
2143 		}
2144 	}
2145 
2146 	if (flags.resetSegmentsFromImmutableCopy) {
2147 		/* Save a pristine copy of the mutable segments */
2148 		kernel_segment_command_t *seg = NULL;
2149 		kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
2150 
2151 		savedMutableSegments = OSArray::withCapacity(0);
2152 
2153 		for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) {
2154 			if (!segmentIsMutable(seg)) {
2155 				continue;
2156 			}
2157 			uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
2158 			uint64_t vmsize = seg->vmsize;
2159 			OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2160 			    "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2161 			OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg);
2162 			if (!savedSegment) {
2163 				OSKextLog(this,
2164 				    kOSKextLogErrorLevel |
2165 				    kOSKextLogGeneralFlag,
2166 				    "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2167 				result = false;
2168 				goto finish;
2169 			}
2170 			savedMutableSegments->setObject(savedSegment);
2171 		}
2172 	}
2173 
2174 	if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) {
2175 		/*
2176 		 * set VM protections now, wire pages for the old style Aux KC now,
2177 		 * wire pages for the rest of the KC types at load time.
2178 		 */
2179 		result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false));
2180 		if (!result) {
2181 			goto finish;
2182 		}
2183 	}
2184 
2185 	flags.prelinked = true;
2186 
2187 	if (isDriverKit()) {
2188 		dextStatistics = OSDextStatistics::create();
2189 		dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
2190 		dextLaunchedCount = 0;
2191 	}
2192 
2193 	/* If we created a kext from prelink info,
2194 	 * we must be booting from a prelinked kernel.
2195 	 */
2196 	sPrelinkBoot = true;
2197 
2198 	result = (registerIdentifier() == kOSKextInitialized);
2199 finish:
2200 	return result;
2201 }
2202 
2203 /*********************************************************************
2204 *********************************************************************/
2205 /* static */
2206 OSSharedPtr<OSKext>
2207 OSKext::withCodelessInfo(OSDictionary * anInfoDict, OSKextInitResult *result)
2208 {
2209 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
2210 	if (!newKext) {
2211 		return NULL;
2212 	}
2213 
2214 	OSKextInitResult ret = newKext->initWithCodelessInfo(anInfoDict);
2215 	if (result != NULL) {
2216 		*result = ret;
2217 	}
2218 	if (ret != kOSKextInitialized) {
2219 		return NULL;
2220 	}
2221 
2222 	return newKext;
2223 }
2224 
2225 /*********************************************************************
2226 *********************************************************************/
2227 OSKextInitResult
2228 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict)
2229 {
2230 	OSKextInitResult result          = kOSKextInitFailure;
2231 	OSString  * kextPath             = NULL;        // do not release
2232 	OSBoolean * scratchBool          = NULL;        // do not release
2233 
2234 	if (anInfoDict == NULL || !super::init()) {
2235 		goto finish;
2236 	}
2237 
2238 	/*
2239 	 * Get the path. Don't look for an arch-specific path property.
2240 	 */
2241 	kextPath = OSDynamicCast(OSString,
2242 	    anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey));
2243 	if (!kextPath) {
2244 		OSKextLog(NULL,
2245 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2246 		    "Requested codeless kext dictionary does not contain the '%s' key",
2247 		    kKextRequestArgumentCodelessInfoBundlePathKey);
2248 		goto finish;
2249 	}
2250 
2251 	uniquePersonalityProperties(anInfoDict);
2252 
2253 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2254 		goto finish;
2255 	}
2256 
2257 	/*
2258 	 * This path is meant to initialize codeless kexts only. Refuse
2259 	 * anything that looks like it has an executable and/or declares
2260 	 * itself as a kernel component.
2261 	 */
2262 	if (declaresExecutable() || isKernelComponent()) {
2263 		OSKextLog(NULL,
2264 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2265 		    "Refusing to register codeless kext that declares an executable/kernel component: %s",
2266 		    getIdentifierCString());
2267 		goto finish;
2268 	}
2269 
2270 	if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
2271 		boolean_t updated = updateExcludeList(infoDict.get());
2272 		if (updated) {
2273 			OSKextLog(this,
2274 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2275 			    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
2276 		}
2277 	}
2278 
2279 	kc_type = KCKindNone;
2280 
2281 	scratchBool = OSDynamicCast(OSBoolean,
2282 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
2283 	if (scratchBool == kOSBooleanTrue) {
2284 		flags.requireExplicitLoad = 1;
2285 	}
2286 
2287 	/* Also get the executable's bundle-relative path if present.
2288 	 * Don't look for an arch-specific path property.
2289 	 */
2290 	userExecutableRelPath.reset(OSDynamicCast(OSString,
2291 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
2292 
2293 	/* remove unnecessary paths from the info dict */
2294 	anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey);
2295 
2296 	if (isDriverKit()) {
2297 		dextStatistics = OSDextStatistics::create();
2298 		dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
2299 		dextLaunchedCount = 0;
2300 	}
2301 
2302 	result = registerIdentifier();
2303 
2304 finish:
2305 	return result;
2306 }
2307 
2308 /*********************************************************************
2309 *********************************************************************/
2310 /* static */
2311 void
2312 OSKext::setAllVMAttributes(void)
2313 {
2314 	OSSharedPtr<OSCollectionIterator> kextIterator;
2315 	const OSSymbol * thisID                 = NULL;        // do not release
2316 
2317 	IORecursiveLockLock(sKextLock);
2318 
2319 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
2320 	if (!kextIterator) {
2321 		goto finish;
2322 	}
2323 
2324 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
2325 		OSKext *    thisKext;        // do not release
2326 
2327 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
2328 		if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
2329 			continue;
2330 		}
2331 
2332 		if (!thisKext->flags.resetSegmentsFromVnode) {
2333 			/*
2334 			 * set VM protections now, wire pages for the old style Aux KC now,
2335 			 * wire pages for the rest of the KC types at load time.
2336 			 */
2337 			thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false);
2338 		}
2339 	}
2340 
2341 finish:
2342 	IORecursiveLockUnlock(sKextLock);
2343 
2344 	return;
2345 }
2346 
2347 /*********************************************************************
2348 *********************************************************************/
2349 OSSharedPtr<OSKext>
2350 OSKext::withBooterData(
2351 	OSString * deviceTreeName,
2352 	OSData   * booterData)
2353 {
2354 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
2355 
2356 	if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
2357 		return NULL;
2358 	}
2359 
2360 	return newKext;
2361 }
2362 
2363 /*********************************************************************
2364 *********************************************************************/
2365 typedef struct _BooterKextFileInfo {
2366 	uint32_t  infoDictPhysAddr;
2367 	uint32_t  infoDictLength;
2368 	uint32_t  executablePhysAddr;
2369 	uint32_t  executableLength;
2370 	uint32_t  bundlePathPhysAddr;
2371 	uint32_t  bundlePathLength;
2372 } _BooterKextFileInfo;
2373 
2374 bool
2375 OSKext::initWithBooterData(
2376 	OSString * deviceTreeName,
2377 	OSData   * booterData)
2378 {
2379 	bool                  result         = false;
2380 	_BooterKextFileInfo * kextFileInfo   = NULL;        // do not free
2381 	char                * infoDictAddr   = NULL;        // do not free
2382 	void                * executableAddr = NULL;        // do not free
2383 	char                * bundlePathAddr = NULL;        // do not free
2384 
2385 	OSDictionary        * theInfoDict    = NULL;        // do not release
2386 	OSSharedPtr<OSObject> parsedXML;
2387 	OSSharedPtr<OSString> kextPath;
2388 
2389 	OSSharedPtr<OSString> errorString;
2390 	OSSharedPtr<OSData>   executable;
2391 
2392 	if (!super::init()) {
2393 		goto finish;
2394 	}
2395 
2396 	kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
2397 	if (!kextFileInfo) {
2398 		OSKextLog(this,
2399 		    kOSKextLogErrorLevel |
2400 		    kOSKextLogGeneralFlag,
2401 		    "No booter-provided data for kext device tree entry %s.",
2402 		    deviceTreeName->getCStringNoCopy());
2403 		goto finish;
2404 	}
2405 
2406 	/* The info plist must exist or we can't read the kext.
2407 	 */
2408 	if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
2409 		OSKextLog(this,
2410 		    kOSKextLogErrorLevel |
2411 		    kOSKextLogGeneralFlag,
2412 		    "No kext info dictionary for booter device tree entry %s.",
2413 		    deviceTreeName->getCStringNoCopy());
2414 		goto finish;
2415 	}
2416 
2417 	infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
2418 	if (!infoDictAddr) {
2419 		OSKextLog(this,
2420 		    kOSKextLogErrorLevel |
2421 		    kOSKextLogGeneralFlag,
2422 		    "Can't translate physical address 0x%x of kext info dictionary "
2423 		    "for device tree entry %s.",
2424 		    (int)kextFileInfo->infoDictPhysAddr,
2425 		    deviceTreeName->getCStringNoCopy());
2426 		goto finish;
2427 	}
2428 
2429 	parsedXML = OSUnserializeXML(infoDictAddr, errorString);
2430 	if (parsedXML) {
2431 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
2432 	}
2433 	if (!theInfoDict) {
2434 		const char * errorCString = "(unknown error)";
2435 
2436 		if (errorString && errorString->getCStringNoCopy()) {
2437 			errorCString = errorString->getCStringNoCopy();
2438 		} else if (parsedXML) {
2439 			errorCString = "not a dictionary";
2440 		}
2441 		OSKextLog(this,
2442 		    kOSKextLogErrorLevel |
2443 		    kOSKextLogGeneralFlag,
2444 		    "Error unserializing info dictionary for device tree entry %s: %s.",
2445 		    deviceTreeName->getCStringNoCopy(), errorCString);
2446 		goto finish;
2447 	}
2448 
2449 	/* A bundle path is not mandatory.
2450 	 */
2451 	if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
2452 		bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
2453 		if (!bundlePathAddr) {
2454 			OSKextLog(this,
2455 			    kOSKextLogErrorLevel |
2456 			    kOSKextLogGeneralFlag,
2457 			    "Can't translate physical address 0x%x of kext bundle path "
2458 			    "for device tree entry %s.",
2459 			    (int)kextFileInfo->bundlePathPhysAddr,
2460 			    deviceTreeName->getCStringNoCopy());
2461 			goto finish;
2462 		}
2463 		bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0';         // just in case!
2464 
2465 		kextPath = OSString::withCString(bundlePathAddr);
2466 		if (!kextPath) {
2467 			OSKextLog(this,
2468 			    kOSKextLogErrorLevel |
2469 			    kOSKextLogGeneralFlag,
2470 			    "Failed to create wrapper for device tree entry %s kext path %s.",
2471 			    deviceTreeName->getCStringNoCopy(), bundlePathAddr);
2472 			goto finish;
2473 		}
2474 	}
2475 
2476 	if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) {
2477 		goto finish;
2478 	}
2479 
2480 	/* An executable is not mandatory.
2481 	 */
2482 	if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
2483 		executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
2484 		if (!executableAddr) {
2485 			OSKextLog(this,
2486 			    kOSKextLogErrorLevel |
2487 			    kOSKextLogGeneralFlag,
2488 			    "Can't translate physical address 0x%x of kext executable "
2489 			    "for device tree entry %s.",
2490 			    (int)kextFileInfo->executablePhysAddr,
2491 			    deviceTreeName->getCStringNoCopy());
2492 			goto finish;
2493 		}
2494 
2495 		executable = OSData::withBytesNoCopy(executableAddr,
2496 		    kextFileInfo->executableLength);
2497 		if (!executable) {
2498 			OSKextLog(this,
2499 			    kOSKextLogErrorLevel |
2500 			    kOSKextLogGeneralFlag,
2501 			    "Failed to create executable wrapper for device tree entry %s.",
2502 			    deviceTreeName->getCStringNoCopy());
2503 			goto finish;
2504 		}
2505 
2506 		/* A kext with an executable needs to retain the whole booterData
2507 		 * object to keep the executable in memory.
2508 		 */
2509 		if (!setExecutable(executable.get(), booterData)) {
2510 			OSKextLog(this,
2511 			    kOSKextLogErrorLevel |
2512 			    kOSKextLogGeneralFlag,
2513 			    "Failed to set kext executable for device tree entry %s.",
2514 			    deviceTreeName->getCStringNoCopy());
2515 			goto finish;
2516 		}
2517 	}
2518 
2519 	if (isDriverKit()) {
2520 		dextStatistics = OSDextStatistics::create();
2521 		dextUniqueID.reset(parseDextUniqueID(theInfoDict, getIdentifierCString()), OSRetain);
2522 		dextLaunchedCount = 0;
2523 	}
2524 
2525 	result = (registerIdentifier() == kOSKextInitialized);
2526 
2527 finish:
2528 	return result;
2529 }
2530 
2531 /*********************************************************************
2532 *********************************************************************/
2533 OSKextInitResult
2534 OSKext::registerIdentifier(void)
2535 {
2536 	OSKextInitResult  result                  = kOSKextInitFailure;
2537 	OSKext        * existingKext              = NULL;        // do not release
2538 	bool            existingIsLoaded          = false;
2539 	bool            existingIsPrelinked       = false;
2540 	bool            existingIsCodeless        = false;
2541 	bool            existingIsDext            = false;
2542 	OSKextVersion   newVersion                = -1;
2543 	OSKextVersion   existingVersion           = -1;
2544 	char            newVersionCString[kOSKextVersionMaxLength];
2545 	char            existingVersionCString[kOSKextVersionMaxLength];
2546 	OSSharedPtr<OSData> newUUID;
2547 	OSSharedPtr<OSData> existingUUID;
2548 	const char *newDextUniqueIDCString = NULL;
2549 	const char *existingDextUniqueIDCString = NULL;
2550 	unsigned int newDextUniqueIDCStringSize = 0;
2551 	unsigned int existingDextUniqueIDCStringSize = 0;
2552 
2553 	IORecursiveLockLock(sKextLock);
2554 
2555 	/* Get the new kext's version for checks & log messages.
2556 	 */
2557 	newVersion = getVersion();
2558 	OSKextVersionGetString(newVersion, newVersionCString,
2559 	    kOSKextVersionMaxLength);
2560 
2561 	/* If we don't have an existing kext with this identifier,
2562 	 * just record the new kext and we're done!
2563 	 */
2564 	existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get()));
2565 	if (!existingKext) {
2566 		sKextsByID->setObject(bundleID.get(), this);
2567 		result = kOSKextInitialized;
2568 		goto finish;
2569 	}
2570 
2571 	/* Get the existing kext's version for checks & log messages.
2572 	 */
2573 	existingVersion = existingKext->getVersion();
2574 	OSKextVersionGetString(existingVersion,
2575 	    existingVersionCString, kOSKextVersionMaxLength);
2576 
2577 	existingIsLoaded = existingKext->isLoaded();
2578 	existingIsPrelinked = existingKext->isPrelinked();
2579 	existingIsDext = existingKext->isDriverKit();
2580 	existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext;
2581 
2582 	/*
2583 	 * Check if we are trying to upgrade a dext
2584 	 * with another dext.
2585 	 */
2586 	if (isDriverKit() && existingIsDext) {
2587 		OSData *newDextUID = getDextUniqueID();
2588 		if (!newDextUID) {
2589 			OSKextLog(this,
2590 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2591 			    "New dext %s, v%s requested does not have a unique dext identifier\n",
2592 			    getIdentifierCString(), newVersionCString);
2593 			goto finish;
2594 		}
2595 		newDextUniqueIDCString = getDextUniqueIDCString(newDextUID, &newDextUniqueIDCStringSize);
2596 		assert(newDextUniqueIDCString != NULL);
2597 
2598 		OSData *existingDextUID = existingKext->getDextUniqueID();
2599 		if (!existingDextUID) {
2600 			OSKextLog(this,
2601 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2602 			    "Found a dext %s, v%s: with no unique dext identifier\n",
2603 			    existingKext->getIdentifierCString(), existingVersionCString);
2604 			goto finish;
2605 		}
2606 		existingDextUniqueIDCString = getDextUniqueIDCString(existingDextUID, &existingDextUniqueIDCStringSize);
2607 		assert(existingDextUniqueIDCString != NULL);
2608 
2609 		/*
2610 		 * We might get multiple requests to save the same dext.
2611 		 * Check if we already have saved it or if this is an upgrade
2612 		 * for a dext with the same BundleID.
2613 		 * Dexts are uniquely identified by DextUniqueID, if a new DextUniqueID
2614 		 * is requested for a BundleID we are going to upgrade to the newest
2615 		 * received irrespective from the dext version.
2616 		 */
2617 		if (newDextUID->isEqualTo(existingDextUID) && existingKext->flags.dextToReplace == 0) {
2618 			OSKextLog(this,
2619 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2620 			    "Refusing new dext %s, v%s:"
2621 			    "a dext v %s with the same unique dext identifier (%s) already exists\n",
2622 			    getIdentifierCString(), newVersionCString,
2623 			    existingVersionCString, newDextUniqueIDCString);
2624 			result = kOSKextAlreadyExist;
2625 			goto finish;
2626 		}
2627 
2628 		bool upgraded = upgradeDext(existingKext, this);
2629 		if (upgraded) {
2630 			/* If the dext was upgraded existingKext might have been deallocated */
2631 			existingKext = NULL;
2632 			OSKextLog(this,
2633 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2634 			    "Dext %s, v%s , unique dext identifier %s "
2635 			    "Upgraded to v%s, unique dext identifier %s \n",
2636 			    getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
2637 			    newVersionCString, newDextUniqueIDCString);
2638 			result = kOSKextInitialized;
2639 		} else {
2640 			OSKextLog(this,
2641 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2642 			    "Upgrade delayed for %s v%s, unique dext identifier %s "
2643 			    "with v%s, unique dext identifier %s.\n",
2644 			    getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
2645 			    newVersionCString, newDextUniqueIDCString);
2646 			result = kOSKextAlreadyExist;
2647 		}
2648 
2649 		goto finish;
2650 	}
2651 
2652 	/* If we have a non-codeless kext with this identifier that's already
2653 	 * loaded/prelinked, we can't use the new one, but let's be really
2654 	 * thorough and check how the two are related for a precise diagnostic
2655 	 * log message.
2656 	 *
2657 	 * This check is valid for kexts that declare an executable and for
2658 	 * dexts, but not for codeless kexts - we can just replace those.
2659 	 */
2660 	if ((!existingIsCodeless || existingIsDext) &&
2661 	    (existingIsLoaded || existingIsPrelinked)) {
2662 		bool sameVersion = (newVersion == existingVersion);
2663 		bool sameExecutable = true;         // assume true unless we have UUIDs
2664 
2665 		/* Only get the UUID if the existing kext is loaded. Doing so
2666 		 * might have to uncompress an mkext executable and we shouldn't
2667 		 * take that hit when neither kext is loaded.
2668 		 *
2669 		 * Note: there is no decompression that happens when all kexts
2670 		 * are loaded from kext collecitons.
2671 		 */
2672 		newUUID = copyUUID();
2673 		existingUUID = existingKext->copyUUID();
2674 
2675 		if (existingIsDext && !isDriverKit()) {
2676 			OSKextLog(this,
2677 			    kOSKextLogWarningLevel |
2678 			    kOSKextLogKextBookkeepingFlag,
2679 			    "Notice - new kext %s, v%s matches a %s dext"
2680 			    "with the same bundle ID, v%s.",
2681 			    getIdentifierCString(), newVersionCString,
2682 			    (existingIsLoaded ? "loaded" : "prelinked"),
2683 			    existingVersionCString);
2684 			goto finish;
2685 		}
2686 
2687 		/* I'm entirely too paranoid about checking equivalence of executables,
2688 		 * but I remember nasty problems with it in the past.
2689 		 *
2690 		 * - If we have UUIDs for both kexts, compare them.
2691 		 * - If only one kext has a UUID, they're definitely different.
2692 		 */
2693 		if (newUUID && existingUUID) {
2694 			sameExecutable = newUUID->isEqualTo(existingUUID.get());
2695 		} else if (newUUID || existingUUID) {
2696 			sameExecutable = false;
2697 		}
2698 
2699 		if (!newUUID && !existingUUID) {
2700 			/* If there are no UUIDs, we can't really tell that the executables
2701 			 * are *different* without a lot of work; the loaded kext's
2702 			 * unrelocated executable is no longer around (and we never had it
2703 			 * in-kernel for a prelinked kext). We certainly don't want to do
2704 			 * a whole fake link for the new kext just to compare, either.
2705 			 */
2706 			OSKextLog(this,
2707 			    kOSKextLogWarningLevel |
2708 			    kOSKextLogKextBookkeepingFlag,
2709 			    "Notice - new kext %s, v%s matches %s kext "
2710 			    "but can't determine if executables are the same (no UUIDs).",
2711 			    getIdentifierCString(),
2712 			    newVersionCString,
2713 			    (existingIsLoaded ? "loaded" : "prelinked"));
2714 		}
2715 
2716 		if (sameVersion && sameExecutable) {
2717 			OSKextLog(this,
2718 			    (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2719 			    kOSKextLogKextBookkeepingFlag,
2720 			    "Refusing new kext %s, v%s: a %s copy is already present "
2721 			    "(same version and executable).",
2722 			    getIdentifierCString(), newVersionCString,
2723 			    (existingIsLoaded ? "loaded" : "prelinked"));
2724 		} else {
2725 			if (!sameVersion) {
2726 				/* This condition is significant so log it under warnings.
2727 				 */
2728 				OSKextLog(this,
2729 				    kOSKextLogWarningLevel |
2730 				    kOSKextLogKextBookkeepingFlag,
2731 				    "Refusing new kext %s, v%s: already have %s v%s.",
2732 				    getIdentifierCString(),
2733 				    newVersionCString,
2734 				    (existingIsLoaded ? "loaded" : "prelinked"),
2735 				    existingVersionCString);
2736 			} else {
2737 				/* This condition is significant so log it under warnings.
2738 				 */
2739 				OSKextLog(this,
2740 				    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2741 				    "Refusing new kext %s, v%s: a %s copy with a different "
2742 				    "executable UUID is already present.",
2743 				    getIdentifierCString(), newVersionCString,
2744 				    (existingIsLoaded ? "loaded" : "prelinked"));
2745 			}
2746 		}
2747 		goto finish;
2748 	} /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */
2749 
2750 	/* Refuse to allow an existing loaded codeless kext be replaced by a
2751 	 * normal kext with the same bundle ID.
2752 	 */
2753 	if (existingIsCodeless && declaresExecutable()) {
2754 		OSKextLog(this,
2755 		    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2756 		    "Refusing new kext %s, v%s: a codeless copy is already %s",
2757 		    getIdentifierCString(), newVersionCString,
2758 		    (existingIsLoaded ? "loaded" : "prelinked"));
2759 		goto finish;
2760 	}
2761 
2762 	/* Dexts packaged in the BootKC will be protected against replacement
2763 	 * by non-dexts by the logic above which checks if they are prelinked.
2764 	 * Dexts which are prelinked into the System KC will be registered
2765 	 * before any other kexts in the AuxKC are registered, and we never
2766 	 * put dexts in the AuxKC. Therefore, there is no need to check if an
2767 	 * existing object is a dext and is being replaced by a non-dext.
2768 	 * The scenario cannot happen by construction.
2769 	 *
2770 	 * See: OSKext::loadFileSetKexts()
2771 	 */
2772 
2773 
2774 	/* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2775 	 * user loads are happening or if we're still in early boot. User agents are
2776 	 * supposed to resolve dependencies topside and include only the exact
2777 	 * kexts needed; so we always accept the new kext (in fact we should never
2778 	 * see an older unloaded copy hanging around).
2779 	 */
2780 	if (sUserLoadsActive) {
2781 		sKextsByID->setObject(bundleID.get(), this);
2782 		result = kOSKextInitialized;
2783 
2784 		OSKextLog(this,
2785 		    kOSKextLogStepLevel |
2786 		    kOSKextLogKextBookkeepingFlag,
2787 		    "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2788 		    getIdentifierCString(),
2789 		    existingVersionCString,
2790 		    newVersionCString);
2791 
2792 		goto finish;
2793 	}
2794 
2795 	/* During early boot, the kext with the highest version always wins out.
2796 	 * Prelinked kernels will never hit this, but mkexts and booter-read
2797 	 * kexts might have duplicates.
2798 	 */
2799 	if (newVersion > existingVersion) {
2800 		sKextsByID->setObject(bundleID.get(), this);
2801 		result = kOSKextInitialized;
2802 
2803 		OSKextLog(this,
2804 		    kOSKextLogStepLevel |
2805 		    kOSKextLogKextBookkeepingFlag,
2806 		    "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2807 		    existingVersionCString,
2808 		    getIdentifierCString(),
2809 		    newVersionCString);
2810 	} else {
2811 		OSKextLog(this,
2812 		    kOSKextLogStepLevel |
2813 		    kOSKextLogKextBookkeepingFlag,
2814 		    "Kext %s is already registered with a higher/same version (v%s); "
2815 		    "dropping newly-added (v%s).",
2816 		    getIdentifierCString(),
2817 		    existingVersionCString,
2818 		    newVersionCString);
2819 	}
2820 
2821 	/* result has been set appropriately by now. */
2822 
2823 finish:
2824 
2825 	IORecursiveLockUnlock(sKextLock);
2826 
2827 	if (newDextUniqueIDCString != NULL) {
2828 		kfree_data(newDextUniqueIDCString, newDextUniqueIDCStringSize);
2829 	}
2830 	if (existingDextUniqueIDCString != NULL) {
2831 		kfree_data(existingDextUniqueIDCString, existingDextUniqueIDCStringSize);
2832 	}
2833 
2834 	if (result == kOSKextInitialized) {
2835 		OSKextLog(this,
2836 		    kOSKextLogStepLevel |
2837 		    kOSKextLogKextBookkeepingFlag,
2838 		    "Kext %s, v%s registered and available for loading.",
2839 		    getIdentifierCString(), newVersionCString);
2840 	}
2841 
2842 	return result;
2843 }
2844 
2845 /*********************************************************************
2846  * Does the bare minimum validation to look up a kext.
2847  * All other validation is done on the spot as needed.
2848  **********************************************************************/
2849 bool
2850 OSKext::setInfoDictionaryAndPath(
2851 	OSDictionary * aDictionary,
2852 	OSString     * aPath)
2853 {
2854 	bool           result                   = false;
2855 	OSString     * bundleIDString           = NULL;        // do not release
2856 	OSString     * versionString            = NULL;        // do not release
2857 	OSString     * compatibleVersionString  = NULL;        // do not release
2858 	const char   * versionCString           = NULL;        // do not free
2859 	const char   * compatibleVersionCString = NULL;        // do not free
2860 	OSBoolean    * scratchBool              = NULL;        // do not release
2861 	OSDictionary * scratchDict              = NULL;        // do not release
2862 
2863 	if (infoDict) {
2864 		panic("Attempt to set info dictionary on a kext "
2865 		    "that already has one (%s).",
2866 		    getIdentifierCString());
2867 	}
2868 
2869 	if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
2870 		goto finish;
2871 	}
2872 
2873 	infoDict.reset(aDictionary, OSRetain);
2874 
2875 	/* Check right away if the info dictionary has any log flags.
2876 	 */
2877 	scratchBool = OSDynamicCast(OSBoolean,
2878 	    getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
2879 	if (scratchBool == kOSBooleanTrue) {
2880 		flags.loggingEnabled = 1;
2881 	}
2882 
2883 	/* The very next thing to get is the bundle identifier. Unlike
2884 	 * in user space, a kext with no bundle identifier gets axed
2885 	 * immediately.
2886 	 */
2887 	bundleIDString = OSDynamicCast(OSString,
2888 	    getPropertyForHostArch(kCFBundleIdentifierKey));
2889 	if (!bundleIDString) {
2890 		OSKextLog(this,
2891 		    kOSKextLogErrorLevel |
2892 		    kOSKextLogValidationFlag,
2893 		    "CFBundleIdentifier missing/invalid type in kext %s.",
2894 		    aPath ? aPath->getCStringNoCopy() : "(unknown)");
2895 		goto finish;
2896 	}
2897 	bundleID = OSSymbol::withString(bundleIDString);
2898 	if (!bundleID) {
2899 		OSKextLog(this,
2900 		    kOSKextLogErrorLevel |
2901 		    kOSKextLogValidationFlag,
2902 		    "Can't copy bundle identifier as symbol for kext %s.",
2903 		    bundleIDString->getCStringNoCopy());
2904 		goto finish;
2905 	}
2906 
2907 	/* Save the path if we got one (it should always be available but it's
2908 	 * just something nice to have for bookkeeping).
2909 	 */
2910 	if (aPath) {
2911 		path.reset(aPath, OSRetain);
2912 	}
2913 
2914 	/*****
2915 	 * Minimal validation to initialize. We'll do other validation on the spot.
2916 	 */
2917 	if (bundleID->getLength() >= KMOD_MAX_NAME) {
2918 		OSKextLog(this,
2919 		    kOSKextLogErrorLevel |
2920 		    kOSKextLogValidationFlag,
2921 		    "Kext %s error - CFBundleIdentifier over max length %d.",
2922 		    getIdentifierCString(), KMOD_MAX_NAME - 1);
2923 		goto finish;
2924 	}
2925 
2926 	version = compatibleVersion = -1;
2927 
2928 	versionString = OSDynamicCast(OSString,
2929 	    getPropertyForHostArch(kCFBundleVersionKey));
2930 	if (!versionString) {
2931 		OSKextLog(this,
2932 		    kOSKextLogErrorLevel |
2933 		    kOSKextLogValidationFlag,
2934 		    "Kext %s error - CFBundleVersion missing/invalid type.",
2935 		    getIdentifierCString());
2936 		goto finish;
2937 	}
2938 	versionCString = versionString->getCStringNoCopy();
2939 	version = OSKextParseVersionString(versionCString);
2940 	if (version < 0) {
2941 		OSKextLog(this,
2942 		    kOSKextLogErrorLevel |
2943 		    kOSKextLogValidationFlag,
2944 		    "Kext %s error - CFBundleVersion bad value '%s'.",
2945 		    getIdentifierCString(), versionCString);
2946 		goto finish;
2947 	}
2948 
2949 	compatibleVersion = -1;         // set to illegal value for kexts that don't have
2950 
2951 	compatibleVersionString = OSDynamicCast(OSString,
2952 	    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2953 	if (compatibleVersionString) {
2954 		compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2955 		compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2956 		if (compatibleVersion < 0) {
2957 			OSKextLog(this,
2958 			    kOSKextLogErrorLevel |
2959 			    kOSKextLogValidationFlag,
2960 			    "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2961 			    getIdentifierCString(), compatibleVersionCString);
2962 			goto finish;
2963 		}
2964 
2965 		if (compatibleVersion > version) {
2966 			OSKextLog(this,
2967 			    kOSKextLogErrorLevel |
2968 			    kOSKextLogValidationFlag,
2969 			    "Kext %s error - %s %s > %s %s (must be <=).",
2970 			    getIdentifierCString(),
2971 			    kOSBundleCompatibleVersionKey, compatibleVersionCString,
2972 			    kCFBundleVersionKey, versionCString);
2973 			goto finish;
2974 		}
2975 	}
2976 
2977 	/* Check to see if this kext is in exclude list */
2978 	if (isInExcludeList()) {
2979 		OSKextLog(this,
2980 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2981 		    "Kext %s is in exclude list, not loadable",
2982 		    getIdentifierCString());
2983 		goto finish;
2984 	}
2985 
2986 	/* Set flags for later use if the infoDict gets flushed. We only
2987 	 * check for true values, not false ones(!)
2988 	 */
2989 	scratchBool = OSDynamicCast(OSBoolean,
2990 	    getPropertyForHostArch(kOSBundleIsInterfaceKey));
2991 	if (scratchBool == kOSBooleanTrue) {
2992 		flags.interface = 1;
2993 	}
2994 
2995 	scratchBool = OSDynamicCast(OSBoolean,
2996 	    getPropertyForHostArch(kOSKernelResourceKey));
2997 	if (scratchBool == kOSBooleanTrue) {
2998 		flags.kernelComponent = 1;
2999 		flags.interface = 1;         // xxx - hm. the kernel itself isn't an interface...
3000 		flags.started = 1;
3001 
3002 		/* A kernel component has one implicit dependency on the kernel.
3003 		 */
3004 		flags.hasAllDependencies = 1;
3005 	}
3006 
3007 	/* Make sure common string values in personalities are uniqued to OSSymbols.
3008 	 */
3009 	scratchDict = OSDynamicCast(OSDictionary,
3010 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
3011 	if (scratchDict) {
3012 		uniquePersonalityProperties(scratchDict);
3013 	}
3014 
3015 	result = true;
3016 
3017 finish:
3018 
3019 	return result;
3020 }
3021 
3022 /*********************************************************************
3023 * Not used for prelinked kernel boot as there is no unrelocated
3024 * executable.
3025 *********************************************************************/
3026 bool
3027 OSKext::setExecutable(
3028 	OSData * anExecutable,
3029 	OSData * externalData,
3030 	bool     externalDataIsMkext)
3031 {
3032 	bool         result        = false;
3033 	const char * executableKey = NULL;         // do not free
3034 
3035 	if (!anExecutable) {
3036 		infoDict->removeObject(_kOSKextExecutableKey);
3037 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
3038 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
3039 		result = true;
3040 		goto finish;
3041 	}
3042 
3043 	if (infoDict->getObject(_kOSKextExecutableKey) ||
3044 	    infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
3045 		panic("Attempt to set an executable on a kext "
3046 		    "that already has one (%s).",
3047 		    getIdentifierCString());
3048 		goto finish;
3049 	}
3050 
3051 	if (externalDataIsMkext) {
3052 		executableKey = _kOSKextMkextExecutableReferenceKey;
3053 	} else {
3054 		executableKey = _kOSKextExecutableKey;
3055 	}
3056 
3057 	if (anExecutable) {
3058 		infoDict->setObject(executableKey, anExecutable);
3059 		if (externalData) {
3060 			infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
3061 		}
3062 	}
3063 
3064 	result = true;
3065 
3066 finish:
3067 	return result;
3068 }
3069 
3070 /*********************************************************************
3071 *********************************************************************/
3072 static void
3073 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
3074 {
3075 	OSObject       * value       = NULL;        // do not release
3076 	OSString       * stringValue = NULL;        // do not release
3077 	OSSharedPtr<const OSSymbol> symbolValue;
3078 
3079 	value = dict->getObject(key);
3080 	if (!value) {
3081 		goto finish;
3082 	}
3083 	if (OSDynamicCast(OSSymbol, value)) {
3084 		/* this is already an OSSymbol: we're good */
3085 		goto finish;
3086 	}
3087 
3088 	stringValue = OSDynamicCast(OSString, value);
3089 	if (!stringValue) {
3090 		goto finish;
3091 	}
3092 
3093 	symbolValue = OSSymbol::withString(stringValue);
3094 	if (!symbolValue) {
3095 		goto finish;
3096 	}
3097 
3098 	dict->setObject(key, symbolValue.get());
3099 
3100 finish:
3101 	return;
3102 }
3103 
3104 /*********************************************************************
3105 *********************************************************************/
3106 static void
3107 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
3108 {
3109 	OSObject       * value       = NULL;        // do not release
3110 	OSString       * stringValue = NULL;        // do not release
3111 	OSSharedPtr<const OSSymbol> symbolValue;
3112 
3113 	value = dict->getObject(key);
3114 	if (!value) {
3115 		goto finish;
3116 	}
3117 	if (OSDynamicCast(OSSymbol, value)) {
3118 		/* this is already an OSSymbol: we're good */
3119 		goto finish;
3120 	}
3121 
3122 	stringValue = OSDynamicCast(OSString, value);
3123 	if (!stringValue) {
3124 		goto finish;
3125 	}
3126 
3127 	symbolValue = OSSymbol::withString(stringValue);
3128 	if (!symbolValue) {
3129 		goto finish;
3130 	}
3131 
3132 	dict->setObject(key, symbolValue.get());
3133 
3134 finish:
3135 	return;
3136 }
3137 
3138 void
3139 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
3140 {
3141 	OSKext::uniquePersonalityProperties(personalityDict, true);
3142 }
3143 
3144 /*********************************************************************
3145 * Replace common personality property values with uniqued instances
3146 * to save on wired memory.
3147 *********************************************************************/
3148 /* static */
3149 void
3150 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier)
3151 {
3152 	/* Properties every personality has.
3153 	 */
3154 	uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
3155 	uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
3156 	uniqueStringPlistProperty(personalityDict, gIOClassKey.get());
3157 	if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
3158 		uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
3159 	} else if (defaultAddKernelBundleIdentifier) {
3160 		personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
3161 	}
3162 
3163 	/* Other commonly used properties.
3164 	 */
3165 	uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
3166 	uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
3167 	uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
3168 
3169 	uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
3170 	uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
3171 	uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
3172 	uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
3173 	uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
3174 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
3175 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
3176 	uniqueStringPlistProperty(personalityDict, "Vendor");
3177 	uniqueStringPlistProperty(personalityDict, "Vendor Identification");
3178 	uniqueStringPlistProperty(personalityDict, "Vendor Name");
3179 	uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
3180 	uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
3181 	uniqueStringPlistProperty(personalityDict, "idProduct");
3182 
3183 	return;
3184 }
3185 
3186 /*********************************************************************
3187 *********************************************************************/
3188 void
3189 OSKext::free(void)
3190 {
3191 	if (isLoaded()) {
3192 		panic("Attempt to free loaded kext %s.", getIdentifierCString());
3193 	}
3194 
3195 	if (isDriverKit()) {
3196 		if (dextLaunchedCount > 0) {
3197 			panic("Freeing dext %s but dextLaunchedCount is %d\n", getIdentifierCString(), dextLaunchedCount);
3198 		}
3199 	}
3200 
3201 	infoDict.reset();
3202 	bundleID.reset();
3203 	path.reset();
3204 	executableRelPath.reset();
3205 	userExecutableRelPath.reset();
3206 	dependencies.reset();
3207 	linkedExecutable.reset();
3208 	metaClasses.reset();
3209 	interfaceUUID.reset();
3210 	driverKitUUID.reset();
3211 	dextStatistics.reset();
3212 	dextUniqueID.reset();
3213 
3214 	if (isInterface() && kmod_info) {
3215 		kfree_type(kmod_info_t, kmod_info);
3216 	}
3217 
3218 	super::free();
3219 	return;
3220 }
3221 
3222 #if PRAGMA_MARK
3223 #pragma mark Mkext files
3224 #endif
3225 
3226 #if CONFIG_KXLD
3227 /*
3228  * mkext archives are really only relevant on kxld-enabled kernels.
3229  * Without a dynamic kernel linker, we don't need to support any mkexts.
3230  */
3231 
3232 /*********************************************************************
3233 *********************************************************************/
3234 OSReturn
3235 OSKext::readMkextArchive(OSData * mkextData,
3236     uint32_t * checksumPtr)
3237 {
3238 	OSReturn       result       = kOSKextReturnBadData;
3239 	uint32_t       mkextLength  = 0;
3240 	mkext_header * mkextHeader  = NULL;        // do not free
3241 	uint32_t       mkextVersion = 0;
3242 
3243 	/* Note default return of kOSKextReturnBadData above.
3244 	 */
3245 	mkextLength = mkextData->getLength();
3246 	if (mkextLength < sizeof(mkext_basic_header)) {
3247 		OSKextLog(/* kext */ NULL,
3248 		    kOSKextLogErrorLevel |
3249 		    kOSKextLogArchiveFlag,
3250 		    "Mkext archive too small to be valid.");
3251 		goto finish;
3252 	}
3253 
3254 	mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
3255 
3256 	if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
3257 	    MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
3258 		OSKextLog(/* kext */ NULL,
3259 		    kOSKextLogErrorLevel |
3260 		    kOSKextLogArchiveFlag,
3261 		    "Mkext archive has invalid magic or signature.");
3262 		goto finish;
3263 	}
3264 
3265 	if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
3266 		OSKextLog(/* kext */ NULL,
3267 		    kOSKextLogErrorLevel |
3268 		    kOSKextLogArchiveFlag,
3269 		    "Mkext archive recorded length doesn't match actual file length.");
3270 		goto finish;
3271 	}
3272 
3273 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3274 
3275 	if (mkextVersion == MKEXT_VERS_2) {
3276 		result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
3277 	} else {
3278 		OSKextLog(/* kext */ NULL,
3279 		    kOSKextLogErrorLevel |
3280 		    kOSKextLogArchiveFlag,
3281 		    "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
3282 		result = kOSKextReturnUnsupported;
3283 	}
3284 
3285 finish:
3286 	return result;
3287 }
3288 
3289 /*********************************************************************
3290 * Assumes magic, signature, version, length have been checked.
3291 * xxx - need to add further bounds checking for each file entry
3292 *
3293 * Should keep track of all kexts created so far, and if we hit a
3294 * fatal error halfway through, remove those kexts. If we've dropped
3295 * an older version that had already been read, whoops! Might want to
3296 * add a level of buffering?
3297 *********************************************************************/
3298 /* static */
3299 OSReturn
3300 OSKext::readMkext2Archive(
3301 	OSData        * mkextData,
3302 	OSDictionary ** mkextPlistOut,
3303 	uint32_t      * checksumPtr)
3304 {
3305 	OSReturn        result                     = kOSReturnError;
3306 	uint32_t        mkextLength;
3307 	mkext2_header * mkextHeader                = NULL;        // do not free
3308 	void          * mkextEnd                   = NULL;        // do not free
3309 	uint32_t        mkextVersion;
3310 	uint8_t       * crc_address                = NULL;
3311 	size_t          crc_buffer_size            = 0;
3312 	uint32_t        checksum;
3313 	uint32_t        mkextPlistOffset;
3314 	uint32_t        mkextPlistCompressedSize;
3315 	char          * mkextPlistEnd              = NULL;        // do not free
3316 	uint32_t        mkextPlistFullSize;
3317 	OSSharedPtr<OSString>     errorString;
3318 	OSSharedPtr<OSData>       mkextPlistUncompressedData;
3319 	const char    * mkextPlistDataBuffer       = NULL;        // do not free
3320 	OSSharedPtr<OSObject>      parsedXML;
3321 	OSDictionary  * mkextPlist                 = NULL;        // do not release
3322 	OSArray       * mkextInfoDictArray         = NULL;        // do not release
3323 	uint32_t        count, i;
3324 	kc_format_t kc_format;
3325 
3326 	if (!PE_get_primary_kc_format(&kc_format)) {
3327 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3328 		    "Unable to determine primary KC format");
3329 		goto finish;
3330 	}
3331 
3332 	mkextLength = mkextData->getLength();
3333 	mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
3334 	mkextEnd = (char *)mkextHeader + mkextLength;
3335 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3336 
3337 	crc_address = (u_int8_t *)&mkextHeader->version;
3338 	crc_buffer_size = (uintptr_t)mkextHeader +
3339 	    MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address;
3340 	if (crc_buffer_size > INT32_MAX) {
3341 		OSKextLog(/* kext */ NULL,
3342 		    kOSKextLogErrorLevel |
3343 		    kOSKextLogArchiveFlag,
3344 		    "Mkext archive size is too large (%lu > INT32_MAX).",
3345 		    crc_buffer_size);
3346 		result = kOSKextReturnBadData;
3347 		goto finish;
3348 	}
3349 	checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size);
3350 
3351 	if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
3352 		OSKextLog(/* kext */ NULL,
3353 		    kOSKextLogErrorLevel |
3354 		    kOSKextLogArchiveFlag,
3355 		    "Mkext archive has bad checksum.");
3356 		result = kOSKextReturnBadData;
3357 		goto finish;
3358 	}
3359 
3360 	if (checksumPtr) {
3361 		*checksumPtr = checksum;
3362 	}
3363 
3364 	/* Check that the CPU type & subtype match that of the running kernel. */
3365 	if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
3366 		OSKextLog(/* kext */ NULL,
3367 		    kOSKextLogErrorLevel |
3368 		    kOSKextLogArchiveFlag,
3369 		    "Mkext archive must have a specific CPU type.");
3370 		result = kOSKextReturnBadData;
3371 		goto finish;
3372 	} else {
3373 		if ((UInt32)_mh_execute_header.cputype !=
3374 		    MKEXT_GET_CPUTYPE(mkextHeader)) {
3375 			OSKextLog(/* kext */ NULL,
3376 			    kOSKextLogErrorLevel |
3377 			    kOSKextLogArchiveFlag,
3378 			    "Mkext archive does not match the running kernel's CPU type.");
3379 			result = kOSKextReturnArchNotFound;
3380 			goto finish;
3381 		}
3382 	}
3383 
3384 	mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
3385 	mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
3386 	mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
3387 	    mkextPlistCompressedSize;
3388 	if (mkextPlistEnd > mkextEnd) {
3389 		OSKextLog(/* kext */ NULL,
3390 		    kOSKextLogErrorLevel |
3391 		    kOSKextLogArchiveFlag,
3392 		    "Mkext archive file overrun.");
3393 		result = kOSKextReturnBadData;
3394 	}
3395 
3396 	mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
3397 	if (mkextPlistCompressedSize) {
3398 		mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
3399 			(UInt8 *)mkextHeader + mkextPlistOffset,
3400 			"plist",
3401 			mkextPlistCompressedSize, mkextPlistFullSize);
3402 		if (!mkextPlistUncompressedData) {
3403 			goto finish;
3404 		}
3405 		mkextPlistDataBuffer = (const char *)
3406 		    mkextPlistUncompressedData->getBytesNoCopy();
3407 	} else {
3408 		mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
3409 	}
3410 
3411 	/* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
3412 	 */
3413 	parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString);
3414 	if (parsedXML) {
3415 		mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get());
3416 	}
3417 	if (!mkextPlist) {
3418 		const char * errorCString = "(unknown error)";
3419 
3420 		if (errorString && errorString->getCStringNoCopy()) {
3421 			errorCString = errorString->getCStringNoCopy();
3422 		} else if (parsedXML) {
3423 			errorCString = "not a dictionary";
3424 		}
3425 		OSKextLog(/* kext */ NULL,
3426 		    kOSKextLogErrorLevel |
3427 		    kOSKextLogArchiveFlag,
3428 		    "Error unserializing mkext plist: %s.", errorCString);
3429 		goto finish;
3430 	}
3431 
3432 	mkextInfoDictArray = OSDynamicCast(OSArray,
3433 	    mkextPlist->getObject(kMKEXTInfoDictionariesKey));
3434 	if (!mkextInfoDictArray) {
3435 		OSKextLog(/* kext */ NULL,
3436 		    kOSKextLogErrorLevel |
3437 		    kOSKextLogArchiveFlag,
3438 		    "Mkext archive contains no kext info dictionaries.");
3439 		goto finish;
3440 	}
3441 
3442 	count = mkextInfoDictArray->getCount();
3443 	for (i = 0; i < count; i++) {
3444 		OSDictionary * infoDict;
3445 
3446 
3447 		infoDict = OSDynamicCast(OSDictionary,
3448 		    mkextInfoDictArray->getObject(i));
3449 
3450 		/* Create the kext for the entry, then release it, because the
3451 		 * kext system keeps them around until explicitly removed.
3452 		 * Any creation/registration failures are already logged for us.
3453 		 */
3454 		if (infoDict) {
3455 			OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData);
3456 
3457 			/* Fail dynamic loading of a kext when booted from MH_FILESET */
3458 			if (kc_format == KCFormatFileset &&
3459 			    newKext &&
3460 			    !(newKext->isPrelinked()) &&
3461 			    newKext->declaresExecutable()) {
3462 				result = kOSReturnError;
3463 				printf("Kext LOG: Dynamic loading of kext denied for kext %s\n",
3464 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3465 
3466 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
3467 				    "Dynamic loading of kext denied for kext %s\n",
3468 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3469 				goto finish;
3470 			}
3471 		}
3472 	}
3473 
3474 	/* If the caller needs the plist, hand them back our copy
3475 	 */
3476 	if (mkextPlistOut) {
3477 		*mkextPlistOut = mkextPlist;
3478 		parsedXML.detach();
3479 	}
3480 
3481 	/* Even if we didn't keep any kexts from the mkext, we may have a load
3482 	 * request to process, so we are successful (no errors occurred).
3483 	 */
3484 	result = kOSReturnSuccess;
3485 
3486 finish:
3487 	return result;
3488 }
3489 
3490 /* static */
3491 OSReturn
3492 OSKext::readMkext2Archive(
3493 	OSData        * mkextData,
3494 	OSSharedPtr<OSDictionary> &mkextPlistOut,
3495 	uint32_t      * checksumPtr)
3496 {
3497 	OSDictionary * mkextPlist = NULL;
3498 	OSReturn ret;
3499 
3500 	if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData,
3501 	    &mkextPlist,
3502 	    checksumPtr))) {
3503 		mkextPlistOut.reset(mkextPlist, OSNoRetain);
3504 	}
3505 	return ret;
3506 }
3507 
3508 /*********************************************************************
3509 *********************************************************************/
3510 /* static */
3511 OSSharedPtr<OSKext>
3512 OSKext::withMkext2Info(
3513 	OSDictionary * anInfoDict,
3514 	OSData       * mkextData)
3515 {
3516 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
3517 
3518 	if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
3519 		return NULL;
3520 	}
3521 
3522 	return newKext;
3523 }
3524 
3525 /*********************************************************************
3526 *********************************************************************/
3527 bool
3528 OSKext::initWithMkext2Info(
3529 	OSDictionary * anInfoDict,
3530 	OSData       * mkextData)
3531 {
3532 	bool                   result              = false;
3533 	OSString             * kextPath            = NULL;        // do not release
3534 	OSNumber             * executableOffsetNum = NULL;        // do not release
3535 	OSSharedPtr<OSData>               executable;
3536 
3537 	if (anInfoDict == NULL || !super::init()) {
3538 		goto finish;
3539 	}
3540 
3541 	/* Get the path. Don't look for an arch-specific path property.
3542 	 */
3543 	kextPath = OSDynamicCast(OSString,
3544 	    anInfoDict->getObject(kMKEXTBundlePathKey));
3545 
3546 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
3547 		goto finish;
3548 	}
3549 
3550 	/* If we have a path to the executable, save it.
3551 	 */
3552 	executableRelPath.reset(OSDynamicCast(OSString,
3553 	    anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain);
3554 
3555 	/* Don't need the paths to be in the info dictionary any more.
3556 	 */
3557 	anInfoDict->removeObject(kMKEXTBundlePathKey);
3558 	anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
3559 
3560 	executableOffsetNum = OSDynamicCast(OSNumber,
3561 	    infoDict->getObject(kMKEXTExecutableKey));
3562 	if (executableOffsetNum) {
3563 		executable = createMkext2FileEntry(mkextData,
3564 		    executableOffsetNum, "executable");
3565 		infoDict->removeObject(kMKEXTExecutableKey);
3566 		if (!executable) {
3567 			goto finish;
3568 		}
3569 		if (!setExecutable(executable.get(), mkextData, true)) {
3570 			goto finish;
3571 		}
3572 	}
3573 
3574 	result = (registerIdentifier() == kOSKextInitialized);
3575 finish:
3576 	return result;
3577 }
3578 
3579 /*********************************************************************
3580 *********************************************************************/
3581 OSSharedPtr<OSData>
3582 OSKext::createMkext2FileEntry(
3583 	OSData     * mkextData,
3584 	OSNumber   * offsetNum,
3585 	const char * name)
3586 {
3587 	OSSharedPtr<OSData> result;
3588 	MkextEntryRef   entryRef;
3589 	uint8_t       * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
3590 	uint32_t        entryOffset = offsetNum->unsigned32BitValue();
3591 
3592 	result = OSData::withCapacity(sizeof(entryRef));
3593 	if (!result) {
3594 		goto finish;
3595 	}
3596 
3597 	entryRef.mkext = (mkext_basic_header *)mkextBuffer;
3598 	entryRef.fileinfo = mkextBuffer + entryOffset;
3599 	if (!result->appendValue(entryRef)) {
3600 		result.reset();
3601 		goto finish;
3602 	}
3603 
3604 finish:
3605 	if (!result) {
3606 		OSKextLog(this,
3607 		    kOSKextLogErrorLevel |
3608 		    kOSKextLogArchiveFlag,
3609 		    "Can't create wrapper for mkext file entry '%s' of kext %s.",
3610 		    name, getIdentifierCString());
3611 	}
3612 	return result;
3613 }
3614 
3615 /*********************************************************************
3616 *********************************************************************/
3617 extern "C" {
3618 static void * z_alloc(void *, u_int items, u_int size);
3619 static void   z_free(void *, void *ptr);
3620 
3621 typedef struct z_mem {
3622 	uint32_t alloc_size;
3623 	uint8_t  data[0];
3624 } z_mem;
3625 
3626 /*
3627  * Space allocation and freeing routines for use by zlib routines.
3628  */
3629 void *
3630 z_alloc(void * notused __unused, u_int num_items, u_int size)
3631 {
3632 	void     * result = NULL;
3633 	z_mem    * zmem = NULL;
3634 
3635 	uint64_t   total = ((uint64_t)num_items) * ((uint64_t)size);
3636 	//Check for overflow due to multiplication
3637 	if (total > UINT32_MAX) {
3638 		panic("z_alloc(%p, %x, %x): overflow caused by %x * %x",
3639 		    notused, num_items, size, num_items, size);
3640 	}
3641 
3642 	uint64_t   allocSize64 =  total + ((uint64_t)sizeof(zmem));
3643 	//Check for overflow due to addition
3644 	if (allocSize64 > UINT32_MAX) {
3645 		panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx",
3646 		    notused, num_items, size, (uint32_t)total, sizeof(zmem));
3647 	}
3648 	uint32_t allocSize = (uint32_t)allocSize64;
3649 
3650 	zmem = (z_mem *)kalloc_data_tag(allocSize, Z_WAITOK,
3651 	    VM_KERN_MEMORY_OSKEXT);
3652 	if (!zmem) {
3653 		goto finish;
3654 	}
3655 	zmem->alloc_size = allocSize;
3656 	result = (void *)&(zmem->data);
3657 finish:
3658 	return result;
3659 }
3660 
3661 void
3662 z_free(void * notused __unused, void * ptr)
3663 {
3664 	uint32_t * skipper = (uint32_t *)ptr - 1;
3665 	z_mem    * zmem = (z_mem *)skipper;
3666 	kfree_data(zmem, zmem->alloc_size);
3667 }
3668 };
3669 
3670 OSSharedPtr<OSData>
3671 OSKext::extractMkext2FileData(
3672 	UInt8      * data,
3673 	const char * name,
3674 	uint32_t     compressedSize,
3675 	uint32_t     fullSize)
3676 {
3677 	OSSharedPtr<OSData>      result;
3678 	OSSharedPtr<OSData>      uncompressedData;        // release on error
3679 
3680 	uint8_t     * uncompressedDataBuffer = NULL;        // do not free
3681 	unsigned long uncompressedSize;
3682 	z_stream      zstream;
3683 	bool          zstream_inited = false;
3684 	int           zlib_result;
3685 
3686 	/* If the file isn't compressed, we want to make a copy
3687 	 * so that we don't have the tie to the larger mkext file buffer any more.
3688 	 */
3689 	if (!compressedSize) {
3690 		uncompressedData = OSData::withBytes(data, fullSize);
3691 		// xxx - no check for failure?
3692 		result = uncompressedData;
3693 		goto finish;
3694 	}
3695 
3696 	if (KERN_SUCCESS != kmem_alloc(kernel_map,
3697 	    (vm_offset_t*)&uncompressedDataBuffer, fullSize,
3698 	    KMA_DATA, VM_KERN_MEMORY_OSKEXT)) {
3699 		/* How's this for cheesy? The kernel is only asked to extract
3700 		 * kext plists so we tailor the log messages.
3701 		 */
3702 		if (isKernel()) {
3703 			OSKextLog(this,
3704 			    kOSKextLogErrorLevel |
3705 			    kOSKextLogArchiveFlag,
3706 			    "Allocation failure extracting %s from mkext.", name);
3707 		} else {
3708 			OSKextLog(this,
3709 			    kOSKextLogErrorLevel |
3710 			    kOSKextLogArchiveFlag,
3711 			    "Allocation failure extracting %s from mkext for kext %s.",
3712 			    name, getIdentifierCString());
3713 		}
3714 
3715 		goto finish;
3716 	}
3717 	uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3718 	if (!uncompressedData) {
3719 		if (isKernel()) {
3720 			OSKextLog(this,
3721 			    kOSKextLogErrorLevel |
3722 			    kOSKextLogArchiveFlag,
3723 			    "Allocation failure extracting %s from mkext.", name);
3724 		} else {
3725 			OSKextLog(this,
3726 			    kOSKextLogErrorLevel |
3727 			    kOSKextLogArchiveFlag,
3728 			    "Allocation failure extracting %s from mkext for kext %s.",
3729 			    name, getIdentifierCString());
3730 		}
3731 		goto finish;
3732 	}
3733 	uncompressedData->setDeallocFunction(&osdata_kmem_free);
3734 
3735 	if (isKernel()) {
3736 		OSKextLog(this,
3737 		    kOSKextLogDetailLevel |
3738 		    kOSKextLogArchiveFlag,
3739 		    "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3740 		    name, compressedSize, fullSize);
3741 	} else {
3742 		OSKextLog(this,
3743 		    kOSKextLogDetailLevel |
3744 		    kOSKextLogArchiveFlag,
3745 		    "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3746 		    getIdentifierCString(), name, compressedSize, fullSize);
3747 	}
3748 
3749 	bzero(&zstream, sizeof(zstream));
3750 	zstream.next_in   = (UInt8 *)data;
3751 	zstream.avail_in  = compressedSize;
3752 
3753 	zstream.next_out  = uncompressedDataBuffer;
3754 	zstream.avail_out = fullSize;
3755 
3756 	zstream.zalloc    = z_alloc;
3757 	zstream.zfree     = z_free;
3758 
3759 	zlib_result = inflateInit(&zstream);
3760 	if (Z_OK != zlib_result) {
3761 		if (isKernel()) {
3762 			OSKextLog(this,
3763 			    kOSKextLogErrorLevel |
3764 			    kOSKextLogArchiveFlag,
3765 			    "Mkext error; zlib inflateInit failed (%d) for %s.",
3766 			    zlib_result, name);
3767 		} else {
3768 			OSKextLog(this,
3769 			    kOSKextLogErrorLevel |
3770 			    kOSKextLogArchiveFlag,
3771 			    "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3772 			    getIdentifierCString(), zlib_result, name);
3773 		}
3774 		goto finish;
3775 	} else {
3776 		zstream_inited = true;
3777 	}
3778 
3779 	zlib_result = inflate(&zstream, Z_FINISH);
3780 
3781 	if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3782 		uncompressedSize = zstream.total_out;
3783 	} else {
3784 		if (isKernel()) {
3785 			OSKextLog(this,
3786 			    kOSKextLogErrorLevel |
3787 			    kOSKextLogArchiveFlag,
3788 			    "Mkext error; zlib inflate failed (%d) for %s.",
3789 			    zlib_result, name);
3790 		} else {
3791 			OSKextLog(this,
3792 			    kOSKextLogErrorLevel |
3793 			    kOSKextLogArchiveFlag,
3794 			    "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3795 			    getIdentifierCString(), zlib_result, name);
3796 		}
3797 		if (zstream.msg) {
3798 			OSKextLog(this,
3799 			    kOSKextLogErrorLevel |
3800 			    kOSKextLogArchiveFlag,
3801 			    "zlib error: %s.", zstream.msg);
3802 		}
3803 		goto finish;
3804 	}
3805 
3806 	if (uncompressedSize != fullSize) {
3807 		if (isKernel()) {
3808 			OSKextLog(this,
3809 			    kOSKextLogErrorLevel |
3810 			    kOSKextLogArchiveFlag,
3811 			    "Mkext error; zlib inflate discrepancy for %s, "
3812 			    "uncompressed size != original size.", name);
3813 		} else {
3814 			OSKextLog(this,
3815 			    kOSKextLogErrorLevel |
3816 			    kOSKextLogArchiveFlag,
3817 			    "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3818 			    "uncompressed size != original size.",
3819 			    getIdentifierCString(), name);
3820 		}
3821 		goto finish;
3822 	}
3823 
3824 	result = os::move(uncompressedData);
3825 
3826 finish:
3827 	/* Don't bother checking return, nothing we can do on fail.
3828 	 */
3829 	if (zstream_inited) {
3830 		inflateEnd(&zstream);
3831 	}
3832 
3833 	return result;
3834 }
3835 
3836 /*********************************************************************
3837 *********************************************************************/
3838 /* static */
3839 OSReturn
3840 OSKext::loadFromMkext(
3841 	OSKextLogSpec   clientLogFilter,
3842 	char          * mkextBuffer,
3843 	uint32_t        mkextBufferLength,
3844 	char         ** logInfoOut,
3845 	uint32_t      * logInfoLengthOut)
3846 {
3847 	OSReturn         result                      = kOSReturnError;
3848 	OSReturn         tempResult                  = kOSReturnError;
3849 
3850 	OSSharedPtr<OSData>        mkextData;
3851 	OSSharedPtr<OSDictionary>  mkextPlist;
3852 
3853 	OSSharedPtr<OSArray>       logInfoArray;
3854 	OSSharedPtr<OSSerialize>   serializer;
3855 
3856 	OSString       * predicate                   = NULL;        // do not release
3857 	OSDictionary   * requestArgs                 = NULL;        // do not release
3858 
3859 	OSString       * kextIdentifier              = NULL;        // do not release
3860 	OSNumber       * startKextExcludeNum         = NULL;        // do not release
3861 	OSNumber       * startMatchingExcludeNum     = NULL;        // do not release
3862 	OSBoolean      * delayAutounloadBool         = NULL;        // do not release
3863 	OSArray        * personalityNames            = NULL;        // do not release
3864 
3865 	/* Default values for these two options: regular autounload behavior,
3866 	 * load all kexts, send no personalities.
3867 	 */
3868 	Boolean            delayAutounload           = false;
3869 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
3870 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3871 
3872 	IORecursiveLockLock(sKextLock);
3873 
3874 	if (logInfoOut) {
3875 		*logInfoOut = NULL;
3876 		*logInfoLengthOut = 0;
3877 	}
3878 
3879 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3880 
3881 	OSKextLog(/* kext */ NULL,
3882 	    kOSKextLogDebugLevel |
3883 	    kOSKextLogIPCFlag,
3884 	    "Received kext load request from user space.");
3885 
3886 	/* Regardless of processing, the fact that we have gotten here means some
3887 	 * user-space program is up and talking to us, so we'll switch our kext
3888 	 * registration to reflect that.
3889 	 */
3890 	if (!sUserLoadsActive) {
3891 		OSKextLog(/* kext */ NULL,
3892 		    kOSKextLogProgressLevel |
3893 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3894 		    "Switching to late startup (user-space) kext loading policy.");
3895 
3896 		sUserLoadsActive = true;
3897 	}
3898 
3899 	if (!sLoadEnabled) {
3900 		OSKextLog(/* kext */ NULL,
3901 		    kOSKextLogErrorLevel |
3902 		    kOSKextLogLoadFlag,
3903 		    "Kext loading is disabled.");
3904 		result = kOSKextReturnDisabled;
3905 		goto finish;
3906 	}
3907 
3908 	/* Note that we do not set a dealloc function on this OSData
3909 	 * object! No references to it can remain after the loadFromMkext()
3910 	 * call since we are in a MIG function, and will vm_deallocate()
3911 	 * the buffer.
3912 	 */
3913 	mkextData = OSData::withBytesNoCopy(mkextBuffer,
3914 	    mkextBufferLength);
3915 	if (!mkextData) {
3916 		OSKextLog(/* kext */ NULL,
3917 		    kOSKextLogErrorLevel |
3918 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3919 		    "Failed to create wrapper for kext load request.");
3920 		result = kOSKextReturnNoMemory;
3921 		goto finish;
3922 	}
3923 
3924 	result = readMkext2Archive(mkextData.get(), mkextPlist, NULL);
3925 	if (result != kOSReturnSuccess) {
3926 		OSKextLog(/* kext */ NULL,
3927 		    kOSKextLogErrorLevel |
3928 		    kOSKextLogLoadFlag,
3929 		    "Failed to read kext load request.");
3930 		goto finish;
3931 	}
3932 
3933 	predicate = _OSKextGetRequestPredicate(mkextPlist.get());
3934 	if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3935 		OSKextLog(/* kext */ NULL,
3936 		    kOSKextLogErrorLevel |
3937 		    kOSKextLogLoadFlag,
3938 		    "Received kext load request with no predicate; skipping.");
3939 		result = kOSKextReturnInvalidArgument;
3940 		goto finish;
3941 	}
3942 
3943 	requestArgs = OSDynamicCast(OSDictionary,
3944 	    mkextPlist->getObject(kKextRequestArgumentsKey));
3945 	if (!requestArgs || !requestArgs->getCount()) {
3946 		OSKextLog(/* kext */ NULL,
3947 		    kOSKextLogErrorLevel |
3948 		    kOSKextLogLoadFlag,
3949 		    "Received kext load request with no arguments.");
3950 		result = kOSKextReturnInvalidArgument;
3951 		goto finish;
3952 	}
3953 
3954 	kextIdentifier = OSDynamicCast(OSString,
3955 	    requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3956 
3957 	if (!kextIdentifier) {
3958 		OSKextLog(/* kext */ NULL,
3959 		    kOSKextLogErrorLevel |
3960 		    kOSKextLogLoadFlag,
3961 		    "Received kext load request with no kext identifier.");
3962 		result = kOSKextReturnInvalidArgument;
3963 		goto finish;
3964 	}
3965 
3966 	startKextExcludeNum = OSDynamicCast(OSNumber,
3967 	    requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3968 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
3969 	    requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3970 	delayAutounloadBool = OSDynamicCast(OSBoolean,
3971 	    requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3972 	personalityNames = OSDynamicCast(OSArray,
3973 	    requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3974 
3975 	if (delayAutounloadBool) {
3976 		delayAutounload = delayAutounloadBool->getValue();
3977 	}
3978 	if (startKextExcludeNum) {
3979 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3980 	}
3981 	if (startMatchingExcludeNum) {
3982 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3983 	}
3984 
3985 	OSKextLog(/* kext */ NULL,
3986 	    kOSKextLogProgressLevel |
3987 	    kOSKextLogIPCFlag,
3988 	    "Received request from user space to load kext %s.",
3989 	    kextIdentifier->getCStringNoCopy());
3990 
3991 	/* Load the kext, with no deferral, since this is a load from outside
3992 	 * the kernel.
3993 	 * xxx - Would like a better way to handle the default values for the
3994 	 * xxx - start/match opt args.
3995 	 */
3996 	result = OSKext::loadKextWithIdentifier(
3997 		kextIdentifier,
3998 		/* kextRef */ NULL,
3999 		/* allowDefer */ false,
4000 		delayAutounload,
4001 		startKextExcludeLevel,
4002 		startMatchingExcludeLevel,
4003 		personalityNames);
4004 	if (result != kOSReturnSuccess) {
4005 		goto finish;
4006 	}
4007 	/* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue
4008 	 * for matching via a separate IOKit calldown.
4009 	 */
4010 
4011 finish:
4012 
4013 	/* Gather up the collected log messages for user space. Any
4014 	 * error messages past this call will not make it up as log messages
4015 	 * but will be in the system log.
4016 	 */
4017 	logInfoArray = OSKext::clearUserSpaceLogFilter();
4018 
4019 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
4020 		tempResult = OSKext::serializeLogInfo(logInfoArray.get(),
4021 		    logInfoOut, logInfoLengthOut);
4022 		if (tempResult != kOSReturnSuccess) {
4023 			result = tempResult;
4024 		}
4025 	}
4026 
4027 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
4028 
4029 	IORecursiveLockUnlock(sKextLock);
4030 
4031 	/* Note: mkextDataObject will have been retained by every kext w/an
4032 	 * executable in it. That should all have been flushed out at the
4033 	 * and of the load operation, but you never know....
4034 	 */
4035 	if (mkextData && mkextData->getRetainCount() > 1) {
4036 		OSKextLog(/* kext */ NULL,
4037 		    kOSKextLogErrorLevel |
4038 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
4039 		    "Kext load request buffer from user space still retained by a kext; "
4040 		    "probable memory leak.");
4041 	}
4042 
4043 	return result;
4044 }
4045 
4046 #endif // CONFIG_KXLD
4047 
4048 /*********************************************************************
4049 *********************************************************************/
4050 /* static */
4051 OSReturn
4052 OSKext::serializeLogInfo(
4053 	OSArray   * logInfoArray,
4054 	char     ** logInfoOut,
4055 	uint32_t  * logInfoLengthOut)
4056 {
4057 	OSReturn        result      = kOSReturnError;
4058 	char          * buffer      = NULL;
4059 	kern_return_t   kmem_result = KERN_FAILURE;
4060 	OSSharedPtr<OSSerialize>  serializer;
4061 	char         * logInfo            = NULL;        // returned by reference
4062 	uint32_t       logInfoLength      = 0;
4063 
4064 	if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
4065 		OSKextLog(/* kext */ NULL,
4066 		    kOSKextLogErrorLevel |
4067 		    kOSKextLogIPCFlag,
4068 		    "Internal error; invalid arguments to OSKext::serializeLogInfo().");
4069 		/* Bad programmer. */
4070 		result = kOSKextReturnInvalidArgument;
4071 		goto finish;
4072 	}
4073 
4074 	serializer = OSSerialize::withCapacity(0);
4075 	if (!serializer) {
4076 		OSKextLog(/* kext */ NULL,
4077 		    kOSKextLogErrorLevel |
4078 		    kOSKextLogIPCFlag,
4079 		    "Failed to create serializer on log info for request from user space.");
4080 		/* Incidental error; we're going to (try to) allow the request
4081 		 * itself to succeed. */
4082 	}
4083 
4084 	if (!logInfoArray->serialize(serializer.get())) {
4085 		OSKextLog(/* kext */ NULL,
4086 		    kOSKextLogErrorLevel |
4087 		    kOSKextLogIPCFlag,
4088 		    "Failed to serialize log info for request from user space.");
4089 		/* Incidental error; we're going to (try to) allow the request
4090 		 * itself to succeed. */
4091 	} else {
4092 		logInfo = serializer->text();
4093 		logInfoLength = serializer->getLength();
4094 
4095 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength),
4096 		    KMA_DATA, VM_KERN_MEMORY_OSKEXT);
4097 		if (kmem_result != KERN_SUCCESS) {
4098 			OSKextLog(/* kext */ NULL,
4099 			    kOSKextLogErrorLevel |
4100 			    kOSKextLogIPCFlag,
4101 			    "Failed to copy log info for request from user space.");
4102 			/* Incidental error; we're going to (try to) allow the request
4103 			 * to succeed. */
4104 		} else {
4105 			/* 11981737 - clear uninitialized data in last page */
4106 			bzero((void *)(buffer + logInfoLength),
4107 			    (round_page(logInfoLength) - logInfoLength));
4108 			memcpy(buffer, logInfo, logInfoLength);
4109 			*logInfoOut = buffer;
4110 			*logInfoLengthOut = logInfoLength;
4111 		}
4112 	}
4113 
4114 	result = kOSReturnSuccess;
4115 finish:
4116 	return result;
4117 }
4118 
4119 #if PRAGMA_MARK
4120 #pragma mark Instance Management Methods
4121 #endif
4122 /*********************************************************************
4123 *********************************************************************/
4124 OSSharedPtr<OSKext>
4125 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
4126 {
4127 	OSSharedPtr<OSKext> foundKext;
4128 
4129 	IORecursiveLockLock(sKextLock);
4130 	foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain);
4131 	IORecursiveLockUnlock(sKextLock);
4132 
4133 	return foundKext;
4134 }
4135 
4136 /*********************************************************************
4137 *********************************************************************/
4138 OSSharedPtr<OSKext>
4139 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
4140 {
4141 	return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
4142 }
4143 
4144 /*********************************************************************
4145 *********************************************************************/
4146 OSSharedPtr<OSKext>
4147 OSKext::lookupDextWithIdentifier(OSString * dextIdentifier, OSData *dextUniqueIdentifier)
4148 {
4149 	OSSharedPtr<OSKext> foundDext;
4150 	foundDext.reset();
4151 
4152 	IORecursiveLockLock(sKextLock);
4153 	OSKext *dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIdentifier->getCStringNoCopy()));
4154 	if (dext != NULL && dext->isDriverKit()) {
4155 		if (dext->dextUniqueID == NULL || dext->dextUniqueID->isEqualTo(dextUniqueIdentifier)) {
4156 			foundDext.reset(dext, OSRetain);
4157 		}
4158 	}
4159 	IORecursiveLockUnlock(sKextLock);
4160 
4161 	return foundDext;
4162 }
4163 
4164 /*********************************************************************
4165 *********************************************************************/
4166 OSSharedPtr<OSKext>
4167 OSKext::lookupKextWithLoadTag(uint32_t aTag)
4168 {
4169 	OSSharedPtr<OSKext> foundKext;             // returned
4170 	uint32_t i, j;
4171 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4172 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4173 
4174 	IORecursiveLockLock(sKextLock);
4175 
4176 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4177 		for (i = 0; i < count[j]; i++) {
4178 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4179 			if (thisKext->getLoadTag() == aTag) {
4180 				foundKext.reset(thisKext, OSRetain);
4181 				goto finish;
4182 			}
4183 		}
4184 	}
4185 
4186 finish:
4187 	IORecursiveLockUnlock(sKextLock);
4188 
4189 	return foundKext;
4190 }
4191 
4192 /*********************************************************************
4193 *********************************************************************/
4194 OSSharedPtr<OSKext>
4195 OSKext::lookupKextWithAddress(vm_address_t address)
4196 {
4197 	OSSharedPtr<OSKext> foundKext;             // returned
4198 	uint32_t count, i;
4199 	kmod_info_t *kmod_info;
4200 	vm_address_t originalAddress;
4201 #if defined(__arm64__)
4202 	uint64_t   textExecBase;
4203 	size_t     textExecSize;
4204 #endif /* defined(__arm64__) */
4205 
4206 	originalAddress = address;
4207 #if  __has_feature(ptrauth_calls)
4208 	address = (vm_address_t)VM_KERNEL_STRIP_PTR(address);
4209 #endif /*  __has_feature(ptrauth_calls) */
4210 
4211 	IORecursiveLockLock(sKextLock);
4212 
4213 	count = sLoadedKexts->getCount();
4214 	for (i = 0; i < count; i++) {
4215 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
4216 		if (thisKext == sKernelKext) {
4217 			continue;
4218 		}
4219 		if (thisKext->kmod_info && thisKext->kmod_info->address) {
4220 			kmod_info = thisKext->kmod_info;
4221 			vm_address_t kext_start = kmod_info->address;
4222 			vm_address_t kext_end = kext_start + kmod_info->size;
4223 			if ((kext_start <= address) && (address < kext_end)) {
4224 				foundKext.reset(thisKext, OSRetain);
4225 				goto finish;
4226 			}
4227 #if defined(__arm64__)
4228 			textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize);
4229 			if ((textExecBase <= address) && (address < textExecBase + textExecSize)) {
4230 				foundKext.reset(thisKext, OSRetain);
4231 				goto finish;
4232 			}
4233 #endif /* defined (__arm64__) */
4234 		}
4235 	}
4236 	if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) {
4237 		foundKext.reset(sKernelKext, OSRetain);
4238 		goto finish;
4239 	}
4240 	/*
4241 	 * DriverKit userspace executables do not have a kernel linkedExecutable,
4242 	 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address
4243 	 * here, so use the original address passed to this method.
4244 	 *
4245 	 * This is supposed to be used for logging reasons only. When logd
4246 	 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
4247 	 * remove it here before checking it against the LoadTag.
4248 	 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
4249 	 */
4250 
4251 	address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
4252 	count = sLoadedDriverKitKexts->getCount();
4253 	for (i = 0; i < count; i++) {
4254 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
4255 		if (thisKext->getLoadTag() == address) {
4256 			foundKext.reset(thisKext, OSRetain);
4257 		}
4258 	}
4259 
4260 finish:
4261 	IORecursiveLockUnlock(sKextLock);
4262 
4263 	return foundKext;
4264 }
4265 
4266 OSSharedPtr<OSData>
4267 OSKext::copyKextUUIDForAddress(OSNumber *address)
4268 {
4269 	OSSharedPtr<OSData>   uuid;
4270 	OSSharedPtr<OSKext>   kext;
4271 
4272 	if (!address) {
4273 		return NULL;
4274 	}
4275 
4276 #if CONFIG_MACF
4277 	/* Is the calling process allowed to query kext info? */
4278 	if (current_task() != kernel_task) {
4279 		int macCheckResult = 0;
4280 		kauth_cred_t cred = NULL;
4281 
4282 		cred = kauth_cred_get_with_ref();
4283 		macCheckResult = mac_kext_check_query(cred);
4284 		kauth_cred_unref(&cred);
4285 
4286 		if (macCheckResult != 0) {
4287 			OSKextLog(/* kext */ NULL,
4288 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4289 			    "Failed to query kext UUID (MAC policy error 0x%x).",
4290 			    macCheckResult);
4291 			return NULL;
4292 		}
4293 	}
4294 #endif
4295 
4296 	uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue());
4297 	if (slidAddress != 0) {
4298 		kext = lookupKextWithAddress(slidAddress);
4299 		if (kext) {
4300 			uuid = kext->copyTextUUID();
4301 		}
4302 	}
4303 
4304 	if (!uuid) {
4305 		/*
4306 		 * If we still don't have a UUID, then we failed to match the slid + stripped address with
4307 		 * a kext. This might have happened because the log message came from a dext.
4308 		 *
4309 		 * Try again with the original address.
4310 		 */
4311 		kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue());
4312 		if (kext && kext->isDriverKit()) {
4313 			uuid = kext->copyTextUUID();
4314 		}
4315 	}
4316 
4317 	return uuid;
4318 }
4319 
4320 /*********************************************************************
4321 *********************************************************************/
4322 OSSharedPtr<OSKext>
4323 OSKext::lookupKextWithUUID(uuid_t wanted)
4324 {
4325 	OSSharedPtr<OSKext> foundKext;             // returned
4326 	uint32_t j, i;
4327 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4328 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4329 
4330 
4331 	IORecursiveLockLock(sKextLock);
4332 
4333 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4334 		for (i = 0; i < count[j]; i++) {
4335 			OSKext   * thisKext     = NULL;
4336 
4337 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4338 			if (!thisKext) {
4339 				continue;
4340 			}
4341 
4342 			OSSharedPtr<OSData> uuid_data = thisKext->copyUUID();
4343 			if (!uuid_data) {
4344 				continue;
4345 			}
4346 
4347 			uuid_t uuid;
4348 			memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
4349 
4350 			if (0 == uuid_compare(wanted, uuid)) {
4351 				foundKext.reset(thisKext, OSRetain);
4352 				goto finish;
4353 			}
4354 		}
4355 	}
4356 finish:
4357 	IORecursiveLockUnlock(sKextLock);
4358 
4359 	return foundKext;
4360 }
4361 
4362 
4363 
4364 
4365 /*********************************************************************
4366 *********************************************************************/
4367 /* static */
4368 bool
4369 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
4370 {
4371 	bool result = false;
4372 	OSKext * foundKext = NULL;             // returned
4373 
4374 	IORecursiveLockLock(sKextLock);
4375 
4376 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4377 	if (foundKext && foundKext->isLoaded()) {
4378 		result = true;
4379 	}
4380 
4381 	IORecursiveLockUnlock(sKextLock);
4382 
4383 	return result;
4384 }
4385 
4386 /*********************************************************************
4387 * xxx - should spawn a separate thread so a kext can safely have
4388 * xxx - itself unloaded.
4389 *********************************************************************/
4390 /* static */
4391 OSReturn
4392 OSKext::removeKext(
4393 	OSKext * aKext,
4394 #if CONFIG_EMBEDDED
4395 	__unused
4396 #endif
4397 	bool     terminateServicesAndRemovePersonalitiesFlag)
4398 {
4399 #if CONFIG_EMBEDDED
4400 	if (!aKext->isDriverKit()) {
4401 		OSKextLog(aKext,
4402 		    kOSKextLogErrorLevel |
4403 		    kOSKextLogKextBookkeepingFlag,
4404 		    "removeKext() called for %s, only supported on embedded for DriverKit dexts",
4405 		    aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
4406 
4407 		return kOSReturnSuccess;
4408 	}
4409 #endif /* CONFIG_EMBEDDED */
4410 	OSReturn result    = kOSKextReturnInUse;
4411 	OSKext * checkKext = NULL;         // do not release
4412 #if CONFIG_MACF
4413 	int macCheckResult = 0;
4414 	kauth_cred_t cred  = NULL;
4415 #endif
4416 
4417 	IORecursiveLockLock(sKextLock);
4418 
4419 	/* If the kext has no identifier, it failed to init
4420 	 * so isn't in sKextsByID and it isn't loaded.
4421 	 */
4422 	if (!aKext->getIdentifier()) {
4423 		result = kOSReturnSuccess;
4424 		goto finish;
4425 	}
4426 
4427 	checkKext = OSDynamicCast(OSKext,
4428 	    sKextsByID->getObject(aKext->getIdentifier()));
4429 	if (checkKext != aKext) {
4430 		result = kOSKextReturnNotFound;
4431 		goto finish;
4432 	}
4433 
4434 	if (aKext->isLoaded() || aKext->isDriverKit()) {
4435 #if CONFIG_MACF
4436 		if (current_task() != kernel_task) {
4437 			cred = kauth_cred_get_with_ref();
4438 			macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
4439 			kauth_cred_unref(&cred);
4440 		}
4441 
4442 		if (macCheckResult != 0) {
4443 			result = kOSReturnError;
4444 			OSKextLog(aKext,
4445 			    kOSKextLogErrorLevel |
4446 			    kOSKextLogKextBookkeepingFlag,
4447 			    "Failed to remove kext %s (MAC policy error 0x%x).",
4448 			    aKext->getIdentifierCString(), macCheckResult);
4449 			goto finish;
4450 		}
4451 #endif
4452 
4453 		/* make sure there are no resource requests in flight - 17187548 */
4454 		if (aKext->declaresExecutable() && aKext->countRequestCallbacks()) {
4455 			goto finish;
4456 		}
4457 		if (aKext->flags.unloadUnsupported) {
4458 			result = kOSKextReturnInUse;
4459 			OSKextLog(aKext,
4460 			    kOSKextLogErrorLevel |
4461 			    kOSKextLogKextBookkeepingFlag,
4462 			    "Can't remove kext %s; unsupported by cache.",
4463 			    aKext->getIdentifierCString());
4464 			goto finish;
4465 		}
4466 
4467 		/* If we are terminating, send the request to the IOCatalogue
4468 		 * (which will actually call us right back but that's ok we have
4469 		 * a recursive lock don't you know) but do not ask the IOCatalogue
4470 		 * to call back with an unload, we'll do that right here.
4471 		 */
4472 		if (terminateServicesAndRemovePersonalitiesFlag) {
4473 			result = gIOCatalogue->terminateDriversForModule(
4474 				aKext->getIdentifierCString(), /* unload */ false);
4475 			if (result != kOSReturnSuccess) {
4476 				OSKextLog(aKext,
4477 				    kOSKextLogErrorLevel |
4478 				    kOSKextLogKextBookkeepingFlag,
4479 				    "Can't remove kext %s; services failed to terminate - 0x%x.",
4480 				    aKext->getIdentifierCString(), result);
4481 				goto finish;
4482 			}
4483 		}
4484 
4485 		result = aKext->unload();
4486 		if (result != kOSReturnSuccess) {
4487 			OSKextLog(aKext,
4488 			    kOSKextLogErrorLevel |
4489 			    kOSKextLogKextBookkeepingFlag,
4490 			    "Can't remove kext %s; kext failed to unload - 0x%x.",
4491 			    aKext->getIdentifierCString(), result);
4492 			goto finish;
4493 		}
4494 	}
4495 
4496 	/* Remove personalities as requested. This is a bit redundant for a loaded
4497 	 * kext as IOCatalogue::terminateDriversForModule() removes driver
4498 	 * personalities, but it doesn't restart matching, which we always want
4499 	 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
4500 	 * that happens.
4501 	 */
4502 	if (terminateServicesAndRemovePersonalitiesFlag) {
4503 		aKext->removePersonalitiesFromCatalog();
4504 	}
4505 
4506 	if (aKext->isInFileset()) {
4507 		OSKextLog(aKext,
4508 		    kOSKextLogProgressLevel |
4509 		    kOSKextLogKextBookkeepingFlag,
4510 		    "Fileset kext %s unloaded.",
4511 		    aKext->getIdentifierCString());
4512 	} else {
4513 		OSKextLog(aKext,
4514 		    kOSKextLogProgressLevel |
4515 		    kOSKextLogKextBookkeepingFlag,
4516 		    "Removing kext %s.",
4517 		    aKext->getIdentifierCString());
4518 
4519 		sKextsByID->removeObject(aKext->getIdentifier());
4520 	}
4521 	result = kOSReturnSuccess;
4522 
4523 finish:
4524 	IORecursiveLockUnlock(sKextLock);
4525 	return result;
4526 }
4527 
4528 /*********************************************************************
4529 *********************************************************************/
4530 /* static */
4531 OSReturn
4532 OSKext::removeKextWithIdentifier(
4533 	const char * kextIdentifier,
4534 	bool         terminateServicesAndRemovePersonalitiesFlag)
4535 {
4536 	OSReturn result = kOSReturnError;
4537 
4538 	IORecursiveLockLock(sKextLock);
4539 
4540 	OSKext * aKext = OSDynamicCast(OSKext,
4541 	    sKextsByID->getObject(kextIdentifier));
4542 	if (!aKext) {
4543 		result = kOSKextReturnNotFound;
4544 		OSKextLog(/* kext */ NULL,
4545 		    kOSKextLogErrorLevel |
4546 		    kOSKextLogKextBookkeepingFlag,
4547 		    "Can't remove kext %s - not found.",
4548 		    kextIdentifier);
4549 		goto finish;
4550 	}
4551 
4552 	result = OSKext::removeKext(aKext,
4553 	    terminateServicesAndRemovePersonalitiesFlag);
4554 
4555 finish:
4556 	IORecursiveLockUnlock(sKextLock);
4557 
4558 	return result;
4559 }
4560 
4561 /*********************************************************************
4562 *********************************************************************/
4563 /* static */
4564 OSReturn
4565 OSKext::removeKextWithLoadTag(
4566 	OSKextLoadTag loadTag,
4567 	bool          terminateServicesAndRemovePersonalitiesFlag)
4568 {
4569 	OSReturn result    = kOSReturnError;
4570 	OSKext * foundKext = NULL;
4571 	uint32_t i, j;
4572 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4573 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4574 
4575 
4576 	IORecursiveLockLock(sKextLock);
4577 
4578 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4579 		for (i = 0; i < count[j]; i++) {
4580 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4581 			if (thisKext->loadTag == loadTag) {
4582 				foundKext = thisKext;
4583 				break;
4584 			}
4585 		}
4586 	}
4587 
4588 	if (!foundKext) {
4589 		result = kOSKextReturnNotFound;
4590 		OSKextLog(/* kext */ NULL,
4591 		    kOSKextLogErrorLevel |
4592 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4593 		    "Can't remove kext with load tag %d - not found.",
4594 		    loadTag);
4595 		goto finish;
4596 	}
4597 
4598 	result = OSKext::removeKext(foundKext,
4599 	    terminateServicesAndRemovePersonalitiesFlag);
4600 
4601 finish:
4602 	IORecursiveLockUnlock(sKextLock);
4603 
4604 	return result;
4605 }
4606 
4607 /*********************************************************************
4608 *********************************************************************/
4609 OSSharedPtr<OSDictionary>
4610 OSKext::copyKexts(void)
4611 {
4612 	OSSharedPtr<OSDictionary> result;
4613 
4614 	IORecursiveLockLock(sKextLock);
4615 	result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection());
4616 	IORecursiveLockUnlock(sKextLock);
4617 
4618 	return result;
4619 }
4620 
4621 /*********************************************************************
4622 *********************************************************************/
4623 #define BOOTER_KEXT_PREFIX   "Driver-"
4624 
4625 typedef struct _DeviceTreeBuffer {
4626 	uint32_t paddr;
4627 	uint32_t length;
4628 } _DeviceTreeBuffer;
4629 
4630 /*********************************************************************
4631 * Create a dictionary of excluded kexts from the given booter data.
4632 *********************************************************************/
4633 /* static */
4634 void
4635 OSKext::createExcludeListFromBooterData(
4636 	OSDictionary *          theDictionary,
4637 	OSCollectionIterator *  theIterator )
4638 {
4639 	OSString                  * deviceTreeName      = NULL;        // do not release
4640 	const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;        // do not release
4641 	char                      * booterDataPtr       = NULL;        // do not release
4642 	_BooterKextFileInfo       * kextFileInfo        = NULL;        // do not release
4643 	char                      * infoDictAddr        = NULL;        // do not release
4644 	OSSharedPtr<OSObject>       parsedXML;
4645 	OSDictionary              * theInfoDict         = NULL;        // do not release
4646 
4647 	theIterator->reset();
4648 
4649 	/* look for AppleKextExcludeList.kext */
4650 	while ((deviceTreeName =
4651 	    OSDynamicCast(OSString, theIterator->getNextObject()))) {
4652 		const char *    devTreeNameCString;
4653 		OSData *        deviceTreeEntry;        // do not release
4654 		OSString *      myBundleID;        // do not release
4655 
4656 		deviceTreeEntry =
4657 		    OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
4658 		if (!deviceTreeEntry) {
4659 			continue;
4660 		}
4661 
4662 		/* Make sure it is a kext */
4663 		devTreeNameCString = deviceTreeName->getCStringNoCopy();
4664 		if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
4665 		    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
4666 			OSKextLog(NULL,
4667 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4668 			    "\"%s\" not a kext",
4669 			    devTreeNameCString);
4670 			continue;
4671 		}
4672 
4673 		deviceTreeBuffer = (const _DeviceTreeBuffer *)
4674 		    deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
4675 		if (!deviceTreeBuffer) {
4676 			continue;
4677 		}
4678 
4679 		booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
4680 		if (!booterDataPtr) {
4681 			continue;
4682 		}
4683 
4684 		kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
4685 		if (!kextFileInfo->infoDictPhysAddr ||
4686 		    !kextFileInfo->infoDictLength) {
4687 			continue;
4688 		}
4689 
4690 		infoDictAddr = (char *)
4691 		    ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
4692 		if (!infoDictAddr) {
4693 			continue;
4694 		}
4695 
4696 		parsedXML = OSUnserializeXML(infoDictAddr);
4697 		if (!parsedXML) {
4698 			continue;
4699 		}
4700 
4701 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
4702 		if (!theInfoDict) {
4703 			continue;
4704 		}
4705 
4706 		myBundleID =
4707 		    OSDynamicCast(OSString,
4708 		    theInfoDict->getObject(kCFBundleIdentifierKey));
4709 		if (myBundleID &&
4710 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4711 			boolean_t updated = updateExcludeList(theInfoDict);
4712 			if (!updated) {
4713 				/* 25322874 */
4714 				panic("Missing OSKextExcludeList dictionary");
4715 			}
4716 			break;
4717 		}
4718 	}         // while ( (deviceTreeName = ...) )
4719 
4720 	return;
4721 }
4722 
4723 /*********************************************************************
4724 * Create a dictionary of excluded kexts from the given prelink
4725 * info (kernelcache).
4726 *********************************************************************/
4727 /* static */
4728 void
4729 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
4730 {
4731 	OSDictionary *  myInfoDict = NULL;        // do not release
4732 	OSString *      myBundleID;        // do not release
4733 	u_int           i;
4734 
4735 	/* Find the Apple Kext Exclude List. */
4736 	for (i = 0; i < theInfoArray->getCount(); i++) {
4737 		myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
4738 		if (!myInfoDict) {
4739 			continue;
4740 		}
4741 		myBundleID =
4742 		    OSDynamicCast(OSString,
4743 		    myInfoDict->getObject(kCFBundleIdentifierKey));
4744 		if (myBundleID &&
4745 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4746 			boolean_t updated = updateExcludeList(myInfoDict);
4747 			if (!updated) {
4748 				/* 25322874 */
4749 				panic("Missing OSKextExcludeList dictionary");
4750 			}
4751 			break;
4752 		}
4753 	}         // for (i = 0; i < theInfoArray->getCount()...
4754 
4755 	return;
4756 }
4757 
4758 /* static */
4759 boolean_t
4760 OSKext::updateExcludeList(OSDictionary *infoDict)
4761 {
4762 	OSDictionary *myTempDict = NULL;         // do not free
4763 	OSString     *myTempString = NULL;        // do not free
4764 	OSKextVersion newVersion = 0;
4765 	boolean_t updated = false;
4766 
4767 	if (!infoDict) {
4768 		return false;
4769 	}
4770 
4771 	myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
4772 	if (!myTempDict) {
4773 		return false;
4774 	}
4775 
4776 	myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
4777 	if (!myTempString) {
4778 		return false;
4779 	}
4780 
4781 	newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
4782 	if (newVersion == 0) {
4783 		return false;
4784 	}
4785 
4786 	IORecursiveLockLock(sKextLock);
4787 
4788 	if (newVersion > sExcludeListVersion) {
4789 		sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
4790 		sExcludeListVersion = newVersion;
4791 		updated = true;
4792 	}
4793 
4794 	IORecursiveLockUnlock(sKextLock);
4795 	return updated;
4796 }
4797 
4798 #if PRAGMA_MARK
4799 #pragma mark Accessors
4800 #endif
4801 
4802 /*********************************************************************
4803 *********************************************************************/
4804 const OSObject *
4805 OSKext::getBundleExecutable(void)
4806 {
4807 	return infoDict->getObject(kCFBundleExecutableKey);
4808 }
4809 
4810 /*********************************************************************
4811 *********************************************************************/
4812 const OSSymbol *
4813 OSKext::getIdentifier(void)
4814 {
4815 	return bundleID.get();
4816 }
4817 
4818 /*********************************************************************
4819 * A kext must have a bundle identifier to even survive initialization;
4820 * this is guaranteed to exist past then.
4821 *********************************************************************/
4822 const char *
4823 OSKext::getIdentifierCString(void)
4824 {
4825 	return bundleID->getCStringNoCopy();
4826 }
4827 
4828 /*********************************************************************
4829 *********************************************************************/
4830 OSKextVersion
4831 OSKext::getVersion(void)
4832 {
4833 	return version;
4834 }
4835 
4836 /*********************************************************************
4837 *********************************************************************/
4838 OSKextVersion
4839 OSKext::getCompatibleVersion(void)
4840 {
4841 	return compatibleVersion;
4842 }
4843 
4844 /*********************************************************************
4845 *********************************************************************/
4846 bool
4847 OSKext::isLibrary(void)
4848 {
4849 	return getCompatibleVersion() > 0;
4850 }
4851 
4852 /*********************************************************************
4853 *********************************************************************/
4854 bool
4855 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
4856 {
4857 	if ((compatibleVersion > -1 && version > -1) &&
4858 	    (compatibleVersion <= version && aVersion <= version)) {
4859 		return true;
4860 	}
4861 	return false;
4862 }
4863 
4864 /*********************************************************************
4865 *********************************************************************/
4866 bool
4867 OSKext::declaresExecutable(void)
4868 {
4869 	if (isDriverKit()) {
4870 		return false;
4871 	}
4872 	return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
4873 }
4874 
4875 /*********************************************************************
4876 *********************************************************************/
4877 OSData *
4878 OSKext::getExecutable(void)
4879 {
4880 	OSData * result              = NULL;
4881 	OSSharedPtr<OSData> extractedExecutable;
4882 
4883 	if (flags.builtin) {
4884 		return sKernelKext->linkedExecutable.get();
4885 	}
4886 
4887 	result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
4888 	if (result) {
4889 		return result;
4890 	}
4891 
4892 #if CONFIG_KXLD
4893 	OSData * mkextExecutableRef  = NULL;        // do not release
4894 	mkextExecutableRef = OSDynamicCast(OSData,
4895 	    getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
4896 
4897 	if (mkextExecutableRef) {
4898 		MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
4899 		    mkextExecutableRef->getBytesNoCopy();
4900 		uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
4901 		if (mkextVersion == MKEXT_VERS_2) {
4902 			mkext2_file_entry * fileinfo =
4903 			    (mkext2_file_entry *)mkextEntryRef->fileinfo;
4904 			uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
4905 			uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
4906 			extractedExecutable = extractMkext2FileData(
4907 				MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
4908 				compressedSize, fullSize);
4909 		} else {
4910 			OSKextLog(this, kOSKextLogErrorLevel |
4911 			    kOSKextLogArchiveFlag,
4912 			    "Kext %s - unknown mkext version 0x%x for executable.",
4913 			    getIdentifierCString(), mkextVersion);
4914 		}
4915 
4916 		/* Regardless of success, remove the mkext executable,
4917 		 * and drop one reference on the mkext.  (setExecutable() does not
4918 		 * replace, it removes, or panics if asked to replace.)
4919 		 */
4920 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4921 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4922 
4923 		if (extractedExecutable && extractedExecutable->getLength()) {
4924 			if (!setExecutable(extractedExecutable.get())) {
4925 				goto finish;
4926 			}
4927 			result = extractedExecutable.get();
4928 		} else {
4929 			goto finish;
4930 		}
4931 	}
4932 
4933 finish:
4934 #endif // CONFIG_KXLD
4935 	return result;
4936 }
4937 
4938 /*********************************************************************
4939 *********************************************************************/
4940 bool
4941 OSKext::isInterface(void)
4942 {
4943 	return flags.interface;
4944 }
4945 
4946 /*********************************************************************
4947 *********************************************************************/
4948 bool
4949 OSKext::isKernel(void)
4950 {
4951 	return this == sKernelKext;
4952 }
4953 
4954 /*********************************************************************
4955 *********************************************************************/
4956 bool
4957 OSKext::isKernelComponent(void)
4958 {
4959 	return flags.kernelComponent ? true : false;
4960 }
4961 
4962 /*********************************************************************
4963 *********************************************************************/
4964 bool
4965 OSKext::isExecutable(void)
4966 {
4967 	return !isKernel() && !isInterface() && declaresExecutable();
4968 }
4969 
4970 /*********************************************************************
4971 * We might want to check this recursively for all dependencies,
4972 * since a subtree of dependencies could get loaded before we hit
4973 * a dependency that isn't safe-boot-loadable.
4974 *
4975 * xxx - Might want to return false if OSBundleEnableKextLogging or
4976 * OSBundleDebugLevel
4977 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4978 * the point except it's usually development drivers, which might
4979 * cause panics on startup, that have those properties). Heh; could
4980 * use a "kx" boot-arg!
4981 *********************************************************************/
4982 bool
4983 OSKext::isLoadableInSafeBoot(void)
4984 {
4985 	bool       result   = false;
4986 	OSString * required = NULL;         // do not release
4987 
4988 	if (isKernel()) {
4989 		result = true;
4990 		goto finish;
4991 	}
4992 
4993 	if (isDriverKit()) {
4994 		result = true;
4995 		goto finish;
4996 	}
4997 
4998 	required = OSDynamicCast(OSString,
4999 	    getPropertyForHostArch(kOSBundleRequiredKey));
5000 	if (!required) {
5001 		goto finish;
5002 	}
5003 	if (required->isEqualTo(kOSBundleRequiredRoot) ||
5004 	    required->isEqualTo(kOSBundleRequiredLocalRoot) ||
5005 	    required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
5006 	    required->isEqualTo(kOSBundleRequiredSafeBoot) ||
5007 	    required->isEqualTo(kOSBundleRequiredConsole)) {
5008 		result = true;
5009 	}
5010 
5011 finish:
5012 	return result;
5013 }
5014 
5015 /*********************************************************************
5016 *********************************************************************/
5017 bool
5018 OSKext::isPrelinked(void)
5019 {
5020 	return flags.prelinked ? true : false;
5021 }
5022 
5023 /*********************************************************************
5024 *********************************************************************/
5025 bool
5026 OSKext::isLoaded(void)
5027 {
5028 	return flags.loaded ? true : false;
5029 }
5030 
5031 /*********************************************************************
5032 *********************************************************************/
5033 bool
5034 OSKext::isStarted(void)
5035 {
5036 	return flags.started ? true : false;
5037 }
5038 
5039 /*********************************************************************
5040 *********************************************************************/
5041 bool
5042 OSKext::isCPPInitialized(void)
5043 {
5044 	return flags.CPPInitialized;
5045 }
5046 
5047 /*********************************************************************
5048 *********************************************************************/
5049 void
5050 OSKext::setCPPInitialized(bool initialized)
5051 {
5052 	flags.CPPInitialized = initialized;
5053 }
5054 
5055 /*********************************************************************
5056 *********************************************************************/
5057 uint32_t
5058 OSKext::getLoadTag(void)
5059 {
5060 	return loadTag;
5061 }
5062 
5063 /*********************************************************************
5064 *********************************************************************/
5065 void
5066 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
5067 {
5068 	if (linkedExecutable) {
5069 		*loadSize = linkedExecutable->getLength();
5070 
5071 		/* If we have a kmod_info struct, calculated the wired size
5072 		 * from that. Otherwise it's the full load size.
5073 		 */
5074 		if (kmod_info) {
5075 			*wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size;
5076 		} else {
5077 			*wiredSize = *loadSize;
5078 		}
5079 	} else {
5080 		*wiredSize = 0;
5081 		*loadSize = 0;
5082 	}
5083 }
5084 
5085 /*********************************************************************
5086 *********************************************************************/
5087 OSSharedPtr<OSData>
5088 OSKext::copyUUID(void)
5089 {
5090 	OSSharedPtr<OSData>          result;
5091 	OSData                     * theExecutable = NULL;        // do not release
5092 	const kernel_mach_header_t * header;
5093 
5094 	/* An interface kext doesn't have a linked executable with an LC_UUID,
5095 	 * we create one when it's linked.
5096 	 */
5097 	if (interfaceUUID) {
5098 		result = interfaceUUID;
5099 		goto finish;
5100 	}
5101 
5102 	if (flags.builtin || isInterface()) {
5103 		return sKernelKext->copyUUID();
5104 	}
5105 
5106 	if (isDriverKit() && infoDict) {
5107 		return driverKitUUID;
5108 	}
5109 
5110 	/* For real kexts, try to get the UUID from the linked executable,
5111 	 * or if is hasn't been linked yet, the unrelocated executable.
5112 	 */
5113 	theExecutable = linkedExecutable.get();
5114 	if (!theExecutable) {
5115 		theExecutable = getExecutable();
5116 	}
5117 
5118 	if (!theExecutable) {
5119 		goto finish;
5120 	}
5121 
5122 	header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
5123 	result = copyMachoUUID(header);
5124 
5125 finish:
5126 	return result;
5127 }
5128 
5129 /*********************************************************************
5130 *********************************************************************/
5131 OSSharedPtr<OSData>
5132 OSKext::copyTextUUID(void)
5133 {
5134 	if (flags.builtin) {
5135 		return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
5136 	}
5137 	return copyUUID();
5138 }
5139 
5140 /*********************************************************************
5141 *********************************************************************/
5142 OSSharedPtr<OSData>
5143 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
5144 {
5145 	OSSharedPtr<OSData>                     result;
5146 	const struct load_command  * load_cmd      = NULL;
5147 	const struct uuid_command  * uuid_cmd      = NULL;
5148 	uint32_t                     i;
5149 
5150 	load_cmd = (const struct load_command *)&header[1];
5151 
5152 	if (header->magic != MH_MAGIC_KERNEL) {
5153 		OSKextLog(NULL,
5154 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
5155 		    "%s: bad header %p",
5156 		    __func__,
5157 		    header);
5158 		goto finish;
5159 	}
5160 
5161 	for (i = 0; i < header->ncmds; i++) {
5162 		if (load_cmd->cmd == LC_UUID) {
5163 			uuid_cmd = (struct uuid_command *)load_cmd;
5164 			result = OSData::withValue(uuid_cmd->uuid);
5165 			goto finish;
5166 		}
5167 		load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
5168 	}
5169 
5170 finish:
5171 	return result;
5172 }
5173 
5174 void
5175 OSKext::setDriverKitUUID(OSData *uuid)
5176 {
5177 	if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
5178 		OSSafeReleaseNULL(uuid);
5179 	}
5180 }
5181 
5182 OSData *
5183 OSKext::getDextUniqueID(void)
5184 {
5185 	if (isDriverKit() && dextUniqueID != NULL) {
5186 		return dextUniqueID.get();
5187 	}
5188 
5189 	return NULL;
5190 }
5191 
5192 /*
5193  * In case a DextUniqueID exists this function returns
5194  * an allocated char* with the hexadecimal represantition of
5195  * DextUniqueID.
5196  * The returned pinter needs to be freed with kfree_data, the
5197  * size of the allocated buffer is returned in size.
5198  */
5199 static const char *
5200 getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size)
5201 {
5202 	if (dextUniqueID != NULL) {
5203 		char *s_buffer = NULL;
5204 		unsigned int d_length = dextUniqueID->getLength();
5205 		/*
5206 		 * We are converting in hex, so for every byte we will have
5207 		 * 2 hex chars and one last \0.
5208 		 */
5209 		unsigned int s_length = d_length * 2 + 1;
5210 		s_buffer = (char *) kalloc_data(s_length, Z_WAITOK_ZERO);
5211 
5212 		char *uid = (char*) dextUniqueID->getBytesNoCopy();
5213 		int cpos = 0;
5214 		for (unsigned int i = 0; i < d_length && cpos < (s_length - 1); i++) {
5215 			int ret = snprintf(s_buffer + cpos, s_length - cpos - 1, "%02X", uid[i]);
5216 			if (ret <= 0) {
5217 				break;
5218 			}
5219 			cpos += ret;
5220 		}
5221 		*size = s_length;
5222 
5223 		return s_buffer;
5224 	}
5225 
5226 	return NULL;
5227 }
5228 
5229 /*
5230  * Atomically swaps the olddext with newdext.
5231  * olddext will be unloaded, so it might be freed
5232  * after this call unless it was previously retained.
5233  *
5234  * If newdext is NULL, this unloads olddext and does not perform an upgrade
5235  */
5236 void
5237 OSKext::replaceDextInternal(OSKext *olddext, OSKext *newdext)
5238 {
5239 	OSReturn result;
5240 	const OSSymbol * dextID = olddext->getIdentifier();
5241 	OSSharedPtr<OSArray> new_personalities;
5242 	OSSharedPtr<OSString> kextIdentifier;
5243 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5244 	assert(lock_held);
5245 
5246 	// The old dext will be unloaded and release dextID, so we need to retain dextID here
5247 	dextID->retain();
5248 
5249 	if (newdext != NULL) {
5250 		__assert_only bool eq = dextID->isEqualTo(newdext->getIdentifier());
5251 		assert(eq);
5252 	}
5253 
5254 	if (newdext != NULL) {
5255 		/*
5256 		 * Swap the catalog personalities.
5257 		 */
5258 		new_personalities = newdext->copyPersonalitiesArray();
5259 		olddext->updatePersonalitiesInCatalog(new_personalities.get());
5260 	}
5261 
5262 	/*
5263 	 * Unload the dext.
5264 	 */
5265 	result = olddext->unload();
5266 	if (result != kOSReturnSuccess) {
5267 		OSKextLog(NULL,
5268 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5269 		    "Cannot unload dext for upgrade %s: %d\n",
5270 		    dextID->getCStringNoCopy(), result);
5271 	}
5272 
5273 	if (newdext != NULL) {
5274 		/*
5275 		 * Swap the dexts on the OSKext dictionary.
5276 		 * This might free the dext.
5277 		 */
5278 		sKextsByID->setObject(dextID, newdext);
5279 	} else {
5280 		/*
5281 		 * Remove the old dext
5282 		 */
5283 		removeKext(olddext, true);
5284 	}
5285 
5286 	/*
5287 	 * Inform userspace.
5288 	 */
5289 	if (newdext != NULL) {
5290 		result = notifyDextUpgrade(OSDynamicCast(OSString, dextID), newdext->getDextUniqueID());
5291 		if (result != kOSReturnSuccess) {
5292 			OSKextLog(NULL,
5293 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5294 			    "Cannot send upgrade notification for %s\n",
5295 			    dextID->getCStringNoCopy());
5296 		}
5297 	} else {
5298 		// notify dext removal
5299 		queueKextNotification(kKextRequestPredicateUnloadNotification, OSDynamicCast(OSString, dextID));
5300 	}
5301 
5302 	OSSafeReleaseNULL(dextID);
5303 }
5304 
5305 /*
5306  * To be called with sKextLock held.
5307  * NOTE: this could unload the olddext.
5308  */
5309 bool
5310 OSKext::upgradeDext(OSKext *olddext, OSKext *newdext)
5311 {
5312 	const char * dextIDCS = newdext->getIdentifierCString();
5313 	__assert_only bool old_isDext = olddext->isDriverKit();
5314 	__assert_only bool new_isDext = newdext->isDriverKit();
5315 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5316 
5317 	assert(old_isDext && new_isDext);
5318 	assert(lock_held);
5319 
5320 	/*
5321 	 * New dext and old dext have the same ID.
5322 	 * We use this ID as key on the OSKext
5323 	 * dictionarys/arrays.
5324 	 */
5325 	const OSSymbol * dextID = newdext->getIdentifier();
5326 	__assert_only bool eq = dextID->isEqualTo(olddext->getIdentifier());
5327 	assert(eq);
5328 
5329 	/*
5330 	 * Set this OSKect as to update.
5331 	 * Note that this flags will never be removed once set.
5332 	 * When a OSKext is marked, it will be substitued by a new
5333 	 * OSKext, and every subsystem having a reference on this
5334 	 * OSKext need to know they have check if they can use
5335 	 * this OSKext or look for a new one.
5336 	 */
5337 	olddext->flags.dextToReplace = 1;
5338 
5339 	/*
5340 	 * Check if the current OSKext has any
5341 	 * userspace processes launched.
5342 	 * In this case we cannot upgrade and we have to
5343 	 * delay the upgrade until all processes
5344 	 * are done.
5345 	 */
5346 	if (olddext->dextLaunchedCount == 0) {
5347 		/*
5348 		 * Be sure that if there are no launched dexts, no
5349 		 * pending upgrades exist.
5350 		 * This is an error if it happens, as the decrement
5351 		 * should have removed the dext from sDriverKitToUpgradeByID
5352 		 * in case it reached 0.
5353 		 */
5354 		OSObject *pending_upgdare = sDriverKitToUpgradeByID->getObject(dextID);
5355 		if (pending_upgdare != NULL) {
5356 			OSKextLog(NULL,
5357 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5358 			    "Pending upgrade found for %s but dextLaunchedCount is 0!\n",
5359 			    dextIDCS);
5360 			goto out;
5361 		}
5362 
5363 		replaceDextInternal(olddext, newdext);
5364 		return true;
5365 	}
5366 
5367 out:
5368 
5369 	/*
5370 	 * Delay the upgrade.
5371 	 * Make the new dext available in sDriverKitToUpgradeByID.
5372 	 * In case there was already a pending upgrade, this will
5373 	 * overwrite it.
5374 	 */
5375 	sDriverKitToUpgradeByID->setObject(dextID, newdext);
5376 	return false;
5377 }
5378 
5379 /*
5380  * To be called with sKextLock held.
5381  * NOTE: this could unload the dext.
5382  */
5383 bool
5384 OSKext::removeDext(OSKext *dext)
5385 {
5386 	__assert_only bool dext_isDext = dext->isDriverKit();
5387 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5388 	IOReturn result;
5389 
5390 	assert(dext_isDext);
5391 	assert(lock_held);
5392 
5393 	/*
5394 	 * Set this OSKext to be unloaded when all running instances exit.
5395 	 */
5396 	dext->flags.dextToReplace = 1;
5397 
5398 	result = gIOCatalogue->terminateDriversForModule(
5399 		dext->getIdentifierCString(), /* unload */ false, /* asynchronous */ true);
5400 	if (result != kOSReturnSuccess) {
5401 		OSKextLog(dext,
5402 		    kOSKextLogErrorLevel |
5403 		    kOSKextLogKextBookkeepingFlag,
5404 		    "%s services failed to terminate - 0x%x.",
5405 		    dext->getIdentifierCString(), result);
5406 	}
5407 
5408 	dext->removePersonalitiesFromCatalog();
5409 	sDriverKitToUpgradeByID->removeObject(dext->getIdentifier());
5410 
5411 	/*
5412 	 * Check if the current OSKext has any
5413 	 * userspace processes launched.
5414 	 * In this case we cannot unload and we have to
5415 	 * delay the unload until all processes
5416 	 * are done.
5417 	 */
5418 	if (dext->dextLaunchedCount == 0) {
5419 		replaceDextInternal(dext, NULL);
5420 		return true;
5421 	}
5422 
5423 	return false;
5424 }
5425 
5426 bool
5427 OSKext::incrementDextLaunchCount(OSKext *dext, OSData *dextUniqueIDToMatch)
5428 {
5429 	bool ret = false;
5430 	__assert_only bool isDext = dext->isDriverKit();
5431 	assert(isDext);
5432 
5433 	const char * dextIDCS = dext->getIdentifierCString();
5434 	OSData *myDextUniqueID = dext->getDextUniqueID();
5435 
5436 	if (!myDextUniqueID || !dextUniqueIDToMatch) {
5437 		OSKextLog(dext,
5438 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5439 		    "Cannot find dext UniqueID for %s, cannot increment dext launches\n",
5440 		    dextIDCS);
5441 		return ret;
5442 	}
5443 
5444 	unsigned int dextUniqueIDCStringSize = 0, dextUniqueIDToMatchCStringSize = 0;
5445 	const char *dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
5446 	const char *dextUniqueIDToMatchCString = getDextUniqueIDCString(dextUniqueIDToMatch, &dextUniqueIDToMatchCStringSize);
5447 	assert(dextUniqueIDCString != NULL);
5448 	assert(dextUniqueIDToMatchCString != NULL);
5449 
5450 	IORecursiveLockLock(sKextLock);
5451 
5452 	/*
5453 	 * Check that the dext we are referencing is the same
5454 	 * looked for the match.
5455 	 */
5456 	if (myDextUniqueID->isEqualTo(dextUniqueIDToMatch)) {
5457 		if (dext->flags.dextToReplace == 0 || dext->dextLaunchedCount > 0) {
5458 			if (dext->dextLaunchedCount == kOSKextMaxDextLaunchedCount) {
5459 				OSKextLog(dext,
5460 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5461 				    "Too many dexts launched for %s UniqueID %s\n",
5462 				    dextIDCS, dextUniqueIDCString);
5463 			} else {
5464 				dext->dextLaunchedCount++;
5465 				ret = true;
5466 
5467 				OSKextLog(dext,
5468 				    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5469 				    "New dext launched for  %s UniqueID %s",
5470 				    dextIDCS, dextUniqueIDCString);
5471 			}
5472 		} else {
5473 			OSKextLog(dext,
5474 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5475 			    "Dext %s UniqueID %s requires update, cannot launch a new dext\n",
5476 			    dextIDCS, dextUniqueIDCString);
5477 		}
5478 	} else {
5479 		OSKextLog(dext,
5480 		    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5481 		    "Dext %s: UniqueID %s does not match UniqueID looked for %s, cannot launch a new dext\n",
5482 		    dextIDCS, dextUniqueIDCString, dextUniqueIDToMatchCString);
5483 	}
5484 
5485 	IORecursiveLockUnlock(sKextLock);
5486 
5487 	if (dextUniqueIDCString != NULL) {
5488 		kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
5489 	}
5490 	if (dextUniqueIDToMatchCString != NULL) {
5491 		kfree_data(dextUniqueIDToMatchCString, dextUniqueIDToMatchCStringSize);
5492 	}
5493 	return ret;
5494 }
5495 
5496 bool
5497 OSKext::decrementDextLaunchCount(OSString *bundleID)
5498 {
5499 	bool ret = false;
5500 	const char * dextIDCS;
5501 	OSData *myDextUniqueID;
5502 	unsigned int dextUniqueIDCStringSize = 0;
5503 	const char * dextUniqueIDCString = NULL;
5504 	OSKext* dext = NULL;
5505 
5506 	if (!bundleID) {
5507 		return ret;
5508 	}
5509 	dextIDCS = bundleID->getCStringNoCopy();
5510 
5511 	IORecursiveLockLock(sKextLock);
5512 
5513 	/*
5514 	 * Look for the dext with the bundle it. This
5515 	 * call is triggered only if a previous increment was
5516 	 * performed. It means that the dext could have not
5517 	 * been upgraded as its dextLaunchedCount was at least 1.
5518 	 * Because of this it still needs to be available
5519 	 * in sKextsByID.
5520 	 */
5521 	dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIDCS));
5522 	if (!dext || !dext->isDriverKit()) {
5523 		OSKextLog(NULL,
5524 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5525 		    "Cannot find dext for %s, cannot decrement dext launches\n",
5526 		    dextIDCS);
5527 
5528 		goto out_locked;
5529 	}
5530 
5531 	myDextUniqueID = dext->getDextUniqueID();
5532 	if (!myDextUniqueID) {
5533 		OSKextLog(dext,
5534 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5535 		    "Cannot find dext UniqueID for %s, cannot decrement dext launches\n",
5536 		    dextIDCS);
5537 
5538 		goto out_locked;
5539 	}
5540 	dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
5541 	assert(dextUniqueIDCString != NULL);
5542 
5543 	if (dext->dextLaunchedCount == 0) {
5544 		OSKextLog(dext,
5545 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5546 		    "Over decrementing dext launch for %s UniqueID %s\n",
5547 		    dextIDCS, dextUniqueIDCString);
5548 
5549 		goto out_locked;
5550 	}
5551 
5552 	dext->dextLaunchedCount--;
5553 
5554 	OSKextLog(dext,
5555 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5556 	    "Dext terminated for %s UniqueID %s",
5557 	    dextIDCS, dextUniqueIDCString);
5558 
5559 	if (dext->dextLaunchedCount == 0 && dext->flags.dextToReplace == 1) {
5560 		/*
5561 		 * Find the upgraded dext.
5562 		 */
5563 		OSKext *newdext = OSDynamicCast(OSKext, sDriverKitToUpgradeByID->getObject(dextIDCS));
5564 		if (newdext) {
5565 			OSKextLog(dext,
5566 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5567 			    "Dext upgrade for %s UniqueID %s",
5568 			    dextIDCS, dextUniqueIDCString);
5569 			replaceDextInternal(dext, newdext);
5570 			/* NOTE dext could have been freed past this point */
5571 
5572 			sDriverKitToUpgradeByID->removeObject(dextIDCS);
5573 		} else {
5574 			OSKextLog(dext,
5575 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5576 			    "Dext unload for %s UniqueID %s",
5577 			    dextIDCS, dextUniqueIDCString);
5578 			replaceDextInternal(dext, NULL);
5579 		}
5580 
5581 		ret = true;
5582 	}
5583 out_locked:
5584 	IORecursiveLockUnlock(sKextLock);
5585 
5586 	if (dextUniqueIDCString != NULL) {
5587 		kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
5588 	}
5589 
5590 	return ret;
5591 }
5592 
5593 /*********************************************************************
5594 *********************************************************************/
5595 #if defined (__arm__)
5596 #include <arm/arch.h>
5597 #endif
5598 
5599 #if   defined (__x86_64__)
5600 #define ARCHNAME "x86_64"
5601 #elif defined (__arm64__)
5602 #define ARCHNAME "arm64"
5603 #elif defined (__arm__)
5604 
5605 #if defined (__ARM_ARCH_7S__)
5606 #define ARCHNAME "armv7s"
5607 #elif defined (__ARM_ARCH_7F__)
5608 #define ARCHNAME "armv7f"
5609 #elif defined (__ARM_ARCH_7K__)
5610 #define ARCHNAME "armv7k"
5611 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
5612 #define ARCHNAME "armv7"
5613 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
5614 #define ARCHNAME "armv6"
5615 #endif
5616 
5617 #elif defined (__arm64__)
5618 #define ARCHNAME "arm64"
5619 #else
5620 #error architecture not supported
5621 #endif
5622 
5623 #define ARCH_SEPARATOR_CHAR  '_'
5624 
5625 static char *
5626 makeHostArchKey(const char * key, size_t * keySizeOut)
5627 {
5628 	char     * result = NULL;
5629 	size_t     keyLength = strlen(key);
5630 	size_t     keySize;
5631 
5632 	/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
5633 	 */
5634 	keySize = 1 + 1 + keyLength + strlen(ARCHNAME);
5635 	result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
5636 
5637 	if (!result) {
5638 		goto finish;
5639 	}
5640 	strlcpy(result, key, keySize);
5641 	result[keyLength++] = ARCH_SEPARATOR_CHAR;
5642 	result[keyLength] = '\0';
5643 	strlcat(result, ARCHNAME, keySize);
5644 	*keySizeOut = keySize;
5645 
5646 finish:
5647 	return result;
5648 }
5649 
5650 /*********************************************************************
5651 *********************************************************************/
5652 OSObject *
5653 OSKext::getPropertyForHostArch(const char * key)
5654 {
5655 	OSObject * result           = NULL;// do not release
5656 	size_t     hostArchKeySize  = 0;
5657 	char     * hostArchKey      = NULL;// must kfree
5658 
5659 	if (!key || !infoDict) {
5660 		goto finish;
5661 	}
5662 
5663 	/* Some properties are not allowed to be arch-variant:
5664 	 * - Any CFBundle... property.
5665 	 * - OSBundleIsInterface.
5666 	 * - OSKernelResource.
5667 	 */
5668 	if (STRING_HAS_PREFIX(key, "OS") ||
5669 	    STRING_HAS_PREFIX(key, "IO")) {
5670 		hostArchKey = makeHostArchKey(key, &hostArchKeySize);
5671 		if (!hostArchKey) {
5672 			OSKextLog(/* kext (this isn't about a kext) */ NULL,
5673 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
5674 			    "Allocation failure.");
5675 			goto finish;
5676 		}
5677 		result = infoDict->getObject(hostArchKey);
5678 	}
5679 
5680 	if (!result) {
5681 		result = infoDict->getObject(key);
5682 	}
5683 
5684 finish:
5685 	if (hostArchKey) {
5686 		kfree_data(hostArchKey, hostArchKeySize);
5687 	}
5688 	return result;
5689 }
5690 
5691 #if PRAGMA_MARK
5692 #pragma mark Load/Start/Stop/Unload
5693 #endif
5694 
5695 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
5696 
5697 /*********************************************************************
5698 * sExcludeListByID is a dictionary with keys / values of:
5699 *  key = bundleID string of kext we will not allow to load
5700 *  value = version string(s) of the kext that is to be denied loading.
5701 *      The version strings can be comma delimited.  For example if kext
5702 *      com.foocompany.fookext has two versions that we want to deny
5703 *      loading then the version strings might look like:
5704 *      1.0.0, 1.0.1
5705 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
5706 *      not load the kext.
5707 *
5708 *      Value may also be in the form of "LE 2.0.0" (version numbers
5709 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
5710 *      number less than 2.0.0 will not load)
5711 *
5712 *      NOTE - we cannot use the characters "<=" or "<" because we have code
5713 *      that serializes plists and treats '<' as a special character.
5714 *********************************************************************/
5715 bool
5716 OSKext::isInExcludeList(void)
5717 {
5718 	OSString *      versionString           = NULL;        // do not release
5719 	char *          versionCString          = NULL;        // do not free
5720 	size_t          i;
5721 	boolean_t       wantLessThan = false;
5722 	boolean_t       wantLessThanEqualTo = false;
5723 	boolean_t       isInExcludeList = true;
5724 	char            myBuffer[32];
5725 
5726 	IORecursiveLockLock(sKextLock);
5727 
5728 	if (!sExcludeListByID) {
5729 		isInExcludeList = false;
5730 	} else {
5731 		/* look up by bundleID in our exclude list and if found get version
5732 		 * string (or strings) that we will not allow to load
5733 		 */
5734 		versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get()));
5735 		if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
5736 			isInExcludeList = false;
5737 		}
5738 	}
5739 
5740 	IORecursiveLockUnlock(sKextLock);
5741 
5742 	if (!isInExcludeList) {
5743 		return false;
5744 	}
5745 
5746 	/* parse version strings */
5747 	versionCString = (char *) versionString->getCStringNoCopy();
5748 
5749 	/* look for "LT" or "LE" form of version string, must be in first two
5750 	 * positions.
5751 	 */
5752 	if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
5753 		wantLessThan = true;
5754 		versionCString += 2;
5755 	} else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
5756 		wantLessThanEqualTo = true;
5757 		versionCString += 2;
5758 	}
5759 
5760 	for (i = 0; *versionCString != 0x00; versionCString++) {
5761 		/* skip whitespace */
5762 		if (isWhiteSpace(*versionCString)) {
5763 			continue;
5764 		}
5765 
5766 		/* peek ahead for version string separator or null terminator */
5767 		if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
5768 			/* OK, we have a version string */
5769 			myBuffer[i++] = *versionCString;
5770 			myBuffer[i] = 0x00;
5771 
5772 			OSKextVersion excludeVers;
5773 			excludeVers = OSKextParseVersionString(myBuffer);
5774 
5775 			if (wantLessThanEqualTo) {
5776 				if (version <= excludeVers) {
5777 					return true;
5778 				}
5779 			} else if (wantLessThan) {
5780 				if (version < excludeVers) {
5781 					return true;
5782 				}
5783 			} else if (version == excludeVers) {
5784 				return true;
5785 			}
5786 
5787 			/* reset for the next (if any) version string */
5788 			i = 0;
5789 			wantLessThan = false;
5790 			wantLessThanEqualTo = false;
5791 		} else {
5792 			/* save valid version character */
5793 			myBuffer[i++] = *versionCString;
5794 
5795 			/* make sure bogus version string doesn't overrun local buffer */
5796 			if (i >= sizeof(myBuffer)) {
5797 				break;
5798 			}
5799 		}
5800 	}
5801 
5802 	return false;
5803 }
5804 
5805 /*********************************************************************
5806 * sNonLoadableKextsByID is a dictionary with keys / values of:
5807 *  key = bundleID string of kext we will not allow to load
5808 *  value = boolean (true == loadable, false == not loadable)
5809 *
5810 *  Only kexts which are in the AuxKC will be marked as "not loadble,"
5811 *  i.e., the value for the kext's bundleID will be false. All kexts in
5812 *  the primary and system KCs will always be marked as "loadable."
5813 *
5814 *  This list ultimately comes from kexts which have been uninstalled
5815 *  in user space by deleting the kext from disk, but which have not
5816 *  yet been removed from the AuxKC. Because the user could choose to
5817 *  re-install the exact same version of the kext, we need to keep
5818 *  a dictionary of boolean values so that user space only needs to
5819 *  keep a simple list of "uninstalled" or "missing" bundles. When
5820 *  a bundle is re-installed, the iokit daemon can use the
5821 *  AucKCBundleAvailable  predicate to set the individual kext's
5822 *  availability to true.
5823 *********************************************************************/
5824 bool
5825 OSKext::isLoadable(void)
5826 {
5827 	bool isLoadable = true;
5828 
5829 	if (kc_type != KCKindAuxiliary) {
5830 		/* this filtering only applies to kexts in the auxkc */
5831 		return true;
5832 	}
5833 
5834 	IORecursiveLockLock(sKextLock);
5835 
5836 	if (sNonLoadableKextsByID) {
5837 		/* look up by bundleID in our exclude list and if found get version
5838 		 * string (or strings) that we will not allow to load
5839 		 */
5840 		OSBoolean *loadableVal;
5841 		loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get()));
5842 		if (loadableVal && !loadableVal->getValue()) {
5843 			isLoadable = false;
5844 		}
5845 	}
5846 	IORecursiveLockUnlock(sKextLock);
5847 
5848 	return isLoadable;
5849 }
5850 
5851 /*********************************************************************
5852 *********************************************************************/
5853 /* static */
5854 OSReturn
5855 OSKext::loadKextWithIdentifier(
5856 	const char       * kextIdentifierCString,
5857 	Boolean            allowDeferFlag,
5858 	Boolean            delayAutounloadFlag,
5859 	OSKextExcludeLevel startOpt,
5860 	OSKextExcludeLevel startMatchingOpt,
5861 	OSArray          * personalityNames)
5862 {
5863 	OSReturn   result         = kOSReturnError;
5864 	OSSharedPtr<OSString> kextIdentifier;
5865 
5866 	kextIdentifier = OSString::withCString(kextIdentifierCString);
5867 	if (!kextIdentifier) {
5868 		result = kOSKextReturnNoMemory;
5869 		goto finish;
5870 	}
5871 	result = OSKext::loadKextWithIdentifier(kextIdentifier.get(),
5872 	    NULL /* kextRef */,
5873 	    allowDeferFlag, delayAutounloadFlag,
5874 	    startOpt, startMatchingOpt, personalityNames);
5875 
5876 finish:
5877 	return result;
5878 }
5879 
5880 OSReturn
5881 OSKext::loadKextWithIdentifier(
5882 	OSString          * kextIdentifier,
5883 	OSSharedPtr<OSObject>         &kextRef,
5884 	Boolean             allowDeferFlag,
5885 	Boolean             delayAutounloadFlag,
5886 	OSKextExcludeLevel  startOpt,
5887 	OSKextExcludeLevel  startMatchingOpt,
5888 	OSArray           * personalityNames)
5889 {
5890 	OSObject * kextRefRaw = NULL;
5891 	OSReturn result;
5892 
5893 	result = loadKextWithIdentifier(kextIdentifier,
5894 	    &kextRefRaw,
5895 	    allowDeferFlag,
5896 	    delayAutounloadFlag,
5897 	    startOpt,
5898 	    startMatchingOpt,
5899 	    personalityNames);
5900 	if ((kOSReturnSuccess == result) && kextRefRaw) {
5901 		kextRef.reset(kextRefRaw, OSNoRetain);
5902 	}
5903 	return result;
5904 }
5905 
5906 /*********************************************************************
5907 *********************************************************************/
5908 OSReturn
5909 OSKext::loadKextWithIdentifier(
5910 	OSString          * kextIdentifier,
5911 	OSObject         ** kextRef,
5912 	Boolean             allowDeferFlag,
5913 	Boolean             delayAutounloadFlag,
5914 	OSKextExcludeLevel  startOpt,
5915 	OSKextExcludeLevel  startMatchingOpt,
5916 	OSArray           * personalityNames)
5917 {
5918 	OSReturn          result               = kOSReturnError;
5919 	OSReturn          pingResult           = kOSReturnError;
5920 	OSKext          * theKext              = NULL;        // do not release
5921 	OSSharedPtr<OSDictionary>   loadRequest;
5922 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5923 
5924 	if (kextRef) {
5925 		*kextRef = NULL;
5926 	}
5927 
5928 	IORecursiveLockLock(sKextLock);
5929 
5930 	if (!kextIdentifier) {
5931 		result = kOSKextReturnInvalidArgument;
5932 		goto finish;
5933 	}
5934 
5935 	OSKext::recordIdentifierRequest(kextIdentifier);
5936 
5937 	theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
5938 	if (!theKext) {
5939 		if (!allowDeferFlag) {
5940 			OSKextLog(/* kext */ NULL,
5941 			    kOSKextLogErrorLevel |
5942 			    kOSKextLogLoadFlag,
5943 			    "Can't load kext %s - not found.",
5944 			    kextIdentifier->getCStringNoCopy());
5945 			goto finish;
5946 		}
5947 
5948 		if (!sKernelRequestsEnabled) {
5949 			OSKextLog(theKext,
5950 			    kOSKextLogErrorLevel |
5951 			    kOSKextLogLoadFlag,
5952 			    "Can't load kext %s - requests to user space are disabled.",
5953 			    kextIdentifier->getCStringNoCopy());
5954 			result = kOSKextReturnDisabled;
5955 			goto finish;
5956 		}
5957 
5958 		/* Create a new request unless one is already sitting
5959 		 * in sKernelRequests for this bundle identifier
5960 		 */
5961 		kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5962 		if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5963 			result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
5964 			    loadRequest);
5965 			if (result != kOSReturnSuccess) {
5966 				goto finish;
5967 			}
5968 			if (!_OSKextSetRequestArgument(loadRequest.get(),
5969 			    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
5970 				result = kOSKextReturnNoMemory;
5971 				goto finish;
5972 			}
5973 			if (!sKernelRequests->setObject(loadRequest.get())) {
5974 				result = kOSKextReturnNoMemory;
5975 				goto finish;
5976 			}
5977 
5978 			if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
5979 				result = kOSKextReturnNoMemory;
5980 				goto finish;
5981 			}
5982 
5983 			OSKextLog(theKext,
5984 			    kOSKextLogDebugLevel |
5985 			    kOSKextLogLoadFlag,
5986 			    "Kext %s not found; queued load request to user space.",
5987 			    kextIdentifier->getCStringNoCopy());
5988 		}
5989 
5990 		pingResult = OSKext::pingIOKitDaemon();
5991 		if (pingResult == kOSKextReturnDisabled) {
5992 			OSKextLog(/* kext */ NULL,
5993 			    ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
5994 			    kOSKextLogLoadFlag,
5995 			    "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.",
5996 			    kextIdentifier->getCStringNoCopy());
5997 		}
5998 
5999 		result = kOSKextReturnDeferred;
6000 		goto finish;
6001 	}
6002 
6003 	result = theKext->load(startOpt, startMatchingOpt, personalityNames);
6004 
6005 	if (result != kOSReturnSuccess) {
6006 		OSKextLog(theKext,
6007 		    kOSKextLogErrorLevel |
6008 		    kOSKextLogLoadFlag,
6009 		    "Failed to load kext %s (error 0x%x).",
6010 		    kextIdentifier->getCStringNoCopy(), (int)result);
6011 
6012 		if (theKext->kc_type == KCKindUnknown) {
6013 			OSKext::removeKext(theKext,
6014 			    /* terminateService/removePersonalities */ true);
6015 		}
6016 		goto finish;
6017 	}
6018 
6019 	if (delayAutounloadFlag) {
6020 		OSKextLog(theKext,
6021 		    kOSKextLogProgressLevel |
6022 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6023 		    "Setting delayed autounload for %s.",
6024 		    kextIdentifier->getCStringNoCopy());
6025 		theKext->flags.delayAutounload = 1;
6026 	}
6027 
6028 finish:
6029 	if ((kOSReturnSuccess == result) && kextRef) {
6030 		*kextRef = theKext;
6031 		theKext->matchingRefCount++;
6032 		theKext->retain();
6033 	}
6034 
6035 	IORecursiveLockUnlock(sKextLock);
6036 
6037 	return result;
6038 }
6039 
6040 /*********************************************************************
6041 *********************************************************************/
6042 /* static */
6043 OSReturn
6044 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict)
6045 {
6046 	OSReturn  result = kOSReturnError;
6047 
6048 	OSBoolean *delayAutounloadBool     = NULL; // do not release
6049 	OSNumber  *startKextExcludeNum     = NULL; // do not release
6050 	OSNumber  *startMatchingExcludeNum = NULL; // do not release
6051 	OSArray   *personalityNames        = NULL; // do not release
6052 
6053 	/*
6054 	 * Default values for these options:
6055 	 *      regular autounload behavior
6056 	 *      start the kext
6057 	 *      send all personalities to the catalog
6058 	 */
6059 	Boolean            delayAutounload           = false;
6060 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
6061 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone;
6062 
6063 	IORecursiveLockLock(sKextLock);
6064 
6065 	OSKextLog(/* kext */ NULL,
6066 	    kOSKextLogDebugLevel |
6067 	    kOSKextLogIPCFlag,
6068 	    "Received kext KC load request from user space.");
6069 
6070 	/* Regardless of processing, the fact that we have gotten here means some
6071 	 * user-space program is up and talking to us, so we'll switch our kext
6072 	 * registration to reflect that.
6073 	 */
6074 	if (!sUserLoadsActive) {
6075 		OSKextLog(/* kext */ NULL,
6076 		    kOSKextLogProgressLevel |
6077 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6078 		    "Switching to late startup (user-space) kext loading policy.");
6079 		sUserLoadsActive = true;
6080 	}
6081 
6082 	delayAutounloadBool = OSDynamicCast(OSBoolean,
6083 	    _OSKextGetRequestArgument(requestDict,
6084 	    kKextRequestArgumentDelayAutounloadKey));
6085 	startKextExcludeNum = OSDynamicCast(OSNumber,
6086 	    _OSKextGetRequestArgument(requestDict,
6087 	    kKextRequestArgumentStartExcludeKey));
6088 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
6089 	    _OSKextGetRequestArgument(requestDict,
6090 	    kKextRequestArgumentStartMatchingExcludeKey));
6091 	personalityNames = OSDynamicCast(OSArray,
6092 	    _OSKextGetRequestArgument(requestDict,
6093 	    kKextRequestArgumentPersonalityNamesKey));
6094 
6095 	if (delayAutounloadBool) {
6096 		delayAutounload = delayAutounloadBool->getValue();
6097 	}
6098 	if (startKextExcludeNum) {
6099 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
6100 	}
6101 	if (startMatchingExcludeNum) {
6102 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
6103 	}
6104 
6105 	OSKextLog(/* kext */ NULL,
6106 	    kOSKextLogProgressLevel |
6107 	    kOSKextLogIPCFlag,
6108 	    "Received request from user space to load KC kext %s.",
6109 	    theKext->getIdentifierCString());
6110 
6111 	/* this could be in the Auxiliary KC, so record the load request */
6112 	OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier()));
6113 
6114 	/*
6115 	 * Load the kext
6116 	 */
6117 	result = theKext->load(startKextExcludeLevel,
6118 	    startMatchingExcludeLevel, personalityNames);
6119 
6120 	if (result != kOSReturnSuccess) {
6121 		OSKextLog(theKext,
6122 		    kOSKextLogErrorLevel |
6123 		    kOSKextLogLoadFlag,
6124 		    "Failed to load kext %s (error 0x%x).",
6125 		    theKext->getIdentifierCString(), (int)result);
6126 
6127 		OSKext::removeKext(theKext,
6128 		    /* terminateService/removePersonalities */ true);
6129 		goto finish;
6130 	} else {
6131 		OSKextLog(theKext,
6132 		    kOSKextLogProgressLevel |
6133 		    kOSKextLogLoadFlag,
6134 		    "Kext %s Loaded successfully from %s KC",
6135 		    theKext->getIdentifierCString(), theKext->getKCTypeString());
6136 	}
6137 
6138 	if (delayAutounload) {
6139 		OSKextLog(theKext,
6140 		    kOSKextLogProgressLevel |
6141 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6142 		    "Setting delayed autounload for %s.",
6143 		    theKext->getIdentifierCString());
6144 		theKext->flags.delayAutounload = 1;
6145 	}
6146 
6147 finish:
6148 	IORecursiveLockUnlock(sKextLock);
6149 
6150 	return result;
6151 }
6152 
6153 /*********************************************************************
6154 *********************************************************************/
6155 /* static */
6156 OSReturn
6157 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict)
6158 {
6159 	OSReturn  result = kOSReturnError;
6160 	OSDictionary *anInfoDict = NULL; // do not release
6161 
6162 	anInfoDict = OSDynamicCast(OSDictionary,
6163 	    _OSKextGetRequestArgument(requestDict,
6164 	    kKextRequestArgumentCodelessInfoKey));
6165 	if (anInfoDict == NULL) {
6166 		OSKextLog(/* kext */ NULL,
6167 		    kOSKextLogErrorLevel |
6168 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6169 		    "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.",
6170 		    kextIdentifier->getCStringNoCopy());
6171 		return kOSKextReturnInvalidArgument;
6172 	}
6173 
6174 	IORecursiveLockLock(sKextLock);
6175 
6176 	OSKextLog(/* kext */ NULL,
6177 	    kOSKextLogProgressLevel |
6178 	    kOSKextLogIPCFlag,
6179 	    "Received request from user space to load codeless kext %s.",
6180 	    kextIdentifier->getCStringNoCopy());
6181 
6182 	{
6183 		// instantiate a new kext, and don't hold a reference
6184 		// (the kext subsystem will hold one implicitly)
6185 		OSKextInitResult ret;
6186 		OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict, &ret);
6187 		if (!newKext) {
6188 			/*
6189 			 * We might have failed to create a new OSKext
6190 			 * because the old one should still be used.
6191 			 * Check if that is the case.
6192 			 */
6193 			if (ret != kOSKextInitFailure) {
6194 				result = kOSReturnSuccess;
6195 				goto finish;
6196 			}
6197 			OSKextLog(/* kext */ NULL,
6198 			    kOSKextLogErrorLevel |
6199 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6200 			    "Could not instantiate codeless kext.");
6201 			result = kOSKextReturnNotLoadable;
6202 			goto finish;
6203 		}
6204 		if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) {
6205 			OSKextLog(/* kext */ NULL,
6206 			    kOSKextLogErrorLevel |
6207 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6208 			    "Codeless kext identifiers don't match '%s' != '%s'",
6209 			    kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString());
6210 
6211 			OSKext::removeKext(newKext.get(), false);
6212 			result = kOSKextReturnInvalidArgument;
6213 			goto finish;
6214 		}
6215 
6216 		/* Record the request for the codeless kext */
6217 		OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier()));
6218 
6219 		result = kOSReturnSuccess;
6220 		/* Send the kext's personalities to the IOCatalog. This is an explicit load. */
6221 		result = newKext->sendPersonalitiesToCatalog(true, NULL);
6222 	}
6223 
6224 finish:
6225 	IORecursiveLockUnlock(sKextLock);
6226 
6227 	return result;
6228 }
6229 
6230 /*********************************************************************
6231 *********************************************************************/
6232 /* static */
6233 void
6234 OSKext::dropMatchingReferences(
6235 	OSSet * kexts)
6236 {
6237 	IORecursiveLockLock(sKextLock);
6238 	kexts->iterateObjects(^bool (OSObject * obj) {
6239 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
6240 		if (!thisKext) {
6241 		        return false;
6242 		}
6243 		thisKext->matchingRefCount--;
6244 		return false;
6245 	});
6246 	IORecursiveLockUnlock(sKextLock);
6247 }
6248 
6249 /*********************************************************************
6250 *********************************************************************/
6251 /* static */
6252 void
6253 OSKext::recordIdentifierRequest(
6254 	OSString * kextIdentifier)
6255 {
6256 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
6257 	bool             fail                 = false;
6258 
6259 	if (!sAllKextLoadIdentifiers || !kextIdentifier) {
6260 		goto finish;
6261 	}
6262 
6263 	kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
6264 	if (!kextIdentifierSymbol) {
6265 		// xxx - this is really a basic alloc failure
6266 		fail = true;
6267 		goto finish;
6268 	}
6269 
6270 	IORecursiveLockLock(sKextLock);
6271 	if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
6272 		if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
6273 			fail = true;
6274 		} else {
6275 			// xxx - need to find a way to associate this whole func w/the kext
6276 			OSKextLog(/* kext */ NULL,
6277 			    // xxx - check level
6278 			    kOSKextLogStepLevel |
6279 			    kOSKextLogArchiveFlag,
6280 			    "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
6281 			    kextIdentifier->getCStringNoCopy());
6282 		}
6283 	}
6284 	IORecursiveLockUnlock(sKextLock);
6285 
6286 finish:
6287 
6288 	if (fail) {
6289 		OSKextLog(/* kext */ NULL,
6290 		    kOSKextLogErrorLevel |
6291 		    kOSKextLogArchiveFlag,
6292 		    "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
6293 		    kextIdentifier->getCStringNoCopy());
6294 	}
6295 	return;
6296 }
6297 
6298 /*********************************************************************
6299 *********************************************************************/
6300 OSReturn
6301 OSKext::load(
6302 	OSKextExcludeLevel   startOpt,
6303 	OSKextExcludeLevel   startMatchingOpt,
6304 	OSArray            * personalityNames)
6305 {
6306 	OSReturn             result                       = kOSReturnError;
6307 	OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
6308 	OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
6309 	unsigned int         i, count;
6310 	Boolean              alreadyLoaded                = false;
6311 	OSKext             * lastLoadedKext               = NULL;        // do not release
6312 
6313 	if (isInExcludeList()) {
6314 		OSKextLog(this,
6315 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
6316 		    kOSKextLogLoadFlag,
6317 		    "Kext %s is in exclude list, not loadable",
6318 		    getIdentifierCString());
6319 
6320 		result = kOSKextReturnNotLoadable;
6321 		goto finish;
6322 	}
6323 	if (!isLoadable()) {
6324 		OSKextLog(this,
6325 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
6326 		    kOSKextLogLoadFlag,
6327 		    "Kext %s is not loadable",
6328 		    getIdentifierCString());
6329 
6330 		result = kOSKextReturnNotLoadable;
6331 		goto finish;
6332 	}
6333 
6334 	if (isLoaded()) {
6335 		alreadyLoaded = true;
6336 		result = kOSReturnSuccess;
6337 
6338 		OSKextLog(this,
6339 		    kOSKextLogDebugLevel |
6340 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6341 		    "Kext %s is already loaded.",
6342 		    getIdentifierCString());
6343 		goto loaded;
6344 	}
6345 
6346 #if CONFIG_MACF
6347 	/*
6348 	 * On kxld and on embedded, only call into the MAC hook when on a
6349 	 * user thread, for access control over userspace kextloads.
6350 	 *
6351 	 * On non-kxld systems, additionally check the MAC hook for kexts in
6352 	 * the Pageable and Aux KCs, regardless of whether we are on a user
6353 	 * thread or not. This means on Apple silicon devices that the MAC
6354 	 * hook will only be useful to block 3rd party kexts loaded via
6355 	 * matching, and any kexts loaded from userspace kextloads.
6356 	 *
6357 	 * Note that this should _not_ be called on kexts loaded from the
6358 	 * kernel bootstrap thread as the kernel proc's cred struct is not
6359 	 * yet initialized! This won't happen on macOS because all the kexts
6360 	 * in the BootKC are self-contained and their kc_type = KCKindPrimary.
6361 	 */
6362 	if (current_task() != kernel_task
6363 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD
6364 	    || (kc_type != KCKindPrimary && kc_type != KCKindUnknown)
6365 #endif
6366 	    ) {
6367 		int                 macCheckResult      = 0;
6368 		kauth_cred_t        cred                = NULL;
6369 
6370 		cred = kauth_cred_get_with_ref();
6371 		macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
6372 		kauth_cred_unref(&cred);
6373 
6374 		if (macCheckResult != 0) {
6375 			result = kOSReturnError;
6376 			OSKextLog(this,
6377 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6378 			    "Failed to load kext %s (MAC policy error 0x%x).",
6379 			    getIdentifierCString(), macCheckResult);
6380 			goto finish;
6381 		}
6382 	}
6383 #endif /* CONFIG_MACF */
6384 
6385 	if (!sLoadEnabled) {
6386 		OSKextLog(this,
6387 		    kOSKextLogErrorLevel |
6388 		    kOSKextLogLoadFlag,
6389 		    "Kext loading is disabled (attempt to load kext %s).",
6390 		    getIdentifierCString());
6391 		result = kOSKextReturnDisabled;
6392 		goto finish;
6393 	}
6394 
6395 	/* If we've pushed the next available load tag to the invalid value,
6396 	 * we can't load any more kexts.
6397 	 */
6398 	if (sNextLoadTag == kOSKextInvalidLoadTag) {
6399 		OSKextLog(this,
6400 		    kOSKextLogErrorLevel |
6401 		    kOSKextLogLoadFlag,
6402 		    "Can't load kext %s - no more load tags to assign.",
6403 		    getIdentifierCString());
6404 		result = kOSKextReturnNoResources;
6405 		goto finish;
6406 	}
6407 
6408 	/* This is a bit of a hack, because we shouldn't be handling
6409 	 * personalities within the load function.
6410 	 */
6411 	if (!declaresExecutable()) {
6412 		/* There is a special case where a non-executable kext can be loaded: the
6413 		 * AppleKextExcludeList.  Detect that special kext by bundle identifier and
6414 		 * load its metadata into the global data structures, if appropriate
6415 		 */
6416 		if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
6417 			boolean_t updated = updateExcludeList(infoDict.get());
6418 			if (updated) {
6419 				OSKextLog(this,
6420 				    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
6421 				    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
6422 			}
6423 		}
6424 
6425 		if (isDriverKit()) {
6426 			if (loadTag == 0) {
6427 				sLoadedDriverKitKexts->setObject(this);
6428 				loadTag = sNextLoadTag++;
6429 			}
6430 		}
6431 		result = kOSReturnSuccess;
6432 		goto loaded;
6433 	}
6434 
6435 	/* Are we in safe boot?
6436 	 */
6437 	if (sSafeBoot && !isLoadableInSafeBoot()) {
6438 		OSKextLog(this,
6439 		    kOSKextLogErrorLevel |
6440 		    kOSKextLogLoadFlag,
6441 		    "Can't load kext %s - not loadable during safe boot.",
6442 		    getIdentifierCString());
6443 		result = kOSKextReturnBootLevel;
6444 		goto finish;
6445 	}
6446 
6447 	OSKextLog(this,
6448 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
6449 	    "Loading kext %s.",
6450 	    getIdentifierCString());
6451 
6452 #if !VM_MAPPED_KEXTS
6453 	if (isPrelinked() == false) {
6454 		OSKextLog(this,
6455 		    kOSKextLogErrorLevel |
6456 		    kOSKextLogLoadFlag,
6457 		    "Can't load kext %s - not in a kext collection.",
6458 		    getIdentifierCString());
6459 		result = kOSKextReturnDisabled;
6460 		goto finish;
6461 	}
6462 #endif /* defined(__x86_64__) */
6463 
6464 #if CONFIG_KXLD
6465 	if (!sKxldContext) {
6466 		kern_return_t kxldResult;
6467 		kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
6468 		    &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
6469 		    /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
6470 		if (kxldResult) {
6471 			OSKextLog(this,
6472 			    kOSKextLogErrorLevel |
6473 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6474 			    "Can't load kext %s - failed to create link context.",
6475 			    getIdentifierCString());
6476 			result = kOSKextReturnNoMemory;
6477 			goto finish;
6478 		}
6479 	}
6480 #endif // CONFIG_KXLD
6481 
6482 	/* We only need to resolve dependencies once for the whole graph, but
6483 	 * resolveDependencies will just return if there's no work to do, so it's
6484 	 * safe to call it more than once.
6485 	 */
6486 	if (!resolveDependencies()) {
6487 		// xxx - check resolveDependencies() for log msg
6488 		OSKextLog(this,
6489 		    kOSKextLogErrorLevel |
6490 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6491 		    "Can't load kext %s - failed to resolve library dependencies.",
6492 		    getIdentifierCString());
6493 		result = kOSKextReturnDependencies;
6494 		goto finish;
6495 	}
6496 
6497 	/* If we are excluding just the kext being loaded now (and not its
6498 	 * dependencies), drop the exclusion level to none so dependencies
6499 	 * start and/or add their personalities.
6500 	 */
6501 	if (dependenciesStartOpt == kOSKextExcludeKext) {
6502 		dependenciesStartOpt = kOSKextExcludeNone;
6503 	}
6504 
6505 	if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
6506 		dependenciesStartMatchingOpt = kOSKextExcludeNone;
6507 	}
6508 
6509 	/* Load the dependencies, recursively.
6510 	 */
6511 	count = getNumDependencies();
6512 	for (i = 0; i < count; i++) {
6513 		OSKext * dependency = OSDynamicCast(OSKext,
6514 		    dependencies->getObject(i));
6515 		if (dependency == NULL) {
6516 			OSKextLog(this,
6517 			    kOSKextLogErrorLevel |
6518 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6519 			    "Internal error loading kext %s; dependency disappeared.",
6520 			    getIdentifierCString());
6521 			result = kOSKextReturnInternalError;
6522 			goto finish;
6523 		}
6524 
6525 		/* Dependencies must be started accorting to the opt,
6526 		 * but not given the personality names of the main kext.
6527 		 */
6528 		result = dependency->load(dependenciesStartOpt,
6529 		    dependenciesStartMatchingOpt,
6530 		    /* personalityNames */ NULL);
6531 		if (result != KERN_SUCCESS) {
6532 			OSKextLog(this,
6533 			    kOSKextLogErrorLevel |
6534 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6535 			    "Dependency %s of kext %s failed to load.",
6536 			    dependency->getIdentifierCString(),
6537 			    getIdentifierCString());
6538 
6539 			OSKext::removeKext(dependency,
6540 			    /* terminateService/removePersonalities */ true);
6541 			result = kOSKextReturnDependencyLoadError;
6542 
6543 			goto finish;
6544 		}
6545 	}
6546 
6547 	result = loadExecutable();
6548 	if (result != KERN_SUCCESS) {
6549 		goto finish;
6550 	}
6551 
6552 	pendingPgoHead.next = &pendingPgoHead;
6553 	pendingPgoHead.prev = &pendingPgoHead;
6554 
6555 	// The kernel PRNG is not initialized when the first kext is
6556 	// loaded, so use early random
6557 	uuid_generate_early_random(instance_uuid);
6558 	account = IOMallocType(OSKextAccount);
6559 
6560 	account->loadTag = kmod_info->id;
6561 	account->site.refcount = 0;
6562 	account->site.flags = VM_TAG_KMOD;
6563 
6564 #if DEVELOPMENT || DEBUG
6565 	/* Setup the task reference group. */
6566 	(void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name),
6567 	    "task_%s", getIdentifierCString());
6568 	account->task_refgrp.grp_name = account->task_refgrp_name;
6569 	account->task_refgrp.grp_parent = &task_external_refgrp;
6570 	account->task_refgrp.grp_flags = OS_REFGRP_F_ALWAYS_ENABLED;
6571 	os_ref_log_init(&account->task_refgrp);
6572 #endif /* DEVELOPMENT || DEBUG */
6573 
6574 	account->kext = this;
6575 	if (gIOSurfaceIdentifier == bundleID) {
6576 		vm_tag_alloc(&account->site);
6577 		gIOSurfaceTag = account->site.tag;
6578 	}
6579 
6580 	flags.loaded = true;
6581 
6582 	/* Add the kext to the list of loaded kexts and update the kmod_info
6583 	 * struct to point to that of the last loaded kext (which is the way
6584 	 * it's always been done, though I'd rather do them in order now).
6585 	 */
6586 	lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
6587 	sLoadedKexts->setObject(this);
6588 
6589 	/* Keep the kernel itself out of the kmod list.
6590 	 */
6591 	if (lastLoadedKext->isKernel()) {
6592 		lastLoadedKext = NULL;
6593 	}
6594 
6595 	if (lastLoadedKext) {
6596 		kmod_info->next = lastLoadedKext->kmod_info;
6597 	}
6598 
6599 	notifyKextLoadObservers(this, kmod_info);
6600 
6601 	/* Make the global kmod list point at the just-loaded kext. Note that the
6602 	 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
6603 	 * although we do report it in kextstat these days by using the newer
6604 	 * OSArray of loaded kexts, which does contain it.
6605 	 *
6606 	 * (The OSKext object representing the kernel doesn't even have a kmod_info
6607 	 * struct, though I suppose we could stick a pointer to it from the
6608 	 * static struct in OSRuntime.cpp.)
6609 	 */
6610 	kmod = kmod_info;
6611 
6612 	/* Save the list of loaded kexts in case we panic.
6613 	 */
6614 	OSKext::saveLoadedKextPanicList();
6615 
6616 	if (isExecutable()) {
6617 		OSKext::updateLoadedKextSummaries();
6618 		savePanicString(/* isLoading */ true);
6619 
6620 #if CONFIG_DTRACE
6621 		registerWithDTrace();
6622 #else
6623 		jettisonLinkeditSegment();
6624 #endif /* CONFIG_DTRACE */
6625 
6626 #if !VM_MAPPED_KEXTS
6627 		/* If there is a page (or more) worth of padding after the end
6628 		 * of the last data section but before the end of the data segment
6629 		 * then free it in the same manner the LinkeditSegment is freed
6630 		 */
6631 		jettisonDATASegmentPadding();
6632 #endif
6633 	}
6634 
6635 loaded:
6636 	if (isExecutable() && !flags.started) {
6637 		if (startOpt == kOSKextExcludeNone) {
6638 			result = start();
6639 			if (result != kOSReturnSuccess) {
6640 				OSKextLog(this,
6641 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6642 				    "Kext %s start failed (result 0x%x).",
6643 				    getIdentifierCString(), result);
6644 				result = kOSKextReturnStartStopError;
6645 			}
6646 		}
6647 	}
6648 
6649 	/* If not excluding matching, send the personalities to the kernel.
6650 	 * This never affects the result of the load operation.
6651 	 * This is a bit of a hack, because we shouldn't be handling
6652 	 * personalities within the load function.
6653 	 */
6654 	if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
6655 		result = sendPersonalitiesToCatalog(true, personalityNames);
6656 	}
6657 
6658 finish:
6659 
6660 	if (result != kOSReturnSuccess) {
6661 		OSKextLog(this,
6662 		    kOSKextLogErrorLevel |
6663 		    kOSKextLogLoadFlag,
6664 		    "Kext %s failed to load (0x%x).",
6665 		    getIdentifierCString(), (int)result);
6666 	} else if (!alreadyLoaded) {
6667 		OSKextLog(this,
6668 		    kOSKextLogProgressLevel |
6669 		    kOSKextLogLoadFlag,
6670 		    "Kext %s loaded.",
6671 		    getIdentifierCString());
6672 
6673 		queueKextNotification(kKextRequestPredicateLoadNotification,
6674 		    OSDynamicCast(OSString, bundleID.get()));
6675 	}
6676 	return result;
6677 }
6678 
6679 #if CONFIG_KXLD
6680 /*********************************************************************
6681 *
6682 *********************************************************************/
6683 static char *
6684 strdup(const char * string)
6685 {
6686 	char * result = NULL;
6687 	size_t size;
6688 
6689 	if (!string) {
6690 		goto finish;
6691 	}
6692 
6693 	size = 1 + strlen(string);
6694 	result = (char *)kalloc_data_tag(size, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
6695 	if (!result) {
6696 		goto finish;
6697 	}
6698 
6699 	memcpy(result, string, size);
6700 
6701 finish:
6702 	return result;
6703 }
6704 #endif // CONFIG_KXLD
6705 
6706 /*********************************************************************
6707 *
6708 *********************************************************************/
6709 
6710 kernel_section_t *
6711 OSKext::lookupSection(const char *segname, const char *secname)
6712 {
6713 	kernel_section_t         * found_section = NULL;
6714 	kernel_mach_header_t     * mh            = NULL;
6715 	kernel_segment_command_t * seg           = NULL;
6716 	kernel_section_t         * sec           = NULL;
6717 
6718 	if (!linkedExecutable) {
6719 		return NULL;
6720 	}
6721 
6722 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6723 
6724 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6725 		if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
6726 			continue;
6727 		}
6728 
6729 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6730 			if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
6731 				found_section = sec;
6732 				goto out;
6733 			}
6734 		}
6735 	}
6736 
6737 out:
6738 	return found_section;
6739 }
6740 
6741 /*********************************************************************
6742 *
6743 *********************************************************************/
6744 
6745 OSReturn
6746 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides)
6747 {
6748 	OSReturn                       result           = kOSKextReturnBadData;
6749 	kernel_mach_header_t         * mh               = NULL;
6750 	kernel_segment_command_t     * seg              = NULL;
6751 	kernel_segment_command_t     * linkeditSeg      = NULL;
6752 	kernel_section_t             * sec              = NULL;
6753 	char                         * linkeditBase     = NULL;
6754 	bool                           haveLinkeditBase = false;
6755 	char                         * relocBase        = NULL;
6756 	bool                           haveRelocBase    = false;
6757 	struct dysymtab_command      * dysymtab         = NULL;
6758 	struct linkedit_data_command * segmentSplitInfo = NULL;
6759 	struct symtab_command        * symtab           = NULL;
6760 	kernel_nlist_t               * sym              = NULL;
6761 	struct relocation_info       * reloc            = NULL;
6762 	uint32_t                       i                = 0;
6763 	int                            reloc_size;
6764 	vm_offset_t                    new_kextsize;
6765 	kc_format                    format             = KCFormatUnknown;
6766 
6767 	if (linkedExecutable == NULL || flags.builtin) {
6768 		result = kOSReturnSuccess;
6769 		goto finish;
6770 	}
6771 
6772 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6773 	if (kernel_mach_header_is_in_fileset(mh)) {
6774 		// kexts in filesets are slid as part of collection sliding
6775 		result = kOSReturnSuccess;
6776 		goto finish;
6777 	}
6778 
6779 	segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
6780 
6781 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6782 		if (!seg->vmaddr) {
6783 			continue;
6784 		}
6785 
6786 		seg->vmaddr = ml_static_slide(seg->vmaddr);
6787 
6788 #if KASLR_KEXT_DEBUG
6789 		IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
6790 		    seg->segname,
6791 		    (unsigned long)ml_static_unslide(seg->vmaddr),
6792 		    (unsigned long)seg->vmaddr);
6793 #endif
6794 
6795 		if (!haveRelocBase) {
6796 			relocBase = (char *) seg->vmaddr;
6797 			haveRelocBase = true;
6798 		}
6799 		if (!strcmp(seg->segname, "__LINKEDIT")) {
6800 			linkeditBase = (char *) seg->vmaddr - seg->fileoff;
6801 			haveLinkeditBase = true;
6802 			linkeditSeg = seg;
6803 		}
6804 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6805 			sec->addr = ml_static_slide(sec->addr);
6806 
6807 #if KASLR_KEXT_DEBUG
6808 			IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
6809 			    sec->sectname,
6810 			    (unsigned long)ml_static_unslide(sec->addr),
6811 			    (unsigned long)sec->addr);
6812 #endif
6813 		}
6814 	}
6815 
6816 	dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
6817 
6818 	symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
6819 
6820 	if (symtab != NULL && doCoalescedSlides == false) {
6821 		/* Some pseudo-kexts have symbol tables without segments.
6822 		 * Ignore them. */
6823 		if (symtab->nsyms > 0 && haveLinkeditBase) {
6824 			sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
6825 			for (i = 0; i < symtab->nsyms; i++) {
6826 				if (sym[i].n_type & N_STAB) {
6827 					continue;
6828 				}
6829 				sym[i].n_value = ml_static_slide(sym[i].n_value);
6830 
6831 #if KASLR_KEXT_DEBUG
6832 #define MAX_SYMS_TO_LOG 5
6833 				if (i < MAX_SYMS_TO_LOG) {
6834 					IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
6835 					    (unsigned long)ml_static_unslide(sym[i].n_value),
6836 					    (unsigned long)sym[i].n_value);
6837 				}
6838 #endif
6839 			}
6840 		}
6841 	}
6842 
6843 	if (dysymtab != NULL && doCoalescedSlides == false) {
6844 		if (dysymtab->nextrel > 0) {
6845 			OSKextLog(this,
6846 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6847 			    kOSKextLogLinkFlag,
6848 			    "Sliding kext %s: External relocations found.",
6849 			    getIdentifierCString());
6850 			goto finish;
6851 		}
6852 
6853 		if (dysymtab->nlocrel > 0) {
6854 			if (!haveLinkeditBase) {
6855 				OSKextLog(this,
6856 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6857 				    kOSKextLogLinkFlag,
6858 				    "Sliding kext %s: No linkedit segment.",
6859 				    getIdentifierCString());
6860 				goto finish;
6861 			}
6862 
6863 			if (!haveRelocBase) {
6864 				OSKextLog(this,
6865 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6866 				    kOSKextLogLinkFlag,
6867 #if __x86_64__
6868 				    "Sliding kext %s: No writable segments.",
6869 #else
6870 				    "Sliding kext %s: No segments.",
6871 #endif
6872 				    getIdentifierCString());
6873 				goto finish;
6874 			}
6875 
6876 			reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
6877 			reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
6878 
6879 			for (i = 0; i < dysymtab->nlocrel; i++) {
6880 				if (reloc[i].r_extern != 0
6881 				    || reloc[i].r_type != 0
6882 				    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
6883 				    ) {
6884 					OSKextLog(this,
6885 					    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6886 					    kOSKextLogLinkFlag,
6887 					    "Sliding kext %s: Unexpected relocation found.",
6888 					    getIdentifierCString());
6889 					goto finish;
6890 				}
6891 				if (reloc[i].r_pcrel != 0) {
6892 					continue;
6893 				}
6894 				uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
6895 				*relocAddr = ml_static_slide(*relocAddr);
6896 
6897 #if KASLR_KEXT_DEBUG
6898 #define MAX_DYSYMS_TO_LOG 5
6899 				if (i < MAX_DYSYMS_TO_LOG) {
6900 					IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
6901 					    (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
6902 					    (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
6903 				}
6904 #endif
6905 			}
6906 
6907 			/* We should free these relocations, not just delete the reference to them.
6908 			 * <rdar://problem/10535549> Free relocations from PIE kexts.
6909 			 *
6910 			 * For now, we do not free LINKEDIT for kexts with split segments.
6911 			 */
6912 			new_kextsize = round_page(kmod_info->size - reloc_size);
6913 			if (new_kextsize > UINT_MAX) {
6914 				OSKextLog(this,
6915 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6916 				    kOSKextLogLinkFlag,
6917 				    "Kext %s: new kext size is too large.",
6918 				    getIdentifierCString());
6919 				goto finish;
6920 			}
6921 			if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
6922 				vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
6923 				vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
6924 				vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
6925 				size_t          bytes_remaining = endofkext - endofrelocInfo;
6926 				OSSharedPtr<OSData>        new_osdata;
6927 
6928 				/* fix up symbol offsets if they are after the dsymtab local relocs */
6929 				if (symtab) {
6930 					if (dysymtab->locreloff < symtab->symoff) {
6931 						symtab->symoff -= reloc_size;
6932 					}
6933 					if (dysymtab->locreloff < symtab->stroff) {
6934 						symtab->stroff -= reloc_size;
6935 					}
6936 				}
6937 				if (dysymtab->locreloff < dysymtab->extreloff) {
6938 					dysymtab->extreloff -= reloc_size;
6939 				}
6940 
6941 				/* move data behind reloc info down to new offset */
6942 				if (endofrelocInfo < endofkext) {
6943 					memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
6944 				}
6945 
6946 				/* Create a new OSData for the smaller kext object and reflect
6947 				 * new linkedit segment size.
6948 				 */
6949 				linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
6950 				linkeditSeg->filesize = linkeditSeg->vmsize;
6951 
6952 				new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize);
6953 				if (new_osdata) {
6954 					/* Fix up kmod info and linkedExecutable.
6955 					 */
6956 					kmod_info->size = new_kextsize;
6957 					/*
6958 					 * Fileset KCs are mapped as a whole by iBoot.
6959 					 * Individual kext executables should not be unmapped
6960 					 * by xnu.
6961 					 * Doing so may result in panics like rdar://85419651
6962 					 */
6963 					if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
6964 						new_osdata->setDeallocFunction(NULL);
6965 					} else { // Not from a Fileset KC
6966 #if VM_MAPPED_KEXTS
6967 						new_osdata->setDeallocFunction(osdata_kext_free);
6968 #else
6969 						new_osdata->setDeallocFunction(osdata_phys_free);
6970 #endif
6971 					}
6972 					linkedExecutable->setDeallocFunction(NULL);
6973 					linkedExecutable = os::move(new_osdata);
6974 
6975 #if VM_MAPPED_KEXTS
6976 					kext_free(new_endofkext, (endofkext - new_endofkext));
6977 #else
6978 					ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
6979 #endif
6980 				}
6981 			}
6982 			dysymtab->nlocrel = 0;
6983 			dysymtab->locreloff = 0;
6984 		}
6985 	}
6986 
6987 	result = kOSReturnSuccess;
6988 finish:
6989 	return result;
6990 }
6991 
6992 /*********************************************************************
6993 * called only by load()
6994 *********************************************************************/
6995 OSReturn
6996 OSKext::loadExecutable()
6997 {
6998 	OSReturn              result             = kOSReturnError;
6999 	OSSharedPtr<OSArray>  linkDependencies;
7000 	uint32_t              num_kmod_refs      = 0;
7001 	OSData              * theExecutable      = NULL;        // do not release
7002 	OSString            * versString         = NULL;        // do not release
7003 	const char          * versCString        = NULL;        // do not free
7004 	const char          * string             = NULL;        // do not free
7005 
7006 #if CONFIG_KXLD
7007 	unsigned int          i;
7008 	uint32_t              numDirectDependencies   = 0;
7009 	kern_return_t         kxldResult;
7010 	KXLDDependency     *  kxlddeps           = NULL;        // must kfree
7011 	uint32_t              num_kxlddeps       = 0;
7012 	struct mach_header ** kxldHeaderPtr      = NULL;        // do not free
7013 	struct mach_header  * kxld_header        = NULL;        // xxx - need to free here?
7014 #endif // CONFIG_KXLD
7015 
7016 	/* We need the version string for a variety of bits below.
7017 	 */
7018 	versString = OSDynamicCast(OSString,
7019 	    getPropertyForHostArch(kCFBundleVersionKey));
7020 	if (!versString) {
7021 		goto finish;
7022 	}
7023 	versCString = versString->getCStringNoCopy();
7024 
7025 	if (isKernelComponent()) {
7026 		if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
7027 			if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
7028 				OSKextLog(this,
7029 				    kOSKextLogErrorLevel |
7030 				    kOSKextLogLoadFlag,
7031 				    "Kernel component %s has incorrect version %s; "
7032 				    "expected %s.",
7033 				    getIdentifierCString(),
7034 				    versCString, KERNEL6_VERSION);
7035 				result = kOSKextReturnInternalError;
7036 				goto finish;
7037 			} else if (strcmp(versCString, osrelease)) {
7038 				OSKextLog(this,
7039 				    kOSKextLogErrorLevel |
7040 				    kOSKextLogLoadFlag,
7041 				    "Kernel component %s has incorrect version %s; "
7042 				    "expected %s.",
7043 				    getIdentifierCString(),
7044 				    versCString, osrelease);
7045 				result = kOSKextReturnInternalError;
7046 				goto finish;
7047 			}
7048 		}
7049 	}
7050 
7051 #if defined(__x86_64__) || defined(__i386__)
7052 	if (flags.resetSegmentsFromVnode) {
7053 		/* Fixup the chains and slide the mach headers */
7054 		kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address;
7055 
7056 		if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) {
7057 			result = kOSKextReturnValidation;
7058 			goto finish;
7059 		}
7060 	}
7061 #endif //(__x86_64__) || defined(__i386__)
7062 
7063 	if (isPrelinked()) {
7064 		goto register_kmod;
7065 	}
7066 
7067 	/* <rdar://problem/21444003> all callers must be entitled */
7068 	if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) {
7069 		OSKextLog(this,
7070 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7071 		    "Not entitled to link kext '%s'",
7072 		    getIdentifierCString());
7073 		result = kOSKextReturnNotPrivileged;
7074 		goto finish;
7075 	}
7076 
7077 	theExecutable = getExecutable();
7078 	if (!theExecutable) {
7079 		if (declaresExecutable()) {
7080 			OSKextLog(this,
7081 			    kOSKextLogErrorLevel |
7082 			    kOSKextLogLoadFlag,
7083 			    "Can't load kext %s - executable is missing.",
7084 			    getIdentifierCString());
7085 			result = kOSKextReturnValidation;
7086 			goto finish;
7087 		}
7088 		goto register_kmod;
7089 	}
7090 
7091 	if (isInterface()) {
7092 		OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable);
7093 		if (executableCopy) {
7094 			setLinkedExecutable(executableCopy.get());
7095 		}
7096 		goto register_kmod;
7097 	}
7098 
7099 #if CONFIG_KXLD
7100 	numDirectDependencies = getNumDependencies();
7101 
7102 	if (flags.hasBleedthrough) {
7103 		linkDependencies = dependencies;
7104 	} else {
7105 		linkDependencies = OSArray::withArray(dependencies.get());
7106 		if (!linkDependencies) {
7107 			OSKextLog(this,
7108 			    kOSKextLogErrorLevel |
7109 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7110 			    "Can't allocate link dependencies to load kext %s.",
7111 			    getIdentifierCString());
7112 			goto finish;
7113 		}
7114 
7115 		for (i = 0; i < numDirectDependencies; ++i) {
7116 			OSKext * dependencyKext = OSDynamicCast(OSKext,
7117 			    dependencies->getObject(i));
7118 			dependencyKext->addBleedthroughDependencies(linkDependencies.get());
7119 		}
7120 	}
7121 
7122 	num_kxlddeps = linkDependencies->getCount();
7123 	if (!num_kxlddeps) {
7124 		OSKextLog(this,
7125 		    kOSKextLogErrorLevel |
7126 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
7127 		    "Can't load kext %s - it has no library dependencies.",
7128 		    getIdentifierCString());
7129 		goto finish;
7130 	}
7131 
7132 	kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
7133 	if (!kxlddeps) {
7134 		OSKextLog(this,
7135 		    kOSKextLogErrorLevel |
7136 		    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7137 		    "Can't allocate link context to load kext %s.",
7138 		    getIdentifierCString());
7139 		goto finish;
7140 	}
7141 	bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
7142 
7143 	for (i = 0; i < num_kxlddeps; ++i) {
7144 		OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
7145 
7146 		if (dependency->isInterface()) {
7147 			OSKext *interfaceTargetKext = NULL;        //do not release
7148 			OSData * interfaceTarget = NULL;        //do not release
7149 
7150 			if (dependency->isKernelComponent()) {
7151 				interfaceTargetKext = sKernelKext;
7152 				interfaceTarget = sKernelKext->linkedExecutable.get();
7153 			} else {
7154 				interfaceTargetKext = OSDynamicCast(OSKext,
7155 				    dependency->dependencies->getObject(0));
7156 
7157 				interfaceTarget = interfaceTargetKext->linkedExecutable.get();
7158 			}
7159 
7160 			if (!interfaceTarget) {
7161 				// panic?
7162 				goto finish;
7163 			}
7164 
7165 			/* The names set here aren't actually logged yet <rdar://problem/7941514>,
7166 			 * it will be useful to have them in the debugger.
7167 			 * strdup() failing isn't critical right here so we don't check that.
7168 			 */
7169 			kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
7170 			kxlddeps[i].kext_size = interfaceTarget->getLength();
7171 			kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
7172 
7173 			if (dependency->linkedExecutable != NULL) {
7174 				kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
7175 				kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
7176 			} else {
7177 				kxlddeps[i].interface = (u_char *) NULL;
7178 				kxlddeps[i].interface_size = 0;
7179 			}
7180 			kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
7181 		} else {
7182 			kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
7183 			kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
7184 			kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
7185 		}
7186 
7187 		kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
7188 	}
7189 
7190 	kxldHeaderPtr = &kxld_header;
7191 
7192 #if DEBUG
7193 	OSKextLog(this,
7194 	    kOSKextLogExplicitLevel |
7195 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7196 	    "Kext %s - calling kxld_link_file:\n"
7197 	    "    kxld_context: %p\n"
7198 	    "    executable: %p    executable_length: %d\n"
7199 	    "    user_data: %p\n"
7200 	    "    kxld_dependencies: %p    num_dependencies: %d\n"
7201 	    "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
7202 	    getIdentifierCString(), sKxldContext,
7203 	    theExecutable->getBytesNoCopy(), theExecutable->getLength(),
7204 	    this, kxlddeps, num_kxlddeps,
7205 	    kxldHeaderPtr, &kmod_info);
7206 #endif
7207 
7208 	/* After this call, the linkedExecutable instance variable
7209 	 * should exist.
7210 	 */
7211 	kxldResult = kxld_link_file(sKxldContext,
7212 	    (u_char *)theExecutable->getBytesNoCopy(),
7213 	    theExecutable->getLength(),
7214 	    getIdentifierCString(), this, kxlddeps, num_kxlddeps,
7215 	    (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
7216 
7217 	if (kxldResult != KERN_SUCCESS) {
7218 		// xxx - add kxldResult here?
7219 		OSKextLog(this,
7220 		    kOSKextLogErrorLevel |
7221 		    kOSKextLogLoadFlag,
7222 		    "Can't load kext %s - link failed.",
7223 		    getIdentifierCString());
7224 		result = kOSKextReturnLinkError;
7225 		goto finish;
7226 	}
7227 
7228 	/* We've written data & instructions into kernel memory, so flush the data
7229 	 * cache and invalidate the instruction cache.
7230 	 * I/D caches are coherent on x86
7231 	 */
7232 #if !defined(__i386__) && !defined(__x86_64__)
7233 	flush_dcache(kmod_info->address, kmod_info->size, false);
7234 	invalidate_icache(kmod_info->address, kmod_info->size, false);
7235 #endif
7236 
7237 #else // !CONFIG_KXLD
7238 	OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7239 	    "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString());
7240 	result = kOSKextReturnLinkError;
7241 	goto finish;
7242 #endif // CONFIG_KXLD
7243 
7244 register_kmod:
7245 
7246 	if (isInterface()) {
7247 		/* Whip up a fake kmod_info entry for the interface kext.
7248 		 */
7249 		kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
7250 		if (!kmod_info) {
7251 			result = KERN_MEMORY_ERROR;
7252 			goto finish;
7253 		}
7254 
7255 		/* A pseudokext has almost nothing in its kmod_info struct.
7256 		 */
7257 		kmod_info->info_version = KMOD_INFO_VERSION;
7258 
7259 		/* An interface kext doesn't have a linkedExecutable, so save a
7260 		 * copy of the UUID out of the original executable via copyUUID()
7261 		 * while we still have the original executable.
7262 		 */
7263 		interfaceUUID = copyUUID();
7264 	}
7265 
7266 	kmod_info->id = loadTag = sNextLoadTag++;
7267 	kmod_info->reference_count = 0;         // KMOD_DECL... sets it to -1 (invalid).
7268 
7269 	/* Stamp the bundle ID and version from the OSKext over anything
7270 	 * resident inside the kmod_info.
7271 	 */
7272 	string = getIdentifierCString();
7273 	strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
7274 
7275 	string = versCString;
7276 	strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
7277 
7278 	/* Add the dependencies' kmod_info structs as kmod_references.
7279 	 */
7280 	num_kmod_refs = getNumDependencies();
7281 	if (num_kmod_refs) {
7282 		kmod_info->reference_list = kalloc_type_tag(kmod_reference_t,
7283 		    num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT);
7284 		if (!kmod_info->reference_list) {
7285 			result = KERN_MEMORY_ERROR;
7286 			goto finish;
7287 		}
7288 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
7289 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
7290 			OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
7291 			ref->info = refKext->kmod_info;
7292 			ref->info->reference_count++;
7293 
7294 			if (refIndex + 1 < num_kmod_refs) {
7295 				ref->next = kmod_info->reference_list + refIndex + 1;
7296 			}
7297 		}
7298 	}
7299 
7300 	if (kmod_info->hdr_size > UINT32_MAX) {
7301 		OSKextLog(this,
7302 		    kOSKextLogErrorLevel |
7303 		    kOSKextLogLoadFlag,
7304 #if __LP64__
7305 		    "Kext %s header size is too large (%lu > UINT32_MAX).",
7306 #else
7307 		    "Kext %s header size is too large (%u > UINT32_MAX).",
7308 #endif
7309 		    kmod_info->name,
7310 		    kmod_info->hdr_size);
7311 		result = KERN_FAILURE;
7312 		goto finish;
7313 	}
7314 
7315 	if (kmod_info->size > UINT32_MAX) {
7316 		OSKextLog(this,
7317 		    kOSKextLogErrorLevel |
7318 		    kOSKextLogLoadFlag,
7319 #if __LP64__
7320 		    "Kext %s size is too large (%lu > UINT32_MAX).",
7321 #else
7322 		    "Kext %s size is too large (%u > UINT32_MAX).",
7323 #endif
7324 		    kmod_info->name,
7325 		    kmod_info->size);
7326 		result = KERN_FAILURE;
7327 		goto finish;
7328 	}
7329 
7330 	if (!isInterface() && linkedExecutable) {
7331 		OSKextLog(this,
7332 		    kOSKextLogProgressLevel |
7333 		    kOSKextLogLoadFlag,
7334 		    "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
7335 		    kmod_info->name,
7336 		    (unsigned)kmod_info->size / PAGE_SIZE,
7337 		    (unsigned long)ml_static_unslide(kmod_info->address),
7338 		    (unsigned)kmod_info->id);
7339 	}
7340 
7341 	/* VM protections and wiring for the Aux KC are done at collection loading time */
7342 	if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) {
7343 		/* if prelinked and primary KC, VM protections are already set */
7344 		result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true);
7345 		if (result != KERN_SUCCESS) {
7346 			goto finish;
7347 		}
7348 	}
7349 
7350 #if KASAN
7351 	if (linkedExecutable) {
7352 		kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
7353 		    linkedExecutable->getLength(), getIdentifierCString());
7354 	}
7355 #else
7356 	if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
7357 		OSKextLog(this,
7358 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7359 		    "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
7360 		    getIdentifierCString()
7361 		    );
7362 		result = KERN_FAILURE;
7363 		goto finish;
7364 	}
7365 #endif
7366 
7367 	result = kOSReturnSuccess;
7368 
7369 finish:
7370 
7371 #if CONFIG_KXLD
7372 	/* Clear up locally allocated dependency info.
7373 	 */
7374 	for (i = 0; i < num_kxlddeps; ++i) {
7375 		size_t size;
7376 
7377 		if (kxlddeps[i].kext_name) {
7378 			size = 1 + strlen(kxlddeps[i].kext_name);
7379 			kfree_data(kxlddeps[i].kext_name, size);
7380 		}
7381 		if (kxlddeps[i].interface_name) {
7382 			size = 1 + strlen(kxlddeps[i].interface_name);
7383 			kfree_data(kxlddeps[i].interface_name, size);
7384 		}
7385 	}
7386 	if (kxlddeps) {
7387 		kfree_type(KXLDDependency, num_kxlddeps, kxlddeps);
7388 	}
7389 #endif // CONFIG_KXLD
7390 
7391 	/* We no longer need the unrelocated executable (which the linker
7392 	 * has altered anyhow).
7393 	 */
7394 	setExecutable(NULL);
7395 
7396 	if (result != kOSReturnSuccess) {
7397 		OSKextLog(this,
7398 		    kOSKextLogErrorLevel |
7399 		    kOSKextLogLoadFlag,
7400 		    "Failed to load executable for kext %s.",
7401 		    getIdentifierCString());
7402 
7403 		if (kmod_info && kmod_info->reference_list) {
7404 			kfree_type(kmod_reference_t, num_kmod_refs,
7405 			    kmod_info->reference_list);
7406 		}
7407 		if (isInterface()) {
7408 			kfree_type(kmod_info_t, kmod_info);
7409 			kmod_info = NULL;
7410 		}
7411 		if (kc_type == KCKindUnknown) {
7412 			kmod_info = NULL;
7413 			if (linkedExecutable) {
7414 				linkedExecutable.reset();
7415 			}
7416 		}
7417 	}
7418 
7419 	return result;
7420 }
7421 
7422 /* static */
7423 void
7424 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh)
7425 {
7426 	kernel_segment_command_t *linkeditseg = NULL;
7427 
7428 	linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT);
7429 	if (linkeditseg == NULL) {
7430 		panic("FileSet booted with no Linkedit segment");
7431 	}
7432 
7433 #if VM_MAPPED_KEXTS
7434 	/* BootKC on x86_64 is not vm mapped */
7435 	ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize);
7436 
7437 	OSKextLog(/* kext */ NULL,
7438 	    kOSKextLogProgressLevel |
7439 	    kOSKextLogGeneralFlag,
7440 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
7441 	    linkeditseg->vmaddr, linkeditseg->vmsize);
7442 #else
7443 	/* BootKC on arm64 is not vm mapped, but is slid */
7444 	vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase));
7445 
7446 	ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize);
7447 
7448 	OSKextLog(/* kext */ NULL,
7449 	    kOSKextLogProgressLevel |
7450 	    kOSKextLogGeneralFlag,
7451 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
7452 	    (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize);
7453 #endif /* VM_MAPPED_KEXTS */
7454 }
7455 
7456 /*********************************************************************
7457 * The linkedit segment is used by the kext linker for dependency
7458 * resolution, and by dtrace for probe initialization. We can free it
7459 * for non-library kexts, since no kexts depend on non-library kexts
7460 * by definition, once dtrace has been initialized.
7461 *********************************************************************/
7462 void
7463 OSKext::jettisonLinkeditSegment(void)
7464 {
7465 	kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
7466 	kernel_segment_command_t * linkedit = NULL;
7467 	vm_offset_t                start;
7468 	vm_size_t                  linkeditsize, kextsize;
7469 	OSSharedPtr<OSData>        data;
7470 	kc_format                format    = KCFormatUnknown;
7471 
7472 	if (isInFileset()) {
7473 		return;
7474 	}
7475 
7476 #if NO_KEXTD
7477 	/* We can free symbol tables for all embedded kexts because we don't
7478 	 * support runtime kext linking.
7479 	 */
7480 	if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
7481 #else
7482 	if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
7483 #endif
7484 		goto finish;
7485 	}
7486 
7487 	/* Find the linkedit segment.  If it's not the last segment, then freeing
7488 	 * it will fragment the kext into multiple VM regions, which OSKext is not
7489 	 * designed to handle, so we'll have to skip it.
7490 	 */
7491 	linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
7492 	if (!linkedit) {
7493 		goto finish;
7494 	}
7495 
7496 	if (round_page(kmod_info->address + kmod_info->size) !=
7497 	    round_page(linkedit->vmaddr + linkedit->vmsize)) {
7498 		goto finish;
7499 	}
7500 
7501 	/* Create a new OSData for the smaller kext object.
7502 	 */
7503 	linkeditsize = round_page(linkedit->vmsize);
7504 	kextsize = kmod_info->size - linkeditsize;
7505 	start = linkedit->vmaddr;
7506 
7507 	if (kextsize > UINT_MAX) {
7508 		goto finish;
7509 	}
7510 	data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize);
7511 	if (!data) {
7512 		goto finish;
7513 	}
7514 
7515 	/* Fix the kmod info and linkedExecutable.
7516 	 */
7517 	kmod_info->size = kextsize;
7518 
7519 	/*
7520 	 * Fileset KCs are mapped as a whole by iBoot.
7521 	 * Individual kext executables should not be unmapped by xnu
7522 	 * Doing so may result in panics like rdar://85419651
7523 	 */
7524 	if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
7525 		data->setDeallocFunction(NULL);
7526 	} else { // Not from a Fileset KC
7527 #if VM_MAPPED_KEXTS
7528 		data->setDeallocFunction(osdata_kext_free);
7529 #else
7530 		data->setDeallocFunction(osdata_phys_free);
7531 #endif
7532 	}
7533 	linkedExecutable->setDeallocFunction(NULL);
7534 	linkedExecutable = os::move(data);
7535 	flags.jettisonLinkeditSeg = 1;
7536 
7537 	/* Free the linkedit segment.
7538 	 */
7539 #if VM_MAPPED_KEXTS
7540 	kext_free(start, linkeditsize);
7541 #else
7542 	ml_static_mfree(start, linkeditsize);
7543 #endif
7544 
7545 finish:
7546 	return;
7547 }
7548 
7549 /*********************************************************************
7550 * If there are whole pages that are unused betweem the last section
7551 * of the DATA segment and the end of the DATA segment then we can free
7552 * them
7553 *********************************************************************/
7554 void
7555 OSKext::jettisonDATASegmentPadding(void)
7556 {
7557 	kernel_mach_header_t * mh;
7558 	kernel_segment_command_t * dataSeg;
7559 	kernel_section_t * sec, * lastSec;
7560 	vm_offset_t dataSegEnd, lastSecEnd;
7561 	vm_size_t padSize;
7562 
7563 	if (flags.builtin) {
7564 		return;
7565 	}
7566 	mh = (kernel_mach_header_t *)kmod_info->address;
7567 
7568 	if (isInFileset()) {
7569 		return;
7570 	}
7571 
7572 	dataSeg = getsegbynamefromheader(mh, SEG_DATA);
7573 	if (dataSeg == NULL) {
7574 		return;
7575 	}
7576 
7577 	lastSec = NULL;
7578 	sec = firstsect(dataSeg);
7579 	while (sec != NULL) {
7580 		lastSec = sec;
7581 		sec = nextsect(dataSeg, sec);
7582 	}
7583 
7584 	if (lastSec == NULL) {
7585 		return;
7586 	}
7587 
7588 	if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
7589 	    (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
7590 		return;
7591 	}
7592 
7593 	dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
7594 	lastSecEnd = round_page(lastSec->addr + lastSec->size);
7595 
7596 	if (dataSegEnd <= lastSecEnd) {
7597 		return;
7598 	}
7599 
7600 	padSize = dataSegEnd - lastSecEnd;
7601 
7602 	if (padSize >= PAGE_SIZE) {
7603 #if VM_MAPPED_KEXTS
7604 		kext_free(lastSecEnd, padSize);
7605 #else
7606 		ml_static_mfree(lastSecEnd, padSize);
7607 #endif
7608 	}
7609 }
7610 
7611 /*********************************************************************
7612 *********************************************************************/
7613 void
7614 OSKext::setLinkedExecutable(OSData * anExecutable)
7615 {
7616 	if (linkedExecutable) {
7617 		panic("Attempt to set linked executable on kext "
7618 		    "that already has one (%s).\n",
7619 		    getIdentifierCString());
7620 	}
7621 	linkedExecutable.reset(anExecutable, OSRetain);
7622 	return;
7623 }
7624 
7625 #if CONFIG_DTRACE
7626 /*********************************************************************
7627 * Go through all loaded kexts and tell them to register with dtrace.
7628 * The instance method only registers if necessary.
7629 *********************************************************************/
7630 /* static */
7631 void
7632 OSKext::registerKextsWithDTrace(void)
7633 {
7634 	uint32_t count = sLoadedKexts->getCount();
7635 	uint32_t i;
7636 
7637 	IORecursiveLockLock(sKextLock);
7638 
7639 	for (i = 0; i < count; i++) {
7640 		OSKext   * thisKext     = NULL;        // do not release
7641 
7642 		thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
7643 		if (!thisKext || !thisKext->isExecutable()) {
7644 			continue;
7645 		}
7646 
7647 		thisKext->registerWithDTrace();
7648 	}
7649 
7650 	IORecursiveLockUnlock(sKextLock);
7651 
7652 	return;
7653 }
7654 
7655 extern "C" {
7656 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
7657 extern int (*dtrace_modunload)(struct kmod_info *);
7658 };
7659 
7660 /*********************************************************************
7661 *********************************************************************/
7662 void
7663 OSKext::registerWithDTrace(void)
7664 {
7665 	/* Register kext with dtrace. A dtrace_modload failure should not
7666 	 * prevent a kext from loading, so we ignore the return code.
7667 	 */
7668 	if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
7669 		uint32_t modflag = 0;
7670 		OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
7671 
7672 		if (!sKeepSymbols && kc_type == KCKindPrimary) {
7673 			if (forceInit == kOSBooleanTrue) {
7674 				OSKextLog(this,
7675 				    kOSKextLogBasicLevel |
7676 				    kOSKextLogGeneralFlag,
7677 				    "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s",
7678 				    getIdentifierCString());
7679 				forceInit = kOSBooleanFalse;
7680 			}
7681 			/* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */
7682 			modflag |= KMOD_DTRACE_NO_KERNEL_SYMS;
7683 		}
7684 
7685 		if (forceInit == kOSBooleanTrue) {
7686 			modflag |= KMOD_DTRACE_FORCE_INIT;
7687 		}
7688 		if (flags.builtin) {
7689 			modflag |= KMOD_DTRACE_STATIC_KEXT;
7690 		}
7691 
7692 		(void)(*dtrace_modload)(kmod_info, modflag);
7693 		flags.dtraceInitialized = true;
7694 		jettisonLinkeditSegment();
7695 	}
7696 	return;
7697 }
7698 /*********************************************************************
7699 *********************************************************************/
7700 void
7701 OSKext::unregisterWithDTrace(void)
7702 {
7703 	/* Unregister kext with dtrace. A dtrace_modunload failure should not
7704 	 * prevent a kext from loading, so we ignore the return code.
7705 	 */
7706 	if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
7707 		(void)(*dtrace_modunload)(kmod_info);
7708 		flags.dtraceInitialized = false;
7709 	}
7710 	return;
7711 }
7712 #endif /* CONFIG_DTRACE */
7713 
7714 
7715 /*********************************************************************
7716 * called only by loadExecutable()
7717 *********************************************************************/
7718 #if !VM_MAPPED_KEXTS
7719 #if defined(__arm__) || defined(__arm64__)
7720 static inline kern_return_t
7721 OSKext_protect(
7722 	kernel_mach_header_t *kext_mh,
7723 	vm_map_t   map,
7724 	vm_map_offset_t    start,
7725 	vm_map_offset_t    end,
7726 	vm_prot_t  new_prot,
7727 	boolean_t  set_max,
7728 	kc_kind_t  kc_type)
7729 {
7730 #pragma unused(kext_mh,map,kc_type)
7731 	assert(map == kernel_map);         // we can handle KEXTs arising from the PRELINK segment and no others
7732 	assert(start <= end);
7733 	if (start >= end) {
7734 		return KERN_SUCCESS;         // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
7735 	} else if (set_max) {
7736 		return KERN_SUCCESS;         // Punt set_max, as there's no mechanism to record that state
7737 	} else {
7738 		return ml_static_protect(start, end - start, new_prot);
7739 	}
7740 }
7741 
7742 static inline kern_return_t
7743 OSKext_wire(
7744 	kernel_mach_header_t *kext_mh,
7745 	vm_map_t   map,
7746 	vm_map_offset_t    start,
7747 	vm_map_offset_t    end,
7748 	vm_prot_t  access_type,
7749 	boolean_t       user_wire,
7750 	kc_kind_t       kc_type)
7751 {
7752 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type)
7753 	return KERN_SUCCESS;         // No-op as PRELINK kexts are cemented into physical memory at boot
7754 }
7755 #else
7756 #error Unrecognized architecture
7757 #endif
7758 #else
7759 static inline kern_return_t
7760 OSKext_protect(
7761 	kernel_mach_header_t *kext_mh,
7762 	vm_map_t   map,
7763 	vm_map_offset_t    start,
7764 	vm_map_offset_t    end,
7765 	vm_prot_t  new_prot,
7766 	boolean_t  set_max,
7767 	kc_kind_t  kc_type)
7768 {
7769 	if (start == end) {         // 10538581
7770 		return KERN_SUCCESS;
7771 	}
7772 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7773 		/*
7774 		 * XXX: This will probably need to be different for AuxKC and
7775 		 * pageableKC!
7776 		 */
7777 		return ml_static_protect(start, end - start, new_prot);
7778 	}
7779 	return vm_map_protect(map, start, end, new_prot, set_max);
7780 }
7781 
7782 static inline kern_return_t
7783 OSKext_wire(
7784 	kernel_mach_header_t *kext_mh,
7785 	vm_map_t   map,
7786 	vm_map_offset_t    start,
7787 	vm_map_offset_t    end,
7788 	vm_prot_t  access_type,
7789 	boolean_t       user_wire,
7790 	kc_kind_t       kc_type)
7791 {
7792 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7793 		/* TODO: we may need to hook this for the pageableKC */
7794 		return KERN_SUCCESS;
7795 	}
7796 	return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
7797 }
7798 #endif
7799 
7800 OSReturn
7801 OSKext::setVMAttributes(bool protect, bool wire)
7802 {
7803 	vm_map_t                    kext_map        = NULL;
7804 	kernel_segment_command_t  * seg             = NULL;
7805 	vm_map_offset_t             start_protect   = 0;
7806 	vm_map_offset_t             start_wire      = 0;
7807 	vm_map_offset_t             end_protect     = 0;
7808 	vm_map_offset_t             end_wire        = 0;
7809 	OSReturn                    result          = kOSReturnError;
7810 
7811 	if (isInterface() || !declaresExecutable() || flags.builtin) {
7812 		result = kOSReturnSuccess;
7813 		goto finish;
7814 	}
7815 
7816 	/* Get the kext's vm map */
7817 	kext_map = kext_get_vm_map(kmod_info);
7818 	if (!kext_map) {
7819 		result = KERN_MEMORY_ERROR;
7820 		goto finish;
7821 	}
7822 
7823 #if !VM_MAPPED_KEXTS
7824 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
7825 		/* This is a split kext in a prelinked kernelcache; we'll let the
7826 		 * platform code take care of protecting it.  It is already wired.
7827 		 */
7828 		/* TODO: Should this still allow protections for the first segment
7829 		 * to go through, in the event that we have a mix of split and
7830 		 * unsplit kexts?
7831 		 */
7832 		result = KERN_SUCCESS;
7833 		goto finish;
7834 	}
7835 
7836 	if (isInFileset() && kc_type != KCKindPageable) {
7837 		// kexts in filesets have protections setup as part of collection loading
7838 		result = KERN_SUCCESS;
7839 		goto finish;
7840 	}
7841 #endif
7842 
7843 	/* Protect the headers as read-only; they do not need to be wired */
7844 	result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7845 	    kext_map, kmod_info->address,
7846 	    kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type)
7847 	    : KERN_SUCCESS;
7848 	if (result != KERN_SUCCESS) {
7849 		goto finish;
7850 	}
7851 
7852 	/* Set the VM protections and wire down each of the segments */
7853 	seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7854 	while (seg) {
7855 #if __arm__
7856 		/* We build all ARM kexts, so we can ensure they are aligned */
7857 		assert((seg->vmaddr & PAGE_MASK) == 0);
7858 		assert((seg->vmsize & PAGE_MASK) == 0);
7859 #endif
7860 
7861 		/*
7862 		 * For the non page aligned segments, the range calculation for protection
7863 		 * and wiring differ as follows:
7864 		 *
7865 		 * Protection: The non page aligned data at the start or at the end of the
7866 		 * segment is excluded from the protection. This exclusion is needed to make
7867 		 * sure OSKext_protect is not called twice on same page, if the page is shared
7868 		 * between two segments.
7869 		 *
7870 		 * Wiring: The non page aligned data at the start or at the end of the
7871 		 * segment is included in the wiring range, this inclusion is needed to make sure
7872 		 * all the data of the segment is wired.
7873 		 */
7874 		start_protect = round_page(seg->vmaddr);
7875 		end_protect = trunc_page(seg->vmaddr + seg->vmsize);
7876 
7877 		start_wire = trunc_page(seg->vmaddr);
7878 		end_wire = round_page(seg->vmaddr + seg->vmsize);
7879 
7880 		/*
7881 		 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared
7882 		 * across kexts and data from kexts is not page aligned
7883 		 */
7884 		if (protect && (end_protect > start_protect) &&
7885 		    ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 &&
7886 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) ||
7887 		    (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) {
7888 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7889 			    kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type);
7890 			if (result != KERN_SUCCESS) {
7891 				OSKextLog(this,
7892 				    kOSKextLogErrorLevel |
7893 				    kOSKextLogLoadFlag,
7894 				    "Kext %s failed to set maximum VM protections "
7895 				    "for segment %s - 0x%x.",
7896 				    getIdentifierCString(), seg->segname, (int)result);
7897 				goto finish;
7898 			}
7899 
7900 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7901 			    kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type);
7902 			if (result != KERN_SUCCESS) {
7903 				OSKextLog(this,
7904 				    kOSKextLogErrorLevel |
7905 				    kOSKextLogLoadFlag,
7906 				    "Kext %s failed to set initial VM protections "
7907 				    "for segment %s - 0x%x.",
7908 				    getIdentifierCString(), seg->segname, (int)result);
7909 				goto finish;
7910 			}
7911 		}
7912 
7913 		if (segmentShouldBeWired(seg) && wire) {
7914 			result = OSKext_wire((kernel_mach_header_t *)kmod_info->address,
7915 			    kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type);
7916 			if (result != KERN_SUCCESS) {
7917 				goto finish;
7918 			}
7919 		}
7920 
7921 		seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7922 	}
7923 
7924 finish:
7925 	return result;
7926 }
7927 
7928 /*********************************************************************
7929 *********************************************************************/
7930 boolean_t
7931 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
7932 {
7933 	return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) &&
7934 	       strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)));
7935 }
7936 
7937 /*********************************************************************
7938 *********************************************************************/
7939 OSReturn
7940 OSKext::validateKextMapping(bool startFlag)
7941 {
7942 	OSReturn                              result      = kOSReturnError;
7943 	const char                          * whichOp = startFlag ? "start" : "stop";
7944 	kern_return_t                         kern_result = 0;
7945 	vm_map_t                              kext_map    = NULL;
7946 	kernel_segment_command_t            * seg         = NULL;
7947 	mach_vm_address_t                     address     = 0;
7948 	mach_vm_size_t                        size        = 0;
7949 	uint32_t                              depth       = 0;
7950 	uint64_t                              kext_segbase = 0;
7951 	uint64_t                              kext_segsize = 0;
7952 	mach_msg_type_number_t                count;
7953 	vm_region_submap_short_info_data_64_t info;
7954 	uintptr_t                             kext_slide = PE_get_kc_slide(kc_type);
7955 
7956 	if (flags.builtin) {
7957 		return kOSReturnSuccess;
7958 	}
7959 
7960 	count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
7961 	bzero(&info, sizeof(info));
7962 
7963 	// xxx - do we need a distinct OSReturn value for these or is "bad data"
7964 	// xxx - sufficient?
7965 
7966 	/* Verify that the kmod_info and start/stop pointers are non-NULL.
7967 	 */
7968 	if (!kmod_info) {
7969 		OSKextLog(this,
7970 		    kOSKextLogErrorLevel |
7971 		    kOSKextLogLoadFlag,
7972 		    "Kext %s - NULL kmod_info pointer.",
7973 		    getIdentifierCString());
7974 		result = kOSKextReturnBadData;
7975 		goto finish;
7976 	}
7977 
7978 	if (startFlag) {
7979 		address = (mach_vm_address_t)kmod_info->start;
7980 	} else {
7981 		address = (mach_vm_address_t)kmod_info->stop;
7982 	}
7983 
7984 	if (!address) {
7985 		OSKextLog(this,
7986 		    kOSKextLogErrorLevel |
7987 		    kOSKextLogLoadFlag,
7988 		    "Kext %s - NULL module %s pointer.",
7989 		    getIdentifierCString(), whichOp);
7990 		result = kOSKextReturnBadData;
7991 		goto finish;
7992 	}
7993 
7994 	kext_map = kext_get_vm_map(kmod_info);
7995 	depth = (kernel_map == kext_map) ? 1 : 2;
7996 	if (isInFileset()) {
7997 #if defined(HAS_APPLE_PAC)
7998 		address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0);
7999 #endif /* defined(HAS_APPLE_PAC) */
8000 	}
8001 
8002 	/* Verify that the start/stop function lies within the kext's address range.
8003 	 */
8004 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) ||
8005 	    isInFileset()) {
8006 		/* This will likely be how we deal with split kexts; walk the segments to
8007 		 * check that the function lies inside one of the segments of this kext.
8008 		 */
8009 		for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8010 		    seg != NULL;
8011 		    seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
8012 			if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
8013 				kext_segbase = seg->vmaddr;
8014 				kext_segsize = seg->vmsize;
8015 				break;
8016 			}
8017 		}
8018 
8019 		if (!seg) {
8020 			OSKextLog(this,
8021 			    kOSKextLogErrorLevel |
8022 			    kOSKextLogLoadFlag,
8023 			    "Kext %s module %s pointer is outside of kext range "
8024 			    "(%s %p - kext starts at %p).",
8025 			    getIdentifierCString(),
8026 			    whichOp,
8027 			    whichOp,
8028 			    (void *)(((uintptr_t)address) - kext_slide),
8029 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide));
8030 			result = kOSKextReturnBadData;
8031 			goto finish;
8032 		}
8033 
8034 		seg = NULL;
8035 	} else {
8036 		if (address < kmod_info->address + kmod_info->hdr_size ||
8037 		    kmod_info->address + kmod_info->size <= address) {
8038 			OSKextLog(this,
8039 			    kOSKextLogErrorLevel |
8040 			    kOSKextLogLoadFlag,
8041 			    "Kext %s module %s pointer is outside of kext range "
8042 			    "(%s %p - kext at %p-%p).",
8043 			    getIdentifierCString(),
8044 			    whichOp,
8045 			    whichOp,
8046 			    (void *)(((uintptr_t)address) - kext_slide),
8047 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide),
8048 			    (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size));
8049 			result = kOSKextReturnBadData;
8050 			goto finish;
8051 		}
8052 	}
8053 
8054 	/* Only do these checks before calling the start function;
8055 	 * If anything goes wrong with the mapping while the kext is running,
8056 	 * we'll likely have panicked well before any attempt to stop the kext.
8057 	 */
8058 	if (startFlag) {
8059 		if (!isInFileset() || kc_type != KCKindPrimary) {
8060 			/*
8061 			 * Verify that the start/stop function is executable.
8062 			 */
8063 			kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
8064 			    (vm_region_recurse_info_t)&info, &count);
8065 			if (kern_result != KERN_SUCCESS) {
8066 				OSKextLog(this,
8067 				    kOSKextLogErrorLevel |
8068 				    kOSKextLogLoadFlag,
8069 				    "Kext %s - bad %s pointer %p.",
8070 				    getIdentifierCString(),
8071 				    whichOp, (void *)ml_static_unslide(address));
8072 				result = kOSKextReturnBadData;
8073 				goto finish;
8074 			}
8075 		} else {
8076 			/*
8077 			 * Since kexts loaded from the primary KC are held in memory
8078 			 * allocated by efiboot, we cannot use mach_vm_region_recurse() to
8079 			 * discover that memory's protection flags.  Instead, we need to
8080 			 * get that information from the kernel pmap itself.  Above, we
8081 			 * (potentially) saved the size of the segment in which the address
8082 			 * in question was located.  If we have a non-zero size, verify
8083 			 * that all pages in the (address, address + kext_segsize) range
8084 			 * are marked executable.  If we somehow did not record the size
8085 			 * (or the base) just verify the single page that includes the address.
8086 			 */
8087 			if (kext_segbase == 0 || kext_segsize == 0) {
8088 				kext_segbase = address & ~(uint64_t)PAGE_MASK;
8089 				kext_segsize = PAGE_SIZE;
8090 			}
8091 		}
8092 
8093 #if VM_MAPPED_KEXTS
8094 		if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) ||
8095 		    ((isInFileset() && kc_type == KCKindPrimary) &&
8096 		    ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) {
8097 			OSKextLog(this,
8098 			    kOSKextLogErrorLevel |
8099 			    kOSKextLogLoadFlag,
8100 			    "Kext %s - memory region containing module %s function "
8101 			    "is not executable.",
8102 			    getIdentifierCString(), whichOp);
8103 			result = kOSKextReturnBadData;
8104 			goto finish;
8105 		}
8106 #endif
8107 
8108 		/* Verify that the kext's segments are backed by physical memory.
8109 		 */
8110 		seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8111 		while (seg) {
8112 			if (!verifySegmentMapping(seg)) {
8113 				result = kOSKextReturnBadData;
8114 				goto finish;
8115 			}
8116 
8117 			seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8118 		}
8119 	}
8120 
8121 	result = kOSReturnSuccess;
8122 finish:
8123 	return result;
8124 }
8125 
8126 /*********************************************************************
8127 *********************************************************************/
8128 boolean_t
8129 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
8130 {
8131 	mach_vm_address_t address = 0;
8132 
8133 	if (seg->vmsize > UINT32_MAX) {
8134 		return false;
8135 	}
8136 
8137 	if (!segmentShouldBeWired(seg)) {
8138 		return true;
8139 	}
8140 
8141 	for (address = seg->vmaddr;
8142 	    address < round_page(seg->vmaddr + seg->vmsize);
8143 	    address += PAGE_SIZE) {
8144 		if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
8145 			OSKextLog(this,
8146 			    kOSKextLogErrorLevel |
8147 			    kOSKextLogLoadFlag,
8148 			    "Kext %s - page %p is not backed by physical memory.",
8149 			    getIdentifierCString(),
8150 			    (void *)address);
8151 			return false;
8152 		}
8153 	}
8154 
8155 	return true;
8156 }
8157 
8158 /*********************************************************************
8159 *********************************************************************/
8160 static void
8161 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
8162 {
8163 	uint64_t                            stamp = 0;
8164 	firehose_tracepoint_id_u            trace_id;
8165 	struct firehose_trace_uuid_info_s   uuid_info_s;
8166 	firehose_trace_uuid_info_t          uuid_info = &uuid_info_s;
8167 	size_t                              uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
8168 	OSSharedPtr<OSData>                 uuid_data;
8169 
8170 	stamp = firehose_tracepoint_time(firehose_activity_flags_default);
8171 	trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
8172 
8173 	uuid_data = aKext->copyTextUUID();
8174 	if (uuid_data) {
8175 		memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
8176 	}
8177 
8178 	uuid_info->ftui_size    = size;
8179 	if (aKext->isDriverKit()) {
8180 		uuid_info->ftui_address = address;
8181 	} else {
8182 		uuid_info->ftui_address = ml_static_unslide(address);
8183 	}
8184 	firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
8185 	return;
8186 }
8187 
8188 void
8189 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
8190 {
8191 	OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
8192 }
8193 
8194 /*********************************************************************
8195 *********************************************************************/
8196 OSReturn
8197 OSKext::start(bool startDependenciesFlag)
8198 {
8199 	OSReturn                            result = kOSReturnError;
8200 	kern_return_t                       (* startfunc)(kmod_info_t *, void *);
8201 	unsigned int                        i, count;
8202 	void                              * kmodStartData = NULL;
8203 
8204 	if (isStarted() || isInterface() || isKernelComponent()) {
8205 		result = kOSReturnSuccess;
8206 		goto finish;
8207 	}
8208 
8209 	if (!isLoaded()) {
8210 		OSKextLog(this,
8211 		    kOSKextLogErrorLevel |
8212 		    kOSKextLogLoadFlag,
8213 		    "Attempt to start nonloaded kext %s.",
8214 		    getIdentifierCString());
8215 		result = kOSKextReturnInvalidArgument;
8216 		goto finish;
8217 	}
8218 
8219 	if (!sLoadEnabled) {
8220 		OSKextLog(this,
8221 		    kOSKextLogErrorLevel |
8222 		    kOSKextLogLoadFlag,
8223 		    "Kext loading is disabled (attempt to start kext %s).",
8224 		    getIdentifierCString());
8225 		result = kOSKextReturnDisabled;
8226 		goto finish;
8227 	}
8228 
8229 	result = validateKextMapping(/* start? */ true);
8230 	if (result != kOSReturnSuccess) {
8231 		goto finish;
8232 	}
8233 
8234 	startfunc = kmod_info->start;
8235 
8236 	count = getNumDependencies();
8237 	for (i = 0; i < count; i++) {
8238 		OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
8239 		if (dependency == NULL) {
8240 			OSKextLog(this,
8241 			    kOSKextLogErrorLevel |
8242 			    kOSKextLogLoadFlag,
8243 			    "Kext %s start - internal error, dependency disappeared.",
8244 			    getIdentifierCString());
8245 			goto finish;
8246 		}
8247 		if (!dependency->isStarted()) {
8248 			if (startDependenciesFlag) {
8249 				OSReturn dependencyResult =
8250 				    dependency->start(startDependenciesFlag);
8251 				if (dependencyResult != KERN_SUCCESS) {
8252 					OSKextLog(this,
8253 					    kOSKextLogErrorLevel |
8254 					    kOSKextLogLoadFlag,
8255 					    "Kext %s start - dependency %s failed to start (error 0x%x).",
8256 					    getIdentifierCString(),
8257 					    dependency->getIdentifierCString(),
8258 					    dependencyResult);
8259 					goto finish;
8260 				}
8261 			} else {
8262 				OSKextLog(this,
8263 				    kOSKextLogErrorLevel |
8264 				    kOSKextLogLoadFlag,
8265 				    "Not starting %s - dependency %s not started yet.",
8266 				    getIdentifierCString(),
8267 				    dependency->getIdentifierCString());
8268 				result = kOSKextReturnStartStopError;         // xxx - make new return?
8269 				goto finish;
8270 			}
8271 		}
8272 	}
8273 
8274 	OSKextLog(this,
8275 	    kOSKextLogDetailLevel |
8276 	    kOSKextLogLoadFlag,
8277 	    "Kext %s calling module start function.",
8278 	    getIdentifierCString());
8279 
8280 	flags.starting = 1;
8281 
8282 	// Drop a log message so logd can grab the needed information to decode this kext
8283 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
8284 	result = OSRuntimeInitializeCPP(this);
8285 	if (result == KERN_SUCCESS) {
8286 		result = startfunc(kmod_info, kmodStartData);
8287 	}
8288 
8289 	flags.starting = 0;
8290 
8291 	/* On success overlap the setting of started/starting. On failure just
8292 	 * clear starting.
8293 	 */
8294 	if (result == KERN_SUCCESS) {
8295 		flags.started = 1;
8296 
8297 		// xxx - log start error from kernel?
8298 		OSKextLog(this,
8299 		    kOSKextLogProgressLevel |
8300 		    kOSKextLogLoadFlag,
8301 		    "Kext %s is now started.",
8302 		    getIdentifierCString());
8303 	} else {
8304 		invokeOrCancelRequestCallbacks(
8305 			/* result not actually used */ kOSKextReturnStartStopError,
8306 			/* invokeFlag */ false);
8307 		OSKextLog(this,
8308 		    kOSKextLogWarningLevel |
8309 		    kOSKextLogLoadFlag,
8310 		    "Kext %s did not start (return code 0x%x).",
8311 		    getIdentifierCString(), result);
8312 	}
8313 
8314 finish:
8315 	return result;
8316 }
8317 
8318 /*********************************************************************
8319 *********************************************************************/
8320 /* static */
8321 bool
8322 OSKext::canUnloadKextWithIdentifier(
8323 	OSString * kextIdentifier,
8324 	bool       checkClassesFlag)
8325 {
8326 	bool     result = false;
8327 	OSKext * aKext  = NULL;        // do not release
8328 
8329 	IORecursiveLockLock(sKextLock);
8330 
8331 	aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
8332 
8333 	if (!aKext) {
8334 		goto finish;         // can't unload what's not loaded
8335 	}
8336 
8337 	if (aKext->isLoaded()) {
8338 		if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
8339 			goto finish;
8340 		}
8341 		if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
8342 			goto finish;
8343 		}
8344 	}
8345 
8346 	result = true;
8347 
8348 finish:
8349 	IORecursiveLockUnlock(sKextLock);
8350 	return result;
8351 }
8352 
8353 /*********************************************************************
8354 *********************************************************************/
8355 OSReturn
8356 OSKext::stop(void)
8357 {
8358 	OSReturn result = kOSReturnError;
8359 	kern_return_t (*stopfunc)(kmod_info_t *, void *);
8360 
8361 	if (!isStarted() || isInterface()) {
8362 		result = kOSReturnSuccess;
8363 		goto finish;
8364 	}
8365 
8366 	if (!isLoaded()) {
8367 		OSKextLog(this,
8368 		    kOSKextLogErrorLevel |
8369 		    kOSKextLogLoadFlag,
8370 		    "Attempt to stop nonloaded kext %s.",
8371 		    getIdentifierCString());
8372 		result = kOSKextReturnInvalidArgument;
8373 		goto finish;
8374 	}
8375 
8376 	/* Refuse to stop if we have clients or instances. It is up to
8377 	 * the caller to make sure those aren't true.
8378 	 */
8379 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8380 		OSKextLog(this,
8381 		    kOSKextLogErrorLevel |
8382 		    kOSKextLogLoadFlag,
8383 		    "Kext %s - C++ instances; can't stop.",
8384 		    getIdentifierCString());
8385 		result = kOSKextReturnInUse;
8386 		goto finish;
8387 	}
8388 
8389 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8390 		OSKextLog(this,
8391 		    kOSKextLogErrorLevel |
8392 		    kOSKextLogLoadFlag,
8393 		    "Kext %s - has references (linkage or tracking object); "
8394 		    "can't stop.",
8395 		    getIdentifierCString());
8396 		result = kOSKextReturnInUse;
8397 		goto finish;
8398 	}
8399 
8400 	/* Note: If validateKextMapping fails on the stop & unload path,
8401 	 * we are in serious trouble and a kernel panic is likely whether
8402 	 * we stop & unload the kext or not.
8403 	 */
8404 	result = validateKextMapping(/* start? */ false);
8405 	if (result != kOSReturnSuccess) {
8406 		goto finish;
8407 	}
8408 
8409 	stopfunc = kmod_info->stop;
8410 	if (stopfunc) {
8411 		OSKextLog(this,
8412 		    kOSKextLogDetailLevel |
8413 		    kOSKextLogLoadFlag,
8414 		    "Kext %s calling module stop function.",
8415 		    getIdentifierCString());
8416 
8417 		flags.stopping = 1;
8418 
8419 		result = stopfunc(kmod_info, /* userData */ NULL);
8420 		if (result == KERN_SUCCESS) {
8421 			result = OSRuntimeFinalizeCPP(this);
8422 		}
8423 
8424 		flags.stopping = 0;
8425 
8426 		if (result == KERN_SUCCESS) {
8427 			flags.started = 0;
8428 
8429 			OSKextLog(this,
8430 			    kOSKextLogDetailLevel |
8431 			    kOSKextLogLoadFlag,
8432 			    "Kext %s is now stopped and ready to unload.",
8433 			    getIdentifierCString());
8434 		} else {
8435 			OSKextLog(this,
8436 			    kOSKextLogErrorLevel |
8437 			    kOSKextLogLoadFlag,
8438 			    "Kext %s did not stop (return code 0x%x).",
8439 			    getIdentifierCString(), result);
8440 			result = kOSKextReturnStartStopError;
8441 		}
8442 	}
8443 
8444 finish:
8445 	// Drop a log message so logd can update this kext's metadata
8446 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
8447 	return result;
8448 }
8449 
8450 /*********************************************************************
8451 *********************************************************************/
8452 OSReturn
8453 OSKext::unload(void)
8454 {
8455 	OSReturn        result = kOSReturnError;
8456 	unsigned int    index;
8457 	uint32_t        num_kmod_refs = 0;
8458 	OSKextAccount * freeAccount;
8459 	bool            in_fileset = false;
8460 
8461 	if (!sUnloadEnabled) {
8462 		OSKextLog(this,
8463 		    kOSKextLogErrorLevel |
8464 		    kOSKextLogLoadFlag,
8465 		    "Kext unloading is disabled (%s).",
8466 		    this->getIdentifierCString());
8467 
8468 		result = kOSKextReturnDisabled;
8469 		goto finish;
8470 	}
8471 
8472 	// cache this result so we don't need to access the kmod_info after
8473 	// it's been potentially free'd
8474 	in_fileset = isInFileset();
8475 
8476 	/* Refuse to unload if we have clients or instances. It is up to
8477 	 * the caller to make sure those aren't true.
8478 	 */
8479 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8480 		// xxx - Don't log under errors? this is more of an info thing
8481 		OSKextLog(this,
8482 		    kOSKextLogErrorLevel |
8483 		    kOSKextLogKextBookkeepingFlag,
8484 		    "Can't unload kext %s; outstanding references %d (linkage or tracking object).",
8485 		    getIdentifierCString(), getRetainCount());
8486 		result = kOSKextReturnInUse;
8487 		goto finish;
8488 	}
8489 
8490 	if (isDriverKit()) {
8491 		index = sLoadedDriverKitKexts->getNextIndexOfObject(this, 0);
8492 		if (index != (unsigned int)-1) {
8493 			sLoadedDriverKitKexts->removeObject(index);
8494 			OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
8495 			loadTag = 0;
8496 		}
8497 	}
8498 
8499 	if (!isLoaded()) {
8500 		result = kOSReturnSuccess;
8501 		goto finish;
8502 	}
8503 
8504 	if (isKernelComponent()) {
8505 		result = kOSKextReturnInvalidArgument;
8506 		goto finish;
8507 	}
8508 
8509 	if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) {
8510 		OSKextLog(this,
8511 		    kOSKextLogErrorLevel |
8512 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8513 		    "Can't unload kext %s; classes have instances:",
8514 		    getIdentifierCString());
8515 		reportOSMetaClassInstances(kOSKextLogErrorLevel |
8516 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
8517 		result = kOSKextReturnInUse;
8518 		goto finish;
8519 	}
8520 
8521 	/* Note that the kext is unloading before running any code that
8522 	 * might be in the kext (request callbacks, module stop function).
8523 	 * We will deny certain requests made against a kext in the process
8524 	 * of unloading.
8525 	 */
8526 	flags.unloading = 1;
8527 
8528 	/* Update the string describing the last kext to unload in case we panic.
8529 	 */
8530 	savePanicString(/* isLoading */ false);
8531 
8532 	if (isStarted()) {
8533 		result = stop();
8534 		if (result != KERN_SUCCESS) {
8535 			OSKextLog(this,
8536 			    kOSKextLogErrorLevel |
8537 			    kOSKextLogLoadFlag,
8538 			    "Kext %s can't unload - module stop returned 0x%x.",
8539 			    getIdentifierCString(), (unsigned)result);
8540 			result = kOSKextReturnStartStopError;
8541 			goto finish;
8542 		}
8543 	}
8544 
8545 	OSKextLog(this,
8546 	    kOSKextLogProgressLevel |
8547 	    kOSKextLogLoadFlag,
8548 	    "Kext %s unloading.",
8549 	    getIdentifierCString());
8550 
8551 	{
8552 		struct list_head *p;
8553 		struct list_head *prev;
8554 		struct list_head *next;
8555 		for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
8556 			OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
8557 			s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
8558 			prev = p->prev;
8559 			next = p->next;
8560 			prev->next = next;
8561 			next->prev = prev;
8562 			p->prev = p;
8563 			p->next = p;
8564 			IORecursiveLockWakeup(sKextLock, s, false);
8565 		}
8566 	}
8567 
8568 
8569 	/* Even if we don't call the stop function, we want to be sure we
8570 	 * have no OSMetaClass references before unloading the kext executable
8571 	 * from memory. OSMetaClasses may have pointers into the kext executable
8572 	 * and that would cause a panic on OSKext::free() when metaClasses is freed.
8573 	 */
8574 	if (metaClasses) {
8575 		metaClasses->flushCollection();
8576 	}
8577 	(void) OSRuntimeFinalizeCPP(this);
8578 
8579 	/* Remove the kext from the list of loaded kexts, patch the gap
8580 	 * in the kmod_info_t linked list, and reset "kmod" to point to the
8581 	 * last loaded kext that isn't the fake kernel kext (sKernelKext).
8582 	 */
8583 	index = sLoadedKexts->getNextIndexOfObject(this, 0);
8584 	if (index != (unsigned int)-1) {
8585 		sLoadedKexts->removeObject(index);
8586 
8587 		OSKext * nextKext = OSDynamicCast(OSKext,
8588 		    sLoadedKexts->getObject(index));
8589 
8590 		if (nextKext) {
8591 			if (index > 0) {
8592 				OSKext * gapKext = OSDynamicCast(OSKext,
8593 				    sLoadedKexts->getObject(index - 1));
8594 
8595 				nextKext->kmod_info->next = gapKext->kmod_info;
8596 			} else {         /* index == 0 */
8597 				nextKext->kmod_info->next = NULL;
8598 			}
8599 		}
8600 
8601 		OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
8602 		if (lastKext && !lastKext->isKernel()) {
8603 			kmod = lastKext->kmod_info;
8604 		} else {
8605 			kmod = NULL;         // clear the global kmod variable
8606 		}
8607 	}
8608 
8609 	/* Clear out the kmod references that we're keeping for compatibility
8610 	 * with current panic backtrace code & kgmacros.
8611 	 * xxx - will want to update those bits sometime and remove this.
8612 	 */
8613 	num_kmod_refs = getNumDependencies();
8614 	if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
8615 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
8616 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
8617 			ref->info->reference_count--;
8618 		}
8619 		kfree_type(kmod_reference_t, num_kmod_refs,
8620 		    kmod_info->reference_list);
8621 	}
8622 
8623 #if CONFIG_DTRACE
8624 	unregisterWithDTrace();
8625 #endif /* CONFIG_DTRACE */
8626 
8627 	notifyKextUnloadObservers(this);
8628 
8629 	freeAccount = NULL;
8630 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
8631 	account->kext = NULL;
8632 	if (account->site.tag) {
8633 		account->site.flags |= VM_TAG_UNLOAD;
8634 	} else {
8635 		freeAccount = account;
8636 	}
8637 
8638 #if DEVELOPMENT || DEBUG
8639 	assertf(account->task_refgrp.grp_count == 0,
8640 	    "unloading a kext with active task references");
8641 #endif /* DEVELOPMENT || DEBUG */
8642 
8643 	lck_ticket_unlock(sKextAccountsLock);
8644 	if (freeAccount) {
8645 		IOFreeType(freeAccount, OSKextAccount);
8646 	}
8647 
8648 	/* Unwire and free the linked executable.
8649 	 */
8650 	if (linkedExecutable) {
8651 #if KASAN
8652 		kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
8653 #endif
8654 
8655 #if VM_MAPPED_KEXTS
8656 		if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) {
8657 			kernel_segment_command_t *seg = NULL;
8658 			vm_map_t kext_map = kext_get_vm_map(kmod_info);
8659 
8660 			if (!kext_map) {
8661 				OSKextLog(this,
8662 				    kOSKextLogErrorLevel |
8663 				    kOSKextLogLoadFlag,
8664 				    "Failed to free kext %s; couldn't find the kext map.",
8665 				    getIdentifierCString());
8666 				result = kOSKextReturnInternalError;
8667 				goto finish;
8668 			}
8669 
8670 			OSKextLog(this,
8671 			    kOSKextLogProgressLevel |
8672 			    kOSKextLogLoadFlag,
8673 			    "Kext %s unwiring and unmapping linked executable.",
8674 			    getIdentifierCString());
8675 
8676 			seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8677 			while (seg) {
8678 				if (segmentShouldBeWired(seg)) {
8679 					vm_map_offset_t start_wire = trunc_page(seg->vmaddr);
8680 					vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize);
8681 
8682 					result = vm_map_unwire(kext_map, start_wire,
8683 					    end_wire, FALSE);
8684 					if (result != KERN_SUCCESS) {
8685 						OSKextLog(this,
8686 						    kOSKextLogErrorLevel |
8687 						    kOSKextLogLoadFlag,
8688 						    "Failed to unwire kext %s.",
8689 						    getIdentifierCString());
8690 						result = kOSKextReturnInternalError;
8691 						goto finish;
8692 					}
8693 				}
8694 
8695 				seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8696 			}
8697 #if defined(__x86_64__) || defined(__i386__)
8698 			if (in_fileset && flags.resetSegmentsFromVnode) {
8699 				IORecursiveLockLock(sKextLock);
8700 				resetKCFileSetSegments();
8701 				IORecursiveLockUnlock(sKextLock);
8702 			}
8703 #endif // (__x86_64__) || defined(__i386__)
8704 		}
8705 #endif /* VM_MAPPED_KEXTS */
8706 		if (flags.resetSegmentsFromImmutableCopy) {
8707 			result = resetMutableSegments();
8708 			if (result != kOSReturnSuccess) {
8709 				OSKextLog(this,
8710 				    kOSKextLogErrorLevel |
8711 				    kOSKextLogLoadFlag,
8712 				    "Failed to reset kext %s.",
8713 				    getIdentifierCString());
8714 				result = kOSKextReturnInternalError;
8715 				goto finish;
8716 			}
8717 		}
8718 		if (kc_type == KCKindUnknown) {
8719 			linkedExecutable.reset();
8720 		}
8721 	}
8722 
8723 	/* An interface kext has a fake kmod_info that was allocated,
8724 	 * so we have to free it.
8725 	 */
8726 	if (isInterface()) {
8727 		kfree_type(kmod_info_t, kmod_info);
8728 		kmod_info = NULL;
8729 	}
8730 
8731 	if (!in_fileset) {
8732 		kmod_info = NULL;
8733 	}
8734 
8735 	flags.loaded = false;
8736 	flushDependencies();
8737 
8738 	/* save a copy of the bundle ID for us to check when deciding to
8739 	 * rebuild the kernel cache file.  If a kext was already in the kernel
8740 	 * cache and unloaded then later loaded we do not need to rebuild the
8741 	 * kernel cache.  9055303
8742 	 */
8743 	if (isPrelinked()) {
8744 		if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) {
8745 			IORecursiveLockLock(sKextLock);
8746 			if (sUnloadedPrelinkedKexts) {
8747 				sUnloadedPrelinkedKexts->setObject(bundleID.get());
8748 			}
8749 			IORecursiveLockUnlock(sKextLock);
8750 		}
8751 	}
8752 
8753 	OSKextLog(this,
8754 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8755 	    "Kext %s unloaded.", getIdentifierCString());
8756 
8757 	queueKextNotification(kKextRequestPredicateUnloadNotification,
8758 	    OSDynamicCast(OSString, bundleID.get()));
8759 
8760 finish:
8761 	OSKext::saveLoadedKextPanicList();
8762 	OSKext::updateLoadedKextSummaries();
8763 
8764 	flags.unloading = 0;
8765 	return result;
8766 }
8767 
8768 /*********************************************************************
8769 * Assumes sKextLock is held.
8770 *********************************************************************/
8771 /* static */
8772 OSReturn
8773 OSKext::queueKextNotification(
8774 	const char * notificationName,
8775 	OSString   * kextIdentifier)
8776 {
8777 	OSReturn          result               = kOSReturnError;
8778 	OSSharedPtr<OSDictionary>    loadRequest;
8779 
8780 	if (!kextIdentifier) {
8781 		result = kOSKextReturnInvalidArgument;
8782 		goto finish;
8783 	}
8784 
8785 	/* Create a new request unless one is already sitting
8786 	 * in sKernelRequests for this bundle identifier
8787 	 */
8788 	result = _OSKextCreateRequest(notificationName, loadRequest);
8789 	if (result != kOSReturnSuccess) {
8790 		goto finish;
8791 	}
8792 	if (!_OSKextSetRequestArgument(loadRequest.get(),
8793 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
8794 		result = kOSKextReturnNoMemory;
8795 		goto finish;
8796 	}
8797 	if (!sKernelRequests->setObject(loadRequest.get())) {
8798 		result = kOSKextReturnNoMemory;
8799 		goto finish;
8800 	}
8801 
8802 	/* We might want to only queue the notification if the IOKit daemon is active,
8803 	 * but that wouldn't work for embedded. Note that we don't care if
8804 	 * the ping immediately succeeds here so don't do anything with the
8805 	 * result of this call.
8806 	 */
8807 	OSKext::pingIOKitDaemon();
8808 
8809 	result = kOSReturnSuccess;
8810 
8811 finish:
8812 	return result;
8813 }
8814 
8815 
8816 #if CONFIG_KXLD
8817 /*********************************************************************
8818 *********************************************************************/
8819 static void
8820 _OSKextConsiderDestroyingLinkContext(
8821 	__unused thread_call_param_t p0,
8822 	__unused thread_call_param_t p1)
8823 {
8824 	/* Take multiple locks in the correct order.
8825 	 */
8826 	IORecursiveLockLock(sKextLock);
8827 	IORecursiveLockLock(sKextInnerLock);
8828 
8829 	/* The first time we destroy the kxldContext is in the first
8830 	 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
8831 	 * before calling this function. Thereafter any call to this function
8832 	 * will actually destroy the context.
8833 	 */
8834 	if (sConsiderUnloadsCalled && sKxldContext) {
8835 		kxld_destroy_context(sKxldContext);
8836 		sKxldContext = NULL;
8837 	}
8838 
8839 	/* Free the thread_call that was allocated to execute this function.
8840 	 */
8841 	if (sDestroyLinkContextThread) {
8842 		if (!thread_call_free(sDestroyLinkContextThread)) {
8843 			OSKextLog(/* kext */ NULL,
8844 			    kOSKextLogErrorLevel |
8845 			    kOSKextLogGeneralFlag,
8846 			    "thread_call_free() failed for kext link context.");
8847 		}
8848 		sDestroyLinkContextThread = NULL;
8849 	}
8850 
8851 	IORecursiveLockUnlock(sKextInnerLock);
8852 	IORecursiveLockUnlock(sKextLock);
8853 
8854 	return;
8855 }
8856 
8857 /*********************************************************************
8858 * Destroying the kxldContext requires checking variables under both
8859 * sKextInnerLock and sKextLock, so we do it on a separate thread
8860 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
8861 * call relationship.
8862 *
8863 * This function must be invoked with sKextInnerLock held.
8864 * Do not call any function that takes sKextLock here!
8865 *********************************************************************/
8866 /* static */
8867 void
8868 OSKext::considerDestroyingLinkContext(void)
8869 {
8870 	IORecursiveLockLock(sKextInnerLock);
8871 
8872 	/* If we have already queued a thread to destroy the link context,
8873 	 * don't bother resetting; that thread will take care of it.
8874 	 */
8875 	if (sDestroyLinkContextThread) {
8876 		goto finish;
8877 	}
8878 
8879 	/* The function to be invoked in the thread will deallocate
8880 	 * this thread_call, so don't share it around.
8881 	 */
8882 	sDestroyLinkContextThread = thread_call_allocate(
8883 		&_OSKextConsiderDestroyingLinkContext, NULL);
8884 	if (!sDestroyLinkContextThread) {
8885 		OSKextLog(/* kext */ NULL,
8886 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
8887 		    "Can't create thread to destroy kext link context.");
8888 		goto finish;
8889 	}
8890 
8891 	thread_call_enter(sDestroyLinkContextThread);
8892 
8893 finish:
8894 	IORecursiveLockUnlock(sKextInnerLock);
8895 	return;
8896 }
8897 
8898 #else // !CONFIG_KXLD
8899 
8900 /* static */
8901 void
8902 OSKext::considerDestroyingLinkContext(void)
8903 {
8904 	return;
8905 }
8906 
8907 #endif // CONFIG_KXLD
8908 
8909 #if PRAGMA_MARK
8910 #pragma mark Autounload
8911 #endif
8912 /*********************************************************************
8913 * This is a static method because the kext will be deallocated if it
8914 * does unload!
8915 *********************************************************************/
8916 /* static */
8917 OSReturn
8918 OSKext::autounloadKext(OSKext * aKext)
8919 {
8920 	OSReturn result = kOSKextReturnInUse;
8921 
8922 #if NO_KEXTD
8923 	/*
8924 	 * Do not unload prelinked kexts on platforms that do not have an
8925 	 * IOKit daemon as there is no way to reload the kext or restart
8926 	 * matching.
8927 	 */
8928 	if (aKext->isPrelinked()) {
8929 		goto finish;
8930 	}
8931 #endif /* defined(__x86_64__) */
8932 
8933 	/* Check for external references to this kext (usu. dependents),
8934 	 * instances of defined classes (or classes derived from them),
8935 	 * outstanding requests.
8936 	 */
8937 	if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
8938 	    !aKext->flags.autounloadEnabled ||
8939 	    aKext->isKernelComponent()) {
8940 		goto finish;
8941 	}
8942 
8943 	/* Skip a delay-autounload kext, once.
8944 	 */
8945 	if (aKext->flags.delayAutounload) {
8946 		OSKextLog(aKext,
8947 		    kOSKextLogProgressLevel |
8948 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8949 		    "Kext %s has delayed autounload set; skipping and clearing flag.",
8950 		    aKext->getIdentifierCString());
8951 		aKext->flags.delayAutounload = 0;
8952 		goto finish;
8953 	}
8954 
8955 	if (aKext->hasOSMetaClassInstances() ||
8956 	    aKext->countRequestCallbacks()) {
8957 		goto finish;
8958 	}
8959 
8960 	result = OSKext::removeKext(aKext);
8961 
8962 finish:
8963 	return result;
8964 }
8965 
8966 /*********************************************************************
8967 *********************************************************************/
8968 void
8969 _OSKextConsiderUnloads(
8970 	__unused thread_call_param_t p0,
8971 	__unused thread_call_param_t p1)
8972 {
8973 	bool         didUnload = false;
8974 	unsigned int count, i;
8975 
8976 	/* Take multiple locks in the correct order
8977 	 * (note also sKextSummaries lock further down).
8978 	 */
8979 	IORecursiveLockLock(sKextLock);
8980 	IORecursiveLockLock(sKextInnerLock);
8981 
8982 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
8983 
8984 	/* If the system is powering down, don't try to unload anything.
8985 	 */
8986 	if (sSystemSleep) {
8987 		goto finish;
8988 	}
8989 
8990 	OSKextLog(/* kext */ NULL,
8991 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8992 	    "Checking for unused kexts to autounload.");
8993 
8994 	/*****
8995 	 * Remove any request callbacks marked as stale,
8996 	 * and mark as stale any currently in flight.
8997 	 */
8998 	count = sRequestCallbackRecords->getCount();
8999 	if (count) {
9000 		i = count - 1;
9001 		do {
9002 			OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
9003 			    sRequestCallbackRecords->getObject(i));
9004 			if (callbackRecord) {
9005 				OSBoolean * stale = OSDynamicCast(OSBoolean,
9006 				    callbackRecord->getObject(kKextRequestStaleKey));
9007 
9008 				if (stale == kOSBooleanTrue) {
9009 					OSKext::invokeRequestCallback(callbackRecord,
9010 					    kOSKextReturnTimeout);
9011 				} else {
9012 					callbackRecord->setObject(kKextRequestStaleKey,
9013 					    kOSBooleanTrue);
9014 				}
9015 			}
9016 		} while (i--);
9017 	}
9018 
9019 	/*****
9020 	 * Make multiple passes through the array of loaded kexts until
9021 	 * we don't unload any. This handles unwinding of dependency
9022 	 * chains. We have to go *backwards* through the array because
9023 	 * kexts are removed from it when unloaded, and we cannot make
9024 	 * a copy or we'll mess up the retain counts we rely on to
9025 	 * check whether a kext will unload. If only we could have
9026 	 * nonretaining collections like CF has....
9027 	 */
9028 	do {
9029 		didUnload = false;
9030 
9031 		count = sLoadedKexts->getCount();
9032 		if (count) {
9033 			i = count - 1;
9034 			do {
9035 				OSKext * thisKext = OSDynamicCast(OSKext,
9036 				    sLoadedKexts->getObject(i));
9037 				didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
9038 			} while (i--);
9039 		}
9040 	} while (didUnload);
9041 
9042 finish:
9043 	sConsiderUnloadsPending = false;
9044 	sConsiderUnloadsExecuted = true;
9045 
9046 	(void) OSKext::considerRebuildOfPrelinkedKernel();
9047 
9048 	IORecursiveLockUnlock(sKextInnerLock);
9049 	IORecursiveLockUnlock(sKextLock);
9050 
9051 	return;
9052 }
9053 
9054 /*********************************************************************
9055 * Do not call any function that takes sKextLock here!
9056 *********************************************************************/
9057 void
9058 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
9059 {
9060 	AbsoluteTime when;
9061 
9062 	IORecursiveLockLock(sKextInnerLock);
9063 
9064 	if (!sUnloadCallout) {
9065 		sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
9066 	}
9067 
9068 	/* we only reset delay value for unloading if we already have something
9069 	 * pending.  rescheduleOnlyFlag should not start the count down.
9070 	 */
9071 	if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
9072 		goto finish;
9073 	}
9074 
9075 	thread_call_cancel(sUnloadCallout);
9076 	if (OSKext::getAutounloadEnabled() && !sSystemSleep
9077 #if !NO_KEXTD
9078 	    && sIOKitDaemonActive
9079 #endif
9080 	    ) {
9081 		clock_interval_to_deadline(sConsiderUnloadDelay,
9082 		    1000 * 1000 * 1000, &when);
9083 
9084 		OSKextLog(/* kext */ NULL,
9085 		    kOSKextLogProgressLevel |
9086 		    kOSKextLogLoadFlag,
9087 		    "%scheduling %sscan for unused kexts in %lu seconds.",
9088 		    sConsiderUnloadsPending ? "Res" : "S",
9089 		    sConsiderUnloadsCalled ? "" : "initial ",
9090 		    (unsigned long)sConsiderUnloadDelay);
9091 
9092 		sConsiderUnloadsPending = true;
9093 		thread_call_enter_delayed(sUnloadCallout, when);
9094 	}
9095 
9096 finish:
9097 	/* The kxld context should be reused throughout boot.  We mark the end of
9098 	 * period as the first time considerUnloads() is called, and we destroy
9099 	 * the first kxld context in that function.  Afterwards, it will be
9100 	 * destroyed in flushNonloadedKexts.
9101 	 */
9102 	if (!sConsiderUnloadsCalled) {
9103 		sConsiderUnloadsCalled = true;
9104 		OSKext::considerDestroyingLinkContext();
9105 	}
9106 
9107 	IORecursiveLockUnlock(sKextInnerLock);
9108 	return;
9109 }
9110 
9111 /*********************************************************************
9112 * Do not call any function that takes sKextLock here!
9113 *********************************************************************/
9114 extern "C" {
9115 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
9116 IOReturn
9117 OSKextSystemSleepOrWake(UInt32 messageType)
9118 {
9119 	IORecursiveLockLock(sKextInnerLock);
9120 
9121 	/* If the system is going to sleep, cancel the reaper thread timer,
9122 	 * and note that we're in a sleep state in case it just fired but hasn't
9123 	 * taken the lock yet. If we are coming back from sleep, just
9124 	 * clear the sleep flag; IOService's normal operation will cause
9125 	 * unloads to be considered soon enough.
9126 	 */
9127 	if (messageType == kIOMessageSystemWillSleep) {
9128 		if (sUnloadCallout) {
9129 			thread_call_cancel(sUnloadCallout);
9130 		}
9131 		sSystemSleep = true;
9132 		AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
9133 	} else if (messageType == kIOMessageSystemHasPoweredOn) {
9134 		sSystemSleep = false;
9135 		clock_get_uptime(&sLastWakeTime);
9136 	}
9137 	IORecursiveLockUnlock(sKextInnerLock);
9138 
9139 	return kIOReturnSuccess;
9140 }
9141 };
9142 
9143 
9144 #if PRAGMA_MARK
9145 #pragma mark Prelinked Kernel
9146 #endif
9147 
9148 #ifdef CONFIG_KXLD
9149 /*********************************************************************
9150 * Do not access sConsiderUnloads... variables other than
9151 * sConsiderUnloadsExecuted in this function. They are guarded by a
9152 * different lock.
9153 *********************************************************************/
9154 /* static */
9155 void
9156 OSKext::considerRebuildOfPrelinkedKernel(void)
9157 {
9158 	static bool     requestedPrelink        = false;
9159 	OSReturn        checkResult             = kOSReturnError;
9160 	OSSharedPtr<OSDictionary>         prelinkRequest;
9161 	OSSharedPtr<OSCollectionIterator> kextIterator;
9162 	const OSSymbol * thisID                 = NULL;        // do not release
9163 	bool            doRebuild               = false;
9164 	AbsoluteTime    my_abstime;
9165 	UInt64          my_ns;
9166 	SInt32          delta_secs;
9167 
9168 	/* Only one auto rebuild per boot and only on boot from prelinked kernel */
9169 	if (requestedPrelink || !sPrelinkBoot) {
9170 		return;
9171 	}
9172 
9173 	/* no direct return from this point */
9174 	IORecursiveLockLock(sKextLock);
9175 
9176 	/* We need to wait for the IOKit daemon to get up and running with unloads already done
9177 	 * and any new startup kexts loaded.
9178 	 */
9179 	if (!sConsiderUnloadsExecuted ||
9180 	    !sDeferredLoadSucceeded) {
9181 		goto finish;
9182 	}
9183 
9184 	/* we really only care about boot / system start up related kexts so bail
9185 	 * if we're here after REBUILD_MAX_TIME.
9186 	 */
9187 	if (!_OSKextInPrelinkRebuildWindow()) {
9188 		OSKextLog(/* kext */ NULL,
9189 		    kOSKextLogArchiveFlag,
9190 		    "%s prebuild rebuild has expired",
9191 		    __FUNCTION__);
9192 		requestedPrelink = true;
9193 		goto finish;
9194 	}
9195 
9196 	/* we do not want to trigger a rebuild if we get here too close to waking
9197 	 * up.  (see radar 10233768)
9198 	 */
9199 	IORecursiveLockLock(sKextInnerLock);
9200 
9201 	clock_get_uptime(&my_abstime);
9202 	delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
9203 	if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
9204 		SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
9205 		absolutetime_to_nanoseconds(my_abstime, &my_ns);
9206 		delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
9207 	}
9208 	IORecursiveLockUnlock(sKextInnerLock);
9209 
9210 	if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
9211 		/* too close to time of last wake from sleep */
9212 		goto finish;
9213 	}
9214 	requestedPrelink = true;
9215 
9216 	/* Now it's time to see if we have a reason to rebuild.  We may have done
9217 	 * some loads and unloads but the kernel cache didn't actually change.
9218 	 * We will rebuild if any kext is not marked prelinked AND is not in our
9219 	 * list of prelinked kexts that got unloaded.  (see radar 9055303)
9220 	 */
9221 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
9222 	if (!kextIterator) {
9223 		goto finish;
9224 	}
9225 
9226 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
9227 		OSKext *    thisKext;        // do not release
9228 
9229 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
9230 		if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
9231 			continue;
9232 		}
9233 
9234 		if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) {
9235 			continue;
9236 		}
9237 		/* kext is loaded and was not in current kernel cache so let's rebuild
9238 		 */
9239 		doRebuild = true;
9240 		OSKextLog(/* kext */ NULL,
9241 		    kOSKextLogArchiveFlag,
9242 		    "considerRebuildOfPrelinkedKernel %s triggered rebuild",
9243 		    thisKext->bundleID->getCStringNoCopy());
9244 		break;
9245 	}
9246 	sUnloadedPrelinkedKexts->flushCollection();
9247 
9248 	if (!doRebuild) {
9249 		goto finish;
9250 	}
9251 
9252 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
9253 	    prelinkRequest);
9254 	if (checkResult != kOSReturnSuccess) {
9255 		goto finish;
9256 	}
9257 
9258 	if (!sKernelRequests->setObject(prelinkRequest.get())) {
9259 		goto finish;
9260 	}
9261 
9262 	OSKext::pingIOKitDaemon();
9263 
9264 finish:
9265 	IORecursiveLockUnlock(sKextLock);
9266 
9267 	return;
9268 }
9269 
9270 #else /* !CONFIG_KXLD */
9271 
9272 void
9273 OSKext::considerRebuildOfPrelinkedKernel(void)
9274 {
9275 	/* in a non-dynamic kext loading world, there is never a reason to rebuild */
9276 	return;
9277 }
9278 
9279 #endif /* CONFIG_KXLD */
9280 
9281 #if PRAGMA_MARK
9282 #pragma mark Dependencies
9283 #endif
9284 /*********************************************************************
9285 *********************************************************************/
9286 bool
9287 OSKext::resolveDependencies(
9288 	OSArray * loopStack)
9289 {
9290 	bool                   result                   = false;
9291 	OSSharedPtr<OSArray>   localLoopStack;
9292 	bool                   addedToLoopStack         = false;
9293 	OSDictionary         * libraries                = NULL;        // do not release
9294 	OSSharedPtr<OSCollectionIterator> libraryIterator;
9295 	OSString             * libraryID                = NULL;        // do not release
9296 	OSKext               * libraryKext              = NULL;        // do not release
9297 	bool                   hasRawKernelDependency   = false;
9298 	bool                   hasKernelDependency      = false;
9299 	bool                   hasKPIDependency         = false;
9300 	bool                   hasPrivateKPIDependency  = false;
9301 	unsigned int           count;
9302 
9303 #if CONFIG_KXLD
9304 	OSString             * infoString               = NULL;        // do not release
9305 	OSString             * readableString           = NULL;        // do not release
9306 #endif // CONFIG_KXLD
9307 
9308 	/* A kernel component will automatically have this flag set,
9309 	 * and a loaded kext should also have it set (as should all its
9310 	 * loaded dependencies).
9311 	 */
9312 	if (flags.hasAllDependencies) {
9313 		result = true;
9314 		goto finish;
9315 	}
9316 
9317 	/* Check for loops in the dependency graph.
9318 	 */
9319 	if (loopStack) {
9320 		if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
9321 			OSKextLog(this,
9322 			    kOSKextLogErrorLevel |
9323 			    kOSKextLogDependenciesFlag,
9324 			    "Kext %s has a dependency loop; can't resolve dependencies.",
9325 			    getIdentifierCString());
9326 			goto finish;
9327 		}
9328 	} else {
9329 		OSKextLog(this,
9330 		    kOSKextLogStepLevel |
9331 		    kOSKextLogDependenciesFlag,
9332 		    "Kext %s resolving dependencies.",
9333 		    getIdentifierCString());
9334 
9335 		localLoopStack = OSArray::withCapacity(6);         // any small capacity will do
9336 		if (!localLoopStack) {
9337 			OSKextLog(this,
9338 			    kOSKextLogErrorLevel |
9339 			    kOSKextLogDependenciesFlag,
9340 			    "Kext %s can't create bookkeeping stack to resolve dependencies.",
9341 			    getIdentifierCString());
9342 			goto finish;
9343 		}
9344 		loopStack = localLoopStack.get();
9345 	}
9346 	if (!loopStack->setObject(this)) {
9347 		OSKextLog(this,
9348 		    kOSKextLogErrorLevel |
9349 		    kOSKextLogDependenciesFlag,
9350 		    "Kext %s - internal error resolving dependencies.",
9351 		    getIdentifierCString());
9352 		goto finish;
9353 	}
9354 	addedToLoopStack = true;
9355 
9356 	/* Purge any existing kexts in the dependency list and start over.
9357 	 */
9358 	flushDependencies();
9359 	if (dependencies) {
9360 		OSKextLog(this,
9361 		    kOSKextLogErrorLevel |
9362 		    kOSKextLogDependenciesFlag,
9363 		    "Kext %s - internal error resolving dependencies.",
9364 		    getIdentifierCString());
9365 	}
9366 
9367 	libraries = OSDynamicCast(OSDictionary,
9368 	    getPropertyForHostArch(kOSBundleLibrariesKey));
9369 	if (libraries == NULL || libraries->getCount() == 0) {
9370 		OSKextLog(this,
9371 		    kOSKextLogErrorLevel |
9372 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9373 		    "Kext %s - can't resolve dependencies; %s missing/invalid type.",
9374 		    getIdentifierCString(), kOSBundleLibrariesKey);
9375 		goto finish;
9376 	}
9377 
9378 	/* Make a new array to hold the dependencies (flush freed the old one).
9379 	 */
9380 	dependencies = OSArray::withCapacity(libraries->getCount());
9381 	if (!dependencies) {
9382 		OSKextLog(this,
9383 		    kOSKextLogErrorLevel |
9384 		    kOSKextLogDependenciesFlag,
9385 		    "Kext %s - can't allocate dependencies array.",
9386 		    getIdentifierCString());
9387 		goto finish;
9388 	}
9389 
9390 	// xxx - compat: We used to add an implicit dependency on kernel 6.0
9391 	// xxx - compat: if none were declared.
9392 
9393 	libraryIterator = OSCollectionIterator::withCollection(libraries);
9394 	if (!libraryIterator) {
9395 		OSKextLog(this,
9396 		    kOSKextLogErrorLevel |
9397 		    kOSKextLogDependenciesFlag,
9398 		    "Kext %s - can't allocate dependencies iterator.",
9399 		    getIdentifierCString());
9400 		goto finish;
9401 	}
9402 
9403 	while ((libraryID = OSDynamicCast(OSString,
9404 	    libraryIterator->getNextObject()))) {
9405 		const char * library_id = libraryID->getCStringNoCopy();
9406 
9407 		OSString * libraryVersion = OSDynamicCast(OSString,
9408 		    libraries->getObject(libraryID));
9409 		if (libraryVersion == NULL) {
9410 			OSKextLog(this,
9411 			    kOSKextLogErrorLevel |
9412 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9413 			    "Kext %s - illegal type in OSBundleLibraries.",
9414 			    getIdentifierCString());
9415 			goto finish;
9416 		}
9417 
9418 		OSKextVersion libraryVers =
9419 		    OSKextParseVersionString(libraryVersion->getCStringNoCopy());
9420 		if (libraryVers == -1) {
9421 			OSKextLog(this,
9422 			    kOSKextLogErrorLevel |
9423 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9424 			    "Kext %s - invalid library version %s.",
9425 			    getIdentifierCString(),
9426 			    libraryVersion->getCStringNoCopy());
9427 			goto finish;
9428 		}
9429 
9430 		libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
9431 		if (libraryKext == NULL) {
9432 			OSKextLog(this,
9433 			    kOSKextLogErrorLevel |
9434 			    kOSKextLogDependenciesFlag,
9435 			    "Kext %s - library kext %s not found.",
9436 			    getIdentifierCString(), library_id);
9437 			goto finish;
9438 		}
9439 
9440 		if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
9441 			OSKextLog(this,
9442 			    kOSKextLogErrorLevel |
9443 			    kOSKextLogDependenciesFlag,
9444 			    "Kext %s - library kext %s not compatible "
9445 			    "with requested version %s.",
9446 			    getIdentifierCString(), library_id,
9447 			    libraryVersion->getCStringNoCopy());
9448 			goto finish;
9449 		}
9450 
9451 		/* If a nonprelinked library somehow got into the mix for a
9452 		 * prelinked kext, at any point in the chain, we must fail
9453 		 * because the prelinked relocs for the library will be all wrong.
9454 		 */
9455 		if (this->isPrelinked() &&
9456 		    libraryKext->declaresExecutable() &&
9457 		    !libraryKext->isPrelinked()) {
9458 			OSKextLog(this,
9459 			    kOSKextLogErrorLevel |
9460 			    kOSKextLogDependenciesFlag,
9461 			    "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
9462 			    getIdentifierCString(), library_id,
9463 			    libraryVersion->getCStringNoCopy());
9464 			goto finish;
9465 		}
9466 
9467 		if (!libraryKext->resolveDependencies(loopStack)) {
9468 			goto finish;
9469 		}
9470 
9471 		/* Add the library directly only if it has an executable to link.
9472 		 * Otherwise it's just used to collect other dependencies, so put
9473 		 * *its* dependencies on the list for this kext.
9474 		 */
9475 		// xxx - We are losing info here; would like to make fake entries or
9476 		// xxx - keep these in the dependency graph for loaded kexts.
9477 		// xxx - I really want to make kernel components not a special case!
9478 		if (libraryKext->declaresExecutable() ||
9479 		    libraryKext->isInterface()) {
9480 			if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
9481 				dependencies->setObject(libraryKext);
9482 
9483 				OSKextLog(this,
9484 				    kOSKextLogDetailLevel |
9485 				    kOSKextLogDependenciesFlag,
9486 				    "Kext %s added dependency %s.",
9487 				    getIdentifierCString(),
9488 				    libraryKext->getIdentifierCString());
9489 			}
9490 		} else {
9491 			int       numLibDependencies  = libraryKext->getNumDependencies();
9492 			OSArray * libraryDependencies = libraryKext->getDependencies();
9493 			int       index;
9494 
9495 			if (numLibDependencies) {
9496 				// xxx - this msg level should be 1 lower than the per-kext one
9497 				OSKextLog(this,
9498 				    kOSKextLogDetailLevel |
9499 				    kOSKextLogDependenciesFlag,
9500 				    "Kext %s pulling %d dependencies from codeless library %s.",
9501 				    getIdentifierCString(),
9502 				    numLibDependencies,
9503 				    libraryKext->getIdentifierCString());
9504 			}
9505 			for (index = 0; index < numLibDependencies; index++) {
9506 				OSKext * thisLibDependency = OSDynamicCast(OSKext,
9507 				    libraryDependencies->getObject(index));
9508 				if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
9509 					dependencies->setObject(thisLibDependency);
9510 					OSKextLog(this,
9511 					    kOSKextLogDetailLevel |
9512 					    kOSKextLogDependenciesFlag,
9513 					    "Kext %s added dependency %s from codeless library %s.",
9514 					    getIdentifierCString(),
9515 					    thisLibDependency->getIdentifierCString(),
9516 					    libraryKext->getIdentifierCString());
9517 				}
9518 			}
9519 		}
9520 
9521 		if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
9522 		    0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
9523 			hasRawKernelDependency = true;
9524 		} else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
9525 			hasKernelDependency = true;
9526 		} else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
9527 			hasKPIDependency = true;
9528 			if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
9529 				hasPrivateKPIDependency = true;
9530 			}
9531 		}
9532 	}
9533 
9534 	if (hasRawKernelDependency) {
9535 		OSKextLog(this,
9536 		    kOSKextLogErrorLevel |
9537 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9538 		    "Error - kext %s declares a dependency on %s, which is not permitted.",
9539 		    getIdentifierCString(), KERNEL_LIB);
9540 		goto finish;
9541 	}
9542 #if __LP64__
9543 	if (hasKernelDependency) {
9544 		OSKextLog(this,
9545 		    kOSKextLogErrorLevel |
9546 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9547 		    "Error - kext %s declares %s dependencies. "
9548 		    "Only %s* dependencies are supported for 64-bit kexts.",
9549 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
9550 		goto finish;
9551 	}
9552 	if (!hasKPIDependency) {
9553 		OSKextLog(this,
9554 		    kOSKextLogWarningLevel |
9555 		    kOSKextLogDependenciesFlag,
9556 		    "Warning - kext %s declares no %s* dependencies. "
9557 		    "If it uses any KPIs, the link may fail with undefined symbols.",
9558 		    getIdentifierCString(), KPI_LIB_PREFIX);
9559 	}
9560 #else /* __LP64__ */
9561 	// xxx - will change to flatly disallow "kernel" dependencies at some point
9562 	// xxx - is it invalid to do both "com.apple.kernel" and any
9563 	// xxx - "com.apple.kernel.*"?
9564 
9565 	if (hasKernelDependency && hasKPIDependency) {
9566 		OSKextLog(this,
9567 		    kOSKextLogWarningLevel |
9568 		    kOSKextLogDependenciesFlag,
9569 		    "Warning - kext %s has immediate dependencies on both "
9570 		    "%s* and %s* components; use only one style.",
9571 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
9572 	}
9573 
9574 	if (!hasKernelDependency && !hasKPIDependency) {
9575 		// xxx - do we want to use validation flag for these too?
9576 		OSKextLog(this,
9577 		    kOSKextLogWarningLevel |
9578 		    kOSKextLogDependenciesFlag,
9579 		    "Warning - %s declares no kernel dependencies; using %s.",
9580 		    getIdentifierCString(), KERNEL6_LIB);
9581 		OSKext * kernelKext = OSDynamicCast(OSKext,
9582 		    sKextsByID->getObject(KERNEL6_LIB));
9583 		if (kernelKext) {
9584 			dependencies->setObject(kernelKext);
9585 		} else {
9586 			OSKextLog(this,
9587 			    kOSKextLogErrorLevel |
9588 			    kOSKextLogDependenciesFlag,
9589 			    "Error - Library %s not found for %s.",
9590 			    KERNEL6_LIB, getIdentifierCString());
9591 		}
9592 	}
9593 
9594 	/* If the kext doesn't have a raw kernel or KPI dependency, then add all of
9595 	 * its indirect dependencies to simulate old-style linking.  XXX - Should
9596 	 * check for duplicates.
9597 	 */
9598 	if (!hasKPIDependency) {
9599 		unsigned int i;
9600 
9601 		flags.hasBleedthrough = true;
9602 
9603 		count = getNumDependencies();
9604 
9605 		/* We add to the dependencies array in this loop, but do not iterate
9606 		 * past its original count.
9607 		 */
9608 		for (i = 0; i < count; i++) {
9609 			OSKext * dependencyKext = OSDynamicCast(OSKext,
9610 			    dependencies->getObject(i));
9611 			dependencyKext->addBleedthroughDependencies(dependencies.get());
9612 		}
9613 	}
9614 #endif /* __LP64__ */
9615 
9616 #if CONFIG_KXLD
9617 	/*
9618 	 * If we're not dynamically linking kexts, then we don't need to check
9619 	 * copyright strings. The linker in user space has already done this.
9620 	 */
9621 	if (hasPrivateKPIDependency) {
9622 		bool hasApplePrefix = false;
9623 		bool infoCopyrightIsValid = false;
9624 		bool readableCopyrightIsValid = false;
9625 
9626 		hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
9627 		    APPLE_KEXT_PREFIX);
9628 
9629 		infoString = OSDynamicCast(OSString,
9630 		    getPropertyForHostArch("CFBundleGetInfoString"));
9631 		if (infoString) {
9632 			infoCopyrightIsValid =
9633 			    kxld_validate_copyright_string(infoString->getCStringNoCopy());
9634 		}
9635 
9636 		readableString = OSDynamicCast(OSString,
9637 		    getPropertyForHostArch("NSHumanReadableCopyright"));
9638 		if (readableString) {
9639 			readableCopyrightIsValid =
9640 			    kxld_validate_copyright_string(readableString->getCStringNoCopy());
9641 		}
9642 
9643 		if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
9644 			OSKextLog(this,
9645 			    kOSKextLogErrorLevel |
9646 			    kOSKextLogDependenciesFlag,
9647 			    "Error - kext %s declares a dependency on %s. "
9648 			    "Only Apple kexts may declare a dependency on %s.",
9649 			    getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
9650 			goto finish;
9651 		}
9652 	}
9653 #endif // CONFIG_KXLD
9654 
9655 	result = true;
9656 	flags.hasAllDependencies = 1;
9657 
9658 finish:
9659 
9660 	if (addedToLoopStack) {
9661 		count = loopStack->getCount();
9662 		if (count > 0 && (this == loopStack->getObject(count - 1))) {
9663 			loopStack->removeObject(count - 1);
9664 		} else {
9665 			OSKextLog(this,
9666 			    kOSKextLogErrorLevel |
9667 			    kOSKextLogDependenciesFlag,
9668 			    "Kext %s - internal error resolving dependencies.",
9669 			    getIdentifierCString());
9670 		}
9671 	}
9672 
9673 	if (result && localLoopStack) {
9674 		OSKextLog(this,
9675 		    kOSKextLogStepLevel |
9676 		    kOSKextLogDependenciesFlag,
9677 		    "Kext %s successfully resolved dependencies.",
9678 		    getIdentifierCString());
9679 	}
9680 
9681 	return result;
9682 }
9683 
9684 /*********************************************************************
9685 *********************************************************************/
9686 bool
9687 OSKext::addBleedthroughDependencies(OSArray * anArray)
9688 {
9689 	bool result = false;
9690 	unsigned int dependencyIndex, dependencyCount;
9691 
9692 	dependencyCount = getNumDependencies();
9693 
9694 	for (dependencyIndex = 0;
9695 	    dependencyIndex < dependencyCount;
9696 	    dependencyIndex++) {
9697 		OSKext * dependency = OSDynamicCast(OSKext,
9698 		    dependencies->getObject(dependencyIndex));
9699 		if (!dependency) {
9700 			OSKextLog(this,
9701 			    kOSKextLogErrorLevel |
9702 			    kOSKextLogDependenciesFlag,
9703 			    "Kext %s - internal error propagating compatibility dependencies.",
9704 			    getIdentifierCString());
9705 			goto finish;
9706 		}
9707 		if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
9708 			anArray->setObject(dependency);
9709 		}
9710 		dependency->addBleedthroughDependencies(anArray);
9711 	}
9712 
9713 	result = true;
9714 
9715 finish:
9716 	return result;
9717 }
9718 
9719 /*********************************************************************
9720 *********************************************************************/
9721 bool
9722 OSKext::flushDependencies(bool forceFlag)
9723 {
9724 	bool result = false;
9725 
9726 	/* Only clear the dependencies if the kext isn't loaded;
9727 	 * we need the info for loaded kexts to track references.
9728 	 */
9729 	if (!isLoaded() || forceFlag) {
9730 		if (dependencies) {
9731 			// xxx - check level
9732 			OSKextLog(this,
9733 			    kOSKextLogProgressLevel |
9734 			    kOSKextLogDependenciesFlag,
9735 			    "Kext %s flushing dependencies.",
9736 			    getIdentifierCString());
9737 			dependencies.reset();
9738 		}
9739 		if (!isKernelComponent()) {
9740 			flags.hasAllDependencies = 0;
9741 		}
9742 		result = true;
9743 	}
9744 
9745 	return result;
9746 }
9747 
9748 /*********************************************************************
9749 *********************************************************************/
9750 uint32_t
9751 OSKext::getNumDependencies(void)
9752 {
9753 	if (!dependencies) {
9754 		return 0;
9755 	}
9756 	return dependencies->getCount();
9757 }
9758 
9759 /*********************************************************************
9760 *********************************************************************/
9761 OSArray *
9762 OSKext::getDependencies(void)
9763 {
9764 	return dependencies.get();
9765 }
9766 
9767 bool
9768 OSKext::hasDependency(const OSSymbol * depID)
9769 {
9770 	bool result __block;
9771 
9772 	if (depID == getIdentifier()) {
9773 		return true;
9774 	}
9775 	if (!dependencies) {
9776 		return false;
9777 	}
9778 	result = false;
9779 	dependencies->iterateObjects(^bool (OSObject * obj) {
9780 		OSKext * kext;
9781 		kext = OSDynamicCast(OSKext, obj);
9782 		if (!kext) {
9783 		        return false;
9784 		}
9785 		result = (depID == kext->getIdentifier());
9786 		return result;
9787 	});
9788 	return result;
9789 }
9790 
9791 #if PRAGMA_MARK
9792 #pragma mark OSMetaClass Support
9793 #endif
9794 /*********************************************************************
9795 *********************************************************************/
9796 OSReturn
9797 OSKext::addClass(
9798 	OSMetaClass * aClass,
9799 	uint32_t      numClasses)
9800 {
9801 	OSReturn result = kOSMetaClassNoInsKModSet;
9802 
9803 	if (!metaClasses) {
9804 		metaClasses = OSSet::withCapacity(numClasses);
9805 		if (!metaClasses) {
9806 			goto finish;
9807 		}
9808 	}
9809 
9810 	if (metaClasses->containsObject(aClass)) {
9811 		OSKextLog(this,
9812 		    kOSKextLogWarningLevel |
9813 		    kOSKextLogLoadFlag,
9814 		    "Notice - kext %s has already registered class %s.",
9815 		    getIdentifierCString(),
9816 		    aClass->getClassName());
9817 		result = kOSReturnSuccess;
9818 		goto finish;
9819 	}
9820 
9821 	if (!metaClasses->setObject(aClass)) {
9822 		goto finish;
9823 	} else {
9824 		OSKextLog(this,
9825 		    kOSKextLogDetailLevel |
9826 		    kOSKextLogLoadFlag,
9827 		    "Kext %s registered class %s.",
9828 		    getIdentifierCString(),
9829 		    aClass->getClassName());
9830 	}
9831 
9832 	if (!flags.autounloadEnabled) {
9833 		const OSMetaClass * metaScan  = NULL;        // do not release
9834 
9835 		for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
9836 			if (metaScan == OSTypeID(IOService)) {
9837 				OSKextLog(this,
9838 				    kOSKextLogProgressLevel |
9839 				    kOSKextLogLoadFlag,
9840 				    "Kext %s has IOService subclass %s; enabling autounload.",
9841 				    getIdentifierCString(),
9842 				    aClass->getClassName());
9843 
9844 				flags.autounloadEnabled = (0 == flags.unloadUnsupported);
9845 				break;
9846 			}
9847 		}
9848 	}
9849 
9850 	notifyAddClassObservers(this, aClass, flags);
9851 
9852 	result = kOSReturnSuccess;
9853 
9854 finish:
9855 	if (result != kOSReturnSuccess) {
9856 		OSKextLog(this,
9857 		    kOSKextLogErrorLevel |
9858 		    kOSKextLogLoadFlag,
9859 		    "Kext %s failed to register class %s.",
9860 		    getIdentifierCString(),
9861 		    aClass->getClassName());
9862 	}
9863 
9864 	return result;
9865 }
9866 
9867 /*********************************************************************
9868 *********************************************************************/
9869 OSReturn
9870 OSKext::removeClass(
9871 	OSMetaClass * aClass)
9872 {
9873 	OSReturn result = kOSMetaClassNoKModSet;
9874 
9875 	if (!metaClasses) {
9876 		goto finish;
9877 	}
9878 
9879 	if (!metaClasses->containsObject(aClass)) {
9880 		OSKextLog(this,
9881 		    kOSKextLogWarningLevel |
9882 		    kOSKextLogLoadFlag,
9883 		    "Notice - kext %s asked to unregister unknown class %s.",
9884 		    getIdentifierCString(),
9885 		    aClass->getClassName());
9886 		result = kOSReturnSuccess;
9887 		goto finish;
9888 	}
9889 
9890 	OSKextLog(this,
9891 	    kOSKextLogDetailLevel |
9892 	    kOSKextLogLoadFlag,
9893 	    "Kext %s unregistering class %s.",
9894 	    getIdentifierCString(),
9895 	    aClass->getClassName());
9896 
9897 	metaClasses->removeObject(aClass);
9898 
9899 	notifyRemoveClassObservers(this, aClass, flags);
9900 
9901 	result = kOSReturnSuccess;
9902 
9903 finish:
9904 	if (result != kOSReturnSuccess) {
9905 		OSKextLog(this,
9906 		    kOSKextLogErrorLevel |
9907 		    kOSKextLogLoadFlag,
9908 		    "Failed to unregister kext %s class %s.",
9909 		    getIdentifierCString(),
9910 		    aClass->getClassName());
9911 	}
9912 	return result;
9913 }
9914 
9915 /*********************************************************************
9916 *********************************************************************/
9917 OSSet *
9918 OSKext::getMetaClasses(void)
9919 {
9920 	return metaClasses.get();
9921 }
9922 
9923 /*********************************************************************
9924 *********************************************************************/
9925 bool
9926 OSKext::hasOSMetaClassInstances(void)
9927 {
9928 	bool                   result        = false;
9929 	OSSharedPtr<OSCollectionIterator> classIterator;
9930 	OSMetaClass          * checkClass    = NULL;        // do not release
9931 
9932 	if (!metaClasses) {
9933 		goto finish;
9934 	}
9935 
9936 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9937 	if (!classIterator) {
9938 		// xxx - log alloc failure?
9939 		goto finish;
9940 	}
9941 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9942 		if (checkClass->getInstanceCount()) {
9943 			result = true;
9944 			goto finish;
9945 		}
9946 	}
9947 
9948 finish:
9949 	return result;
9950 }
9951 
9952 /*********************************************************************
9953 *********************************************************************/
9954 /* static */
9955 void
9956 OSKext::reportOSMetaClassInstances(
9957 	const char     * kextIdentifier,
9958 	OSKextLogSpec    msgLogSpec)
9959 {
9960 	OSSharedPtr<OSKext> theKext;
9961 
9962 	theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
9963 	if (!theKext) {
9964 		goto finish;
9965 	}
9966 
9967 	theKext->reportOSMetaClassInstances(msgLogSpec);
9968 finish:
9969 	return;
9970 }
9971 
9972 /*********************************************************************
9973 *********************************************************************/
9974 void
9975 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
9976 {
9977 	OSSharedPtr<OSCollectionIterator> classIterator;
9978 	OSMetaClass          * checkClass    = NULL;        // do not release
9979 
9980 	if (!metaClasses) {
9981 		goto finish;
9982 	}
9983 
9984 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9985 	if (!classIterator) {
9986 		goto finish;
9987 	}
9988 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9989 		if (checkClass->getInstanceCount()) {
9990 			OSKextLog(this,
9991 			    msgLogSpec,
9992 			    "    Kext %s class %s has %d instance%s.",
9993 			    getIdentifierCString(),
9994 			    checkClass->getClassName(),
9995 			    checkClass->getInstanceCount(),
9996 			    checkClass->getInstanceCount() == 1 ? "" : "s");
9997 		}
9998 	}
9999 
10000 finish:
10001 	return;
10002 }
10003 
10004 #if PRAGMA_MARK
10005 #pragma mark User-Space Requests
10006 #endif
10007 
10008 static kern_return_t
10009 patchDextLaunchRequests(task_t calling_task, OSArray *requests)
10010 {
10011 	OSReturn result = kOSReturnSuccess;
10012 	for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) {
10013 		OSDictionary * request = NULL;         //do not release
10014 		IOUserServerCheckInToken * token = NULL;         //do not release
10015 		OSString * requestPredicate = NULL;         //do not release
10016 		OSSharedPtr<OSNumber> portNameNumber;
10017 		mach_port_name_t portName = 0;
10018 		request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex));
10019 		if (!request) {
10020 			OSKextLog(/* kext */ NULL,
10021 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10022 			    "Elements of request should be of type OSDictionary");
10023 			result = kOSKextReturnInternalError;
10024 			goto finish;
10025 		}
10026 		requestPredicate = _OSKextGetRequestPredicate(request);
10027 		if (!requestPredicate) {
10028 			OSKextLog(/* kext */ NULL,
10029 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10030 			    "Failed to get request predicate");
10031 			result = kOSKextReturnInternalError;
10032 			goto finish;
10033 		}
10034 		// is this a dext launch?
10035 		if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) {
10036 			token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken));
10037 			if (!token) {
10038 				OSKextLog(/* kext */ NULL,
10039 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10040 				    "Could not find a IOUserServerCheckInToken in daemon launch request.");
10041 				result = kOSKextReturnInternalError;
10042 				goto finish;
10043 			}
10044 			portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT);
10045 			if (portName == 0 || portName == MACH_PORT_DEAD) {
10046 				OSKextLog(/* kext */ NULL,
10047 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10048 				    "Could not create send right for object.");
10049 				result = kOSKextReturnInternalError;
10050 				goto finish;
10051 			}
10052 			// Store the mach port name as a OSNumber
10053 			portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName));
10054 			if (!portNameNumber) {
10055 				OSKextLog(/* kext */ NULL,
10056 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10057 				    "Could not create OSNumber object.");
10058 				result = kOSKextReturnNoMemory;
10059 				goto finish;
10060 			}
10061 			if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) {
10062 				OSKextLog(/* kext */ NULL,
10063 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10064 				    "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken);
10065 				result = kOSKextReturnNoMemory;
10066 				goto finish;
10067 			}
10068 		}
10069 finish:
10070 		if (result != kOSReturnSuccess) {
10071 			break;
10072 		}
10073 	}
10074 	return result;
10075 }
10076 
10077 bool
10078 OSKext::iokitDaemonActive()
10079 {
10080 	bool result;
10081 	IORecursiveLockLock(sKextLock);
10082 	result = sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot;
10083 	IORecursiveLockUnlock(sKextLock);
10084 	return result;
10085 }
10086 
10087 /*********************************************************************
10088 * XXX - this function is a big ugly mess
10089 *********************************************************************/
10090 /* static */
10091 OSReturn
10092 OSKext::handleRequest(
10093 	host_priv_t     hostPriv,
10094 	OSKextLogSpec   clientLogFilter,
10095 	char          * requestBuffer,
10096 	uint32_t        requestLength,
10097 	char         ** responseOut,
10098 	uint32_t      * responseLengthOut,
10099 	char         ** logInfoOut,
10100 	uint32_t      * logInfoLengthOut)
10101 {
10102 	OSReturn       result             = kOSReturnError;
10103 	kern_return_t  kmem_result        = KERN_FAILURE;
10104 
10105 	char         * response           = NULL;        // returned by reference
10106 	uint32_t       responseLength     = 0;
10107 
10108 	bool           taskCanManageAllKCs   = false;
10109 	bool           taskOnlyManagesBootKC = false;
10110 
10111 	OSSharedPtr<OSObject>     parsedXML;
10112 	OSDictionary            * requestDict    = NULL;        // do not release
10113 	OSSharedPtr<OSString>     errorString;
10114 
10115 	OSSharedPtr<OSObject>     responseObject;
10116 
10117 	OSSharedPtr<OSSerialize>  serializer;
10118 
10119 	OSSharedPtr<OSArray>      logInfoArray;
10120 
10121 	OSString     * predicate          = NULL;        // do not release
10122 	OSString     * kextIdentifier     = NULL;        // do not release
10123 	OSArray      * kextIdentifiers    = NULL;        // do not release
10124 	OSKext       * theKext            = NULL;        // do not release
10125 	OSBoolean    * boolArg            = NULL;        // do not release
10126 
10127 
10128 	IORecursiveLockLock(sKextLock);
10129 
10130 	if (responseOut) {
10131 		*responseOut = NULL;
10132 		*responseLengthOut = 0;
10133 	}
10134 	if (logInfoOut) {
10135 		*logInfoOut = NULL;
10136 		*logInfoLengthOut = 0;
10137 	}
10138 
10139 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
10140 
10141 	/* XML must be nul-terminated.
10142 	 */
10143 	if (requestBuffer[requestLength - 1] != '\0') {
10144 		OSKextLog(/* kext */ NULL,
10145 		    kOSKextLogErrorLevel |
10146 		    kOSKextLogIPCFlag,
10147 		    "Invalid request from user space (not nul-terminated).");
10148 		result = kOSKextReturnBadData;
10149 		goto finish;
10150 	}
10151 	parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString);
10152 	if (parsedXML) {
10153 		requestDict = OSDynamicCast(OSDictionary, parsedXML.get());
10154 	}
10155 	if (!requestDict) {
10156 		const char * errorCString = "(unknown error)";
10157 
10158 		if (errorString && errorString->getCStringNoCopy()) {
10159 			errorCString = errorString->getCStringNoCopy();
10160 		} else if (parsedXML) {
10161 			errorCString = "not a dictionary";
10162 		}
10163 		OSKextLog(/* kext */ NULL,
10164 		    kOSKextLogErrorLevel |
10165 		    kOSKextLogIPCFlag,
10166 		    "Error unserializing request from user space: %s.",
10167 		    errorCString);
10168 		result = kOSKextReturnSerialization;
10169 		goto finish;
10170 	}
10171 
10172 	predicate = _OSKextGetRequestPredicate(requestDict);
10173 	if (!predicate) {
10174 		OSKextLog(/* kext */ NULL,
10175 		    kOSKextLogErrorLevel |
10176 		    kOSKextLogIPCFlag,
10177 		    "Recieved kext request from user space with no predicate.");
10178 		result = kOSKextReturnInvalidArgument;
10179 		goto finish;
10180 	}
10181 	OSKextLog(/* kext */ NULL,
10182 	    kOSKextLogDebugLevel |
10183 	    kOSKextLogIPCFlag,
10184 	    "Received '%s' request from user space.",
10185 	    predicate->getCStringNoCopy());
10186 
10187 	/*
10188 	 * All management of file sets requires an entitlement
10189 	 */
10190 	result = kOSKextReturnNotPrivileged;
10191 	if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
10192 	    predicate->isEqualTo(kKextRequestPredicateStart) ||
10193 	    predicate->isEqualTo(kKextRequestPredicateStop) ||
10194 	    predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
10195 	    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
10196 	    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
10197 	    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
10198 	    predicate->isEqualTo(kKextRequestPredicateLoadFromKC) ||
10199 	    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
10200 	    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
10201 	    predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
10202 		if (!iokitDaemonAvailable()) {
10203 			panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable");
10204 		}
10205 		if (hostPriv == HOST_PRIV_NULL) {
10206 			OSKextLog(/* kext */ NULL,
10207 			    kOSKextLogErrorLevel |
10208 			    kOSKextLogIPCFlag,
10209 			    "Access Failure - must be root user.");
10210 			goto finish;
10211 		}
10212 		taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE;
10213 		taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE;
10214 
10215 		if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) {
10216 			OSKextLog(/* kext */ NULL,
10217 			    kOSKextLogErrorLevel |
10218 			    kOSKextLogIPCFlag,
10219 			    "Access Failure - client not entitled to manage file sets.");
10220 			goto finish;
10221 		}
10222 
10223 		/*
10224 		 * The OnlyBootKC entitlement restricts the
10225 		 * collection-management entitlement to only managing kexts in
10226 		 * the BootKC. All other predicates that alter global state or
10227 		 * add new KCs are disallowed.
10228 		 */
10229 		if (taskOnlyManagesBootKC &&
10230 		    (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
10231 		    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
10232 		    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
10233 		    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
10234 		    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
10235 		    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
10236 		    predicate->isEqualTo(kKextRequestPredicateDaemonReady))) {
10237 			OSKextLog(/* kext */ NULL,
10238 			    kOSKextLogErrorLevel |
10239 			    kOSKextLogIPCFlag,
10240 			    "Access Failure - client not entitled to manage non-primary KCs");
10241 			goto finish;
10242 		}
10243 
10244 		/*
10245 		 * If we get here, then the process either has the full KC
10246 		 * management entitlement, or it has the BootKC-only
10247 		 * entitlement and the request is about the BootKC.
10248 		 */
10249 	}
10250 
10251 	/* Get common args in anticipation of use.
10252 	 */
10253 	kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
10254 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
10255 	kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
10256 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
10257 	if (kextIdentifier) {
10258 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
10259 	}
10260 	boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
10261 		    requestDict, kKextRequestArgumentValueKey));
10262 
10263 	if (taskOnlyManagesBootKC &&
10264 	    theKext &&
10265 	    theKext->isInFileset() &&
10266 	    theKext->kc_type != KCKindPrimary) {
10267 		OSKextLog(/* kext */ NULL,
10268 		    kOSKextLogErrorLevel |
10269 		    kOSKextLogIPCFlag,
10270 		    "Access Failure - client not entitled to manage kext in non-primary KC");
10271 		result = kOSKextReturnNotPrivileged;
10272 		goto finish;
10273 	}
10274 	result = kOSKextReturnInvalidArgument;
10275 
10276 	if (predicate->isEqualTo(kKextRequestPredicateStart)) {
10277 		if (!kextIdentifier) {
10278 			OSKextLog(/* kext */ NULL,
10279 			    kOSKextLogErrorLevel |
10280 			    kOSKextLogIPCFlag,
10281 			    "Invalid arguments to kext start request.");
10282 		} else if (!theKext) {
10283 			OSKextLog(/* kext */ NULL,
10284 			    kOSKextLogErrorLevel |
10285 			    kOSKextLogIPCFlag,
10286 			    "Kext %s not found for start request.",
10287 			    kextIdentifier->getCStringNoCopy());
10288 			result = kOSKextReturnNotFound;
10289 		} else {
10290 			result = theKext->start();
10291 		}
10292 	} else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
10293 		if (!kextIdentifier) {
10294 			OSKextLog(/* kext */ NULL,
10295 			    kOSKextLogErrorLevel |
10296 			    kOSKextLogIPCFlag,
10297 			    "Invalid arguments to kext stop request.");
10298 		} else if (!theKext) {
10299 			OSKextLog(/* kext */ NULL,
10300 			    kOSKextLogErrorLevel |
10301 			    kOSKextLogIPCFlag,
10302 			    "Kext %s not found for stop request.",
10303 			    kextIdentifier->getCStringNoCopy());
10304 			result = kOSKextReturnNotFound;
10305 		} else {
10306 			result = theKext->stop();
10307 		}
10308 	} else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) {
10309 		result = OSKext::setMissingAuxKCBundles(requestDict);
10310 	} else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) {
10311 		if (!kextIdentifier) {
10312 			OSKextLog(/* kext */ NULL,
10313 			    kOSKextLogErrorLevel |
10314 			    kOSKextLogIPCFlag,
10315 			    "Invalid arguments to AuxKC Bundle Available request.");
10316 		} else {
10317 			result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict);
10318 		}
10319 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) {
10320 		if (!kextIdentifier) {
10321 			OSKextLog(/* kext */ NULL,
10322 			    kOSKextLogErrorLevel |
10323 			    kOSKextLogIPCFlag,
10324 			    "Invalid arguments to kext load from KC request.");
10325 		} else if (!theKext) {
10326 			OSKextLog(/* kext */ NULL,
10327 			    kOSKextLogErrorLevel |
10328 			    kOSKextLogIPCFlag,
10329 			    "Kext %s not found for load from KC request.",
10330 			    kextIdentifier->getCStringNoCopy());
10331 			result = kOSKextReturnNotFound;
10332 		} else if (!theKext->isInFileset()) {
10333 			OSKextLog(/* kext */ NULL,
10334 			    kOSKextLogErrorLevel |
10335 			    kOSKextLogIPCFlag,
10336 			    "Kext %s does not exist in a KC: refusing to load.",
10337 			    kextIdentifier->getCStringNoCopy());
10338 			result = kOSKextReturnNotLoadable;
10339 		} else {
10340 			result = OSKext::loadKextFromKC(theKext, requestDict);
10341 		}
10342 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) {
10343 		if (!kextIdentifier) {
10344 			OSKextLog(/* kext */ NULL,
10345 			    kOSKextLogErrorLevel |
10346 			    kOSKextLogIPCFlag,
10347 			    "Invalid arguments to codeless kext load interface (missing identifier).");
10348 		} else {
10349 			result = OSKext::loadCodelessKext(kextIdentifier, requestDict);
10350 		}
10351 	} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
10352 		if (!kextIdentifier) {
10353 			OSKextLog(/* kext */ NULL,
10354 			    kOSKextLogErrorLevel |
10355 			    kOSKextLogIPCFlag,
10356 			    "Invalid arguments to kext unload request.");
10357 		} else if (!theKext) {
10358 			OSKextLog(/* kext */ NULL,
10359 			    kOSKextLogErrorLevel |
10360 			    kOSKextLogIPCFlag,
10361 			    "Kext %s not found for unload request.",
10362 			    kextIdentifier->getCStringNoCopy());
10363 			result = kOSKextReturnNotFound;
10364 		} else {
10365 			if (theKext->isDriverKit()) {
10366 				result = OSKext::removeDext(theKext);
10367 			} else {
10368 				OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
10369 				    _OSKextGetRequestArgument(requestDict,
10370 				    kKextRequestArgumentTerminateIOServicesKey));
10371 				result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
10372 			}
10373 		}
10374 	} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
10375 		result = OSKext::dispatchResource(requestDict);
10376 	} else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
10377 		OSNumber     *lookupNum   = NULL;
10378 		lookupNum = OSDynamicCast(OSNumber,
10379 		    _OSKextGetRequestArgument(requestDict,
10380 		    kKextRequestArgumentLookupAddressKey));
10381 
10382 		responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
10383 		if (responseObject) {
10384 			result = kOSReturnSuccess;
10385 		} else {
10386 			goto finish;
10387 		}
10388 	} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
10389 	    predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) ||
10390 	    predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection) ||
10391 	    predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
10392 		OSBoolean    * delayAutounloadBool = NULL;
10393 		OSObject     * infoKeysRaw         = NULL;
10394 		OSArray      * infoKeys            = NULL;
10395 		uint32_t       infoKeysCount       = 0;
10396 
10397 		delayAutounloadBool = OSDynamicCast(OSBoolean,
10398 		    _OSKextGetRequestArgument(requestDict,
10399 		    kKextRequestArgumentDelayAutounloadKey));
10400 
10401 		/* If asked to delay autounload, reset the timer if it's currently set.
10402 		 * (That is, don't schedule an unload if one isn't already pending.
10403 		 */
10404 		if (delayAutounloadBool == kOSBooleanTrue) {
10405 			OSKext::considerUnloads(/* rescheduleOnly? */ true);
10406 		}
10407 
10408 		infoKeysRaw = _OSKextGetRequestArgument(requestDict,
10409 		    kKextRequestArgumentInfoKeysKey);
10410 		infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
10411 		if (infoKeysRaw && !infoKeys) {
10412 			OSKextLog(/* kext */ NULL,
10413 			    kOSKextLogErrorLevel |
10414 			    kOSKextLogIPCFlag,
10415 			    "Invalid arguments to kext info request.");
10416 			goto finish;
10417 		}
10418 
10419 		if (infoKeys) {
10420 			infoKeysCount = infoKeys->getCount();
10421 			for (uint32_t i = 0; i < infoKeysCount; i++) {
10422 				if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
10423 					OSKextLog(/* kext */ NULL,
10424 					    kOSKextLogErrorLevel |
10425 					    kOSKextLogIPCFlag,
10426 					    "Invalid arguments to kext info request.");
10427 					goto finish;
10428 				}
10429 			}
10430 		}
10431 
10432 		if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
10433 			responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
10434 		} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
10435 			responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
10436 		} else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
10437 			responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys);
10438 		} else if (predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
10439 			responseObject = OSKext::copyDextsInfo(kextIdentifiers, infoKeys);
10440 		}
10441 
10442 		if (!responseObject) {
10443 			result = kOSKextReturnInternalError;
10444 		} else {
10445 			OSKextLog(/* kext */ NULL,
10446 			    kOSKextLogDebugLevel |
10447 			    kOSKextLogIPCFlag,
10448 			    "Returning loaded kext info.");
10449 			result = kOSReturnSuccess;
10450 		}
10451 	} else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
10452 		/* Hand the current sKernelRequests array to the caller
10453 		 * (who must release it), and make a new one.
10454 		 */
10455 		responseObject = os::move(sKernelRequests);
10456 		sKernelRequests = OSArray::withCapacity(0);
10457 		sPostedKextLoadIdentifiers->flushCollection();
10458 		OSKextLog(/* kext */ NULL,
10459 		    kOSKextLogDebugLevel |
10460 		    kOSKextLogIPCFlag,
10461 		    "Returning kernel requests.");
10462 		result = kOSReturnSuccess;
10463 	} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
10464 		/* Return the set of all requested bundle identifiers */
10465 		responseObject = sAllKextLoadIdentifiers;
10466 		OSKextLog(/* kext */ NULL,
10467 		    kOSKextLogDebugLevel |
10468 		    kOSKextLogIPCFlag,
10469 		    "Returning load requests.");
10470 		result = kOSReturnSuccess;
10471 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) {
10472 		printf("KextLog: Loading FileSet KC(s)\n");
10473 		result = OSKext::loadFileSetKexts(requestDict);
10474 	} else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
10475 		bool active = iokitDaemonActive();
10476 		printf("KextLog: " kIOKitDaemonName " is %s\n", active ? "active" : "not active");
10477 		if (sOSKextWasResetAfterUserspaceReboot) {
10478 			printf("KextLog: was reset after userspace reboot\n");
10479 		}
10480 		result = active ? kOSReturnSuccess : kIOReturnNotReady;
10481 	} else {
10482 		OSKextLog(/* kext */ NULL,
10483 		    kOSKextLogDebugLevel |
10484 		    kOSKextLogIPCFlag,
10485 		    "Received '%s' invalid request from user space.",
10486 		    predicate->getCStringNoCopy());
10487 		goto finish;
10488 	}
10489 
10490 	/**********
10491 	 * Now we have handle the request, or not. Gather up the response & logging
10492 	 * info to ship to user space.
10493 	 *********/
10494 
10495 	/* Note: Nothing in OSKext is supposed to retain requestDict,
10496 	 * but you never know....
10497 	 */
10498 	if (requestDict->getRetainCount() > 1) {
10499 		OSKextLog(/* kext */ NULL,
10500 		    kOSKextLogWarningLevel |
10501 		    kOSKextLogIPCFlag,
10502 		    "Request from user space still retained by a kext; "
10503 		    "probable memory leak.");
10504 	}
10505 
10506 	if (responseOut && responseObject) {
10507 		serializer = OSSerialize::withCapacity(0);
10508 		if (!serializer) {
10509 			result = kOSKextReturnNoMemory;
10510 			goto finish;
10511 		}
10512 		/*
10513 		 * Before serializing the kernel requests, patch the dext launch requests so
10514 		 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the
10515 		 * IOUserServerCheckInToken kernel object.
10516 		 */
10517 		if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
10518 			OSArray * requests = OSDynamicCast(OSArray, responseObject.get());
10519 			task_t calling_task = current_task();
10520 			if (!requests) {
10521 				OSKextLog(/* kext */ NULL,
10522 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10523 				    "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests);
10524 				result = kOSKextReturnInternalError;
10525 				goto finish;
10526 			}
10527 			result = patchDextLaunchRequests(calling_task, requests);
10528 			if (result != kOSReturnSuccess) {
10529 				OSKextLog(/* kext */ NULL,
10530 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10531 				    "Failed to patch dext launch requests.");
10532 				goto finish;
10533 			}
10534 		}
10535 
10536 		if (!responseObject->serialize(serializer.get())) {
10537 			OSKextLog(/* kext */ NULL,
10538 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10539 			    "Failed to serialize response to request from user space.");
10540 			result = kOSKextReturnSerialization;
10541 			goto finish;
10542 		}
10543 
10544 		response = (char *)serializer->text();
10545 		responseLength = serializer->getLength();
10546 	}
10547 
10548 	if (responseOut && response) {
10549 		char * buffer;
10550 
10551 		/* This kmem_alloc sets the return value of the function.
10552 		 */
10553 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
10554 		    round_page(responseLength), KMA_DATA, VM_KERN_MEMORY_OSKEXT);
10555 		if (kmem_result != KERN_SUCCESS) {
10556 			OSKextLog(/* kext */ NULL,
10557 			    kOSKextLogErrorLevel |
10558 			    kOSKextLogIPCFlag,
10559 			    "Failed to copy response to request from user space.");
10560 			result = kmem_result;
10561 			goto finish;
10562 		} else {
10563 			/* 11981737 - clear uninitialized data in last page */
10564 			bzero((void *)(buffer + responseLength),
10565 			    (round_page(responseLength) - responseLength));
10566 			memcpy(buffer, response, responseLength);
10567 			*responseOut = buffer;
10568 			*responseLengthOut = responseLength;
10569 		}
10570 	}
10571 
10572 finish:
10573 
10574 	/* Gather up the collected log messages for user space. Any messages
10575 	 * messages past this call will not make it up as log messages but
10576 	 * will be in the system log. Note that we ignore the return of the
10577 	 * serialize; it has no bearing on the operation at hand even if we
10578 	 * fail to get the log messages.
10579 	 */
10580 	logInfoArray = OSKext::clearUserSpaceLogFilter();
10581 
10582 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
10583 		(void)OSKext::serializeLogInfo(logInfoArray.get(),
10584 		    logInfoOut, logInfoLengthOut);
10585 	}
10586 
10587 	IORecursiveLockUnlock(sKextLock);
10588 
10589 	return result;
10590 }
10591 
10592 #if PRAGMA_MARK
10593 #pragma mark Linked Kext Collection Support
10594 #endif
10595 
10596 static int
10597 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount)
10598 {
10599 	for (int i = 0; i < segCount; i++) {
10600 		vm_offset_t segStart = segAddrs[i];
10601 		vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i];
10602 
10603 		if (theAddr >= segStart && theAddr < segEnd) {
10604 			return i;
10605 		}
10606 	}
10607 	return -1;
10608 }
10609 
10610 static void
10611 __slideOldKaslrOffsets(kernel_mach_header_t *mh,
10612     kernel_segment_command_t *kextTextSeg,
10613     OSData *kaslrOffsets)
10614 {
10615 	static const char *plk_segNames[] = {
10616 		"__TEXT",
10617 		"__TEXT_EXEC",
10618 		"__DATA",
10619 		"__DATA_CONST",
10620 		"__LINKEDIT",
10621 		"__PRELINK_TEXT",
10622 		"__PLK_TEXT_EXEC",
10623 		"__PRELINK_DATA",
10624 		"__PLK_DATA_CONST",
10625 		"__PLK_LLVM_COV",
10626 		"__PLK_LINKEDIT",
10627 		"__PRELINK_INFO"
10628 	};
10629 	static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0]));
10630 
10631 	unsigned long plk_segSizes[num_plk_seg];
10632 	vm_offset_t   plk_segAddrs[num_plk_seg];
10633 
10634 	for (size_t i = 0; i < num_plk_seg; i++) {
10635 		plk_segSizes[i] = 0;
10636 		plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]);
10637 	}
10638 
10639 	uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr;
10640 
10641 	int slidKextAddrCount = 0;
10642 	int badSlideAddr = 0;
10643 	int badSlideTarget = 0;
10644 
10645 	struct kaslrPackedOffsets {
10646 		uint32_t    count;          /* number of offsets */
10647 		uint32_t    offsetsArray[];        /* offsets to slide */
10648 	};
10649 	const struct kaslrPackedOffsets *myOffsets = NULL;
10650 	myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy();
10651 
10652 	for (uint32_t j = 0; j < myOffsets->count; j++) {
10653 		uint64_t   slideOffset = (uint64_t)myOffsets->offsetsArray[j];
10654 		vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset);
10655 		int        slideAddrSegIndex = -1;
10656 		int        addrToSlideSegIndex = -1;
10657 
10658 		slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
10659 		if (slideAddrSegIndex >= 0) {
10660 			addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
10661 			if (addrToSlideSegIndex < 0) {
10662 				badSlideTarget++;
10663 				continue;
10664 			}
10665 		} else {
10666 			badSlideAddr++;
10667 			continue;
10668 		}
10669 
10670 		slidKextAddrCount++;
10671 		*slideAddr = ml_static_slide(*slideAddr);
10672 	}         // for ...
10673 }
10674 
10675 
10676 
10677 /********************************************************************
10678 * addKextsFromKextCollection
10679 *
10680 * Input: MachO header of kext collection. The MachO is assumed to
10681 *        have a section named 'info_seg_name,info_sect_name' that
10682 *        contains a serialized XML info dictionary. This dictionary
10683 *        contains a UUID, possibly a set of relocations (for older
10684 *        kxld-built binaries), and an array of kext personalities.
10685 *
10686 ********************************************************************/
10687 bool
10688 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10689     OSDictionary *infoDict, const char *text_seg_name,
10690     OSData **kcUUID, kc_kind_t type)
10691 {
10692 	bool result = false;
10693 
10694 	OSArray *kextArray     = NULL;        // do not release
10695 	OSData *infoDictKCUUID = NULL;         // do not release
10696 	OSData *kaslrOffsets   = NULL;        // do not release
10697 
10698 	IORegistryEntry *registryRoot = NULL;         // do not release
10699 	OSSharedPtr<OSNumber> kcKextCount;
10700 
10701 	/* extract the KC UUID from the dictionary */
10702 	infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10703 	if (infoDictKCUUID) {
10704 		if (infoDictKCUUID->getLength() != sizeof(uuid_t)) {
10705 			panic("kcUUID length is %d, expected %lu",
10706 			    infoDictKCUUID->getLength(), sizeof(uuid_t));
10707 		}
10708 	}
10709 
10710 	/* locate the array of kext dictionaries */
10711 	kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey));
10712 	if (!kextArray) {
10713 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10714 		    "The given KC has no kext info dictionaries");
10715 		goto finish;
10716 	}
10717 
10718 	/*
10719 	 * old-style KASLR offsets may be present in the info dictionary. If
10720 	 * we find them, use them and eventually slide them.
10721 	 */
10722 	kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey));
10723 
10724 	/*
10725 	 * Before processing any kexts, locate the special kext bundle which
10726 	 * contains a list of kexts that we are to prevent from loading.
10727 	 */
10728 	createExcludeListFromPrelinkInfo(kextArray);
10729 
10730 	/*
10731 	 * Create OSKext objects for each kext we find in the array of kext
10732 	 * info plist dictionaries.
10733 	 */
10734 	for (int i = 0; i < (int)kextArray->getCount(); ++i) {
10735 		OSDictionary *kextDict = NULL;
10736 		kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i));
10737 		if (!kextDict) {
10738 			OSKextLog(/* kext */ NULL,
10739 			    kOSKextLogErrorLevel |
10740 			    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10741 			    "Kext info dictionary for kext #%d isn't a dictionary?", i);
10742 			continue;
10743 		}
10744 
10745 		/*
10746 		 * Create the kext for the entry, then release it, because the
10747 		 * kext system keeps a reference around until the kext is
10748 		 * explicitly removed.  Any creation/registration failures are
10749 		 * already logged for us.
10750 		 */
10751 		withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type);
10752 	}
10753 
10754 	/*
10755 	 * slide old-style kxld relocations
10756 	 * NOTE: this is still used on embedded KCs built with kcgen
10757 	 * TODO: Remove this once we use the new kext linker everywhere!
10758 	 */
10759 	if (kaslrOffsets && vm_kernel_slide > 0) {
10760 		kernel_segment_command_t *text_segment = NULL;
10761 		text_segment = getsegbynamefromheader(mh, text_seg_name);
10762 		if (!text_segment) {
10763 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10764 			    "Can't find a TEXT segment named '%s' in macho header", text_seg_name);
10765 			goto finish;
10766 		}
10767 
10768 		__slideOldKaslrOffsets(mh, text_segment, kaslrOffsets);
10769 		/* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */
10770 		setAllVMAttributes();
10771 	}
10772 
10773 	/* Store the number of prelinked kexts in the registry so we can tell
10774 	 * when the system has been started from a prelinked kernel.
10775 	 */
10776 	registryRoot = IORegistryEntry::getRegistryRoot();
10777 	assert(registryRoot);
10778 
10779 	kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t));
10780 	assert(kcKextCount);
10781 	if (kcKextCount) {
10782 		OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey);
10783 		OSNumber *num;
10784 		num = OSDynamicCast(OSNumber, prop.get());
10785 		if (num) {
10786 			kcKextCount->addValue(num->unsigned64BitValue());
10787 		}
10788 		registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get());
10789 	}
10790 
10791 	OSKextLog(/* kext */ NULL,
10792 	    kOSKextLogProgressLevel |
10793 	    kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
10794 	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10795 	    "%u prelinked kexts", infoDict->getCount());
10796 
10797 
10798 	if (kcUUID && infoDictKCUUID) {
10799 		*kcUUID = OSData::withData(infoDictKCUUID).detach();
10800 	}
10801 
10802 	result = true;
10803 
10804 finish:
10805 	return result;
10806 }
10807 
10808 bool
10809 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10810     OSDictionary *infoDict, const char *text_seg_name,
10811     OSSharedPtr<OSData> &kcUUID, kc_kind_t type)
10812 {
10813 	OSData  *result = NULL;
10814 	bool success = addKextsFromKextCollection(mh,
10815 	    infoDict,
10816 	    text_seg_name,
10817 	    &result,
10818 	    type);
10819 	if (success) {
10820 		kcUUID.reset(result, OSNoRetain);
10821 	}
10822 	return success;
10823 }
10824 
10825 static OSSharedPtr<OSObject> deferredAuxKCXML;
10826 bool
10827 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh,
10828     OSSharedPtr<OSObject> &parsedXML, kc_kind_t type)
10829 {
10830 	if (type != KCKindAuxiliary) {
10831 		return false;
10832 	}
10833 
10834 	kernel_mach_header_t *_mh;
10835 	_mh = (kernel_mach_header_t*)PE_get_kc_header(type);
10836 	if (!_mh || _mh != mh) {
10837 		return false;
10838 	}
10839 
10840 	if (deferredAuxKCXML) {
10841 		/* only allow this to be called once */
10842 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10843 		    "An Aux KC has already been registered for deferred processing.");
10844 		return false;
10845 	}
10846 
10847 	OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
10848 	if (!infoDict) {
10849 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10850 		    "The Aux KC has info dictionary");
10851 		return false;
10852 	}
10853 
10854 	OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10855 	if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) {
10856 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10857 		    "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey);
10858 		return false;
10859 	}
10860 
10861 	/*
10862 	 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid
10863 	 * sysctl can return the UUID to user space which will check this
10864 	 * value for errors.
10865 	 */
10866 	memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(),
10867 	    kcUUID->getLength());
10868 	uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
10869 	auxkc_uuid_valid = TRUE;
10870 
10871 	deferredAuxKCXML = parsedXML;
10872 
10873 	return true;
10874 }
10875 
10876 OSSharedPtr<OSObject>
10877 OSKext::consumeDeferredKextCollection(kc_kind_t type)
10878 {
10879 	if (type != KCKindAuxiliary || !deferredAuxKCXML) {
10880 		return NULL;
10881 	}
10882 
10883 	return os::move(deferredAuxKCXML);
10884 }
10885 
10886 #if PRAGMA_MARK
10887 #pragma mark Profile-Guided-Optimization Support
10888 #endif
10889 
10890 // #include <InstrProfiling.h>
10891 extern "C" {
10892 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
10893     const char *DataEnd,
10894     const char *CountersBegin,
10895     const char *CountersEnd,
10896     const char *NamesBegin,
10897     const char *NamesEnd);
10898 int __llvm_profile_write_buffer_internal(char *Buffer,
10899     const char *DataBegin,
10900     const char *DataEnd,
10901     const char *CountersBegin,
10902     const char *CountersEnd,
10903     const char *NamesBegin,
10904     const char *NamesEnd);
10905 }
10906 
10907 
10908 static
10909 void
10910 OSKextPgoMetadataPut(char *pBuffer,
10911     size_t *position,
10912     size_t bufferSize,
10913     uint32_t *num_pairs,
10914     const char *key,
10915     const char *value)
10916 {
10917 	size_t strlen_key = strlen(key);
10918 	size_t strlen_value = strlen(value);
10919 	size_t len = strlen(key) + 1 + strlen(value) + 1;
10920 	char *pos = pBuffer + *position;
10921 	*position += len;
10922 	if (pBuffer && bufferSize && *position <= bufferSize) {
10923 		memcpy(pos, key, strlen_key); pos += strlen_key;
10924 		*(pos++) = '=';
10925 		memcpy(pos, value, strlen_value); pos += strlen_value;
10926 		*(pos++) = 0;
10927 		if (num_pairs) {
10928 			(*num_pairs)++;
10929 		}
10930 	}
10931 }
10932 
10933 
10934 static
10935 void
10936 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
10937 {
10938 	*position += strlen(key) + 1 + value_max + 1;
10939 }
10940 
10941 
10942 static
10943 void
10944 OSKextPgoMetadataPutAll(OSKext *kext,
10945     uuid_t instance_uuid,
10946     char *pBuffer,
10947     size_t *position,
10948     size_t bufferSize,
10949     uint32_t *num_pairs)
10950 {
10951 	_static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
10952 	//log_10 2^16 ≈ 4.82
10953 	const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
10954 	const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
10955 
10956 	if (!pBuffer) {
10957 		OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
10958 		OSKextPgoMetadataPutMax(position, "UUID", 36);
10959 		OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
10960 	} else {
10961 		uuid_string_t instance_uuid_string;
10962 		uuid_unparse(instance_uuid, instance_uuid_string);
10963 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10964 		    "INSTANCE", instance_uuid_string);
10965 
10966 		OSSharedPtr<OSData> uuid_data;
10967 		uuid_t uuid;
10968 		uuid_string_t uuid_string;
10969 		uuid_data = kext->copyUUID();
10970 		if (uuid_data) {
10971 			memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
10972 			uuid_unparse(uuid, uuid_string);
10973 			OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10974 			    "UUID", uuid_string);
10975 		}
10976 
10977 		clock_sec_t secs;
10978 		clock_usec_t usecs;
10979 		clock_get_calendar_microtime(&secs, &usecs);
10980 		assert(usecs < 1000000);
10981 		char timestamp[max_timestamp_string_size + 1];
10982 		_static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
10983 		snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
10984 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10985 		    "TIMESTAMP", timestamp);
10986 	}
10987 
10988 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10989 	    "NAME", kext->getIdentifierCString());
10990 
10991 	char versionCString[kOSKextVersionMaxLength];
10992 	OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
10993 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10994 	    "VERSION", versionCString);
10995 }
10996 
10997 static
10998 size_t
10999 OSKextPgoMetadataSize(OSKext *kext)
11000 {
11001 	size_t position = 0;
11002 	uuid_t fakeuuid = {};
11003 	OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
11004 	return position;
11005 }
11006 
11007 int
11008 OSKextGrabPgoDataLocked(OSKext *kext,
11009     bool metadata,
11010     uuid_t instance_uuid,
11011     uint64_t *pSize,
11012     char *pBuffer,
11013     uint64_t bufferSize)
11014 {
11015 	int err = 0;
11016 
11017 	kernel_section_t *sect_prf_data = NULL;
11018 	kernel_section_t *sect_prf_name = NULL;
11019 	kernel_section_t *sect_prf_cnts = NULL;
11020 	uint64_t size;
11021 	size_t metadata_size = 0;
11022 	size_t offset_to_pairs = 0;
11023 
11024 	sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
11025 	sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
11026 	if (!sect_prf_name) {
11027 		// kextcache sometimes truncates the section name to 15 chars
11028 		// <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
11029 		sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
11030 	}
11031 	sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
11032 
11033 	if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
11034 		err = ENOTSUP;
11035 		goto out;
11036 	}
11037 
11038 	size = __llvm_profile_get_size_for_buffer_internal(
11039 		(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
11040 		(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
11041 		(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
11042 
11043 	if (metadata) {
11044 		metadata_size = OSKextPgoMetadataSize(kext);
11045 		size += metadata_size;
11046 		size += sizeof(pgo_metadata_footer);
11047 	}
11048 
11049 
11050 	if (pSize) {
11051 		*pSize = size;
11052 	}
11053 
11054 	if (pBuffer && bufferSize) {
11055 		if (bufferSize < size) {
11056 			err = ERANGE;
11057 			goto out;
11058 		}
11059 
11060 		err = __llvm_profile_write_buffer_internal(
11061 			pBuffer,
11062 			(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
11063 			(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
11064 			(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
11065 
11066 		if (err) {
11067 			err = EIO;
11068 			goto out;
11069 		}
11070 
11071 		if (metadata) {
11072 			offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size;
11073 			if (offset_to_pairs > UINT32_MAX) {
11074 				err = E2BIG;
11075 				goto out;
11076 			}
11077 
11078 			char *end_of_buffer = pBuffer + size;
11079 			struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
11080 			char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
11081 
11082 			size_t metadata_position = 0;
11083 			uint32_t num_pairs = 0;
11084 			OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
11085 			while (metadata_position < metadata_size) {
11086 				metadata_buffer[metadata_position++] = 0;
11087 			}
11088 
11089 			struct pgo_metadata_footer footer;
11090 			footer.magic = htonl(0x6d657461);
11091 			footer.number_of_pairs = htonl( num_pairs );
11092 			footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs );
11093 			memcpy(footerp, &footer, sizeof(footer));
11094 		}
11095 	}
11096 
11097 out:
11098 	return err;
11099 }
11100 
11101 
11102 int
11103 OSKextGrabPgoData(uuid_t uuid,
11104     uint64_t *pSize,
11105     char *pBuffer,
11106     uint64_t bufferSize,
11107     int wait_for_unload,
11108     int metadata)
11109 {
11110 	int err = 0;
11111 	OSSharedPtr<OSKext> kext;
11112 
11113 
11114 	IORecursiveLockLock(sKextLock);
11115 
11116 	kext = OSKext::lookupKextWithUUID(uuid);
11117 	if (!kext) {
11118 		err = ENOENT;
11119 		goto out;
11120 	}
11121 
11122 	if (wait_for_unload) {
11123 		OSKextGrabPgoStruct s;
11124 
11125 		s.metadata = metadata;
11126 		s.pSize = pSize;
11127 		s.pBuffer = pBuffer;
11128 		s.bufferSize = bufferSize;
11129 		s.err = EINTR;
11130 
11131 		struct list_head *prev = &kext->pendingPgoHead;
11132 		struct list_head *next = kext->pendingPgoHead.next;
11133 
11134 		s.list_head.prev = prev;
11135 		s.list_head.next = next;
11136 
11137 		prev->next = &s.list_head;
11138 		next->prev = &s.list_head;
11139 
11140 		kext.reset();
11141 
11142 		IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
11143 
11144 		prev = s.list_head.prev;
11145 		next = s.list_head.next;
11146 
11147 		prev->next = next;
11148 		next->prev = prev;
11149 
11150 		err = s.err;
11151 	} else {
11152 		err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
11153 	}
11154 
11155 out:
11156 
11157 	IORecursiveLockUnlock(sKextLock);
11158 
11159 	return err;
11160 }
11161 
11162 void
11163 OSKextResetPgoCountersLock()
11164 {
11165 	IORecursiveLockLock(sKextLock);
11166 }
11167 
11168 void
11169 OSKextResetPgoCountersUnlock()
11170 {
11171 	IORecursiveLockUnlock(sKextLock);
11172 }
11173 
11174 
11175 extern unsigned int not_in_kdp;
11176 
11177 void
11178 OSKextResetPgoCounters()
11179 {
11180 	assert(!not_in_kdp);
11181 	uint32_t count = sLoadedKexts->getCount();
11182 	for (uint32_t i = 0; i < count; i++) {
11183 		OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
11184 		kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
11185 		if (!sect_prf_cnts) {
11186 			continue;
11187 		}
11188 		memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
11189 	}
11190 }
11191 
11192 OSSharedPtr<OSDictionary>
11193 OSKext::copyLoadedKextInfoByUUID(
11194 	OSArray * kextIdentifiers,
11195 	OSArray * infoKeys)
11196 {
11197 	OSSharedPtr<OSDictionary> result;
11198 	OSSharedPtr<OSDictionary> kextInfo;
11199 	uint32_t       max_count, i, j;
11200 	uint32_t       idCount = 0;
11201 	uint32_t       idIndex = 0;
11202 	IORecursiveLockLock(sKextLock);
11203 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
11204 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
11205 
11206 #if CONFIG_MACF
11207 	/* Is the calling process allowed to query kext info? */
11208 	if (current_task() != kernel_task) {
11209 		int                 macCheckResult      = 0;
11210 		kauth_cred_t        cred                = NULL;
11211 
11212 		cred = kauth_cred_get_with_ref();
11213 		macCheckResult = mac_kext_check_query(cred);
11214 		kauth_cred_unref(&cred);
11215 
11216 		if (macCheckResult != 0) {
11217 			OSKextLog(/* kext */ NULL,
11218 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11219 			    "Failed to query kext info (MAC policy error 0x%x).",
11220 			    macCheckResult);
11221 			goto finish;
11222 		}
11223 	}
11224 #endif
11225 
11226 	/* Empty list of UUIDs is equivalent to no list (get all).
11227 	 */
11228 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11229 		kextIdentifiers = NULL;
11230 	} else if (kextIdentifiers) {
11231 		idCount = kextIdentifiers->getCount();
11232 	}
11233 
11234 	/* Same for keys.
11235 	 */
11236 	if (infoKeys && !infoKeys->getCount()) {
11237 		infoKeys = NULL;
11238 	}
11239 
11240 	max_count = count[0] + count[1];
11241 	result = OSDictionary::withCapacity(max_count);
11242 	if (!result) {
11243 		goto finish;
11244 	}
11245 
11246 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
11247 		for (i = 0; i < count[j]; i++) {
11248 			OSKext       *thisKext     = NULL;        // do not release
11249 			Boolean       includeThis  = true;
11250 			uuid_t        thisKextUUID;
11251 			uuid_t        thisKextTextUUID;
11252 			OSSharedPtr<OSData> uuid_data;
11253 			uuid_string_t uuid_key;
11254 
11255 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
11256 			if (!thisKext) {
11257 				continue;
11258 			}
11259 
11260 			uuid_data = thisKext->copyUUID();
11261 			if (!uuid_data) {
11262 				continue;
11263 			}
11264 
11265 			memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
11266 
11267 			uuid_unparse(thisKextUUID, uuid_key);
11268 
11269 			uuid_data = thisKext->copyTextUUID();
11270 			if (!uuid_data) {
11271 				continue;
11272 			}
11273 			memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
11274 
11275 			/* Skip current kext if we have a list of UUIDs and
11276 			 * it isn't in the list.
11277 			 */
11278 			if (kextIdentifiers) {
11279 				includeThis = false;
11280 
11281 				for (idIndex = 0; idIndex < idCount; idIndex++) {
11282 					const OSString* wantedUUID = OSDynamicCast(OSString,
11283 					    kextIdentifiers->getObject(idIndex));
11284 
11285 					uuid_t uuid;
11286 					uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
11287 
11288 					if ((0 == uuid_compare(uuid, thisKextUUID))
11289 					    || (0 == uuid_compare(uuid, thisKextTextUUID))) {
11290 						includeThis = true;
11291 						/* Only need to find the first kext if multiple match,
11292 						 * ie. asking for the kernel uuid does not need to find
11293 						 * interface kexts or builtin static kexts.
11294 						 */
11295 						kextIdentifiers->removeObject(idIndex);
11296 						uuid_unparse(uuid, uuid_key);
11297 						break;
11298 					}
11299 				}
11300 			}
11301 
11302 			if (!includeThis) {
11303 				continue;
11304 			}
11305 
11306 			kextInfo = thisKext->copyInfo(infoKeys);
11307 			if (kextInfo) {
11308 				result->setObject(uuid_key, kextInfo.get());
11309 			}
11310 
11311 			if (kextIdentifiers && !kextIdentifiers->getCount()) {
11312 				goto finish;
11313 			}
11314 		}
11315 	}
11316 
11317 finish:
11318 	IORecursiveLockUnlock(sKextLock);
11319 
11320 	return result;
11321 }
11322 
11323 /*********************************************************************
11324 *********************************************************************/
11325 /* static */
11326 OSSharedPtr<OSDictionary>
11327 OSKext::copyKextCollectionInfo(
11328 	OSDictionary *requestDict,
11329 	OSArray  *infoKeys)
11330 {
11331 	OSSharedPtr<OSDictionary> result;
11332 	OSString *collectionType = NULL;
11333 	OSObject *rawLoadedState = NULL;
11334 	OSString *loadedState    = NULL;
11335 
11336 	kc_kind_t kc_request_kind = KCKindUnknown;
11337 	bool onlyLoaded = false;
11338 	bool onlyUnloaded = false;
11339 
11340 #if CONFIG_MACF
11341 	/* Is the calling process allowed to query kext info? */
11342 	if (current_task() != kernel_task) {
11343 		int                 macCheckResult      = 0;
11344 		kauth_cred_t        cred                = NULL;
11345 
11346 		cred = kauth_cred_get_with_ref();
11347 		macCheckResult = mac_kext_check_query(cred);
11348 		kauth_cred_unref(&cred);
11349 
11350 		if (macCheckResult != 0) {
11351 			OSKextLog(/* kext */ NULL,
11352 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11353 			    "Failed to query kext info (MAC policy error 0x%x).",
11354 			    macCheckResult);
11355 			goto finish;
11356 		}
11357 	}
11358 #endif
11359 
11360 	if (infoKeys && !infoKeys->getCount()) {
11361 		infoKeys = NULL;
11362 	}
11363 
11364 	collectionType = OSDynamicCast(OSString,
11365 	    _OSKextGetRequestArgument(requestDict,
11366 	    kKextRequestArgumentCollectionTypeKey));
11367 	if (!collectionType) {
11368 		OSKextLog(/* kext */ NULL,
11369 		    kOSKextLogErrorLevel |
11370 		    kOSKextLogIPCFlag,
11371 		    "Invalid '%s' argument to kext collection info request.",
11372 		    kKextRequestArgumentCollectionTypeKey);
11373 		goto finish;
11374 	}
11375 	if (collectionType->isEqualTo(kKCTypePrimary)) {
11376 		kc_request_kind = KCKindPrimary;
11377 	} else if (collectionType->isEqualTo(kKCTypeSystem)) {
11378 		kc_request_kind = KCKindPageable;
11379 	} else if (collectionType->isEqualTo(kKCTypeAuxiliary)) {
11380 		kc_request_kind = KCKindAuxiliary;
11381 	} else if (collectionType->isEqualTo(kKCTypeCodeless)) {
11382 		kc_request_kind = KCKindNone;
11383 	} else if (!collectionType->isEqualTo(kKCTypeAny)) {
11384 		OSKextLog(/* kext */ NULL,
11385 		    kOSKextLogErrorLevel |
11386 		    kOSKextLogIPCFlag,
11387 		    "Invalid '%s' argument value '%s' to kext collection info request.",
11388 		    kKextRequestArgumentCollectionTypeKey,
11389 		    collectionType->getCStringNoCopy());
11390 		goto finish;
11391 	}
11392 
11393 	rawLoadedState = _OSKextGetRequestArgument(requestDict,
11394 	    kKextRequestArgumentLoadedStateKey);
11395 	if (rawLoadedState) {
11396 		loadedState = OSDynamicCast(OSString, rawLoadedState);
11397 		if (!loadedState) {
11398 			OSKextLog(/* kext */ NULL,
11399 			    kOSKextLogErrorLevel |
11400 			    kOSKextLogIPCFlag,
11401 			    "Invalid '%s' argument to kext collection info request.",
11402 			    kKextRequestArgumentLoadedStateKey);
11403 			goto finish;
11404 		}
11405 	}
11406 	if (loadedState) {
11407 		if (loadedState->isEqualTo("Loaded")) {
11408 			onlyLoaded = true;
11409 		} else if (loadedState->isEqualTo("Unloaded")) {
11410 			onlyUnloaded = true;
11411 		} else if (!loadedState->isEqualTo("Any")) {
11412 			OSKextLog(/* kext */ NULL,
11413 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11414 			    "Invalid '%s' argument value '%s' for '%s' collection info",
11415 			    kKextRequestArgumentLoadedStateKey,
11416 			    loadedState->getCStringNoCopy(),
11417 			    collectionType->getCStringNoCopy());
11418 			goto finish;
11419 		}
11420 	}
11421 
11422 	result = OSDictionary::withCapacity(sKextsByID->getCount());
11423 	if (!result) {
11424 		goto finish;
11425 	}
11426 
11427 	IORecursiveLockLock(sKextLock);
11428 	{         // start block scope
11429 		sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11430 		{
11431 			OSKext       *thisKext    = NULL;  // do not release
11432 			OSSharedPtr<OSDictionary> kextInfo;
11433 
11434 			(void)thisKextID;
11435 
11436 			thisKext = OSDynamicCast(OSKext, obj);
11437 			if (!thisKext) {
11438 			        return false;
11439 			}
11440 
11441 			/*
11442 			 * skip the kext if it came from the wrong collection type
11443 			 * (and the caller requested a specific type)
11444 			 */
11445 			if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) {
11446 			        return false;
11447 			}
11448 
11449 			/*
11450 			 * respect the caller's desire to find only loaded or
11451 			 * unloaded kexts
11452 			 */
11453 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11454 			        return false;
11455 			}
11456 			if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11457 			        return false;
11458 			}
11459 
11460 			kextInfo = thisKext->copyInfo(infoKeys);
11461 			if (kextInfo) {
11462 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
11463 			}
11464 			return false;
11465 		});
11466 	} // end block scope
11467 	IORecursiveLockUnlock(sKextLock);
11468 
11469 finish:
11470 	return result;
11471 }
11472 
11473 /* static */
11474 OSSharedPtr<OSArray>
11475 OSKext::copyDextsInfo(
11476 	OSArray *kextIdentifiers,
11477 	OSArray *infoKeys)
11478 {
11479 	OSSharedPtr<OSArray> result = NULL;
11480 	uint32_t idCount = 0;
11481 	bool getActive = false;
11482 	bool getLoaded = false;
11483 	bool getUnloaded = false;
11484 	bool getPendingUpgrade = false;
11485 	unsigned int avgDextCount = 0;
11486 
11487 #if CONFIG_MACF
11488 	/* Is the calling process allowed to query dext info? */
11489 	if (current_task() != kernel_task) {
11490 		int                 macCheckResult      = 0;
11491 		kauth_cred_t        cred                = NULL;
11492 
11493 		cred = kauth_cred_get_with_ref();
11494 		macCheckResult = mac_kext_check_query(cred);
11495 		kauth_cred_unref(&cred);
11496 
11497 		if (macCheckResult != 0) {
11498 			OSKextLog(/* kext */ NULL,
11499 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11500 			    "Failed to query kext info (MAC policy error 0x%x).",
11501 			    macCheckResult);
11502 			goto finish;
11503 		}
11504 	}
11505 #endif
11506 	/*
11507 	 * No infoKeys means return everything we
11508 	 * know about the dexts.
11509 	 */
11510 	if (infoKeys && !infoKeys->getCount()) {
11511 		infoKeys = NULL;
11512 	}
11513 
11514 	/*
11515 	 * Empty list of bundle ids is equivalent to
11516 	 * no list (get all).
11517 	 */
11518 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11519 		kextIdentifiers = NULL;
11520 	} else if (kextIdentifiers) {
11521 		idCount = kextIdentifiers->getCount();
11522 	}
11523 
11524 	/*
11525 	 * Caller can specify which state of dexts to query.
11526 	 */
11527 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveKey)) {
11528 		getActive = true;
11529 	}
11530 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveLoadedKey)) {
11531 		getLoaded = true;
11532 	}
11533 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveUnloadedKey)) {
11534 		getUnloaded = true;
11535 	}
11536 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStatePendingUpgradeKey)) {
11537 		getPendingUpgrade = true;
11538 	}
11539 
11540 	/*
11541 	 * By default we are going to return all active and pendingUpgrade dexts
11542 	 * only.
11543 	 */
11544 	if (!(getActive || getLoaded || getUnloaded || getPendingUpgrade)) {
11545 		getActive = true;
11546 		getPendingUpgrade = true;
11547 	}
11548 
11549 	/*
11550 	 * We return a dictionary of dexts
11551 	 * for every group requested.
11552 	 */
11553 	avgDextCount = sLoadedDriverKitKexts->getCount() + sDriverKitToUpgradeByID->getCount();
11554 	result = OSArray::withCapacity(avgDextCount);
11555 	if (!result) {
11556 		goto finish;
11557 	}
11558 
11559 	IORecursiveLockLock(sKextLock);
11560 	{ // start block scope
11561 		if (getActive || getLoaded || getUnloaded) {
11562 			sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11563 			{
11564 				OSKext *thisKext = NULL;  // do not release
11565 				OSSharedPtr<OSDictionary> kextInfo;
11566 				Boolean includeThis = true;
11567 				(void)thisKextID;
11568 
11569 				thisKext = OSDynamicCast(OSKext, obj);
11570 				if (!thisKext || !thisKext->isDriverKit()) {
11571 				        return false;
11572 				}
11573 
11574 				/*
11575 				 * Skip current dext if we have a list of bundle IDs and
11576 				 * it isn't in the list.
11577 				 */
11578 				if (kextIdentifiers) {
11579 				        includeThis = false;
11580 
11581 				        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11582 				                const OSString * thisRequestID = OSDynamicCast(OSString,
11583 				                kextIdentifiers->getObject(idIndex));
11584 				                if (thisKextID->isEqualTo(thisRequestID)) {
11585 				                        includeThis = true;
11586 				                        break;
11587 						}
11588 					}
11589 				}
11590 
11591 				if (!includeThis) {
11592 				        return false;
11593 				}
11594 
11595 				OSSharedPtr<OSString> state;
11596 				if (sLoadedDriverKitKexts->getNextIndexOfObject(thisKext, 0) == -1U) {
11597 				        if (!(getActive || getUnloaded)) {
11598 				                return false;
11599 					}
11600 				        state = OSString::withCString(kOSBundleDextStateActiveUnloadedKey);
11601 				} else {
11602 				        if (!(getActive || getLoaded)) {
11603 				                return false;
11604 					}
11605 				        state = OSString::withCString(kOSBundleDextStateActiveLoadedKey);
11606 				}
11607 
11608 				kextInfo = thisKext->copyInfo(infoKeys);
11609 				if (kextInfo) {
11610 				        kextInfo->setObject(kOSBundleDextStateKey, state.get());
11611 				        result->setObject(kextInfo.get());
11612 				}
11613 
11614 				return false;
11615 			});
11616 		}
11617 
11618 		if (getPendingUpgrade) {
11619 			sDriverKitToUpgradeByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11620 			{
11621 				OSKext *thisKext = NULL;  // do not release
11622 				OSSharedPtr<OSDictionary> kextInfo;
11623 				Boolean includeThis = true;
11624 				(void)thisKextID;
11625 
11626 				thisKext = OSDynamicCast(OSKext, obj);
11627 				if (!thisKext) {
11628 				        return false;
11629 				}
11630 				__assert_only bool isDext = thisKext->isDriverKit();
11631 				assert(isDext == true);
11632 
11633 				/*
11634 				 * Skip current dext if we have a list of bundle IDs and
11635 				 * it isn't in the list.
11636 				 */
11637 				if (kextIdentifiers) {
11638 				        includeThis = false;
11639 
11640 				        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11641 				                const OSString * thisRequestID = OSDynamicCast(OSString,
11642 				                kextIdentifiers->getObject(idIndex));
11643 				                if (thisKextID->isEqualTo(thisRequestID)) {
11644 				                        includeThis = true;
11645 				                        break;
11646 						}
11647 					}
11648 				}
11649 
11650 				if (!includeThis) {
11651 				        return false;
11652 				}
11653 
11654 				kextInfo = thisKext->copyInfo(infoKeys);
11655 				if (kextInfo) {
11656 				        OSSharedPtr<OSString> state = OSString::withCString(kOSBundleDextStatePendingUpgradeKey);
11657 				        kextInfo->setObject(kOSBundleDextStateKey, state.get());
11658 				        result->setObject(kextInfo.get());
11659 				}
11660 				return false;
11661 			});
11662 		}
11663 	} // end block scope
11664 	IORecursiveLockUnlock(sKextLock);
11665 finish:
11666 	return result;
11667 }
11668 
11669 /*********************************************************************
11670 *********************************************************************/
11671 /* static */
11672 OSSharedPtr<OSDictionary>
11673 OSKext::copyLoadedKextInfo(
11674 	OSArray * kextIdentifiers,
11675 	OSArray * infoKeys)
11676 {
11677 	OSSharedPtr<OSDictionary> result;
11678 	uint32_t       idCount = 0;
11679 	bool           onlyLoaded;
11680 
11681 	IORecursiveLockLock(sKextLock);
11682 
11683 #if CONFIG_MACF
11684 	/* Is the calling process allowed to query kext info? */
11685 	if (current_task() != kernel_task) {
11686 		int                 macCheckResult      = 0;
11687 		kauth_cred_t        cred                = NULL;
11688 
11689 		cred = kauth_cred_get_with_ref();
11690 		macCheckResult = mac_kext_check_query(cred);
11691 		kauth_cred_unref(&cred);
11692 
11693 		if (macCheckResult != 0) {
11694 			OSKextLog(/* kext */ NULL,
11695 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11696 			    "Failed to query kext info (MAC policy error 0x%x).",
11697 			    macCheckResult);
11698 			goto finish;
11699 		}
11700 	}
11701 #endif
11702 
11703 	/* Empty list of bundle ids is equivalent to no list (get all).
11704 	 */
11705 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11706 		kextIdentifiers = NULL;
11707 	} else if (kextIdentifiers) {
11708 		idCount = kextIdentifiers->getCount();
11709 	}
11710 
11711 	/* Same for keys.
11712 	 */
11713 	if (infoKeys && !infoKeys->getCount()) {
11714 		infoKeys = NULL;
11715 	}
11716 
11717 	onlyLoaded =  (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
11718 
11719 	result = OSDictionary::withCapacity(128);
11720 	if (!result) {
11721 		goto finish;
11722 	}
11723 
11724 #if 0
11725 	OSKextLog(/* kext */ NULL,
11726 	    kOSKextLogErrorLevel |
11727 	    kOSKextLogGeneralFlag,
11728 	    "kaslr: vm_kernel_slide 0x%lx \n",
11729 	    vm_kernel_slide);
11730 	OSKextLog(/* kext */ NULL,
11731 	    kOSKextLogErrorLevel |
11732 	    kOSKextLogGeneralFlag,
11733 	    "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
11734 	    vm_kernel_stext, vm_kernel_etext);
11735 	OSKextLog(/* kext */ NULL,
11736 	    kOSKextLogErrorLevel |
11737 	    kOSKextLogGeneralFlag,
11738 	    "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
11739 	    vm_kernel_base, vm_kernel_top);
11740 	OSKextLog(/* kext */ NULL,
11741 	    kOSKextLogErrorLevel |
11742 	    kOSKextLogGeneralFlag,
11743 	    "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
11744 	    vm_kext_base, vm_kext_top);
11745 	OSKextLog(/* kext */ NULL,
11746 	    kOSKextLogErrorLevel |
11747 	    kOSKextLogGeneralFlag,
11748 	    "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
11749 	    vm_prelink_stext, vm_prelink_etext);
11750 	OSKextLog(/* kext */ NULL,
11751 	    kOSKextLogErrorLevel |
11752 	    kOSKextLogGeneralFlag,
11753 	    "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
11754 	    vm_prelink_sinfo, vm_prelink_einfo);
11755 	OSKextLog(/* kext */ NULL,
11756 	    kOSKextLogErrorLevel |
11757 	    kOSKextLogGeneralFlag,
11758 	    "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
11759 	    vm_slinkedit, vm_elinkedit);
11760 #endif
11761 	{         // start block scope
11762 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
11763 		{
11764 			OSKext       * thisKext     = NULL;        // do not release
11765 			Boolean        includeThis  = true;
11766 			OSSharedPtr<OSDictionary> kextInfo;
11767 
11768 			thisKext = OSDynamicCast(OSKext, obj);
11769 			if (!thisKext) {
11770 			        return false;
11771 			}
11772 
11773 			/* Skip current kext if not yet started and caller didn't request all.
11774 			 */
11775 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11776 			        return false;
11777 			}
11778 
11779 			/* Skip current kext if we have a list of bundle IDs and
11780 			 * it isn't in the list.
11781 			 */
11782 			if (kextIdentifiers) {
11783 			        includeThis = false;
11784 
11785 			        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11786 			                const OSString * thisRequestID = OSDynamicCast(OSString,
11787 			                kextIdentifiers->getObject(idIndex));
11788 			                if (thisKextID->isEqualTo(thisRequestID)) {
11789 			                        includeThis = true;
11790 			                        break;
11791 					}
11792 				}
11793 			}
11794 
11795 			if (!includeThis) {
11796 			        return false;
11797 			}
11798 
11799 			kextInfo = thisKext->copyInfo(infoKeys);
11800 			if (kextInfo) {
11801 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
11802 			}
11803 			return false;
11804 		});
11805 	}         // end block scope
11806 
11807 finish:
11808 	IORecursiveLockUnlock(sKextLock);
11809 
11810 	return result;
11811 }
11812 
11813 /*********************************************************************
11814 * Any info that needs to do allocations must goto finish on alloc
11815 * failure. Info that is just a lookup should just not set the object
11816 * if the info does not exist.
11817 *********************************************************************/
11818 #define _OSKextLoadInfoDictCapacity   (12)
11819 
11820 OSSharedPtr<OSDictionary>
11821 OSKext::copyInfo(OSArray * infoKeys)
11822 {
11823 	OSSharedPtr<OSDictionary>  result;
11824 	bool                       success                     = false;
11825 	OSSharedPtr<OSData>        headerData;
11826 	OSSharedPtr<OSData>        logData;
11827 	OSSharedPtr<OSNumber>      cpuTypeNumber;
11828 	OSSharedPtr<OSNumber>      cpuSubtypeNumber;
11829 	OSString                 * versionString               = NULL;        // do not release
11830 	OSString                 * bundleType                  = NULL;        // do not release
11831 	uint32_t                   executablePathCStringSize   = 0;
11832 	char                     * executablePathCString       = NULL;        // must kfree
11833 	OSSharedPtr<OSString>      executablePathString;
11834 	OSSharedPtr<OSData>        uuid;
11835 	OSSharedPtr<OSArray>       dependencyLoadTags;
11836 	OSSharedPtr<OSCollectionIterator>      metaClassIterator;
11837 	OSSharedPtr<OSArray>       metaClassInfo;
11838 	OSSharedPtr<OSDictionary>  metaClassDict;
11839 	OSMetaClass              * thisMetaClass               = NULL;        // do not release
11840 	OSSharedPtr<OSString>      metaClassName;
11841 	OSSharedPtr<OSString>      superclassName;
11842 	kc_format_t                kcformat;
11843 	uint32_t                   count, i;
11844 
11845 	result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
11846 	if (!result) {
11847 		goto finish;
11848 	}
11849 
11850 
11851 	/* Empty keys means no keys, but NULL is quicker to check.
11852 	 */
11853 	if (infoKeys && !infoKeys->getCount()) {
11854 		infoKeys = NULL;
11855 	}
11856 
11857 	if (!PE_get_primary_kc_format(&kcformat)) {
11858 		goto finish;
11859 	}
11860 
11861 	/* Headers, CPU type, and CPU subtype.
11862 	 */
11863 	if (!infoKeys ||
11864 	    _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
11865 	    _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
11866 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
11867 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
11868 		if (linkedExecutable && !isInterface()) {
11869 			kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
11870 			    linkedExecutable->getBytesNoCopy();
11871 
11872 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX
11873 			// do not return macho header info on shipping embedded - 19095897
11874 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
11875 				kernel_mach_header_t *  temp_kext_mach_hdr;
11876 				struct load_command *   lcp;
11877 
11878 				headerData = OSData::withBytes(kext_mach_hdr,
11879 				    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
11880 				if (!headerData) {
11881 					goto finish;
11882 				}
11883 
11884 				// unslide any vmaddrs we return to userspace - 10726716
11885 				temp_kext_mach_hdr = (kernel_mach_header_t *)
11886 				    headerData->getBytesNoCopy();
11887 				if (temp_kext_mach_hdr == NULL) {
11888 					goto finish;
11889 				}
11890 
11891 				lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
11892 				for (i = 0; (i < temp_kext_mach_hdr->ncmds) && !flags.unslidMachO; i++) {
11893 					if (lcp->cmd == LC_SEGMENT_KERNEL) {
11894 						kernel_segment_command_t *  segp;
11895 						kernel_section_t *          secp;
11896 
11897 						segp = (kernel_segment_command_t *) lcp;
11898 						// 10543468 - if we jettisoned __LINKEDIT clear size info
11899 						if (flags.jettisonLinkeditSeg) {
11900 							if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
11901 								segp->vmsize = 0;
11902 								segp->fileoff = 0;
11903 								segp->filesize = 0;
11904 							}
11905 						}
11906 
11907 #if __arm__ || __arm64__
11908 						// iBoot disregards zero-size segments, just set their addresses to gVirtBase
11909 						// and unslide them to avoid vm assertion failures / kernel logging breakage.
11910 						if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) {
11911 							segp->vmaddr = gVirtBase;
11912 							for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
11913 								secp->size = 0; // paranoia :)
11914 								secp->addr = gVirtBase;
11915 							}
11916 						}
11917 #endif
11918 
11919 #if 0
11920 						OSKextLog(/* kext */ NULL,
11921 						    kOSKextLogErrorLevel |
11922 						    kOSKextLogGeneralFlag,
11923 						    "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
11924 						    __FUNCTION__, segp->segname, segp->vmaddr,
11925 						    VM_KERNEL_UNSLIDE(segp->vmaddr),
11926 						    segp->vmsize, segp->nsects);
11927 						if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
11928 						    (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
11929 						    (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
11930 						    (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
11931 						    (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
11932 							OSKextLog(/* kext */ NULL,
11933 							    kOSKextLogErrorLevel |
11934 							    kOSKextLogGeneralFlag,
11935 							    "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
11936 							    __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
11937 						}
11938 #endif
11939 						segp->vmaddr = ml_static_unslide(segp->vmaddr);
11940 
11941 						for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
11942 							secp->addr = ml_static_unslide(secp->addr);
11943 						}
11944 					}
11945 					lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
11946 				}
11947 				result->setObject(kOSBundleMachOHeadersKey, headerData.get());
11948 			}
11949 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX
11950 
11951 			if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
11952 				osLogDataHeaderRef *header;
11953 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
11954 
11955 				void *os_log_data               = NULL;
11956 				void *cstring_data              = NULL;
11957 				void *asan_cstring_data         = NULL;
11958 				unsigned long os_log_size       = 0;
11959 				unsigned long cstring_size      = 0;
11960 				unsigned long asan_cstring_size = 0;
11961 				uint32_t os_log_offset          = 0;
11962 				uint32_t cstring_offset         = 0;
11963 				uint32_t asan_cstring_offset    = 0;
11964 				bool res;
11965 
11966 				os_log_data         = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
11967 				cstring_data        = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
11968 				asan_cstring_data   = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size);
11969 
11970 				/*
11971 				 * If the addresses in the Mach-O header are unslid, manually
11972 				 * slide them to allow for dereferencing.
11973 				 */
11974 				if (flags.unslidMachO) {
11975 					os_log_data = (os_log_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)os_log_data) : nullptr;
11976 					cstring_data = (cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)cstring_data) : nullptr;
11977 					asan_cstring_data = (asan_cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)asan_cstring_data) : nullptr;
11978 				}
11979 
11980 				os_log_offset       = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr;
11981 				cstring_offset      = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr;
11982 				asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr;
11983 
11984 				header             = (osLogDataHeaderRef *) headerBytes;
11985 				header->version    = OS_LOG_HDR_VERSION;
11986 				header->sect_count = NUM_OS_LOG_SECTIONS;
11987 				header->sections[OS_LOG_SECT_IDX].sect_offset       = os_log_offset;
11988 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) os_log_size;
11989 				header->sections[CSTRING_SECT_IDX].sect_offset      = cstring_offset;
11990 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) cstring_size;
11991 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset;
11992 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) asan_cstring_size;
11993 
11994 
11995 				logData = OSData::withValue(*header);
11996 				if (!logData) {
11997 					goto finish;
11998 				}
11999 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
12000 				if (!res) {
12001 					goto finish;
12002 				}
12003 				if (os_log_data) {
12004 					res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
12005 					if (!res) {
12006 						goto finish;
12007 					}
12008 				}
12009 				if (cstring_data) {
12010 					res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
12011 					if (!res) {
12012 						goto finish;
12013 					}
12014 				}
12015 				if (asan_cstring_data) {
12016 					res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size);
12017 					if (!res) {
12018 						goto finish;
12019 					}
12020 				}
12021 				result->setObject(kOSBundleLogStringsKey, logData.get());
12022 			}
12023 
12024 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
12025 				cpuTypeNumber = OSNumber::withNumber(
12026 					(uint64_t) kext_mach_hdr->cputype,
12027 					8 * sizeof(kext_mach_hdr->cputype));
12028 				if (!cpuTypeNumber) {
12029 					goto finish;
12030 				}
12031 				result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get());
12032 			}
12033 
12034 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
12035 				cpuSubtypeNumber = OSNumber::withNumber(
12036 					(uint64_t) kext_mach_hdr->cpusubtype,
12037 					8 * sizeof(kext_mach_hdr->cpusubtype));
12038 				if (!cpuSubtypeNumber) {
12039 					goto finish;
12040 				}
12041 				result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get());
12042 			}
12043 		} else {
12044 			if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
12045 				osLogDataHeaderRef *header;
12046 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
12047 				bool res;
12048 
12049 				header             = (osLogDataHeaderRef *) headerBytes;
12050 				header->version    = OS_LOG_HDR_VERSION;
12051 				header->sect_count = NUM_OS_LOG_SECTIONS;
12052 				header->sections[OS_LOG_SECT_IDX].sect_offset       = 0;
12053 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) 0;
12054 				header->sections[CSTRING_SECT_IDX].sect_offset      = 0;
12055 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) 0;
12056 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0;
12057 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) 0;
12058 
12059 				logData = OSData::withValue(*header);
12060 				if (!logData) {
12061 					goto finish;
12062 				}
12063 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
12064 				if (!res) {
12065 					goto finish;
12066 				}
12067 				result->setObject(kOSBundleLogStringsKey, logData.get());
12068 			}
12069 		}
12070 	}
12071 
12072 	/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
12073 	 */
12074 	result->setObject(kCFBundleIdentifierKey, bundleID.get());
12075 
12076 	/* kOSBundleDextUniqueIdentifierKey if present.
12077 	 */
12078 	if (isDriverKit() && dextUniqueID != NULL) {
12079 		result->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID.get());
12080 	}
12081 
12082 	/* CFBundlePackageType
12083 	 */
12084 	bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL;
12085 	if (bundleType) {
12086 		result->setObject(kCFBundlePackageTypeKey, bundleType);
12087 	}
12088 
12089 	/* CFBundleVersion.
12090 	 */
12091 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
12092 		versionString = OSDynamicCast(OSString,
12093 		    getPropertyForHostArch(kCFBundleVersionKey));
12094 		if (versionString) {
12095 			result->setObject(kCFBundleVersionKey, versionString);
12096 		}
12097 	}
12098 
12099 	/* OSBundleCompatibleVersion.
12100 	 */
12101 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
12102 		versionString = OSDynamicCast(OSString,
12103 		    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
12104 		if (versionString) {
12105 			result->setObject(kOSBundleCompatibleVersionKey, versionString);
12106 		}
12107 	}
12108 
12109 	/* Path.
12110 	 */
12111 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
12112 		if (path) {
12113 			result->setObject(kOSBundlePathKey, path.get());
12114 		}
12115 	}
12116 
12117 
12118 	/* OSBundleExecutablePath.
12119 	 */
12120 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
12121 		if (path && executableRelPath) {
12122 			uint32_t pathLength = path->getLength();         // gets incremented below
12123 
12124 			// +1 for slash, +1 for \0
12125 			executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
12126 
12127 			executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
12128 			    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);         // +1 for \0
12129 			if (!executablePathCString) {
12130 				goto finish;
12131 			}
12132 			strlcpy(executablePathCString, path->getCStringNoCopy(),
12133 			    executablePathCStringSize);
12134 			executablePathCString[pathLength++] = '/';
12135 			executablePathCString[pathLength++] = '\0';
12136 			strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
12137 			    executablePathCStringSize);
12138 
12139 			executablePathString = OSString::withCString(executablePathCString);
12140 
12141 			if (!executablePathString) {
12142 				goto finish;
12143 			}
12144 
12145 			result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
12146 		} else if (flags.builtin) {
12147 			result->setObject(kOSBundleExecutablePathKey, bundleID.get());
12148 		} else if (isDriverKit()) {
12149 			if (path) {
12150 				// +1 for slash, +1 for \0
12151 				uint32_t pathLength = path->getLength();
12152 				executablePathCStringSize = pathLength + 2;
12153 
12154 				executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
12155 				    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
12156 				if (!executablePathCString) {
12157 					goto finish;
12158 				}
12159 				strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
12160 				executablePathCString[pathLength++] = '/';
12161 				executablePathCString[pathLength++] = '\0';
12162 
12163 				executablePathString = OSString::withCString(executablePathCString);
12164 
12165 				if (!executablePathString) {
12166 					goto finish;
12167 				}
12168 
12169 				result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
12170 			}
12171 		}
12172 	}
12173 
12174 	/* UUID, if the kext has one.
12175 	 */
12176 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
12177 		uuid = copyUUID();
12178 		if (uuid) {
12179 			result->setObject(kOSBundleUUIDKey, uuid.get());
12180 		}
12181 	}
12182 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
12183 		uuid = copyTextUUID();
12184 		if (uuid) {
12185 			result->setObject(kOSBundleTextUUIDKey, uuid.get());
12186 		}
12187 	}
12188 
12189 	/*
12190 	 * Info.plist digest
12191 	 */
12192 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) {
12193 		OSData *digest;
12194 		digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL;
12195 		if (digest) {
12196 			result->setObject(kOSKextInfoPlistDigestKey, digest);
12197 		}
12198 	}
12199 
12200 	/*
12201 	 * Collection type
12202 	 */
12203 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) {
12204 		result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString()));
12205 	}
12206 
12207 	/*
12208 	 * Collection availability
12209 	 */
12210 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) {
12211 		result->setObject(kOSKextAuxKCAvailabilityKey,
12212 		    isLoadable() ? kOSBooleanTrue : kOSBooleanFalse);
12213 	}
12214 
12215 	/*
12216 	 * Allows user load
12217 	 */
12218 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) {
12219 		OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey));
12220 		if (allowUserLoad) {
12221 			result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad);
12222 		}
12223 	}
12224 
12225 	/*
12226 	 * Bundle Dependencies (OSBundleLibraries)
12227 	 */
12228 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) {
12229 		OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey));
12230 		if (libraries) {
12231 			result->setObject(kOSBundleLibrariesKey, libraries);
12232 		}
12233 	}
12234 
12235 	/*****
12236 	 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
12237 	 */
12238 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
12239 		result->setObject(kOSKernelResourceKey,
12240 		    isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
12241 	}
12242 
12243 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
12244 		result->setObject(kOSBundleIsInterfaceKey,
12245 		    isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
12246 	}
12247 
12248 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
12249 		result->setObject(kOSBundlePrelinkedKey,
12250 		    isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
12251 	}
12252 
12253 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
12254 		result->setObject(kOSBundleStartedKey,
12255 		    isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
12256 	}
12257 
12258 	/* LoadTag (Index).
12259 	 */
12260 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
12261 		OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
12262 		    /* numBits */ 8 * sizeof(loadTag));
12263 		if (!scratchNumber) {
12264 			goto finish;
12265 		}
12266 		result->setObject(kOSBundleLoadTagKey, scratchNumber.get());
12267 	}
12268 
12269 	/* LoadAddress, LoadSize.
12270 	 */
12271 	if (!infoKeys ||
12272 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
12273 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
12274 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
12275 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
12276 	    _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
12277 		bool is_dext = isDriverKit();
12278 		if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
12279 			/* These go to userspace via serialization, so we don't want any doubts
12280 			 * about their size.
12281 			 */
12282 			uint64_t    loadAddress     = 0;
12283 			uint32_t    loadSize        = 0;
12284 			uint32_t    wiredSize       = 0;
12285 			uint64_t    execLoadAddress = 0;
12286 			uint32_t    execLoadSize    = 0;
12287 
12288 			/* Interfaces always report 0 load address & size.
12289 			 * Just the way they roll.
12290 			 *
12291 			 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
12292 			 * xxx - shouldn't have one!
12293 			 */
12294 
12295 			if (flags.builtin || linkedExecutable) {
12296 				kernel_mach_header_t     *mh  = NULL;
12297 				kernel_segment_command_t *seg = NULL;
12298 
12299 				if (flags.builtin) {
12300 					loadAddress = kmod_info->address;
12301 					loadSize    = (uint32_t)kmod_info->size;
12302 				} else {
12303 					loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
12304 					loadSize = linkedExecutable->getLength();
12305 				}
12306 				mh = (kernel_mach_header_t *)loadAddress;
12307 				loadAddress = ml_static_unslide(loadAddress);
12308 
12309 				/* Walk through the kext, looking for the first executable
12310 				 * segment in case we were asked for its size/address.
12311 				 */
12312 				for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
12313 					if (seg->initprot & VM_PROT_EXECUTE) {
12314 						execLoadAddress = (flags.unslidMachO) ? seg->vmaddr : ml_static_unslide(seg->vmaddr);
12315 						execLoadSize = (uint32_t)seg->vmsize;
12316 						break;
12317 					}
12318 				}
12319 
12320 				/* If we have a kmod_info struct, calculated the wired size
12321 				 * from that. Otherwise it's the full load size.
12322 				 */
12323 				if (kmod_info) {
12324 					wiredSize = loadSize - (uint32_t)kmod_info->hdr_size;
12325 				} else {
12326 					wiredSize = loadSize;
12327 				}
12328 			} else if (is_dext) {
12329 				/*
12330 				 * DriverKit userspace executables do not have a kernel linkedExecutable,
12331 				 * so we "fake" their address range with the LoadTag.
12332 				 */
12333 				if (loadTag) {
12334 					loadAddress = execLoadAddress = loadTag;
12335 					loadSize = execLoadSize = 1;
12336 				}
12337 			}
12338 
12339 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
12340 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12341 					(unsigned long long)(loadAddress),
12342 					/* numBits */ 8 * sizeof(loadAddress));
12343 				if (!scratchNumber) {
12344 					goto finish;
12345 				}
12346 				result->setObject(kOSBundleLoadAddressKey, scratchNumber.get());
12347 			}
12348 			if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) {
12349 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
12350 				    && loadAddress && loadSize) {
12351 					void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary);
12352 					if (!baseAddress) {
12353 						goto finish;
12354 					}
12355 
12356 					OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12357 						(unsigned long long)ml_static_unslide((vm_offset_t)baseAddress),
12358 						/* numBits */ 8 * sizeof(loadAddress));
12359 					if (!scratchNumber) {
12360 						goto finish;
12361 					}
12362 					result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get());
12363 				}
12364 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
12365 				    && (this == sKernelKext) && gBuiltinKmodsCount) {
12366 					result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
12367 				}
12368 			}
12369 
12370 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
12371 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12372 					(unsigned long long)(execLoadAddress),
12373 					/* numBits */ 8 * sizeof(execLoadAddress));
12374 				if (!scratchNumber) {
12375 					goto finish;
12376 				}
12377 				result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get());
12378 			}
12379 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
12380 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12381 					(unsigned long long)(loadSize),
12382 					/* numBits */ 8 * sizeof(loadSize));
12383 				if (!scratchNumber) {
12384 					goto finish;
12385 				}
12386 				result->setObject(kOSBundleLoadSizeKey, scratchNumber.get());
12387 			}
12388 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
12389 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12390 					(unsigned long long)(execLoadSize),
12391 					/* numBits */ 8 * sizeof(execLoadSize));
12392 				if (!scratchNumber) {
12393 					goto finish;
12394 				}
12395 				result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get());
12396 			}
12397 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
12398 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12399 					(unsigned long long)(wiredSize),
12400 					/* numBits */ 8 * sizeof(wiredSize));
12401 				if (!scratchNumber) {
12402 					goto finish;
12403 				}
12404 				result->setObject(kOSBundleWiredSizeKey, scratchNumber.get());
12405 			}
12406 		}
12407 	}
12408 
12409 	/* OSBundleDependencies. In descending order for
12410 	 * easy compatibility with kextstat(8).
12411 	 */
12412 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
12413 		if ((count = getNumDependencies())) {
12414 			dependencyLoadTags = OSArray::withCapacity(count);
12415 			result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get());
12416 
12417 			i = count - 1;
12418 			do {
12419 				OSKext * dependency = OSDynamicCast(OSKext,
12420 				    dependencies->getObject(i));
12421 
12422 				if (!dependency) {
12423 					continue;
12424 				}
12425 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12426 					(unsigned long long)dependency->getLoadTag(),
12427 					/* numBits*/ 8 * sizeof(loadTag));
12428 				if (!scratchNumber) {
12429 					goto finish;
12430 				}
12431 				dependencyLoadTags->setObject(scratchNumber.get());
12432 			} while (i--);
12433 		}
12434 	}
12435 
12436 	/* OSBundleMetaClasses.
12437 	 */
12438 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
12439 		if (metaClasses && metaClasses->getCount()) {
12440 			metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get());
12441 			metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
12442 			if (!metaClassIterator || !metaClassInfo) {
12443 				goto finish;
12444 			}
12445 			result->setObject(kOSBundleClassesKey, metaClassInfo.get());
12446 
12447 			while ((thisMetaClass = OSDynamicCast(OSMetaClass,
12448 			    metaClassIterator->getNextObject()))) {
12449 				metaClassDict = OSDictionary::withCapacity(3);
12450 				if (!metaClassDict) {
12451 					goto finish;
12452 				}
12453 
12454 				metaClassName = OSString::withCString(thisMetaClass->getClassName());
12455 				if (thisMetaClass->getSuperClass()) {
12456 					superclassName = OSString::withCString(
12457 						thisMetaClass->getSuperClass()->getClassName());
12458 				}
12459 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
12460 				    8 * sizeof(unsigned int));
12461 
12462 				/* Bail if any of the essentials is missing. The root class lacks a superclass,
12463 				 * of course.
12464 				 */
12465 				if (!metaClassDict || !metaClassName || !scratchNumber) {
12466 					goto finish;
12467 				}
12468 
12469 				metaClassInfo->setObject(metaClassDict.get());
12470 				metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get());
12471 				if (superclassName) {
12472 					metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get());
12473 				}
12474 				metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get());
12475 			}
12476 		}
12477 	}
12478 
12479 	/* OSBundleRetainCount.
12480 	 */
12481 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
12482 		{
12483 			int kextRetainCount = getRetainCount() - 1;
12484 			if (isLoaded()) {
12485 				kextRetainCount--;
12486 			}
12487 			OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12488 				(int)kextRetainCount,
12489 				/* numBits*/ 8 * sizeof(int));
12490 			if (scratchNumber) {
12491 				result->setObject(kOSBundleRetainCountKey, scratchNumber.get());
12492 			}
12493 		}
12494 	}
12495 
12496 	success = true;
12497 
12498 finish:
12499 	if (executablePathCString) {
12500 		kfree_data(executablePathCString, executablePathCStringSize);
12501 	}
12502 	if (!success) {
12503 		result.reset();
12504 	}
12505 	return result;
12506 }
12507 
12508 /*********************************************************************
12509 *********************************************************************/
12510 /* static */
12511 bool
12512 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
12513 {
12514 	bool ok;
12515 	OSSharedPtr<OSKext> kext;
12516 
12517 	IORecursiveLockLock(sKextLock);
12518 	kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain);
12519 	IORecursiveLockUnlock(sKextLock);
12520 
12521 	if (!kext || !kext->path || !kext->userExecutableRelPath) {
12522 		return false;
12523 	}
12524 	snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
12525 	    kext->path->getCStringNoCopy(),
12526 	    kext->userExecutableRelPath->getCStringNoCopy());
12527 	ok = true;
12528 
12529 	return ok;
12530 }
12531 
12532 /*********************************************************************
12533 *********************************************************************/
12534 /* static */
12535 OSReturn
12536 OSKext::requestResource(
12537 	const char                    * kextIdentifierCString,
12538 	const char                    * resourceNameCString,
12539 	OSKextRequestResourceCallback   callback,
12540 	void                          * context,
12541 	OSKextRequestTag              * requestTagOut)
12542 {
12543 	OSReturn                        result = kOSReturnError;
12544 	OSSharedPtr<OSKext>             callbackKext;        // looked up
12545 
12546 	OSKextRequestTag   requestTag      = -1;
12547 	OSSharedPtr<OSNumber>           requestTagNum;
12548 	OSSharedPtr<OSDictionary>       requestDict;
12549 	OSSharedPtr<OSString>           kextIdentifier;
12550 	OSSharedPtr<OSString>           resourceName;
12551 
12552 	OSSharedPtr<OSDictionary>       callbackRecord;
12553 	OSSharedPtr<OSValueObject<OSKextRequestResourceCallback> > callbackWrapper;
12554 
12555 	OSSharedPtr<OSValueObject<void *> > contextWrapper;
12556 
12557 	IORecursiveLockLock(sKextLock);
12558 
12559 	if (requestTagOut) {
12560 		*requestTagOut = kOSKextRequestTagInvalid;
12561 	}
12562 
12563 	/* If requests to user space are disabled, don't go any further */
12564 	if (!sKernelRequestsEnabled) {
12565 		OSKextLog(/* kext */ NULL,
12566 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12567 		    "Can't request resource %s for %s - requests to user space are disabled.",
12568 		    resourceNameCString,
12569 		    kextIdentifierCString);
12570 		result = kOSKextReturnDisabled;
12571 		goto finish;
12572 	}
12573 
12574 	if (!kextIdentifierCString || !resourceNameCString || !callback) {
12575 		result = kOSKextReturnInvalidArgument;
12576 		goto finish;
12577 	}
12578 
12579 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
12580 	if (!callbackKext) {
12581 		OSKextLog(/* kext */ NULL,
12582 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12583 		    "Resource request has bad callback address.");
12584 		result = kOSKextReturnInvalidArgument;
12585 		goto finish;
12586 	}
12587 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
12588 		OSKextLog(/* kext */ NULL,
12589 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12590 		    "Resource request callback is in a kext that is not started.");
12591 		result = kOSKextReturnInvalidArgument;
12592 		goto finish;
12593 	}
12594 
12595 	/* Do not allow any new requests to be made on a kext that is unloading.
12596 	 */
12597 	if (callbackKext->flags.stopping) {
12598 		result = kOSKextReturnStopping;
12599 		goto finish;
12600 	}
12601 
12602 	/* If we're wrapped the next available request tag around to the negative
12603 	 * numbers, we can't service any more requests.
12604 	 */
12605 	if (sNextRequestTag == kOSKextRequestTagInvalid) {
12606 		OSKextLog(/* kext */ NULL,
12607 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12608 		    "No more request tags available; restart required.");
12609 		result = kOSKextReturnNoResources;
12610 		goto finish;
12611 	}
12612 	requestTag = sNextRequestTag++;
12613 
12614 	result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
12615 	    requestDict);
12616 	if (result != kOSReturnSuccess) {
12617 		goto finish;
12618 	}
12619 
12620 	kextIdentifier = OSString::withCString(kextIdentifierCString);
12621 	resourceName   = OSString::withCString(resourceNameCString);
12622 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
12623 	    8 * sizeof(requestTag));
12624 	if (!kextIdentifier ||
12625 	    !resourceName ||
12626 	    !requestTagNum ||
12627 	    !_OSKextSetRequestArgument(requestDict.get(),
12628 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) ||
12629 	    !_OSKextSetRequestArgument(requestDict.get(),
12630 	    kKextRequestArgumentNameKey, resourceName.get()) ||
12631 	    !_OSKextSetRequestArgument(requestDict.get(),
12632 	    kKextRequestArgumentRequestTagKey, requestTagNum.get())) {
12633 		result = kOSKextReturnNoMemory;
12634 		goto finish;
12635 	}
12636 
12637 	callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection());
12638 	if (!callbackRecord) {
12639 		result = kOSKextReturnNoMemory;
12640 		goto finish;
12641 	}
12642 	// we validate callback address at call time
12643 	callbackWrapper = OSValueObjectWithValue(callback);
12644 	if (context) {
12645 		contextWrapper = OSValueObjectWithValue(context);
12646 	}
12647 	if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
12648 	    kKextRequestArgumentCallbackKey, callbackWrapper.get())) {
12649 		result = kOSKextReturnNoMemory;
12650 		goto finish;
12651 	}
12652 
12653 	if (context) {
12654 		if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
12655 		    kKextRequestArgumentContextKey, contextWrapper.get())) {
12656 			result = kOSKextReturnNoMemory;
12657 			goto finish;
12658 		}
12659 	}
12660 
12661 	/* Only post the requests after all the other potential failure points
12662 	 * have been passed.
12663 	 */
12664 	if (!sKernelRequests->setObject(requestDict.get()) ||
12665 	    !sRequestCallbackRecords->setObject(callbackRecord.get())) {
12666 		result = kOSKextReturnNoMemory;
12667 		goto finish;
12668 	}
12669 
12670 	OSKext::pingIOKitDaemon();
12671 
12672 	result = kOSReturnSuccess;
12673 	if (requestTagOut) {
12674 		*requestTagOut = requestTag;
12675 	}
12676 
12677 finish:
12678 
12679 	/* If we didn't succeed, yank the request & callback
12680 	 * from their holding arrays.
12681 	 */
12682 	if (result != kOSReturnSuccess) {
12683 		unsigned int index;
12684 
12685 		index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0);
12686 		if (index != (unsigned int)-1) {
12687 			sKernelRequests->removeObject(index);
12688 		}
12689 		index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0);
12690 		if (index != (unsigned int)-1) {
12691 			sRequestCallbackRecords->removeObject(index);
12692 		}
12693 	}
12694 
12695 	OSKext::considerUnloads(/* rescheduleOnly? */ true);
12696 
12697 	IORecursiveLockUnlock(sKextLock);
12698 
12699 	return result;
12700 }
12701 
12702 OSReturn
12703 OSKext::requestDaemonLaunch(
12704 	OSString *kextIdentifier,
12705 	OSString *serverName,
12706 	OSNumber *serverTag,
12707 	OSBoolean *reslide,
12708 	IOUserServerCheckInToken * checkInToken,
12709 	OSData *serverDUI)
12710 {
12711 	OSReturn       result        = kOSReturnError;
12712 	OSSharedPtr<OSDictionary> requestDict;
12713 	unsigned int size = 0;
12714 	const char *dextUniqueIDCString = NULL;
12715 
12716 	if (!kextIdentifier || !serverName || !serverTag || !checkInToken) {
12717 		return kOSKextReturnInvalidArgument;
12718 	}
12719 
12720 	if (serverDUI != NULL) {
12721 		dextUniqueIDCString = getDextUniqueIDCString(serverDUI, &size);
12722 	}
12723 
12724 	IORecursiveLockLock(sKextLock);
12725 
12726 	OSKextLog(/* kext */ NULL,
12727 	    kOSKextLogDebugLevel |
12728 	    kOSKextLogGeneralFlag,
12729 	    "Requesting daemon launch for %s %s with serverName %s and tag %llu%s",
12730 	    kextIdentifier->getCStringNoCopy(),
12731 	    (dextUniqueIDCString != NULL)?dextUniqueIDCString:"",
12732 	    serverName->getCStringNoCopy(),
12733 	    serverTag->unsigned64BitValue(),
12734 	    reslide == kOSBooleanTrue ? " with reslid shared cache" : ""
12735 	    );
12736 
12737 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict);
12738 	if (result != kOSReturnSuccess) {
12739 		goto finish;
12740 	}
12741 
12742 	if (!_OSKextSetRequestArgument(requestDict.get(),
12743 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
12744 	    !_OSKextSetRequestArgument(requestDict.get(),
12745 	    kKextRequestArgumentDriverExtensionServerName, serverName) ||
12746 	    !_OSKextSetRequestArgument(requestDict.get(),
12747 	    kKextRequestArgumentDriverExtensionServerTag, serverTag) ||
12748 	    !_OSKextSetRequestArgument(requestDict.get(),
12749 	    kKextRequestArgumentDriverExtensionReslideSharedCache, reslide) ||
12750 	    !_OSKextSetRequestArgument(requestDict.get(),
12751 	    kKextRequestArgumentCheckInToken, checkInToken)) {
12752 		result = kOSKextReturnNoMemory;
12753 		goto finish;
12754 	}
12755 
12756 	if (serverDUI) {
12757 		if (!_OSKextSetRequestArgument(requestDict.get(),
12758 		    kOSBundleDextUniqueIdentifierKey, serverDUI)) {
12759 			result = kOSKextReturnNoMemory;
12760 			goto finish;
12761 		}
12762 	}
12763 
12764 	/* Only post the requests after all the other potential failure points
12765 	 * have been passed.
12766 	 */
12767 	if (!sKernelRequests->setObject(requestDict.get())) {
12768 		result = kOSKextReturnNoMemory;
12769 		goto finish;
12770 	}
12771 	OSKext::pingIOKitDaemon();
12772 
12773 	result = kOSReturnSuccess;
12774 finish:
12775 	IORecursiveLockUnlock(sKextLock);
12776 	if (dextUniqueIDCString) {
12777 		kfree_data(dextUniqueIDCString, size);
12778 	}
12779 	return result;
12780 }
12781 
12782 OSReturn
12783 OSKext::notifyDextUpgrade(
12784 	OSString *kextIdentifier,
12785 	OSData *dextUniqueIdentifier)
12786 {
12787 	OSReturn result = kOSReturnError;
12788 	OSSharedPtr<OSDictionary> requestDict;
12789 	unsigned int size = 0;
12790 	const char *dextUniqueIDCString = getDextUniqueIDCString(dextUniqueIdentifier, &size);
12791 	assert(dextUniqueIDCString != NULL);
12792 
12793 	IORecursiveLockLock(sKextLock);
12794 
12795 	OSKextLog(NULL,
12796 	    kOSKextLogDebugLevel |
12797 	    kOSKextLogGeneralFlag,
12798 	    "Notifying of dext upgrade for %s with UniqueID %s",
12799 	    kextIdentifier->getCStringNoCopy(), dextUniqueIDCString);
12800 
12801 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonUpgradeNotification, requestDict);
12802 	if (result != kOSReturnSuccess) {
12803 		goto finish;
12804 	}
12805 
12806 	if (!_OSKextSetRequestArgument(requestDict.get(),
12807 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
12808 	    !_OSKextSetRequestArgument(requestDict.get(),
12809 	    kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) {
12810 		result = kOSKextReturnNoMemory;
12811 		goto finish;
12812 	}
12813 
12814 	/* Only post the requests after all the other potential failure points
12815 	 * have been passed.
12816 	 */
12817 	if (!sKernelRequests->setObject(requestDict.get())) {
12818 		result = kOSKextReturnNoMemory;
12819 		goto finish;
12820 	}
12821 	OSKext::pingIOKitDaemon();
12822 
12823 	result = kOSReturnSuccess;
12824 finish:
12825 	IORecursiveLockUnlock(sKextLock);
12826 
12827 	if (dextUniqueIDCString != NULL) {
12828 		kfree_data(dextUniqueIDCString, size);
12829 	}
12830 	return result;
12831 }
12832 
12833 /*********************************************************************
12834 * Assumes sKextLock is held.
12835 *********************************************************************/
12836 /* static */
12837 OSReturn
12838 OSKext::dequeueCallbackForRequestTag(
12839 	OSKextRequestTag    requestTag,
12840 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
12841 {
12842 	OSDictionary * callbackRecordOutRaw = NULL;
12843 	OSReturn result;
12844 
12845 	result = dequeueCallbackForRequestTag(requestTag,
12846 	    &callbackRecordOutRaw);
12847 
12848 	if (kOSReturnSuccess == result) {
12849 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
12850 	}
12851 
12852 	return result;
12853 }
12854 OSReturn
12855 OSKext::dequeueCallbackForRequestTag(
12856 	OSKextRequestTag    requestTag,
12857 	OSDictionary     ** callbackRecordOut)
12858 {
12859 	OSReturn   result = kOSReturnError;
12860 	OSSharedPtr<OSNumber> requestTagNum;
12861 
12862 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
12863 	    8 * sizeof(requestTag));
12864 	if (!requestTagNum) {
12865 		goto finish;
12866 	}
12867 
12868 	result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(),
12869 	    callbackRecordOut);
12870 
12871 finish:
12872 	return result;
12873 }
12874 
12875 /*********************************************************************
12876 * Assumes sKextLock is held.
12877 *********************************************************************/
12878 /* static */
12879 OSReturn
12880 OSKext::dequeueCallbackForRequestTag(
12881 	OSNumber     *    requestTagNum,
12882 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
12883 {
12884 	OSDictionary * callbackRecordOutRaw = NULL;
12885 	OSReturn result;
12886 
12887 	result = dequeueCallbackForRequestTag(requestTagNum,
12888 	    &callbackRecordOutRaw);
12889 
12890 	if (kOSReturnSuccess == result) {
12891 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
12892 	}
12893 
12894 	return result;
12895 }
12896 OSReturn
12897 OSKext::dequeueCallbackForRequestTag(
12898 	OSNumber     *    requestTagNum,
12899 	OSDictionary ** callbackRecordOut)
12900 {
12901 	OSReturn        result          = kOSKextReturnInvalidArgument;
12902 	OSDictionary  * callbackRecord  = NULL;        // retain if matched!
12903 	OSNumber      * callbackTagNum  = NULL;        // do not release
12904 	unsigned int    count, i;
12905 
12906 	result = kOSReturnError;
12907 	count = sRequestCallbackRecords->getCount();
12908 	for (i = 0; i < count; i++) {
12909 		callbackRecord = OSDynamicCast(OSDictionary,
12910 		    sRequestCallbackRecords->getObject(i));
12911 		if (!callbackRecord) {
12912 			goto finish;
12913 		}
12914 
12915 		/* If we don't find a tag, we basically have a leak here. Maybe
12916 		 * we should just remove it.
12917 		 */
12918 		callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
12919 			    callbackRecord, kKextRequestArgumentRequestTagKey));
12920 		if (!callbackTagNum) {
12921 			goto finish;
12922 		}
12923 
12924 		/* We could be even more paranoid and check that all the incoming
12925 		 * args match what's in the callback record.
12926 		 */
12927 		if (callbackTagNum->isEqualTo(requestTagNum)) {
12928 			if (callbackRecordOut) {
12929 				*callbackRecordOut = callbackRecord;
12930 				callbackRecord->retain();
12931 			}
12932 			sRequestCallbackRecords->removeObject(i);
12933 			result = kOSReturnSuccess;
12934 			goto finish;
12935 		}
12936 	}
12937 	result = kOSKextReturnNotFound;
12938 
12939 finish:
12940 	return result;
12941 }
12942 
12943 
12944 /*********************************************************************
12945 * Busy timeout triage
12946 *********************************************************************/
12947 /* static */
12948 bool
12949 OSKext::pendingIOKitDaemonRequests(void)
12950 {
12951 	return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
12952 }
12953 
12954 /*********************************************************************
12955 * Acquires and releases sKextLock
12956 *
12957 * This function is designed to be called by kernelmanagerd and driverkitd
12958 * and it gathers all codeless kext and dext personalities, and then attempts
12959 * to map a System (pageable) KC and an Auxiliary (aux) KC.
12960 *
12961 * The pageable and aux KC can be loaded only once at boot time.
12962 * Even if the pageable or aux KC fail to load - this function will
12963 * not allow a new pageable or aux KC to be installed by subsequent calls.
12964 * This is done to avoid security issues where userspace has been compromised
12965 * or the pageable kc has been tampered with and the attacker
12966 * attempts to re-load a malicious variant.
12967 * However dexts can be dynamically loaded, so this function can be used
12968 * to request the installation of a new set of dexts even after boot time.
12969 *
12970 *
12971 *
12972 * Return: if a KC fails to load the return value will contain:
12973 *         kOSKextReturnKCLoadFailure. If the pageable KC fails,
12974 *         the return value will contain kOSKextReturnKCLoadFailureSystemKC.
12975 *         Similarly, if the aux kc load fails, the return value will
12976 *         contain kOSKextReturnKCLoadFailureAuxKC. The two values
12977 *         compose with each other and with kOSKextReturnKCLoadFailure.
12978 *********************************************************************/
12979 /* static */
12980 OSReturn
12981 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused)
12982 {
12983 	static bool daemon_ready = false;
12984 
12985 	OSReturn ret = kOSKextReturnInvalidArgument;
12986 	OSReturn kcerr = 0;
12987 	bool start_matching = false;
12988 
12989 	bool allow_fileset_load = !daemon_ready;
12990 #if !(defined(__x86_64__) || defined(__i386__))
12991 	/* never allow KCs full of kexts on non-x86 machines */
12992 	allow_fileset_load = false;
12993 #endif
12994 
12995 	/*
12996 	 * Change with 70582300
12997 	 */
12998 #if 0 || !defined(VM_MAPPED_KEXTS)
12999 	/*
13000 	 * On platforms that don't support the SystemKC or a file-backed
13001 	 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter
13002 	 * needs to be queried before we load any codeless kexts or release
13003 	 * any 3rd party kexts to run. On platforms that support a file-backed
13004 	 * AuxKC, this process is done via the kext audit mechanism.
13005 	 */
13006 
13007 	printf("KextLog: waiting for kext receipt to be queried.\n");
13008 	while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) {
13009 		IOSleep(30);
13010 	}
13011 #endif /* !VM_MAPPED_KEXTS */
13012 
13013 	/*
13014 	 * Get the args from the request. Right now we need the file
13015 	 * name for the pageable and the aux kext collection file sets.
13016 	 */
13017 	OSDictionary * requestArgs                = NULL;        // do not release
13018 	OSString     * pageable_filepath          = NULL;        // do not release
13019 	OSString     * aux_filepath               = NULL;        // do not release
13020 	OSArray      * codeless_kexts             = NULL;        // do not release
13021 
13022 	kernel_mach_header_t *akc_mh              = NULL;
13023 
13024 	requestArgs = OSDynamicCast(OSDictionary,
13025 	    requestDict->getObject(kKextRequestArgumentsKey));
13026 
13027 	if (requestArgs == NULL) {
13028 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13029 		    "KextLog: No arguments in plist for loading fileset kext\n");
13030 		printf("KextLog: No arguments in plist for loading fileset kext\n");
13031 		return ret;
13032 	}
13033 
13034 	ret = kOSKextReturnDisabled;
13035 
13036 	IORecursiveLockLock(sKextLock);
13037 
13038 	if (!sLoadEnabled) {
13039 		OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13040 		    "KextLog: Kext loading is disabled (attempt to load KCs).");
13041 		IORecursiveLockUnlock(sKextLock);
13042 		return ret;
13043 	}
13044 
13045 	pageable_filepath = OSDynamicCast(OSString,
13046 	    requestArgs->getObject(kKextRequestArgumentPageableKCFilename));
13047 
13048 	if (allow_fileset_load && pageable_filepath != NULL) {
13049 		printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy());
13050 
13051 		ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable);
13052 		if (ret) {
13053 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13054 			    "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
13055 
13056 			printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
13057 			ret = kOSKextReturnKCLoadFailure;
13058 			kcerr |= kOSKextReturnKCLoadFailureSystemKC;
13059 			goto try_auxkc;
13060 		}
13061 		/*
13062 		 * Even if the AuxKC fails to load, we still want to send
13063 		 * the System KC personalities to the catalog for matching
13064 		 */
13065 		start_matching = true;
13066 	} else if (pageable_filepath != NULL) {
13067 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13068 		    "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy());
13069 		ret = kOSKextReturnUnsupported;
13070 	}
13071 
13072 try_auxkc:
13073 	akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
13074 	if (akc_mh) {
13075 		/*
13076 		 * If we try to load a deferred AuxKC, then don't ever attempt
13077 		 * a filesystem map of a file
13078 		 */
13079 		allow_fileset_load = false;
13080 
13081 		/*
13082 		 * This function is only called once per boot, so we haven't
13083 		 * yet loaded an AuxKC. If we have registered the AuxKC mach
13084 		 * header, that means that the kext collection has been placed
13085 		 * in memory for us by the booter, and is waiting for us to
13086 		 * process it.  Grab the deferred XML plist of info
13087 		 * dictionaries and add all the kexts.
13088 		 */
13089 		OSSharedPtr<OSObject>  parsedXML;
13090 		OSSharedPtr<OSData>    loaded_kcUUID;
13091 		OSDictionary          *infoDict;
13092 		parsedXML = consumeDeferredKextCollection(KCKindAuxiliary);
13093 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
13094 #if !defined(VM_MAPPED_KEXTS)
13095 		/*
13096 		 * On platforms where we don't dynamically wire-down / page-in
13097 		 * kext memory, we need to maintain the invariant that if the
13098 		 * AuxKC in memory does not contain a kext receipt, then we
13099 		 * should not load any of the kexts.
13100 		 */
13101 		size_t receipt_sz = 0;
13102 		if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) {
13103 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13104 			    "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt");
13105 			ret = kOSKextReturnKCLoadFailure;
13106 			goto try_codeless;
13107 		}
13108 #endif
13109 		if (infoDict) {
13110 			bool added;
13111 			printf("KextLog: Adding kexts from in-memory AuxKC\n");
13112 			added = OSKext::addKextsFromKextCollection(akc_mh, infoDict,
13113 			    kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary);
13114 			if (!loaded_kcUUID) {
13115 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13116 				    "KextLog: WARNING: did not find UUID in deferred Aux KC!");
13117 			} else if (!added) {
13118 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13119 				    "KextLog: WARNING: Failed to load AuxKC from memory.");
13120 			}
13121 			/* only return success if the pageable load (above) was successful */
13122 			if (ret != kOSKextReturnKCLoadFailure) {
13123 				ret = kOSReturnSuccess;
13124 			}
13125 			/* the registration of the AuxKC parsed out the KC's UUID already */
13126 		} else {
13127 			if (daemon_ready) {
13128 				/*
13129 				 * Complain, but don't return an error if this isn't the first time the
13130 				 * IOKit daemon is checking in. If the daemon ever restarts, we will
13131 				 * hit this case because we've already consumed the deferred personalities.
13132 				 * We return success here so that a call to this function from a restarted
13133 				 * daemon with no codeless kexts will succeed.
13134 				 */
13135 				OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13136 				    "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart");
13137 				if (ret != kOSKextReturnKCLoadFailure) {
13138 					ret = kOSReturnSuccess;
13139 				}
13140 			} else {
13141 				/* this is a real error case */
13142 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13143 				    "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary");
13144 				printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n");
13145 				ret = kOSKextReturnKCLoadFailure;
13146 				kcerr |= kOSKextReturnKCLoadFailureAuxKC;
13147 			}
13148 		}
13149 	}
13150 
13151 	aux_filepath = OSDynamicCast(OSString,
13152 	    requestArgs->getObject(kKextRequestArgumentAuxKCFilename));
13153 	if (allow_fileset_load && aux_filepath != NULL) {
13154 		printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy());
13155 
13156 		ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary);
13157 		if (ret) {
13158 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13159 			    "KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
13160 
13161 			printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
13162 			ret = kOSKextReturnKCLoadFailure;
13163 			kcerr |= kOSKextReturnKCLoadFailureAuxKC;
13164 			goto try_codeless;
13165 		}
13166 		start_matching = true;
13167 	} else if (aux_filepath != NULL) {
13168 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13169 		    "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy());
13170 		if (ret != kOSKextReturnKCLoadFailure) {
13171 			ret = kOSKextReturnUnsupported;
13172 		}
13173 	}
13174 
13175 try_codeless:
13176 	/*
13177 	 * Load codeless kexts last so that there is no possibilty of a
13178 	 * codeless kext bundle ID preventing a kext in the system KC from
13179 	 * loading
13180 	 */
13181 	codeless_kexts = OSDynamicCast(OSArray,
13182 	    requestArgs->getObject(kKextRequestArgumentCodelessPersonalities));
13183 	if (codeless_kexts != NULL) {
13184 		uint32_t count = codeless_kexts->getCount();
13185 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13186 		    "KextLog: loading %d codeless kexts/dexts", count);
13187 		for (uint32_t i = 0; i < count; i++) {
13188 			OSDictionary *infoDict;
13189 			infoDict = OSDynamicCast(OSDictionary,
13190 			    codeless_kexts->getObject(i));
13191 			if (!infoDict) {
13192 				continue;
13193 			}
13194 			// instantiate a new kext, and don't hold a reference
13195 			// (the kext subsystem will hold one implicitly)
13196 			OSKext::withCodelessInfo(infoDict, NULL);
13197 		}
13198 		/* ignore errors that are not KC load failures */
13199 		if (ret != kOSKextReturnKCLoadFailure) {
13200 			ret = kOSReturnSuccess;
13201 		}
13202 		start_matching = true;
13203 	}
13204 
13205 	/* send personalities to the IOCatalog once */
13206 	if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) {
13207 		OSKext::sendAllKextPersonalitiesToCatalog(true);
13208 		/*
13209 		 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark
13210 		 * things as active and start all the delayed matching: the
13211 		 * dext and codeless kext personalities should have all been
13212 		 * delivered via this one call.
13213 		 */
13214 		if (!daemon_ready) {
13215 			OSKext::setIOKitDaemonActive();
13216 			OSKext::setDeferredLoadSucceeded(TRUE);
13217 			IOService::iokitDaemonLaunched();
13218 		}
13219 		if (sOSKextWasResetAfterUserspaceReboot) {
13220 			sOSKextWasResetAfterUserspaceReboot = false;
13221 			OSKext::setIOKitDaemonActive();
13222 			IOService::startDeferredMatches();
13223 		}
13224 	}
13225 
13226 	if (ret == kOSKextReturnKCLoadFailure) {
13227 		ret |= kcerr;
13228 	}
13229 
13230 	/*
13231 	 * Only allow this function to attempt to load the pageable and
13232 	 * aux KCs once per boot.
13233 	 */
13234 	daemon_ready = true;
13235 
13236 	IORecursiveLockUnlock(sKextLock);
13237 
13238 	return ret;
13239 }
13240 
13241 OSReturn
13242 OSKext::resetMutableSegments(void)
13243 {
13244 	kernel_segment_command_t *seg = NULL;
13245 	kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
13246 	u_int index = 0;
13247 	OSKextSavedMutableSegment *savedSegment = NULL;
13248 	uintptr_t kext_slide = PE_get_kc_slide(kc_type);
13249 	OSReturn err;
13250 
13251 	if (!savedMutableSegments) {
13252 		OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
13253 		    "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString());
13254 		err = kOSKextReturnInternalError;
13255 		goto finish;
13256 	}
13257 
13258 	for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) {
13259 		if (!segmentIsMutable(seg)) {
13260 			continue;
13261 		}
13262 		uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
13263 		uint64_t vmsize = seg->vmsize;
13264 		err = kOSKextReturnInternalError;
13265 		for (index = 0; index < savedMutableSegments->getCount(); index++) {
13266 			savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index));
13267 			assert(savedSegment);
13268 			if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) {
13269 				OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
13270 				    "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13271 				err = savedSegment->restoreContents(seg);
13272 				if (err != kOSReturnSuccess) {
13273 					panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13274 				}
13275 			}
13276 		}
13277 		if (err != kOSReturnSuccess) {
13278 			panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13279 		}
13280 	}
13281 	err = kOSReturnSuccess;
13282 finish:
13283 	return err;
13284 }
13285 
13286 
13287 /*********************************************************************
13288 * Assumes sKextLock is held.
13289 *********************************************************************/
13290 /* static */
13291 OSReturn
13292 OSKext::loadKCFileSet(
13293 	const char *filepath,
13294 	kc_kind_t   type)
13295 {
13296 #if VM_MAPPED_KEXTS
13297 	/* we only need to load filesets on systems that support VM_MAPPED kexts */
13298 	OSReturn err;
13299 	struct vnode *vp = NULL;
13300 	void *fileset_control;
13301 	off_t fsize;
13302 	bool pageable = (type == KCKindPageable);
13303 
13304 	if ((pageable && pageableKCloaded) ||
13305 	    (!pageable && auxKCloaded)) {
13306 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13307 		    "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux"));
13308 
13309 		return kOSKextReturnInvalidArgument;
13310 	}
13311 
13312 	/* Do not allow AuxKC to load if Pageable KC is not loaded */
13313 	if (!pageable && !pageableKCloaded) {
13314 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13315 		    "Trying to load the Aux KC without loading the Pageable KC");
13316 		return kOSKextReturnInvalidArgument;
13317 	}
13318 
13319 	fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize);
13320 
13321 	if (fileset_control == NULL) {
13322 		printf("Could not get memory control object for file %s", filepath);
13323 
13324 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13325 		    "Could not get memory control object for file %s", filepath);
13326 		return kOSKextReturnInvalidArgument;
13327 	}
13328 	if (vp == NULL) {
13329 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13330 		    "Could not find vnode for file %s", filepath);
13331 		return kOSKextReturnInvalidArgument;
13332 	}
13333 
13334 	kernel_mach_header_t *mh = NULL;
13335 	uintptr_t slide = 0;
13336 
13337 #if CONFIG_CSR
13338 	/*
13339 	 * When SIP is enabled, the KC we map must be SIP-protected
13340 	 */
13341 	if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) {
13342 		struct vnode_attr va;
13343 		int error;
13344 		VATTR_INIT(&va);
13345 		VATTR_WANTED(&va, va_flags);
13346 		error = vnode_getattr(vp, &va, vfs_context_current());
13347 		if (error) {
13348 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13349 			    "vnode_getattr(%s) failed (error=%d)", filepath, error);
13350 			err = kOSKextReturnInternalError;
13351 			goto finish;
13352 		}
13353 		if (!(va.va_flags & SF_RESTRICTED)) {
13354 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13355 			    "Path to KC '%s' is not SIP-protected", filepath);
13356 			err = kOSKextReturnInvalidArgument;
13357 			goto finish;
13358 		}
13359 	}
13360 #endif
13361 
13362 	err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL);
13363 	if (err) {
13364 		printf("KextLog: mapKCFileSet returned %d\n", err);
13365 
13366 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13367 		    "mapKCFileSet returned %d\n", err);
13368 
13369 		err = kOSKextReturnInvalidArgument;
13370 	}
13371 
13372 #if CONFIG_CSR
13373 finish:
13374 #endif
13375 	/* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */
13376 	assert(vp != NULL);
13377 	if (err == kOSReturnSuccess) {
13378 		PE_set_kc_vp(type, vp);
13379 		if (pageable) {
13380 			pageableKCloaded = true;
13381 		} else {
13382 			auxKCloaded = true;
13383 		}
13384 	} else {
13385 		vnode_put(vp);
13386 	}
13387 
13388 	return err;
13389 #else
13390 	(void)filepath;
13391 	(void)type;
13392 	return kOSKextReturnUnsupported;
13393 #endif // VM_MAPPED_KEXTS
13394 }
13395 
13396 #if defined(__x86_64__) || defined(__i386__)
13397 /*********************************************************************
13398 * Assumes sKextLock is held.
13399 *********************************************************************/
13400 /* static */
13401 OSReturn
13402 OSKext::mapKCFileSet(
13403 	void                 *control,
13404 	vm_size_t            fsize,
13405 	kernel_mach_header_t **mhp,
13406 	off_t                file_offset,
13407 	uintptr_t            *slidep,
13408 	bool                 pageable,
13409 	void                 *map_entry_list)
13410 {
13411 	bool fileset_load = false;
13412 	kern_return_t ret;
13413 	OSReturn err;
13414 	kernel_section_t *infoPlistSection = NULL;
13415 	OSDictionary *infoDict = NULL;
13416 
13417 	OSSharedPtr<OSObject> parsedXML;
13418 	OSSharedPtr<OSString> errorString;
13419 	OSSharedPtr<OSData> loaded_kcUUID;
13420 
13421 	/* Check if initial load for file set */
13422 	if (*mhp == NULL) {
13423 		fileset_load = true;
13424 
13425 		/* Get a page aligned address from kext map to map the file */
13426 		vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize);
13427 		if (pagealigned_addr == 0) {
13428 			return kOSKextReturnNoMemory;
13429 		}
13430 
13431 		*mhp = (kernel_mach_header_t *)pagealigned_addr;
13432 
13433 		/* Allocate memory for bailout mechanism */
13434 		map_entry_list = allocate_kcfileset_map_entry_list();
13435 		if (map_entry_list == NULL) {
13436 			return kOSKextReturnNoMemory;
13437 		}
13438 	}
13439 
13440 	uintptr_t *slideptr = fileset_load ? slidep : NULL;
13441 	err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list);
13442 	/* mhp and slideptr are updated by mapKCTextSegment */
13443 	if (err) {
13444 		if (fileset_load) {
13445 			deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13446 		}
13447 		return err;
13448 	}
13449 
13450 	/* Initialize the kc header globals */
13451 	if (fileset_load) {
13452 		if (pageable) {
13453 			PE_set_kc_header(KCKindPageable, *mhp, *slidep);
13454 		} else {
13455 			PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep);
13456 		}
13457 	}
13458 
13459 	/* Iterate through all the segments and map necessary segments */
13460 	struct load_command *lcp = (struct load_command *) (*mhp + 1);
13461 	for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) {
13462 		vm_map_offset_t start;
13463 		kernel_mach_header_t *k_mh = NULL;
13464 		kernel_segment_command_t * seg = NULL;
13465 		struct fileset_entry_command *fse = NULL;
13466 
13467 		if (lcp->cmd == LC_SEGMENT_KERNEL) {
13468 			seg = (kernel_segment_command_t *)lcp;
13469 			start = ((uintptr_t)(seg->vmaddr)) + *slidep;
13470 		} else if (lcp->cmd == LC_FILESET_ENTRY) {
13471 			fse = (struct fileset_entry_command *)lcp;
13472 			k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep);
13473 
13474 			/* Map the segments of the mach-o binary */
13475 			err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list);
13476 			if (err) {
13477 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13478 				return kOSKextReturnInvalidArgument;
13479 			}
13480 			continue;
13481 		} else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) {
13482 			/* Check if the Aux KC is built pageable style */
13483 			if (!pageable && !fileset_load && !auxKCloaded) {
13484 				resetAuxKCSegmentOnUnload = true;
13485 			}
13486 			continue;
13487 		} else {
13488 			continue;
13489 		}
13490 
13491 		if (fileset_load) {
13492 			if (seg->vmsize == 0) {
13493 				continue;
13494 			}
13495 
13496 			/* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */
13497 			if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 &&
13498 			    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 &&
13499 			    strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 &&
13500 			    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) {
13501 				continue;
13502 			}
13503 		} else {
13504 			if (seg->vmsize == 0) {
13505 				continue;
13506 			}
13507 
13508 			/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
13509 			if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
13510 			    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
13511 			    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
13512 				continue;
13513 			}
13514 		}
13515 
13516 		ret = vm_map_kcfileset_segment(
13517 			&start, seg->vmsize,
13518 			(memory_object_control_t)control, seg->fileoff, seg->maxprot);
13519 
13520 		if (ret != KERN_SUCCESS) {
13521 			if (fileset_load) {
13522 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13523 			}
13524 			return kOSKextReturnInvalidArgument;
13525 		}
13526 		add_kcfileset_map_entry(map_entry_list, start, seg->vmsize);
13527 	}
13528 
13529 	/* Return if regular mach-o */
13530 	if (!fileset_load) {
13531 		return 0;
13532 	}
13533 
13534 	/*
13535 	 * Fixup for the Pageable KC and the Aux KC is done by
13536 	 * i386_slide_kext_collection_mh_addrs, but it differs in
13537 	 * following ways:
13538 	 *
13539 	 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands.
13540 	 * The fixup of kext segments and kext load commands are done at kext
13541 	 * load time by calling i386_slide_individual_kext.
13542 	 *
13543 	 * AuxKC old style: Fixup all the segments and all the load commands.
13544 	 *
13545 	 * AuxKC pageable style: Same as the Pageable KC.
13546 	 */
13547 	bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false));
13548 	ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header);
13549 	if (ret != KERN_SUCCESS) {
13550 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13551 		return kOSKextReturnInvalidArgument;
13552 	}
13553 
13554 	/* Get the prelink info dictionary */
13555 	infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection);
13556 	parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
13557 	if (parsedXML) {
13558 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
13559 	}
13560 
13561 	if (!infoDict) {
13562 		const char *errorCString = "(unknown error)";
13563 
13564 		if (errorString && errorString->getCStringNoCopy()) {
13565 			errorCString = errorString->getCStringNoCopy();
13566 		} else if (parsedXML) {
13567 			errorCString = "not a dictionary";
13568 		}
13569 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13570 		    "Error unserializing kext info plist section: %s.", errorCString);
13571 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13572 		return kOSKextReturnInvalidArgument;
13573 	}
13574 
13575 	/* Validate that the Kext Collection is prelinked to the loaded KC */
13576 	err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary);
13577 	if (err) {
13578 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13579 		return kOSKextReturnInvalidArgument;
13580 	}
13581 
13582 	/* Set Protection of Segments */
13583 	OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary);
13584 
13585 	OSKext::addKextsFromKextCollection(*mhp,
13586 	    infoDict, kPrelinkTextSegment,
13587 	    loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary);
13588 
13589 	/* Copy in the KC UUID */
13590 	if (!loaded_kcUUID) {
13591 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13592 		    "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux");
13593 	} else if (pageable) {
13594 		pageablekc_uuid_valid = TRUE;
13595 		memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
13596 		uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string);
13597 	} else {
13598 		auxkc_uuid_valid = TRUE;
13599 		memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
13600 		uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
13601 	}
13602 
13603 	deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable);
13604 
13605 	return 0;
13606 }
13607 
13608 /*********************************************************************
13609 * Assumes sKextLock is held.
13610 *********************************************************************/
13611 /* static */
13612 OSReturn
13613 OSKext::mapKCTextSegment(
13614 	void                 *control,
13615 	kernel_mach_header_t **mhp,
13616 	off_t                file_offset,
13617 	uintptr_t            *slidep,
13618 	void                 *map_entry_list)
13619 {
13620 	kern_return_t ret;
13621 	vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t),
13622 	    PAGE_MASK);
13623 	vm_map_offset_t load_command_map_size = 0;
13624 	kernel_mach_header_t *base_mh = *mhp;
13625 
13626 	/* Map the mach header at start of fileset for now (vmaddr = 0) */
13627 	ret = vm_map_kcfileset_segment(
13628 		(vm_map_offset_t *)&base_mh, mach_header_map_size,
13629 		(memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE));
13630 
13631 	if (ret != KERN_SUCCESS) {
13632 		printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret);
13633 
13634 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13635 		    "Failed to map mach header of kc fileset with error %d", ret);
13636 		return kOSKextReturnInvalidArgument;
13637 	}
13638 
13639 	if (slidep) {
13640 		/* Verify that it's an MH_FILESET */
13641 		if (base_mh->filetype != MH_FILESET) {
13642 			printf("Kext Log: mapKCTextSegment mach header filetype"
13643 			    " is not an MH_FILESET, it is %x", base_mh->filetype);
13644 
13645 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13646 			    "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype);
13647 
13648 			/* Unmap the mach header */
13649 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13650 			return kOSKextReturnInvalidArgument;
13651 		}
13652 	}
13653 
13654 	/* Map the remaining pages of load commands */
13655 	if (base_mh->sizeofcmds > mach_header_map_size) {
13656 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
13657 		load_command_map_size = base_mh->sizeofcmds - mach_header_map_size;
13658 
13659 		/* Map the load commands */
13660 		ret = vm_map_kcfileset_segment(
13661 			&load_command_addr, load_command_map_size,
13662 			(memory_object_control_t)control, file_offset + mach_header_map_size,
13663 			(VM_PROT_READ | VM_PROT_WRITE));
13664 
13665 		if (ret != KERN_SUCCESS) {
13666 			printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret);
13667 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13668 			    "Failed to map load commands of kc fileset with error %d", ret);
13669 
13670 			/* Unmap the mach header */
13671 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13672 			return kOSKextReturnInvalidArgument;
13673 		}
13674 	}
13675 
13676 	kernel_segment_command_t *text_seg;
13677 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT);
13678 
13679 	/* Calculate the slide and vm addr of mach header */
13680 	if (slidep) {
13681 		*mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr);
13682 		*slidep = ((uintptr_t)*mhp) - text_seg->vmaddr;
13683 	}
13684 
13685 	/* Cache the text segment size and file offset before unmapping */
13686 	vm_map_offset_t text_segment_size = text_seg->vmsize;
13687 	vm_object_offset_t text_segment_fileoff = text_seg->fileoff;
13688 	vm_prot_t text_maxprot = text_seg->maxprot;
13689 
13690 	/* Unmap the first page and loadcommands and map the text segment */
13691 	ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13692 	assert(ret == KERN_SUCCESS);
13693 
13694 	if (load_command_map_size) {
13695 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
13696 		ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size);
13697 		assert(ret == KERN_SUCCESS);
13698 	}
13699 
13700 	/* Map the text segment at actual vm addr specified in fileset */
13701 	ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size,
13702 	    (memory_object_control_t)control, text_segment_fileoff, text_maxprot);
13703 	if (ret != KERN_SUCCESS) {
13704 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13705 		    "Failed to map Text segment of kc fileset with error %d", ret);
13706 		return kOSKextReturnInvalidArgument;
13707 	}
13708 
13709 	add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size);
13710 	return 0;
13711 }
13712 
13713 /*********************************************************************
13714 * Assumes sKextLock is held.
13715 *********************************************************************/
13716 /* static */
13717 OSReturn
13718 OSKext::protectKCFileSet(
13719 	kernel_mach_header_t *mh,
13720 	kc_kind_t            type)
13721 {
13722 	vm_map_t                    kext_map        = g_kext_map;
13723 	kernel_segment_command_t  * seg             = NULL;
13724 	vm_map_offset_t             start           = 0;
13725 	vm_map_offset_t             end             = 0;
13726 	OSReturn                    ret             = 0;
13727 
13728 	/* Set VM permissions */
13729 	seg = firstsegfromheader((kernel_mach_header_t *)mh);
13730 	while (seg) {
13731 		start = round_page(seg->vmaddr);
13732 		end = trunc_page(seg->vmaddr + seg->vmsize);
13733 
13734 		/*
13735 		 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS
13736 		 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT
13737 		 * for the Aux KC as well.
13738 		 */
13739 		if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 ||
13740 		    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 ||
13741 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 ||
13742 		    (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload &&
13743 		    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) {
13744 			ret = OSKext_protect((kernel_mach_header_t *)mh,
13745 			    kext_map, start, end, seg->maxprot, TRUE, type);
13746 			if (ret != KERN_SUCCESS) {
13747 				printf("OSKext protect failed with error %d", ret);
13748 				return kOSKextReturnInvalidArgument;
13749 			}
13750 
13751 			ret = OSKext_protect((kernel_mach_header_t *)mh,
13752 			    kext_map, start, end, seg->initprot, FALSE, type);
13753 			if (ret != KERN_SUCCESS) {
13754 				printf("OSKext protect failed with error %d", ret);
13755 				return kOSKextReturnInvalidArgument;
13756 			}
13757 
13758 			ret = OSKext_wire((kernel_mach_header_t *)mh,
13759 			    kext_map, start, end, seg->initprot, FALSE, type);
13760 			if (ret != KERN_SUCCESS) {
13761 				printf("OSKext wire failed with error %d", ret);
13762 				return kOSKextReturnInvalidArgument;
13763 			}
13764 		}
13765 
13766 		seg = nextsegfromheader((kernel_mach_header_t *) mh, seg);
13767 	}
13768 
13769 	return 0;
13770 }
13771 
13772 /*********************************************************************
13773 * Assumes sKextLock is held.
13774 *********************************************************************/
13775 /* static */
13776 void
13777 OSKext::freeKCFileSetcontrol(void)
13778 {
13779 	PE_reset_all_kc_vp();
13780 }
13781 
13782 /*********************************************************************
13783 * Assumes sKextLock is held.
13784 *
13785 * resetKCFileSetSegments: Kext start function expects data segment to
13786 * be pristine on every load, unmap the dirty segments on unload and
13787 * remap them from FileSet on disk. Remap all segments of kext since
13788 * fixups are done per kext and not per segment.
13789 *********************************************************************/
13790 OSReturn
13791 OSKext::resetKCFileSetSegments(void)
13792 {
13793 	kernel_segment_command_t *seg = NULL;
13794 	kernel_segment_command_t *text_seg;
13795 	uint32_t text_fileoff;
13796 	kernel_mach_header_t *k_mh = NULL;
13797 	uintptr_t slide;
13798 	struct vnode *vp = NULL;
13799 	void *fileset_control = NULL;
13800 	bool pageable = (kc_type == KCKindPageable);
13801 	OSReturn err;
13802 	kern_return_t kr;
13803 
13804 	/* Check the vnode reference is still available */
13805 	vp = (struct vnode *)PE_get_kc_vp(kc_type);
13806 	if (vp == NULL) {
13807 		OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
13808 		    "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString());
13809 		return kOSKextReturnInternalError;
13810 	}
13811 
13812 	fileset_control = ubc_getobject(vp, 0);
13813 	assert(fileset_control != NULL);
13814 
13815 	OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
13816 	    "Kext %s resetting all segments", getIdentifierCString());
13817 
13818 	k_mh = (kernel_mach_header_t *)kmod_info->address;
13819 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT);
13820 	text_fileoff = text_seg->fileoff;
13821 	slide = PE_get_kc_slide(kc_type);
13822 
13823 	seg = firstsegfromheader((kernel_mach_header_t *)k_mh);
13824 	while (seg) {
13825 		if (seg->vmsize == 0) {
13826 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
13827 			continue;
13828 		}
13829 
13830 		/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
13831 		if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
13832 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
13833 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
13834 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
13835 			continue;
13836 		}
13837 
13838 		kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize);
13839 		assert(kr == KERN_SUCCESS);
13840 		seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
13841 	}
13842 
13843 	/* Unmap the text segment */
13844 	kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize);
13845 	assert(kr == KERN_SUCCESS);
13846 
13847 	/* Map all the segments of the kext */
13848 	err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL);
13849 	if (err) {
13850 		panic("Could not reset segments of a mapped kext, error %x", err);
13851 	}
13852 
13853 	/* Update address in kmod_info, since it has been reset */
13854 	if (kmod_info->address) {
13855 		kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide);
13856 	}
13857 
13858 	return 0;
13859 }
13860 
13861 /*********************************************************************
13862 * Mechanism to track all segment mapping while mapping KC fileset.
13863 *********************************************************************/
13864 
13865 struct kcfileset_map_entry {
13866 	vm_map_offset_t me_start;
13867 	vm_map_offset_t me_size;
13868 };
13869 
13870 struct kcfileset_map_entry_list {
13871 	int                        kme_list_count;
13872 	int                        kme_list_index;
13873 	struct kcfileset_map_entry kme_list[];
13874 };
13875 
13876 #define KCFILESET_MAP_ENTRY_MAX (16380)
13877 
13878 static void *
13879 allocate_kcfileset_map_entry_list(void)
13880 {
13881 	struct kcfileset_map_entry_list *entry_list;
13882 
13883 	entry_list = kalloc_type(struct kcfileset_map_entry_list,
13884 	    struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO);
13885 
13886 	entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX;
13887 	entry_list->kme_list_index = 0;
13888 	return entry_list;
13889 }
13890 
13891 static void
13892 add_kcfileset_map_entry(
13893 	void            *map_entry_list,
13894 	vm_map_offset_t start,
13895 	vm_map_offset_t size)
13896 {
13897 	if (map_entry_list == NULL) {
13898 		return;
13899 	}
13900 
13901 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
13902 
13903 	if (entry_list->kme_list_index >= entry_list->kme_list_count) {
13904 		panic("Ran out of map kc fileset list");
13905 	}
13906 
13907 	entry_list->kme_list[entry_list->kme_list_index].me_start = start;
13908 	entry_list->kme_list[entry_list->kme_list_index].me_size = size;
13909 
13910 	entry_list->kme_list_index++;
13911 }
13912 
13913 static void
13914 deallocate_kcfileset_map_entry_list_and_unmap_entries(
13915 	void      *map_entry_list,
13916 	boolean_t unmap_entries,
13917 	bool      pageable)
13918 {
13919 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
13920 
13921 	if (unmap_entries) {
13922 		for (int i = 0; i < entry_list->kme_list_index; i++) {
13923 			kern_return_t ret;
13924 			ret = vm_unmap_kcfileset_segment(
13925 				&(entry_list->kme_list[i].me_start),
13926 				entry_list->kme_list[i].me_size);
13927 			assert(ret == KERN_SUCCESS);
13928 		}
13929 
13930 		PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary);
13931 	}
13932 
13933 	kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry,
13934 	    KCFILESET_MAP_ENTRY_MAX, entry_list);
13935 }
13936 
13937 /*********************************************************************
13938 * Mechanism to map kext segment.
13939 *********************************************************************/
13940 
13941 kern_return_t
13942 vm_map_kcfileset_segment(
13943 	vm_map_offset_t    *start,
13944 	vm_map_offset_t    size,
13945 	void               *control,
13946 	vm_object_offset_t fileoffset,
13947 	vm_prot_t          max_prot)
13948 {
13949 	vm_map_kernel_flags_t vmk_flags = {
13950 		.vmf_fixed = true,
13951 		.vmkf_no_copy_on_read = true,
13952 		.vmkf_cs_enforcement_override = true,
13953 		.vm_tag = VM_KERN_MEMORY_OSKEXT,
13954 	};
13955 	kern_return_t ret;
13956 
13957 	/* Add Write to max prot to allow fixups */
13958 	max_prot = max_prot | VM_PROT_WRITE;
13959 
13960 	/*
13961 	 * Map the segments from file as COPY mappings to
13962 	 * make sure changes on disk to the file does not affect
13963 	 * mapped segments.
13964 	 */
13965 	ret = vm_map_enter_mem_object_control(
13966 		g_kext_map,
13967 		start,
13968 		size,
13969 		(mach_vm_offset_t)0,
13970 		vmk_flags,
13971 		(memory_object_control_t)control,
13972 		fileoffset,
13973 		TRUE,         /* copy */
13974 		(VM_PROT_READ | VM_PROT_WRITE), max_prot,
13975 		VM_INHERIT_NONE);
13976 
13977 	return ret;
13978 }
13979 
13980 kern_return_t
13981 vm_unmap_kcfileset_segment(
13982 	vm_map_offset_t    *start,
13983 	vm_map_offset_t    size)
13984 {
13985 	return mach_vm_deallocate(g_kext_map, *start, size);
13986 }
13987 
13988 #endif //(__x86_64__) || defined(__i386__)
13989 
13990 /*********************************************************************
13991 * Assumes sKextLock is held.
13992 *********************************************************************/
13993 /* static */
13994 OSReturn
13995 OSKext::validateKCFileSetUUID(
13996 	OSDictionary         *infoDict,
13997 	kc_kind_t            type)
13998 {
13999 	OSReturn ret           = kOSReturnSuccess;
14000 
14001 	if (!kernelcache_uuid_valid) {
14002 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14003 		    "validateKCFileSetUUID Boot KC UUID was not set at boot.");
14004 		ret = kOSKextReturnInvalidArgument;
14005 		goto finish;
14006 	}
14007 	ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey);
14008 	if (ret != 0) {
14009 		goto finish;
14010 	}
14011 
14012 #if defined(__x86_64__) || defined(__i386__)
14013 	/* Check if the Aux KC is prelinked to correct Pageable KC */
14014 	if (type == KCKindAuxiliary) {
14015 		if (!pageablekc_uuid_valid) {
14016 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14017 			    "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC.");
14018 			ret = kOSKextReturnInvalidArgument;
14019 			goto finish;
14020 		}
14021 		ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey);
14022 		if (ret != 0) {
14023 			goto finish;
14024 		}
14025 	}
14026 #endif //(__x86_64__) || defined(__i386__)
14027 
14028 	printf("KextLog: Collection UUID matches with loaded KCs.\n");
14029 finish:
14030 	return ret;
14031 }
14032 
14033 /*********************************************************************
14034 * Assumes sKextLock is held.
14035 *********************************************************************/
14036 /* static */
14037 OSReturn
14038 OSKext::validateKCUUIDfromPrelinkInfo(
14039 	uuid_t               *loaded_kcuuid,
14040 	kc_kind_t             type,
14041 	OSDictionary         *infoDict,
14042 	const char           *uuid_key)
14043 {
14044 	/* extract the UUID from the dictionary */
14045 	OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key));
14046 	if (!prelinkinfoKCUUID) {
14047 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14048 		    "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key);
14049 		return kOSKextReturnInvalidArgument;
14050 	}
14051 
14052 	if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) {
14053 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14054 		    "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength());
14055 		return kOSKextReturnInvalidArgument;
14056 	}
14057 
14058 	if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(),
14059 	    prelinkinfoKCUUID->getLength())) {
14060 		OSData       *info_dict_uuid;
14061 		uuid_string_t info_dict_uuid_str = {};
14062 		uuid_string_t expected_uuid_str = {};
14063 		uuid_string_t given_uuid_str = {};
14064 		uuid_t        given_uuid;
14065 
14066 		/* extract the KC UUID from the dictionary */
14067 		info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
14068 		if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) {
14069 			uuid_t tmp_uuid;
14070 			memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid));
14071 			uuid_unparse(tmp_uuid, info_dict_uuid_str);
14072 		}
14073 
14074 		uuid_unparse(*loaded_kcuuid, expected_uuid_str);
14075 		memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid));
14076 		uuid_unparse(given_uuid, given_uuid_str);
14077 
14078 		printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
14079 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
14080 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14081 		    "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
14082 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
14083 		if (type == KCKindPageable && sPanicOnKCMismatch) {
14084 			panic("System KC UUID %s linked against %s, but %s is loaded",
14085 			    info_dict_uuid_str, given_uuid_str, expected_uuid_str);
14086 		}
14087 		return kOSKextReturnInvalidArgument;
14088 	}
14089 
14090 	return 0;
14091 }
14092 
14093 /*********************************************************************
14094 * Assumes sKextLock is held.
14095 *********************************************************************/
14096 /* static */
14097 OSReturn
14098 OSKext::dispatchResource(OSDictionary * requestDict)
14099 {
14100 	OSReturn                        result          = kOSReturnError;
14101 	OSSharedPtr<OSDictionary>       callbackRecord;
14102 	OSNumber                      * requestTag      = NULL;        // do not release
14103 	OSNumber                      * requestResult   = NULL;        // do not release
14104 	OSData                        * dataObj         = NULL;        // do not release
14105 	uint32_t                        dataLength      = 0;
14106 	const void                    * dataPtr         = NULL;        // do not free
14107 	OSValueObject<OSKextRequestResourceCallback> * callbackWrapper = nullptr; // do not release
14108 	OSKextRequestResourceCallback   callback        = NULL;
14109 	OSValueObject<void *>         * contextWrapper  = nullptr;     // do not release
14110 	void                          * context         = NULL;        // do not free
14111 	OSSharedPtr<OSKext>             callbackKext;
14112 
14113 	/* Get the args from the request. Right now we need the tag
14114 	 * to look up the callback record, and the result for invoking the callback.
14115 	 */
14116 	requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
14117 	    kKextRequestArgumentRequestTagKey));
14118 	requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
14119 	    kKextRequestArgumentResultKey));
14120 	if (!requestTag || !requestResult) {
14121 		result = kOSKextReturnInvalidArgument;
14122 		goto finish;
14123 	}
14124 
14125 	/* Look for a callback record matching this request's tag.
14126 	 */
14127 	result = dequeueCallbackForRequestTag(requestTag, callbackRecord);
14128 	if (result != kOSReturnSuccess) {
14129 		goto finish;
14130 	}
14131 
14132 	/*****
14133 	 * Get the context pointer of the callback record (if there is one).
14134 	 */
14135 	contextWrapper = OSDynamicCast(OSValueObject<void *>, _OSKextGetRequestArgument(
14136 		    callbackRecord.get(), kKextRequestArgumentContextKey));
14137 	context = _OSKextExtractPointer(contextWrapper);
14138 	if (contextWrapper && !context) {
14139 		goto finish;
14140 	}
14141 
14142 	callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14143 	    _OSKextGetRequestArgument(callbackRecord.get(),
14144 	    kKextRequestArgumentCallbackKey));
14145 	callback = _OSKextExtractCallbackPointer(callbackWrapper);
14146 	if (!callback) {
14147 		goto finish;
14148 	}
14149 
14150 	/* Check for a data obj. We might not have one and that's ok, that means
14151 	 * we didn't find the requested resource, and we still have to tell the
14152 	 * caller that via the callback.
14153 	 */
14154 	dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
14155 	    kKextRequestArgumentValueKey));
14156 	if (dataObj) {
14157 		dataPtr = dataObj->getBytesNoCopy();
14158 		dataLength = dataObj->getLength();
14159 	}
14160 
14161 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
14162 	if (!callbackKext) {
14163 		OSKextLog(/* kext */ NULL,
14164 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
14165 		    "Can't invoke callback for resource request; ");
14166 		goto finish;
14167 	}
14168 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
14169 		OSKextLog(/* kext */ NULL,
14170 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
14171 		    "Can't invoke kext resource callback; ");
14172 		goto finish;
14173 	}
14174 
14175 	(void)callback(requestTag->unsigned32BitValue(),
14176 	    (OSReturn)requestResult->unsigned32BitValue(),
14177 	    dataPtr, dataLength, context);
14178 
14179 	result = kOSReturnSuccess;
14180 
14181 finish:
14182 	return result;
14183 }
14184 
14185 /*********************************************************************
14186 * Assumes sKextLock is held.
14187 *********************************************************************/
14188 /* static */
14189 OSReturn
14190 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict)
14191 {
14192 	OSSharedPtr<OSDictionary> missingIDs;
14193 	OSArray *bundleIDList     = NULL; // do not release
14194 
14195 	bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
14196 		    requestDict, kKextRequestArgumentMissingBundleIDs));
14197 	if (!bundleIDList) {
14198 		return kOSKextReturnInvalidArgument;
14199 	}
14200 
14201 	missingIDs = OSDictionary::withCapacity(bundleIDList->getCount());
14202 	if (!missingIDs) {
14203 		return kOSKextReturnNoMemory;
14204 	}
14205 
14206 	uint32_t count, i;
14207 	count = bundleIDList->getCount();
14208 	for (i = 0; i < count; i++) {
14209 		OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i));
14210 		if (thisID) {
14211 			missingIDs->setObject(thisID, kOSBooleanFalse);
14212 		}
14213 	}
14214 
14215 	sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain);
14216 
14217 	return kOSReturnSuccess;
14218 }
14219 
14220 /*********************************************************************
14221 * Assumes sKextLock is held.
14222 *********************************************************************/
14223 /* static */
14224 OSReturn
14225 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict)
14226 {
14227 	bool loadable = true;
14228 	if (!kextIdentifier) {
14229 		return kOSKextReturnInvalidArgument;
14230 	}
14231 
14232 	if (requestDict) {
14233 		OSBoolean *loadableArg;
14234 		loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
14235 			    requestDict, kKextRequestArgumentBundleAvailability));
14236 		/* If we find the "Bundle Available" arg, and it's false, then
14237 		 * mark the bundle ID as _not_ loadable
14238 		 */
14239 		if (loadableArg && !loadableArg->getValue()) {
14240 			loadable = false;
14241 		}
14242 	}
14243 
14244 	if (!sNonLoadableKextsByID) {
14245 		sNonLoadableKextsByID = OSDictionary::withCapacity(1);
14246 	}
14247 
14248 	sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable));
14249 
14250 	OSKextLog(/* kext */ NULL,
14251 	    kOSKextLogBasicLevel | kOSKextLogIPCFlag,
14252 	    "KextLog: AuxKC bundle %s marked as %s",
14253 	    kextIdentifier->getCStringNoCopy(),
14254 	    (loadable ? "loadable" : "NOT loadable"));
14255 
14256 	return kOSReturnSuccess;
14257 }
14258 
14259 /*********************************************************************
14260 *********************************************************************/
14261 /* static */
14262 void
14263 OSKext::invokeRequestCallback(
14264 	OSDictionary * callbackRecord,
14265 	OSReturn       callbackResult)
14266 {
14267 	OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
14268 	OSSharedPtr<OSNumber> resultNum;
14269 
14270 	if (!predicate) {
14271 		goto finish;
14272 	}
14273 
14274 	resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
14275 	    8 * sizeof(callbackResult));
14276 	if (!resultNum) {
14277 		goto finish;
14278 	}
14279 
14280 	/* Insert the result into the callback record and dispatch it as if it
14281 	 * were the reply coming down from user space.
14282 	 */
14283 	_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
14284 	    resultNum.get());
14285 
14286 	if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
14287 		/* This removes the pending callback record.
14288 		 */
14289 		OSKext::dispatchResource(callbackRecord);
14290 	}
14291 
14292 finish:
14293 	return;
14294 }
14295 
14296 /*********************************************************************
14297 * Assumes sKextLock is held.
14298 *********************************************************************/
14299 /* static */
14300 OSReturn
14301 OSKext::cancelRequest(
14302 	OSKextRequestTag    requestTag,
14303 	void             ** contextOut)
14304 {
14305 	OSReturn       result         = kOSKextReturnNoMemory;
14306 	OSSharedPtr<OSDictionary> callbackRecord;
14307 	OSValueObject<void *> * contextWrapper = nullptr; // do not release
14308 
14309 	IORecursiveLockLock(sKextLock);
14310 	result = OSKext::dequeueCallbackForRequestTag(requestTag,
14311 	    callbackRecord);
14312 	IORecursiveLockUnlock(sKextLock);
14313 
14314 	if (result == kOSReturnSuccess && contextOut) {
14315 		contextWrapper = OSDynamicCast(OSValueObject<void *>,
14316 		    _OSKextGetRequestArgument(callbackRecord.get(),
14317 		    kKextRequestArgumentContextKey));
14318 		*contextOut = _OSKextExtractPointer(contextWrapper);
14319 	}
14320 
14321 	return result;
14322 }
14323 
14324 /*********************************************************************
14325 * Assumes sKextLock is held.
14326 *********************************************************************/
14327 void
14328 OSKext::invokeOrCancelRequestCallbacks(
14329 	OSReturn callbackResult,
14330 	bool     invokeFlag)
14331 {
14332 	unsigned int count, i;
14333 
14334 	count = sRequestCallbackRecords->getCount();
14335 	if (!count) {
14336 		goto finish;
14337 	}
14338 
14339 	i = count - 1;
14340 	do {
14341 		OSDictionary * request = OSDynamicCast(OSDictionary,
14342 		    sRequestCallbackRecords->getObject(i));
14343 
14344 		if (!request) {
14345 			continue;
14346 		}
14347 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14348 		    _OSKextGetRequestArgument(request,
14349 		    kKextRequestArgumentCallbackKey));
14350 
14351 		if (!callbackWrapper) {
14352 			sRequestCallbackRecords->removeObject(i);
14353 			continue;
14354 		}
14355 
14356 		vm_address_t callbackAddress = (vm_address_t)
14357 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
14358 
14359 		if ((kmod_info->address <= callbackAddress) &&
14360 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
14361 			if (invokeFlag) {
14362 				/* This removes the callback record.
14363 				 */
14364 				invokeRequestCallback(request, callbackResult);
14365 			} else {
14366 				sRequestCallbackRecords->removeObject(i);
14367 			}
14368 		}
14369 	} while (i--);
14370 
14371 finish:
14372 	return;
14373 }
14374 
14375 /*********************************************************************
14376 * Assumes sKextLock is held.
14377 *********************************************************************/
14378 uint32_t
14379 OSKext::countRequestCallbacks(void)
14380 {
14381 	uint32_t     result = 0;
14382 	unsigned int count, i;
14383 
14384 	count = sRequestCallbackRecords->getCount();
14385 	if (!count) {
14386 		goto finish;
14387 	}
14388 
14389 	i = count - 1;
14390 	do {
14391 		OSDictionary * request = OSDynamicCast(OSDictionary,
14392 		    sRequestCallbackRecords->getObject(i));
14393 
14394 		if (!request) {
14395 			continue;
14396 		}
14397 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14398 		    _OSKextGetRequestArgument(request,
14399 		    kKextRequestArgumentCallbackKey));
14400 
14401 		if (!callbackWrapper) {
14402 			continue;
14403 		}
14404 
14405 		vm_address_t callbackAddress = (vm_address_t)
14406 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
14407 
14408 		if ((kmod_info->address <= callbackAddress) &&
14409 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
14410 			result++;
14411 		}
14412 	} while (i--);
14413 
14414 finish:
14415 	return result;
14416 }
14417 
14418 /*********************************************************************
14419 *********************************************************************/
14420 static OSReturn
14421 _OSKextCreateRequest(
14422 	const char    * predicate,
14423 	OSSharedPtr<OSDictionary> & requestR)
14424 {
14425 	OSReturn result = kOSKextReturnNoMemory;
14426 	OSSharedPtr<OSDictionary> request;
14427 
14428 	request = OSDictionary::withCapacity(2);
14429 	if (!request) {
14430 		goto finish;
14431 	}
14432 	result = _OSDictionarySetCStringValue(request.get(),
14433 	    kKextRequestPredicateKey, predicate);
14434 	if (result != kOSReturnSuccess) {
14435 		goto finish;
14436 	}
14437 	result = kOSReturnSuccess;
14438 
14439 finish:
14440 	if (result == kOSReturnSuccess) {
14441 		requestR = os::move(request);
14442 	}
14443 
14444 	return result;
14445 }
14446 
14447 /*********************************************************************
14448 *********************************************************************/
14449 static OSString *
14450 _OSKextGetRequestPredicate(OSDictionary * requestDict)
14451 {
14452 	return OSDynamicCast(OSString,
14453 	           requestDict->getObject(kKextRequestPredicateKey));
14454 }
14455 
14456 /*********************************************************************
14457 *********************************************************************/
14458 static OSObject *
14459 _OSKextGetRequestArgument(
14460 	OSDictionary * requestDict,
14461 	const char   * argName)
14462 {
14463 	OSDictionary * args = OSDynamicCast(OSDictionary,
14464 	    requestDict->getObject(kKextRequestArgumentsKey));
14465 	if (args) {
14466 		return args->getObject(argName);
14467 	}
14468 	return NULL;
14469 }
14470 
14471 /*********************************************************************
14472 *********************************************************************/
14473 static bool
14474 _OSKextSetRequestArgument(
14475 	OSDictionary    * requestDict,
14476 	const char      * argName,
14477 	OSMetaClassBase * value)
14478 {
14479 	OSDictionary * args = OSDynamicCast(OSDictionary,
14480 	    requestDict->getObject(kKextRequestArgumentsKey));
14481 	OSSharedPtr<OSDictionary> newArgs;
14482 	if (!args) {
14483 		newArgs = OSDictionary::withCapacity(2);
14484 		args = newArgs.get();
14485 		if (!args) {
14486 			goto finish;
14487 		}
14488 		requestDict->setObject(kKextRequestArgumentsKey, args);
14489 	}
14490 	if (args) {
14491 		return args->setObject(argName, value);
14492 	}
14493 finish:
14494 	return false;
14495 }
14496 
14497 /*********************************************************************
14498 *********************************************************************/
14499 template <typename T>
14500 static T *
14501 _OSKextExtractPointer(OSValueObject<T *> * wrapper)
14502 {
14503 	if (!wrapper) {
14504 		return nullptr;
14505 	}
14506 	return wrapper->getRef();
14507 }
14508 
14509 /*********************************************************************
14510 *********************************************************************/
14511 static OSKextRequestResourceCallback
14512 _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper)
14513 {
14514 	if (!wrapper) {
14515 		return nullptr;
14516 	}
14517 	return wrapper->getRef();
14518 }
14519 
14520 
14521 /*********************************************************************
14522 *********************************************************************/
14523 static OSReturn
14524 _OSDictionarySetCStringValue(
14525 	OSDictionary * dict,
14526 	const char   * cKey,
14527 	const char   * cValue)
14528 {
14529 	OSReturn result = kOSKextReturnNoMemory;
14530 	OSSharedPtr<const OSSymbol> key;
14531 	OSSharedPtr<OSString> value;
14532 
14533 	key = OSSymbol::withCString(cKey);
14534 	value = OSString::withCString(cValue);
14535 	if (!key || !value) {
14536 		goto finish;
14537 	}
14538 	if (dict->setObject(key.get(), value.get())) {
14539 		result = kOSReturnSuccess;
14540 	}
14541 
14542 finish:
14543 	return result;
14544 }
14545 
14546 /*********************************************************************
14547 *********************************************************************/
14548 static bool
14549 _OSArrayContainsCString(
14550 	OSArray    * array,
14551 	const char * cString)
14552 {
14553 	bool             result = false;
14554 	OSSharedPtr<const OSSymbol> symbol;
14555 	uint32_t         count, i;
14556 
14557 	if (!array || !cString) {
14558 		goto finish;
14559 	}
14560 
14561 	symbol = OSSymbol::withCStringNoCopy(cString);
14562 	if (!symbol) {
14563 		goto finish;
14564 	}
14565 
14566 	count = array->getCount();
14567 	for (i = 0; i < count; i++) {
14568 		OSObject * thisObject = array->getObject(i);
14569 		if (symbol->isEqualTo(thisObject)) {
14570 			result = true;
14571 			goto finish;
14572 		}
14573 	}
14574 
14575 finish:
14576 	return result;
14577 }
14578 
14579 #if CONFIG_KXLD
14580 /*********************************************************************
14581 * We really only care about boot / system start up related kexts.
14582 * We return true if we're less than REBUILD_MAX_TIME since start up,
14583 * otherwise return false.
14584 *********************************************************************/
14585 bool
14586 _OSKextInPrelinkRebuildWindow(void)
14587 {
14588 	static bool     outside_the_window = false;
14589 	AbsoluteTime    my_abstime;
14590 	UInt64          my_ns;
14591 	SInt32          my_secs;
14592 
14593 	if (outside_the_window) {
14594 		return false;
14595 	}
14596 	clock_get_uptime(&my_abstime);
14597 	absolutetime_to_nanoseconds(my_abstime, &my_ns);
14598 	my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
14599 	if (my_secs > REBUILD_MAX_TIME) {
14600 		outside_the_window = true;
14601 		return false;
14602 	}
14603 	return true;
14604 }
14605 #endif /* CONFIG_KXLD */
14606 
14607 /*********************************************************************
14608 *********************************************************************/
14609 bool
14610 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
14611 {
14612 	int unLoadedCount, i;
14613 	bool result = false;
14614 
14615 	IORecursiveLockLock(sKextLock);
14616 
14617 	if (sUnloadedPrelinkedKexts == NULL) {
14618 		goto finish;
14619 	}
14620 	unLoadedCount = sUnloadedPrelinkedKexts->getCount();
14621 	if (unLoadedCount == 0) {
14622 		goto finish;
14623 	}
14624 
14625 	for (i = 0; i < unLoadedCount; i++) {
14626 		const OSSymbol *    myBundleID;        // do not release
14627 
14628 		myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
14629 		if (!myBundleID) {
14630 			continue;
14631 		}
14632 		if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
14633 			result = true;
14634 			break;
14635 		}
14636 	}
14637 finish:
14638 	IORecursiveLockUnlock(sKextLock);
14639 	return result;
14640 }
14641 
14642 #if PRAGMA_MARK
14643 #pragma mark Personalities (IOKit Drivers)
14644 #endif
14645 /*********************************************************************
14646 *********************************************************************/
14647 /* static */
14648 OSSharedPtr<OSArray>
14649 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
14650 {
14651 	OSSharedPtr<OSArray>              result;
14652 	OSSharedPtr<OSCollectionIterator> kextIterator;
14653 	OSSharedPtr<OSArray>              personalities;
14654 
14655 	OSString             * kextID                = NULL;        // do not release
14656 	OSKext               * theKext               = NULL;        // do not release
14657 
14658 	IORecursiveLockLock(sKextLock);
14659 
14660 	/* Let's conservatively guess that any given kext has around 3
14661 	 * personalities for now.
14662 	 */
14663 	result = OSArray::withCapacity(sKextsByID->getCount() * 3);
14664 	if (!result) {
14665 		goto finish;
14666 	}
14667 
14668 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
14669 	if (!kextIterator) {
14670 		goto finish;
14671 	}
14672 
14673 	while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
14674 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
14675 		if (theKext->flags.requireExplicitLoad) {
14676 			OSKextLog(theKext,
14677 			    kOSKextLogDebugLevel |
14678 			    kOSKextLogLoadFlag,
14679 			    "Kext %s requires an explicit kextload; "
14680 			    "omitting its personalities.",
14681 			    theKext->getIdentifierCString());
14682 		} else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
14683 			personalities = theKext->copyPersonalitiesArray();
14684 			if (!personalities) {
14685 				continue;
14686 			}
14687 			result->merge(personalities.get());
14688 		} else {
14689 			// xxx - check for better place to put this log msg
14690 			OSKextLog(theKext,
14691 			    kOSKextLogWarningLevel |
14692 			    kOSKextLogLoadFlag,
14693 			    "Kext %s is not loadable during safe boot; "
14694 			    "omitting its personalities.",
14695 			    theKext->getIdentifierCString());
14696 		}
14697 	}
14698 
14699 finish:
14700 	IORecursiveLockUnlock(sKextLock);
14701 
14702 	return result;
14703 }
14704 
14705 /*********************************************************************
14706 *********************************************************************/
14707 /* static */
14708 void
14709 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
14710 {
14711 	int numPersonalities = 0;
14712 
14713 	OSKextLog(/* kext */ NULL,
14714 	    kOSKextLogStepLevel |
14715 	    kOSKextLogLoadFlag,
14716 	    "Sending all eligible registered kexts' personalities "
14717 	    "to the IOCatalogue %s.",
14718 	    startMatching ? "and starting matching" : "but not starting matching");
14719 
14720 	OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities(
14721 		/* filterSafeBootFlag */ true);
14722 
14723 	if (personalities) {
14724 		gIOCatalogue->addDrivers(personalities.get(), startMatching);
14725 		numPersonalities = personalities->getCount();
14726 	}
14727 
14728 	OSKextLog(/* kext */ NULL,
14729 	    kOSKextLogStepLevel |
14730 	    kOSKextLogLoadFlag,
14731 	    "%d kext personalit%s sent to the IOCatalogue; %s.",
14732 	    numPersonalities, numPersonalities > 0 ? "ies" : "y",
14733 	    startMatching ? "matching started" : "matching not started");
14734 	return;
14735 }
14736 
14737 /*********************************************************************
14738 * Do not make a deep copy, just convert the IOKitPersonalities dict
14739 * to an array for sending to the IOCatalogue.
14740 *********************************************************************/
14741 OSSharedPtr<OSArray>
14742 OSKext::copyPersonalitiesArray(void)
14743 {
14744 	OSSharedPtr<OSArray>              result;
14745 	OSDictionary         * personalities               = NULL;        // do not release
14746 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
14747 
14748 	OSString             * personalityName             = NULL;        // do not release
14749 	OSString             * personalityBundleIdentifier = NULL;        // do not release
14750 
14751 	personalities = OSDynamicCast(OSDictionary,
14752 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
14753 	if (!personalities) {
14754 		goto finish;
14755 	}
14756 
14757 	result = OSArray::withCapacity(personalities->getCount());
14758 	if (!result) {
14759 		goto finish;
14760 	}
14761 
14762 	personalitiesIterator =
14763 	    OSCollectionIterator::withCollection(personalities);
14764 	if (!personalitiesIterator) {
14765 		goto finish;
14766 	}
14767 	while ((personalityName = OSDynamicCast(OSString,
14768 	    personalitiesIterator->getNextObject()))) {
14769 		OSDictionary * personality = OSDynamicCast(OSDictionary,
14770 		    personalities->getObject(personalityName));
14771 
14772 		if (personality) {
14773 			/******
14774 			 * If the personality doesn't have a CFBundleIdentifier, or if it
14775 			 * differs from the kext's, insert the kext's ID so we can find it.
14776 			 * The publisher ID is used to remove personalities from bundles
14777 			 * correctly.
14778 			 */
14779 			personalityBundleIdentifier = OSDynamicCast(OSString,
14780 			    personality->getObject(kCFBundleIdentifierKey));
14781 
14782 			if (!personalityBundleIdentifier) {
14783 				personality->setObject(kCFBundleIdentifierKey, bundleID.get());
14784 			} else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) {
14785 				personality->setObject(kIOPersonalityPublisherKey, bundleID.get());
14786 			}
14787 		}
14788 
14789 		result->setObject(personality);
14790 	}
14791 
14792 finish:
14793 	return result;
14794 }
14795 
14796 /*********************************************************************
14797 *   Might want to change this to a bool return?
14798 *********************************************************************/
14799 OSReturn
14800 OSKext::sendPersonalitiesToCatalog(
14801 	bool      startMatching,
14802 	OSArray * personalityNames)
14803 {
14804 	OSReturn       result              = kOSReturnSuccess;
14805 	OSSharedPtr<OSArray> personalitiesToSend;
14806 	OSDictionary * kextPersonalities   = NULL;        // do not release
14807 	int            count, i;
14808 
14809 	if (!sLoadEnabled) {
14810 		OSKextLog(this,
14811 		    kOSKextLogErrorLevel |
14812 		    kOSKextLogLoadFlag,
14813 		    "Kext loading is disabled (attempt to start matching for kext %s).",
14814 		    getIdentifierCString());
14815 		result = kOSKextReturnDisabled;
14816 		goto finish;
14817 	}
14818 
14819 	if (sSafeBoot && !isLoadableInSafeBoot()) {
14820 		OSKextLog(this,
14821 		    kOSKextLogErrorLevel |
14822 		    kOSKextLogLoadFlag,
14823 		    "Kext %s is not loadable during safe boot; "
14824 		    "not sending personalities to the IOCatalogue.",
14825 		    getIdentifierCString());
14826 		result = kOSKextReturnNotLoadable;
14827 		goto finish;
14828 	}
14829 
14830 	if (!personalityNames || !personalityNames->getCount()) {
14831 		personalitiesToSend = copyPersonalitiesArray();
14832 	} else {
14833 		kextPersonalities = OSDynamicCast(OSDictionary,
14834 		    getPropertyForHostArch(kIOKitPersonalitiesKey));
14835 		if (!kextPersonalities || !kextPersonalities->getCount()) {
14836 			// not an error
14837 			goto finish;
14838 		}
14839 		personalitiesToSend = OSArray::withCapacity(0);
14840 		if (!personalitiesToSend) {
14841 			result = kOSKextReturnNoMemory;
14842 			goto finish;
14843 		}
14844 		count = personalityNames->getCount();
14845 		for (i = 0; i < count; i++) {
14846 			OSString * name = OSDynamicCast(OSString,
14847 			    personalityNames->getObject(i));
14848 			if (!name) {
14849 				continue;
14850 			}
14851 			OSDictionary * personality = OSDynamicCast(OSDictionary,
14852 			    kextPersonalities->getObject(name));
14853 			if (personality) {
14854 				personalitiesToSend->setObject(personality);
14855 			}
14856 		}
14857 	}
14858 	if (personalitiesToSend) {
14859 		unsigned numPersonalities = personalitiesToSend->getCount();
14860 		OSKextLog(this,
14861 		    kOSKextLogStepLevel |
14862 		    kOSKextLogLoadFlag,
14863 		    "Kext %s sending %d personalit%s to the IOCatalogue%s.",
14864 		    getIdentifierCString(),
14865 		    numPersonalities,
14866 		    numPersonalities > 1 ? "ies" : "y",
14867 		    startMatching ? " and starting matching" : " but not starting matching");
14868 		gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching);
14869 	}
14870 finish:
14871 	return result;
14872 }
14873 
14874 /*********************************************************************
14875 * xxx - We should allow removing the kext's declared personalities,
14876 * xxx - even with other bundle identifiers.
14877 *********************************************************************/
14878 void
14879 OSKext::removePersonalitiesFromCatalog(void)
14880 {
14881 	OSSharedPtr<OSDictionary> personality;
14882 
14883 	personality = OSDictionary::withCapacity(1);
14884 	if (!personality) {
14885 		goto finish;
14886 	}
14887 	personality->setObject(kCFBundleIdentifierKey, getIdentifier());
14888 
14889 	OSKextLog(this,
14890 	    kOSKextLogStepLevel |
14891 	    kOSKextLogLoadFlag,
14892 	    "Kext %s removing all personalities naming it from the IOCatalogue.",
14893 	    getIdentifierCString());
14894 
14895 	/* Have the IOCatalog remove all personalities matching this kext's
14896 	 * bundle ID and trigger matching anew.
14897 	 */
14898 	gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true);
14899 
14900 finish:
14901 	return;
14902 }
14903 
14904 void
14905 OSKext::updatePersonalitiesInCatalog(OSArray *upgradedPersonalities)
14906 {
14907 	if (!upgradedPersonalities || upgradedPersonalities->getCount() == 0) {
14908 		return;
14909 	}
14910 
14911 	OSSharedPtr<OSDictionary> personalityToRemove = OSDictionary::withCapacity(1);
14912 	if (!personalityToRemove) {
14913 		return;
14914 	}
14915 
14916 	/*
14917 	 * Create a personality dictionary with just the bundleID.
14918 	 * We will remove any personality that has a matching bundleID,
14919 	 * irrespective of which other keys are present on the dictionary.
14920 	 */
14921 	personalityToRemove->setObject(kCFBundleIdentifierKey, getIdentifier());
14922 	gIOCatalogue->exchangeDrivers(personalityToRemove.get(), upgradedPersonalities, true);
14923 }
14924 
14925 #if PRAGMA_MARK
14926 #pragma mark Logging
14927 #endif
14928 /*********************************************************************
14929 * Do not call any function that takes sKextLock here!
14930 *********************************************************************/
14931 /* static */
14932 OSKextLogSpec
14933 OSKext::setUserSpaceLogFilter(
14934 	OSKextLogSpec   newUserLogFilter,
14935 	bool            captureFlag)
14936 {
14937 	OSKextLogSpec result;
14938 	bool          allocError = false;
14939 
14940 	/* Do not call any function that takes sKextLoggingLock during
14941 	 * this critical block. That means do logging after.
14942 	 */
14943 	IOLockLock(sKextLoggingLock);
14944 
14945 	result = sUserSpaceKextLogFilter;
14946 	sUserSpaceKextLogFilter = newUserLogFilter;
14947 
14948 	if (newUserLogFilter && captureFlag &&
14949 	    !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
14950 		// xxx - do some measurements for a good initial capacity?
14951 		sUserSpaceLogSpecArray = OSArray::withCapacity(0);
14952 		sUserSpaceLogMessageArray = OSArray::withCapacity(0);
14953 
14954 		if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
14955 			allocError = true;
14956 		}
14957 	}
14958 
14959 	IOLockUnlock(sKextLoggingLock);
14960 
14961 	/* If the config flag itself is changing, log the state change
14962 	 * going both ways, before setting up the user-space log arrays,
14963 	 * so that this is only logged in the kernel.
14964 	 */
14965 	if (result != newUserLogFilter) {
14966 		OSKextLog(/* kext */ NULL,
14967 		    kOSKextLogDebugLevel |
14968 		    kOSKextLogGeneralFlag,
14969 		    "User-space log flags changed from 0x%x to 0x%x.",
14970 		    result, newUserLogFilter);
14971 	}
14972 	if (allocError) {
14973 		OSKextLog(/* kext */ NULL,
14974 		    kOSKextLogErrorLevel |
14975 		    kOSKextLogGeneralFlag,
14976 		    "Failed to allocate user-space log message arrays.");
14977 	}
14978 
14979 	return result;
14980 }
14981 
14982 /*********************************************************************
14983 * Do not call any function that takes sKextLock here!
14984 *********************************************************************/
14985 /* static */
14986 OSSharedPtr<OSArray>
14987 OSKext::clearUserSpaceLogFilter(void)
14988 {
14989 	OSSharedPtr<OSArray>       result;
14990 	OSKextLogSpec   oldLogFilter;
14991 	OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
14992 
14993 	/* Do not call any function that takes sKextLoggingLock during
14994 	 * this critical block. That means do logging after.
14995 	 */
14996 	IOLockLock(sKextLoggingLock);
14997 
14998 	result = OSArray::withCapacity(2);
14999 	if (result) {
15000 		result->setObject(sUserSpaceLogSpecArray.get());
15001 		result->setObject(sUserSpaceLogMessageArray.get());
15002 	}
15003 	sUserSpaceLogSpecArray.reset();
15004 	sUserSpaceLogMessageArray.reset();
15005 
15006 	oldLogFilter = sUserSpaceKextLogFilter;
15007 	sUserSpaceKextLogFilter = newLogFilter;
15008 
15009 	IOLockUnlock(sKextLoggingLock);
15010 
15011 	/* If the config flag itself is changing, log the state change
15012 	 * going both ways, after tearing down the user-space log
15013 	 * arrays, so this is only logged within the kernel.
15014 	 */
15015 	if (oldLogFilter != newLogFilter) {
15016 		OSKextLog(/* kext */ NULL,
15017 		    kOSKextLogDebugLevel |
15018 		    kOSKextLogGeneralFlag,
15019 		    "User-space log flags changed from 0x%x to 0x%x.",
15020 		    oldLogFilter, newLogFilter);
15021 	}
15022 
15023 	return result;
15024 }
15025 
15026 
15027 /*********************************************************************
15028 * Do not call any function that takes sKextLock here!
15029 *********************************************************************/
15030 /* static */
15031 OSKextLogSpec
15032 OSKext::getUserSpaceLogFilter(void)
15033 {
15034 	OSKextLogSpec result;
15035 
15036 	IOLockLock(sKextLoggingLock);
15037 	result = sUserSpaceKextLogFilter;
15038 	IOLockUnlock(sKextLoggingLock);
15039 
15040 	return result;
15041 }
15042 
15043 /*********************************************************************
15044 * This function is called by OSMetaClass during kernel C++ setup.
15045 * Be careful what you access here; assume only OSKext::initialize()
15046 * has been called.
15047 *
15048 * Do not call any function that takes sKextLock here!
15049 *********************************************************************/
15050 #define VTRESET   "\033[0m"
15051 
15052 #define VTBOLD    "\033[1m"
15053 #define VTUNDER   "\033[4m"
15054 
15055 #define VTRED     "\033[31m"
15056 #define VTGREEN   "\033[32m"
15057 #define VTYELLOW  "\033[33m"
15058 #define VTBLUE    "\033[34m"
15059 #define VTMAGENTA "\033[35m"
15060 #define VTCYAN    "\033[36m"
15061 
15062 inline const char *
15063 colorForFlags(OSKextLogSpec flags)
15064 {
15065 	OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
15066 
15067 	switch (logLevel) {
15068 	case kOSKextLogErrorLevel:
15069 		return VTRED VTBOLD;
15070 	case kOSKextLogWarningLevel:
15071 		return VTRED;
15072 	case kOSKextLogBasicLevel:
15073 		return VTYELLOW VTUNDER;
15074 	case kOSKextLogProgressLevel:
15075 		return VTYELLOW;
15076 	case kOSKextLogStepLevel:
15077 		return VTGREEN;
15078 	case kOSKextLogDetailLevel:
15079 		return VTCYAN;
15080 	case kOSKextLogDebugLevel:
15081 		return VTMAGENTA;
15082 	default:
15083 		return "";         // white
15084 	}
15085 }
15086 
15087 inline bool
15088 logSpecMatch(
15089 	OSKextLogSpec msgLogSpec,
15090 	OSKextLogSpec logFilter)
15091 {
15092 	OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
15093 	OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
15094 	OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
15095 
15096 	OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
15097 	OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
15098 	OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
15099 
15100 	/* Explicit messages always get logged.
15101 	 */
15102 	if (msgLevel == kOSKextLogExplicitLevel) {
15103 		return true;
15104 	}
15105 
15106 	/* Warnings and errors are logged regardless of the flags.
15107 	 */
15108 	if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
15109 		return true;
15110 	}
15111 
15112 	/* A verbose message that isn't for a logging-enabled kext and isn't global
15113 	 * does *not* get logged.
15114 	 */
15115 	if (!msgKextGlobal && !filterKextGlobal) {
15116 		return false;
15117 	}
15118 
15119 	/* Warnings and errors are logged regardless of the flags.
15120 	 * All other messages must fit the flags and
15121 	 * have a level at or below the filter.
15122 	 *
15123 	 */
15124 	if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
15125 		return true;
15126 	}
15127 	return false;
15128 }
15129 
15130 extern "C" {
15131 void
15132 OSKextLog(
15133 	OSKext         * aKext,
15134 	OSKextLogSpec    msgLogSpec,
15135 	const char     * format, ...)
15136 {
15137 	va_list argList;
15138 
15139 	va_start(argList, format);
15140 	OSKextVLog(aKext, msgLogSpec, format, argList);
15141 	va_end(argList);
15142 }
15143 
15144 void
15145 OSKextVLog(
15146 	OSKext         * aKext,
15147 	OSKextLogSpec    msgLogSpec,
15148 	const char     * format,
15149 	va_list          srcArgList)
15150 {
15151 	extern int       disableConsoleOutput;
15152 
15153 	bool             logForKernel       = false;
15154 	bool             logForUser         = false;
15155 	va_list          argList;
15156 	char             stackBuffer[120];
15157 	uint32_t         length            = 0;
15158 	char           * allocBuffer       = NULL;        // must kfree
15159 	OSSharedPtr<OSNumber> logSpecNum;
15160 	OSSharedPtr<OSString> logString;
15161 	char           * buffer            = stackBuffer;        // do not free
15162 
15163 	IOLockLock(sKextLoggingLock);
15164 
15165 	/* Set the kext/global bit in the message spec if we have no
15166 	 * kext or if the kext requests logging.
15167 	 */
15168 	if (!aKext || aKext->flags.loggingEnabled) {
15169 		msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
15170 	}
15171 
15172 	logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
15173 	if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
15174 		logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
15175 	}
15176 
15177 	if (!(logForKernel || logForUser)) {
15178 		goto finish;
15179 	}
15180 
15181 	/* No goto from here until past va_end()!
15182 	 */
15183 	va_copy(argList, srcArgList);
15184 	length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
15185 	va_end(argList);
15186 
15187 	if (length + 1 >= sizeof(stackBuffer)) {
15188 		allocBuffer = (char *)kalloc_data_tag(length + 1,
15189 		    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
15190 		if (!allocBuffer) {
15191 			goto finish;
15192 		}
15193 
15194 		/* No goto from here until past va_end()!
15195 		 */
15196 		va_copy(argList, srcArgList);
15197 		vsnprintf(allocBuffer, length + 1, format, argList);
15198 		va_end(argList);
15199 
15200 		buffer = allocBuffer;
15201 	}
15202 
15203 	/* If user space wants the log message, queue it up.
15204 	 */
15205 	if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
15206 		logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
15207 		logString = OSString::withCString(buffer);
15208 		if (logSpecNum && logString) {
15209 			sUserSpaceLogSpecArray->setObject(logSpecNum.get());
15210 			sUserSpaceLogMessageArray->setObject(logString.get());
15211 		}
15212 	}
15213 
15214 	/* Always log messages from the kernel according to the kernel's
15215 	 * log flags.
15216 	 */
15217 	if (logForKernel) {
15218 		/* If we are in console mode and have a custom log filter,
15219 		 * colorize the log message.
15220 		 */
15221 		if (!disableConsoleOutput && sBootArgLogFilterFound) {
15222 			const char * color = "";         // do not free
15223 			color = colorForFlags(msgLogSpec);
15224 			printf("%s%s%s\n", colorForFlags(msgLogSpec),
15225 			    buffer, color[0] ? VTRESET : "");
15226 		} else {
15227 			printf("%s\n", buffer);
15228 		}
15229 	}
15230 
15231 finish:
15232 	IOLockUnlock(sKextLoggingLock);
15233 
15234 	if (allocBuffer) {
15235 		kfree_data(allocBuffer, length + 1);
15236 	}
15237 	return;
15238 }
15239 
15240 #if KASLR_IOREG_DEBUG
15241 
15242 #define IOLOG_INDENT( the_indention ) \
15243 { \
15244     int     i; \
15245     for ( i = 0; i < (the_indention); i++ ) { \
15246 	IOLog(" "); \
15247     } \
15248 }
15249 
15250 extern vm_offset_t       vm_kernel_stext;
15251 extern vm_offset_t       vm_kernel_etext;
15252 extern mach_vm_offset_t kext_alloc_base;
15253 extern mach_vm_offset_t kext_alloc_max;
15254 
15255 bool ScanForAddrInObject(OSObject * theObject,
15256     int indent );
15257 
15258 bool
15259 ScanForAddrInObject(OSObject * theObject,
15260     int indent)
15261 {
15262 	const OSMetaClass *     myTypeID;
15263 	OSSharedPtr<OSCollectionIterator>  myIter;
15264 	OSSymbol *              myKey;
15265 	OSObject *              myValue;
15266 	bool                    myResult = false;
15267 
15268 	if (theObject == NULL) {
15269 		IOLog("%s: theObject is NULL \n",
15270 		    __FUNCTION__);
15271 		return myResult;
15272 	}
15273 
15274 	myTypeID = OSTypeIDInst(theObject);
15275 
15276 	if (myTypeID == OSTypeID(OSDictionary)) {
15277 		OSDictionary *      myDictionary;
15278 
15279 		myDictionary = OSDynamicCast(OSDictionary, theObject);
15280 		myIter = OSCollectionIterator::withCollection( myDictionary );
15281 		if (myIter == NULL) {
15282 			return myResult;
15283 		}
15284 
15285 		// !! reset the iterator
15286 		myIter->reset();
15287 
15288 		while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
15289 			bool    myTempResult;
15290 
15291 			myValue = myDictionary->getObject(myKey);
15292 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
15293 			if (myTempResult) {
15294 				// if we ever get a true result return true
15295 				myResult = true;
15296 				IOLOG_INDENT(indent);
15297 				IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
15298 			}
15299 		}
15300 
15301 		// !! release the iterator
15302 		myIter.reset();
15303 	} else if (myTypeID == OSTypeID(OSArray)) {
15304 		OSArray *   myArray;
15305 
15306 		myArray = OSDynamicCast(OSArray, theObject);
15307 		myIter = OSCollectionIterator::withCollection(myArray);
15308 		if (myIter == NULL) {
15309 			return myResult;
15310 		}
15311 		// !! reset the iterator
15312 		myIter->reset();
15313 
15314 		while ((myValue = myIter->getNextObject())) {
15315 			bool        myTempResult;
15316 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
15317 			if (myTempResult) {
15318 				// if we ever get a true result return true
15319 				myResult = true;
15320 				IOLOG_INDENT(indent);
15321 				IOLog("OSArray: \n");
15322 			}
15323 		}
15324 		// !! release the iterator
15325 		myIter.reset();
15326 	} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
15327 		// should we look for addresses in strings?
15328 	} else if (myTypeID == OSTypeID(OSData)) {
15329 		void * *        myPtrPtr;
15330 		unsigned int    myLen;
15331 		OSData *        myDataObj;
15332 
15333 		myDataObj =    OSDynamicCast(OSData, theObject);
15334 		myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
15335 		myLen = myDataObj->getLength();
15336 
15337 		if (myPtrPtr && myLen && myLen > 7) {
15338 			int     i;
15339 			int     myPtrCount = (myLen / sizeof(void *));
15340 
15341 			for (i = 0; i < myPtrCount; i++) {
15342 				UInt64 numberValue = (UInt64) * (myPtrPtr);
15343 
15344 				if (kext_alloc_max != 0 &&
15345 				    numberValue >= kext_alloc_base &&
15346 				    numberValue < kext_alloc_max) {
15347 					OSSharedPtr<OSKext> myKext;
15348 					// IOLog("found OSData %p in kext map %p to %p  \n",
15349 					//       *(myPtrPtr),
15350 					//       (void *) kext_alloc_base,
15351 					//       (void *) kext_alloc_max);
15352 
15353 					myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
15354 					if (myKext) {
15355 						IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
15356 						    *(myPtrPtr),
15357 						    myKext->getIdentifierCString());
15358 					}
15359 					myResult = true;
15360 				}
15361 				if (vm_kernel_etext != 0 &&
15362 				    numberValue >= vm_kernel_stext &&
15363 				    numberValue < vm_kernel_etext) {
15364 					IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
15365 					    *(myPtrPtr),
15366 					    (void *) vm_kernel_stext,
15367 					    (void *) vm_kernel_etext);
15368 					myResult = true;
15369 				}
15370 				myPtrPtr++;
15371 			}
15372 		}
15373 	} else if (myTypeID == OSTypeID(OSBoolean)) {
15374 		// do nothing here...
15375 	} else if (myTypeID == OSTypeID(OSNumber)) {
15376 		OSNumber * number = OSDynamicCast(OSNumber, theObject);
15377 
15378 		UInt64 numberValue = number->unsigned64BitValue();
15379 
15380 		if (kext_alloc_max != 0 &&
15381 		    numberValue >= kext_alloc_base &&
15382 		    numberValue < kext_alloc_max) {
15383 			OSSharedPtr<OSKext> myKext;
15384 			IOLog("found OSNumber in kext map %p to %p  \n",
15385 			    (void *) kext_alloc_base,
15386 			    (void *) kext_alloc_max);
15387 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
15388 
15389 			myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
15390 			if (myKext) {
15391 				IOLog("found in kext \"%s\"  \n",
15392 				    myKext->getIdentifierCString());
15393 			}
15394 
15395 			myResult = true;
15396 		}
15397 		if (vm_kernel_etext != 0 &&
15398 		    numberValue >= vm_kernel_stext &&
15399 		    numberValue < vm_kernel_etext) {
15400 			IOLog("found OSNumber in kernel text segment %p to %p  \n",
15401 			    (void *) vm_kernel_stext,
15402 			    (void *) vm_kernel_etext);
15403 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
15404 			myResult = true;
15405 		}
15406 	}
15407 #if 0
15408 	else {
15409 		const OSMetaClass* myMetaClass = NULL;
15410 
15411 		myMetaClass = theObject->getMetaClass();
15412 		if (myMetaClass) {
15413 			IOLog("class %s \n", myMetaClass->getClassName());
15414 		} else {
15415 			IOLog("Unknown object \n" );
15416 		}
15417 	}
15418 #endif
15419 
15420 	return myResult;
15421 }
15422 #endif // KASLR_KEXT_DEBUG
15423 };         /* extern "C" */
15424 
15425 #if PRAGMA_MARK
15426 #pragma mark Backtrace Dump & kmod_get_info() support
15427 #endif
15428 /*********************************************************************
15429 * This function must be safe to call in panic context.
15430 *********************************************************************/
15431 /* static */
15432 void
15433 OSKext::printKextsInBacktrace(
15434 	vm_offset_t  * addr __unused,
15435 	unsigned int   cnt __unused,
15436 	int         (* printf_func)(const char *fmt, ...) __unused,
15437 	uint32_t       flags __unused)
15438 {
15439 	addr64_t    summary_page = 0;
15440 	addr64_t    last_summary_page = 0;
15441 	bool        found_kmod = false;
15442 	u_int       i = 0;
15443 
15444 	if (kPrintKextsLock & flags) {
15445 		if (!sKextSummariesLock) {
15446 			return;
15447 		}
15448 		IOLockLock(sKextSummariesLock);
15449 	}
15450 
15451 	if (!gLoadedKextSummaries) {
15452 		(*printf_func)("         can't perform kext scan: no kext summary");
15453 		goto finish;
15454 	}
15455 
15456 	summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
15457 	last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
15458 	for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
15459 		if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
15460 			(*printf_func)("         can't perform kext scan: "
15461 			    "missing kext summary page %p", summary_page);
15462 			goto finish;
15463 		}
15464 	}
15465 
15466 	for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15467 		OSKextLoadedKextSummary * summary;
15468 
15469 		summary = gLoadedKextSummaries->summaries + i;
15470 		if (!summary->address) {
15471 			continue;
15472 		}
15473 
15474 		if (!summaryIsInBacktrace(summary, addr, cnt)) {
15475 			continue;
15476 		}
15477 
15478 		if (!found_kmod) {
15479 			if (!(kPrintKextsTerse & flags)) {
15480 				(*printf_func)("      Kernel Extensions in backtrace:\n");
15481 			}
15482 			found_kmod = true;
15483 		}
15484 
15485 		printSummary(summary, printf_func, flags);
15486 	}
15487 
15488 finish:
15489 	if (kPrintKextsLock & flags) {
15490 		IOLockUnlock(sKextSummariesLock);
15491 	}
15492 
15493 	return;
15494 }
15495 
15496 /*********************************************************************
15497 * This function must be safe to call in panic context.
15498 *********************************************************************/
15499 /* static */
15500 boolean_t
15501 OSKext::summaryIsInBacktrace(
15502 	OSKextLoadedKextSummary   * summary,
15503 	vm_offset_t               * addr,
15504 	unsigned int                cnt)
15505 {
15506 	u_int i = 0;
15507 
15508 	for (i = 0; i < cnt; i++) {
15509 		vm_offset_t kscan_addr = addr[i];
15510 #if  __has_feature(ptrauth_calls)
15511 		kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr);
15512 #endif /*  __has_feature(ptrauth_calls) */
15513 		if ((kscan_addr >= summary->text_exec_address) &&
15514 		    (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) {
15515 			return TRUE;
15516 		}
15517 	}
15518 
15519 	return FALSE;
15520 }
15521 
15522 /*
15523  * Get the kext summary object for the kext where 'addr' lies. Must be called with
15524  * sKextSummariesLock held.
15525  */
15526 OSKextLoadedKextSummary *
15527 OSKext::summaryForAddress(uintptr_t addr)
15528 {
15529 #if  __has_feature(ptrauth_calls)
15530 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
15531 #endif /*  __has_feature(ptrauth_calls) */
15532 	for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15533 		OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
15534 		if (!summary->address) {
15535 			continue;
15536 		}
15537 
15538 #if VM_MAPPED_KEXTS
15539 		/* On our platforms that use VM_MAPPED_KEXTS, we currently do not
15540 		 * support split kexts, but we also may unmap the kexts, which can
15541 		 * race with the above codepath (see OSKext::unload).  As such,
15542 		 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
15543 		 */
15544 		if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
15545 			return summary;
15546 		}
15547 #else
15548 		kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
15549 		kernel_segment_command_t *seg;
15550 
15551 		for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
15552 			if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
15553 				return summary;
15554 			}
15555 		}
15556 #endif
15557 	}
15558 
15559 	/* addr did not map to any kext */
15560 	return NULL;
15561 }
15562 
15563 /* static */
15564 void *
15565 OSKext::kextForAddress(const void *address)
15566 {
15567 	OSKextActiveAccount * active;
15568 	OSKext              * kext = NULL;
15569 	uint32_t              baseIdx;
15570 	uint32_t              lim;
15571 	uintptr_t             addr = (uintptr_t) address;
15572 	size_t                i;
15573 
15574 	if (!addr) {
15575 		return NULL;
15576 	}
15577 #if  __has_feature(ptrauth_calls)
15578 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
15579 #endif /*  __has_feature(ptrauth_calls) */
15580 
15581 	if (sKextAccountsCount) {
15582 		lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
15583 		// bsearch sKextAccounts list
15584 		for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15585 			active = &sKextAccounts[baseIdx + (lim >> 1)];
15586 			if ((addr >= active->address) && (addr < active->address_end)) {
15587 				kext = active->account->kext;
15588 				if (kext && kext->kmod_info) {
15589 					lck_ticket_unlock(sKextAccountsLock);
15590 					return (void *)kext->kmod_info->address;
15591 				}
15592 				break;
15593 			} else if (addr > active->address) {
15594 				// move right
15595 				baseIdx += (lim >> 1) + 1;
15596 				lim--;
15597 			}
15598 			// else move left
15599 		}
15600 		lck_ticket_unlock(sKextAccountsLock);
15601 	}
15602 	if (kernel_text_contains(addr)) {
15603 		return (void *)&_mh_execute_header;
15604 	}
15605 	if (gLoadedKextSummaries) {
15606 		IOLockLock(sKextSummariesLock);
15607 		for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) {
15608 			OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
15609 			if (addr >= summary->address && addr < summary->address + summary->size) {
15610 				void *kextAddress = (void *)summary->address;
15611 				IOLockUnlock(sKextSummariesLock);
15612 				return kextAddress;
15613 			}
15614 		}
15615 		IOLockUnlock(sKextSummariesLock);
15616 	}
15617 
15618 	return NULL;
15619 }
15620 
15621 /*
15622  * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t *
15623  * Safe to call in panic context.
15624  */
15625 static OSKextLoadedKextSummary *
15626 findSummary(uint32_t tagID)
15627 {
15628 	OSKextLoadedKextSummary * summary;
15629 	for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15630 		summary = gLoadedKextSummaries->summaries + i;
15631 		if (summary->loadTag == tagID) {
15632 			return summary;
15633 		}
15634 	}
15635 	return NULL;
15636 }
15637 
15638 /*********************************************************************
15639 * This function must be safe to call in panic context.
15640 *********************************************************************/
15641 void
15642 OSKext::printSummary(
15643 	OSKextLoadedKextSummary * summary,
15644 	int                    (* printf_func)(const char *fmt, ...),
15645 	uint32_t                  flags)
15646 {
15647 	kmod_reference_t * kmod_ref = NULL;
15648 	uuid_string_t uuid;
15649 	char version[kOSKextVersionMaxLength];
15650 	uint64_t tmpAddr;
15651 	uint64_t tmpSize;
15652 	OSKextLoadedKextSummary *dependencySummary;
15653 
15654 	if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
15655 		strlcpy(version, "unknown version", sizeof(version));
15656 	}
15657 	(void) uuid_unparse(summary->uuid, uuid);
15658 
15659 #if defined(__arm__) || defined(__arm64__)
15660 	tmpAddr = summary->text_exec_address;
15661 	tmpSize = summary->text_exec_size;
15662 #else
15663 	tmpAddr = summary->address;
15664 	tmpSize = summary->size;
15665 #endif
15666 	if (kPrintKextsUnslide & flags) {
15667 		tmpAddr = ml_static_unslide(tmpAddr);
15668 	}
15669 	(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
15670 	    (kPrintKextsTerse & flags) ? "" : "         ",
15671 	    summary->name, version, uuid,
15672 	    tmpAddr, tmpAddr + tmpSize - 1);
15673 
15674 	if (kPrintKextsTerse & flags) {
15675 		return;
15676 	}
15677 
15678 	/* print dependency info */
15679 	for (kmod_ref = (kmod_reference_t *) summary->reference_list;
15680 	    kmod_ref;
15681 	    kmod_ref = kmod_ref->next) {
15682 		kmod_info_t * rinfo;
15683 
15684 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
15685 			(*printf_func)("            kmod dependency scan stopped "
15686 			    "due to missing dependency page: %p\n",
15687 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
15688 			break;
15689 		}
15690 		rinfo = kmod_ref->info;
15691 
15692 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
15693 			(*printf_func)("            kmod dependency scan stopped "
15694 			    "due to missing kmod page: %p\n",
15695 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
15696 			break;
15697 		}
15698 
15699 		if (!rinfo->address) {
15700 			continue;         // skip fake entries for built-ins
15701 		}
15702 
15703 		dependencySummary = findSummary(rinfo->id);
15704 		uuid[0] = 0x00;
15705 		tmpAddr = rinfo->address;
15706 		tmpSize = rinfo->size;
15707 		if (dependencySummary) {
15708 			(void) uuid_unparse(dependencySummary->uuid, uuid);
15709 #if defined(__arm__) || defined(__arm64__)
15710 			tmpAddr = dependencySummary->text_exec_address;
15711 			tmpSize = dependencySummary->text_exec_size;
15712 #endif
15713 		}
15714 
15715 		if (kPrintKextsUnslide & flags) {
15716 			tmpAddr = ml_static_unslide(tmpAddr);
15717 		}
15718 		(*printf_func)("            dependency: %s(%s)[%s]@%p->%p\n",
15719 		    rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1);
15720 	}
15721 	return;
15722 }
15723 
15724 
15725 #if !defined(__arm__) && !defined(__arm64__)
15726 /*******************************************************************************
15727 * substitute() looks at an input string (a pointer within a larger buffer)
15728 * for a match to a substring, and on match it writes the marker & substitution
15729 * character to an output string, updating the scan (from) and
15730 * output (to) indexes as appropriate.
15731 *******************************************************************************/
15732 static int substitute(
15733 	const char * scan_string,
15734 	char       * string_out,
15735 	uint32_t   * to_index,
15736 	uint32_t   * from_index,
15737 	const char * substring,
15738 	char         marker,
15739 	char         substitution);
15740 
15741 /* string_out must be at least KMOD_MAX_NAME bytes.
15742  */
15743 static int
15744 substitute(
15745 	const char * scan_string,
15746 	char       * string_out,
15747 	uint32_t   * to_index,
15748 	uint32_t   * from_index,
15749 	const char * substring,
15750 	char         marker,
15751 	char         substitution)
15752 {
15753 	size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
15754 
15755 	/* On a substring match, append the marker (if there is one) and then
15756 	 * the substitution character, updating the output (to) index accordingly.
15757 	 * Then update the input (from) length by the length of the substring
15758 	 * that got replaced.
15759 	 */
15760 	if (!strncmp(scan_string, substring, substring_length)) {
15761 		if (marker) {
15762 			string_out[(*to_index)++] = marker;
15763 		}
15764 		string_out[(*to_index)++] = substitution;
15765 		(*from_index) += substring_length;
15766 		return 1;
15767 	}
15768 	return 0;
15769 }
15770 
15771 /*******************************************************************************
15772 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
15773 * KMOD_MAX_NAME characters and performs various substitutions of common
15774 * prefixes & substrings as defined by tables in kext_panic_report.h.
15775 *******************************************************************************/
15776 static void compactIdentifier(
15777 	const char * identifier,
15778 	char       * identifier_out,
15779 	char      ** identifier_out_end);
15780 
15781 static void
15782 compactIdentifier(
15783 	const char * identifier,
15784 	char       * identifier_out,
15785 	char      ** identifier_out_end)
15786 {
15787 	uint32_t       from_index, to_index;
15788 	uint32_t       scan_from_index = 0;
15789 	uint32_t       scan_to_index   = 0;
15790 	subs_entry_t * subs_entry    = NULL;
15791 	int            did_sub       = 0;
15792 
15793 	from_index = to_index = 0;
15794 	identifier_out[0] = '\0';
15795 
15796 	/* Replace certain identifier prefixes with shorter @+character sequences.
15797 	 * Check the return value of substitute() so we only replace the prefix.
15798 	 */
15799 	for (subs_entry = &kext_identifier_prefix_subs[0];
15800 	    subs_entry->substring && !did_sub;
15801 	    subs_entry++) {
15802 		did_sub = substitute(identifier, identifier_out,
15803 		    &scan_to_index, &scan_from_index,
15804 		    subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
15805 	}
15806 	did_sub = 0;
15807 
15808 	/* Now scan through the identifier looking for the common substrings
15809 	 * and replacing them with shorter !+character sequences via substitute().
15810 	 */
15811 	for (/* see above */;
15812 	    scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
15813 	    /* see loop */) {
15814 		const char   * scan_string = &identifier[scan_from_index];
15815 
15816 		did_sub = 0;
15817 
15818 		if (scan_from_index) {
15819 			for (subs_entry = &kext_identifier_substring_subs[0];
15820 			    subs_entry->substring && !did_sub;
15821 			    subs_entry++) {
15822 				did_sub = substitute(scan_string, identifier_out,
15823 				    &scan_to_index, &scan_from_index,
15824 				    subs_entry->substring, '!', subs_entry->substitute);
15825 			}
15826 		}
15827 
15828 		/* If we didn't substitute, copy the input character to the output.
15829 		 */
15830 		if (!did_sub) {
15831 			identifier_out[scan_to_index++] = identifier[scan_from_index++];
15832 		}
15833 	}
15834 
15835 	identifier_out[scan_to_index] = '\0';
15836 	if (identifier_out_end) {
15837 		*identifier_out_end = &identifier_out[scan_to_index];
15838 	}
15839 
15840 	return;
15841 }
15842 #endif /* !defined(__arm__) && !defined(__arm64__) */
15843 
15844 /*******************************************************************************
15845 * assemble_identifier_and_version() adds to a string buffer a compacted
15846 * bundle identifier followed by a version string.
15847 *******************************************************************************/
15848 
15849 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
15850  */
15851 static size_t assemble_identifier_and_version(
15852 	kmod_info_t * kmod_info,
15853 	char        * identPlusVers,
15854 	size_t        bufSize);
15855 
15856 static size_t
15857 assemble_identifier_and_version(
15858 	kmod_info_t * kmod_info,
15859 	char        * identPlusVers,
15860 	size_t        bufSize)
15861 {
15862 	size_t result = 0;
15863 
15864 #if defined(__arm__) || defined(__arm64__)
15865 	result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME);
15866 #else
15867 	compactIdentifier(kmod_info->name, identPlusVers, NULL);
15868 	result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
15869 #endif
15870 	identPlusVers[result++] = '\t';         // increment for real char
15871 	identPlusVers[result] = '\0';         // don't increment for nul char
15872 	result = strlcat(identPlusVers, kmod_info->version, bufSize);
15873 	if (result >= bufSize) {
15874 		identPlusVers[bufSize - 1] = '\0';
15875 		result = bufSize - 1;
15876 	}
15877 
15878 	return result;
15879 }
15880 
15881 /*******************************************************************************
15882 * Assumes sKextLock is held.
15883 *******************************************************************************/
15884 /* static */
15885 int
15886 OSKext::saveLoadedKextPanicListTyped(
15887 	const char * prefix,
15888 	int          invertFlag,
15889 	int          libsFlag,
15890 	char       * paniclist,
15891 	uint32_t     list_size)
15892 {
15893 	int             result = -1;
15894 	unsigned int    count, i;
15895 
15896 	count = sLoadedKexts->getCount();
15897 	if (!count) {
15898 		goto finish;
15899 	}
15900 
15901 	i = count - 1;
15902 	do {
15903 		OSObject    * rawKext = sLoadedKexts->getObject(i);
15904 		OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
15905 		int           match;
15906 		size_t        identPlusVersLength;
15907 		size_t        tempLen;
15908 		char          identPlusVers[2 * KMOD_MAX_NAME];
15909 
15910 		if (!rawKext) {
15911 			printf("OSKext::saveLoadedKextPanicListTyped - "
15912 			    "NULL kext in loaded kext list; continuing\n");
15913 			continue;
15914 		}
15915 
15916 		if (!theKext) {
15917 			printf("OSKext::saveLoadedKextPanicListTyped - "
15918 			    "Kext type cast failed in loaded kext list; continuing\n");
15919 			continue;
15920 		}
15921 
15922 		/* Skip all built-in kexts.
15923 		 */
15924 		if (theKext->isKernelComponent()) {
15925 			continue;
15926 		}
15927 
15928 		kmod_info_t * kmod_info = theKext->kmod_info;
15929 
15930 		/* Filter for kmod name (bundle identifier).
15931 		 */
15932 		match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
15933 		if ((match && invertFlag) || (!match && !invertFlag)) {
15934 			continue;
15935 		}
15936 
15937 		/* Filter for libraries (kexts that have a compatible version).
15938 		 */
15939 		if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
15940 		    (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
15941 			continue;
15942 		}
15943 
15944 		if (!kmod_info ||
15945 		    !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
15946 			printf("kext scan stopped due to missing kmod_info page: %p\n",
15947 			    kmod_info);
15948 			goto finish;
15949 		}
15950 
15951 		identPlusVersLength = assemble_identifier_and_version(kmod_info,
15952 		    identPlusVers,
15953 		    sizeof(identPlusVers));
15954 		if (!identPlusVersLength) {
15955 			printf("error saving loaded kext info\n");
15956 			goto finish;
15957 		}
15958 
15959 		/* make sure everything fits and we null terminate.
15960 		 */
15961 		tempLen = strlcat(paniclist, identPlusVers, list_size);
15962 		if (tempLen >= list_size) {
15963 			// panic list is full, keep it and null terminate
15964 			paniclist[list_size - 1] = 0x00;
15965 			result = 0;
15966 			goto finish;
15967 		}
15968 		tempLen = strlcat(paniclist, "\n", list_size);
15969 		if (tempLen >= list_size) {
15970 			// panic list is full, keep it and null terminate
15971 			paniclist[list_size - 1] = 0x00;
15972 			result = 0;
15973 			goto finish;
15974 		}
15975 	} while (i--);
15976 
15977 	result = 0;
15978 finish:
15979 
15980 	return result;
15981 }
15982 
15983 /*********************************************************************
15984 *********************************************************************/
15985 /* static */
15986 void
15987 OSKext::saveLoadedKextPanicList(void)
15988 {
15989 	char     * newlist        = NULL;
15990 	uint32_t   newlist_size   = 0;
15991 
15992 	newlist_size = KEXT_PANICLIST_SIZE;
15993 	newlist = (char *)kalloc_data_tag(newlist_size,
15994 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
15995 
15996 	if (!newlist) {
15997 		OSKextLog(/* kext */ NULL,
15998 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
15999 		    "Couldn't allocate kext panic log buffer.");
16000 		goto finish;
16001 	}
16002 
16003 	newlist[0] = '\0';
16004 
16005 	// non-"com.apple." kexts
16006 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
16007 	    /* libs? */ -1, newlist, newlist_size) != 0) {
16008 		goto finish;
16009 	}
16010 	// "com.apple." nonlibrary kexts
16011 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
16012 	    /* libs? */ 0, newlist, newlist_size) != 0) {
16013 		goto finish;
16014 	}
16015 	// "com.apple." library kexts
16016 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
16017 	    /* libs? */ 1, newlist, newlist_size) != 0) {
16018 		goto finish;
16019 	}
16020 
16021 	if (loaded_kext_paniclist) {
16022 		kfree_data(loaded_kext_paniclist, loaded_kext_paniclist_size);
16023 	}
16024 	loaded_kext_paniclist = newlist;
16025 	newlist = NULL;
16026 	loaded_kext_paniclist_size = newlist_size;
16027 
16028 finish:
16029 	if (newlist) {
16030 		kfree_data(newlist, newlist_size);
16031 	}
16032 	return;
16033 }
16034 
16035 /*********************************************************************
16036 * Assumes sKextLock is held.
16037 *********************************************************************/
16038 void
16039 OSKext::savePanicString(bool isLoading)
16040 {
16041 	u_long len;
16042 
16043 	if (!kmod_info) {
16044 		return;         // do not goto finish here b/c of lock
16045 	}
16046 
16047 	len = assemble_identifier_and_version( kmod_info,
16048 	    (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
16049 	    (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
16050 	if (!len) {
16051 		printf("error saving unloaded kext info\n");
16052 		goto finish;
16053 	}
16054 
16055 	if (isLoading) {
16056 		last_loaded_strlen = len;
16057 		last_loaded_address = (void *)kmod_info->address;
16058 		last_loaded_size = kmod_info->size;
16059 		clock_get_uptime(&last_loaded_timestamp);
16060 	} else {
16061 		last_unloaded_strlen = len;
16062 		last_unloaded_address = (void *)kmod_info->address;
16063 		last_unloaded_size = kmod_info->size;
16064 		clock_get_uptime(&last_unloaded_timestamp);
16065 	}
16066 
16067 finish:
16068 	return;
16069 }
16070 
16071 /*********************************************************************
16072 *********************************************************************/
16073 /* static */
16074 void
16075 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
16076 {
16077 	if (last_loaded_strlen) {
16078 		printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n",
16079 		    AbsoluteTime_to_scalar(&last_loaded_timestamp),
16080 		    last_loaded_strlen, last_loaded_str_buf,
16081 		    last_loaded_address, last_loaded_size);
16082 	}
16083 
16084 	if (last_unloaded_strlen) {
16085 		printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n",
16086 		    AbsoluteTime_to_scalar(&last_unloaded_timestamp),
16087 		    last_unloaded_strlen, last_unloaded_str_buf,
16088 		    last_unloaded_address, last_unloaded_size);
16089 	}
16090 
16091 	printf_func("loaded kexts:\n");
16092 	if (loaded_kext_paniclist &&
16093 	    pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
16094 	    loaded_kext_paniclist[0]) {
16095 		printf_func("%.*s",
16096 		    strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
16097 		    loaded_kext_paniclist);
16098 	} else {
16099 		printf_func("(none)\n");
16100 	}
16101 	return;
16102 }
16103 
16104 /*********************************************************************
16105 * Assumes sKextLock is held.
16106 *********************************************************************/
16107 /* static */
16108 void
16109 OSKext::updateLoadedKextSummaries(void)
16110 {
16111 	kern_return_t result = KERN_FAILURE;
16112 	OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
16113 	OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
16114 	OSKext *aKext;
16115 	vm_map_offset_t start, end;
16116 	size_t summarySize = 0;
16117 	size_t size;
16118 	u_int count;
16119 	u_int maxKexts;
16120 	u_int i, j;
16121 	OSKextActiveAccount * accountingList;
16122 	OSKextActiveAccount * prevAccountingList;
16123 	uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
16124 
16125 	prevAccountingList = NULL;
16126 	prevAccountingListCount = 0;
16127 
16128 #if DEVELOPMENT || DEBUG
16129 	if (IORecursiveLockHaveLock(sKextLock) == false) {
16130 		panic("sKextLock must be held");
16131 	}
16132 #endif
16133 
16134 	IOLockLock(sKextSummariesLock);
16135 
16136 	count = sLoadedKexts->getCount();
16137 	for (i = 0, maxKexts = 0; i < count; ++i) {
16138 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16139 		maxKexts += (aKext && aKext->isExecutable());
16140 	}
16141 
16142 	if (!maxKexts) {
16143 		goto finish;
16144 	}
16145 	if (maxKexts < kOSKextTypicalLoadCount) {
16146 		maxKexts = kOSKextTypicalLoadCount;
16147 	}
16148 
16149 	/* Calculate the size needed for the new summary headers.
16150 	 */
16151 
16152 	size = sizeof(*gLoadedKextSummaries);
16153 	size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
16154 	size = round_page(size);
16155 
16156 	if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
16157 		if (gLoadedKextSummaries) {
16158 			kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
16159 			gLoadedKextSummaries = NULL;
16160 			gLoadedKextSummariesTimestamp = mach_absolute_time();
16161 			sLoadedKextSummariesAllocSize = 0;
16162 		}
16163 		result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size,
16164 		    KMA_DATA, VM_KERN_MEMORY_OSKEXT);
16165 		if (result != KERN_SUCCESS) {
16166 			goto finish;
16167 		}
16168 		summaryHeader = summaryHeaderAlloc;
16169 		summarySize = size;
16170 	} else {
16171 		summaryHeader = gLoadedKextSummaries;
16172 		summarySize = sLoadedKextSummariesAllocSize;
16173 
16174 		start = (vm_map_offset_t) summaryHeader;
16175 		end = start + summarySize;
16176 		result = vm_map_protect(kernel_map,
16177 		    start,
16178 		    end,
16179 		    VM_PROT_DEFAULT,
16180 		    FALSE);
16181 		if (result != KERN_SUCCESS) {
16182 			goto finish;
16183 		}
16184 	}
16185 
16186 	/* Populate the summary header.
16187 	 */
16188 
16189 	bzero(summaryHeader, summarySize);
16190 	summaryHeader->version = kOSKextLoadedKextSummaryVersion;
16191 	summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
16192 
16193 	/* Populate each kext summary.
16194 	 */
16195 
16196 	count = sLoadedKexts->getCount();
16197 	accountingListAlloc = 0;
16198 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
16199 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16200 		if (!aKext || !aKext->isExecutable()) {
16201 			continue;
16202 		}
16203 
16204 		aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
16205 		summaryHeader->numSummaries++;
16206 		accountingListAlloc++;
16207 	}
16208 
16209 	accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
16210 	accountingListCount = 0;
16211 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
16212 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16213 		if (!aKext || !aKext->isExecutable()) {
16214 			continue;
16215 		}
16216 
16217 		OSKextActiveAccount activeAccount;
16218 		aKext->updateActiveAccount(&activeAccount);
16219 		// order by address
16220 		for (idx = 0; idx < accountingListCount; idx++) {
16221 			if (activeAccount.address < accountingList[idx].address) {
16222 				break;
16223 			}
16224 		}
16225 		bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
16226 		accountingList[idx] = activeAccount;
16227 		accountingListCount++;
16228 	}
16229 	assert(accountingListCount == accountingListAlloc);
16230 	/* Write protect the buffer and move it into place.
16231 	 */
16232 
16233 	start = (vm_map_offset_t) summaryHeader;
16234 	end = start + summarySize;
16235 
16236 	result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
16237 	if (result != KERN_SUCCESS) {
16238 		goto finish;
16239 	}
16240 
16241 	gLoadedKextSummaries = summaryHeader;
16242 	gLoadedKextSummariesTimestamp = mach_absolute_time();
16243 	sLoadedKextSummariesAllocSize = summarySize;
16244 	summaryHeaderAlloc = NULL;
16245 
16246 	/* Call the magic breakpoint function through a static function pointer so
16247 	 * the compiler can't optimize the function away.
16248 	 */
16249 	if (sLoadedKextSummariesUpdated) {
16250 		(*sLoadedKextSummariesUpdated)();
16251 	}
16252 
16253 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16254 	prevAccountingList      = sKextAccounts;
16255 	prevAccountingListCount = sKextAccountsCount;
16256 	sKextAccounts           = accountingList;
16257 	sKextAccountsCount      = accountingListCount;
16258 	lck_ticket_unlock(sKextAccountsLock);
16259 
16260 finish:
16261 	IOLockUnlock(sKextSummariesLock);
16262 
16263 	/* If we had to allocate a new buffer but failed to generate the summaries,
16264 	 * free that now.
16265 	 */
16266 	if (summaryHeaderAlloc) {
16267 		kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
16268 	}
16269 	if (prevAccountingList) {
16270 		IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
16271 	}
16272 
16273 	return;
16274 }
16275 
16276 /*********************************************************************
16277 *********************************************************************/
16278 void
16279 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
16280 {
16281 	OSSharedPtr<OSData> uuid;
16282 
16283 	strlcpy(summary->name, getIdentifierCString(),
16284 	    sizeof(summary->name));
16285 
16286 	uuid = copyUUID();
16287 	if (uuid) {
16288 		memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
16289 	}
16290 
16291 	if (flags.builtin) {
16292 //      this value will stop lldb from parsing the mach-o header
16293 //      summary->address = UINT64_MAX;
16294 //      summary->size = 0;
16295 		summary->address = kmod_info->address;
16296 		summary->size = kmod_info->size;
16297 	} else {
16298 		summary->address = kmod_info->address;
16299 		summary->size = kmod_info->size;
16300 	}
16301 	summary->version = getVersion();
16302 	summary->loadTag = kmod_info->id;
16303 	summary->flags = 0;
16304 	summary->reference_list = (uint64_t) kmod_info->reference_list;
16305 
16306 	summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size);
16307 	if (summary->text_exec_address == 0) {
16308 		// Fallback to __TEXT
16309 		summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size);
16310 	}
16311 	return;
16312 }
16313 
16314 /*********************************************************************
16315 *********************************************************************/
16316 
16317 void
16318 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
16319 {
16320 	kernel_mach_header_t     *hdr = NULL;
16321 	kernel_segment_command_t *seg = NULL;
16322 
16323 	bzero(accountp, sizeof(*accountp));
16324 
16325 	hdr = (kernel_mach_header_t *)kmod_info->address;
16326 	if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) {
16327 		/*
16328 		 * If this kext supports split segments (or is in a new
16329 		 * MH_FILESET kext collection), use the first
16330 		 * executable segment as the range for instructions
16331 		 * (and thus for backtracing.
16332 		 */
16333 		for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
16334 			if (seg->initprot & VM_PROT_EXECUTE) {
16335 				break;
16336 			}
16337 		}
16338 	}
16339 	if (seg) {
16340 		accountp->address = seg->vmaddr;
16341 		if (accountp->address) {
16342 			accountp->address_end = seg->vmaddr + seg->vmsize;
16343 		}
16344 	} else {
16345 		/* For non-split kexts and for kexts without executable
16346 		 * segments, just use the kmod_info range (as the kext
16347 		 * is either all in one range or should not show up in
16348 		 * instruction backtraces).
16349 		 */
16350 		accountp->address = kmod_info->address;
16351 		if (accountp->address) {
16352 			accountp->address_end = kmod_info->address + kmod_info->size;
16353 		}
16354 	}
16355 
16356 	accountp->account = this->account;
16357 }
16358 
16359 bool
16360 OSKext::isDriverKit(void)
16361 {
16362 	OSString *bundleType;
16363 
16364 	if (infoDict) {
16365 		bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
16366 		if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
16367 			return TRUE;
16368 		}
16369 	}
16370 	return FALSE;
16371 }
16372 
16373 bool
16374 OSKext::isInFileset(void)
16375 {
16376 	if (!kmod_info) {
16377 		goto check_prelinked;
16378 	}
16379 
16380 	if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) {
16381 		return true;
16382 	}
16383 
16384 check_prelinked:
16385 	if (isPrelinked()) {
16386 		/*
16387 		 * If we haven't setup kmod_info yet, but we know
16388 		 * we're loading a prelinked kext in an MH_FILESET KC,
16389 		 * then return true
16390 		 */
16391 		kc_format_t kc_format;
16392 		if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
16393 			return true;
16394 		}
16395 	}
16396 	return false;
16397 }
16398 
16399 OSSharedPtr<OSDextStatistics>
16400 OSKext::copyDextStatistics(void)
16401 {
16402 	return dextStatistics;
16403 }
16404 
16405 bool
16406 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg)
16407 {
16408 	kern_return_t result;
16409 	if (!super::init()) {
16410 		return false;
16411 	}
16412 	if (seg == nullptr) {
16413 		return false;
16414 	}
16415 	result = kmem_alloc(kernel_map, (vm_offset_t *)&data, seg->vmsize,
16416 	    KMA_PAGEABLE, VM_KERN_MEMORY_KEXT);
16417 	if (result != KERN_SUCCESS) {
16418 		return false;
16419 	}
16420 	memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize);
16421 	savedSegment = seg;
16422 	vmsize = seg->vmsize;
16423 	vmaddr = seg->vmaddr;
16424 	return true;
16425 }
16426 
16427 OSSharedPtr<OSKextSavedMutableSegment>
16428 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg)
16429 {
16430 	OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>();
16431 	if (me && !me->initWithSegment(seg)) {
16432 		return nullptr;
16433 	}
16434 	return me;
16435 }
16436 
16437 void
16438 OSKextSavedMutableSegment::free(void)
16439 {
16440 	if (data) {
16441 		kmem_free(kernel_map, (vm_offset_t)data, vmsize);
16442 	}
16443 }
16444 
16445 vm_offset_t
16446 OSKextSavedMutableSegment::getVMAddr() const
16447 {
16448 	return vmaddr;
16449 }
16450 
16451 vm_offset_t
16452 OSKextSavedMutableSegment::getVMSize() const
16453 {
16454 	return vmsize;
16455 }
16456 
16457 OSReturn
16458 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg)
16459 {
16460 	if (seg != savedSegment) {
16461 		return kOSKextReturnInvalidArgument;
16462 	}
16463 	if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) {
16464 		return kOSKextReturnInvalidArgument;
16465 	}
16466 	memcpy((void *)seg->vmaddr, data, vmsize);
16467 	return kOSReturnSuccess;
16468 }
16469 
16470 extern "C" kern_return_t
16471 OSKextSetReceiptQueried(void)
16472 {
16473 	OSKextLog(/* kext */ NULL,
16474 	    kOSKextLogStepLevel | kOSKextLogGeneralFlag,
16475 	    "Setting kext receipt as queried");
16476 
16477 	IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue);
16478 	return KERN_SUCCESS;
16479 }
16480 
16481 extern "C" const vm_allocation_site_t *
16482 OSKextGetAllocationSiteForCaller(uintptr_t address)
16483 {
16484 	OSKextActiveAccount *  active;
16485 	vm_allocation_site_t * site;
16486 	vm_allocation_site_t * releasesite;
16487 
16488 	uint32_t baseIdx;
16489 	uint32_t lim;
16490 #if  __has_feature(ptrauth_calls)
16491 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
16492 #endif /*  __has_feature(ptrauth_calls) */
16493 
16494 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16495 	site = releasesite = NULL;
16496 
16497 	// bsearch sKextAccounts list
16498 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
16499 		active = &sKextAccounts[baseIdx + (lim >> 1)];
16500 		if ((address >= active->address) && (address < active->address_end)) {
16501 			site = &active->account->site;
16502 			if (!site->tag) {
16503 				vm_tag_alloc_locked(site, &releasesite);
16504 			}
16505 			break;
16506 		} else if (address > active->address) {
16507 			// move right
16508 			baseIdx += (lim >> 1) + 1;
16509 			lim--;
16510 		}
16511 		// else move left
16512 	}
16513 	lck_ticket_unlock(sKextAccountsLock);
16514 	if (releasesite) {
16515 		kern_allocation_name_release(releasesite);
16516 	}
16517 
16518 	return site;
16519 }
16520 
16521 #if DEVELOPMENT || DEBUG
16522 extern "C" void
16523 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *))
16524 {
16525 	OSKextActiveAccount *  active;
16526 
16527 	uint32_t baseIdx;
16528 	uint32_t lim;
16529 #if  __has_feature(ptrauth_calls)
16530 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
16531 #endif /*  __has_feature(ptrauth_calls) */
16532 
16533 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16534 
16535 	// bsearch sKextAccounts list
16536 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
16537 		active = &sKextAccounts[baseIdx + (lim >> 1)];
16538 		if ((address >= active->address) && (address < active->address_end)) {
16539 			cb(&active->account->task_refgrp);
16540 			break;
16541 		} else if (address > active->address) {
16542 			// move right
16543 			baseIdx += (lim >> 1) + 1;
16544 			lim--;
16545 		}
16546 		// else move left
16547 	}
16548 	lck_ticket_unlock(sKextAccountsLock);
16549 }
16550 #endif /* DEVELOPMENT || DEBUG */
16551 
16552 extern "C" uint32_t
16553 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
16554 {
16555 	OSKextAccount * account = (typeof(account))site;
16556 	const char    * kname;
16557 
16558 	if (name) {
16559 		if (account->kext) {
16560 			kname = account->kext->getIdentifierCString();
16561 		} else {
16562 			kname = "<>";
16563 		}
16564 		strlcpy(name, kname, namelen);
16565 	}
16566 
16567 	return account->loadTag;
16568 }
16569 
16570 extern "C" void
16571 OSKextFreeSite(vm_allocation_site_t * site)
16572 {
16573 	OSKextAccount * freeAccount = (typeof(freeAccount))site;
16574 	IOFreeType(freeAccount, OSKextAccount);
16575 }
16576 
16577 /*********************************************************************
16578 *********************************************************************/
16579 
16580 #if CONFIG_IMAGEBOOT
16581 int
16582 OSKextGetUUIDForName(const char *name, uuid_t uuid)
16583 {
16584 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name);
16585 	if (!kext) {
16586 		return 1;
16587 	}
16588 
16589 	OSSharedPtr<OSData> uuid_data = kext->copyUUID();
16590 	if (uuid_data) {
16591 		memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
16592 		return 0;
16593 	}
16594 
16595 	return 1;
16596 }
16597 #endif
16598 
16599 
16600 
16601 class OSDextCrash : public OSObject {
16602 	OSDeclareDefaultStructors(OSDextCrash);
16603 public:
16604 	static OSPtr<OSDextCrash> withTimestamp(uint64_t timestamp);
16605 	uint64_t getTimestamp();
16606 
16607 private:
16608 	virtual bool initWithTimestamp(uint64_t timestamp);
16609 	uint64_t fTimestamp;
16610 };
16611 
16612 OSDefineMetaClassAndStructors(OSDextCrash, OSObject);
16613 
16614 OSSharedPtr<OSDextCrash>
16615 OSDextCrash::withTimestamp(uint64_t timestamp)
16616 {
16617 	OSSharedPtr<OSDextCrash> result = OSMakeShared<OSDextCrash>();
16618 	if (!result->initWithTimestamp(timestamp)) {
16619 		return NULL;
16620 	}
16621 	return result;
16622 }
16623 
16624 bool
16625 OSDextCrash::initWithTimestamp(uint64_t timestamp)
16626 {
16627 	if (!OSObject::init()) {
16628 		return false;
16629 	}
16630 	fTimestamp = timestamp;
16631 	return true;
16632 }
16633 
16634 uint64_t
16635 OSDextCrash::getTimestamp()
16636 {
16637 	return fTimestamp;
16638 }
16639 
16640 OSSharedPtr<OSDextStatistics>
16641 OSDextStatistics::create()
16642 {
16643 	OSSharedPtr<OSDextStatistics> result = OSMakeShared<OSDextStatistics>();
16644 	if (!result->init()) {
16645 		return NULL;
16646 	}
16647 	return result;
16648 }
16649 
16650 bool
16651 OSDextStatistics::init()
16652 {
16653 	if (!OSObject::init()) {
16654 		return false;
16655 	}
16656 
16657 	lock = IOLockAlloc();
16658 	crashes = OSArray::withCapacity(kMaxDextCrashesInOneDay);
16659 	return true;
16660 }
16661 
16662 void
16663 OSDextStatistics::free()
16664 {
16665 	if (lock) {
16666 		IOLockFree(lock);
16667 	}
16668 	crashes.reset();
16669 	OSObject::free();
16670 }
16671 
16672 OSDextCrashPolicy
16673 OSDextStatistics::recordCrash()
16674 {
16675 	size_t i = 0;
16676 	uint64_t timestamp = mach_continuous_time();
16677 	uint64_t interval;
16678 	nanoseconds_to_absolutetime(86400 * NSEC_PER_SEC /* 1 day */, &interval);
16679 	uint64_t lastTimestamp = timestamp > interval ? timestamp - interval : 0;
16680 	OSDextCrashPolicy policy;
16681 
16682 	IOLockLock(lock);
16683 	OSSharedPtr<OSDextCrash> crash = OSDextCrash::withTimestamp(timestamp);
16684 	for (i = 0; i < crashes->getCount();) {
16685 		OSDextCrash * current = OSDynamicCast(OSDextCrash, crashes->getObject(i));
16686 		assert(current != NULL);
16687 		if (current->getTimestamp() < lastTimestamp) {
16688 			crashes->removeObject(i);
16689 		} else {
16690 			i++;
16691 		}
16692 	}
16693 
16694 	crashes->setObject(crash);
16695 
16696 	if (crashes->getCount() > kMaxDextCrashesInOneDay) {
16697 		policy = kOSDextCrashPolicyReboot;
16698 	} else {
16699 		policy = kOSDextCrashPolicyNone;
16700 	}
16701 
16702 	IOLockUnlock(lock);
16703 
16704 	return policy;
16705 }
16706 
16707 size_t
16708 OSDextStatistics::getCrashCount()
16709 {
16710 	size_t result = 0;
16711 	IOLockLock(lock);
16712 	result = crashes->getCount();
16713 	IOLockUnlock(lock);
16714 	return result;
16715 }
16716 
16717 static int
16718 sysctl_willuserspacereboot
16719 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
16720 {
16721 	int new_value = 0, old_value = 0, changed = 0;
16722 	int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
16723 	if (error) {
16724 		return error;
16725 	}
16726 	if (changed) {
16727 		OSKext::willUserspaceReboot();
16728 	}
16729 	return 0;
16730 }
16731 
16732 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot,
16733     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
16734     NULL, 0, sysctl_willuserspacereboot, "I", "");
16735