xref: /xnu-8020.140.41/libkern/c++/OSKext.cpp (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
1 /*
2  * Copyright (c) 2008-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #define IOKIT_ENABLE_SHARED_PTR
30 
31 extern "C" {
32 #include <string.h>
33 #include <kern/clock.h>
34 #include <kern/host.h>
35 #include <kern/kext_alloc.h>
36 #include <firehose/tracepoint_private.h>
37 #include <firehose/chunk_private.h>
38 #include <os/firehose_buffer_private.h>
39 #include <vm/vm_map.h>
40 #include <kextd/kextd_mach.h>
41 #include <libkern/kernel_mach_header.h>
42 #include <libkern/kext_panic_report.h>
43 #include <libkern/kext_request_keys.h>
44 #include <libkern/mkext.h>
45 #include <libkern/prelink.h>
46 #include <libkern/version.h>
47 #include <libkern/zlib.h>
48 #include <mach/host_special_ports.h>
49 #include <mach/mach_vm.h>
50 #include <mach/mach_time.h>
51 #include <uuid/uuid.h>
52 #include <sys/random.h>
53 #include <pexpert/pexpert.h>
54 
55 #include <sys/pgo.h>
56 
57 #if CONFIG_CSR
58 #include <sys/csr.h>
59 #include <sys/stat.h>
60 #include <sys/vnode.h>
61 #endif /* CONFIG_CSR */
62 };
63 
64 #if CONFIG_MACF
65 #include <sys/kauth.h>
66 #include <security/mac_framework.h>
67 #endif
68 
69 #include <vm/vm_kern.h>
70 #include <sys/sysctl.h>
71 #include <kern/task.h>
72 #include <os/cpp_util.h>
73 
74 #include <libkern/OSKextLibPrivate.h>
75 #include <libkern/c++/OSKext.h>
76 #include <libkern/c++/OSLib.h>
77 
78 #include <IOKit/IOLib.h>
79 #include <IOKit/IOCatalogue.h>
80 #include <IOKit/IORegistryEntry.h>
81 #include <IOKit/IOService.h>
82 #include <IOKit/IOUserServer.h>
83 
84 #include <IOKit/IOStatisticsPrivate.h>
85 #include <IOKit/IOBSD.h>
86 #include <IOKit/IOPlatformExpert.h>
87 
88 #include <san/kasan.h>
89 
90 #if PRAGMA_MARK
91 #pragma mark External & Internal Function Protos
92 #endif
93 /*********************************************************************
94 *********************************************************************/
95 extern "C" {
96 extern int  IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
97 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
98 
99 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
100 extern int dtrace_keep_kernel_symbols(void);
101 
102 #if defined(__x86_64__) || defined(__i386__)
103 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide);
104 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers);
105 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size);
106 static void *allocate_kcfileset_map_entry_list(void);
107 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size);
108 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable);
109 int vnode_put(struct vnode *vp);
110 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size,
111     void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot);
112 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size);
113 void * ubc_getobject(struct vnode *vp, __unused int flags);
114 #endif //(__x86_64__) || defined(__i386__)
115 }
116 
117 extern unsigned long gVirtBase;
118 extern unsigned long gPhysBase;
119 extern vm_map_t g_kext_map;
120 
121 bool pageableKCloaded = false;
122 bool auxKCloaded = false;
123 bool resetAuxKCSegmentOnUnload = false;
124 
125 extern boolean_t pageablekc_uuid_valid;
126 extern uuid_t pageablekc_uuid;
127 extern uuid_string_t pageablekc_uuid_string;
128 
129 extern boolean_t auxkc_uuid_valid;
130 extern uuid_t auxkc_uuid;
131 extern uuid_string_t auxkc_uuid_string;
132 
133 static OSReturn _OSKextCreateRequest(
134 	const char    * predicate,
135 	OSSharedPtr<OSDictionary> & requestP);
136 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
137 static OSObject * _OSKextGetRequestArgument(
138 	OSDictionary * requestDict,
139 	const char   * argName);
140 static bool _OSKextSetRequestArgument(
141 	OSDictionary    * requestDict,
142 	const char      * argName,
143 	OSMetaClassBase * value);
144 template <typename T>
145 static T * _OSKextExtractPointer(OSValueObject<T *> * wrapper);
146 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper);
147 static OSReturn _OSDictionarySetCStringValue(
148 	OSDictionary * dict,
149 	const char   * key,
150 	const char   * value);
151 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
152 #if CONFIG_KXLD
153 static bool _OSKextInPrelinkRebuildWindow(void);
154 #endif
155 
156 // We really should add containsObject() & containsCString to OSCollection & subclasses.
157 // So few pad slots, though....
158 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
159 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
160 
161 /* Prelinked arm kexts do not have VM entries because the method we use to
162  * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
163  * not work on ARM.  To get around that, we must free prelinked kext
164  * executables with ml_static_mfree() instead of kext_free().
165  */
166 #if __i386__ || __x86_64__
167 #define VM_MAPPED_KEXTS 1
168 #define KASLR_KEXT_DEBUG 0
169 #define KASLR_IOREG_DEBUG 0
170 #elif __arm__ || __arm64__
171 #define VM_MAPPED_KEXTS 0
172 #define KASLR_KEXT_DEBUG 0
173 #else
174 #error Unsupported architecture
175 #endif
176 
177 #if PRAGMA_MARK
178 #pragma mark Constants & Macros
179 #endif
180 /*********************************************************************
181 * Constants & Macros
182 *********************************************************************/
183 
184 /* Use this number to create containers.
185  */
186 #define kOSKextTypicalLoadCount      (150)
187 
188 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
189  * A loaded kext will no dependents or external retains will have 2 retains.
190  */
191 #define kOSKextMinRetainCount        (1)
192 #define kOSKextMinLoadedRetainCount  (2)
193 
194 /**********
195  * Strings and substrings used in dependency resolution.
196  */
197 #define APPLE_KEXT_PREFIX            "com.apple."
198 #define KERNEL_LIB                   "com.apple.kernel"
199 
200 #define PRIVATE_KPI                  "com.apple.kpi.private"
201 
202 /* Version for compatbility pseudokexts (com.apple.kernel.*),
203  * compatible back to v6.0.
204  */
205 #define KERNEL6_LIB                  "com.apple.kernel.6.0"
206 #define KERNEL6_VERSION              "7.9.9"
207 
208 #define KERNEL_LIB_PREFIX            "com.apple.kernel."
209 #define KPI_LIB_PREFIX               "com.apple.kpi."
210 
211 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0)
212 
213 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
214 #define MINIMUM_WAKEUP_SECONDS (30)
215 
216 /*********************************************************************
217 * infoDict keys for internally-stored data. Saves on ivar slots for
218 * objects we don't keep around past boot time or during active load.
219 *********************************************************************/
220 
221 /* A usable, uncompressed file is stored under this key.
222  */
223 #define _kOSKextExecutableKey                "_OSKextExecutable"
224 
225 /* An indirect reference to the executable file from an mkext
226  * is stored under this key.
227  */
228 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference"
229 
230 /* If the file is contained in a larger buffer laid down by the booter or
231  * sent from user space, the OSKext stores that OSData under this key so that
232  * references are properly tracked. This is always an mkext, right now.
233  */
234 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData"
235 
236 #define OS_LOG_HDR_VERSION  1
237 #define NUM_OS_LOG_SECTIONS 3
238 
239 #define OS_LOG_SECT_IDX         0
240 #define CSTRING_SECT_IDX        1
241 #define ASAN_CSTRING_SECT_IDX   2
242 
243 #if PRAGMA_MARK
244 #pragma mark Typedefs
245 #endif
246 /*********************************************************************
247 * Typedefs
248 *********************************************************************/
249 
250 /*********************************************************************
251 * osLogDataHeaderRef describes the header information of an OSData
252 * object that is returned when querying for kOSBundleLogStringsKey.
253 * We currently return information regarding 2 sections - os_log and
254 * cstring. In the case that the os_log section doesn't exist, we just
255 * return an offset and length of 0 for that section.
256 *********************************************************************/
257 typedef struct osLogDataHeader {
258 	uint32_t version;
259 	uint32_t sect_count;
260 	struct {
261 		uint32_t sect_offset;
262 		uint32_t sect_size;
263 	} sections[0];
264 } osLogDataHeaderRef;
265 
266 /*********************************************************************
267 * MkextEntryRef describes the contents of an OSData object
268 * referencing a file entry from an mkext so that we can uncompress
269 * (if necessary) and extract it on demand.
270 *
271 * It contains the mkextVersion in case we ever wind up supporting
272 * multiple mkext formats. Mkext format 1 is officially retired as of
273 * Snow Leopard.
274 *********************************************************************/
275 typedef struct MkextEntryRef {
276 	mkext_basic_header * mkext; // beginning of whole mkext file
277 	void               * fileinfo;// mkext2_file_entry or equiv; see mkext.h
278 } MkextEntryRef;
279 
280 #if PRAGMA_MARK
281 #pragma mark Global and static Module Variables
282 #endif
283 /*********************************************************************
284 * Global & static variables, used to keep track of kexts.
285 *********************************************************************/
286 
287 static  bool                sPrelinkBoot               = false;
288 static  bool                sSafeBoot                  = false;
289 static  bool                sKeepSymbols               = false;
290 static  bool                sPanicOnKCMismatch         = false;
291 static  bool                sOSKextWasResetAfterUserspaceReboot = false;
292 
293 /*********************************************************************
294  * sKextLock is the principal lock for OSKext, and guards all static
295  * and global variables not owned by other locks (declared further
296  * below). It must be taken by any entry-point method or function,
297  * including internal functions called on scheduled threads.
298  *
299  * sKextLock and sKextInnerLock are recursive due to multiple functions
300  * that are called both externally and internally. The other locks are
301  * nonrecursive.
302  *
303  * Which locks are taken depends on what they protect, but if more than
304  * one must be taken, they must always be locked in this order
305  * (and unlocked in reverse order) to prevent deadlocks:
306  *
307  *    1. sKextLock
308  *    2. sKextInnerLock
309  *    3. sKextSummariesLock
310  *    4. sKextLoggingLock
311  */
312 static IORecursiveLock    * sKextLock                  = NULL;
313 
314 static OSSharedPtr<OSDictionary>   sKextsByID;
315 static OSSharedPtr<OSDictionary>   sExcludeListByID;
316 static OSKextVersion               sExcludeListVersion        = 0;
317 static OSSharedPtr<OSArray>        sLoadedKexts;
318 static OSSharedPtr<OSDictionary>   sNonLoadableKextsByID;
319 static OSSharedPtr<OSArray>        sUnloadedPrelinkedKexts;
320 static OSSharedPtr<OSArray>        sLoadedDriverKitKexts;
321 
322 // Requests to the IOKit daemon waiting to be picked up.
323 static OSSharedPtr<OSArray>        sKernelRequests;
324 // Identifier of kext load requests in sKernelRequests
325 static OSSharedPtr<OSSet>          sPostedKextLoadIdentifiers;
326 static OSSharedPtr<OSArray>        sRequestCallbackRecords;
327 
328 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
329 static OSSharedPtr<OSSet>          sAllKextLoadIdentifiers;
330 #if CONFIG_KXLD
331 static KXLDContext        * sKxldContext               = NULL;
332 #endif
333 static uint32_t             sNextLoadTag               = 0;
334 static uint32_t             sNextRequestTag            = 0;
335 
336 static bool                 sUserLoadsActive           = false;
337 static bool                 sIOKitDaemonActive         = false;
338 static bool                 sDeferredLoadSucceeded     = false;
339 static bool                 sConsiderUnloadsExecuted   = false;
340 
341 #if NO_KEXTD
342 static bool                 sKernelRequestsEnabled     = false;
343 #else
344 static bool                 sKernelRequestsEnabled     = true;
345 #endif
346 static bool                 sLoadEnabled               = true;
347 static bool                 sUnloadEnabled             = true;
348 
349 /*********************************************************************
350  * Stuff for the OSKext representing the kernel itself.
351  **********/
352 static OSKext          * sKernelKext             = NULL;
353 
354 /* Set up a fake kmod_info struct for the kernel.
355  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
356  * before OSKext is initialized; that call only needs the name
357  * and address to be set correctly.
358  *
359  * We don't do much else with the kerne's kmod_info; we never
360  * put it into the kmod list, never adjust the reference count,
361  * and never have kernel components reference it.
362  * For that matter, we don't do much with kmod_info structs
363  * at all anymore! We just keep them filled in for gdb and
364  * binary compability.
365  */
366 kmod_info_t g_kernel_kmod_info = {
367 	.next =            NULL,
368 	.info_version =    KMOD_INFO_VERSION,
369 	.id =              0,             // loadTag: kernel is always 0
370 	.name =            kOSKextKernelIdentifier,// bundle identifier
371 	.version =         "0",           // filled in in OSKext::initialize()
372 	.reference_count = -1,            // never adjusted; kernel never unloads
373 	.reference_list =  NULL,
374 	.address =         0,
375 	.size =            0,             // filled in in OSKext::initialize()
376 	.hdr_size =        0,
377 	.start =           NULL,
378 	.stop =            NULL
379 };
380 
381 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
382 
383 kmod_info_t invalid_kmod_info = {
384 	.next =            NULL,
385 	.info_version =    KMOD_INFO_VERSION,
386 	.id =              UINT32_MAX,
387 	.name =            "invalid",
388 	.version =         "0",
389 	.reference_count = -1,
390 	.reference_list =  NULL,
391 	.address =         0,
392 	.size =            0,
393 	.hdr_size =        0,
394 	.start =           NULL,
395 	.stop =            NULL
396 };
397 
398 extern "C" {
399 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
400 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
401 // misc_protos.h, db_low_trace.c, kgmacros
402 // 'kmod' is a holdover from the old kmod system, we can't rename it.
403 kmod_info_t * kmod = NULL;
404 
405 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE)
406 
407 
408 static char     * loaded_kext_paniclist         = NULL;
409 static uint32_t   loaded_kext_paniclist_size    = 0;
410 
411 AbsoluteTime      last_loaded_timestamp;
412 static char       last_loaded_str_buf[2 * KMOD_MAX_NAME];
413 static u_long     last_loaded_strlen            = 0;
414 static void     * last_loaded_address           = NULL;
415 static u_long     last_loaded_size              = 0;
416 
417 AbsoluteTime      last_unloaded_timestamp;
418 static char       last_unloaded_str_buf[2 * KMOD_MAX_NAME];
419 static u_long     last_unloaded_strlen          = 0;
420 static void     * last_unloaded_address         = NULL;
421 static u_long     last_unloaded_size            = 0;
422 
423 // Statically linked kmods described by several mach-o sections:
424 //
425 // kPrelinkInfoSegment:kBuiltinInfoSection
426 // Array of pointers to kmod_info_t structs.
427 //
428 // kPrelinkInfoSegment:kBuiltinInfoSection
429 // Array of pointers to an embedded mach-o header.
430 //
431 // __DATA:kBuiltinInitSection, kBuiltinTermSection
432 // Structors for all kmods. Has to be filtered by proc address.
433 //
434 
435 static uint32_t gBuiltinKmodsCount;
436 static kernel_section_t * gBuiltinKmodsSectionInfo;
437 static kernel_section_t * gBuiltinKmodsSectionStart;
438 
439 const OSSymbol              * gIOSurfaceIdentifier;
440 vm_tag_t                      gIOSurfaceTag;
441 
442 /*********************************************************************
443  * sKextInnerLock protects against cross-calls with IOService and
444  * IOCatalogue, and owns the variables declared immediately below.
445  *
446  * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
447  *
448  * When both sKextLock and sKextInnerLock need to be taken,
449  * always lock sKextLock first and unlock it second. Never take both
450  * locks in an entry point to OSKext; if you need to do so, you must
451  * spawn an independent thread to avoid potential deadlocks for threads
452  * calling into OSKext.
453  **********/
454 static IORecursiveLock *    sKextInnerLock             = NULL;
455 
456 #if XNU_TARGET_OS_OSX
457 static bool                 sAutounloadEnabled         = true;
458 #endif
459 static bool                 sConsiderUnloadsCalled     = false;
460 static bool                 sConsiderUnloadsPending    = false;
461 
462 static unsigned int         sConsiderUnloadDelay       = 60;     // seconds
463 static thread_call_t        sUnloadCallout             = NULL;
464 #if CONFIG_KXLD
465 static thread_call_t        sDestroyLinkContextThread  = NULL;   // one-shot, one-at-a-time thread
466 #endif // CONFIG_KXLD
467 static bool                 sSystemSleep               = false;  // true when system going to sleep
468 static AbsoluteTime         sLastWakeTime;                       // last time we woke up
469 
470 /*********************************************************************
471  * Backtraces can be printed at various times so we need a tight lock
472  * on data used for that. sKextSummariesLock protects the variables
473  * declared immediately below.
474  *
475  * gLoadedKextSummaries is accessed by other modules, but only during
476  * a panic so the lock isn't needed then.
477  *
478  * gLoadedKextSummaries has the "used" attribute in order to ensure
479  * that it remains visible even when we are performing extremely
480  * aggressive optimizations, as it is needed to allow the debugger
481  * to automatically parse the list of loaded kexts.
482  **********/
483 static IOLock                 * sKextSummariesLock                = NULL;
484 extern "C" lck_spin_t           vm_allocation_sites_lock;
485 static IOSimpleLock           * sKextAccountsLock = &vm_allocation_sites_lock;
486 
487 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
488 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
489 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
490 static size_t sLoadedKextSummariesAllocSize = 0;
491 
492 static OSKextActiveAccount    * sKextAccounts;
493 static uint32_t                 sKextAccountsCount;
494 };
495 
496 /*********************************************************************
497  * sKextLoggingLock protects the logging variables declared immediately below.
498  **********/
499 static IOLock                 * sKextLoggingLock           = NULL;
500 
501 static  const OSKextLogSpec     kDefaultKernelLogFilter    = kOSKextLogBasicLevel |
502     kOSKextLogVerboseFlagsMask;
503 static  OSKextLogSpec           sKernelLogFilter           = kDefaultKernelLogFilter;
504 static  bool                    sBootArgLogFilterFound     = false;
505 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
506     0, "kernel kext logging");
507 
508 static  OSKextLogSpec           sUserSpaceKextLogFilter    = kOSKextLogSilentFilter;
509 static  OSSharedPtr<OSArray>    sUserSpaceLogSpecArray;
510 static  OSSharedPtr<OSArray>    sUserSpaceLogMessageArray;
511 
512 /*********
513  * End scope for sKextInnerLock-protected variables.
514  *********************************************************************/
515 
516 
517 /*********************************************************************
518  *  helper function used for collecting PGO data upon unload of a kext
519  */
520 
521 static int OSKextGrabPgoDataLocked(OSKext *kext,
522     bool metadata,
523     uuid_t instance_uuid,
524     uint64_t *pSize,
525     char *pBuffer,
526     uint64_t bufferSize);
527 
528 /**********************************************************************/
529 
530 
531 
532 #if PRAGMA_MARK
533 #pragma mark OSData callbacks (need to move to OSData)
534 #endif
535 /*********************************************************************
536 * C functions used for callbacks.
537 *********************************************************************/
538 extern "C" {
539 void
osdata_kmem_free(void * ptr,unsigned int length)540 osdata_kmem_free(void * ptr, unsigned int length)
541 {
542 	kmem_free(kernel_map, (vm_address_t)ptr, length);
543 	return;
544 }
545 
546 void
osdata_phys_free(void * ptr,unsigned int length)547 osdata_phys_free(void * ptr, unsigned int length)
548 {
549 	ml_static_mfree((vm_offset_t)ptr, length);
550 	return;
551 }
552 
553 void
osdata_vm_deallocate(void * ptr,unsigned int length)554 osdata_vm_deallocate(void * ptr, unsigned int length)
555 {
556 	(void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
557 	return;
558 }
559 
560 void
osdata_kext_free(void * ptr,unsigned int length)561 osdata_kext_free(void * ptr, unsigned int length)
562 {
563 	(void)kext_free((vm_offset_t)ptr, length);
564 }
565 };
566 
567 #if PRAGMA_MARK
568 #pragma mark KXLD Allocation Callback
569 #endif
570 #if CONFIG_KXLD
571 /*********************************************************************
572 * KXLD Allocation Callback
573 *********************************************************************/
574 kxld_addr_t
kern_allocate(u_long size,KXLDAllocateFlags * flags,void * user_data)575 kern_allocate(
576 	u_long              size,
577 	KXLDAllocateFlags * flags,
578 	void              * user_data)
579 {
580 	vm_address_t  result       = 0; // returned
581 	kern_return_t mach_result  = KERN_FAILURE;
582 	bool          success      = false;
583 	OSKext      * theKext      = (OSKext *)user_data;
584 	unsigned int  roundSize    = 0;
585 	OSSharedPtr<OSData>      linkBuffer;
586 
587 	if (round_page(size) > UINT_MAX) {
588 		OSKextLog(theKext,
589 		    kOSKextLogErrorLevel |
590 		    kOSKextLogGeneralFlag,
591 		    "%s: Requested memory size is greater than UINT_MAX.",
592 		    theKext->getIdentifierCString());
593 		goto finish;
594 	}
595 
596 	roundSize = (unsigned int)round_page(size);
597 
598 	mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
599 	if (mach_result != KERN_SUCCESS) {
600 		OSKextLog(theKext,
601 		    kOSKextLogErrorLevel |
602 		    kOSKextLogGeneralFlag,
603 		    "Can't allocate kernel memory to link %s.",
604 		    theKext->getIdentifierCString());
605 		goto finish;
606 	}
607 
608 	/* Create an OSData wrapper for the allocated buffer.
609 	 */
610 	linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
611 	if (!linkBuffer) {
612 		OSKextLog(theKext,
613 		    kOSKextLogErrorLevel |
614 		    kOSKextLogGeneralFlag,
615 		    "Can't allocate linked executable wrapper for %s.",
616 		    theKext->getIdentifierCString());
617 		goto finish;
618 	}
619 	linkBuffer->setDeallocFunction(osdata_kext_free);
620 	OSKextLog(theKext,
621 	    kOSKextLogProgressLevel |
622 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
623 	    "Allocated link buffer for kext %s at %p (%lu bytes).",
624 	    theKext->getIdentifierCString(),
625 	    (void *)result, (unsigned long)roundSize);
626 
627 	theKext->setLinkedExecutable(linkBuffer.get());
628 
629 	*flags = kKxldAllocateWritable;
630 	success = true;
631 
632 finish:
633 	if (!success && result) {
634 		kext_free(result, roundSize);
635 		result = 0;
636 	}
637 
638 	return (kxld_addr_t)result;
639 }
640 
641 /*********************************************************************
642 *********************************************************************/
643 void
kxld_log_callback(KXLDLogSubsystem subsystem,KXLDLogLevel level,const char * format,va_list argList,void * user_data)644 kxld_log_callback(
645 	KXLDLogSubsystem    subsystem,
646 	KXLDLogLevel        level,
647 	const char        * format,
648 	va_list             argList,
649 	void              * user_data)
650 {
651 	OSKext *theKext = (OSKext *) user_data;
652 	OSKextLogSpec logSpec = 0;
653 
654 	switch (subsystem) {
655 	case kKxldLogLinking:
656 		logSpec |= kOSKextLogLinkFlag;
657 		break;
658 	case kKxldLogPatching:
659 		logSpec |= kOSKextLogPatchFlag;
660 		break;
661 	}
662 
663 	switch (level) {
664 	case kKxldLogExplicit:
665 		logSpec |= kOSKextLogExplicitLevel;
666 		break;
667 	case kKxldLogErr:
668 		logSpec |= kOSKextLogErrorLevel;
669 		break;
670 	case kKxldLogWarn:
671 		logSpec |= kOSKextLogWarningLevel;
672 		break;
673 	case kKxldLogBasic:
674 		logSpec |= kOSKextLogProgressLevel;
675 		break;
676 	case kKxldLogDetail:
677 		logSpec |= kOSKextLogDetailLevel;
678 		break;
679 	case kKxldLogDebug:
680 		logSpec |= kOSKextLogDebugLevel;
681 		break;
682 	}
683 
684 	OSKextVLog(theKext, logSpec, format, argList);
685 }
686 #endif // CONFIG_KXLD
687 
688 #if PRAGMA_MARK
689 #pragma mark IOStatistics defines
690 #endif
691 
692 #if IOKITSTATS
693 
694 #define notifyKextLoadObservers(kext, kmod_info) \
695 do { \
696     IOStatistics::onKextLoad(kext, kmod_info); \
697 } while (0)
698 
699 #define notifyKextUnloadObservers(kext) \
700 do { \
701     IOStatistics::onKextUnload(kext); \
702 } while (0)
703 
704 #define notifyAddClassObservers(kext, addedClass, flags) \
705 do { \
706     IOStatistics::onClassAdded(kext, addedClass); \
707 } while (0)
708 
709 #define notifyRemoveClassObservers(kext, removedClass, flags) \
710 do { \
711     IOStatistics::onClassRemoved(kext, removedClass); \
712 } while (0)
713 
714 #else
715 
716 #define notifyKextLoadObservers(kext, kmod_info)
717 #define notifyKextUnloadObservers(kext)
718 #define notifyAddClassObservers(kext, addedClass, flags)
719 #define notifyRemoveClassObservers(kext, removedClass, flags)
720 
721 #endif /* IOKITSTATS */
722 
723 #if PRAGMA_MARK
724 #pragma mark Module Config (Startup & Shutdown)
725 #endif
726 /*********************************************************************
727 * Module Config (Class Definition & Class Methods)
728 *********************************************************************/
729 #define super OSObject
730 OSDefineMetaClassAndStructors(OSKext, OSObject)
731 
732 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject);
733 
734 /*********************************************************************
735 *********************************************************************/
736 /* static */
737 void
initialize(void)738 OSKext::initialize(void)
739 {
740 	OSSharedPtr<OSData>     kernelExecutable   = NULL;// do not release
741 	u_char          * kernelStart        = NULL;// do not free
742 	size_t            kernelLength       = 0;
743 	IORegistryEntry * registryRoot       = NULL;// do not release
744 	OSSharedPtr<OSNumber> kernelCPUType;
745 	OSSharedPtr<OSNumber> kernelCPUSubtype;
746 	OSKextLogSpec     bootLogFilter      = kOSKextLogSilentFilter;
747 	bool              setResult          = false;
748 	uint64_t        * timestamp          = NULL;
749 	__unused char     bootArgBuffer[16];// for PE_parse_boot_argn w/strings
750 
751 	/* This must be the first thing allocated. Everything else grabs this lock.
752 	 */
753 	sKextLock = IORecursiveLockAlloc();
754 	sKextInnerLock = IORecursiveLockAlloc();
755 	sKextSummariesLock = IOLockAlloc();
756 	sKextLoggingLock = IOLockAlloc();
757 	assert(sKextLock);
758 	assert(sKextInnerLock);
759 	assert(sKextSummariesLock);
760 	assert(sKextLoggingLock);
761 
762 	sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
763 	sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
764 	sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
765 	sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
766 	sKernelRequests = OSArray::withCapacity(0);
767 	sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
768 	sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
769 	sRequestCallbackRecords = OSArray::withCapacity(0);
770 	assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
771 	    sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
772 	    sRequestCallbackRecords && sUnloadedPrelinkedKexts);
773 
774 	/* Read the log flag boot-args and set the log flags.
775 	 */
776 	if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
777 		sBootArgLogFilterFound = true;
778 		sKernelLogFilter = bootLogFilter;
779 		// log this if any flags are set
780 		OSKextLog(/* kext */ NULL,
781 		    kOSKextLogBasicLevel |
782 		    kOSKextLogFlagsMask,
783 		    "Kernel kext log filter 0x%x per kextlog boot arg.",
784 		    (unsigned)sKernelLogFilter);
785 	}
786 
787 #if !defined(__arm__) && !defined(__arm64__)
788 	/*
789 	 * On our ARM targets, the kernelcache/boot kernel collection contains
790 	 * the set of kexts required to boot, as specified by KCB.  Safeboot is
791 	 * either unsupported, or is supported by the bootloader only loading
792 	 * the boot kernel collection; as a result OSKext has no role to play
793 	 * in safeboot policy on ARM.
794 	 */
795 	sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
796 	    sizeof(bootArgBuffer)) ? true : false;
797 #endif /* defined(__arm__) && defined(__arm64__) */
798 
799 	if (sSafeBoot) {
800 		OSKextLog(/* kext */ NULL,
801 		    kOSKextLogWarningLevel |
802 		    kOSKextLogGeneralFlag,
803 		    "SAFE BOOT DETECTED - "
804 		    "only valid OSBundleRequired kexts will be loaded.");
805 	}
806 
807 	PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
808 #if CONFIG_DTRACE
809 	if (dtrace_keep_kernel_symbols()) {
810 		sKeepSymbols = true;
811 	}
812 #endif /* CONFIG_DTRACE */
813 #if KASAN_DYNAMIC_BLACKLIST
814 	/* needed for function lookup */
815 	sKeepSymbols = true;
816 #endif
817 
818 	/*
819 	 * Should we panic when the SystemKC is not linked against the
820 	 * BootKC that was loaded by the booter? By default: yes, if the
821 	 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic
822 	 * on mis-match and instead just print an error and continue.
823 	 */
824 	sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer,
825 	    sizeof(bootArgBuffer)) ? false : true;
826 
827 	/* Set up an OSKext instance to represent the kernel itself.
828 	 */
829 	sKernelKext = new OSKext;
830 	assert(sKernelKext);
831 
832 	kernelStart = (u_char *)&_mh_execute_header;
833 	kernelLength = getlastaddr() - (vm_offset_t)kernelStart;
834 	assert(kernelLength <= UINT_MAX);
835 	kernelExecutable = OSData::withBytesNoCopy(
836 		kernelStart, (unsigned int)kernelLength);
837 	assert(kernelExecutable);
838 
839 #if KASLR_KEXT_DEBUG
840 	IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %lu (0x%016lx) \n",
841 	    (unsigned long)kernelStart,
842 	    (unsigned long)getlastaddr(),
843 	    kernelLength,
844 	    (unsigned long)vm_kernel_slide,
845 	    (unsigned long)vm_kernel_slide);
846 #endif
847 
848 	sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0
849 	sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier);
850 
851 	sKernelKext->version = OSKextParseVersionString(osrelease);
852 	sKernelKext->compatibleVersion = sKernelKext->version;
853 	sKernelKext->linkedExecutable = os::move(kernelExecutable);
854 	sKernelKext->interfaceUUID = sKernelKext->copyUUID();
855 
856 	sKernelKext->flags.hasAllDependencies = 1;
857 	sKernelKext->flags.kernelComponent = 1;
858 	sKernelKext->flags.prelinked = 0;
859 	sKernelKext->flags.loaded = 1;
860 	sKernelKext->flags.started = 1;
861 	sKernelKext->flags.CPPInitialized = 0;
862 	sKernelKext->flags.jettisonLinkeditSeg = 0;
863 
864 	sKernelKext->kmod_info = &g_kernel_kmod_info;
865 	strlcpy(g_kernel_kmod_info.version, osrelease,
866 	    sizeof(g_kernel_kmod_info.version));
867 	g_kernel_kmod_info.size = kernelLength;
868 	g_kernel_kmod_info.id = sKernelKext->loadTag;
869 
870 	/* Cons up an info dict, so we don't have to have special-case
871 	 * checking all over.
872 	 */
873 	sKernelKext->infoDict = OSDictionary::withCapacity(5);
874 	assert(sKernelKext->infoDict);
875 	setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey,
876 	    sKernelKext->bundleID.get());
877 	assert(setResult);
878 	setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey,
879 	    kOSBooleanTrue);
880 	assert(setResult);
881 
882 	{
883 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease));
884 		assert(scratchString);
885 		setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey,
886 		    scratchString.get());
887 		assert(setResult);
888 	}
889 
890 	{
891 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy("mach_kernel"));
892 		assert(scratchString);
893 		setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey,
894 		    scratchString.get());
895 		assert(setResult);
896 	}
897 
898 	/* Add the kernel kext to the bookkeeping dictionaries. Note that
899 	 * the kernel kext doesn't have a kmod_info struct. copyInfo()
900 	 * gathers info from other places anyhow.
901 	 */
902 	setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext);
903 	assert(setResult);
904 	setResult = sLoadedKexts->setObject(sKernelKext);
905 	assert(setResult);
906 
907 	// XXX: better way with OSSharedPtr?
908 	// sKernelKext remains a valid pointer even after the decref
909 	sKernelKext->release();
910 
911 	registryRoot = IORegistryEntry::getRegistryRoot();
912 	kernelCPUType = OSNumber::withNumber(
913 		(long long unsigned int)_mh_execute_header.cputype,
914 		8 * sizeof(_mh_execute_header.cputype));
915 	kernelCPUSubtype = OSNumber::withNumber(
916 		(long long unsigned int)_mh_execute_header.cpusubtype,
917 		8 * sizeof(_mh_execute_header.cpusubtype));
918 	assert(registryRoot && kernelCPUSubtype && kernelCPUType);
919 
920 	registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get());
921 	registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get());
922 
923 	gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
924 	if (gBuiltinKmodsSectionInfo) {
925 		uint32_t count;
926 
927 		assert(gBuiltinKmodsSectionInfo->addr);
928 		assert(gBuiltinKmodsSectionInfo->size);
929 		assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX);
930 		gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
931 
932 		gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
933 		assert(gBuiltinKmodsSectionStart);
934 		assert(gBuiltinKmodsSectionStart->addr);
935 		assert(gBuiltinKmodsSectionStart->size);
936 		assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX);
937 		count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
938 		// one extra pointer for the end of last kmod
939 		assert(count == (gBuiltinKmodsCount + 1));
940 
941 		vm_kernel_builtinkmod_text     = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
942 		vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
943 	}
944 
945 	// Don't track this object -- it's never released
946 	gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach();
947 
948 	timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
949 	*timestamp = 0;
950 	timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
951 	*timestamp = 0;
952 	timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
953 	*timestamp = 0;
954 
955 	OSKextLog(/* kext */ NULL,
956 	    kOSKextLogProgressLevel |
957 	    kOSKextLogGeneralFlag,
958 	    "Kext system initialized.");
959 
960 	notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
961 
962 	return;
963 }
964 
965 /*********************************************************************
966 * This is expected to be called exactly once, from exactly one thread
967 * context, during kernel bootstrap.
968 *********************************************************************/
969 /* static */
970 OSReturn
removeKextBootstrap(void)971 OSKext::removeKextBootstrap(void)
972 {
973 	OSReturn                   result                = kOSReturnError;
974 
975 	const char               * dt_kernel_header_name = "Kernel-__HEADER";
976 	const char               * dt_kernel_symtab_name = "Kernel-__SYMTAB";
977 	kernel_mach_header_t     * dt_mach_header        = NULL;
978 	int                        dt_mach_header_size   = 0;
979 	struct symtab_command    * dt_symtab             = NULL;
980 	int                        dt_symtab_size        = 0;
981 	int                        dt_result             = 0;
982 
983 	kernel_segment_command_t * seg_kld               = NULL;
984 	kernel_segment_command_t * seg_klddata           = NULL;
985 	kernel_segment_command_t * seg_linkedit          = NULL;
986 
987 	const char __unused      * dt_segment_name       = NULL;
988 	void       __unused      * segment_paddress      = NULL;
989 	int        __unused        segment_size          = 0;
990 
991 	OSKextLog(/* kext */ NULL,
992 	    kOSKextLogProgressLevel |
993 	    kOSKextLogGeneralFlag,
994 	    "Jettisoning kext bootstrap segments.");
995 
996 	/*
997 	 * keep the linkedit segment around when booted from a new MH_FILESET
998 	 * KC because all the kexts shared a linkedit segment.
999 	 */
1000 	kc_format_t kc_format;
1001 	if (!PE_get_primary_kc_format(&kc_format)) {
1002 		OSKextLog(/* kext */ NULL,
1003 		    kOSKextLogErrorLevel |
1004 		    kOSKextLogGeneralFlag,
1005 		    "Unable to determine primary KC format");
1006 	}
1007 
1008 	/*****
1009 	 * Dispose of unnecessary stuff that the booter didn't need to load.
1010 	 */
1011 	dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
1012 	    (void **)&dt_mach_header, &dt_mach_header_size);
1013 	if (dt_result == 0 && dt_mach_header) {
1014 		IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
1015 		    round_page_32(dt_mach_header_size));
1016 	}
1017 	dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
1018 	    (void **)&dt_symtab, &dt_symtab_size);
1019 	if (dt_result == 0 && dt_symtab) {
1020 		IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
1021 		    round_page_32(dt_symtab_size));
1022 	}
1023 
1024 	/*****
1025 	 * KLD & KLDDATA bootstrap segments.
1026 	 */
1027 	// xxx - should rename KLD segment
1028 	seg_kld = getsegbyname("__KLD");
1029 	seg_klddata = getsegbyname("__KLDDATA");
1030 	if (seg_klddata) {
1031 		// __mod_term_func is part of __KLDDATA
1032 		OSRuntimeUnloadCPPForSegment(seg_klddata);
1033 	}
1034 
1035 #if __arm__ || __arm64__
1036 	/* Free the memory that was set up by iBoot.
1037 	 */
1038 #if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR)
1039 	/* We cannot free the KLD segment with CTRR enabled as it contains text and
1040 	 * is covered by the contiguous rorgn.
1041 	 */
1042 	dt_segment_name = "Kernel-__KLD";
1043 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1044 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1045 		    (int)segment_size); // calls ml_static_mfree
1046 	} else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1047 		/* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */
1048 		ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase),
1049 		    seg_kld->vmsize);
1050 	}
1051 #endif
1052 	dt_segment_name = "Kernel-__KLDDATA";
1053 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1054 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1055 		    (int)segment_size);  // calls ml_static_mfree
1056 	} else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1057 		/* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */
1058 		ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase),
1059 		    seg_klddata->vmsize);
1060 	}
1061 #elif __i386__ || __x86_64__
1062 	/* On x86, use the mapping data from the segment load command to
1063 	 * unload KLD & KLDDATA directly.
1064 	 * This may invalidate any assumptions about  "avail_start"
1065 	 * defining the lower bound for valid physical addresses.
1066 	 */
1067 	if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1068 		bzero((void *)seg_kld->vmaddr, seg_kld->vmsize);
1069 		ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
1070 	}
1071 	if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1072 		bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize);
1073 		ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
1074 	}
1075 #else
1076 #error arch
1077 #endif
1078 
1079 	/*****
1080 	 * Prelinked kernel's symtab (if there is one).
1081 	 */
1082 	if (kc_format != KCFormatFileset) {
1083 		kernel_section_t * sect;
1084 		sect = getsectbyname("__PRELINK", "__symtab");
1085 		if (sect && sect->addr && sect->size) {
1086 			ml_static_mfree(sect->addr, sect->size);
1087 		}
1088 	}
1089 
1090 	seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
1091 
1092 	/* kxld always needs the kernel's __LINKEDIT segment, but we can make it
1093 	 * pageable, unless keepsyms is set.  To do that, we have to copy it from
1094 	 * its booter-allocated memory, free the booter memory, reallocate proper
1095 	 * managed memory, then copy the segment back in.
1096 	 *
1097 	 * NOTE: This optimization is not valid for fileset KCs because each
1098 	 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment
1099 	 * that points to one fileset-global LINKEDIT segment. This
1100 	 * optimization is also only valid for platforms that support vm
1101 	 * mapped kexts or mapped kext collections (pageable KCs)
1102 	 */
1103 #if VM_MAPPED_KEXTS
1104 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1105 		kern_return_t mem_result;
1106 		void *seg_copy = NULL;
1107 		void *seg_data = NULL;
1108 		vm_map_offset_t seg_offset = 0;
1109 		vm_map_offset_t seg_copy_offset = 0;
1110 		vm_map_size_t seg_length = 0;
1111 
1112 		seg_data = (void *) seg_linkedit->vmaddr;
1113 		seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr;
1114 		seg_length = (vm_map_size_t) seg_linkedit->vmsize;
1115 
1116 		/* Allocate space for the LINKEDIT copy.
1117 		 */
1118 		mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
1119 		    seg_length, KMA_ZERO, VM_KERN_MEMORY_KEXT);
1120 		if (mem_result != KERN_SUCCESS) {
1121 			OSKextLog(/* kext */ NULL,
1122 			    kOSKextLogErrorLevel |
1123 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1124 			    "Can't copy __LINKEDIT segment for VM reassign.");
1125 			return result;
1126 		}
1127 		seg_copy_offset = (vm_map_offset_t) seg_copy;
1128 
1129 		/* Copy it out.
1130 		 */
1131 		memcpy(seg_copy, seg_data, seg_length);
1132 
1133 		/* Dump the booter memory.
1134 		 */
1135 		ml_static_mfree(seg_offset, seg_length);
1136 
1137 		/* Set up the VM region.
1138 		 */
1139 		mem_result = vm_map_enter_mem_object(
1140 			kernel_map,
1141 			&seg_offset,
1142 			seg_length, /* mask */ 0,
1143 			VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
1144 			VM_MAP_KERNEL_FLAGS_NONE,
1145 			VM_KERN_MEMORY_NONE,
1146 			(ipc_port_t)NULL,
1147 			(vm_object_offset_t) 0,
1148 			/* copy */ FALSE,
1149 			/* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1150 			/* max_protection */ VM_PROT_ALL,
1151 			/* inheritance */ VM_INHERIT_DEFAULT);
1152 		if ((mem_result != KERN_SUCCESS) ||
1153 		    (seg_offset != (vm_map_offset_t) seg_data)) {
1154 			OSKextLog(/* kext */ NULL,
1155 			    kOSKextLogErrorLevel |
1156 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1157 			    "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1158 			    seg_data, seg_length, mem_result);
1159 			return result;
1160 		}
1161 
1162 		/* And copy it back.
1163 		 */
1164 		memcpy(seg_data, seg_copy, seg_length);
1165 
1166 		/* Free the copy.
1167 		 */
1168 		kmem_free(kernel_map, seg_copy_offset, seg_length);
1169 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1170 		/* Remove the linkedit segment of the Boot KC */
1171 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1172 		OSKext::jettisonFileSetLinkeditSegment(mh);
1173 	}
1174 #else // !VM_MAPPED_KEXTS
1175 	/*****
1176 	 * Dump the LINKEDIT segment, unless keepsyms is set.
1177 	 */
1178 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1179 		dt_segment_name = "Kernel-__LINKEDIT";
1180 		if (0 == IODTGetLoaderInfo(dt_segment_name,
1181 		    &segment_paddress, &segment_size)) {
1182 #ifdef SECURE_KERNEL
1183 			vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1184 			bzero((void*)vmaddr, segment_size);
1185 #endif
1186 			IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1187 			    (int)segment_size);
1188 		}
1189 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1190 		/* Remove the linkedit segment of the Boot KC */
1191 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1192 		OSKext::jettisonFileSetLinkeditSegment(mh);
1193 	} else {
1194 		OSKextLog(/* kext */ NULL,
1195 		    kOSKextLogBasicLevel |
1196 		    kOSKextLogGeneralFlag,
1197 		    "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1198 	}
1199 #endif // VM_MAPPED_KEXTS
1200 
1201 	result = kOSReturnSuccess;
1202 
1203 	return result;
1204 }
1205 
1206 #if CONFIG_KXLD
1207 /*********************************************************************
1208 *********************************************************************/
1209 void
flushNonloadedKexts(Boolean flushPrelinkedKexts)1210 OSKext::flushNonloadedKexts(
1211 	Boolean flushPrelinkedKexts)
1212 {
1213 	OSSharedPtr<OSSet>                keepKexts;
1214 
1215 	/* TODO: make this more efficient with MH_FILESET kexts */
1216 
1217 	// Do not unload prelinked kexts on arm because the kernelcache is not
1218 	// structured in a way that allows them to be unmapped
1219 #if !defined(__x86_64__)
1220 	flushPrelinkedKexts = false;
1221 #endif /* defined(__x86_64__) */
1222 
1223 	IORecursiveLockLock(sKextLock);
1224 
1225 	OSKextLog(/* kext */ NULL,
1226 	    kOSKextLogProgressLevel |
1227 	    kOSKextLogKextBookkeepingFlag,
1228 	    "Flushing nonloaded kexts and other unused data.");
1229 
1230 	OSKext::considerDestroyingLinkContext();
1231 
1232 	/* If we aren't flushing unused prelinked kexts, we have to put them
1233 	 * aside while we flush everything else so make a container for them.
1234 	 */
1235 	keepKexts = OSSet::withCapacity(16);
1236 	if (!keepKexts) {
1237 		goto finish;
1238 	}
1239 
1240 	/* Set aside prelinked kexts (in-use or not) and break
1241 	 * any lingering inter-kext references for nonloaded kexts
1242 	 * so they have min. retain counts.
1243 	 */
1244 	{
1245 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1246 			OSKext * thisKext = OSDynamicCast(OSKext, obj);
1247 			if (!thisKext) {
1248 			        return false;
1249 			}
1250 			if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
1251 			        keepKexts->setObject(thisKext);
1252 			} else if (!thisKext->declaresExecutable()) {
1253 			        /*
1254 			         * Don't unload codeless kexts, because they never appear in the loadedKexts array.
1255 			         * Requesting one from the IOKit daemon will load it and then immediately remove it by calling
1256 			         * flushNonloadedKexts().
1257 			         * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
1258 			         */
1259 			        keepKexts->setObject(thisKext);
1260 			} else if (thisKext->isInFileset()) {
1261 			        /* keep all kexts in the new MH_FILESET KC */
1262 			        keepKexts->setObject(thisKext);
1263 			}
1264 
1265 			thisKext->flushDependencies(/* forceIfLoaded */ false);
1266 			return false;
1267 		});
1268 	}
1269 	/* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1270 	 */
1271 	sKextsByID->flushCollection();
1272 
1273 	/* Now put the loaded kexts back into the ID dictionary.
1274 	 */
1275 	sLoadedKexts->iterateObjects(^bool (OSObject * obj) {
1276 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1277 		if (!thisKext) {
1278 		        return false;
1279 		}
1280 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1281 		return false;
1282 	});
1283 
1284 	/* Finally, put back the kept kexts if we saved any.
1285 	 */
1286 	keepKexts->iterateObjects(^bool (OSObject * obj) {
1287 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1288 		if (!thisKext) {
1289 		        return false;
1290 		}
1291 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1292 		return false;
1293 	});
1294 
1295 finish:
1296 	IORecursiveLockUnlock(sKextLock);
1297 	return;
1298 }
1299 #else /* !CONFIG_KXLD */
1300 
1301 void
flushNonloadedKexts(Boolean flushPrelinkedKexts __unused)1302 OSKext::flushNonloadedKexts(
1303 	Boolean flushPrelinkedKexts __unused)
1304 {
1305 	IORecursiveLockLock(sKextLock);
1306 
1307 	OSKextLog(/* kext */ NULL,
1308 	    kOSKextLogProgressLevel |
1309 	    kOSKextLogKextBookkeepingFlag,
1310 	    "Flushing dependency info for non-loaded kexts.");
1311 
1312 	/*
1313 	 * In a world where we don't dynamically link kexts, they all come
1314 	 * from a kext collection that's either in wired memory, or
1315 	 * wire-on-demand. We don't need to mess around with moving kexts in
1316 	 * and out of the sKextsByID array - they can all just stay there.
1317 	 * Here we just flush the dependency list for kexts that are not
1318 	 * loaded.
1319 	 */
1320 	sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1321 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1322 		if (!thisKext) {
1323 		        return false;
1324 		}
1325 		thisKext->flushDependencies(/* forceIfLoaded */ false);
1326 		return false;
1327 	});
1328 
1329 	IORecursiveLockUnlock(sKextLock);
1330 	return;
1331 }
1332 
1333 #endif /* CONFIG_KXLD */
1334 
1335 /*********************************************************************
1336 *********************************************************************/
1337 /* static */
1338 void
setIOKitDaemonActive(bool active)1339 OSKext::setIOKitDaemonActive(bool active)
1340 {
1341 	IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
1342 	IORecursiveLockLock(sKextLock);
1343 	sIOKitDaemonActive = active;
1344 	if (sKernelRequests->getCount()) {
1345 		OSKext::pingIOKitDaemon();
1346 	}
1347 	IORecursiveLockUnlock(sKextLock);
1348 
1349 	return;
1350 }
1351 
1352 /*********************************************************************
1353 * OSKextLib.cpp might need access to this someday but for now it's
1354 * private.
1355 *********************************************************************/
1356 extern "C" {
1357 extern void ipc_port_release_send(ipc_port_t);
1358 };
1359 
1360 /* static */
1361 OSReturn
pingIOKitDaemon(void)1362 OSKext::pingIOKitDaemon(void)
1363 {
1364 	OSReturn    result     = kOSReturnError;
1365 #if !NO_KEXTD
1366 	mach_port_t kextd_port = IPC_PORT_NULL;
1367 
1368 	if (!sIOKitDaemonActive) {
1369 		result = kOSKextReturnDisabled; // basically unavailable
1370 		goto finish;
1371 	}
1372 
1373 	result = host_get_kextd_port(host_priv_self(), &kextd_port);
1374 	if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1375 		OSKextLog(/* kext */ NULL,
1376 		    kOSKextLogErrorLevel |
1377 		    kOSKextLogIPCFlag,
1378 		    "Can't get " kIOKitDaemonName " port.");
1379 		goto finish;
1380 	}
1381 
1382 	result = kextd_ping(kextd_port);
1383 	if (result != KERN_SUCCESS) {
1384 		OSKextLog(/* kext */ NULL,
1385 		    kOSKextLogErrorLevel |
1386 		    kOSKextLogIPCFlag,
1387 		    kIOKitDaemonName " ping failed (0x%x).", (int)result);
1388 		goto finish;
1389 	}
1390 
1391 finish:
1392 	if (IPC_PORT_VALID(kextd_port)) {
1393 		ipc_port_release_send(kextd_port);
1394 	}
1395 #endif
1396 
1397 	return result;
1398 }
1399 
1400 /*********************************************************************
1401 *********************************************************************/
1402 /* static */
1403 void
setDeferredLoadSucceeded(Boolean succeeded)1404 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1405 {
1406 	IORecursiveLockLock(sKextLock);
1407 	sDeferredLoadSucceeded = succeeded;
1408 	IORecursiveLockUnlock(sKextLock);
1409 
1410 	return;
1411 }
1412 
1413 /*********************************************************************
1414 * Called from IOSystemShutdownNotification.
1415 *********************************************************************/
1416 /* static */
1417 void
willShutdown(void)1418 OSKext::willShutdown(void)
1419 {
1420 #if !NO_KEXTD
1421 	OSReturn       checkResult = kOSReturnError;
1422 #endif
1423 	OSSharedPtr<OSDictionary> exitRequest;
1424 
1425 	IORecursiveLockLock(sKextLock);
1426 
1427 	OSKext::setLoadEnabled(false);
1428 	OSKext::setUnloadEnabled(false);
1429 	OSKext::setAutounloadsEnabled(false);
1430 	OSKext::setKernelRequestsEnabled(false);
1431 
1432 #if defined(__x86_64__) || defined(__i386__)
1433 	if (IOPMRootDomainGetWillShutdown()) {
1434 		OSKext::freeKCFileSetcontrol();
1435 	}
1436 #endif // (__x86_64__) || defined(__i386__)
1437 
1438 #if !NO_KEXTD
1439 	OSKextLog(/* kext */ NULL,
1440 	    kOSKextLogProgressLevel |
1441 	    kOSKextLogGeneralFlag,
1442 	    "System shutdown; requesting immediate " kIOKitDaemonName " exit.");
1443 
1444 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit,
1445 	    exitRequest);
1446 	if (checkResult != kOSReturnSuccess) {
1447 		goto finish;
1448 	}
1449 	if (!sKernelRequests->setObject(exitRequest.get())) {
1450 		goto finish;
1451 	}
1452 
1453 	OSKext::pingIOKitDaemon();
1454 
1455 finish:
1456 #endif
1457 
1458 	IORecursiveLockUnlock(sKextLock);
1459 	return;
1460 }
1461 
1462 void
willUserspaceReboot(void)1463 OSKext::willUserspaceReboot(void)
1464 {
1465 	OSKext::willShutdown();
1466 	IOService::userSpaceWillReboot();
1467 	gIOCatalogue->terminateDriversForUserspaceReboot();
1468 }
1469 
1470 void
resetAfterUserspaceReboot(void)1471 OSKext::resetAfterUserspaceReboot(void)
1472 {
1473 	OSSharedPtr<OSArray> arr = OSArray::withCapacity(1);
1474 	IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */);
1475 
1476 	IORecursiveLockLock(sKextLock);
1477 	gIOCatalogue->resetAfterUserspaceReboot();
1478 	IOService::userSpaceDidReboot();
1479 	OSKext::removeDaemonExitRequests();
1480 	OSKext::setLoadEnabled(true);
1481 	OSKext::setUnloadEnabled(true);
1482 	OSKext::setAutounloadsEnabled(true);
1483 	OSKext::setKernelRequestsEnabled(true);
1484 	sOSKextWasResetAfterUserspaceReboot = true;
1485 	IORecursiveLockUnlock(sKextLock);
1486 }
1487 
1488 extern "C" void
OSKextResetAfterUserspaceReboot(void)1489 OSKextResetAfterUserspaceReboot(void)
1490 {
1491 	OSKext::resetAfterUserspaceReboot();
1492 }
1493 
1494 /*
1495  * Remove daemon exit requests from sKernelRequests
1496  *
1497  * If we sent a daemon exit request during a userspace reboot and launchd
1498  * killed the IOKit daemon before it was able to dequeue the exit request, the
1499  * next time the daemon starts up it will immediately exit as it gets the old exit request.
1500  *
1501  * This removes exit requests so that this does not happen.
1502  */
1503 void
removeDaemonExitRequests(void)1504 OSKext::removeDaemonExitRequests(void)
1505 {
1506 	OSDictionary * current = NULL;
1507 	OSString     * predicate = NULL;
1508 	size_t         index     = 0;
1509 	OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey);
1510 
1511 	while (index < sKernelRequests->getCount()) {
1512 		current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index));
1513 		if (current) {
1514 			predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get()));
1515 			if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) {
1516 				sKernelRequests->removeObject(index);
1517 				continue;
1518 			}
1519 		}
1520 		index++;
1521 	}
1522 }
1523 
1524 /*********************************************************************
1525 *********************************************************************/
1526 /* static */
1527 bool
getLoadEnabled(void)1528 OSKext::getLoadEnabled(void)
1529 {
1530 	bool result;
1531 
1532 	IORecursiveLockLock(sKextLock);
1533 	result = sLoadEnabled;
1534 	IORecursiveLockUnlock(sKextLock);
1535 	return result;
1536 }
1537 
1538 /*********************************************************************
1539 *********************************************************************/
1540 /* static */
1541 bool
setLoadEnabled(bool flag)1542 OSKext::setLoadEnabled(bool flag)
1543 {
1544 	bool result;
1545 
1546 	IORecursiveLockLock(sKextLock);
1547 	result = sLoadEnabled;
1548 	sLoadEnabled = (flag ? true : false);
1549 
1550 	if (sLoadEnabled != result) {
1551 		OSKextLog(/* kext */ NULL,
1552 		    kOSKextLogBasicLevel |
1553 		    kOSKextLogLoadFlag,
1554 		    "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1555 	}
1556 
1557 	IORecursiveLockUnlock(sKextLock);
1558 
1559 	return result;
1560 }
1561 
1562 /*********************************************************************
1563 *********************************************************************/
1564 /* static */
1565 bool
getUnloadEnabled(void)1566 OSKext::getUnloadEnabled(void)
1567 {
1568 	bool result;
1569 
1570 	IORecursiveLockLock(sKextLock);
1571 	result = sUnloadEnabled;
1572 	IORecursiveLockUnlock(sKextLock);
1573 	return result;
1574 }
1575 
1576 /*********************************************************************
1577 *********************************************************************/
1578 /* static */
1579 bool
setUnloadEnabled(bool flag)1580 OSKext::setUnloadEnabled(bool flag)
1581 {
1582 	bool result;
1583 
1584 	IORecursiveLockLock(sKextLock);
1585 	result = sUnloadEnabled;
1586 	sUnloadEnabled = (flag ? true : false);
1587 	IORecursiveLockUnlock(sKextLock);
1588 
1589 	if (sUnloadEnabled != result) {
1590 		OSKextLog(/* kext */ NULL,
1591 		    kOSKextLogBasicLevel |
1592 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1593 		    "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1594 	}
1595 
1596 	return result;
1597 }
1598 
1599 /*********************************************************************
1600 * Do not call any function that takes sKextLock here!
1601 *********************************************************************/
1602 /* static */
1603 bool
getAutounloadEnabled(void)1604 OSKext::getAutounloadEnabled(void)
1605 {
1606 #if XNU_TARGET_OS_OSX
1607 	bool result;
1608 
1609 	IORecursiveLockLock(sKextInnerLock);
1610 	result = sAutounloadEnabled ? true : false;
1611 	IORecursiveLockUnlock(sKextInnerLock);
1612 	return result;
1613 #else
1614 	return false;
1615 #endif /* XNU_TARGET_OS_OSX */
1616 }
1617 
1618 /*********************************************************************
1619 * Do not call any function that takes sKextLock here!
1620 *********************************************************************/
1621 /* static */
1622 bool
setAutounloadsEnabled(bool flag)1623 OSKext::setAutounloadsEnabled(bool flag)
1624 {
1625 #if XNU_TARGET_OS_OSX
1626 	bool result;
1627 
1628 	IORecursiveLockLock(sKextInnerLock);
1629 
1630 	result = sAutounloadEnabled;
1631 	sAutounloadEnabled = (flag ? true : false);
1632 	if (!sAutounloadEnabled && sUnloadCallout) {
1633 		thread_call_cancel(sUnloadCallout);
1634 	}
1635 
1636 	if (sAutounloadEnabled != result) {
1637 		OSKextLog(/* kext */ NULL,
1638 		    kOSKextLogBasicLevel |
1639 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1640 		    "Kext autounloading now %sabled.",
1641 		    sAutounloadEnabled ? "en" : "dis");
1642 	}
1643 
1644 	IORecursiveLockUnlock(sKextInnerLock);
1645 
1646 	return result;
1647 #else
1648 	(void)flag;
1649 	return false;
1650 #endif /* XNU_TARGET_OS_OSX */
1651 }
1652 
1653 /*********************************************************************
1654 *********************************************************************/
1655 /* instance method operating on OSKext field */
1656 bool
setAutounloadEnabled(bool flag)1657 OSKext::setAutounloadEnabled(bool flag)
1658 {
1659 	bool result = flags.autounloadEnabled ? true : false;
1660 	flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0;
1661 
1662 	if (result != (flag ? true : false)) {
1663 		OSKextLog(this,
1664 		    kOSKextLogProgressLevel |
1665 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1666 		    "Autounloading for kext %s now %sabled.",
1667 		    getIdentifierCString(),
1668 		    flags.autounloadEnabled ? "en" : "dis");
1669 	}
1670 	return result;
1671 }
1672 
1673 /*********************************************************************
1674 *********************************************************************/
1675 /* static */
1676 bool
setKernelRequestsEnabled(bool flag)1677 OSKext::setKernelRequestsEnabled(bool flag)
1678 {
1679 	bool result;
1680 
1681 	IORecursiveLockLock(sKextLock);
1682 	result = sKernelRequestsEnabled;
1683 	sKernelRequestsEnabled = flag ? true : false;
1684 
1685 	if (sKernelRequestsEnabled != result) {
1686 		OSKextLog(/* kext */ NULL,
1687 		    kOSKextLogBasicLevel |
1688 		    kOSKextLogGeneralFlag,
1689 		    "Kernel requests now %sabled.",
1690 		    sKernelRequestsEnabled ? "en" : "dis");
1691 	}
1692 	IORecursiveLockUnlock(sKextLock);
1693 	return result;
1694 }
1695 
1696 /*********************************************************************
1697 *********************************************************************/
1698 /* static */
1699 bool
getKernelRequestsEnabled(void)1700 OSKext::getKernelRequestsEnabled(void)
1701 {
1702 	bool result;
1703 
1704 	IORecursiveLockLock(sKextLock);
1705 	result = sKernelRequestsEnabled;
1706 	IORecursiveLockUnlock(sKextLock);
1707 	return result;
1708 }
1709 
1710 static bool
segmentIsMutable(kernel_segment_command_t * seg)1711 segmentIsMutable(kernel_segment_command_t *seg)
1712 {
1713 	/* Mutable segments have to have VM_PROT_WRITE */
1714 	if ((seg->maxprot & VM_PROT_WRITE) == 0) {
1715 		return false;
1716 	}
1717 	/* Exclude the __DATA_CONST segment */
1718 	if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) {
1719 		return false;
1720 	}
1721 	/* Exclude __LINKEDIT */
1722 	if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) {
1723 		return false;
1724 	}
1725 	return true;
1726 }
1727 
1728 #if PRAGMA_MARK
1729 #pragma mark Kext Life Cycle
1730 #endif
1731 /*********************************************************************
1732 *********************************************************************/
1733 OSSharedPtr<OSKext>
withPrelinkedInfoDict(OSDictionary * anInfoDict,bool doCoalescedSlides,kc_kind_t type)1734 OSKext::withPrelinkedInfoDict(
1735 	OSDictionary * anInfoDict,
1736 	bool doCoalescedSlides,
1737 	kc_kind_t type)
1738 {
1739 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
1740 
1741 	if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) {
1742 		return NULL;
1743 	}
1744 
1745 	return newKext;
1746 }
1747 
1748 /*********************************************************************
1749 *********************************************************************/
1750 bool
initWithPrelinkedInfoDict(OSDictionary * anInfoDict,bool doCoalescedSlides,kc_kind_t type)1751 OSKext::initWithPrelinkedInfoDict(
1752 	OSDictionary * anInfoDict,
1753 	bool doCoalescedSlides,
1754 	kc_kind_t type)
1755 {
1756 	bool            result              = false;
1757 	OSString      * kextPath            = NULL;                // do not release
1758 	OSNumber      * addressNum          = NULL;                // reused; do not release
1759 	OSNumber      * lengthNum           = NULL;                // reused; do not release
1760 	OSBoolean     * scratchBool         = NULL;                // do not release
1761 	void          * data                = NULL;                // do not free
1762 	void          * srcData             = NULL;                // do not free
1763 	OSSharedPtr<OSData>        prelinkedExecutable;
1764 	uint32_t        length              = 0;                // reused
1765 	uintptr_t       kext_slide          = PE_get_kc_slide(type);
1766 	bool            shouldSaveSegments  = false;
1767 
1768 	if (!super::init()) {
1769 		goto finish;
1770 	}
1771 
1772 	/* Get the path. Don't look for an arch-specific path property.
1773 	 */
1774 	kextPath = OSDynamicCast(OSString,
1775 	    anInfoDict->getObject(kPrelinkBundlePathKey));
1776 
1777 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1778 		goto finish;
1779 	}
1780 
1781 #if KASLR_KEXT_DEBUG
1782 	IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString());
1783 #endif
1784 
1785 	/* Also get the executable's bundle-relative path if present.
1786 	 * Don't look for an arch-specific path property.
1787 	 */
1788 	executableRelPath.reset(OSDynamicCast(OSString,
1789 	    anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain);
1790 	userExecutableRelPath.reset(OSDynamicCast(OSString,
1791 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
1792 
1793 	/* Don't need the paths to be in the info dictionary any more.
1794 	 */
1795 	anInfoDict->removeObject(kPrelinkBundlePathKey);
1796 	anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1797 
1798 	scratchBool = OSDynamicCast(OSBoolean,
1799 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
1800 	if (scratchBool == kOSBooleanTrue) {
1801 		flags.requireExplicitLoad = 1;
1802 	}
1803 
1804 	/* Create an OSData wrapper around the linked executable.
1805 	 */
1806 	addressNum = OSDynamicCast(OSNumber,
1807 	    anInfoDict->getObject(kPrelinkExecutableLoadKey));
1808 	if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) {
1809 		lengthNum = OSDynamicCast(OSNumber,
1810 		    anInfoDict->getObject(kPrelinkExecutableSizeKey));
1811 		if (!lengthNum) {
1812 			OSKextLog(this,
1813 			    kOSKextLogErrorLevel |
1814 			    kOSKextLogArchiveFlag,
1815 			    "Kext %s can't find prelinked kext executable size.",
1816 			    getIdentifierCString());
1817 			return result;
1818 		}
1819 
1820 		data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1821 		length = (uint32_t) (lengthNum->unsigned32BitValue());
1822 
1823 #if KASLR_KEXT_DEBUG
1824 		IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1825 		    (unsigned long)ml_static_unslide((vm_offset_t)data),
1826 		    (unsigned long)data,
1827 		    length);
1828 #endif
1829 
1830 		anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1831 		anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1832 
1833 		/* If the kext's load address differs from its source address, allocate
1834 		 * space in the kext map at the load address and copy the kext over.
1835 		 */
1836 		addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1837 		if (addressNum) {
1838 			srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1839 
1840 #if KASLR_KEXT_DEBUG
1841 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1842 			    (unsigned long)ml_static_unslide((vm_offset_t)srcData),
1843 			    (unsigned long)srcData);
1844 #endif
1845 
1846 			if (data != srcData) {
1847 #if __LP64__
1848 				kern_return_t alloc_result;
1849 
1850 				alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
1851 				if (alloc_result != KERN_SUCCESS) {
1852 					OSKextLog(this,
1853 					    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1854 					    "Failed to allocate space for prelinked kext %s.",
1855 					    getIdentifierCString());
1856 					goto finish;
1857 				}
1858 				memcpy(data, srcData, length);
1859 #else
1860 				OSKextLog(this,
1861 				    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1862 				    "Error: prelinked kext %s - source and load addresses "
1863 				    "differ on ILP32 architecture.",
1864 				    getIdentifierCString());
1865 				goto finish;
1866 #endif /* __LP64__ */
1867 			}
1868 
1869 			anInfoDict->removeObject(kPrelinkExecutableSourceKey);
1870 		}
1871 
1872 		prelinkedExecutable = OSData::withBytesNoCopy(data, length);
1873 		if (!prelinkedExecutable) {
1874 			OSKextLog(this,
1875 			    kOSKextLogErrorLevel |
1876 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1877 			    "Kext %s failed to create executable wrapper.",
1878 			    getIdentifierCString());
1879 			goto finish;
1880 		}
1881 
1882 #if VM_MAPPED_KEXTS
1883 		prelinkedExecutable->setDeallocFunction(osdata_kext_free);
1884 #else
1885 		prelinkedExecutable->setDeallocFunction(osdata_phys_free);
1886 #endif
1887 		setLinkedExecutable(prelinkedExecutable.get());
1888 		addressNum = OSDynamicCast(OSNumber,
1889 		    anInfoDict->getObject(kPrelinkKmodInfoKey));
1890 		if (!addressNum) {
1891 			OSKextLog(this,
1892 			    kOSKextLogErrorLevel |
1893 			    kOSKextLogArchiveFlag,
1894 			    "Kext %s can't find prelinked kext kmod_info address.",
1895 			    getIdentifierCString());
1896 			goto finish;
1897 		}
1898 
1899 		if (addressNum->unsigned64BitValue() != 0) {
1900 			kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1901 			if (kmod_info->address) {
1902 				kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide);
1903 			} else {
1904 				kmod_info->address = (uintptr_t)data;
1905 				kmod_info->size = length;
1906 			}
1907 #if KASLR_KEXT_DEBUG
1908 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1909 			    (unsigned long)((vm_offset_t)kmod_info) - kext_slide,
1910 			    (unsigned long)kmod_info);
1911 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1912 			    (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide,
1913 			    (unsigned long)kmod_info->address);
1914  #endif
1915 		}
1916 
1917 		anInfoDict->removeObject(kPrelinkKmodInfoKey);
1918 	}
1919 
1920 	if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
1921 		uintptr_t builtinTextStart;
1922 		uintptr_t builtinTextEnd;
1923 
1924 		flags.builtin = true;
1925 		builtinKmodIdx = addressNum->unsigned32BitValue();
1926 		assert(builtinKmodIdx < gBuiltinKmodsCount);
1927 
1928 		builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
1929 		builtinTextEnd   = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
1930 
1931 		kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
1932 		kmod_info->address = builtinTextStart;
1933 		kmod_info->size    = builtinTextEnd - builtinTextStart;
1934 	}
1935 
1936 	/* If the plist has a UUID for an interface, save that off.
1937 	 */
1938 	if (isInterface()) {
1939 		interfaceUUID.reset(OSDynamicCast(OSData,
1940 		    anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain);
1941 		if (interfaceUUID) {
1942 			anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
1943 		}
1944 	}
1945 
1946 	result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides));
1947 	if (!result) {
1948 		goto finish;
1949 	}
1950 
1951 	kc_type = type;
1952 	/* Exclude builtin and codeless kexts */
1953 	if (prelinkedExecutable && kmod_info) {
1954 		switch (kc_type) {
1955 		case KCKindPrimary:
1956 			shouldSaveSegments = (
1957 				getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue ||
1958 				getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue);
1959 			if (shouldSaveSegments) {
1960 				flags.resetSegmentsFromImmutableCopy = 1;
1961 			} else {
1962 				flags.unloadUnsupported = 1;
1963 			}
1964 			break;
1965 		case KCKindPageable:
1966 			flags.resetSegmentsFromVnode = 1;
1967 			break;
1968 		case KCKindAuxiliary:
1969 			if (!pageableKCloaded) {
1970 				flags.resetSegmentsFromImmutableCopy = 1;
1971 			} else if (resetAuxKCSegmentOnUnload) {
1972 				flags.resetSegmentsFromVnode = 1;
1973 			} else {
1974 				flags.unloadUnsupported = 1;
1975 			}
1976 			break;
1977 		default:
1978 			break;
1979 		}
1980 	}
1981 
1982 	if (flags.resetSegmentsFromImmutableCopy) {
1983 		/* Save a pristine copy of the mutable segments */
1984 		kernel_segment_command_t *seg = NULL;
1985 		kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
1986 
1987 		savedMutableSegments = OSArray::withCapacity(0);
1988 
1989 		for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) {
1990 			if (!segmentIsMutable(seg)) {
1991 				continue;
1992 			}
1993 			uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
1994 			uint64_t vmsize = seg->vmsize;
1995 			OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
1996 			    "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
1997 			OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg);
1998 			if (!savedSegment) {
1999 				OSKextLog(this,
2000 				    kOSKextLogErrorLevel |
2001 				    kOSKextLogGeneralFlag,
2002 				    "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2003 				result = kOSKextReturnInternalError;
2004 				goto finish;
2005 			}
2006 			savedMutableSegments->setObject(savedSegment);
2007 		}
2008 	}
2009 
2010 	if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) {
2011 		/*
2012 		 * set VM protections now, wire pages for the old style Aux KC now,
2013 		 * wire pages for the rest of the KC types at load time.
2014 		 */
2015 		result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false));
2016 		if (!result) {
2017 			goto finish;
2018 		}
2019 	}
2020 
2021 	flags.prelinked = true;
2022 
2023 	/* If we created a kext from prelink info,
2024 	 * we must be booting from a prelinked kernel.
2025 	 */
2026 	sPrelinkBoot = true;
2027 
2028 	result = registerIdentifier();
2029 
2030 finish:
2031 	return result;
2032 }
2033 
2034 /*********************************************************************
2035 *********************************************************************/
2036 /* static */
2037 OSSharedPtr<OSKext>
withCodelessInfo(OSDictionary * anInfoDict)2038 OSKext::withCodelessInfo(OSDictionary * anInfoDict)
2039 {
2040 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
2041 
2042 	if (newKext && !newKext->initWithCodelessInfo(anInfoDict)) {
2043 		return NULL;
2044 	}
2045 
2046 	return newKext;
2047 }
2048 
2049 /*********************************************************************
2050 *********************************************************************/
2051 bool
initWithCodelessInfo(OSDictionary * anInfoDict)2052 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict)
2053 {
2054 	bool        result      = false;
2055 	OSString  * kextPath    = NULL;        // do not release
2056 	OSBoolean * scratchBool = NULL;        // do not release
2057 
2058 	if (anInfoDict == NULL || !super::init()) {
2059 		goto finish;
2060 	}
2061 
2062 	/*
2063 	 * Get the path. Don't look for an arch-specific path property.
2064 	 */
2065 	kextPath = OSDynamicCast(OSString,
2066 	    anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey));
2067 	if (!kextPath) {
2068 		OSKextLog(NULL,
2069 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2070 		    "Requested codeless kext dictionary does not contain the '%s' key",
2071 		    kKextRequestArgumentCodelessInfoBundlePathKey);
2072 		goto finish;
2073 	}
2074 
2075 	uniquePersonalityProperties(anInfoDict);
2076 
2077 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2078 		goto finish;
2079 	}
2080 
2081 	/*
2082 	 * This path is meant to initialize codeless kexts only. Refuse
2083 	 * anything that looks like it has an executable and/or declares
2084 	 * itself as a kernel component.
2085 	 */
2086 	if (declaresExecutable() || isKernelComponent()) {
2087 		OSKextLog(NULL,
2088 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2089 		    "Refusing to register codeless kext that declares an executable/kernel component: %s",
2090 		    getIdentifierCString());
2091 		goto finish;
2092 	}
2093 
2094 	if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
2095 		boolean_t updated = updateExcludeList(infoDict.get());
2096 		if (updated) {
2097 			OSKextLog(this,
2098 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2099 			    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
2100 		}
2101 	}
2102 
2103 	kc_type = KCKindNone;
2104 
2105 	scratchBool = OSDynamicCast(OSBoolean,
2106 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
2107 	if (scratchBool == kOSBooleanTrue) {
2108 		flags.requireExplicitLoad = 1;
2109 	}
2110 
2111 	/* Also get the executable's bundle-relative path if present.
2112 	 * Don't look for an arch-specific path property.
2113 	 */
2114 	userExecutableRelPath.reset(OSDynamicCast(OSString,
2115 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
2116 
2117 	/* remove unnecessary paths from the info dict */
2118 	anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey);
2119 
2120 	result = registerIdentifier();
2121 
2122 finish:
2123 	return result;
2124 }
2125 
2126 /*********************************************************************
2127 *********************************************************************/
2128 /* static */
2129 void
setAllVMAttributes(void)2130 OSKext::setAllVMAttributes(void)
2131 {
2132 	OSSharedPtr<OSCollectionIterator> kextIterator;
2133 	const OSSymbol * thisID                 = NULL;        // do not release
2134 
2135 	IORecursiveLockLock(sKextLock);
2136 
2137 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
2138 	if (!kextIterator) {
2139 		goto finish;
2140 	}
2141 
2142 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
2143 		OSKext *    thisKext;        // do not release
2144 
2145 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
2146 		if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
2147 			continue;
2148 		}
2149 
2150 		if (!thisKext->flags.resetSegmentsFromVnode) {
2151 			/*
2152 			 * set VM protections now, wire pages for the old style Aux KC now,
2153 			 * wire pages for the rest of the KC types at load time.
2154 			 */
2155 			thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false);
2156 		}
2157 	}
2158 
2159 finish:
2160 	IORecursiveLockUnlock(sKextLock);
2161 
2162 	return;
2163 }
2164 
2165 /*********************************************************************
2166 *********************************************************************/
2167 OSSharedPtr<OSKext>
withBooterData(OSString * deviceTreeName,OSData * booterData)2168 OSKext::withBooterData(
2169 	OSString * deviceTreeName,
2170 	OSData   * booterData)
2171 {
2172 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
2173 
2174 	if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
2175 		return NULL;
2176 	}
2177 
2178 	return newKext;
2179 }
2180 
2181 /*********************************************************************
2182 *********************************************************************/
2183 typedef struct _BooterKextFileInfo {
2184 	uint32_t  infoDictPhysAddr;
2185 	uint32_t  infoDictLength;
2186 	uint32_t  executablePhysAddr;
2187 	uint32_t  executableLength;
2188 	uint32_t  bundlePathPhysAddr;
2189 	uint32_t  bundlePathLength;
2190 } _BooterKextFileInfo;
2191 
2192 bool
initWithBooterData(OSString * deviceTreeName,OSData * booterData)2193 OSKext::initWithBooterData(
2194 	OSString * deviceTreeName,
2195 	OSData   * booterData)
2196 {
2197 	bool                  result         = false;
2198 	_BooterKextFileInfo * kextFileInfo   = NULL;        // do not free
2199 	char                * infoDictAddr   = NULL;        // do not free
2200 	void                * executableAddr = NULL;        // do not free
2201 	char                * bundlePathAddr = NULL;        // do not free
2202 
2203 	OSDictionary        * theInfoDict    = NULL;        // do not release
2204 	OSSharedPtr<OSObject> parsedXML;
2205 	OSSharedPtr<OSString> kextPath;
2206 
2207 	OSSharedPtr<OSString> errorString;
2208 	OSSharedPtr<OSData>   executable;
2209 
2210 	if (!super::init()) {
2211 		goto finish;
2212 	}
2213 
2214 	kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
2215 	if (!kextFileInfo) {
2216 		OSKextLog(this,
2217 		    kOSKextLogErrorLevel |
2218 		    kOSKextLogGeneralFlag,
2219 		    "No booter-provided data for kext device tree entry %s.",
2220 		    deviceTreeName->getCStringNoCopy());
2221 		goto finish;
2222 	}
2223 
2224 	/* The info plist must exist or we can't read the kext.
2225 	 */
2226 	if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
2227 		OSKextLog(this,
2228 		    kOSKextLogErrorLevel |
2229 		    kOSKextLogGeneralFlag,
2230 		    "No kext info dictionary for booter device tree entry %s.",
2231 		    deviceTreeName->getCStringNoCopy());
2232 		goto finish;
2233 	}
2234 
2235 	infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
2236 	if (!infoDictAddr) {
2237 		OSKextLog(this,
2238 		    kOSKextLogErrorLevel |
2239 		    kOSKextLogGeneralFlag,
2240 		    "Can't translate physical address 0x%x of kext info dictionary "
2241 		    "for device tree entry %s.",
2242 		    (int)kextFileInfo->infoDictPhysAddr,
2243 		    deviceTreeName->getCStringNoCopy());
2244 		goto finish;
2245 	}
2246 
2247 	parsedXML = OSUnserializeXML(infoDictAddr, errorString);
2248 	if (parsedXML) {
2249 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
2250 	}
2251 	if (!theInfoDict) {
2252 		const char * errorCString = "(unknown error)";
2253 
2254 		if (errorString && errorString->getCStringNoCopy()) {
2255 			errorCString = errorString->getCStringNoCopy();
2256 		} else if (parsedXML) {
2257 			errorCString = "not a dictionary";
2258 		}
2259 		OSKextLog(this,
2260 		    kOSKextLogErrorLevel |
2261 		    kOSKextLogGeneralFlag,
2262 		    "Error unserializing info dictionary for device tree entry %s: %s.",
2263 		    deviceTreeName->getCStringNoCopy(), errorCString);
2264 		goto finish;
2265 	}
2266 
2267 	/* A bundle path is not mandatory.
2268 	 */
2269 	if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
2270 		bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
2271 		if (!bundlePathAddr) {
2272 			OSKextLog(this,
2273 			    kOSKextLogErrorLevel |
2274 			    kOSKextLogGeneralFlag,
2275 			    "Can't translate physical address 0x%x of kext bundle path "
2276 			    "for device tree entry %s.",
2277 			    (int)kextFileInfo->bundlePathPhysAddr,
2278 			    deviceTreeName->getCStringNoCopy());
2279 			goto finish;
2280 		}
2281 		bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0';         // just in case!
2282 
2283 		kextPath = OSString::withCString(bundlePathAddr);
2284 		if (!kextPath) {
2285 			OSKextLog(this,
2286 			    kOSKextLogErrorLevel |
2287 			    kOSKextLogGeneralFlag,
2288 			    "Failed to create wrapper for device tree entry %s kext path %s.",
2289 			    deviceTreeName->getCStringNoCopy(), bundlePathAddr);
2290 			goto finish;
2291 		}
2292 	}
2293 
2294 	if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) {
2295 		goto finish;
2296 	}
2297 
2298 	/* An executable is not mandatory.
2299 	 */
2300 	if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
2301 		executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
2302 		if (!executableAddr) {
2303 			OSKextLog(this,
2304 			    kOSKextLogErrorLevel |
2305 			    kOSKextLogGeneralFlag,
2306 			    "Can't translate physical address 0x%x of kext executable "
2307 			    "for device tree entry %s.",
2308 			    (int)kextFileInfo->executablePhysAddr,
2309 			    deviceTreeName->getCStringNoCopy());
2310 			goto finish;
2311 		}
2312 
2313 		executable = OSData::withBytesNoCopy(executableAddr,
2314 		    kextFileInfo->executableLength);
2315 		if (!executable) {
2316 			OSKextLog(this,
2317 			    kOSKextLogErrorLevel |
2318 			    kOSKextLogGeneralFlag,
2319 			    "Failed to create executable wrapper for device tree entry %s.",
2320 			    deviceTreeName->getCStringNoCopy());
2321 			goto finish;
2322 		}
2323 
2324 		/* A kext with an executable needs to retain the whole booterData
2325 		 * object to keep the executable in memory.
2326 		 */
2327 		if (!setExecutable(executable.get(), booterData)) {
2328 			OSKextLog(this,
2329 			    kOSKextLogErrorLevel |
2330 			    kOSKextLogGeneralFlag,
2331 			    "Failed to set kext executable for device tree entry %s.",
2332 			    deviceTreeName->getCStringNoCopy());
2333 			goto finish;
2334 		}
2335 	}
2336 
2337 	result = registerIdentifier();
2338 
2339 finish:
2340 	return result;
2341 }
2342 
2343 /*********************************************************************
2344 *********************************************************************/
2345 bool
registerIdentifier(void)2346 OSKext::registerIdentifier(void)
2347 {
2348 	bool            result              = false;
2349 	OSKext        * existingKext        = NULL;        // do not release
2350 	bool            existingIsLoaded    = false;
2351 	bool            existingIsPrelinked = false;
2352 	bool            existingIsCodeless  = false;
2353 	bool            existingIsDext      = false;
2354 	OSKextVersion   newVersion          = -1;
2355 	OSKextVersion   existingVersion     = -1;
2356 	char            newVersionCString[kOSKextVersionMaxLength];
2357 	char            existingVersionCString[kOSKextVersionMaxLength];
2358 	OSSharedPtr<OSData> newUUID;
2359 	OSSharedPtr<OSData> existingUUID;
2360 
2361 	IORecursiveLockLock(sKextLock);
2362 
2363 	/* Get the new kext's version for checks & log messages.
2364 	 */
2365 	newVersion = getVersion();
2366 	OSKextVersionGetString(newVersion, newVersionCString,
2367 	    kOSKextVersionMaxLength);
2368 
2369 	/* If we don't have an existing kext with this identifier,
2370 	 * just record the new kext and we're done!
2371 	 */
2372 	existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get()));
2373 	if (!existingKext) {
2374 		sKextsByID->setObject(bundleID.get(), this);
2375 		result = true;
2376 		goto finish;
2377 	}
2378 
2379 	/* Get the existing kext's version for checks & log messages.
2380 	 */
2381 	existingVersion = existingKext->getVersion();
2382 	OSKextVersionGetString(existingVersion,
2383 	    existingVersionCString, kOSKextVersionMaxLength);
2384 
2385 	existingIsLoaded = existingKext->isLoaded();
2386 	existingIsPrelinked = existingKext->isPrelinked();
2387 	existingIsDext = existingKext->isDriverKit();
2388 	existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext;
2389 
2390 	/* If we have a non-codeless kext with this identifier that's already
2391 	 * loaded/prelinked, we can't use the new one, but let's be really
2392 	 * thorough and check how the two are related for a precise diagnostic
2393 	 * log message.
2394 	 *
2395 	 * This check is valid for kexts that declare an executable and for
2396 	 * dexts, but not for codeless kexts - we can just replace those.
2397 	 */
2398 	if ((!existingIsCodeless || existingIsDext) &&
2399 	    (existingIsLoaded || existingIsPrelinked)) {
2400 		bool sameVersion = (newVersion == existingVersion);
2401 		bool sameExecutable = true;         // assume true unless we have UUIDs
2402 
2403 		/* Only get the UUID if the existing kext is loaded. Doing so
2404 		 * might have to uncompress an mkext executable and we shouldn't
2405 		 * take that hit when neither kext is loaded.
2406 		 *
2407 		 * Note: there is no decompression that happens when all kexts
2408 		 * are loaded from kext collecitons.
2409 		 */
2410 		newUUID = copyUUID();
2411 		existingUUID = existingKext->copyUUID();
2412 
2413 		if (existingIsDext && !isDriverKit()) {
2414 			OSKextLog(this,
2415 			    kOSKextLogWarningLevel |
2416 			    kOSKextLogKextBookkeepingFlag,
2417 			    "Notice - new kext %s, v%s matches a %s dext"
2418 			    "with the same bundle ID, v%s.",
2419 			    getIdentifierCString(), newVersionCString,
2420 			    (existingIsLoaded ? "loaded" : "prelinked"),
2421 			    existingVersionCString);
2422 			goto finish;
2423 		}
2424 
2425 		/* I'm entirely too paranoid about checking equivalence of executables,
2426 		 * but I remember nasty problems with it in the past.
2427 		 *
2428 		 * - If we have UUIDs for both kexts, compare them.
2429 		 * - If only one kext has a UUID, they're definitely different.
2430 		 */
2431 		if (newUUID && existingUUID) {
2432 			sameExecutable = newUUID->isEqualTo(existingUUID.get());
2433 		} else if (newUUID || existingUUID) {
2434 			sameExecutable = false;
2435 		}
2436 
2437 		if (!newUUID && !existingUUID) {
2438 			/* If there are no UUIDs, we can't really tell that the executables
2439 			 * are *different* without a lot of work; the loaded kext's
2440 			 * unrelocated executable is no longer around (and we never had it
2441 			 * in-kernel for a prelinked kext). We certainly don't want to do
2442 			 * a whole fake link for the new kext just to compare, either.
2443 			 */
2444 			OSKextLog(this,
2445 			    kOSKextLogWarningLevel |
2446 			    kOSKextLogKextBookkeepingFlag,
2447 			    "Notice - new kext %s, v%s matches %s kext "
2448 			    "but can't determine if executables are the same (no UUIDs).",
2449 			    getIdentifierCString(),
2450 			    newVersionCString,
2451 			    (existingIsLoaded ? "loaded" : "prelinked"));
2452 		}
2453 
2454 		if (sameVersion && sameExecutable) {
2455 			OSKextLog(this,
2456 			    (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2457 			    kOSKextLogKextBookkeepingFlag,
2458 			    "Refusing new kext %s, v%s: a %s copy is already present "
2459 			    "(same version and executable).",
2460 			    getIdentifierCString(), newVersionCString,
2461 			    (existingIsLoaded ? "loaded" : "prelinked"));
2462 		} else {
2463 			if (!sameVersion) {
2464 				/* This condition is significant so log it under warnings.
2465 				 */
2466 				OSKextLog(this,
2467 				    kOSKextLogWarningLevel |
2468 				    kOSKextLogKextBookkeepingFlag,
2469 				    "Refusing new kext %s, v%s: already have %s v%s.",
2470 				    getIdentifierCString(),
2471 				    newVersionCString,
2472 				    (existingIsLoaded ? "loaded" : "prelinked"),
2473 				    existingVersionCString);
2474 			} else {
2475 				/* This condition is significant so log it under warnings.
2476 				 */
2477 				OSKextLog(this,
2478 				    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2479 				    "Refusing new kext %s, v%s: a %s copy with a different "
2480 				    "executable UUID is already present.",
2481 				    getIdentifierCString(), newVersionCString,
2482 				    (existingIsLoaded ? "loaded" : "prelinked"));
2483 			}
2484 		}
2485 		goto finish;
2486 	} /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */
2487 
2488 	/* Refuse to allow an existing loaded codeless kext be replaced by a
2489 	 * normal kext with the same bundle ID.
2490 	 */
2491 	if (existingIsCodeless && declaresExecutable()) {
2492 		OSKextLog(this,
2493 		    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2494 		    "Refusing new kext %s, v%s: a codeless copy is already %s",
2495 		    getIdentifierCString(), newVersionCString,
2496 		    (existingIsLoaded ? "loaded" : "prelinked"));
2497 		goto finish;
2498 	}
2499 
2500 	/* Dexts packaged in the BootKC will be protected against replacement
2501 	 * by non-dexts by the logic above which checks if they are prelinked.
2502 	 * Dexts which are prelinked into the System KC will be registered
2503 	 * before any other kexts in the AuxKC are registered, and we never
2504 	 * put dexts in the AuxKC. Therefore, there is no need to check if an
2505 	 * existing object is a dext and is being replaced by a non-dext.
2506 	 * The scenario cannot happen by construction.
2507 	 *
2508 	 * See: OSKext::loadFileSetKexts()
2509 	 */
2510 
2511 	/* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2512 	 * user loads are happening or if we're still in early boot. User agents are
2513 	 * supposed to resolve dependencies topside and include only the exact
2514 	 * kexts needed; so we always accept the new kext (in fact we should never
2515 	 * see an older unloaded copy hanging around).
2516 	 */
2517 	if (sUserLoadsActive) {
2518 		sKextsByID->setObject(bundleID.get(), this);
2519 		result = true;
2520 
2521 		OSKextLog(this,
2522 		    kOSKextLogStepLevel |
2523 		    kOSKextLogKextBookkeepingFlag,
2524 		    "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2525 		    getIdentifierCString(),
2526 		    existingVersionCString,
2527 		    newVersionCString);
2528 
2529 		goto finish;
2530 	}
2531 
2532 	/* During early boot, the kext with the highest version always wins out.
2533 	 * Prelinked kernels will never hit this, but mkexts and booter-read
2534 	 * kexts might have duplicates.
2535 	 */
2536 	if (newVersion > existingVersion) {
2537 		sKextsByID->setObject(bundleID.get(), this);
2538 		result = true;
2539 
2540 		OSKextLog(this,
2541 		    kOSKextLogStepLevel |
2542 		    kOSKextLogKextBookkeepingFlag,
2543 		    "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2544 		    existingVersionCString,
2545 		    getIdentifierCString(),
2546 		    newVersionCString);
2547 	} else {
2548 		OSKextLog(this,
2549 		    kOSKextLogStepLevel |
2550 		    kOSKextLogKextBookkeepingFlag,
2551 		    "Kext %s is already registered with a higher/same version (v%s); "
2552 		    "dropping newly-added (v%s).",
2553 		    getIdentifierCString(),
2554 		    existingVersionCString,
2555 		    newVersionCString);
2556 	}
2557 
2558 	/* result has been set appropriately by now. */
2559 
2560 finish:
2561 
2562 	IORecursiveLockUnlock(sKextLock);
2563 
2564 	if (result) {
2565 		OSKextLog(this,
2566 		    kOSKextLogStepLevel |
2567 		    kOSKextLogKextBookkeepingFlag,
2568 		    "Kext %s, v%s registered and available for loading.",
2569 		    getIdentifierCString(), newVersionCString);
2570 	}
2571 
2572 	return result;
2573 }
2574 
2575 /*********************************************************************
2576  * Does the bare minimum validation to look up a kext.
2577  * All other validation is done on the spot as needed.
2578  **********************************************************************/
2579 bool
setInfoDictionaryAndPath(OSDictionary * aDictionary,OSString * aPath)2580 OSKext::setInfoDictionaryAndPath(
2581 	OSDictionary * aDictionary,
2582 	OSString     * aPath)
2583 {
2584 	bool           result                   = false;
2585 	OSString     * bundleIDString           = NULL;        // do not release
2586 	OSString     * versionString            = NULL;        // do not release
2587 	OSString     * compatibleVersionString  = NULL;        // do not release
2588 	const char   * versionCString           = NULL;        // do not free
2589 	const char   * compatibleVersionCString = NULL;        // do not free
2590 	OSBoolean    * scratchBool              = NULL;        // do not release
2591 	OSDictionary * scratchDict              = NULL;        // do not release
2592 
2593 	if (infoDict) {
2594 		panic("Attempt to set info dictionary on a kext "
2595 		    "that already has one (%s).",
2596 		    getIdentifierCString());
2597 	}
2598 
2599 	if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
2600 		goto finish;
2601 	}
2602 
2603 	infoDict.reset(aDictionary, OSRetain);
2604 
2605 	/* Check right away if the info dictionary has any log flags.
2606 	 */
2607 	scratchBool = OSDynamicCast(OSBoolean,
2608 	    getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
2609 	if (scratchBool == kOSBooleanTrue) {
2610 		flags.loggingEnabled = 1;
2611 	}
2612 
2613 	/* The very next thing to get is the bundle identifier. Unlike
2614 	 * in user space, a kext with no bundle identifier gets axed
2615 	 * immediately.
2616 	 */
2617 	bundleIDString = OSDynamicCast(OSString,
2618 	    getPropertyForHostArch(kCFBundleIdentifierKey));
2619 	if (!bundleIDString) {
2620 		OSKextLog(this,
2621 		    kOSKextLogErrorLevel |
2622 		    kOSKextLogValidationFlag,
2623 		    "CFBundleIdentifier missing/invalid type in kext %s.",
2624 		    aPath ? aPath->getCStringNoCopy() : "(unknown)");
2625 		goto finish;
2626 	}
2627 	bundleID = OSSymbol::withString(bundleIDString);
2628 	if (!bundleID) {
2629 		OSKextLog(this,
2630 		    kOSKextLogErrorLevel |
2631 		    kOSKextLogValidationFlag,
2632 		    "Can't copy bundle identifier as symbol for kext %s.",
2633 		    bundleIDString->getCStringNoCopy());
2634 		goto finish;
2635 	}
2636 
2637 	/* Save the path if we got one (it should always be available but it's
2638 	 * just something nice to have for bookkeeping).
2639 	 */
2640 	if (aPath) {
2641 		path.reset(aPath, OSRetain);
2642 	}
2643 
2644 	/*****
2645 	 * Minimal validation to initialize. We'll do other validation on the spot.
2646 	 */
2647 	if (bundleID->getLength() >= KMOD_MAX_NAME) {
2648 		OSKextLog(this,
2649 		    kOSKextLogErrorLevel |
2650 		    kOSKextLogValidationFlag,
2651 		    "Kext %s error - CFBundleIdentifier over max length %d.",
2652 		    getIdentifierCString(), KMOD_MAX_NAME - 1);
2653 		goto finish;
2654 	}
2655 
2656 	version = compatibleVersion = -1;
2657 
2658 	versionString = OSDynamicCast(OSString,
2659 	    getPropertyForHostArch(kCFBundleVersionKey));
2660 	if (!versionString) {
2661 		OSKextLog(this,
2662 		    kOSKextLogErrorLevel |
2663 		    kOSKextLogValidationFlag,
2664 		    "Kext %s error - CFBundleVersion missing/invalid type.",
2665 		    getIdentifierCString());
2666 		goto finish;
2667 	}
2668 	versionCString = versionString->getCStringNoCopy();
2669 	version = OSKextParseVersionString(versionCString);
2670 	if (version < 0) {
2671 		OSKextLog(this,
2672 		    kOSKextLogErrorLevel |
2673 		    kOSKextLogValidationFlag,
2674 		    "Kext %s error - CFBundleVersion bad value '%s'.",
2675 		    getIdentifierCString(), versionCString);
2676 		goto finish;
2677 	}
2678 
2679 	compatibleVersion = -1;         // set to illegal value for kexts that don't have
2680 
2681 	compatibleVersionString = OSDynamicCast(OSString,
2682 	    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2683 	if (compatibleVersionString) {
2684 		compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2685 		compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2686 		if (compatibleVersion < 0) {
2687 			OSKextLog(this,
2688 			    kOSKextLogErrorLevel |
2689 			    kOSKextLogValidationFlag,
2690 			    "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2691 			    getIdentifierCString(), compatibleVersionCString);
2692 			goto finish;
2693 		}
2694 
2695 		if (compatibleVersion > version) {
2696 			OSKextLog(this,
2697 			    kOSKextLogErrorLevel |
2698 			    kOSKextLogValidationFlag,
2699 			    "Kext %s error - %s %s > %s %s (must be <=).",
2700 			    getIdentifierCString(),
2701 			    kOSBundleCompatibleVersionKey, compatibleVersionCString,
2702 			    kCFBundleVersionKey, versionCString);
2703 			goto finish;
2704 		}
2705 	}
2706 
2707 	/* Check to see if this kext is in exclude list */
2708 	if (isInExcludeList()) {
2709 		OSKextLog(this,
2710 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2711 		    "Kext %s is in exclude list, not loadable",
2712 		    getIdentifierCString());
2713 		goto finish;
2714 	}
2715 
2716 	/* Set flags for later use if the infoDict gets flushed. We only
2717 	 * check for true values, not false ones(!)
2718 	 */
2719 	scratchBool = OSDynamicCast(OSBoolean,
2720 	    getPropertyForHostArch(kOSBundleIsInterfaceKey));
2721 	if (scratchBool == kOSBooleanTrue) {
2722 		flags.interface = 1;
2723 	}
2724 
2725 	scratchBool = OSDynamicCast(OSBoolean,
2726 	    getPropertyForHostArch(kOSKernelResourceKey));
2727 	if (scratchBool == kOSBooleanTrue) {
2728 		flags.kernelComponent = 1;
2729 		flags.interface = 1;         // xxx - hm. the kernel itself isn't an interface...
2730 		flags.started = 1;
2731 
2732 		/* A kernel component has one implicit dependency on the kernel.
2733 		 */
2734 		flags.hasAllDependencies = 1;
2735 	}
2736 
2737 	/* Make sure common string values in personalities are uniqued to OSSymbols.
2738 	 */
2739 	scratchDict = OSDynamicCast(OSDictionary,
2740 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
2741 	if (scratchDict) {
2742 		uniquePersonalityProperties(scratchDict);
2743 	}
2744 
2745 	result = true;
2746 
2747 finish:
2748 
2749 	return result;
2750 }
2751 
2752 /*********************************************************************
2753 * Not used for prelinked kernel boot as there is no unrelocated
2754 * executable.
2755 *********************************************************************/
2756 bool
setExecutable(OSData * anExecutable,OSData * externalData,bool externalDataIsMkext)2757 OSKext::setExecutable(
2758 	OSData * anExecutable,
2759 	OSData * externalData,
2760 	bool     externalDataIsMkext)
2761 {
2762 	bool         result        = false;
2763 	const char * executableKey = NULL;         // do not free
2764 
2765 	if (!anExecutable) {
2766 		infoDict->removeObject(_kOSKextExecutableKey);
2767 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
2768 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
2769 		result = true;
2770 		goto finish;
2771 	}
2772 
2773 	if (infoDict->getObject(_kOSKextExecutableKey) ||
2774 	    infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
2775 		panic("Attempt to set an executable on a kext "
2776 		    "that already has one (%s).",
2777 		    getIdentifierCString());
2778 		goto finish;
2779 	}
2780 
2781 	if (externalDataIsMkext) {
2782 		executableKey = _kOSKextMkextExecutableReferenceKey;
2783 	} else {
2784 		executableKey = _kOSKextExecutableKey;
2785 	}
2786 
2787 	if (anExecutable) {
2788 		infoDict->setObject(executableKey, anExecutable);
2789 		if (externalData) {
2790 			infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
2791 		}
2792 	}
2793 
2794 	result = true;
2795 
2796 finish:
2797 	return result;
2798 }
2799 
2800 /*********************************************************************
2801 *********************************************************************/
2802 static void
uniqueStringPlistProperty(OSDictionary * dict,const char * key)2803 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
2804 {
2805 	OSObject       * value       = NULL;        // do not release
2806 	OSString       * stringValue = NULL;        // do not release
2807 	OSSharedPtr<const OSSymbol> symbolValue;
2808 
2809 	value = dict->getObject(key);
2810 	if (!value) {
2811 		goto finish;
2812 	}
2813 	if (OSDynamicCast(OSSymbol, value)) {
2814 		/* this is already an OSSymbol: we're good */
2815 		goto finish;
2816 	}
2817 
2818 	stringValue = OSDynamicCast(OSString, value);
2819 	if (!stringValue) {
2820 		goto finish;
2821 	}
2822 
2823 	symbolValue = OSSymbol::withString(stringValue);
2824 	if (!symbolValue) {
2825 		goto finish;
2826 	}
2827 
2828 	dict->setObject(key, symbolValue.get());
2829 
2830 finish:
2831 	return;
2832 }
2833 
2834 /*********************************************************************
2835 *********************************************************************/
2836 static void
uniqueStringPlistProperty(OSDictionary * dict,const OSString * key)2837 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
2838 {
2839 	OSObject       * value       = NULL;        // do not release
2840 	OSString       * stringValue = NULL;        // do not release
2841 	OSSharedPtr<const OSSymbol> symbolValue;
2842 
2843 	value = dict->getObject(key);
2844 	if (!value) {
2845 		goto finish;
2846 	}
2847 	if (OSDynamicCast(OSSymbol, value)) {
2848 		/* this is already an OSSymbol: we're good */
2849 		goto finish;
2850 	}
2851 
2852 	stringValue = OSDynamicCast(OSString, value);
2853 	if (!stringValue) {
2854 		goto finish;
2855 	}
2856 
2857 	symbolValue = OSSymbol::withString(stringValue);
2858 	if (!symbolValue) {
2859 		goto finish;
2860 	}
2861 
2862 	dict->setObject(key, symbolValue.get());
2863 
2864 finish:
2865 	return;
2866 }
2867 
2868 void
uniquePersonalityProperties(OSDictionary * personalityDict)2869 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
2870 {
2871 	OSKext::uniquePersonalityProperties(personalityDict, true);
2872 }
2873 
2874 /*********************************************************************
2875 * Replace common personality property values with uniqued instances
2876 * to save on wired memory.
2877 *********************************************************************/
2878 /* static */
2879 void
uniquePersonalityProperties(OSDictionary * personalityDict,bool defaultAddKernelBundleIdentifier)2880 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier)
2881 {
2882 	/* Properties every personality has.
2883 	 */
2884 	uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
2885 	uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
2886 	uniqueStringPlistProperty(personalityDict, gIOClassKey.get());
2887 	if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
2888 		uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
2889 	} else if (defaultAddKernelBundleIdentifier) {
2890 		personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
2891 	}
2892 
2893 	/* Other commonly used properties.
2894 	 */
2895 	uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
2896 	uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
2897 	uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
2898 
2899 	uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
2900 	uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
2901 	uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
2902 	uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
2903 	uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
2904 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
2905 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
2906 	uniqueStringPlistProperty(personalityDict, "Vendor");
2907 	uniqueStringPlistProperty(personalityDict, "Vendor Identification");
2908 	uniqueStringPlistProperty(personalityDict, "Vendor Name");
2909 	uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
2910 	uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
2911 	uniqueStringPlistProperty(personalityDict, "idProduct");
2912 
2913 	return;
2914 }
2915 
2916 /*********************************************************************
2917 *********************************************************************/
2918 void
free(void)2919 OSKext::free(void)
2920 {
2921 	if (isLoaded()) {
2922 		panic("Attempt to free loaded kext %s.", getIdentifierCString());
2923 	}
2924 
2925 	infoDict.reset();
2926 	bundleID.reset();
2927 	path.reset();
2928 	executableRelPath.reset();
2929 	userExecutableRelPath.reset();
2930 	dependencies.reset();
2931 	linkedExecutable.reset();
2932 	metaClasses.reset();
2933 	interfaceUUID.reset();
2934 	driverKitUUID.reset();
2935 
2936 	if (isInterface() && kmod_info) {
2937 		kfree_type(kmod_info_t, kmod_info);
2938 	}
2939 
2940 	super::free();
2941 	return;
2942 }
2943 
2944 #if PRAGMA_MARK
2945 #pragma mark Mkext files
2946 #endif
2947 
2948 #if CONFIG_KXLD
2949 /*
2950  * mkext archives are really only relevant on kxld-enabled kernels.
2951  * Without a dynamic kernel linker, we don't need to support any mkexts.
2952  */
2953 
2954 /*********************************************************************
2955 *********************************************************************/
2956 OSReturn
readMkextArchive(OSData * mkextData,uint32_t * checksumPtr)2957 OSKext::readMkextArchive(OSData * mkextData,
2958     uint32_t * checksumPtr)
2959 {
2960 	OSReturn       result       = kOSKextReturnBadData;
2961 	uint32_t       mkextLength  = 0;
2962 	mkext_header * mkextHeader  = NULL;        // do not free
2963 	uint32_t       mkextVersion = 0;
2964 
2965 	/* Note default return of kOSKextReturnBadData above.
2966 	 */
2967 	mkextLength = mkextData->getLength();
2968 	if (mkextLength < sizeof(mkext_basic_header)) {
2969 		OSKextLog(/* kext */ NULL,
2970 		    kOSKextLogErrorLevel |
2971 		    kOSKextLogArchiveFlag,
2972 		    "Mkext archive too small to be valid.");
2973 		goto finish;
2974 	}
2975 
2976 	mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
2977 
2978 	if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
2979 	    MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
2980 		OSKextLog(/* kext */ NULL,
2981 		    kOSKextLogErrorLevel |
2982 		    kOSKextLogArchiveFlag,
2983 		    "Mkext archive has invalid magic or signature.");
2984 		goto finish;
2985 	}
2986 
2987 	if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
2988 		OSKextLog(/* kext */ NULL,
2989 		    kOSKextLogErrorLevel |
2990 		    kOSKextLogArchiveFlag,
2991 		    "Mkext archive recorded length doesn't match actual file length.");
2992 		goto finish;
2993 	}
2994 
2995 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2996 
2997 	if (mkextVersion == MKEXT_VERS_2) {
2998 		result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
2999 	} else {
3000 		OSKextLog(/* kext */ NULL,
3001 		    kOSKextLogErrorLevel |
3002 		    kOSKextLogArchiveFlag,
3003 		    "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
3004 		result = kOSKextReturnUnsupported;
3005 	}
3006 
3007 finish:
3008 	return result;
3009 }
3010 
3011 /*********************************************************************
3012 * Assumes magic, signature, version, length have been checked.
3013 * xxx - need to add further bounds checking for each file entry
3014 *
3015 * Should keep track of all kexts created so far, and if we hit a
3016 * fatal error halfway through, remove those kexts. If we've dropped
3017 * an older version that had already been read, whoops! Might want to
3018 * add a level of buffering?
3019 *********************************************************************/
3020 /* static */
3021 OSReturn
readMkext2Archive(OSData * mkextData,OSDictionary ** mkextPlistOut,uint32_t * checksumPtr)3022 OSKext::readMkext2Archive(
3023 	OSData        * mkextData,
3024 	OSDictionary ** mkextPlistOut,
3025 	uint32_t      * checksumPtr)
3026 {
3027 	OSReturn        result                     = kOSReturnError;
3028 	uint32_t        mkextLength;
3029 	mkext2_header * mkextHeader                = NULL;        // do not free
3030 	void          * mkextEnd                   = NULL;        // do not free
3031 	uint32_t        mkextVersion;
3032 	uint8_t       * crc_address                = NULL;
3033 	size_t          crc_buffer_size            = 0;
3034 	uint32_t        checksum;
3035 	uint32_t        mkextPlistOffset;
3036 	uint32_t        mkextPlistCompressedSize;
3037 	char          * mkextPlistEnd              = NULL;        // do not free
3038 	uint32_t        mkextPlistFullSize;
3039 	OSSharedPtr<OSString>     errorString;
3040 	OSSharedPtr<OSData>       mkextPlistUncompressedData;
3041 	const char    * mkextPlistDataBuffer       = NULL;        // do not free
3042 	OSSharedPtr<OSObject>      parsedXML;
3043 	OSDictionary  * mkextPlist                 = NULL;        // do not release
3044 	OSArray       * mkextInfoDictArray         = NULL;        // do not release
3045 	uint32_t        count, i;
3046 	kc_format_t kc_format;
3047 
3048 	if (!PE_get_primary_kc_format(&kc_format)) {
3049 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3050 		    "Unable to determine primary KC format");
3051 		goto finish;
3052 	}
3053 
3054 	mkextLength = mkextData->getLength();
3055 	mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
3056 	mkextEnd = (char *)mkextHeader + mkextLength;
3057 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3058 
3059 	crc_address = (u_int8_t *)&mkextHeader->version;
3060 	crc_buffer_size = (uintptr_t)mkextHeader +
3061 	    MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address;
3062 	if (crc_buffer_size > INT32_MAX) {
3063 		OSKextLog(/* kext */ NULL,
3064 		    kOSKextLogErrorLevel |
3065 		    kOSKextLogArchiveFlag,
3066 		    "Mkext archive size is too large (%lu > INT32_MAX).",
3067 		    crc_buffer_size);
3068 		result = kOSKextReturnBadData;
3069 		goto finish;
3070 	}
3071 	checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size);
3072 
3073 	if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
3074 		OSKextLog(/* kext */ NULL,
3075 		    kOSKextLogErrorLevel |
3076 		    kOSKextLogArchiveFlag,
3077 		    "Mkext archive has bad checksum.");
3078 		result = kOSKextReturnBadData;
3079 		goto finish;
3080 	}
3081 
3082 	if (checksumPtr) {
3083 		*checksumPtr = checksum;
3084 	}
3085 
3086 	/* Check that the CPU type & subtype match that of the running kernel. */
3087 	if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
3088 		OSKextLog(/* kext */ NULL,
3089 		    kOSKextLogErrorLevel |
3090 		    kOSKextLogArchiveFlag,
3091 		    "Mkext archive must have a specific CPU type.");
3092 		result = kOSKextReturnBadData;
3093 		goto finish;
3094 	} else {
3095 		if ((UInt32)_mh_execute_header.cputype !=
3096 		    MKEXT_GET_CPUTYPE(mkextHeader)) {
3097 			OSKextLog(/* kext */ NULL,
3098 			    kOSKextLogErrorLevel |
3099 			    kOSKextLogArchiveFlag,
3100 			    "Mkext archive does not match the running kernel's CPU type.");
3101 			result = kOSKextReturnArchNotFound;
3102 			goto finish;
3103 		}
3104 	}
3105 
3106 	mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
3107 	mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
3108 	mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
3109 	    mkextPlistCompressedSize;
3110 	if (mkextPlistEnd > mkextEnd) {
3111 		OSKextLog(/* kext */ NULL,
3112 		    kOSKextLogErrorLevel |
3113 		    kOSKextLogArchiveFlag,
3114 		    "Mkext archive file overrun.");
3115 		result = kOSKextReturnBadData;
3116 	}
3117 
3118 	mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
3119 	if (mkextPlistCompressedSize) {
3120 		mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
3121 			(UInt8 *)mkextHeader + mkextPlistOffset,
3122 			"plist",
3123 			mkextPlistCompressedSize, mkextPlistFullSize);
3124 		if (!mkextPlistUncompressedData) {
3125 			goto finish;
3126 		}
3127 		mkextPlistDataBuffer = (const char *)
3128 		    mkextPlistUncompressedData->getBytesNoCopy();
3129 	} else {
3130 		mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
3131 	}
3132 
3133 	/* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
3134 	 */
3135 	parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString);
3136 	if (parsedXML) {
3137 		mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get());
3138 	}
3139 	if (!mkextPlist) {
3140 		const char * errorCString = "(unknown error)";
3141 
3142 		if (errorString && errorString->getCStringNoCopy()) {
3143 			errorCString = errorString->getCStringNoCopy();
3144 		} else if (parsedXML) {
3145 			errorCString = "not a dictionary";
3146 		}
3147 		OSKextLog(/* kext */ NULL,
3148 		    kOSKextLogErrorLevel |
3149 		    kOSKextLogArchiveFlag,
3150 		    "Error unserializing mkext plist: %s.", errorCString);
3151 		goto finish;
3152 	}
3153 
3154 	mkextInfoDictArray = OSDynamicCast(OSArray,
3155 	    mkextPlist->getObject(kMKEXTInfoDictionariesKey));
3156 	if (!mkextInfoDictArray) {
3157 		OSKextLog(/* kext */ NULL,
3158 		    kOSKextLogErrorLevel |
3159 		    kOSKextLogArchiveFlag,
3160 		    "Mkext archive contains no kext info dictionaries.");
3161 		goto finish;
3162 	}
3163 
3164 	count = mkextInfoDictArray->getCount();
3165 	for (i = 0; i < count; i++) {
3166 		OSDictionary * infoDict;
3167 
3168 
3169 		infoDict = OSDynamicCast(OSDictionary,
3170 		    mkextInfoDictArray->getObject(i));
3171 
3172 		/* Create the kext for the entry, then release it, because the
3173 		 * kext system keeps them around until explicitly removed.
3174 		 * Any creation/registration failures are already logged for us.
3175 		 */
3176 		if (infoDict) {
3177 			OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData);
3178 
3179 			/* Fail dynamic loading of a kext when booted from MH_FILESET */
3180 			if (kc_format == KCFormatFileset &&
3181 			    newKext &&
3182 			    !(newKext->isPrelinked()) &&
3183 			    newKext->declaresExecutable()) {
3184 				result = kOSReturnError;
3185 				printf("Kext LOG: Dynamic loading of kext denied for kext %s\n",
3186 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3187 
3188 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
3189 				    "Dynamic loading of kext denied for kext %s\n",
3190 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3191 				goto finish;
3192 			}
3193 		}
3194 	}
3195 
3196 	/* If the caller needs the plist, hand them back our copy
3197 	 */
3198 	if (mkextPlistOut) {
3199 		*mkextPlistOut = mkextPlist;
3200 		parsedXML.detach();
3201 	}
3202 
3203 	/* Even if we didn't keep any kexts from the mkext, we may have a load
3204 	 * request to process, so we are successful (no errors occurred).
3205 	 */
3206 	result = kOSReturnSuccess;
3207 
3208 finish:
3209 	return result;
3210 }
3211 
3212 /* static */
3213 OSReturn
readMkext2Archive(OSData * mkextData,OSSharedPtr<OSDictionary> & mkextPlistOut,uint32_t * checksumPtr)3214 OSKext::readMkext2Archive(
3215 	OSData        * mkextData,
3216 	OSSharedPtr<OSDictionary> &mkextPlistOut,
3217 	uint32_t      * checksumPtr)
3218 {
3219 	OSDictionary * mkextPlist = NULL;
3220 	OSReturn ret;
3221 
3222 	if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData,
3223 	    &mkextPlist,
3224 	    checksumPtr))) {
3225 		mkextPlistOut.reset(mkextPlist, OSNoRetain);
3226 	}
3227 	return ret;
3228 }
3229 
3230 /*********************************************************************
3231 *********************************************************************/
3232 /* static */
3233 OSSharedPtr<OSKext>
withMkext2Info(OSDictionary * anInfoDict,OSData * mkextData)3234 OSKext::withMkext2Info(
3235 	OSDictionary * anInfoDict,
3236 	OSData       * mkextData)
3237 {
3238 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
3239 
3240 	if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
3241 		return NULL;
3242 	}
3243 
3244 	return newKext;
3245 }
3246 
3247 /*********************************************************************
3248 *********************************************************************/
3249 bool
initWithMkext2Info(OSDictionary * anInfoDict,OSData * mkextData)3250 OSKext::initWithMkext2Info(
3251 	OSDictionary * anInfoDict,
3252 	OSData       * mkextData)
3253 {
3254 	bool                   result              = false;
3255 	OSString             * kextPath            = NULL;        // do not release
3256 	OSNumber             * executableOffsetNum = NULL;        // do not release
3257 	OSSharedPtr<OSData>               executable;
3258 
3259 	if (anInfoDict == NULL || !super::init()) {
3260 		goto finish;
3261 	}
3262 
3263 	/* Get the path. Don't look for an arch-specific path property.
3264 	 */
3265 	kextPath = OSDynamicCast(OSString,
3266 	    anInfoDict->getObject(kMKEXTBundlePathKey));
3267 
3268 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
3269 		goto finish;
3270 	}
3271 
3272 	/* If we have a path to the executable, save it.
3273 	 */
3274 	executableRelPath.reset(OSDynamicCast(OSString,
3275 	    anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain);
3276 
3277 	/* Don't need the paths to be in the info dictionary any more.
3278 	 */
3279 	anInfoDict->removeObject(kMKEXTBundlePathKey);
3280 	anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
3281 
3282 	executableOffsetNum = OSDynamicCast(OSNumber,
3283 	    infoDict->getObject(kMKEXTExecutableKey));
3284 	if (executableOffsetNum) {
3285 		executable = createMkext2FileEntry(mkextData,
3286 		    executableOffsetNum, "executable");
3287 		infoDict->removeObject(kMKEXTExecutableKey);
3288 		if (!executable) {
3289 			goto finish;
3290 		}
3291 		if (!setExecutable(executable.get(), mkextData, true)) {
3292 			goto finish;
3293 		}
3294 	}
3295 
3296 	result = registerIdentifier();
3297 
3298 finish:
3299 	return result;
3300 }
3301 
3302 /*********************************************************************
3303 *********************************************************************/
3304 OSSharedPtr<OSData>
createMkext2FileEntry(OSData * mkextData,OSNumber * offsetNum,const char * name)3305 OSKext::createMkext2FileEntry(
3306 	OSData     * mkextData,
3307 	OSNumber   * offsetNum,
3308 	const char * name)
3309 {
3310 	OSSharedPtr<OSData> result;
3311 	MkextEntryRef   entryRef;
3312 	uint8_t       * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
3313 	uint32_t        entryOffset = offsetNum->unsigned32BitValue();
3314 
3315 	result = OSData::withCapacity(sizeof(entryRef));
3316 	if (!result) {
3317 		goto finish;
3318 	}
3319 
3320 	entryRef.mkext = (mkext_basic_header *)mkextBuffer;
3321 	entryRef.fileinfo = mkextBuffer + entryOffset;
3322 	if (!result->appendValue(entryRef)) {
3323 		result.reset();
3324 		goto finish;
3325 	}
3326 
3327 finish:
3328 	if (!result) {
3329 		OSKextLog(this,
3330 		    kOSKextLogErrorLevel |
3331 		    kOSKextLogArchiveFlag,
3332 		    "Can't create wrapper for mkext file entry '%s' of kext %s.",
3333 		    name, getIdentifierCString());
3334 	}
3335 	return result;
3336 }
3337 
3338 /*********************************************************************
3339 *********************************************************************/
3340 extern "C" {
3341 static void * z_alloc(void *, u_int items, u_int size);
3342 static void   z_free(void *, void *ptr);
3343 
3344 typedef struct z_mem {
3345 	uint32_t alloc_size;
3346 	uint8_t  data[0];
3347 } z_mem;
3348 
3349 /*
3350  * Space allocation and freeing routines for use by zlib routines.
3351  */
3352 void *
z_alloc(void * notused __unused,u_int num_items,u_int size)3353 z_alloc(void * notused __unused, u_int num_items, u_int size)
3354 {
3355 	void     * result = NULL;
3356 	z_mem    * zmem = NULL;
3357 
3358 	uint64_t   total = ((uint64_t)num_items) * ((uint64_t)size);
3359 	//Check for overflow due to multiplication
3360 	if (total > UINT32_MAX) {
3361 		panic("z_alloc(%p, %x, %x): overflow caused by %x * %x",
3362 		    notused, num_items, size, num_items, size);
3363 	}
3364 
3365 	uint64_t   allocSize64 =  total + ((uint64_t)sizeof(zmem));
3366 	//Check for overflow due to addition
3367 	if (allocSize64 > UINT32_MAX) {
3368 		panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx",
3369 		    notused, num_items, size, (uint32_t)total, sizeof(zmem));
3370 	}
3371 	uint32_t allocSize = (uint32_t)allocSize64;
3372 
3373 	zmem = (z_mem *)kalloc_data_tag(allocSize, Z_WAITOK,
3374 	    VM_KERN_MEMORY_OSKEXT);
3375 	if (!zmem) {
3376 		goto finish;
3377 	}
3378 	zmem->alloc_size = allocSize;
3379 	result = (void *)&(zmem->data);
3380 finish:
3381 	return result;
3382 }
3383 
3384 void
z_free(void * notused __unused,void * ptr)3385 z_free(void * notused __unused, void * ptr)
3386 {
3387 	uint32_t * skipper = (uint32_t *)ptr - 1;
3388 	z_mem    * zmem = (z_mem *)skipper;
3389 	kfree_data(zmem, zmem->alloc_size);
3390 }
3391 };
3392 
3393 OSSharedPtr<OSData>
extractMkext2FileData(UInt8 * data,const char * name,uint32_t compressedSize,uint32_t fullSize)3394 OSKext::extractMkext2FileData(
3395 	UInt8      * data,
3396 	const char * name,
3397 	uint32_t     compressedSize,
3398 	uint32_t     fullSize)
3399 {
3400 	OSSharedPtr<OSData>      result;
3401 	OSSharedPtr<OSData>      uncompressedData;        // release on error
3402 
3403 	uint8_t     * uncompressedDataBuffer = NULL;        // do not free
3404 	unsigned long uncompressedSize;
3405 	z_stream      zstream;
3406 	bool          zstream_inited = false;
3407 	int           zlib_result;
3408 
3409 	/* If the file isn't compressed, we want to make a copy
3410 	 * so that we don't have the tie to the larger mkext file buffer any more.
3411 	 */
3412 	if (!compressedSize) {
3413 		uncompressedData = OSData::withBytes(data, fullSize);
3414 		// xxx - no check for failure?
3415 		result = uncompressedData;
3416 		goto finish;
3417 	}
3418 
3419 	if (KERN_SUCCESS != kmem_alloc(kernel_map,
3420 	    (vm_offset_t*)&uncompressedDataBuffer, fullSize,
3421 	    KMA_DATA, VM_KERN_MEMORY_OSKEXT)) {
3422 		/* How's this for cheesy? The kernel is only asked to extract
3423 		 * kext plists so we tailor the log messages.
3424 		 */
3425 		if (isKernel()) {
3426 			OSKextLog(this,
3427 			    kOSKextLogErrorLevel |
3428 			    kOSKextLogArchiveFlag,
3429 			    "Allocation failure extracting %s from mkext.", name);
3430 		} else {
3431 			OSKextLog(this,
3432 			    kOSKextLogErrorLevel |
3433 			    kOSKextLogArchiveFlag,
3434 			    "Allocation failure extracting %s from mkext for kext %s.",
3435 			    name, getIdentifierCString());
3436 		}
3437 
3438 		goto finish;
3439 	}
3440 	uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3441 	if (!uncompressedData) {
3442 		if (isKernel()) {
3443 			OSKextLog(this,
3444 			    kOSKextLogErrorLevel |
3445 			    kOSKextLogArchiveFlag,
3446 			    "Allocation failure extracting %s from mkext.", name);
3447 		} else {
3448 			OSKextLog(this,
3449 			    kOSKextLogErrorLevel |
3450 			    kOSKextLogArchiveFlag,
3451 			    "Allocation failure extracting %s from mkext for kext %s.",
3452 			    name, getIdentifierCString());
3453 		}
3454 		goto finish;
3455 	}
3456 	uncompressedData->setDeallocFunction(&osdata_kmem_free);
3457 
3458 	if (isKernel()) {
3459 		OSKextLog(this,
3460 		    kOSKextLogDetailLevel |
3461 		    kOSKextLogArchiveFlag,
3462 		    "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3463 		    name, compressedSize, fullSize);
3464 	} else {
3465 		OSKextLog(this,
3466 		    kOSKextLogDetailLevel |
3467 		    kOSKextLogArchiveFlag,
3468 		    "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3469 		    getIdentifierCString(), name, compressedSize, fullSize);
3470 	}
3471 
3472 	bzero(&zstream, sizeof(zstream));
3473 	zstream.next_in   = (UInt8 *)data;
3474 	zstream.avail_in  = compressedSize;
3475 
3476 	zstream.next_out  = uncompressedDataBuffer;
3477 	zstream.avail_out = fullSize;
3478 
3479 	zstream.zalloc    = z_alloc;
3480 	zstream.zfree     = z_free;
3481 
3482 	zlib_result = inflateInit(&zstream);
3483 	if (Z_OK != zlib_result) {
3484 		if (isKernel()) {
3485 			OSKextLog(this,
3486 			    kOSKextLogErrorLevel |
3487 			    kOSKextLogArchiveFlag,
3488 			    "Mkext error; zlib inflateInit failed (%d) for %s.",
3489 			    zlib_result, name);
3490 		} else {
3491 			OSKextLog(this,
3492 			    kOSKextLogErrorLevel |
3493 			    kOSKextLogArchiveFlag,
3494 			    "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3495 			    getIdentifierCString(), zlib_result, name);
3496 		}
3497 		goto finish;
3498 	} else {
3499 		zstream_inited = true;
3500 	}
3501 
3502 	zlib_result = inflate(&zstream, Z_FINISH);
3503 
3504 	if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3505 		uncompressedSize = zstream.total_out;
3506 	} else {
3507 		if (isKernel()) {
3508 			OSKextLog(this,
3509 			    kOSKextLogErrorLevel |
3510 			    kOSKextLogArchiveFlag,
3511 			    "Mkext error; zlib inflate failed (%d) for %s.",
3512 			    zlib_result, name);
3513 		} else {
3514 			OSKextLog(this,
3515 			    kOSKextLogErrorLevel |
3516 			    kOSKextLogArchiveFlag,
3517 			    "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3518 			    getIdentifierCString(), zlib_result, name);
3519 		}
3520 		if (zstream.msg) {
3521 			OSKextLog(this,
3522 			    kOSKextLogErrorLevel |
3523 			    kOSKextLogArchiveFlag,
3524 			    "zlib error: %s.", zstream.msg);
3525 		}
3526 		goto finish;
3527 	}
3528 
3529 	if (uncompressedSize != fullSize) {
3530 		if (isKernel()) {
3531 			OSKextLog(this,
3532 			    kOSKextLogErrorLevel |
3533 			    kOSKextLogArchiveFlag,
3534 			    "Mkext error; zlib inflate discrepancy for %s, "
3535 			    "uncompressed size != original size.", name);
3536 		} else {
3537 			OSKextLog(this,
3538 			    kOSKextLogErrorLevel |
3539 			    kOSKextLogArchiveFlag,
3540 			    "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3541 			    "uncompressed size != original size.",
3542 			    getIdentifierCString(), name);
3543 		}
3544 		goto finish;
3545 	}
3546 
3547 	result = os::move(uncompressedData);
3548 
3549 finish:
3550 	/* Don't bother checking return, nothing we can do on fail.
3551 	 */
3552 	if (zstream_inited) {
3553 		inflateEnd(&zstream);
3554 	}
3555 
3556 	return result;
3557 }
3558 
3559 /*********************************************************************
3560 *********************************************************************/
3561 /* static */
3562 OSReturn
loadFromMkext(OSKextLogSpec clientLogFilter,char * mkextBuffer,uint32_t mkextBufferLength,char ** logInfoOut,uint32_t * logInfoLengthOut)3563 OSKext::loadFromMkext(
3564 	OSKextLogSpec   clientLogFilter,
3565 	char          * mkextBuffer,
3566 	uint32_t        mkextBufferLength,
3567 	char         ** logInfoOut,
3568 	uint32_t      * logInfoLengthOut)
3569 {
3570 	OSReturn         result                      = kOSReturnError;
3571 	OSReturn         tempResult                  = kOSReturnError;
3572 
3573 	OSSharedPtr<OSData>        mkextData;
3574 	OSSharedPtr<OSDictionary>  mkextPlist;
3575 
3576 	OSSharedPtr<OSArray>       logInfoArray;
3577 	OSSharedPtr<OSSerialize>   serializer;
3578 
3579 	OSString       * predicate                   = NULL;        // do not release
3580 	OSDictionary   * requestArgs                 = NULL;        // do not release
3581 
3582 	OSString       * kextIdentifier              = NULL;        // do not release
3583 	OSNumber       * startKextExcludeNum         = NULL;        // do not release
3584 	OSNumber       * startMatchingExcludeNum     = NULL;        // do not release
3585 	OSBoolean      * delayAutounloadBool         = NULL;        // do not release
3586 	OSArray        * personalityNames            = NULL;        // do not release
3587 
3588 	/* Default values for these two options: regular autounload behavior,
3589 	 * load all kexts, send no personalities.
3590 	 */
3591 	Boolean            delayAutounload           = false;
3592 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
3593 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3594 
3595 	IORecursiveLockLock(sKextLock);
3596 
3597 	if (logInfoOut) {
3598 		*logInfoOut = NULL;
3599 		*logInfoLengthOut = 0;
3600 	}
3601 
3602 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3603 
3604 	OSKextLog(/* kext */ NULL,
3605 	    kOSKextLogDebugLevel |
3606 	    kOSKextLogIPCFlag,
3607 	    "Received kext load request from user space.");
3608 
3609 	/* Regardless of processing, the fact that we have gotten here means some
3610 	 * user-space program is up and talking to us, so we'll switch our kext
3611 	 * registration to reflect that.
3612 	 */
3613 	if (!sUserLoadsActive) {
3614 		OSKextLog(/* kext */ NULL,
3615 		    kOSKextLogProgressLevel |
3616 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3617 		    "Switching to late startup (user-space) kext loading policy.");
3618 
3619 		sUserLoadsActive = true;
3620 	}
3621 
3622 	if (!sLoadEnabled) {
3623 		OSKextLog(/* kext */ NULL,
3624 		    kOSKextLogErrorLevel |
3625 		    kOSKextLogLoadFlag,
3626 		    "Kext loading is disabled.");
3627 		result = kOSKextReturnDisabled;
3628 		goto finish;
3629 	}
3630 
3631 	/* Note that we do not set a dealloc function on this OSData
3632 	 * object! No references to it can remain after the loadFromMkext()
3633 	 * call since we are in a MIG function, and will vm_deallocate()
3634 	 * the buffer.
3635 	 */
3636 	mkextData = OSData::withBytesNoCopy(mkextBuffer,
3637 	    mkextBufferLength);
3638 	if (!mkextData) {
3639 		OSKextLog(/* kext */ NULL,
3640 		    kOSKextLogErrorLevel |
3641 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3642 		    "Failed to create wrapper for kext load request.");
3643 		result = kOSKextReturnNoMemory;
3644 		goto finish;
3645 	}
3646 
3647 	result = readMkext2Archive(mkextData.get(), mkextPlist, NULL);
3648 	if (result != kOSReturnSuccess) {
3649 		OSKextLog(/* kext */ NULL,
3650 		    kOSKextLogErrorLevel |
3651 		    kOSKextLogLoadFlag,
3652 		    "Failed to read kext load request.");
3653 		goto finish;
3654 	}
3655 
3656 	predicate = _OSKextGetRequestPredicate(mkextPlist.get());
3657 	if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3658 		OSKextLog(/* kext */ NULL,
3659 		    kOSKextLogErrorLevel |
3660 		    kOSKextLogLoadFlag,
3661 		    "Received kext load request with no predicate; skipping.");
3662 		result = kOSKextReturnInvalidArgument;
3663 		goto finish;
3664 	}
3665 
3666 	requestArgs = OSDynamicCast(OSDictionary,
3667 	    mkextPlist->getObject(kKextRequestArgumentsKey));
3668 	if (!requestArgs || !requestArgs->getCount()) {
3669 		OSKextLog(/* kext */ NULL,
3670 		    kOSKextLogErrorLevel |
3671 		    kOSKextLogLoadFlag,
3672 		    "Received kext load request with no arguments.");
3673 		result = kOSKextReturnInvalidArgument;
3674 		goto finish;
3675 	}
3676 
3677 	kextIdentifier = OSDynamicCast(OSString,
3678 	    requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3679 
3680 	if (!kextIdentifier) {
3681 		OSKextLog(/* kext */ NULL,
3682 		    kOSKextLogErrorLevel |
3683 		    kOSKextLogLoadFlag,
3684 		    "Received kext load request with no kext identifier.");
3685 		result = kOSKextReturnInvalidArgument;
3686 		goto finish;
3687 	}
3688 
3689 	startKextExcludeNum = OSDynamicCast(OSNumber,
3690 	    requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3691 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
3692 	    requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3693 	delayAutounloadBool = OSDynamicCast(OSBoolean,
3694 	    requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3695 	personalityNames = OSDynamicCast(OSArray,
3696 	    requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3697 
3698 	if (delayAutounloadBool) {
3699 		delayAutounload = delayAutounloadBool->getValue();
3700 	}
3701 	if (startKextExcludeNum) {
3702 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3703 	}
3704 	if (startMatchingExcludeNum) {
3705 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3706 	}
3707 
3708 	OSKextLog(/* kext */ NULL,
3709 	    kOSKextLogProgressLevel |
3710 	    kOSKextLogIPCFlag,
3711 	    "Received request from user space to load kext %s.",
3712 	    kextIdentifier->getCStringNoCopy());
3713 
3714 	/* Load the kext, with no deferral, since this is a load from outside
3715 	 * the kernel.
3716 	 * xxx - Would like a better way to handle the default values for the
3717 	 * xxx - start/match opt args.
3718 	 */
3719 	result = OSKext::loadKextWithIdentifier(
3720 		kextIdentifier,
3721 		/* kextRef */ NULL,
3722 		/* allowDefer */ false,
3723 		delayAutounload,
3724 		startKextExcludeLevel,
3725 		startMatchingExcludeLevel,
3726 		personalityNames);
3727 	if (result != kOSReturnSuccess) {
3728 		goto finish;
3729 	}
3730 	/* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue
3731 	 * for matching via a separate IOKit calldown.
3732 	 */
3733 
3734 finish:
3735 
3736 	/* Gather up the collected log messages for user space. Any
3737 	 * error messages past this call will not make it up as log messages
3738 	 * but will be in the system log.
3739 	 */
3740 	logInfoArray = OSKext::clearUserSpaceLogFilter();
3741 
3742 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
3743 		tempResult = OSKext::serializeLogInfo(logInfoArray.get(),
3744 		    logInfoOut, logInfoLengthOut);
3745 		if (tempResult != kOSReturnSuccess) {
3746 			result = tempResult;
3747 		}
3748 	}
3749 
3750 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3751 
3752 	IORecursiveLockUnlock(sKextLock);
3753 
3754 	/* Note: mkextDataObject will have been retained by every kext w/an
3755 	 * executable in it. That should all have been flushed out at the
3756 	 * and of the load operation, but you never know....
3757 	 */
3758 	if (mkextData && mkextData->getRetainCount() > 1) {
3759 		OSKextLog(/* kext */ NULL,
3760 		    kOSKextLogErrorLevel |
3761 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3762 		    "Kext load request buffer from user space still retained by a kext; "
3763 		    "probable memory leak.");
3764 	}
3765 
3766 	return result;
3767 }
3768 
3769 #endif // CONFIG_KXLD
3770 
3771 /*********************************************************************
3772 *********************************************************************/
3773 /* static */
3774 OSReturn
serializeLogInfo(OSArray * logInfoArray,char ** logInfoOut,uint32_t * logInfoLengthOut)3775 OSKext::serializeLogInfo(
3776 	OSArray   * logInfoArray,
3777 	char     ** logInfoOut,
3778 	uint32_t  * logInfoLengthOut)
3779 {
3780 	OSReturn        result      = kOSReturnError;
3781 	char          * buffer      = NULL;
3782 	kern_return_t   kmem_result = KERN_FAILURE;
3783 	OSSharedPtr<OSSerialize>  serializer;
3784 	char         * logInfo            = NULL;        // returned by reference
3785 	uint32_t       logInfoLength      = 0;
3786 
3787 	if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
3788 		OSKextLog(/* kext */ NULL,
3789 		    kOSKextLogErrorLevel |
3790 		    kOSKextLogIPCFlag,
3791 		    "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3792 		/* Bad programmer. */
3793 		result = kOSKextReturnInvalidArgument;
3794 		goto finish;
3795 	}
3796 
3797 	serializer = OSSerialize::withCapacity(0);
3798 	if (!serializer) {
3799 		OSKextLog(/* kext */ NULL,
3800 		    kOSKextLogErrorLevel |
3801 		    kOSKextLogIPCFlag,
3802 		    "Failed to create serializer on log info for request from user space.");
3803 		/* Incidental error; we're going to (try to) allow the request
3804 		 * itself to succeed. */
3805 	}
3806 
3807 	if (!logInfoArray->serialize(serializer.get())) {
3808 		OSKextLog(/* kext */ NULL,
3809 		    kOSKextLogErrorLevel |
3810 		    kOSKextLogIPCFlag,
3811 		    "Failed to serialize log info for request from user space.");
3812 		/* Incidental error; we're going to (try to) allow the request
3813 		 * itself to succeed. */
3814 	} else {
3815 		logInfo = serializer->text();
3816 		logInfoLength = serializer->getLength();
3817 
3818 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength),
3819 		    KMA_DATA, VM_KERN_MEMORY_OSKEXT);
3820 		if (kmem_result != KERN_SUCCESS) {
3821 			OSKextLog(/* kext */ NULL,
3822 			    kOSKextLogErrorLevel |
3823 			    kOSKextLogIPCFlag,
3824 			    "Failed to copy log info for request from user space.");
3825 			/* Incidental error; we're going to (try to) allow the request
3826 			 * to succeed. */
3827 		} else {
3828 			/* 11981737 - clear uninitialized data in last page */
3829 			bzero((void *)(buffer + logInfoLength),
3830 			    (round_page(logInfoLength) - logInfoLength));
3831 			memcpy(buffer, logInfo, logInfoLength);
3832 			*logInfoOut = buffer;
3833 			*logInfoLengthOut = logInfoLength;
3834 		}
3835 	}
3836 
3837 	result = kOSReturnSuccess;
3838 finish:
3839 	return result;
3840 }
3841 
3842 #if PRAGMA_MARK
3843 #pragma mark Instance Management Methods
3844 #endif
3845 /*********************************************************************
3846 *********************************************************************/
3847 OSSharedPtr<OSKext>
lookupKextWithIdentifier(const char * kextIdentifier)3848 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
3849 {
3850 	OSSharedPtr<OSKext> foundKext;
3851 
3852 	IORecursiveLockLock(sKextLock);
3853 	foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain);
3854 	IORecursiveLockUnlock(sKextLock);
3855 
3856 	return foundKext;
3857 }
3858 
3859 /*********************************************************************
3860 *********************************************************************/
3861 OSSharedPtr<OSKext>
lookupKextWithIdentifier(OSString * kextIdentifier)3862 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
3863 {
3864 	return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
3865 }
3866 
3867 /*********************************************************************
3868 *********************************************************************/
3869 OSSharedPtr<OSKext>
lookupKextWithLoadTag(uint32_t aTag)3870 OSKext::lookupKextWithLoadTag(uint32_t aTag)
3871 {
3872 	OSSharedPtr<OSKext> foundKext;             // returned
3873 	uint32_t i, j;
3874 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
3875 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3876 
3877 	IORecursiveLockLock(sKextLock);
3878 
3879 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3880 		for (i = 0; i < count[j]; i++) {
3881 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3882 			if (thisKext->getLoadTag() == aTag) {
3883 				foundKext.reset(thisKext, OSRetain);
3884 				goto finish;
3885 			}
3886 		}
3887 	}
3888 
3889 finish:
3890 	IORecursiveLockUnlock(sKextLock);
3891 
3892 	return foundKext;
3893 }
3894 
3895 /*********************************************************************
3896 *********************************************************************/
3897 OSSharedPtr<OSKext>
lookupKextWithAddress(vm_address_t address)3898 OSKext::lookupKextWithAddress(vm_address_t address)
3899 {
3900 	OSSharedPtr<OSKext> foundKext;             // returned
3901 	uint32_t count, i;
3902 	kmod_info_t *kmod_info;
3903 	vm_address_t originalAddress;
3904 #if defined(__arm64__)
3905 	uint64_t   textExecBase;
3906 	size_t     textExecSize;
3907 #endif /* defined(__arm64__) */
3908 
3909 	originalAddress = address;
3910 #if  __has_feature(ptrauth_calls)
3911 	address = (vm_address_t)VM_KERNEL_STRIP_PTR(address);
3912 #endif /*  __has_feature(ptrauth_calls) */
3913 
3914 	IORecursiveLockLock(sKextLock);
3915 
3916 	count = sLoadedKexts->getCount();
3917 	for (i = 0; i < count; i++) {
3918 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3919 		if (thisKext == sKernelKext) {
3920 			continue;
3921 		}
3922 		if (thisKext->kmod_info && thisKext->kmod_info->address) {
3923 			kmod_info = thisKext->kmod_info;
3924 			vm_address_t kext_start = kmod_info->address;
3925 			vm_address_t kext_end = kext_start + kmod_info->size;
3926 			if ((kext_start <= address) && (address < kext_end)) {
3927 				foundKext.reset(thisKext, OSRetain);
3928 				goto finish;
3929 			}
3930 #if defined(__arm64__)
3931 			textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize);
3932 			if ((textExecBase <= address) && (address < textExecBase + textExecSize)) {
3933 				foundKext.reset(thisKext, OSRetain);
3934 				goto finish;
3935 			}
3936 #endif /* defined (__arm64__) */
3937 		}
3938 	}
3939 	if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) {
3940 		foundKext.reset(sKernelKext, OSRetain);
3941 		goto finish;
3942 	}
3943 	/*
3944 	 * DriverKit userspace executables do not have a kernel linkedExecutable,
3945 	 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address
3946 	 * here, so use the original address passed to this method.
3947 	 *
3948 	 * This is supposed to be used for logging reasons only. When logd
3949 	 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
3950 	 * remove it here before checking it against the LoadTag.
3951 	 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
3952 	 */
3953 
3954 	address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
3955 	count = sLoadedDriverKitKexts->getCount();
3956 	for (i = 0; i < count; i++) {
3957 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
3958 		if (thisKext->getLoadTag() == address) {
3959 			foundKext.reset(thisKext, OSRetain);
3960 		}
3961 	}
3962 
3963 finish:
3964 	IORecursiveLockUnlock(sKextLock);
3965 
3966 	return foundKext;
3967 }
3968 
3969 OSSharedPtr<OSData>
copyKextUUIDForAddress(OSNumber * address)3970 OSKext::copyKextUUIDForAddress(OSNumber *address)
3971 {
3972 	OSSharedPtr<OSData>   uuid;
3973 	OSSharedPtr<OSKext>   kext;
3974 
3975 	if (!address) {
3976 		return NULL;
3977 	}
3978 
3979 #if CONFIG_MACF
3980 	/* Is the calling process allowed to query kext info? */
3981 	if (current_task() != kernel_task) {
3982 		int macCheckResult = 0;
3983 		kauth_cred_t cred = NULL;
3984 
3985 		cred = kauth_cred_get_with_ref();
3986 		macCheckResult = mac_kext_check_query(cred);
3987 		kauth_cred_unref(&cred);
3988 
3989 		if (macCheckResult != 0) {
3990 			OSKextLog(/* kext */ NULL,
3991 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
3992 			    "Failed to query kext UUID (MAC policy error 0x%x).",
3993 			    macCheckResult);
3994 			return NULL;
3995 		}
3996 	}
3997 #endif
3998 
3999 	uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue());
4000 	if (slidAddress != 0) {
4001 		kext = lookupKextWithAddress(slidAddress);
4002 		if (kext) {
4003 			uuid = kext->copyTextUUID();
4004 		}
4005 	}
4006 
4007 	if (!uuid) {
4008 		/*
4009 		 * If we still don't have a UUID, then we failed to match the slid + stripped address with
4010 		 * a kext. This might have happened because the log message came from a dext.
4011 		 *
4012 		 * Try again with the original address.
4013 		 */
4014 		kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue());
4015 		if (kext && kext->isDriverKit()) {
4016 			uuid = kext->copyTextUUID();
4017 		}
4018 	}
4019 
4020 	return uuid;
4021 }
4022 
4023 /*********************************************************************
4024 *********************************************************************/
4025 OSSharedPtr<OSKext>
lookupKextWithUUID(uuid_t wanted)4026 OSKext::lookupKextWithUUID(uuid_t wanted)
4027 {
4028 	OSSharedPtr<OSKext> foundKext;             // returned
4029 	uint32_t j, i;
4030 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4031 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4032 
4033 
4034 	IORecursiveLockLock(sKextLock);
4035 
4036 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4037 		for (i = 0; i < count[j]; i++) {
4038 			OSKext   * thisKext     = NULL;
4039 
4040 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4041 			if (!thisKext) {
4042 				continue;
4043 			}
4044 
4045 			OSSharedPtr<OSData> uuid_data = thisKext->copyUUID();
4046 			if (!uuid_data) {
4047 				continue;
4048 			}
4049 
4050 			uuid_t uuid;
4051 			memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
4052 
4053 			if (0 == uuid_compare(wanted, uuid)) {
4054 				foundKext.reset(thisKext, OSRetain);
4055 				goto finish;
4056 			}
4057 		}
4058 	}
4059 finish:
4060 	IORecursiveLockUnlock(sKextLock);
4061 
4062 	return foundKext;
4063 }
4064 
4065 
4066 
4067 
4068 /*********************************************************************
4069 *********************************************************************/
4070 /* static */
4071 bool
isKextWithIdentifierLoaded(const char * kextIdentifier)4072 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
4073 {
4074 	bool result = false;
4075 	OSKext * foundKext = NULL;             // returned
4076 
4077 	IORecursiveLockLock(sKextLock);
4078 
4079 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4080 	if (foundKext && foundKext->isLoaded()) {
4081 		result = true;
4082 	}
4083 
4084 	IORecursiveLockUnlock(sKextLock);
4085 
4086 	return result;
4087 }
4088 
4089 /*********************************************************************
4090 * xxx - should spawn a separate thread so a kext can safely have
4091 * xxx - itself unloaded.
4092 *********************************************************************/
4093 /* static */
4094 OSReturn
removeKext(OSKext * aKext,__unused bool terminateServicesAndRemovePersonalitiesFlag)4095 OSKext::removeKext(
4096 	OSKext * aKext,
4097 #if CONFIG_EMBEDDED
4098 	__unused
4099 #endif
4100 	bool     terminateServicesAndRemovePersonalitiesFlag)
4101 {
4102 #if CONFIG_EMBEDDED
4103 	OSKextLog(aKext,
4104 	    kOSKextLogErrorLevel |
4105 	    kOSKextLogKextBookkeepingFlag,
4106 	    "removeKext() called for %s, not supported on embedded",
4107 	    aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
4108 
4109 	return kOSReturnSuccess;
4110 #else /* CONFIG_EMBEDDED */
4111 
4112 	OSReturn result    = kOSKextReturnInUse;
4113 	OSKext * checkKext = NULL;         // do not release
4114 #if CONFIG_MACF
4115 	int macCheckResult = 0;
4116 	kauth_cred_t cred  = NULL;
4117 #endif
4118 
4119 	IORecursiveLockLock(sKextLock);
4120 
4121 	/* If the kext has no identifier, it failed to init
4122 	 * so isn't in sKextsByID and it isn't loaded.
4123 	 */
4124 	if (!aKext->getIdentifier()) {
4125 		result = kOSReturnSuccess;
4126 		goto finish;
4127 	}
4128 
4129 	checkKext = OSDynamicCast(OSKext,
4130 	    sKextsByID->getObject(aKext->getIdentifier()));
4131 	if (checkKext != aKext) {
4132 		result = kOSKextReturnNotFound;
4133 		goto finish;
4134 	}
4135 
4136 	if (aKext->isLoaded()) {
4137 #if CONFIG_MACF
4138 		if (current_task() != kernel_task) {
4139 			cred = kauth_cred_get_with_ref();
4140 			macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
4141 			kauth_cred_unref(&cred);
4142 		}
4143 
4144 		if (macCheckResult != 0) {
4145 			result = kOSReturnError;
4146 			OSKextLog(aKext,
4147 			    kOSKextLogErrorLevel |
4148 			    kOSKextLogKextBookkeepingFlag,
4149 			    "Failed to remove kext %s (MAC policy error 0x%x).",
4150 			    aKext->getIdentifierCString(), macCheckResult);
4151 			goto finish;
4152 		}
4153 #endif
4154 
4155 		/* make sure there are no resource requests in flight - 17187548 */
4156 		if (aKext->countRequestCallbacks()) {
4157 			goto finish;
4158 		}
4159 		if (aKext->flags.unloadUnsupported) {
4160 			result = kOSKextReturnInUse;
4161 			OSKextLog(aKext,
4162 			    kOSKextLogErrorLevel |
4163 			    kOSKextLogKextBookkeepingFlag,
4164 			    "Can't remove kext %s; unsupported by cache.",
4165 			    aKext->getIdentifierCString());
4166 			goto finish;
4167 		}
4168 
4169 		/* If we are terminating, send the request to the IOCatalogue
4170 		 * (which will actually call us right back but that's ok we have
4171 		 * a recursive lock don't you know) but do not ask the IOCatalogue
4172 		 * to call back with an unload, we'll do that right here.
4173 		 */
4174 		if (terminateServicesAndRemovePersonalitiesFlag) {
4175 			result = gIOCatalogue->terminateDriversForModule(
4176 				aKext->getIdentifierCString(), /* unload */ false);
4177 			if (result != kOSReturnSuccess) {
4178 				OSKextLog(aKext,
4179 				    kOSKextLogErrorLevel |
4180 				    kOSKextLogKextBookkeepingFlag,
4181 				    "Can't remove kext %s; services failed to terminate - 0x%x.",
4182 				    aKext->getIdentifierCString(), result);
4183 				goto finish;
4184 			}
4185 		}
4186 
4187 		result = aKext->unload();
4188 		if (result != kOSReturnSuccess) {
4189 			goto finish;
4190 		}
4191 	}
4192 
4193 	/* Remove personalities as requested. This is a bit redundant for a loaded
4194 	 * kext as IOCatalogue::terminateDriversForModule() removes driver
4195 	 * personalities, but it doesn't restart matching, which we always want
4196 	 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
4197 	 * that happens.
4198 	 */
4199 	if (terminateServicesAndRemovePersonalitiesFlag) {
4200 		aKext->removePersonalitiesFromCatalog();
4201 	}
4202 
4203 	if (aKext->isInFileset()) {
4204 		OSKextLog(aKext,
4205 		    kOSKextLogProgressLevel |
4206 		    kOSKextLogKextBookkeepingFlag,
4207 		    "Fileset kext %s unloaded.",
4208 		    aKext->getIdentifierCString());
4209 	} else {
4210 		OSKextLog(aKext,
4211 		    kOSKextLogProgressLevel |
4212 		    kOSKextLogKextBookkeepingFlag,
4213 		    "Removing kext %s.",
4214 		    aKext->getIdentifierCString());
4215 
4216 		sKextsByID->removeObject(aKext->getIdentifier());
4217 	}
4218 	result = kOSReturnSuccess;
4219 
4220 finish:
4221 	IORecursiveLockUnlock(sKextLock);
4222 	return result;
4223 #endif /* CONFIG_EMBEDDED */
4224 }
4225 
4226 /*********************************************************************
4227 *********************************************************************/
4228 /* static */
4229 OSReturn
removeKextWithIdentifier(const char * kextIdentifier,bool terminateServicesAndRemovePersonalitiesFlag)4230 OSKext::removeKextWithIdentifier(
4231 	const char * kextIdentifier,
4232 	bool         terminateServicesAndRemovePersonalitiesFlag)
4233 {
4234 	OSReturn result = kOSReturnError;
4235 
4236 	IORecursiveLockLock(sKextLock);
4237 
4238 	OSKext * aKext = OSDynamicCast(OSKext,
4239 	    sKextsByID->getObject(kextIdentifier));
4240 	if (!aKext) {
4241 		result = kOSKextReturnNotFound;
4242 		OSKextLog(/* kext */ NULL,
4243 		    kOSKextLogErrorLevel |
4244 		    kOSKextLogKextBookkeepingFlag,
4245 		    "Can't remove kext %s - not found.",
4246 		    kextIdentifier);
4247 		goto finish;
4248 	}
4249 
4250 	result = OSKext::removeKext(aKext,
4251 	    terminateServicesAndRemovePersonalitiesFlag);
4252 
4253 finish:
4254 	IORecursiveLockUnlock(sKextLock);
4255 
4256 	return result;
4257 }
4258 
4259 /*********************************************************************
4260 *********************************************************************/
4261 /* static */
4262 OSReturn
removeKextWithLoadTag(OSKextLoadTag loadTag,bool terminateServicesAndRemovePersonalitiesFlag)4263 OSKext::removeKextWithLoadTag(
4264 	OSKextLoadTag loadTag,
4265 	bool          terminateServicesAndRemovePersonalitiesFlag)
4266 {
4267 	OSReturn result    = kOSReturnError;
4268 	OSKext * foundKext = NULL;
4269 	uint32_t i, j;
4270 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4271 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4272 
4273 
4274 	IORecursiveLockLock(sKextLock);
4275 
4276 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4277 		for (i = 0; i < count[j]; i++) {
4278 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4279 			if (thisKext->loadTag == loadTag) {
4280 				foundKext = thisKext;
4281 				break;
4282 			}
4283 		}
4284 	}
4285 
4286 	if (!foundKext) {
4287 		result = kOSKextReturnNotFound;
4288 		OSKextLog(/* kext */ NULL,
4289 		    kOSKextLogErrorLevel |
4290 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4291 		    "Can't remove kext with load tag %d - not found.",
4292 		    loadTag);
4293 		goto finish;
4294 	}
4295 
4296 	result = OSKext::removeKext(foundKext,
4297 	    terminateServicesAndRemovePersonalitiesFlag);
4298 
4299 finish:
4300 	IORecursiveLockUnlock(sKextLock);
4301 
4302 	return result;
4303 }
4304 
4305 /*********************************************************************
4306 *********************************************************************/
4307 OSSharedPtr<OSDictionary>
copyKexts(void)4308 OSKext::copyKexts(void)
4309 {
4310 	OSSharedPtr<OSDictionary> result;
4311 
4312 	IORecursiveLockLock(sKextLock);
4313 	result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection());
4314 	IORecursiveLockUnlock(sKextLock);
4315 
4316 	return result;
4317 }
4318 
4319 /*********************************************************************
4320 *********************************************************************/
4321 #define BOOTER_KEXT_PREFIX   "Driver-"
4322 
4323 typedef struct _DeviceTreeBuffer {
4324 	uint32_t paddr;
4325 	uint32_t length;
4326 } _DeviceTreeBuffer;
4327 
4328 /*********************************************************************
4329 * Create a dictionary of excluded kexts from the given booter data.
4330 *********************************************************************/
4331 /* static */
4332 void
createExcludeListFromBooterData(OSDictionary * theDictionary,OSCollectionIterator * theIterator)4333 OSKext::createExcludeListFromBooterData(
4334 	OSDictionary *          theDictionary,
4335 	OSCollectionIterator *  theIterator )
4336 {
4337 	OSString                  * deviceTreeName      = NULL;        // do not release
4338 	const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;        // do not release
4339 	char                      * booterDataPtr       = NULL;        // do not release
4340 	_BooterKextFileInfo       * kextFileInfo        = NULL;        // do not release
4341 	char                      * infoDictAddr        = NULL;        // do not release
4342 	OSSharedPtr<OSObject>       parsedXML;
4343 	OSDictionary              * theInfoDict         = NULL;        // do not release
4344 
4345 	theIterator->reset();
4346 
4347 	/* look for AppleKextExcludeList.kext */
4348 	while ((deviceTreeName =
4349 	    OSDynamicCast(OSString, theIterator->getNextObject()))) {
4350 		const char *    devTreeNameCString;
4351 		OSData *        deviceTreeEntry;        // do not release
4352 		OSString *      myBundleID;        // do not release
4353 
4354 		deviceTreeEntry =
4355 		    OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
4356 		if (!deviceTreeEntry) {
4357 			continue;
4358 		}
4359 
4360 		/* Make sure it is a kext */
4361 		devTreeNameCString = deviceTreeName->getCStringNoCopy();
4362 		if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
4363 		    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
4364 			OSKextLog(NULL,
4365 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4366 			    "\"%s\" not a kext",
4367 			    devTreeNameCString);
4368 			continue;
4369 		}
4370 
4371 		deviceTreeBuffer = (const _DeviceTreeBuffer *)
4372 		    deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
4373 		if (!deviceTreeBuffer) {
4374 			continue;
4375 		}
4376 
4377 		booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
4378 		if (!booterDataPtr) {
4379 			continue;
4380 		}
4381 
4382 		kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
4383 		if (!kextFileInfo->infoDictPhysAddr ||
4384 		    !kextFileInfo->infoDictLength) {
4385 			continue;
4386 		}
4387 
4388 		infoDictAddr = (char *)
4389 		    ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
4390 		if (!infoDictAddr) {
4391 			continue;
4392 		}
4393 
4394 		parsedXML = OSUnserializeXML(infoDictAddr);
4395 		if (!parsedXML) {
4396 			continue;
4397 		}
4398 
4399 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
4400 		if (!theInfoDict) {
4401 			continue;
4402 		}
4403 
4404 		myBundleID =
4405 		    OSDynamicCast(OSString,
4406 		    theInfoDict->getObject(kCFBundleIdentifierKey));
4407 		if (myBundleID &&
4408 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4409 			boolean_t updated = updateExcludeList(theInfoDict);
4410 			if (!updated) {
4411 				/* 25322874 */
4412 				panic("Missing OSKextExcludeList dictionary");
4413 			}
4414 			break;
4415 		}
4416 	}         // while ( (deviceTreeName = ...) )
4417 
4418 	return;
4419 }
4420 
4421 /*********************************************************************
4422 * Create a dictionary of excluded kexts from the given prelink
4423 * info (kernelcache).
4424 *********************************************************************/
4425 /* static */
4426 void
createExcludeListFromPrelinkInfo(OSArray * theInfoArray)4427 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
4428 {
4429 	OSDictionary *  myInfoDict = NULL;        // do not release
4430 	OSString *      myBundleID;        // do not release
4431 	u_int           i;
4432 
4433 	/* Find the Apple Kext Exclude List. */
4434 	for (i = 0; i < theInfoArray->getCount(); i++) {
4435 		myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
4436 		if (!myInfoDict) {
4437 			continue;
4438 		}
4439 		myBundleID =
4440 		    OSDynamicCast(OSString,
4441 		    myInfoDict->getObject(kCFBundleIdentifierKey));
4442 		if (myBundleID &&
4443 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4444 			boolean_t updated = updateExcludeList(myInfoDict);
4445 			if (!updated) {
4446 				/* 25322874 */
4447 				panic("Missing OSKextExcludeList dictionary");
4448 			}
4449 			break;
4450 		}
4451 	}         // for (i = 0; i < theInfoArray->getCount()...
4452 
4453 	return;
4454 }
4455 
4456 /* static */
4457 boolean_t
updateExcludeList(OSDictionary * infoDict)4458 OSKext::updateExcludeList(OSDictionary *infoDict)
4459 {
4460 	OSDictionary *myTempDict = NULL;         // do not free
4461 	OSString     *myTempString = NULL;        // do not free
4462 	OSKextVersion newVersion = 0;
4463 	boolean_t updated = false;
4464 
4465 	if (!infoDict) {
4466 		return false;
4467 	}
4468 
4469 	myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
4470 	if (!myTempDict) {
4471 		return false;
4472 	}
4473 
4474 	myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
4475 	if (!myTempString) {
4476 		return false;
4477 	}
4478 
4479 	newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
4480 	if (newVersion == 0) {
4481 		return false;
4482 	}
4483 
4484 	IORecursiveLockLock(sKextLock);
4485 
4486 	if (newVersion > sExcludeListVersion) {
4487 		sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
4488 		sExcludeListVersion = newVersion;
4489 		updated = true;
4490 	}
4491 
4492 	IORecursiveLockUnlock(sKextLock);
4493 	return updated;
4494 }
4495 
4496 #if PRAGMA_MARK
4497 #pragma mark Accessors
4498 #endif
4499 /*********************************************************************
4500 *********************************************************************/
4501 const OSSymbol *
getIdentifier(void)4502 OSKext::getIdentifier(void)
4503 {
4504 	return bundleID.get();
4505 }
4506 
4507 /*********************************************************************
4508 * A kext must have a bundle identifier to even survive initialization;
4509 * this is guaranteed to exist past then.
4510 *********************************************************************/
4511 const char *
getIdentifierCString(void)4512 OSKext::getIdentifierCString(void)
4513 {
4514 	return bundleID->getCStringNoCopy();
4515 }
4516 
4517 /*********************************************************************
4518 *********************************************************************/
4519 OSKextVersion
getVersion(void)4520 OSKext::getVersion(void)
4521 {
4522 	return version;
4523 }
4524 
4525 /*********************************************************************
4526 *********************************************************************/
4527 OSKextVersion
getCompatibleVersion(void)4528 OSKext::getCompatibleVersion(void)
4529 {
4530 	return compatibleVersion;
4531 }
4532 
4533 /*********************************************************************
4534 *********************************************************************/
4535 bool
isLibrary(void)4536 OSKext::isLibrary(void)
4537 {
4538 	return getCompatibleVersion() > 0;
4539 }
4540 
4541 /*********************************************************************
4542 *********************************************************************/
4543 bool
isCompatibleWithVersion(OSKextVersion aVersion)4544 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
4545 {
4546 	if ((compatibleVersion > -1 && version > -1) &&
4547 	    (compatibleVersion <= version && aVersion <= version)) {
4548 		return true;
4549 	}
4550 	return false;
4551 }
4552 
4553 /*********************************************************************
4554 *********************************************************************/
4555 bool
declaresExecutable(void)4556 OSKext::declaresExecutable(void)
4557 {
4558 	if (isDriverKit()) {
4559 		return false;
4560 	}
4561 	return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
4562 }
4563 
4564 /*********************************************************************
4565 *********************************************************************/
4566 OSData *
getExecutable(void)4567 OSKext::getExecutable(void)
4568 {
4569 	OSData * result              = NULL;
4570 	OSSharedPtr<OSData> extractedExecutable;
4571 
4572 	if (flags.builtin) {
4573 		return sKernelKext->linkedExecutable.get();
4574 	}
4575 
4576 	result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
4577 	if (result) {
4578 		return result;
4579 	}
4580 
4581 #if CONFIG_KXLD
4582 	OSData * mkextExecutableRef  = NULL;        // do not release
4583 	mkextExecutableRef = OSDynamicCast(OSData,
4584 	    getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
4585 
4586 	if (mkextExecutableRef) {
4587 		MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
4588 		    mkextExecutableRef->getBytesNoCopy();
4589 		uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
4590 		if (mkextVersion == MKEXT_VERS_2) {
4591 			mkext2_file_entry * fileinfo =
4592 			    (mkext2_file_entry *)mkextEntryRef->fileinfo;
4593 			uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
4594 			uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
4595 			extractedExecutable = extractMkext2FileData(
4596 				MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
4597 				compressedSize, fullSize);
4598 		} else {
4599 			OSKextLog(this, kOSKextLogErrorLevel |
4600 			    kOSKextLogArchiveFlag,
4601 			    "Kext %s - unknown mkext version 0x%x for executable.",
4602 			    getIdentifierCString(), mkextVersion);
4603 		}
4604 
4605 		/* Regardless of success, remove the mkext executable,
4606 		 * and drop one reference on the mkext.  (setExecutable() does not
4607 		 * replace, it removes, or panics if asked to replace.)
4608 		 */
4609 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4610 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4611 
4612 		if (extractedExecutable && extractedExecutable->getLength()) {
4613 			if (!setExecutable(extractedExecutable.get())) {
4614 				goto finish;
4615 			}
4616 			result = extractedExecutable.get();
4617 		} else {
4618 			goto finish;
4619 		}
4620 	}
4621 
4622 finish:
4623 #endif // CONFIG_KXLD
4624 	return result;
4625 }
4626 
4627 /*********************************************************************
4628 *********************************************************************/
4629 bool
isInterface(void)4630 OSKext::isInterface(void)
4631 {
4632 	return flags.interface;
4633 }
4634 
4635 /*********************************************************************
4636 *********************************************************************/
4637 bool
isKernel(void)4638 OSKext::isKernel(void)
4639 {
4640 	return this == sKernelKext;
4641 }
4642 
4643 /*********************************************************************
4644 *********************************************************************/
4645 bool
isKernelComponent(void)4646 OSKext::isKernelComponent(void)
4647 {
4648 	return flags.kernelComponent ? true : false;
4649 }
4650 
4651 /*********************************************************************
4652 *********************************************************************/
4653 bool
isExecutable(void)4654 OSKext::isExecutable(void)
4655 {
4656 	return !isKernel() && !isInterface() && declaresExecutable();
4657 }
4658 
4659 /*********************************************************************
4660 * We might want to check this recursively for all dependencies,
4661 * since a subtree of dependencies could get loaded before we hit
4662 * a dependency that isn't safe-boot-loadable.
4663 *
4664 * xxx - Might want to return false if OSBundleEnableKextLogging or
4665 * OSBundleDebugLevel
4666 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4667 * the point except it's usually development drivers, which might
4668 * cause panics on startup, that have those properties). Heh; could
4669 * use a "kx" boot-arg!
4670 *********************************************************************/
4671 bool
isLoadableInSafeBoot(void)4672 OSKext::isLoadableInSafeBoot(void)
4673 {
4674 	bool       result   = false;
4675 	OSString * required = NULL;         // do not release
4676 
4677 	if (isKernel()) {
4678 		result = true;
4679 		goto finish;
4680 	}
4681 
4682 	if (isDriverKit()) {
4683 		result = true;
4684 		goto finish;
4685 	}
4686 
4687 	required = OSDynamicCast(OSString,
4688 	    getPropertyForHostArch(kOSBundleRequiredKey));
4689 	if (!required) {
4690 		goto finish;
4691 	}
4692 	if (required->isEqualTo(kOSBundleRequiredRoot) ||
4693 	    required->isEqualTo(kOSBundleRequiredLocalRoot) ||
4694 	    required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
4695 	    required->isEqualTo(kOSBundleRequiredSafeBoot) ||
4696 	    required->isEqualTo(kOSBundleRequiredConsole)) {
4697 		result = true;
4698 	}
4699 
4700 finish:
4701 	return result;
4702 }
4703 
4704 /*********************************************************************
4705 *********************************************************************/
4706 bool
isPrelinked(void)4707 OSKext::isPrelinked(void)
4708 {
4709 	return flags.prelinked ? true : false;
4710 }
4711 
4712 /*********************************************************************
4713 *********************************************************************/
4714 bool
isLoaded(void)4715 OSKext::isLoaded(void)
4716 {
4717 	return flags.loaded ? true : false;
4718 }
4719 
4720 /*********************************************************************
4721 *********************************************************************/
4722 bool
isStarted(void)4723 OSKext::isStarted(void)
4724 {
4725 	return flags.started ? true : false;
4726 }
4727 
4728 /*********************************************************************
4729 *********************************************************************/
4730 bool
isCPPInitialized(void)4731 OSKext::isCPPInitialized(void)
4732 {
4733 	return flags.CPPInitialized;
4734 }
4735 
4736 /*********************************************************************
4737 *********************************************************************/
4738 void
setCPPInitialized(bool initialized)4739 OSKext::setCPPInitialized(bool initialized)
4740 {
4741 	flags.CPPInitialized = initialized;
4742 }
4743 
4744 /*********************************************************************
4745 *********************************************************************/
4746 uint32_t
getLoadTag(void)4747 OSKext::getLoadTag(void)
4748 {
4749 	return loadTag;
4750 }
4751 
4752 /*********************************************************************
4753 *********************************************************************/
4754 void
getSizeInfo(uint32_t * loadSize,uint32_t * wiredSize)4755 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
4756 {
4757 	if (linkedExecutable) {
4758 		*loadSize = linkedExecutable->getLength();
4759 
4760 		/* If we have a kmod_info struct, calculated the wired size
4761 		 * from that. Otherwise it's the full load size.
4762 		 */
4763 		if (kmod_info) {
4764 			*wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size;
4765 		} else {
4766 			*wiredSize = *loadSize;
4767 		}
4768 	} else {
4769 		*wiredSize = 0;
4770 		*loadSize = 0;
4771 	}
4772 }
4773 
4774 /*********************************************************************
4775 *********************************************************************/
4776 OSSharedPtr<OSData>
copyUUID(void)4777 OSKext::copyUUID(void)
4778 {
4779 	OSSharedPtr<OSData>          result;
4780 	OSData                     * theExecutable = NULL;        // do not release
4781 	const kernel_mach_header_t * header;
4782 
4783 	/* An interface kext doesn't have a linked executable with an LC_UUID,
4784 	 * we create one when it's linked.
4785 	 */
4786 	if (interfaceUUID) {
4787 		result = interfaceUUID;
4788 		goto finish;
4789 	}
4790 
4791 	if (flags.builtin || isInterface()) {
4792 		return sKernelKext->copyUUID();
4793 	}
4794 
4795 	if (isDriverKit() && infoDict) {
4796 		return driverKitUUID;
4797 	}
4798 
4799 	/* For real kexts, try to get the UUID from the linked executable,
4800 	 * or if is hasn't been linked yet, the unrelocated executable.
4801 	 */
4802 	theExecutable = linkedExecutable.get();
4803 	if (!theExecutable) {
4804 		theExecutable = getExecutable();
4805 	}
4806 
4807 	if (!theExecutable) {
4808 		goto finish;
4809 	}
4810 
4811 	header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
4812 	result = copyMachoUUID(header);
4813 
4814 finish:
4815 	return result;
4816 }
4817 
4818 /*********************************************************************
4819 *********************************************************************/
4820 OSSharedPtr<OSData>
copyTextUUID(void)4821 OSKext::copyTextUUID(void)
4822 {
4823 	if (flags.builtin) {
4824 		return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
4825 	}
4826 	return copyUUID();
4827 }
4828 
4829 /*********************************************************************
4830 *********************************************************************/
4831 OSSharedPtr<OSData>
copyMachoUUID(const kernel_mach_header_t * header)4832 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
4833 {
4834 	OSSharedPtr<OSData>                     result;
4835 	const struct load_command  * load_cmd      = NULL;
4836 	const struct uuid_command  * uuid_cmd      = NULL;
4837 	uint32_t                     i;
4838 
4839 	load_cmd = (const struct load_command *)&header[1];
4840 
4841 	if (header->magic != MH_MAGIC_KERNEL) {
4842 		OSKextLog(NULL,
4843 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4844 		    "%s: bad header %p",
4845 		    __func__,
4846 		    header);
4847 		goto finish;
4848 	}
4849 
4850 	for (i = 0; i < header->ncmds; i++) {
4851 		if (load_cmd->cmd == LC_UUID) {
4852 			uuid_cmd = (struct uuid_command *)load_cmd;
4853 			result = OSData::withValue(uuid_cmd->uuid);
4854 			goto finish;
4855 		}
4856 		load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
4857 	}
4858 
4859 finish:
4860 	return result;
4861 }
4862 
4863 void
setDriverKitUUID(OSData * uuid)4864 OSKext::setDriverKitUUID(OSData *uuid)
4865 {
4866 	if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
4867 		OSSafeReleaseNULL(uuid);
4868 	}
4869 }
4870 
4871 /*********************************************************************
4872 *********************************************************************/
4873 #if defined (__arm__)
4874 #include <arm/arch.h>
4875 #endif
4876 
4877 #if   defined (__x86_64__)
4878 #define ARCHNAME "x86_64"
4879 #elif defined (__arm64__)
4880 #define ARCHNAME "arm64"
4881 #elif defined (__arm__)
4882 
4883 #if defined (__ARM_ARCH_7S__)
4884 #define ARCHNAME "armv7s"
4885 #elif defined (__ARM_ARCH_7F__)
4886 #define ARCHNAME "armv7f"
4887 #elif defined (__ARM_ARCH_7K__)
4888 #define ARCHNAME "armv7k"
4889 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
4890 #define ARCHNAME "armv7"
4891 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
4892 #define ARCHNAME "armv6"
4893 #endif
4894 
4895 #elif defined (__arm64__)
4896 #define ARCHNAME "arm64"
4897 #else
4898 #error architecture not supported
4899 #endif
4900 
4901 #define ARCH_SEPARATOR_CHAR  '_'
4902 
4903 static char *
makeHostArchKey(const char * key,size_t * keySizeOut)4904 makeHostArchKey(const char * key, size_t * keySizeOut)
4905 {
4906 	char     * result = NULL;
4907 	size_t     keyLength = strlen(key);
4908 	size_t     keySize;
4909 
4910 	/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4911 	 */
4912 	keySize = 1 + 1 + keyLength + strlen(ARCHNAME);
4913 	result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
4914 
4915 	if (!result) {
4916 		goto finish;
4917 	}
4918 	strlcpy(result, key, keySize);
4919 	result[keyLength++] = ARCH_SEPARATOR_CHAR;
4920 	result[keyLength] = '\0';
4921 	strlcat(result, ARCHNAME, keySize);
4922 	*keySizeOut = keySize;
4923 
4924 finish:
4925 	return result;
4926 }
4927 
4928 /*********************************************************************
4929 *********************************************************************/
4930 OSObject *
getPropertyForHostArch(const char * key)4931 OSKext::getPropertyForHostArch(const char * key)
4932 {
4933 	OSObject * result           = NULL;// do not release
4934 	size_t     hostArchKeySize  = 0;
4935 	char     * hostArchKey      = NULL;// must kfree
4936 
4937 	if (!key || !infoDict) {
4938 		goto finish;
4939 	}
4940 
4941 	/* Some properties are not allowed to be arch-variant:
4942 	 * - Any CFBundle... property.
4943 	 * - OSBundleIsInterface.
4944 	 * - OSKernelResource.
4945 	 */
4946 	if (STRING_HAS_PREFIX(key, "OS") ||
4947 	    STRING_HAS_PREFIX(key, "IO")) {
4948 		hostArchKey = makeHostArchKey(key, &hostArchKeySize);
4949 		if (!hostArchKey) {
4950 			OSKextLog(/* kext (this isn't about a kext) */ NULL,
4951 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4952 			    "Allocation failure.");
4953 			goto finish;
4954 		}
4955 		result = infoDict->getObject(hostArchKey);
4956 	}
4957 
4958 	if (!result) {
4959 		result = infoDict->getObject(key);
4960 	}
4961 
4962 finish:
4963 	if (hostArchKey) {
4964 		kfree_data(hostArchKey, hostArchKeySize);
4965 	}
4966 	return result;
4967 }
4968 
4969 #if PRAGMA_MARK
4970 #pragma mark Load/Start/Stop/Unload
4971 #endif
4972 
4973 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4974 
4975 /*********************************************************************
4976 * sExcludeListByID is a dictionary with keys / values of:
4977 *  key = bundleID string of kext we will not allow to load
4978 *  value = version string(s) of the kext that is to be denied loading.
4979 *      The version strings can be comma delimited.  For example if kext
4980 *      com.foocompany.fookext has two versions that we want to deny
4981 *      loading then the version strings might look like:
4982 *      1.0.0, 1.0.1
4983 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4984 *      not load the kext.
4985 *
4986 *      Value may also be in the form of "LE 2.0.0" (version numbers
4987 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4988 *      number less than 2.0.0 will not load)
4989 *
4990 *      NOTE - we cannot use the characters "<=" or "<" because we have code
4991 *      that serializes plists and treats '<' as a special character.
4992 *********************************************************************/
4993 bool
isInExcludeList(void)4994 OSKext::isInExcludeList(void)
4995 {
4996 	OSString *      versionString           = NULL;        // do not release
4997 	char *          versionCString          = NULL;        // do not free
4998 	size_t          i;
4999 	boolean_t       wantLessThan = false;
5000 	boolean_t       wantLessThanEqualTo = false;
5001 	boolean_t       isInExcludeList = true;
5002 	char            myBuffer[32];
5003 
5004 	IORecursiveLockLock(sKextLock);
5005 
5006 	if (!sExcludeListByID) {
5007 		isInExcludeList = false;
5008 	} else {
5009 		/* look up by bundleID in our exclude list and if found get version
5010 		 * string (or strings) that we will not allow to load
5011 		 */
5012 		versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get()));
5013 		if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
5014 			isInExcludeList = false;
5015 		}
5016 	}
5017 
5018 	IORecursiveLockUnlock(sKextLock);
5019 
5020 	if (!isInExcludeList) {
5021 		return false;
5022 	}
5023 
5024 	/* parse version strings */
5025 	versionCString = (char *) versionString->getCStringNoCopy();
5026 
5027 	/* look for "LT" or "LE" form of version string, must be in first two
5028 	 * positions.
5029 	 */
5030 	if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
5031 		wantLessThan = true;
5032 		versionCString += 2;
5033 	} else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
5034 		wantLessThanEqualTo = true;
5035 		versionCString += 2;
5036 	}
5037 
5038 	for (i = 0; *versionCString != 0x00; versionCString++) {
5039 		/* skip whitespace */
5040 		if (isWhiteSpace(*versionCString)) {
5041 			continue;
5042 		}
5043 
5044 		/* peek ahead for version string separator or null terminator */
5045 		if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
5046 			/* OK, we have a version string */
5047 			myBuffer[i++] = *versionCString;
5048 			myBuffer[i] = 0x00;
5049 
5050 			OSKextVersion excludeVers;
5051 			excludeVers = OSKextParseVersionString(myBuffer);
5052 
5053 			if (wantLessThanEqualTo) {
5054 				if (version <= excludeVers) {
5055 					return true;
5056 				}
5057 			} else if (wantLessThan) {
5058 				if (version < excludeVers) {
5059 					return true;
5060 				}
5061 			} else if (version == excludeVers) {
5062 				return true;
5063 			}
5064 
5065 			/* reset for the next (if any) version string */
5066 			i = 0;
5067 			wantLessThan = false;
5068 			wantLessThanEqualTo = false;
5069 		} else {
5070 			/* save valid version character */
5071 			myBuffer[i++] = *versionCString;
5072 
5073 			/* make sure bogus version string doesn't overrun local buffer */
5074 			if (i >= sizeof(myBuffer)) {
5075 				break;
5076 			}
5077 		}
5078 	}
5079 
5080 	return false;
5081 }
5082 
5083 /*********************************************************************
5084 * sNonLoadableKextsByID is a dictionary with keys / values of:
5085 *  key = bundleID string of kext we will not allow to load
5086 *  value = boolean (true == loadable, false == not loadable)
5087 *
5088 *  Only kexts which are in the AuxKC will be marked as "not loadble,"
5089 *  i.e., the value for the kext's bundleID will be false. All kexts in
5090 *  the primary and system KCs will always be marked as "loadable."
5091 *
5092 *  This list ultimately comes from kexts which have been uninstalled
5093 *  in user space by deleting the kext from disk, but which have not
5094 *  yet been removed from the AuxKC. Because the user could choose to
5095 *  re-install the exact same version of the kext, we need to keep
5096 *  a dictionary of boolean values so that user space only needs to
5097 *  keep a simple list of "uninstalled" or "missing" bundles. When
5098 *  a bundle is re-installed, the iokit daemon can use the
5099 *  AucKCBundleAvailable  predicate to set the individual kext's
5100 *  availability to true.
5101 *********************************************************************/
5102 bool
isLoadable(void)5103 OSKext::isLoadable(void)
5104 {
5105 	bool isLoadable = true;
5106 
5107 	if (kc_type != KCKindAuxiliary) {
5108 		/* this filtering only applies to kexts in the auxkc */
5109 		return true;
5110 	}
5111 
5112 	IORecursiveLockLock(sKextLock);
5113 
5114 	if (sNonLoadableKextsByID) {
5115 		/* look up by bundleID in our exclude list and if found get version
5116 		 * string (or strings) that we will not allow to load
5117 		 */
5118 		OSBoolean *loadableVal;
5119 		loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get()));
5120 		if (loadableVal && !loadableVal->getValue()) {
5121 			isLoadable = false;
5122 		}
5123 	}
5124 	IORecursiveLockUnlock(sKextLock);
5125 
5126 	return isLoadable;
5127 }
5128 
5129 /*********************************************************************
5130 *********************************************************************/
5131 /* static */
5132 OSReturn
loadKextWithIdentifier(const char * kextIdentifierCString,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5133 OSKext::loadKextWithIdentifier(
5134 	const char       * kextIdentifierCString,
5135 	Boolean            allowDeferFlag,
5136 	Boolean            delayAutounloadFlag,
5137 	OSKextExcludeLevel startOpt,
5138 	OSKextExcludeLevel startMatchingOpt,
5139 	OSArray          * personalityNames)
5140 {
5141 	OSReturn   result         = kOSReturnError;
5142 	OSSharedPtr<OSString> kextIdentifier;
5143 
5144 	kextIdentifier = OSString::withCString(kextIdentifierCString);
5145 	if (!kextIdentifier) {
5146 		result = kOSKextReturnNoMemory;
5147 		goto finish;
5148 	}
5149 	result = OSKext::loadKextWithIdentifier(kextIdentifier.get(),
5150 	    NULL /* kextRef */,
5151 	    allowDeferFlag, delayAutounloadFlag,
5152 	    startOpt, startMatchingOpt, personalityNames);
5153 
5154 finish:
5155 	return result;
5156 }
5157 
5158 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSSharedPtr<OSObject> & kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5159 OSKext::loadKextWithIdentifier(
5160 	OSString          * kextIdentifier,
5161 	OSSharedPtr<OSObject>         &kextRef,
5162 	Boolean             allowDeferFlag,
5163 	Boolean             delayAutounloadFlag,
5164 	OSKextExcludeLevel  startOpt,
5165 	OSKextExcludeLevel  startMatchingOpt,
5166 	OSArray           * personalityNames)
5167 {
5168 	OSObject * kextRefRaw = NULL;
5169 	OSReturn result;
5170 
5171 	result = loadKextWithIdentifier(kextIdentifier,
5172 	    &kextRefRaw,
5173 	    allowDeferFlag,
5174 	    delayAutounloadFlag,
5175 	    startOpt,
5176 	    startMatchingOpt,
5177 	    personalityNames);
5178 	if ((kOSReturnSuccess == result) && kextRefRaw) {
5179 		kextRef.reset(kextRefRaw, OSNoRetain);
5180 	}
5181 	return result;
5182 }
5183 
5184 /*********************************************************************
5185 *********************************************************************/
5186 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSObject ** kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5187 OSKext::loadKextWithIdentifier(
5188 	OSString          * kextIdentifier,
5189 	OSObject         ** kextRef,
5190 	Boolean             allowDeferFlag,
5191 	Boolean             delayAutounloadFlag,
5192 	OSKextExcludeLevel  startOpt,
5193 	OSKextExcludeLevel  startMatchingOpt,
5194 	OSArray           * personalityNames)
5195 {
5196 	OSReturn          result               = kOSReturnError;
5197 	OSReturn          pingResult           = kOSReturnError;
5198 	OSKext          * theKext              = NULL;        // do not release
5199 	OSSharedPtr<OSDictionary>   loadRequest;
5200 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5201 
5202 	if (kextRef) {
5203 		*kextRef = NULL;
5204 	}
5205 
5206 	IORecursiveLockLock(sKextLock);
5207 
5208 	if (!kextIdentifier) {
5209 		result = kOSKextReturnInvalidArgument;
5210 		goto finish;
5211 	}
5212 
5213 	OSKext::recordIdentifierRequest(kextIdentifier);
5214 
5215 	theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
5216 	if (!theKext) {
5217 		if (!allowDeferFlag) {
5218 			OSKextLog(/* kext */ NULL,
5219 			    kOSKextLogErrorLevel |
5220 			    kOSKextLogLoadFlag,
5221 			    "Can't load kext %s - not found.",
5222 			    kextIdentifier->getCStringNoCopy());
5223 			goto finish;
5224 		}
5225 
5226 		if (!sKernelRequestsEnabled) {
5227 			OSKextLog(theKext,
5228 			    kOSKextLogErrorLevel |
5229 			    kOSKextLogLoadFlag,
5230 			    "Can't load kext %s - requests to user space are disabled.",
5231 			    kextIdentifier->getCStringNoCopy());
5232 			result = kOSKextReturnDisabled;
5233 			goto finish;
5234 		}
5235 
5236 		/* Create a new request unless one is already sitting
5237 		 * in sKernelRequests for this bundle identifier
5238 		 */
5239 		kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5240 		if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5241 			result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
5242 			    loadRequest);
5243 			if (result != kOSReturnSuccess) {
5244 				goto finish;
5245 			}
5246 			if (!_OSKextSetRequestArgument(loadRequest.get(),
5247 			    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
5248 				result = kOSKextReturnNoMemory;
5249 				goto finish;
5250 			}
5251 			if (!sKernelRequests->setObject(loadRequest.get())) {
5252 				result = kOSKextReturnNoMemory;
5253 				goto finish;
5254 			}
5255 
5256 			if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
5257 				result = kOSKextReturnNoMemory;
5258 				goto finish;
5259 			}
5260 
5261 			OSKextLog(theKext,
5262 			    kOSKextLogDebugLevel |
5263 			    kOSKextLogLoadFlag,
5264 			    "Kext %s not found; queued load request to user space.",
5265 			    kextIdentifier->getCStringNoCopy());
5266 		}
5267 
5268 		pingResult = OSKext::pingIOKitDaemon();
5269 		if (pingResult == kOSKextReturnDisabled) {
5270 			OSKextLog(/* kext */ NULL,
5271 			    ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
5272 			    kOSKextLogLoadFlag,
5273 			    "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.",
5274 			    kextIdentifier->getCStringNoCopy());
5275 		}
5276 
5277 		result = kOSKextReturnDeferred;
5278 		goto finish;
5279 	}
5280 
5281 	result = theKext->load(startOpt, startMatchingOpt, personalityNames);
5282 
5283 	if (result != kOSReturnSuccess) {
5284 		OSKextLog(theKext,
5285 		    kOSKextLogErrorLevel |
5286 		    kOSKextLogLoadFlag,
5287 		    "Failed to load kext %s (error 0x%x).",
5288 		    kextIdentifier->getCStringNoCopy(), (int)result);
5289 
5290 		if (theKext->kc_type == KCKindUnknown) {
5291 			OSKext::removeKext(theKext,
5292 			    /* terminateService/removePersonalities */ true);
5293 		}
5294 		goto finish;
5295 	}
5296 
5297 	if (delayAutounloadFlag) {
5298 		OSKextLog(theKext,
5299 		    kOSKextLogProgressLevel |
5300 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5301 		    "Setting delayed autounload for %s.",
5302 		    kextIdentifier->getCStringNoCopy());
5303 		theKext->flags.delayAutounload = 1;
5304 	}
5305 
5306 finish:
5307 	if ((kOSReturnSuccess == result) && kextRef) {
5308 		*kextRef = theKext;
5309 		theKext->matchingRefCount++;
5310 		theKext->retain();
5311 	}
5312 
5313 	IORecursiveLockUnlock(sKextLock);
5314 
5315 	return result;
5316 }
5317 
5318 /*********************************************************************
5319 *********************************************************************/
5320 /* static */
5321 OSReturn
loadKextFromKC(OSKext * theKext,OSDictionary * requestDict)5322 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict)
5323 {
5324 	OSReturn  result = kOSReturnError;
5325 
5326 	OSBoolean *delayAutounloadBool     = NULL; // do not release
5327 	OSNumber  *startKextExcludeNum     = NULL; // do not release
5328 	OSNumber  *startMatchingExcludeNum = NULL; // do not release
5329 	OSArray   *personalityNames        = NULL; // do not release
5330 
5331 	/*
5332 	 * Default values for these options:
5333 	 *      regular autounload behavior
5334 	 *      start the kext
5335 	 *      send all personalities to the catalog
5336 	 */
5337 	Boolean            delayAutounload           = false;
5338 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
5339 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone;
5340 
5341 	IORecursiveLockLock(sKextLock);
5342 
5343 	OSKextLog(/* kext */ NULL,
5344 	    kOSKextLogDebugLevel |
5345 	    kOSKextLogIPCFlag,
5346 	    "Received kext KC load request from user space.");
5347 
5348 	/* Regardless of processing, the fact that we have gotten here means some
5349 	 * user-space program is up and talking to us, so we'll switch our kext
5350 	 * registration to reflect that.
5351 	 */
5352 	if (!sUserLoadsActive) {
5353 		OSKextLog(/* kext */ NULL,
5354 		    kOSKextLogProgressLevel |
5355 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5356 		    "Switching to late startup (user-space) kext loading policy.");
5357 		sUserLoadsActive = true;
5358 	}
5359 
5360 	delayAutounloadBool = OSDynamicCast(OSBoolean,
5361 	    _OSKextGetRequestArgument(requestDict,
5362 	    kKextRequestArgumentDelayAutounloadKey));
5363 	startKextExcludeNum = OSDynamicCast(OSNumber,
5364 	    _OSKextGetRequestArgument(requestDict,
5365 	    kKextRequestArgumentStartExcludeKey));
5366 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
5367 	    _OSKextGetRequestArgument(requestDict,
5368 	    kKextRequestArgumentStartMatchingExcludeKey));
5369 	personalityNames = OSDynamicCast(OSArray,
5370 	    _OSKextGetRequestArgument(requestDict,
5371 	    kKextRequestArgumentPersonalityNamesKey));
5372 
5373 	if (delayAutounloadBool) {
5374 		delayAutounload = delayAutounloadBool->getValue();
5375 	}
5376 	if (startKextExcludeNum) {
5377 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
5378 	}
5379 	if (startMatchingExcludeNum) {
5380 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
5381 	}
5382 
5383 	OSKextLog(/* kext */ NULL,
5384 	    kOSKextLogProgressLevel |
5385 	    kOSKextLogIPCFlag,
5386 	    "Received request from user space to load KC kext %s.",
5387 	    theKext->getIdentifierCString());
5388 
5389 	/* this could be in the Auxiliary KC, so record the load request */
5390 	OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier()));
5391 
5392 	/*
5393 	 * Load the kext
5394 	 */
5395 	result = theKext->load(startKextExcludeLevel,
5396 	    startMatchingExcludeLevel, personalityNames);
5397 
5398 	if (result != kOSReturnSuccess) {
5399 		OSKextLog(theKext,
5400 		    kOSKextLogErrorLevel |
5401 		    kOSKextLogLoadFlag,
5402 		    "Failed to load kext %s (error 0x%x).",
5403 		    theKext->getIdentifierCString(), (int)result);
5404 
5405 		OSKext::removeKext(theKext,
5406 		    /* terminateService/removePersonalities */ true);
5407 		goto finish;
5408 	} else {
5409 		OSKextLog(theKext,
5410 		    kOSKextLogProgressLevel |
5411 		    kOSKextLogLoadFlag,
5412 		    "Kext %s Loaded successfully from %s KC",
5413 		    theKext->getIdentifierCString(), theKext->getKCTypeString());
5414 	}
5415 
5416 	if (delayAutounload) {
5417 		OSKextLog(theKext,
5418 		    kOSKextLogProgressLevel |
5419 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5420 		    "Setting delayed autounload for %s.",
5421 		    theKext->getIdentifierCString());
5422 		theKext->flags.delayAutounload = 1;
5423 	}
5424 
5425 finish:
5426 	IORecursiveLockUnlock(sKextLock);
5427 
5428 	return result;
5429 }
5430 
5431 /*********************************************************************
5432 *********************************************************************/
5433 /* static */
5434 OSReturn
loadCodelessKext(OSString * kextIdentifier,OSDictionary * requestDict)5435 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict)
5436 {
5437 	OSReturn  result = kOSReturnError;
5438 	OSDictionary *anInfoDict = NULL; // do not release
5439 
5440 	anInfoDict = OSDynamicCast(OSDictionary,
5441 	    _OSKextGetRequestArgument(requestDict,
5442 	    kKextRequestArgumentCodelessInfoKey));
5443 	if (anInfoDict == NULL) {
5444 		OSKextLog(/* kext */ NULL,
5445 		    kOSKextLogErrorLevel |
5446 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5447 		    "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.",
5448 		    kextIdentifier->getCStringNoCopy());
5449 		return kOSKextReturnInvalidArgument;
5450 	}
5451 
5452 	IORecursiveLockLock(sKextLock);
5453 
5454 	OSKextLog(/* kext */ NULL,
5455 	    kOSKextLogProgressLevel |
5456 	    kOSKextLogIPCFlag,
5457 	    "Received request from user space to load codeless kext %s.",
5458 	    kextIdentifier->getCStringNoCopy());
5459 
5460 	{
5461 		// instantiate a new kext, and don't hold a reference
5462 		// (the kext subsystem will hold one implicitly)
5463 		OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict);
5464 		if (!newKext) {
5465 			OSKextLog(/* kext */ NULL,
5466 			    kOSKextLogErrorLevel |
5467 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5468 			    "Could not instantiate codeless kext.");
5469 			result = kOSKextReturnNotLoadable;
5470 			goto finish;
5471 		}
5472 		if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) {
5473 			OSKextLog(/* kext */ NULL,
5474 			    kOSKextLogErrorLevel |
5475 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5476 			    "Codeless kext identifiers don't match '%s' != '%s'",
5477 			    kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString());
5478 
5479 			OSKext::removeKext(newKext.get(), false);
5480 			result = kOSKextReturnInvalidArgument;
5481 			goto finish;
5482 		}
5483 
5484 		/* Record the request for the codeless kext */
5485 		OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier()));
5486 
5487 		result = kOSReturnSuccess;
5488 		/* Send the kext's personalities to the IOCatalog. This is an explicit load. */
5489 		result = newKext->sendPersonalitiesToCatalog(true, NULL);
5490 	}
5491 
5492 finish:
5493 	IORecursiveLockUnlock(sKextLock);
5494 
5495 	return result;
5496 }
5497 
5498 /*********************************************************************
5499 *********************************************************************/
5500 /* static */
5501 void
dropMatchingReferences(OSSet * kexts)5502 OSKext::dropMatchingReferences(
5503 	OSSet * kexts)
5504 {
5505 	IORecursiveLockLock(sKextLock);
5506 	kexts->iterateObjects(^bool (OSObject * obj) {
5507 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
5508 		if (!thisKext) {
5509 		        return false;
5510 		}
5511 		thisKext->matchingRefCount--;
5512 		return false;
5513 	});
5514 	IORecursiveLockUnlock(sKextLock);
5515 }
5516 
5517 /*********************************************************************
5518 *********************************************************************/
5519 /* static */
5520 void
recordIdentifierRequest(OSString * kextIdentifier)5521 OSKext::recordIdentifierRequest(
5522 	OSString * kextIdentifier)
5523 {
5524 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5525 	bool             fail                 = false;
5526 
5527 	if (!sAllKextLoadIdentifiers || !kextIdentifier) {
5528 		goto finish;
5529 	}
5530 
5531 	kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5532 	if (!kextIdentifierSymbol) {
5533 		// xxx - this is really a basic alloc failure
5534 		fail = true;
5535 		goto finish;
5536 	}
5537 
5538 	IORecursiveLockLock(sKextLock);
5539 	if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5540 		if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
5541 			fail = true;
5542 		} else {
5543 			// xxx - need to find a way to associate this whole func w/the kext
5544 			OSKextLog(/* kext */ NULL,
5545 			    // xxx - check level
5546 			    kOSKextLogStepLevel |
5547 			    kOSKextLogArchiveFlag,
5548 			    "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
5549 			    kextIdentifier->getCStringNoCopy());
5550 		}
5551 	}
5552 	IORecursiveLockUnlock(sKextLock);
5553 
5554 finish:
5555 
5556 	if (fail) {
5557 		OSKextLog(/* kext */ NULL,
5558 		    kOSKextLogErrorLevel |
5559 		    kOSKextLogArchiveFlag,
5560 		    "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
5561 		    kextIdentifier->getCStringNoCopy());
5562 	}
5563 	return;
5564 }
5565 
5566 /*********************************************************************
5567 *********************************************************************/
5568 OSReturn
load(OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5569 OSKext::load(
5570 	OSKextExcludeLevel   startOpt,
5571 	OSKextExcludeLevel   startMatchingOpt,
5572 	OSArray            * personalityNames)
5573 {
5574 	OSReturn             result                       = kOSReturnError;
5575 	OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
5576 	OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
5577 	unsigned int         i, count;
5578 	Boolean              alreadyLoaded                = false;
5579 	OSKext             * lastLoadedKext               = NULL;        // do not release
5580 
5581 	if (isInExcludeList()) {
5582 		OSKextLog(this,
5583 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
5584 		    kOSKextLogLoadFlag,
5585 		    "Kext %s is in exclude list, not loadable",
5586 		    getIdentifierCString());
5587 
5588 		result = kOSKextReturnNotLoadable;
5589 		goto finish;
5590 	}
5591 	if (!isLoadable()) {
5592 		OSKextLog(this,
5593 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
5594 		    kOSKextLogLoadFlag,
5595 		    "Kext %s is not loadable",
5596 		    getIdentifierCString());
5597 
5598 		result = kOSKextReturnNotLoadable;
5599 		goto finish;
5600 	}
5601 
5602 	if (isLoaded()) {
5603 		alreadyLoaded = true;
5604 		result = kOSReturnSuccess;
5605 
5606 		OSKextLog(this,
5607 		    kOSKextLogDebugLevel |
5608 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5609 		    "Kext %s is already loaded.",
5610 		    getIdentifierCString());
5611 		goto loaded;
5612 	}
5613 
5614 #if CONFIG_MACF
5615 	/*
5616 	 * On kxld and on embedded, only call into the MAC hook when on a
5617 	 * user thread, for access control over userspace kextloads.
5618 	 *
5619 	 * On non-kxld systems, additionally check the MAC hook for kexts in
5620 	 * the Pageable and Aux KCs, regardless of whether we are on a user
5621 	 * thread or not. This means on Apple silicon devices that the MAC
5622 	 * hook will only be useful to block 3rd party kexts loaded via
5623 	 * matching, and any kexts loaded from userspace kextloads.
5624 	 *
5625 	 * Note that this should _not_ be called on kexts loaded from the
5626 	 * kernel bootstrap thread as the kernel proc's cred struct is not
5627 	 * yet initialized! This won't happen on macOS because all the kexts
5628 	 * in the BootKC are self-contained and their kc_type = KCKindPrimary.
5629 	 */
5630 	if (current_task() != kernel_task
5631 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD
5632 	    || (kc_type != KCKindPrimary && kc_type != KCKindUnknown)
5633 #endif
5634 	    ) {
5635 		int                 macCheckResult      = 0;
5636 		kauth_cred_t        cred                = NULL;
5637 
5638 		cred = kauth_cred_get_with_ref();
5639 		macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
5640 		kauth_cred_unref(&cred);
5641 
5642 		if (macCheckResult != 0) {
5643 			result = kOSReturnError;
5644 			OSKextLog(this,
5645 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5646 			    "Failed to load kext %s (MAC policy error 0x%x).",
5647 			    getIdentifierCString(), macCheckResult);
5648 			goto finish;
5649 		}
5650 	}
5651 #endif /* CONFIG_MACF */
5652 
5653 	if (!sLoadEnabled) {
5654 		OSKextLog(this,
5655 		    kOSKextLogErrorLevel |
5656 		    kOSKextLogLoadFlag,
5657 		    "Kext loading is disabled (attempt to load kext %s).",
5658 		    getIdentifierCString());
5659 		result = kOSKextReturnDisabled;
5660 		goto finish;
5661 	}
5662 
5663 	/* If we've pushed the next available load tag to the invalid value,
5664 	 * we can't load any more kexts.
5665 	 */
5666 	if (sNextLoadTag == kOSKextInvalidLoadTag) {
5667 		OSKextLog(this,
5668 		    kOSKextLogErrorLevel |
5669 		    kOSKextLogLoadFlag,
5670 		    "Can't load kext %s - no more load tags to assign.",
5671 		    getIdentifierCString());
5672 		result = kOSKextReturnNoResources;
5673 		goto finish;
5674 	}
5675 
5676 	/* This is a bit of a hack, because we shouldn't be handling
5677 	 * personalities within the load function.
5678 	 */
5679 	if (!declaresExecutable()) {
5680 		/* There is a special case where a non-executable kext can be loaded: the
5681 		 * AppleKextExcludeList.  Detect that special kext by bundle identifier and
5682 		 * load its metadata into the global data structures, if appropriate
5683 		 */
5684 		if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
5685 			boolean_t updated = updateExcludeList(infoDict.get());
5686 			if (updated) {
5687 				OSKextLog(this,
5688 				    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
5689 				    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
5690 			}
5691 		}
5692 
5693 		if (isDriverKit()) {
5694 			if (loadTag == 0) {
5695 				sLoadedDriverKitKexts->setObject(this);
5696 				loadTag = sNextLoadTag++;
5697 			}
5698 		}
5699 		result = kOSReturnSuccess;
5700 		goto loaded;
5701 	}
5702 
5703 	/* Are we in safe boot?
5704 	 */
5705 	if (sSafeBoot && !isLoadableInSafeBoot()) {
5706 		OSKextLog(this,
5707 		    kOSKextLogErrorLevel |
5708 		    kOSKextLogLoadFlag,
5709 		    "Can't load kext %s - not loadable during safe boot.",
5710 		    getIdentifierCString());
5711 		result = kOSKextReturnBootLevel;
5712 		goto finish;
5713 	}
5714 
5715 	OSKextLog(this,
5716 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5717 	    "Loading kext %s.",
5718 	    getIdentifierCString());
5719 
5720 #if !VM_MAPPED_KEXTS
5721 	if (isPrelinked() == false) {
5722 		OSKextLog(this,
5723 		    kOSKextLogErrorLevel |
5724 		    kOSKextLogLoadFlag,
5725 		    "Can't load kext %s - not in a kext collection.",
5726 		    getIdentifierCString());
5727 		result = kOSKextReturnDisabled;
5728 		goto finish;
5729 	}
5730 #endif /* defined(__x86_64__) */
5731 
5732 #if CONFIG_KXLD
5733 	if (!sKxldContext) {
5734 		kern_return_t kxldResult;
5735 		kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
5736 		    &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
5737 		    /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
5738 		if (kxldResult) {
5739 			OSKextLog(this,
5740 			    kOSKextLogErrorLevel |
5741 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5742 			    "Can't load kext %s - failed to create link context.",
5743 			    getIdentifierCString());
5744 			result = kOSKextReturnNoMemory;
5745 			goto finish;
5746 		}
5747 	}
5748 #endif // CONFIG_KXLD
5749 
5750 	/* We only need to resolve dependencies once for the whole graph, but
5751 	 * resolveDependencies will just return if there's no work to do, so it's
5752 	 * safe to call it more than once.
5753 	 */
5754 	if (!resolveDependencies()) {
5755 		// xxx - check resolveDependencies() for log msg
5756 		OSKextLog(this,
5757 		    kOSKextLogErrorLevel |
5758 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5759 		    "Can't load kext %s - failed to resolve library dependencies.",
5760 		    getIdentifierCString());
5761 		result = kOSKextReturnDependencies;
5762 		goto finish;
5763 	}
5764 
5765 	/* If we are excluding just the kext being loaded now (and not its
5766 	 * dependencies), drop the exclusion level to none so dependencies
5767 	 * start and/or add their personalities.
5768 	 */
5769 	if (dependenciesStartOpt == kOSKextExcludeKext) {
5770 		dependenciesStartOpt = kOSKextExcludeNone;
5771 	}
5772 
5773 	if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
5774 		dependenciesStartMatchingOpt = kOSKextExcludeNone;
5775 	}
5776 
5777 	/* Load the dependencies, recursively.
5778 	 */
5779 	count = getNumDependencies();
5780 	for (i = 0; i < count; i++) {
5781 		OSKext * dependency = OSDynamicCast(OSKext,
5782 		    dependencies->getObject(i));
5783 		if (dependency == NULL) {
5784 			OSKextLog(this,
5785 			    kOSKextLogErrorLevel |
5786 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5787 			    "Internal error loading kext %s; dependency disappeared.",
5788 			    getIdentifierCString());
5789 			result = kOSKextReturnInternalError;
5790 			goto finish;
5791 		}
5792 
5793 		/* Dependencies must be started accorting to the opt,
5794 		 * but not given the personality names of the main kext.
5795 		 */
5796 		result = dependency->load(dependenciesStartOpt,
5797 		    dependenciesStartMatchingOpt,
5798 		    /* personalityNames */ NULL);
5799 		if (result != KERN_SUCCESS) {
5800 			OSKextLog(this,
5801 			    kOSKextLogErrorLevel |
5802 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5803 			    "Dependency %s of kext %s failed to load.",
5804 			    dependency->getIdentifierCString(),
5805 			    getIdentifierCString());
5806 
5807 			OSKext::removeKext(dependency,
5808 			    /* terminateService/removePersonalities */ true);
5809 			result = kOSKextReturnDependencyLoadError;
5810 
5811 			goto finish;
5812 		}
5813 	}
5814 
5815 	result = loadExecutable();
5816 	if (result != KERN_SUCCESS) {
5817 		goto finish;
5818 	}
5819 
5820 	pendingPgoHead.next = &pendingPgoHead;
5821 	pendingPgoHead.prev = &pendingPgoHead;
5822 
5823 	// The kernel PRNG is not initialized when the first kext is
5824 	// loaded, so use early random
5825 	uuid_generate_early_random(instance_uuid);
5826 	account = IOMallocType(OSKextAccount);
5827 
5828 	account->loadTag = kmod_info->id;
5829 	account->site.refcount = 0;
5830 	account->site.flags = VM_TAG_KMOD;
5831 
5832 #if DEVELOPMENT || DEBUG
5833 	/* Setup the task reference group. */
5834 	(void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name),
5835 	    "task_%s", getIdentifierCString());
5836 	account->task_refgrp.grp_name = account->task_refgrp_name;
5837 	account->task_refgrp.grp_parent = &task_external_refgrp;
5838 	os_ref_log_init(&account->task_refgrp);
5839 #endif /* DEVELOPMENT || DEBUG */
5840 
5841 	account->kext = this;
5842 	if (gIOSurfaceIdentifier == bundleID) {
5843 		vm_tag_alloc(&account->site);
5844 		gIOSurfaceTag = account->site.tag;
5845 	}
5846 
5847 	flags.loaded = true;
5848 
5849 	/* Add the kext to the list of loaded kexts and update the kmod_info
5850 	 * struct to point to that of the last loaded kext (which is the way
5851 	 * it's always been done, though I'd rather do them in order now).
5852 	 */
5853 	lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
5854 	sLoadedKexts->setObject(this);
5855 
5856 	/* Keep the kernel itself out of the kmod list.
5857 	 */
5858 	if (lastLoadedKext->isKernel()) {
5859 		lastLoadedKext = NULL;
5860 	}
5861 
5862 	if (lastLoadedKext) {
5863 		kmod_info->next = lastLoadedKext->kmod_info;
5864 	}
5865 
5866 	notifyKextLoadObservers(this, kmod_info);
5867 
5868 	/* Make the global kmod list point at the just-loaded kext. Note that the
5869 	 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
5870 	 * although we do report it in kextstat these days by using the newer
5871 	 * OSArray of loaded kexts, which does contain it.
5872 	 *
5873 	 * (The OSKext object representing the kernel doesn't even have a kmod_info
5874 	 * struct, though I suppose we could stick a pointer to it from the
5875 	 * static struct in OSRuntime.cpp.)
5876 	 */
5877 	kmod = kmod_info;
5878 
5879 	/* Save the list of loaded kexts in case we panic.
5880 	 */
5881 	OSKext::saveLoadedKextPanicList();
5882 
5883 	if (isExecutable()) {
5884 		OSKext::updateLoadedKextSummaries();
5885 		savePanicString(/* isLoading */ true);
5886 
5887 #if CONFIG_DTRACE
5888 		registerWithDTrace();
5889 #else
5890 		jettisonLinkeditSegment();
5891 #endif /* CONFIG_DTRACE */
5892 
5893 #if !VM_MAPPED_KEXTS
5894 		/* If there is a page (or more) worth of padding after the end
5895 		 * of the last data section but before the end of the data segment
5896 		 * then free it in the same manner the LinkeditSegment is freed
5897 		 */
5898 		jettisonDATASegmentPadding();
5899 #endif
5900 	}
5901 
5902 loaded:
5903 	if (isExecutable() && !flags.started) {
5904 		if (startOpt == kOSKextExcludeNone) {
5905 			result = start();
5906 			if (result != kOSReturnSuccess) {
5907 				OSKextLog(this,
5908 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5909 				    "Kext %s start failed (result 0x%x).",
5910 				    getIdentifierCString(), result);
5911 				result = kOSKextReturnStartStopError;
5912 			}
5913 		}
5914 	}
5915 
5916 	/* If not excluding matching, send the personalities to the kernel.
5917 	 * This never affects the result of the load operation.
5918 	 * This is a bit of a hack, because we shouldn't be handling
5919 	 * personalities within the load function.
5920 	 */
5921 	if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
5922 		result = sendPersonalitiesToCatalog(true, personalityNames);
5923 	}
5924 
5925 finish:
5926 
5927 	if (result != kOSReturnSuccess) {
5928 		OSKextLog(this,
5929 		    kOSKextLogErrorLevel |
5930 		    kOSKextLogLoadFlag,
5931 		    "Kext %s failed to load (0x%x).",
5932 		    getIdentifierCString(), (int)result);
5933 	} else if (!alreadyLoaded) {
5934 		OSKextLog(this,
5935 		    kOSKextLogProgressLevel |
5936 		    kOSKextLogLoadFlag,
5937 		    "Kext %s loaded.",
5938 		    getIdentifierCString());
5939 
5940 		queueKextNotification(kKextRequestPredicateLoadNotification,
5941 		    OSDynamicCast(OSString, bundleID.get()));
5942 	}
5943 	return result;
5944 }
5945 
5946 #if CONFIG_KXLD
5947 /*********************************************************************
5948 *
5949 *********************************************************************/
5950 static char *
strdup(const char * string)5951 strdup(const char * string)
5952 {
5953 	char * result = NULL;
5954 	size_t size;
5955 
5956 	if (!string) {
5957 		goto finish;
5958 	}
5959 
5960 	size = 1 + strlen(string);
5961 	result = (char *)kalloc_data_tag(size, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
5962 	if (!result) {
5963 		goto finish;
5964 	}
5965 
5966 	memcpy(result, string, size);
5967 
5968 finish:
5969 	return result;
5970 }
5971 #endif // CONFIG_KXLD
5972 
5973 /*********************************************************************
5974 *
5975 *********************************************************************/
5976 
5977 kernel_section_t *
lookupSection(const char * segname,const char * secname)5978 OSKext::lookupSection(const char *segname, const char *secname)
5979 {
5980 	kernel_section_t         * found_section = NULL;
5981 	kernel_mach_header_t     * mh            = NULL;
5982 	kernel_segment_command_t * seg           = NULL;
5983 	kernel_section_t         * sec           = NULL;
5984 
5985 	if (!linkedExecutable) {
5986 		return NULL;
5987 	}
5988 
5989 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5990 
5991 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5992 		if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
5993 			continue;
5994 		}
5995 
5996 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5997 			if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
5998 				found_section = sec;
5999 				goto out;
6000 			}
6001 		}
6002 	}
6003 
6004 out:
6005 	return found_section;
6006 }
6007 
6008 /*********************************************************************
6009 *
6010 *********************************************************************/
6011 
6012 OSReturn
slidePrelinkedExecutable(bool doCoalescedSlides)6013 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides)
6014 {
6015 	OSReturn                       result           = kOSKextReturnBadData;
6016 	kernel_mach_header_t         * mh               = NULL;
6017 	kernel_segment_command_t     * seg              = NULL;
6018 	kernel_segment_command_t     * linkeditSeg      = NULL;
6019 	kernel_section_t             * sec              = NULL;
6020 	char                         * linkeditBase     = NULL;
6021 	bool                           haveLinkeditBase = false;
6022 	char                         * relocBase        = NULL;
6023 	bool                           haveRelocBase    = false;
6024 	struct dysymtab_command      * dysymtab         = NULL;
6025 	struct linkedit_data_command * segmentSplitInfo = NULL;
6026 	struct symtab_command        * symtab           = NULL;
6027 	kernel_nlist_t               * sym              = NULL;
6028 	struct relocation_info       * reloc            = NULL;
6029 	uint32_t                       i                = 0;
6030 	int                            reloc_size;
6031 	vm_offset_t                    new_kextsize;
6032 
6033 	if (linkedExecutable == NULL || flags.builtin) {
6034 		result = kOSReturnSuccess;
6035 		goto finish;
6036 	}
6037 
6038 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6039 	if (kernel_mach_header_is_in_fileset(mh)) {
6040 		// kexts in filesets are slid as part of collection sliding
6041 		result = kOSReturnSuccess;
6042 		goto finish;
6043 	}
6044 
6045 	segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
6046 
6047 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6048 		if (!seg->vmaddr) {
6049 			continue;
6050 		}
6051 
6052 		seg->vmaddr = ml_static_slide(seg->vmaddr);
6053 
6054 #if KASLR_KEXT_DEBUG
6055 		IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
6056 		    seg->segname,
6057 		    (unsigned long)ml_static_unslide(seg->vmaddr),
6058 		    (unsigned long)seg->vmaddr);
6059 #endif
6060 
6061 		if (!haveRelocBase) {
6062 			relocBase = (char *) seg->vmaddr;
6063 			haveRelocBase = true;
6064 		}
6065 		if (!strcmp(seg->segname, "__LINKEDIT")) {
6066 			linkeditBase = (char *) seg->vmaddr - seg->fileoff;
6067 			haveLinkeditBase = true;
6068 			linkeditSeg = seg;
6069 		}
6070 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6071 			sec->addr = ml_static_slide(sec->addr);
6072 
6073 #if KASLR_KEXT_DEBUG
6074 			IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
6075 			    sec->sectname,
6076 			    (unsigned long)ml_static_unslide(sec->addr),
6077 			    (unsigned long)sec->addr);
6078 #endif
6079 		}
6080 	}
6081 
6082 	dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
6083 
6084 	symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
6085 
6086 	if (symtab != NULL && doCoalescedSlides == false) {
6087 		/* Some pseudo-kexts have symbol tables without segments.
6088 		 * Ignore them. */
6089 		if (symtab->nsyms > 0 && haveLinkeditBase) {
6090 			sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
6091 			for (i = 0; i < symtab->nsyms; i++) {
6092 				if (sym[i].n_type & N_STAB) {
6093 					continue;
6094 				}
6095 				sym[i].n_value = ml_static_slide(sym[i].n_value);
6096 
6097 #if KASLR_KEXT_DEBUG
6098 #define MAX_SYMS_TO_LOG 5
6099 				if (i < MAX_SYMS_TO_LOG) {
6100 					IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
6101 					    (unsigned long)ml_static_unslide(sym[i].n_value),
6102 					    (unsigned long)sym[i].n_value);
6103 				}
6104 #endif
6105 			}
6106 		}
6107 	}
6108 
6109 	if (dysymtab != NULL && doCoalescedSlides == false) {
6110 		if (dysymtab->nextrel > 0) {
6111 			OSKextLog(this,
6112 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6113 			    kOSKextLogLinkFlag,
6114 			    "Sliding kext %s: External relocations found.",
6115 			    getIdentifierCString());
6116 			goto finish;
6117 		}
6118 
6119 		if (dysymtab->nlocrel > 0) {
6120 			if (!haveLinkeditBase) {
6121 				OSKextLog(this,
6122 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6123 				    kOSKextLogLinkFlag,
6124 				    "Sliding kext %s: No linkedit segment.",
6125 				    getIdentifierCString());
6126 				goto finish;
6127 			}
6128 
6129 			if (!haveRelocBase) {
6130 				OSKextLog(this,
6131 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6132 				    kOSKextLogLinkFlag,
6133 #if __x86_64__
6134 				    "Sliding kext %s: No writable segments.",
6135 #else
6136 				    "Sliding kext %s: No segments.",
6137 #endif
6138 				    getIdentifierCString());
6139 				goto finish;
6140 			}
6141 
6142 			reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
6143 			reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
6144 
6145 			for (i = 0; i < dysymtab->nlocrel; i++) {
6146 				if (reloc[i].r_extern != 0
6147 				    || reloc[i].r_type != 0
6148 				    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
6149 				    ) {
6150 					OSKextLog(this,
6151 					    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6152 					    kOSKextLogLinkFlag,
6153 					    "Sliding kext %s: Unexpected relocation found.",
6154 					    getIdentifierCString());
6155 					goto finish;
6156 				}
6157 				if (reloc[i].r_pcrel != 0) {
6158 					continue;
6159 				}
6160 				uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
6161 				*relocAddr = ml_static_slide(*relocAddr);
6162 
6163 #if KASLR_KEXT_DEBUG
6164 #define MAX_DYSYMS_TO_LOG 5
6165 				if (i < MAX_DYSYMS_TO_LOG) {
6166 					IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
6167 					    (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
6168 					    (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
6169 				}
6170 #endif
6171 			}
6172 
6173 			/* We should free these relocations, not just delete the reference to them.
6174 			 * <rdar://problem/10535549> Free relocations from PIE kexts.
6175 			 *
6176 			 * For now, we do not free LINKEDIT for kexts with split segments.
6177 			 */
6178 			new_kextsize = round_page(kmod_info->size - reloc_size);
6179 			if (new_kextsize > UINT_MAX) {
6180 				OSKextLog(this,
6181 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6182 				    kOSKextLogLinkFlag,
6183 				    "Kext %s: new kext size is too large.",
6184 				    getIdentifierCString());
6185 				goto finish;
6186 			}
6187 			if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
6188 				vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
6189 				vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
6190 				vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
6191 				size_t          bytes_remaining = endofkext - endofrelocInfo;
6192 				OSSharedPtr<OSData>        new_osdata;
6193 
6194 				/* fix up symbol offsets if they are after the dsymtab local relocs */
6195 				if (symtab) {
6196 					if (dysymtab->locreloff < symtab->symoff) {
6197 						symtab->symoff -= reloc_size;
6198 					}
6199 					if (dysymtab->locreloff < symtab->stroff) {
6200 						symtab->stroff -= reloc_size;
6201 					}
6202 				}
6203 				if (dysymtab->locreloff < dysymtab->extreloff) {
6204 					dysymtab->extreloff -= reloc_size;
6205 				}
6206 
6207 				/* move data behind reloc info down to new offset */
6208 				if (endofrelocInfo < endofkext) {
6209 					memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
6210 				}
6211 
6212 				/* Create a new OSData for the smaller kext object and reflect
6213 				 * new linkedit segment size.
6214 				 */
6215 				linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
6216 				linkeditSeg->filesize = linkeditSeg->vmsize;
6217 
6218 				new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize);
6219 				if (new_osdata) {
6220 					/* Fix up kmod info and linkedExecutable.
6221 					 */
6222 					kmod_info->size = new_kextsize;
6223 #if VM_MAPPED_KEXTS
6224 					new_osdata->setDeallocFunction(osdata_kext_free);
6225 #else
6226 					new_osdata->setDeallocFunction(osdata_phys_free);
6227 #endif
6228 					linkedExecutable->setDeallocFunction(NULL);
6229 					linkedExecutable = os::move(new_osdata);
6230 
6231 #if VM_MAPPED_KEXTS
6232 					kext_free(new_endofkext, (endofkext - new_endofkext));
6233 #else
6234 					ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
6235 #endif
6236 				}
6237 			}
6238 			dysymtab->nlocrel = 0;
6239 			dysymtab->locreloff = 0;
6240 		}
6241 	}
6242 
6243 	result = kOSReturnSuccess;
6244 finish:
6245 	return result;
6246 }
6247 
6248 /*********************************************************************
6249 * called only by load()
6250 *********************************************************************/
6251 OSReturn
loadExecutable()6252 OSKext::loadExecutable()
6253 {
6254 	OSReturn              result             = kOSReturnError;
6255 	OSSharedPtr<OSArray>  linkDependencies;
6256 	uint32_t              num_kmod_refs      = 0;
6257 	OSData              * theExecutable      = NULL;        // do not release
6258 	OSString            * versString         = NULL;        // do not release
6259 	const char          * versCString        = NULL;        // do not free
6260 	const char          * string             = NULL;        // do not free
6261 
6262 #if CONFIG_KXLD
6263 	unsigned int          i;
6264 	uint32_t              numDirectDependencies   = 0;
6265 	kern_return_t         kxldResult;
6266 	KXLDDependency     *  kxlddeps           = NULL;        // must kfree
6267 	uint32_t              num_kxlddeps       = 0;
6268 	struct mach_header ** kxldHeaderPtr      = NULL;        // do not free
6269 	struct mach_header  * kxld_header        = NULL;        // xxx - need to free here?
6270 #endif // CONFIG_KXLD
6271 
6272 	/* We need the version string for a variety of bits below.
6273 	 */
6274 	versString = OSDynamicCast(OSString,
6275 	    getPropertyForHostArch(kCFBundleVersionKey));
6276 	if (!versString) {
6277 		goto finish;
6278 	}
6279 	versCString = versString->getCStringNoCopy();
6280 
6281 	if (isKernelComponent()) {
6282 		if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
6283 			if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
6284 				OSKextLog(this,
6285 				    kOSKextLogErrorLevel |
6286 				    kOSKextLogLoadFlag,
6287 				    "Kernel component %s has incorrect version %s; "
6288 				    "expected %s.",
6289 				    getIdentifierCString(),
6290 				    versCString, KERNEL6_VERSION);
6291 				result = kOSKextReturnInternalError;
6292 				goto finish;
6293 			} else if (strcmp(versCString, osrelease)) {
6294 				OSKextLog(this,
6295 				    kOSKextLogErrorLevel |
6296 				    kOSKextLogLoadFlag,
6297 				    "Kernel component %s has incorrect version %s; "
6298 				    "expected %s.",
6299 				    getIdentifierCString(),
6300 				    versCString, osrelease);
6301 				result = kOSKextReturnInternalError;
6302 				goto finish;
6303 			}
6304 		}
6305 	}
6306 
6307 #if defined(__x86_64__) || defined(__i386__)
6308 	if (flags.resetSegmentsFromVnode) {
6309 		/* Fixup the chains and slide the mach headers */
6310 		kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address;
6311 
6312 		if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) {
6313 			result = kOSKextReturnValidation;
6314 			goto finish;
6315 		}
6316 	}
6317 #endif //(__x86_64__) || defined(__i386__)
6318 
6319 	if (isPrelinked()) {
6320 		goto register_kmod;
6321 	}
6322 
6323 	/* <rdar://problem/21444003> all callers must be entitled */
6324 	if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) {
6325 		OSKextLog(this,
6326 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6327 		    "Not entitled to link kext '%s'",
6328 		    getIdentifierCString());
6329 		result = kOSKextReturnNotPrivileged;
6330 		goto finish;
6331 	}
6332 
6333 	theExecutable = getExecutable();
6334 	if (!theExecutable) {
6335 		if (declaresExecutable()) {
6336 			OSKextLog(this,
6337 			    kOSKextLogErrorLevel |
6338 			    kOSKextLogLoadFlag,
6339 			    "Can't load kext %s - executable is missing.",
6340 			    getIdentifierCString());
6341 			result = kOSKextReturnValidation;
6342 			goto finish;
6343 		}
6344 		goto register_kmod;
6345 	}
6346 
6347 	if (isInterface()) {
6348 		OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable);
6349 		if (executableCopy) {
6350 			setLinkedExecutable(executableCopy.get());
6351 		}
6352 		goto register_kmod;
6353 	}
6354 
6355 #if CONFIG_KXLD
6356 	numDirectDependencies = getNumDependencies();
6357 
6358 	if (flags.hasBleedthrough) {
6359 		linkDependencies = dependencies;
6360 	} else {
6361 		linkDependencies = OSArray::withArray(dependencies.get());
6362 		if (!linkDependencies) {
6363 			OSKextLog(this,
6364 			    kOSKextLogErrorLevel |
6365 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6366 			    "Can't allocate link dependencies to load kext %s.",
6367 			    getIdentifierCString());
6368 			goto finish;
6369 		}
6370 
6371 		for (i = 0; i < numDirectDependencies; ++i) {
6372 			OSKext * dependencyKext = OSDynamicCast(OSKext,
6373 			    dependencies->getObject(i));
6374 			dependencyKext->addBleedthroughDependencies(linkDependencies.get());
6375 		}
6376 	}
6377 
6378 	num_kxlddeps = linkDependencies->getCount();
6379 	if (!num_kxlddeps) {
6380 		OSKextLog(this,
6381 		    kOSKextLogErrorLevel |
6382 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6383 		    "Can't load kext %s - it has no library dependencies.",
6384 		    getIdentifierCString());
6385 		goto finish;
6386 	}
6387 
6388 	kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
6389 	if (!kxlddeps) {
6390 		OSKextLog(this,
6391 		    kOSKextLogErrorLevel |
6392 		    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6393 		    "Can't allocate link context to load kext %s.",
6394 		    getIdentifierCString());
6395 		goto finish;
6396 	}
6397 	bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
6398 
6399 	for (i = 0; i < num_kxlddeps; ++i) {
6400 		OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
6401 
6402 		if (dependency->isInterface()) {
6403 			OSKext *interfaceTargetKext = NULL;        //do not release
6404 			OSData * interfaceTarget = NULL;        //do not release
6405 
6406 			if (dependency->isKernelComponent()) {
6407 				interfaceTargetKext = sKernelKext;
6408 				interfaceTarget = sKernelKext->linkedExecutable.get();
6409 			} else {
6410 				interfaceTargetKext = OSDynamicCast(OSKext,
6411 				    dependency->dependencies->getObject(0));
6412 
6413 				interfaceTarget = interfaceTargetKext->linkedExecutable.get();
6414 			}
6415 
6416 			if (!interfaceTarget) {
6417 				// panic?
6418 				goto finish;
6419 			}
6420 
6421 			/* The names set here aren't actually logged yet <rdar://problem/7941514>,
6422 			 * it will be useful to have them in the debugger.
6423 			 * strdup() failing isn't critical right here so we don't check that.
6424 			 */
6425 			kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
6426 			kxlddeps[i].kext_size = interfaceTarget->getLength();
6427 			kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
6428 
6429 			if (dependency->linkedExecutable != NULL) {
6430 				kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
6431 				kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
6432 			} else {
6433 				kxlddeps[i].interface = (u_char *) NULL;
6434 				kxlddeps[i].interface_size = 0;
6435 			}
6436 			kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
6437 		} else {
6438 			kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
6439 			kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
6440 			kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
6441 		}
6442 
6443 		kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
6444 	}
6445 
6446 	kxldHeaderPtr = &kxld_header;
6447 
6448 #if DEBUG
6449 	OSKextLog(this,
6450 	    kOSKextLogExplicitLevel |
6451 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6452 	    "Kext %s - calling kxld_link_file:\n"
6453 	    "    kxld_context: %p\n"
6454 	    "    executable: %p    executable_length: %d\n"
6455 	    "    user_data: %p\n"
6456 	    "    kxld_dependencies: %p    num_dependencies: %d\n"
6457 	    "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
6458 	    getIdentifierCString(), sKxldContext,
6459 	    theExecutable->getBytesNoCopy(), theExecutable->getLength(),
6460 	    this, kxlddeps, num_kxlddeps,
6461 	    kxldHeaderPtr, &kmod_info);
6462 #endif
6463 
6464 	/* After this call, the linkedExecutable instance variable
6465 	 * should exist.
6466 	 */
6467 	kxldResult = kxld_link_file(sKxldContext,
6468 	    (u_char *)theExecutable->getBytesNoCopy(),
6469 	    theExecutable->getLength(),
6470 	    getIdentifierCString(), this, kxlddeps, num_kxlddeps,
6471 	    (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
6472 
6473 	if (kxldResult != KERN_SUCCESS) {
6474 		// xxx - add kxldResult here?
6475 		OSKextLog(this,
6476 		    kOSKextLogErrorLevel |
6477 		    kOSKextLogLoadFlag,
6478 		    "Can't load kext %s - link failed.",
6479 		    getIdentifierCString());
6480 		result = kOSKextReturnLinkError;
6481 		goto finish;
6482 	}
6483 
6484 	/* We've written data & instructions into kernel memory, so flush the data
6485 	 * cache and invalidate the instruction cache.
6486 	 * I/D caches are coherent on x86
6487 	 */
6488 #if !defined(__i386__) && !defined(__x86_64__)
6489 	flush_dcache(kmod_info->address, kmod_info->size, false);
6490 	invalidate_icache(kmod_info->address, kmod_info->size, false);
6491 #endif
6492 
6493 #else // !CONFIG_KXLD
6494 	OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6495 	    "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString());
6496 	result = kOSKextReturnLinkError;
6497 	goto finish;
6498 #endif // CONFIG_KXLD
6499 
6500 register_kmod:
6501 
6502 	if (isInterface()) {
6503 		/* Whip up a fake kmod_info entry for the interface kext.
6504 		 */
6505 		kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
6506 		if (!kmod_info) {
6507 			result = KERN_MEMORY_ERROR;
6508 			goto finish;
6509 		}
6510 
6511 		/* A pseudokext has almost nothing in its kmod_info struct.
6512 		 */
6513 		kmod_info->info_version = KMOD_INFO_VERSION;
6514 
6515 		/* An interface kext doesn't have a linkedExecutable, so save a
6516 		 * copy of the UUID out of the original executable via copyUUID()
6517 		 * while we still have the original executable.
6518 		 */
6519 		interfaceUUID = copyUUID();
6520 	}
6521 
6522 	kmod_info->id = loadTag = sNextLoadTag++;
6523 	kmod_info->reference_count = 0;         // KMOD_DECL... sets it to -1 (invalid).
6524 
6525 	/* Stamp the bundle ID and version from the OSKext over anything
6526 	 * resident inside the kmod_info.
6527 	 */
6528 	string = getIdentifierCString();
6529 	strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
6530 
6531 	string = versCString;
6532 	strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
6533 
6534 	/* Add the dependencies' kmod_info structs as kmod_references.
6535 	 */
6536 	num_kmod_refs = getNumDependencies();
6537 	if (num_kmod_refs) {
6538 		kmod_info->reference_list = kalloc_type_tag(kmod_reference_t,
6539 		    num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT);
6540 		if (!kmod_info->reference_list) {
6541 			result = KERN_MEMORY_ERROR;
6542 			goto finish;
6543 		}
6544 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
6545 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
6546 			OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
6547 			ref->info = refKext->kmod_info;
6548 			ref->info->reference_count++;
6549 
6550 			if (refIndex + 1 < num_kmod_refs) {
6551 				ref->next = kmod_info->reference_list + refIndex + 1;
6552 			}
6553 		}
6554 	}
6555 
6556 	if (kmod_info->hdr_size > UINT32_MAX) {
6557 		OSKextLog(this,
6558 		    kOSKextLogErrorLevel |
6559 		    kOSKextLogLoadFlag,
6560 #if __LP64__
6561 		    "Kext %s header size is too large (%lu > UINT32_MAX).",
6562 #else
6563 		    "Kext %s header size is too large (%u > UINT32_MAX).",
6564 #endif
6565 		    kmod_info->name,
6566 		    kmod_info->hdr_size);
6567 		result = KERN_FAILURE;
6568 		goto finish;
6569 	}
6570 
6571 	if (kmod_info->size > UINT32_MAX) {
6572 		OSKextLog(this,
6573 		    kOSKextLogErrorLevel |
6574 		    kOSKextLogLoadFlag,
6575 #if __LP64__
6576 		    "Kext %s size is too large (%lu > UINT32_MAX).",
6577 #else
6578 		    "Kext %s size is too large (%u > UINT32_MAX).",
6579 #endif
6580 		    kmod_info->name,
6581 		    kmod_info->size);
6582 		result = KERN_FAILURE;
6583 		goto finish;
6584 	}
6585 
6586 	if (!isInterface() && linkedExecutable) {
6587 		OSKextLog(this,
6588 		    kOSKextLogProgressLevel |
6589 		    kOSKextLogLoadFlag,
6590 		    "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
6591 		    kmod_info->name,
6592 		    (unsigned)kmod_info->size / PAGE_SIZE,
6593 		    (unsigned long)ml_static_unslide(kmod_info->address),
6594 		    (unsigned)kmod_info->id);
6595 	}
6596 
6597 	/* VM protections and wiring for the Aux KC are done at collection loading time */
6598 	if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) {
6599 		/* if prelinked and primary KC, VM protections are already set */
6600 		result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true);
6601 		if (result != KERN_SUCCESS) {
6602 			goto finish;
6603 		}
6604 	}
6605 
6606 #if KASAN
6607 	if (linkedExecutable) {
6608 		kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
6609 		    linkedExecutable->getLength(), getIdentifierCString());
6610 	}
6611 #else
6612 	if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
6613 		OSKextLog(this,
6614 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6615 		    "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
6616 		    getIdentifierCString()
6617 		    );
6618 		result = KERN_FAILURE;
6619 		goto finish;
6620 	}
6621 #endif
6622 
6623 	result = kOSReturnSuccess;
6624 
6625 finish:
6626 
6627 #if CONFIG_KXLD
6628 	/* Clear up locally allocated dependency info.
6629 	 */
6630 	for (i = 0; i < num_kxlddeps; ++i) {
6631 		size_t size;
6632 
6633 		if (kxlddeps[i].kext_name) {
6634 			size = 1 + strlen(kxlddeps[i].kext_name);
6635 			kfree_data(kxlddeps[i].kext_name, size);
6636 		}
6637 		if (kxlddeps[i].interface_name) {
6638 			size = 1 + strlen(kxlddeps[i].interface_name);
6639 			kfree_data(kxlddeps[i].interface_name, size);
6640 		}
6641 	}
6642 	if (kxlddeps) {
6643 		kfree_type(KXLDDependency, num_kxlddeps, kxlddeps);
6644 	}
6645 #endif // CONFIG_KXLD
6646 
6647 	/* We no longer need the unrelocated executable (which the linker
6648 	 * has altered anyhow).
6649 	 */
6650 	setExecutable(NULL);
6651 
6652 	if (result != kOSReturnSuccess) {
6653 		OSKextLog(this,
6654 		    kOSKextLogErrorLevel |
6655 		    kOSKextLogLoadFlag,
6656 		    "Failed to load executable for kext %s.",
6657 		    getIdentifierCString());
6658 
6659 		if (kmod_info && kmod_info->reference_list) {
6660 			kfree_type(kmod_reference_t, num_kmod_refs,
6661 			    kmod_info->reference_list);
6662 		}
6663 		if (isInterface()) {
6664 			kfree_type(kmod_info_t, kmod_info);
6665 			kmod_info = NULL;
6666 		}
6667 		if (kc_type == KCKindUnknown) {
6668 			kmod_info = NULL;
6669 			if (linkedExecutable) {
6670 				linkedExecutable.reset();
6671 			}
6672 		}
6673 	}
6674 
6675 	return result;
6676 }
6677 
6678 /* static */
6679 void
jettisonFileSetLinkeditSegment(kernel_mach_header_t * mh)6680 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh)
6681 {
6682 	kernel_segment_command_t *linkeditseg = NULL;
6683 
6684 	linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT);
6685 	if (linkeditseg == NULL) {
6686 		panic("FileSet booted with no Linkedit segment");
6687 	}
6688 
6689 #if VM_MAPPED_KEXTS
6690 	/* BootKC on x86_64 is not vm mapped */
6691 	ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize);
6692 
6693 	OSKextLog(/* kext */ NULL,
6694 	    kOSKextLogProgressLevel |
6695 	    kOSKextLogGeneralFlag,
6696 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
6697 	    linkeditseg->vmaddr, linkeditseg->vmsize);
6698 #else
6699 	/* BootKC on arm64 is not vm mapped, but is slid */
6700 	vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase));
6701 
6702 	ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize);
6703 
6704 	OSKextLog(/* kext */ NULL,
6705 	    kOSKextLogProgressLevel |
6706 	    kOSKextLogGeneralFlag,
6707 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
6708 	    (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize);
6709 #endif /* VM_MAPPED_KEXTS */
6710 }
6711 
6712 /*********************************************************************
6713 * The linkedit segment is used by the kext linker for dependency
6714 * resolution, and by dtrace for probe initialization. We can free it
6715 * for non-library kexts, since no kexts depend on non-library kexts
6716 * by definition, once dtrace has been initialized.
6717 *********************************************************************/
6718 void
jettisonLinkeditSegment(void)6719 OSKext::jettisonLinkeditSegment(void)
6720 {
6721 	kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
6722 	kernel_segment_command_t * linkedit = NULL;
6723 	vm_offset_t                start;
6724 	vm_size_t                  linkeditsize, kextsize;
6725 	OSSharedPtr<OSData>        data;
6726 
6727 	if (isInFileset()) {
6728 		return;
6729 	}
6730 
6731 #if NO_KEXTD
6732 	/* We can free symbol tables for all embedded kexts because we don't
6733 	 * support runtime kext linking.
6734 	 */
6735 	if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
6736 #else
6737 	if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
6738 #endif
6739 		goto finish;
6740 	}
6741 
6742 	/* Find the linkedit segment.  If it's not the last segment, then freeing
6743 	 * it will fragment the kext into multiple VM regions, which OSKext is not
6744 	 * designed to handle, so we'll have to skip it.
6745 	 */
6746 	linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
6747 	if (!linkedit) {
6748 		goto finish;
6749 	}
6750 
6751 	if (round_page(kmod_info->address + kmod_info->size) !=
6752 	    round_page(linkedit->vmaddr + linkedit->vmsize)) {
6753 		goto finish;
6754 	}
6755 
6756 	/* Create a new OSData for the smaller kext object.
6757 	 */
6758 	linkeditsize = round_page(linkedit->vmsize);
6759 	kextsize = kmod_info->size - linkeditsize;
6760 	start = linkedit->vmaddr;
6761 
6762 	if (kextsize > UINT_MAX) {
6763 		goto finish;
6764 	}
6765 	data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize);
6766 	if (!data) {
6767 		goto finish;
6768 	}
6769 
6770 	/* Fix the kmod info and linkedExecutable.
6771 	 */
6772 	kmod_info->size = kextsize;
6773 
6774 #if VM_MAPPED_KEXTS
6775 	data->setDeallocFunction(osdata_kext_free);
6776 #else
6777 	data->setDeallocFunction(osdata_phys_free);
6778 #endif
6779 	linkedExecutable->setDeallocFunction(NULL);
6780 	linkedExecutable = os::move(data);
6781 	flags.jettisonLinkeditSeg = 1;
6782 
6783 	/* Free the linkedit segment.
6784 	 */
6785 #if VM_MAPPED_KEXTS
6786 	kext_free(start, linkeditsize);
6787 #else
6788 	ml_static_mfree(start, linkeditsize);
6789 #endif
6790 
6791 finish:
6792 	return;
6793 }
6794 
6795 /*********************************************************************
6796 * If there are whole pages that are unused betweem the last section
6797 * of the DATA segment and the end of the DATA segment then we can free
6798 * them
6799 *********************************************************************/
6800 void
6801 OSKext::jettisonDATASegmentPadding(void)
6802 {
6803 	kernel_mach_header_t * mh;
6804 	kernel_segment_command_t * dataSeg;
6805 	kernel_section_t * sec, * lastSec;
6806 	vm_offset_t dataSegEnd, lastSecEnd;
6807 	vm_size_t padSize;
6808 
6809 	if (flags.builtin) {
6810 		return;
6811 	}
6812 	mh = (kernel_mach_header_t *)kmod_info->address;
6813 
6814 	if (isInFileset()) {
6815 		return;
6816 	}
6817 
6818 	dataSeg = getsegbynamefromheader(mh, SEG_DATA);
6819 	if (dataSeg == NULL) {
6820 		return;
6821 	}
6822 
6823 	lastSec = NULL;
6824 	sec = firstsect(dataSeg);
6825 	while (sec != NULL) {
6826 		lastSec = sec;
6827 		sec = nextsect(dataSeg, sec);
6828 	}
6829 
6830 	if (lastSec == NULL) {
6831 		return;
6832 	}
6833 
6834 	if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
6835 	    (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
6836 		return;
6837 	}
6838 
6839 	dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
6840 	lastSecEnd = round_page(lastSec->addr + lastSec->size);
6841 
6842 	if (dataSegEnd <= lastSecEnd) {
6843 		return;
6844 	}
6845 
6846 	padSize = dataSegEnd - lastSecEnd;
6847 
6848 	if (padSize >= PAGE_SIZE) {
6849 #if VM_MAPPED_KEXTS
6850 		kext_free(lastSecEnd, padSize);
6851 #else
6852 		ml_static_mfree(lastSecEnd, padSize);
6853 #endif
6854 	}
6855 }
6856 
6857 /*********************************************************************
6858 *********************************************************************/
6859 void
6860 OSKext::setLinkedExecutable(OSData * anExecutable)
6861 {
6862 	if (linkedExecutable) {
6863 		panic("Attempt to set linked executable on kext "
6864 		    "that already has one (%s).\n",
6865 		    getIdentifierCString());
6866 	}
6867 	linkedExecutable.reset(anExecutable, OSRetain);
6868 	return;
6869 }
6870 
6871 #if CONFIG_DTRACE
6872 /*********************************************************************
6873 * Go through all loaded kexts and tell them to register with dtrace.
6874 * The instance method only registers if necessary.
6875 *********************************************************************/
6876 /* static */
6877 void
6878 OSKext::registerKextsWithDTrace(void)
6879 {
6880 	uint32_t count = sLoadedKexts->getCount();
6881 	uint32_t i;
6882 
6883 	IORecursiveLockLock(sKextLock);
6884 
6885 	for (i = 0; i < count; i++) {
6886 		OSKext   * thisKext     = NULL;        // do not release
6887 
6888 		thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
6889 		if (!thisKext || !thisKext->isExecutable()) {
6890 			continue;
6891 		}
6892 
6893 		thisKext->registerWithDTrace();
6894 	}
6895 
6896 	IORecursiveLockUnlock(sKextLock);
6897 
6898 	return;
6899 }
6900 
6901 extern "C" {
6902 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
6903 extern int (*dtrace_modunload)(struct kmod_info *);
6904 };
6905 
6906 /*********************************************************************
6907 *********************************************************************/
6908 void
6909 OSKext::registerWithDTrace(void)
6910 {
6911 	/* Register kext with dtrace. A dtrace_modload failure should not
6912 	 * prevent a kext from loading, so we ignore the return code.
6913 	 */
6914 	if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
6915 		uint32_t modflag = 0;
6916 		OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
6917 
6918 #if XNU_TARGET_OS_OSX
6919 		if (!sKeepSymbols && kc_type == KCKindPrimary) {
6920 			if (forceInit == kOSBooleanTrue) {
6921 				OSKextLog(this,
6922 				    kOSKextLogBasicLevel |
6923 				    kOSKextLogGeneralFlag,
6924 				    "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s",
6925 				    getIdentifierCString());
6926 				forceInit = kOSBooleanFalse;
6927 			}
6928 			/* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */
6929 			modflag |= KMOD_DTRACE_NO_KERNEL_SYMS;
6930 		}
6931 #endif /* XNU_TARGET_OS_OSX */
6932 		if (forceInit == kOSBooleanTrue) {
6933 			modflag |= KMOD_DTRACE_FORCE_INIT;
6934 		}
6935 		if (flags.builtin) {
6936 			modflag |= KMOD_DTRACE_STATIC_KEXT;
6937 		}
6938 
6939 		(void)(*dtrace_modload)(kmod_info, modflag);
6940 		flags.dtraceInitialized = true;
6941 		jettisonLinkeditSegment();
6942 	}
6943 	return;
6944 }
6945 /*********************************************************************
6946 *********************************************************************/
6947 void
6948 OSKext::unregisterWithDTrace(void)
6949 {
6950 	/* Unregister kext with dtrace. A dtrace_modunload failure should not
6951 	 * prevent a kext from loading, so we ignore the return code.
6952 	 */
6953 	if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
6954 		(void)(*dtrace_modunload)(kmod_info);
6955 		flags.dtraceInitialized = false;
6956 	}
6957 	return;
6958 }
6959 #endif /* CONFIG_DTRACE */
6960 
6961 
6962 /*********************************************************************
6963 * called only by loadExecutable()
6964 *********************************************************************/
6965 #if !VM_MAPPED_KEXTS
6966 #if defined(__arm__) || defined(__arm64__)
6967 static inline kern_return_t
6968 OSKext_protect(
6969 	kernel_mach_header_t *kext_mh,
6970 	vm_map_t   map,
6971 	vm_map_offset_t    start,
6972 	vm_map_offset_t    end,
6973 	vm_prot_t  new_prot,
6974 	boolean_t  set_max,
6975 	kc_kind_t  kc_type)
6976 {
6977 #pragma unused(kext_mh,map,kc_type)
6978 	assert(map == kernel_map);         // we can handle KEXTs arising from the PRELINK segment and no others
6979 	assert(start <= end);
6980 	if (start >= end) {
6981 		return KERN_SUCCESS;         // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
6982 	} else if (set_max) {
6983 		return KERN_SUCCESS;         // Punt set_max, as there's no mechanism to record that state
6984 	} else {
6985 		return ml_static_protect(start, end - start, new_prot);
6986 	}
6987 }
6988 
6989 static inline kern_return_t
6990 OSKext_wire(
6991 	kernel_mach_header_t *kext_mh,
6992 	vm_map_t   map,
6993 	vm_map_offset_t    start,
6994 	vm_map_offset_t    end,
6995 	vm_prot_t  access_type,
6996 	boolean_t       user_wire,
6997 	kc_kind_t       kc_type)
6998 {
6999 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type)
7000 	return KERN_SUCCESS;         // No-op as PRELINK kexts are cemented into physical memory at boot
7001 }
7002 #else
7003 #error Unrecognized architecture
7004 #endif
7005 #else
7006 static inline kern_return_t
7007 OSKext_protect(
7008 	kernel_mach_header_t *kext_mh,
7009 	vm_map_t   map,
7010 	vm_map_offset_t    start,
7011 	vm_map_offset_t    end,
7012 	vm_prot_t  new_prot,
7013 	boolean_t  set_max,
7014 	kc_kind_t  kc_type)
7015 {
7016 	if (start == end) {         // 10538581
7017 		return KERN_SUCCESS;
7018 	}
7019 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7020 		/*
7021 		 * XXX: This will probably need to be different for AuxKC and
7022 		 * pageableKC!
7023 		 */
7024 		return ml_static_protect(start, end - start, new_prot);
7025 	}
7026 	return vm_map_protect(map, start, end, new_prot, set_max);
7027 }
7028 
7029 static inline kern_return_t
7030 OSKext_wire(
7031 	kernel_mach_header_t *kext_mh,
7032 	vm_map_t   map,
7033 	vm_map_offset_t    start,
7034 	vm_map_offset_t    end,
7035 	vm_prot_t  access_type,
7036 	boolean_t       user_wire,
7037 	kc_kind_t       kc_type)
7038 {
7039 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7040 		/* TODO: we may need to hook this for the pageableKC */
7041 		return KERN_SUCCESS;
7042 	}
7043 	return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
7044 }
7045 #endif
7046 
7047 OSReturn
7048 OSKext::setVMAttributes(bool protect, bool wire)
7049 {
7050 	vm_map_t                    kext_map        = NULL;
7051 	kernel_segment_command_t  * seg             = NULL;
7052 	vm_map_offset_t             start_protect   = 0;
7053 	vm_map_offset_t             start_wire      = 0;
7054 	vm_map_offset_t             end_protect     = 0;
7055 	vm_map_offset_t             end_wire        = 0;
7056 	OSReturn                    result          = kOSReturnError;
7057 
7058 	if (isInterface() || !declaresExecutable() || flags.builtin) {
7059 		result = kOSReturnSuccess;
7060 		goto finish;
7061 	}
7062 
7063 	/* Get the kext's vm map */
7064 	kext_map = kext_get_vm_map(kmod_info);
7065 	if (!kext_map) {
7066 		result = KERN_MEMORY_ERROR;
7067 		goto finish;
7068 	}
7069 
7070 #if !VM_MAPPED_KEXTS
7071 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
7072 		/* This is a split kext in a prelinked kernelcache; we'll let the
7073 		 * platform code take care of protecting it.  It is already wired.
7074 		 */
7075 		/* TODO: Should this still allow protections for the first segment
7076 		 * to go through, in the event that we have a mix of split and
7077 		 * unsplit kexts?
7078 		 */
7079 		result = KERN_SUCCESS;
7080 		goto finish;
7081 	}
7082 
7083 	if (isInFileset() && kc_type != KCKindPageable) {
7084 		// kexts in filesets have protections setup as part of collection loading
7085 		result = KERN_SUCCESS;
7086 		goto finish;
7087 	}
7088 #endif
7089 
7090 	/* Protect the headers as read-only; they do not need to be wired */
7091 	result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7092 	    kext_map, kmod_info->address,
7093 	    kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type)
7094 	    : KERN_SUCCESS;
7095 	if (result != KERN_SUCCESS) {
7096 		goto finish;
7097 	}
7098 
7099 	/* Set the VM protections and wire down each of the segments */
7100 	seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7101 	while (seg) {
7102 #if __arm__
7103 		/* We build all ARM kexts, so we can ensure they are aligned */
7104 		assert((seg->vmaddr & PAGE_MASK) == 0);
7105 		assert((seg->vmsize & PAGE_MASK) == 0);
7106 #endif
7107 
7108 		/*
7109 		 * For the non page aligned segments, the range calculation for protection
7110 		 * and wiring differ as follows:
7111 		 *
7112 		 * Protection: The non page aligned data at the start or at the end of the
7113 		 * segment is excluded from the protection. This exclusion is needed to make
7114 		 * sure OSKext_protect is not called twice on same page, if the page is shared
7115 		 * between two segments.
7116 		 *
7117 		 * Wiring: The non page aligned data at the start or at the end of the
7118 		 * segment is included in the wiring range, this inclusion is needed to make sure
7119 		 * all the data of the segment is wired.
7120 		 */
7121 		start_protect = round_page(seg->vmaddr);
7122 		end_protect = trunc_page(seg->vmaddr + seg->vmsize);
7123 
7124 		start_wire = trunc_page(seg->vmaddr);
7125 		end_wire = round_page(seg->vmaddr + seg->vmsize);
7126 
7127 		/*
7128 		 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared
7129 		 * across kexts and data from kexts is not page aligned
7130 		 */
7131 		if (protect && (end_protect > start_protect) &&
7132 		    ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 &&
7133 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) ||
7134 		    (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) {
7135 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7136 			    kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type);
7137 			if (result != KERN_SUCCESS) {
7138 				OSKextLog(this,
7139 				    kOSKextLogErrorLevel |
7140 				    kOSKextLogLoadFlag,
7141 				    "Kext %s failed to set maximum VM protections "
7142 				    "for segment %s - 0x%x.",
7143 				    getIdentifierCString(), seg->segname, (int)result);
7144 				goto finish;
7145 			}
7146 
7147 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7148 			    kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type);
7149 			if (result != KERN_SUCCESS) {
7150 				OSKextLog(this,
7151 				    kOSKextLogErrorLevel |
7152 				    kOSKextLogLoadFlag,
7153 				    "Kext %s failed to set initial VM protections "
7154 				    "for segment %s - 0x%x.",
7155 				    getIdentifierCString(), seg->segname, (int)result);
7156 				goto finish;
7157 			}
7158 		}
7159 
7160 		if (segmentShouldBeWired(seg) && wire) {
7161 			result = OSKext_wire((kernel_mach_header_t *)kmod_info->address,
7162 			    kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type);
7163 			if (result != KERN_SUCCESS) {
7164 				goto finish;
7165 			}
7166 		}
7167 
7168 		seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7169 	}
7170 
7171 finish:
7172 	return result;
7173 }
7174 
7175 /*********************************************************************
7176 *********************************************************************/
7177 boolean_t
7178 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
7179 {
7180 	return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) &&
7181 	       strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)));
7182 }
7183 
7184 /*********************************************************************
7185 *********************************************************************/
7186 OSReturn
7187 OSKext::validateKextMapping(bool startFlag)
7188 {
7189 	OSReturn                              result      = kOSReturnError;
7190 	const char                          * whichOp = startFlag ? "start" : "stop";
7191 	kern_return_t                         kern_result = 0;
7192 	vm_map_t                              kext_map    = NULL;
7193 	kernel_segment_command_t            * seg         = NULL;
7194 	mach_vm_address_t                     address     = 0;
7195 	mach_vm_size_t                        size        = 0;
7196 	uint32_t                              depth       = 0;
7197 	uint64_t                              kext_segbase = 0;
7198 	uint64_t                              kext_segsize = 0;
7199 	mach_msg_type_number_t                count;
7200 	vm_region_submap_short_info_data_64_t info;
7201 	uintptr_t                             kext_slide = PE_get_kc_slide(kc_type);
7202 
7203 	if (flags.builtin) {
7204 		return kOSReturnSuccess;
7205 	}
7206 
7207 	count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
7208 	bzero(&info, sizeof(info));
7209 
7210 	// xxx - do we need a distinct OSReturn value for these or is "bad data"
7211 	// xxx - sufficient?
7212 
7213 	/* Verify that the kmod_info and start/stop pointers are non-NULL.
7214 	 */
7215 	if (!kmod_info) {
7216 		OSKextLog(this,
7217 		    kOSKextLogErrorLevel |
7218 		    kOSKextLogLoadFlag,
7219 		    "Kext %s - NULL kmod_info pointer.",
7220 		    getIdentifierCString());
7221 		result = kOSKextReturnBadData;
7222 		goto finish;
7223 	}
7224 
7225 	if (startFlag) {
7226 		address = (mach_vm_address_t)kmod_info->start;
7227 	} else {
7228 		address = (mach_vm_address_t)kmod_info->stop;
7229 	}
7230 
7231 	if (!address) {
7232 		OSKextLog(this,
7233 		    kOSKextLogErrorLevel |
7234 		    kOSKextLogLoadFlag,
7235 		    "Kext %s - NULL module %s pointer.",
7236 		    getIdentifierCString(), whichOp);
7237 		result = kOSKextReturnBadData;
7238 		goto finish;
7239 	}
7240 
7241 	kext_map = kext_get_vm_map(kmod_info);
7242 	depth = (kernel_map == kext_map) ? 1 : 2;
7243 	if (isInFileset()) {
7244 #if defined(HAS_APPLE_PAC)
7245 		address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0);
7246 #endif /* defined(HAS_APPLE_PAC) */
7247 	}
7248 
7249 	/* Verify that the start/stop function lies within the kext's address range.
7250 	 */
7251 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) ||
7252 	    isInFileset()) {
7253 		/* This will likely be how we deal with split kexts; walk the segments to
7254 		 * check that the function lies inside one of the segments of this kext.
7255 		 */
7256 		for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7257 		    seg != NULL;
7258 		    seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
7259 			if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
7260 				kext_segbase = seg->vmaddr;
7261 				kext_segsize = seg->vmsize;
7262 				break;
7263 			}
7264 		}
7265 
7266 		if (!seg) {
7267 			OSKextLog(this,
7268 			    kOSKextLogErrorLevel |
7269 			    kOSKextLogLoadFlag,
7270 			    "Kext %s module %s pointer is outside of kext range "
7271 			    "(%s %p - kext starts at %p).",
7272 			    getIdentifierCString(),
7273 			    whichOp,
7274 			    whichOp,
7275 			    (void *)(((uintptr_t)address) - kext_slide),
7276 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide));
7277 			result = kOSKextReturnBadData;
7278 			goto finish;
7279 		}
7280 
7281 		seg = NULL;
7282 	} else {
7283 		if (address < kmod_info->address + kmod_info->hdr_size ||
7284 		    kmod_info->address + kmod_info->size <= address) {
7285 			OSKextLog(this,
7286 			    kOSKextLogErrorLevel |
7287 			    kOSKextLogLoadFlag,
7288 			    "Kext %s module %s pointer is outside of kext range "
7289 			    "(%s %p - kext at %p-%p).",
7290 			    getIdentifierCString(),
7291 			    whichOp,
7292 			    whichOp,
7293 			    (void *)(((uintptr_t)address) - kext_slide),
7294 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide),
7295 			    (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size));
7296 			result = kOSKextReturnBadData;
7297 			goto finish;
7298 		}
7299 	}
7300 
7301 	/* Only do these checks before calling the start function;
7302 	 * If anything goes wrong with the mapping while the kext is running,
7303 	 * we'll likely have panicked well before any attempt to stop the kext.
7304 	 */
7305 	if (startFlag) {
7306 		if (!isInFileset() || kc_type != KCKindPrimary) {
7307 			/*
7308 			 * Verify that the start/stop function is executable.
7309 			 */
7310 			kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
7311 			    (vm_region_recurse_info_t)&info, &count);
7312 			if (kern_result != KERN_SUCCESS) {
7313 				OSKextLog(this,
7314 				    kOSKextLogErrorLevel |
7315 				    kOSKextLogLoadFlag,
7316 				    "Kext %s - bad %s pointer %p.",
7317 				    getIdentifierCString(),
7318 				    whichOp, (void *)ml_static_unslide(address));
7319 				result = kOSKextReturnBadData;
7320 				goto finish;
7321 			}
7322 		} else {
7323 			/*
7324 			 * Since kexts loaded from the primary KC are held in memory
7325 			 * allocated by efiboot, we cannot use mach_vm_region_recurse() to
7326 			 * discover that memory's protection flags.  Instead, we need to
7327 			 * get that information from the kernel pmap itself.  Above, we
7328 			 * (potentially) saved the size of the segment in which the address
7329 			 * in question was located.  If we have a non-zero size, verify
7330 			 * that all pages in the (address, address + kext_segsize) range
7331 			 * are marked executable.  If we somehow did not record the size
7332 			 * (or the base) just verify the single page that includes the address.
7333 			 */
7334 			if (kext_segbase == 0 || kext_segsize == 0) {
7335 				kext_segbase = address & ~(uint64_t)PAGE_MASK;
7336 				kext_segsize = PAGE_SIZE;
7337 			}
7338 		}
7339 
7340 #if VM_MAPPED_KEXTS
7341 		if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) ||
7342 		    ((isInFileset() && kc_type == KCKindPrimary) &&
7343 		    ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) {
7344 			OSKextLog(this,
7345 			    kOSKextLogErrorLevel |
7346 			    kOSKextLogLoadFlag,
7347 			    "Kext %s - memory region containing module %s function "
7348 			    "is not executable.",
7349 			    getIdentifierCString(), whichOp);
7350 			result = kOSKextReturnBadData;
7351 			goto finish;
7352 		}
7353 #endif
7354 
7355 		/* Verify that the kext's segments are backed by physical memory.
7356 		 */
7357 		seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7358 		while (seg) {
7359 			if (!verifySegmentMapping(seg)) {
7360 				result = kOSKextReturnBadData;
7361 				goto finish;
7362 			}
7363 
7364 			seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7365 		}
7366 	}
7367 
7368 	result = kOSReturnSuccess;
7369 finish:
7370 	return result;
7371 }
7372 
7373 /*********************************************************************
7374 *********************************************************************/
7375 boolean_t
7376 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
7377 {
7378 	mach_vm_address_t address = 0;
7379 
7380 	if (seg->vmsize > UINT32_MAX) {
7381 		return false;
7382 	}
7383 
7384 	if (!segmentShouldBeWired(seg)) {
7385 		return true;
7386 	}
7387 
7388 	for (address = seg->vmaddr;
7389 	    address < round_page(seg->vmaddr + seg->vmsize);
7390 	    address += PAGE_SIZE) {
7391 		if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
7392 			OSKextLog(this,
7393 			    kOSKextLogErrorLevel |
7394 			    kOSKextLogLoadFlag,
7395 			    "Kext %s - page %p is not backed by physical memory.",
7396 			    getIdentifierCString(),
7397 			    (void *)address);
7398 			return false;
7399 		}
7400 	}
7401 
7402 	return true;
7403 }
7404 
7405 /*********************************************************************
7406 *********************************************************************/
7407 static void
7408 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
7409 {
7410 	uint64_t                            stamp = 0;
7411 	firehose_tracepoint_id_u            trace_id;
7412 	struct firehose_trace_uuid_info_s   uuid_info_s;
7413 	firehose_trace_uuid_info_t          uuid_info = &uuid_info_s;
7414 	size_t                              uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
7415 	OSSharedPtr<OSData>                 uuid_data;
7416 
7417 	stamp = firehose_tracepoint_time(firehose_activity_flags_default);
7418 	trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
7419 
7420 	uuid_data = aKext->copyTextUUID();
7421 	if (uuid_data) {
7422 		memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
7423 	}
7424 
7425 	uuid_info->ftui_size    = size;
7426 	if (aKext->isDriverKit()) {
7427 		uuid_info->ftui_address = address;
7428 	} else {
7429 		uuid_info->ftui_address = ml_static_unslide(address);
7430 	}
7431 	firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
7432 	return;
7433 }
7434 
7435 void
7436 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
7437 {
7438 	OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
7439 }
7440 
7441 /*********************************************************************
7442 *********************************************************************/
7443 OSReturn
7444 OSKext::start(bool startDependenciesFlag)
7445 {
7446 	OSReturn                            result = kOSReturnError;
7447 	kern_return_t                       (* startfunc)(kmod_info_t *, void *);
7448 	unsigned int                        i, count;
7449 	void                              * kmodStartData = NULL;
7450 
7451 	if (isStarted() || isInterface() || isKernelComponent()) {
7452 		result = kOSReturnSuccess;
7453 		goto finish;
7454 	}
7455 
7456 	if (!isLoaded()) {
7457 		OSKextLog(this,
7458 		    kOSKextLogErrorLevel |
7459 		    kOSKextLogLoadFlag,
7460 		    "Attempt to start nonloaded kext %s.",
7461 		    getIdentifierCString());
7462 		result = kOSKextReturnInvalidArgument;
7463 		goto finish;
7464 	}
7465 
7466 	if (!sLoadEnabled) {
7467 		OSKextLog(this,
7468 		    kOSKextLogErrorLevel |
7469 		    kOSKextLogLoadFlag,
7470 		    "Kext loading is disabled (attempt to start kext %s).",
7471 		    getIdentifierCString());
7472 		result = kOSKextReturnDisabled;
7473 		goto finish;
7474 	}
7475 
7476 	result = validateKextMapping(/* start? */ true);
7477 	if (result != kOSReturnSuccess) {
7478 		goto finish;
7479 	}
7480 
7481 	startfunc = kmod_info->start;
7482 
7483 	count = getNumDependencies();
7484 	for (i = 0; i < count; i++) {
7485 		OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
7486 		if (dependency == NULL) {
7487 			OSKextLog(this,
7488 			    kOSKextLogErrorLevel |
7489 			    kOSKextLogLoadFlag,
7490 			    "Kext %s start - internal error, dependency disappeared.",
7491 			    getIdentifierCString());
7492 			goto finish;
7493 		}
7494 		if (!dependency->isStarted()) {
7495 			if (startDependenciesFlag) {
7496 				OSReturn dependencyResult =
7497 				    dependency->start(startDependenciesFlag);
7498 				if (dependencyResult != KERN_SUCCESS) {
7499 					OSKextLog(this,
7500 					    kOSKextLogErrorLevel |
7501 					    kOSKextLogLoadFlag,
7502 					    "Kext %s start - dependency %s failed to start (error 0x%x).",
7503 					    getIdentifierCString(),
7504 					    dependency->getIdentifierCString(),
7505 					    dependencyResult);
7506 					goto finish;
7507 				}
7508 			} else {
7509 				OSKextLog(this,
7510 				    kOSKextLogErrorLevel |
7511 				    kOSKextLogLoadFlag,
7512 				    "Not starting %s - dependency %s not started yet.",
7513 				    getIdentifierCString(),
7514 				    dependency->getIdentifierCString());
7515 				result = kOSKextReturnStartStopError;         // xxx - make new return?
7516 				goto finish;
7517 			}
7518 		}
7519 	}
7520 
7521 	OSKextLog(this,
7522 	    kOSKextLogDetailLevel |
7523 	    kOSKextLogLoadFlag,
7524 	    "Kext %s calling module start function.",
7525 	    getIdentifierCString());
7526 
7527 	flags.starting = 1;
7528 
7529 	// Drop a log message so logd can grab the needed information to decode this kext
7530 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
7531 	result = OSRuntimeInitializeCPP(this);
7532 	if (result == KERN_SUCCESS) {
7533 		result = startfunc(kmod_info, kmodStartData);
7534 	}
7535 
7536 	flags.starting = 0;
7537 
7538 	/* On success overlap the setting of started/starting. On failure just
7539 	 * clear starting.
7540 	 */
7541 	if (result == KERN_SUCCESS) {
7542 		flags.started = 1;
7543 
7544 		// xxx - log start error from kernel?
7545 		OSKextLog(this,
7546 		    kOSKextLogProgressLevel |
7547 		    kOSKextLogLoadFlag,
7548 		    "Kext %s is now started.",
7549 		    getIdentifierCString());
7550 	} else {
7551 		invokeOrCancelRequestCallbacks(
7552 			/* result not actually used */ kOSKextReturnStartStopError,
7553 			/* invokeFlag */ false);
7554 		OSKextLog(this,
7555 		    kOSKextLogWarningLevel |
7556 		    kOSKextLogLoadFlag,
7557 		    "Kext %s did not start (return code 0x%x).",
7558 		    getIdentifierCString(), result);
7559 	}
7560 
7561 finish:
7562 	return result;
7563 }
7564 
7565 /*********************************************************************
7566 *********************************************************************/
7567 /* static */
7568 bool
7569 OSKext::canUnloadKextWithIdentifier(
7570 	OSString * kextIdentifier,
7571 	bool       checkClassesFlag)
7572 {
7573 	bool     result = false;
7574 	OSKext * aKext  = NULL;        // do not release
7575 
7576 	IORecursiveLockLock(sKextLock);
7577 
7578 	aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
7579 
7580 	if (!aKext) {
7581 		goto finish;         // can't unload what's not loaded
7582 	}
7583 
7584 	if (aKext->isLoaded()) {
7585 		if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
7586 			goto finish;
7587 		}
7588 		if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
7589 			goto finish;
7590 		}
7591 	}
7592 
7593 	result = true;
7594 
7595 finish:
7596 	IORecursiveLockUnlock(sKextLock);
7597 	return result;
7598 }
7599 
7600 /*********************************************************************
7601 *********************************************************************/
7602 OSReturn
7603 OSKext::stop(void)
7604 {
7605 	OSReturn result = kOSReturnError;
7606 	kern_return_t (*stopfunc)(kmod_info_t *, void *);
7607 
7608 	if (!isStarted() || isInterface()) {
7609 		result = kOSReturnSuccess;
7610 		goto finish;
7611 	}
7612 
7613 	if (!isLoaded()) {
7614 		OSKextLog(this,
7615 		    kOSKextLogErrorLevel |
7616 		    kOSKextLogLoadFlag,
7617 		    "Attempt to stop nonloaded kext %s.",
7618 		    getIdentifierCString());
7619 		result = kOSKextReturnInvalidArgument;
7620 		goto finish;
7621 	}
7622 
7623 	/* Refuse to stop if we have clients or instances. It is up to
7624 	 * the caller to make sure those aren't true.
7625 	 */
7626 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7627 		OSKextLog(this,
7628 		    kOSKextLogErrorLevel |
7629 		    kOSKextLogLoadFlag,
7630 		    "Kext %s - C++ instances; can't stop.",
7631 		    getIdentifierCString());
7632 		result = kOSKextReturnInUse;
7633 		goto finish;
7634 	}
7635 
7636 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7637 		OSKextLog(this,
7638 		    kOSKextLogErrorLevel |
7639 		    kOSKextLogLoadFlag,
7640 		    "Kext %s - has references (linkage or tracking object); "
7641 		    "can't stop.",
7642 		    getIdentifierCString());
7643 		result = kOSKextReturnInUse;
7644 		goto finish;
7645 	}
7646 
7647 	/* Note: If validateKextMapping fails on the stop & unload path,
7648 	 * we are in serious trouble and a kernel panic is likely whether
7649 	 * we stop & unload the kext or not.
7650 	 */
7651 	result = validateKextMapping(/* start? */ false);
7652 	if (result != kOSReturnSuccess) {
7653 		goto finish;
7654 	}
7655 
7656 	stopfunc = kmod_info->stop;
7657 	if (stopfunc) {
7658 		OSKextLog(this,
7659 		    kOSKextLogDetailLevel |
7660 		    kOSKextLogLoadFlag,
7661 		    "Kext %s calling module stop function.",
7662 		    getIdentifierCString());
7663 
7664 		flags.stopping = 1;
7665 
7666 		result = stopfunc(kmod_info, /* userData */ NULL);
7667 		if (result == KERN_SUCCESS) {
7668 			result = OSRuntimeFinalizeCPP(this);
7669 		}
7670 
7671 		flags.stopping = 0;
7672 
7673 		if (result == KERN_SUCCESS) {
7674 			flags.started = 0;
7675 
7676 			OSKextLog(this,
7677 			    kOSKextLogDetailLevel |
7678 			    kOSKextLogLoadFlag,
7679 			    "Kext %s is now stopped and ready to unload.",
7680 			    getIdentifierCString());
7681 		} else {
7682 			OSKextLog(this,
7683 			    kOSKextLogErrorLevel |
7684 			    kOSKextLogLoadFlag,
7685 			    "Kext %s did not stop (return code 0x%x).",
7686 			    getIdentifierCString(), result);
7687 			result = kOSKextReturnStartStopError;
7688 		}
7689 	}
7690 
7691 finish:
7692 	// Drop a log message so logd can update this kext's metadata
7693 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
7694 	return result;
7695 }
7696 
7697 /*********************************************************************
7698 *********************************************************************/
7699 OSReturn
7700 OSKext::unload(void)
7701 {
7702 	OSReturn        result = kOSReturnError;
7703 	unsigned int    index;
7704 	uint32_t        num_kmod_refs = 0;
7705 	OSKextAccount * freeAccount;
7706 	bool            in_fileset = false;
7707 
7708 	if (!sUnloadEnabled) {
7709 		OSKextLog(this,
7710 		    kOSKextLogErrorLevel |
7711 		    kOSKextLogLoadFlag,
7712 		    "Kext unloading is disabled (%s).",
7713 		    this->getIdentifierCString());
7714 
7715 		result = kOSKextReturnDisabled;
7716 		goto finish;
7717 	}
7718 
7719 	// cache this result so we don't need to access the kmod_info after
7720 	// it's been potentially free'd
7721 	in_fileset = isInFileset();
7722 
7723 	/* Refuse to unload if we have clients or instances. It is up to
7724 	 * the caller to make sure those aren't true.
7725 	 */
7726 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7727 		// xxx - Don't log under errors? this is more of an info thing
7728 		OSKextLog(this,
7729 		    kOSKextLogErrorLevel |
7730 		    kOSKextLogKextBookkeepingFlag,
7731 		    "Can't unload kext %s; outstanding references (linkage or tracking object).",
7732 		    getIdentifierCString());
7733 		result = kOSKextReturnInUse;
7734 		goto finish;
7735 	}
7736 
7737 	if (isDriverKit()) {
7738 		index = sLoadedKexts->getNextIndexOfObject(this, 0);
7739 		if (index != (unsigned int)-1) {
7740 			sLoadedDriverKitKexts->removeObject(index);
7741 			OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
7742 			loadTag = 0;
7743 		}
7744 	}
7745 
7746 	if (!isLoaded()) {
7747 		result = kOSReturnSuccess;
7748 		goto finish;
7749 	}
7750 
7751 	if (isKernelComponent()) {
7752 		result = kOSKextReturnInvalidArgument;
7753 		goto finish;
7754 	}
7755 
7756 	if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) {
7757 		OSKextLog(this,
7758 		    kOSKextLogErrorLevel |
7759 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
7760 		    "Can't unload kext %s; classes have instances:",
7761 		    getIdentifierCString());
7762 		reportOSMetaClassInstances(kOSKextLogErrorLevel |
7763 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
7764 		result = kOSKextReturnInUse;
7765 		goto finish;
7766 	}
7767 
7768 	/* Note that the kext is unloading before running any code that
7769 	 * might be in the kext (request callbacks, module stop function).
7770 	 * We will deny certain requests made against a kext in the process
7771 	 * of unloading.
7772 	 */
7773 	flags.unloading = 1;
7774 
7775 	/* Update the string describing the last kext to unload in case we panic.
7776 	 */
7777 	savePanicString(/* isLoading */ false);
7778 
7779 	if (isStarted()) {
7780 		result = stop();
7781 		if (result != KERN_SUCCESS) {
7782 			OSKextLog(this,
7783 			    kOSKextLogErrorLevel |
7784 			    kOSKextLogLoadFlag,
7785 			    "Kext %s can't unload - module stop returned 0x%x.",
7786 			    getIdentifierCString(), (unsigned)result);
7787 			result = kOSKextReturnStartStopError;
7788 			goto finish;
7789 		}
7790 	}
7791 
7792 	OSKextLog(this,
7793 	    kOSKextLogProgressLevel |
7794 	    kOSKextLogLoadFlag,
7795 	    "Kext %s unloading.",
7796 	    getIdentifierCString());
7797 
7798 	{
7799 		struct list_head *p;
7800 		struct list_head *prev;
7801 		struct list_head *next;
7802 		for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
7803 			OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
7804 			s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
7805 			prev = p->prev;
7806 			next = p->next;
7807 			prev->next = next;
7808 			next->prev = prev;
7809 			p->prev = p;
7810 			p->next = p;
7811 			IORecursiveLockWakeup(sKextLock, s, false);
7812 		}
7813 	}
7814 
7815 
7816 	/* Even if we don't call the stop function, we want to be sure we
7817 	 * have no OSMetaClass references before unloading the kext executable
7818 	 * from memory. OSMetaClasses may have pointers into the kext executable
7819 	 * and that would cause a panic on OSKext::free() when metaClasses is freed.
7820 	 */
7821 	if (metaClasses) {
7822 		metaClasses->flushCollection();
7823 	}
7824 	(void) OSRuntimeFinalizeCPP(this);
7825 
7826 	/* Remove the kext from the list of loaded kexts, patch the gap
7827 	 * in the kmod_info_t linked list, and reset "kmod" to point to the
7828 	 * last loaded kext that isn't the fake kernel kext (sKernelKext).
7829 	 */
7830 	index = sLoadedKexts->getNextIndexOfObject(this, 0);
7831 	if (index != (unsigned int)-1) {
7832 		sLoadedKexts->removeObject(index);
7833 
7834 		OSKext * nextKext = OSDynamicCast(OSKext,
7835 		    sLoadedKexts->getObject(index));
7836 
7837 		if (nextKext) {
7838 			if (index > 0) {
7839 				OSKext * gapKext = OSDynamicCast(OSKext,
7840 				    sLoadedKexts->getObject(index - 1));
7841 
7842 				nextKext->kmod_info->next = gapKext->kmod_info;
7843 			} else {         /* index == 0 */
7844 				nextKext->kmod_info->next = NULL;
7845 			}
7846 		}
7847 
7848 		OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
7849 		if (lastKext && !lastKext->isKernel()) {
7850 			kmod = lastKext->kmod_info;
7851 		} else {
7852 			kmod = NULL;         // clear the global kmod variable
7853 		}
7854 	}
7855 
7856 	/* Clear out the kmod references that we're keeping for compatibility
7857 	 * with current panic backtrace code & kgmacros.
7858 	 * xxx - will want to update those bits sometime and remove this.
7859 	 */
7860 	num_kmod_refs = getNumDependencies();
7861 	if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
7862 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
7863 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
7864 			ref->info->reference_count--;
7865 		}
7866 		kfree_type(kmod_reference_t, num_kmod_refs,
7867 		    kmod_info->reference_list);
7868 	}
7869 
7870 #if CONFIG_DTRACE
7871 	unregisterWithDTrace();
7872 #endif /* CONFIG_DTRACE */
7873 
7874 	notifyKextUnloadObservers(this);
7875 
7876 	freeAccount = NULL;
7877 	IOSimpleLockLock(sKextAccountsLock);
7878 	account->kext = NULL;
7879 	if (account->site.tag) {
7880 		account->site.flags |= VM_TAG_UNLOAD;
7881 	} else {
7882 		freeAccount = account;
7883 	}
7884 
7885 #if DEVELOPMENT || DEBUG
7886 	assertf(account->task_refgrp.grp_count == 0,
7887 	    "unloading a kext with active task references");
7888 #endif /* DEVELOPMENT || DEBUG */
7889 
7890 	IOSimpleLockUnlock(sKextAccountsLock);
7891 	if (freeAccount) {
7892 		IOFreeType(freeAccount, OSKextAccount);
7893 	}
7894 
7895 	/* Unwire and free the linked executable.
7896 	 */
7897 	if (linkedExecutable) {
7898 #if KASAN
7899 		kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
7900 #endif
7901 
7902 #if VM_MAPPED_KEXTS
7903 		if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) {
7904 			kernel_segment_command_t *seg = NULL;
7905 			vm_map_t kext_map = kext_get_vm_map(kmod_info);
7906 
7907 			if (!kext_map) {
7908 				OSKextLog(this,
7909 				    kOSKextLogErrorLevel |
7910 				    kOSKextLogLoadFlag,
7911 				    "Failed to free kext %s; couldn't find the kext map.",
7912 				    getIdentifierCString());
7913 				result = kOSKextReturnInternalError;
7914 				goto finish;
7915 			}
7916 
7917 			OSKextLog(this,
7918 			    kOSKextLogProgressLevel |
7919 			    kOSKextLogLoadFlag,
7920 			    "Kext %s unwiring and unmapping linked executable.",
7921 			    getIdentifierCString());
7922 
7923 			seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7924 			while (seg) {
7925 				if (segmentShouldBeWired(seg)) {
7926 					vm_map_offset_t start_wire = trunc_page(seg->vmaddr);
7927 					vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize);
7928 
7929 					result = vm_map_unwire(kext_map, start_wire,
7930 					    end_wire, FALSE);
7931 					if (result != KERN_SUCCESS) {
7932 						OSKextLog(this,
7933 						    kOSKextLogErrorLevel |
7934 						    kOSKextLogLoadFlag,
7935 						    "Failed to unwire kext %s.",
7936 						    getIdentifierCString());
7937 						result = kOSKextReturnInternalError;
7938 						goto finish;
7939 					}
7940 				}
7941 
7942 				seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7943 			}
7944 #if defined(__x86_64__) || defined(__i386__)
7945 			if (in_fileset && flags.resetSegmentsFromVnode) {
7946 				IORecursiveLockLock(sKextLock);
7947 				resetKCFileSetSegments();
7948 				IORecursiveLockUnlock(sKextLock);
7949 			}
7950 #endif // (__x86_64__) || defined(__i386__)
7951 		}
7952 #endif /* VM_MAPPED_KEXTS */
7953 		if (flags.resetSegmentsFromImmutableCopy) {
7954 			result = resetMutableSegments();
7955 			if (result != kOSReturnSuccess) {
7956 				OSKextLog(this,
7957 				    kOSKextLogErrorLevel |
7958 				    kOSKextLogLoadFlag,
7959 				    "Failed to reset kext %s.",
7960 				    getIdentifierCString());
7961 				result = kOSKextReturnInternalError;
7962 				goto finish;
7963 			}
7964 		}
7965 		if (kc_type == KCKindUnknown) {
7966 			linkedExecutable.reset();
7967 		}
7968 	}
7969 
7970 	/* An interface kext has a fake kmod_info that was allocated,
7971 	 * so we have to free it.
7972 	 */
7973 	if (isInterface()) {
7974 		kfree_type(kmod_info_t, kmod_info);
7975 		kmod_info = NULL;
7976 	}
7977 
7978 	if (!in_fileset) {
7979 		kmod_info = NULL;
7980 	}
7981 
7982 	flags.loaded = false;
7983 	flushDependencies();
7984 
7985 	/* save a copy of the bundle ID for us to check when deciding to
7986 	 * rebuild the kernel cache file.  If a kext was already in the kernel
7987 	 * cache and unloaded then later loaded we do not need to rebuild the
7988 	 * kernel cache.  9055303
7989 	 */
7990 	if (isPrelinked()) {
7991 		if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) {
7992 			IORecursiveLockLock(sKextLock);
7993 			if (sUnloadedPrelinkedKexts) {
7994 				sUnloadedPrelinkedKexts->setObject(bundleID.get());
7995 			}
7996 			IORecursiveLockUnlock(sKextLock);
7997 		}
7998 	}
7999 
8000 	OSKextLog(this,
8001 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8002 	    "Kext %s unloaded.", getIdentifierCString());
8003 
8004 	queueKextNotification(kKextRequestPredicateUnloadNotification,
8005 	    OSDynamicCast(OSString, bundleID.get()));
8006 
8007 finish:
8008 	OSKext::saveLoadedKextPanicList();
8009 	OSKext::updateLoadedKextSummaries();
8010 
8011 	flags.unloading = 0;
8012 	return result;
8013 }
8014 
8015 /*********************************************************************
8016 * Assumes sKextLock is held.
8017 *********************************************************************/
8018 /* static */
8019 OSReturn
8020 OSKext::queueKextNotification(
8021 	const char * notificationName,
8022 	OSString   * kextIdentifier)
8023 {
8024 	OSReturn          result               = kOSReturnError;
8025 	OSSharedPtr<OSDictionary>    loadRequest;
8026 
8027 	if (!kextIdentifier) {
8028 		result = kOSKextReturnInvalidArgument;
8029 		goto finish;
8030 	}
8031 
8032 	/* Create a new request unless one is already sitting
8033 	 * in sKernelRequests for this bundle identifier
8034 	 */
8035 	result = _OSKextCreateRequest(notificationName, loadRequest);
8036 	if (result != kOSReturnSuccess) {
8037 		goto finish;
8038 	}
8039 	if (!_OSKextSetRequestArgument(loadRequest.get(),
8040 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
8041 		result = kOSKextReturnNoMemory;
8042 		goto finish;
8043 	}
8044 	if (!sKernelRequests->setObject(loadRequest.get())) {
8045 		result = kOSKextReturnNoMemory;
8046 		goto finish;
8047 	}
8048 
8049 	/* We might want to only queue the notification if the IOKit daemon is active,
8050 	 * but that wouldn't work for embedded. Note that we don't care if
8051 	 * the ping immediately succeeds here so don't do anything with the
8052 	 * result of this call.
8053 	 */
8054 	OSKext::pingIOKitDaemon();
8055 
8056 	result = kOSReturnSuccess;
8057 
8058 finish:
8059 	return result;
8060 }
8061 
8062 
8063 #if CONFIG_KXLD
8064 /*********************************************************************
8065 *********************************************************************/
8066 static void
8067 _OSKextConsiderDestroyingLinkContext(
8068 	__unused thread_call_param_t p0,
8069 	__unused thread_call_param_t p1)
8070 {
8071 	/* Take multiple locks in the correct order.
8072 	 */
8073 	IORecursiveLockLock(sKextLock);
8074 	IORecursiveLockLock(sKextInnerLock);
8075 
8076 	/* The first time we destroy the kxldContext is in the first
8077 	 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
8078 	 * before calling this function. Thereafter any call to this function
8079 	 * will actually destroy the context.
8080 	 */
8081 	if (sConsiderUnloadsCalled && sKxldContext) {
8082 		kxld_destroy_context(sKxldContext);
8083 		sKxldContext = NULL;
8084 	}
8085 
8086 	/* Free the thread_call that was allocated to execute this function.
8087 	 */
8088 	if (sDestroyLinkContextThread) {
8089 		if (!thread_call_free(sDestroyLinkContextThread)) {
8090 			OSKextLog(/* kext */ NULL,
8091 			    kOSKextLogErrorLevel |
8092 			    kOSKextLogGeneralFlag,
8093 			    "thread_call_free() failed for kext link context.");
8094 		}
8095 		sDestroyLinkContextThread = NULL;
8096 	}
8097 
8098 	IORecursiveLockUnlock(sKextInnerLock);
8099 	IORecursiveLockUnlock(sKextLock);
8100 
8101 	return;
8102 }
8103 
8104 /*********************************************************************
8105 * Destroying the kxldContext requires checking variables under both
8106 * sKextInnerLock and sKextLock, so we do it on a separate thread
8107 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
8108 * call relationship.
8109 *
8110 * This function must be invoked with sKextInnerLock held.
8111 * Do not call any function that takes sKextLock here!
8112 *********************************************************************/
8113 /* static */
8114 void
8115 OSKext::considerDestroyingLinkContext(void)
8116 {
8117 	IORecursiveLockLock(sKextInnerLock);
8118 
8119 	/* If we have already queued a thread to destroy the link context,
8120 	 * don't bother resetting; that thread will take care of it.
8121 	 */
8122 	if (sDestroyLinkContextThread) {
8123 		goto finish;
8124 	}
8125 
8126 	/* The function to be invoked in the thread will deallocate
8127 	 * this thread_call, so don't share it around.
8128 	 */
8129 	sDestroyLinkContextThread = thread_call_allocate(
8130 		&_OSKextConsiderDestroyingLinkContext, NULL);
8131 	if (!sDestroyLinkContextThread) {
8132 		OSKextLog(/* kext */ NULL,
8133 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
8134 		    "Can't create thread to destroy kext link context.");
8135 		goto finish;
8136 	}
8137 
8138 	thread_call_enter(sDestroyLinkContextThread);
8139 
8140 finish:
8141 	IORecursiveLockUnlock(sKextInnerLock);
8142 	return;
8143 }
8144 
8145 #else // !CONFIG_KXLD
8146 
8147 /* static */
8148 void
8149 OSKext::considerDestroyingLinkContext(void)
8150 {
8151 	return;
8152 }
8153 
8154 #endif // CONFIG_KXLD
8155 
8156 #if PRAGMA_MARK
8157 #pragma mark Autounload
8158 #endif
8159 /*********************************************************************
8160 * This is a static method because the kext will be deallocated if it
8161 * does unload!
8162 *********************************************************************/
8163 /* static */
8164 OSReturn
8165 OSKext::autounloadKext(OSKext * aKext)
8166 {
8167 	OSReturn result = kOSKextReturnInUse;
8168 
8169 #if NO_KEXTD
8170 	/*
8171 	 * Do not unload prelinked kexts on platforms that do not have an
8172 	 * IOKit daemon as there is no way to reload the kext or restart
8173 	 * matching.
8174 	 */
8175 	if (aKext->isPrelinked()) {
8176 		goto finish;
8177 	}
8178 #endif /* defined(__x86_64__) */
8179 
8180 	/* Check for external references to this kext (usu. dependents),
8181 	 * instances of defined classes (or classes derived from them),
8182 	 * outstanding requests.
8183 	 */
8184 	if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
8185 	    !aKext->flags.autounloadEnabled ||
8186 	    aKext->isKernelComponent()) {
8187 		goto finish;
8188 	}
8189 
8190 	/* Skip a delay-autounload kext, once.
8191 	 */
8192 	if (aKext->flags.delayAutounload) {
8193 		OSKextLog(aKext,
8194 		    kOSKextLogProgressLevel |
8195 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8196 		    "Kext %s has delayed autounload set; skipping and clearing flag.",
8197 		    aKext->getIdentifierCString());
8198 		aKext->flags.delayAutounload = 0;
8199 		goto finish;
8200 	}
8201 
8202 	if (aKext->hasOSMetaClassInstances() ||
8203 	    aKext->countRequestCallbacks()) {
8204 		goto finish;
8205 	}
8206 
8207 	result = OSKext::removeKext(aKext);
8208 
8209 finish:
8210 	return result;
8211 }
8212 
8213 /*********************************************************************
8214 *********************************************************************/
8215 void
8216 _OSKextConsiderUnloads(
8217 	__unused thread_call_param_t p0,
8218 	__unused thread_call_param_t p1)
8219 {
8220 	bool         didUnload = false;
8221 	unsigned int count, i;
8222 
8223 	/* Take multiple locks in the correct order
8224 	 * (note also sKextSummaries lock further down).
8225 	 */
8226 	IORecursiveLockLock(sKextLock);
8227 	IORecursiveLockLock(sKextInnerLock);
8228 
8229 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
8230 
8231 	/* If the system is powering down, don't try to unload anything.
8232 	 */
8233 	if (sSystemSleep) {
8234 		goto finish;
8235 	}
8236 
8237 	OSKextLog(/* kext */ NULL,
8238 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8239 	    "Checking for unused kexts to autounload.");
8240 
8241 	/*****
8242 	 * Remove any request callbacks marked as stale,
8243 	 * and mark as stale any currently in flight.
8244 	 */
8245 	count = sRequestCallbackRecords->getCount();
8246 	if (count) {
8247 		i = count - 1;
8248 		do {
8249 			OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
8250 			    sRequestCallbackRecords->getObject(i));
8251 			if (callbackRecord) {
8252 				OSBoolean * stale = OSDynamicCast(OSBoolean,
8253 				    callbackRecord->getObject(kKextRequestStaleKey));
8254 
8255 				if (stale == kOSBooleanTrue) {
8256 					OSKext::invokeRequestCallback(callbackRecord,
8257 					    kOSKextReturnTimeout);
8258 				} else {
8259 					callbackRecord->setObject(kKextRequestStaleKey,
8260 					    kOSBooleanTrue);
8261 				}
8262 			}
8263 		} while (i--);
8264 	}
8265 
8266 	/*****
8267 	 * Make multiple passes through the array of loaded kexts until
8268 	 * we don't unload any. This handles unwinding of dependency
8269 	 * chains. We have to go *backwards* through the array because
8270 	 * kexts are removed from it when unloaded, and we cannot make
8271 	 * a copy or we'll mess up the retain counts we rely on to
8272 	 * check whether a kext will unload. If only we could have
8273 	 * nonretaining collections like CF has....
8274 	 */
8275 	do {
8276 		didUnload = false;
8277 
8278 		count = sLoadedKexts->getCount();
8279 		if (count) {
8280 			i = count - 1;
8281 			do {
8282 				OSKext * thisKext = OSDynamicCast(OSKext,
8283 				    sLoadedKexts->getObject(i));
8284 				didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
8285 			} while (i--);
8286 		}
8287 	} while (didUnload);
8288 
8289 finish:
8290 	sConsiderUnloadsPending = false;
8291 	sConsiderUnloadsExecuted = true;
8292 
8293 	(void) OSKext::considerRebuildOfPrelinkedKernel();
8294 
8295 	IORecursiveLockUnlock(sKextInnerLock);
8296 	IORecursiveLockUnlock(sKextLock);
8297 
8298 	return;
8299 }
8300 
8301 /*********************************************************************
8302 * Do not call any function that takes sKextLock here!
8303 *********************************************************************/
8304 void
8305 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
8306 {
8307 	AbsoluteTime when;
8308 
8309 	IORecursiveLockLock(sKextInnerLock);
8310 
8311 	if (!sUnloadCallout) {
8312 		sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
8313 	}
8314 
8315 	/* we only reset delay value for unloading if we already have something
8316 	 * pending.  rescheduleOnlyFlag should not start the count down.
8317 	 */
8318 	if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
8319 		goto finish;
8320 	}
8321 
8322 	thread_call_cancel(sUnloadCallout);
8323 	if (OSKext::getAutounloadEnabled() && !sSystemSleep
8324 #if !NO_KEXTD
8325 	    && sIOKitDaemonActive
8326 #endif
8327 	    ) {
8328 		clock_interval_to_deadline(sConsiderUnloadDelay,
8329 		    1000 * 1000 * 1000, &when);
8330 
8331 		OSKextLog(/* kext */ NULL,
8332 		    kOSKextLogProgressLevel |
8333 		    kOSKextLogLoadFlag,
8334 		    "%scheduling %sscan for unused kexts in %lu seconds.",
8335 		    sConsiderUnloadsPending ? "Res" : "S",
8336 		    sConsiderUnloadsCalled ? "" : "initial ",
8337 		    (unsigned long)sConsiderUnloadDelay);
8338 
8339 		sConsiderUnloadsPending = true;
8340 		thread_call_enter_delayed(sUnloadCallout, when);
8341 	}
8342 
8343 finish:
8344 	/* The kxld context should be reused throughout boot.  We mark the end of
8345 	 * period as the first time considerUnloads() is called, and we destroy
8346 	 * the first kxld context in that function.  Afterwards, it will be
8347 	 * destroyed in flushNonloadedKexts.
8348 	 */
8349 	if (!sConsiderUnloadsCalled) {
8350 		sConsiderUnloadsCalled = true;
8351 		OSKext::considerDestroyingLinkContext();
8352 	}
8353 
8354 	IORecursiveLockUnlock(sKextInnerLock);
8355 	return;
8356 }
8357 
8358 /*********************************************************************
8359 * Do not call any function that takes sKextLock here!
8360 *********************************************************************/
8361 extern "C" {
8362 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
8363 IOReturn
8364 OSKextSystemSleepOrWake(UInt32 messageType)
8365 {
8366 	IORecursiveLockLock(sKextInnerLock);
8367 
8368 	/* If the system is going to sleep, cancel the reaper thread timer,
8369 	 * and note that we're in a sleep state in case it just fired but hasn't
8370 	 * taken the lock yet. If we are coming back from sleep, just
8371 	 * clear the sleep flag; IOService's normal operation will cause
8372 	 * unloads to be considered soon enough.
8373 	 */
8374 	if (messageType == kIOMessageSystemWillSleep) {
8375 		if (sUnloadCallout) {
8376 			thread_call_cancel(sUnloadCallout);
8377 		}
8378 		sSystemSleep = true;
8379 		AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
8380 	} else if (messageType == kIOMessageSystemHasPoweredOn) {
8381 		sSystemSleep = false;
8382 		clock_get_uptime(&sLastWakeTime);
8383 	}
8384 	IORecursiveLockUnlock(sKextInnerLock);
8385 
8386 	return kIOReturnSuccess;
8387 }
8388 };
8389 
8390 
8391 #if PRAGMA_MARK
8392 #pragma mark Prelinked Kernel
8393 #endif
8394 
8395 #ifdef CONFIG_KXLD
8396 /*********************************************************************
8397 * Do not access sConsiderUnloads... variables other than
8398 * sConsiderUnloadsExecuted in this function. They are guarded by a
8399 * different lock.
8400 *********************************************************************/
8401 /* static */
8402 void
8403 OSKext::considerRebuildOfPrelinkedKernel(void)
8404 {
8405 	static bool     requestedPrelink        = false;
8406 	OSReturn        checkResult             = kOSReturnError;
8407 	OSSharedPtr<OSDictionary>         prelinkRequest;
8408 	OSSharedPtr<OSCollectionIterator> kextIterator;
8409 	const OSSymbol * thisID                 = NULL;        // do not release
8410 	bool            doRebuild               = false;
8411 	AbsoluteTime    my_abstime;
8412 	UInt64          my_ns;
8413 	SInt32          delta_secs;
8414 
8415 	/* Only one auto rebuild per boot and only on boot from prelinked kernel */
8416 	if (requestedPrelink || !sPrelinkBoot) {
8417 		return;
8418 	}
8419 
8420 	/* no direct return from this point */
8421 	IORecursiveLockLock(sKextLock);
8422 
8423 	/* We need to wait for the IOKit daemon to get up and running with unloads already done
8424 	 * and any new startup kexts loaded.
8425 	 */
8426 	if (!sConsiderUnloadsExecuted ||
8427 	    !sDeferredLoadSucceeded) {
8428 		goto finish;
8429 	}
8430 
8431 	/* we really only care about boot / system start up related kexts so bail
8432 	 * if we're here after REBUILD_MAX_TIME.
8433 	 */
8434 	if (!_OSKextInPrelinkRebuildWindow()) {
8435 		OSKextLog(/* kext */ NULL,
8436 		    kOSKextLogArchiveFlag,
8437 		    "%s prebuild rebuild has expired",
8438 		    __FUNCTION__);
8439 		requestedPrelink = true;
8440 		goto finish;
8441 	}
8442 
8443 	/* we do not want to trigger a rebuild if we get here too close to waking
8444 	 * up.  (see radar 10233768)
8445 	 */
8446 	IORecursiveLockLock(sKextInnerLock);
8447 
8448 	clock_get_uptime(&my_abstime);
8449 	delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
8450 	if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
8451 		SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
8452 		absolutetime_to_nanoseconds(my_abstime, &my_ns);
8453 		delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
8454 	}
8455 	IORecursiveLockUnlock(sKextInnerLock);
8456 
8457 	if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
8458 		/* too close to time of last wake from sleep */
8459 		goto finish;
8460 	}
8461 	requestedPrelink = true;
8462 
8463 	/* Now it's time to see if we have a reason to rebuild.  We may have done
8464 	 * some loads and unloads but the kernel cache didn't actually change.
8465 	 * We will rebuild if any kext is not marked prelinked AND is not in our
8466 	 * list of prelinked kexts that got unloaded.  (see radar 9055303)
8467 	 */
8468 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
8469 	if (!kextIterator) {
8470 		goto finish;
8471 	}
8472 
8473 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
8474 		OSKext *    thisKext;        // do not release
8475 
8476 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
8477 		if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
8478 			continue;
8479 		}
8480 
8481 		if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) {
8482 			continue;
8483 		}
8484 		/* kext is loaded and was not in current kernel cache so let's rebuild
8485 		 */
8486 		doRebuild = true;
8487 		OSKextLog(/* kext */ NULL,
8488 		    kOSKextLogArchiveFlag,
8489 		    "considerRebuildOfPrelinkedKernel %s triggered rebuild",
8490 		    thisKext->bundleID->getCStringNoCopy());
8491 		break;
8492 	}
8493 	sUnloadedPrelinkedKexts->flushCollection();
8494 
8495 	if (!doRebuild) {
8496 		goto finish;
8497 	}
8498 
8499 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
8500 	    prelinkRequest);
8501 	if (checkResult != kOSReturnSuccess) {
8502 		goto finish;
8503 	}
8504 
8505 	if (!sKernelRequests->setObject(prelinkRequest.get())) {
8506 		goto finish;
8507 	}
8508 
8509 	OSKext::pingIOKitDaemon();
8510 
8511 finish:
8512 	IORecursiveLockUnlock(sKextLock);
8513 
8514 	return;
8515 }
8516 
8517 #else /* !CONFIG_KXLD */
8518 
8519 void
8520 OSKext::considerRebuildOfPrelinkedKernel(void)
8521 {
8522 	/* in a non-dynamic kext loading world, there is never a reason to rebuild */
8523 	return;
8524 }
8525 
8526 #endif /* CONFIG_KXLD */
8527 
8528 #if PRAGMA_MARK
8529 #pragma mark Dependencies
8530 #endif
8531 /*********************************************************************
8532 *********************************************************************/
8533 bool
8534 OSKext::resolveDependencies(
8535 	OSArray * loopStack)
8536 {
8537 	bool                   result                   = false;
8538 	OSSharedPtr<OSArray>   localLoopStack;
8539 	bool                   addedToLoopStack         = false;
8540 	OSDictionary         * libraries                = NULL;        // do not release
8541 	OSSharedPtr<OSCollectionIterator> libraryIterator;
8542 	OSString             * libraryID                = NULL;        // do not release
8543 	OSKext               * libraryKext              = NULL;        // do not release
8544 	bool                   hasRawKernelDependency   = false;
8545 	bool                   hasKernelDependency      = false;
8546 	bool                   hasKPIDependency         = false;
8547 	bool                   hasPrivateKPIDependency  = false;
8548 	unsigned int           count;
8549 
8550 #if CONFIG_KXLD
8551 	OSString             * infoString               = NULL;        // do not release
8552 	OSString             * readableString           = NULL;        // do not release
8553 #endif // CONFIG_KXLD
8554 
8555 	/* A kernel component will automatically have this flag set,
8556 	 * and a loaded kext should also have it set (as should all its
8557 	 * loaded dependencies).
8558 	 */
8559 	if (flags.hasAllDependencies) {
8560 		result = true;
8561 		goto finish;
8562 	}
8563 
8564 	/* Check for loops in the dependency graph.
8565 	 */
8566 	if (loopStack) {
8567 		if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
8568 			OSKextLog(this,
8569 			    kOSKextLogErrorLevel |
8570 			    kOSKextLogDependenciesFlag,
8571 			    "Kext %s has a dependency loop; can't resolve dependencies.",
8572 			    getIdentifierCString());
8573 			goto finish;
8574 		}
8575 	} else {
8576 		OSKextLog(this,
8577 		    kOSKextLogStepLevel |
8578 		    kOSKextLogDependenciesFlag,
8579 		    "Kext %s resolving dependencies.",
8580 		    getIdentifierCString());
8581 
8582 		localLoopStack = OSArray::withCapacity(6);         // any small capacity will do
8583 		if (!localLoopStack) {
8584 			OSKextLog(this,
8585 			    kOSKextLogErrorLevel |
8586 			    kOSKextLogDependenciesFlag,
8587 			    "Kext %s can't create bookkeeping stack to resolve dependencies.",
8588 			    getIdentifierCString());
8589 			goto finish;
8590 		}
8591 		loopStack = localLoopStack.get();
8592 	}
8593 	if (!loopStack->setObject(this)) {
8594 		OSKextLog(this,
8595 		    kOSKextLogErrorLevel |
8596 		    kOSKextLogDependenciesFlag,
8597 		    "Kext %s - internal error resolving dependencies.",
8598 		    getIdentifierCString());
8599 		goto finish;
8600 	}
8601 	addedToLoopStack = true;
8602 
8603 	/* Purge any existing kexts in the dependency list and start over.
8604 	 */
8605 	flushDependencies();
8606 	if (dependencies) {
8607 		OSKextLog(this,
8608 		    kOSKextLogErrorLevel |
8609 		    kOSKextLogDependenciesFlag,
8610 		    "Kext %s - internal error resolving dependencies.",
8611 		    getIdentifierCString());
8612 	}
8613 
8614 	libraries = OSDynamicCast(OSDictionary,
8615 	    getPropertyForHostArch(kOSBundleLibrariesKey));
8616 	if (libraries == NULL || libraries->getCount() == 0) {
8617 		OSKextLog(this,
8618 		    kOSKextLogErrorLevel |
8619 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8620 		    "Kext %s - can't resolve dependencies; %s missing/invalid type.",
8621 		    getIdentifierCString(), kOSBundleLibrariesKey);
8622 		goto finish;
8623 	}
8624 
8625 	/* Make a new array to hold the dependencies (flush freed the old one).
8626 	 */
8627 	dependencies = OSArray::withCapacity(libraries->getCount());
8628 	if (!dependencies) {
8629 		OSKextLog(this,
8630 		    kOSKextLogErrorLevel |
8631 		    kOSKextLogDependenciesFlag,
8632 		    "Kext %s - can't allocate dependencies array.",
8633 		    getIdentifierCString());
8634 		goto finish;
8635 	}
8636 
8637 	// xxx - compat: We used to add an implicit dependency on kernel 6.0
8638 	// xxx - compat: if none were declared.
8639 
8640 	libraryIterator = OSCollectionIterator::withCollection(libraries);
8641 	if (!libraryIterator) {
8642 		OSKextLog(this,
8643 		    kOSKextLogErrorLevel |
8644 		    kOSKextLogDependenciesFlag,
8645 		    "Kext %s - can't allocate dependencies iterator.",
8646 		    getIdentifierCString());
8647 		goto finish;
8648 	}
8649 
8650 	while ((libraryID = OSDynamicCast(OSString,
8651 	    libraryIterator->getNextObject()))) {
8652 		const char * library_id = libraryID->getCStringNoCopy();
8653 
8654 		OSString * libraryVersion = OSDynamicCast(OSString,
8655 		    libraries->getObject(libraryID));
8656 		if (libraryVersion == NULL) {
8657 			OSKextLog(this,
8658 			    kOSKextLogErrorLevel |
8659 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8660 			    "Kext %s - illegal type in OSBundleLibraries.",
8661 			    getIdentifierCString());
8662 			goto finish;
8663 		}
8664 
8665 		OSKextVersion libraryVers =
8666 		    OSKextParseVersionString(libraryVersion->getCStringNoCopy());
8667 		if (libraryVers == -1) {
8668 			OSKextLog(this,
8669 			    kOSKextLogErrorLevel |
8670 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8671 			    "Kext %s - invalid library version %s.",
8672 			    getIdentifierCString(),
8673 			    libraryVersion->getCStringNoCopy());
8674 			goto finish;
8675 		}
8676 
8677 		libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
8678 		if (libraryKext == NULL) {
8679 			OSKextLog(this,
8680 			    kOSKextLogErrorLevel |
8681 			    kOSKextLogDependenciesFlag,
8682 			    "Kext %s - library kext %s not found.",
8683 			    getIdentifierCString(), library_id);
8684 			goto finish;
8685 		}
8686 
8687 		if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
8688 			OSKextLog(this,
8689 			    kOSKextLogErrorLevel |
8690 			    kOSKextLogDependenciesFlag,
8691 			    "Kext %s - library kext %s not compatible "
8692 			    "with requested version %s.",
8693 			    getIdentifierCString(), library_id,
8694 			    libraryVersion->getCStringNoCopy());
8695 			goto finish;
8696 		}
8697 
8698 		/* If a nonprelinked library somehow got into the mix for a
8699 		 * prelinked kext, at any point in the chain, we must fail
8700 		 * because the prelinked relocs for the library will be all wrong.
8701 		 */
8702 		if (this->isPrelinked() &&
8703 		    libraryKext->declaresExecutable() &&
8704 		    !libraryKext->isPrelinked()) {
8705 			OSKextLog(this,
8706 			    kOSKextLogErrorLevel |
8707 			    kOSKextLogDependenciesFlag,
8708 			    "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
8709 			    getIdentifierCString(), library_id,
8710 			    libraryVersion->getCStringNoCopy());
8711 			goto finish;
8712 		}
8713 
8714 		if (!libraryKext->resolveDependencies(loopStack)) {
8715 			goto finish;
8716 		}
8717 
8718 		/* Add the library directly only if it has an executable to link.
8719 		 * Otherwise it's just used to collect other dependencies, so put
8720 		 * *its* dependencies on the list for this kext.
8721 		 */
8722 		// xxx - We are losing info here; would like to make fake entries or
8723 		// xxx - keep these in the dependency graph for loaded kexts.
8724 		// xxx - I really want to make kernel components not a special case!
8725 		if (libraryKext->declaresExecutable() ||
8726 		    libraryKext->isInterface()) {
8727 			if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
8728 				dependencies->setObject(libraryKext);
8729 
8730 				OSKextLog(this,
8731 				    kOSKextLogDetailLevel |
8732 				    kOSKextLogDependenciesFlag,
8733 				    "Kext %s added dependency %s.",
8734 				    getIdentifierCString(),
8735 				    libraryKext->getIdentifierCString());
8736 			}
8737 		} else {
8738 			int       numLibDependencies  = libraryKext->getNumDependencies();
8739 			OSArray * libraryDependencies = libraryKext->getDependencies();
8740 			int       index;
8741 
8742 			if (numLibDependencies) {
8743 				// xxx - this msg level should be 1 lower than the per-kext one
8744 				OSKextLog(this,
8745 				    kOSKextLogDetailLevel |
8746 				    kOSKextLogDependenciesFlag,
8747 				    "Kext %s pulling %d dependencies from codeless library %s.",
8748 				    getIdentifierCString(),
8749 				    numLibDependencies,
8750 				    libraryKext->getIdentifierCString());
8751 			}
8752 			for (index = 0; index < numLibDependencies; index++) {
8753 				OSKext * thisLibDependency = OSDynamicCast(OSKext,
8754 				    libraryDependencies->getObject(index));
8755 				if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
8756 					dependencies->setObject(thisLibDependency);
8757 					OSKextLog(this,
8758 					    kOSKextLogDetailLevel |
8759 					    kOSKextLogDependenciesFlag,
8760 					    "Kext %s added dependency %s from codeless library %s.",
8761 					    getIdentifierCString(),
8762 					    thisLibDependency->getIdentifierCString(),
8763 					    libraryKext->getIdentifierCString());
8764 				}
8765 			}
8766 		}
8767 
8768 		if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
8769 		    0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
8770 			hasRawKernelDependency = true;
8771 		} else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
8772 			hasKernelDependency = true;
8773 		} else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
8774 			hasKPIDependency = true;
8775 			if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
8776 				hasPrivateKPIDependency = true;
8777 			}
8778 		}
8779 	}
8780 
8781 	if (hasRawKernelDependency) {
8782 		OSKextLog(this,
8783 		    kOSKextLogErrorLevel |
8784 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8785 		    "Error - kext %s declares a dependency on %s, which is not permitted.",
8786 		    getIdentifierCString(), KERNEL_LIB);
8787 		goto finish;
8788 	}
8789 #if __LP64__
8790 	if (hasKernelDependency) {
8791 		OSKextLog(this,
8792 		    kOSKextLogErrorLevel |
8793 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8794 		    "Error - kext %s declares %s dependencies. "
8795 		    "Only %s* dependencies are supported for 64-bit kexts.",
8796 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
8797 		goto finish;
8798 	}
8799 	if (!hasKPIDependency) {
8800 		OSKextLog(this,
8801 		    kOSKextLogWarningLevel |
8802 		    kOSKextLogDependenciesFlag,
8803 		    "Warning - kext %s declares no %s* dependencies. "
8804 		    "If it uses any KPIs, the link may fail with undefined symbols.",
8805 		    getIdentifierCString(), KPI_LIB_PREFIX);
8806 	}
8807 #else /* __LP64__ */
8808 	// xxx - will change to flatly disallow "kernel" dependencies at some point
8809 	// xxx - is it invalid to do both "com.apple.kernel" and any
8810 	// xxx - "com.apple.kernel.*"?
8811 
8812 	if (hasKernelDependency && hasKPIDependency) {
8813 		OSKextLog(this,
8814 		    kOSKextLogWarningLevel |
8815 		    kOSKextLogDependenciesFlag,
8816 		    "Warning - kext %s has immediate dependencies on both "
8817 		    "%s* and %s* components; use only one style.",
8818 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
8819 	}
8820 
8821 	if (!hasKernelDependency && !hasKPIDependency) {
8822 		// xxx - do we want to use validation flag for these too?
8823 		OSKextLog(this,
8824 		    kOSKextLogWarningLevel |
8825 		    kOSKextLogDependenciesFlag,
8826 		    "Warning - %s declares no kernel dependencies; using %s.",
8827 		    getIdentifierCString(), KERNEL6_LIB);
8828 		OSKext * kernelKext = OSDynamicCast(OSKext,
8829 		    sKextsByID->getObject(KERNEL6_LIB));
8830 		if (kernelKext) {
8831 			dependencies->setObject(kernelKext);
8832 		} else {
8833 			OSKextLog(this,
8834 			    kOSKextLogErrorLevel |
8835 			    kOSKextLogDependenciesFlag,
8836 			    "Error - Library %s not found for %s.",
8837 			    KERNEL6_LIB, getIdentifierCString());
8838 		}
8839 	}
8840 
8841 	/* If the kext doesn't have a raw kernel or KPI dependency, then add all of
8842 	 * its indirect dependencies to simulate old-style linking.  XXX - Should
8843 	 * check for duplicates.
8844 	 */
8845 	if (!hasKPIDependency) {
8846 		unsigned int i;
8847 
8848 		flags.hasBleedthrough = true;
8849 
8850 		count = getNumDependencies();
8851 
8852 		/* We add to the dependencies array in this loop, but do not iterate
8853 		 * past its original count.
8854 		 */
8855 		for (i = 0; i < count; i++) {
8856 			OSKext * dependencyKext = OSDynamicCast(OSKext,
8857 			    dependencies->getObject(i));
8858 			dependencyKext->addBleedthroughDependencies(dependencies.get());
8859 		}
8860 	}
8861 #endif /* __LP64__ */
8862 
8863 #if CONFIG_KXLD
8864 	/*
8865 	 * If we're not dynamically linking kexts, then we don't need to check
8866 	 * copyright strings. The linker in user space has already done this.
8867 	 */
8868 	if (hasPrivateKPIDependency) {
8869 		bool hasApplePrefix = false;
8870 		bool infoCopyrightIsValid = false;
8871 		bool readableCopyrightIsValid = false;
8872 
8873 		hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
8874 		    APPLE_KEXT_PREFIX);
8875 
8876 		infoString = OSDynamicCast(OSString,
8877 		    getPropertyForHostArch("CFBundleGetInfoString"));
8878 		if (infoString) {
8879 			infoCopyrightIsValid =
8880 			    kxld_validate_copyright_string(infoString->getCStringNoCopy());
8881 		}
8882 
8883 		readableString = OSDynamicCast(OSString,
8884 		    getPropertyForHostArch("NSHumanReadableCopyright"));
8885 		if (readableString) {
8886 			readableCopyrightIsValid =
8887 			    kxld_validate_copyright_string(readableString->getCStringNoCopy());
8888 		}
8889 
8890 		if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
8891 			OSKextLog(this,
8892 			    kOSKextLogErrorLevel |
8893 			    kOSKextLogDependenciesFlag,
8894 			    "Error - kext %s declares a dependency on %s. "
8895 			    "Only Apple kexts may declare a dependency on %s.",
8896 			    getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
8897 			goto finish;
8898 		}
8899 	}
8900 #endif // CONFIG_KXLD
8901 
8902 	result = true;
8903 	flags.hasAllDependencies = 1;
8904 
8905 finish:
8906 
8907 	if (addedToLoopStack) {
8908 		count = loopStack->getCount();
8909 		if (count > 0 && (this == loopStack->getObject(count - 1))) {
8910 			loopStack->removeObject(count - 1);
8911 		} else {
8912 			OSKextLog(this,
8913 			    kOSKextLogErrorLevel |
8914 			    kOSKextLogDependenciesFlag,
8915 			    "Kext %s - internal error resolving dependencies.",
8916 			    getIdentifierCString());
8917 		}
8918 	}
8919 
8920 	if (result && localLoopStack) {
8921 		OSKextLog(this,
8922 		    kOSKextLogStepLevel |
8923 		    kOSKextLogDependenciesFlag,
8924 		    "Kext %s successfully resolved dependencies.",
8925 		    getIdentifierCString());
8926 	}
8927 
8928 	return result;
8929 }
8930 
8931 /*********************************************************************
8932 *********************************************************************/
8933 bool
8934 OSKext::addBleedthroughDependencies(OSArray * anArray)
8935 {
8936 	bool result = false;
8937 	unsigned int dependencyIndex, dependencyCount;
8938 
8939 	dependencyCount = getNumDependencies();
8940 
8941 	for (dependencyIndex = 0;
8942 	    dependencyIndex < dependencyCount;
8943 	    dependencyIndex++) {
8944 		OSKext * dependency = OSDynamicCast(OSKext,
8945 		    dependencies->getObject(dependencyIndex));
8946 		if (!dependency) {
8947 			OSKextLog(this,
8948 			    kOSKextLogErrorLevel |
8949 			    kOSKextLogDependenciesFlag,
8950 			    "Kext %s - internal error propagating compatibility dependencies.",
8951 			    getIdentifierCString());
8952 			goto finish;
8953 		}
8954 		if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
8955 			anArray->setObject(dependency);
8956 		}
8957 		dependency->addBleedthroughDependencies(anArray);
8958 	}
8959 
8960 	result = true;
8961 
8962 finish:
8963 	return result;
8964 }
8965 
8966 /*********************************************************************
8967 *********************************************************************/
8968 bool
8969 OSKext::flushDependencies(bool forceFlag)
8970 {
8971 	bool result = false;
8972 
8973 	/* Only clear the dependencies if the kext isn't loaded;
8974 	 * we need the info for loaded kexts to track references.
8975 	 */
8976 	if (!isLoaded() || forceFlag) {
8977 		if (dependencies) {
8978 			// xxx - check level
8979 			OSKextLog(this,
8980 			    kOSKextLogProgressLevel |
8981 			    kOSKextLogDependenciesFlag,
8982 			    "Kext %s flushing dependencies.",
8983 			    getIdentifierCString());
8984 			dependencies.reset();
8985 		}
8986 		if (!isKernelComponent()) {
8987 			flags.hasAllDependencies = 0;
8988 		}
8989 		result = true;
8990 	}
8991 
8992 	return result;
8993 }
8994 
8995 /*********************************************************************
8996 *********************************************************************/
8997 uint32_t
8998 OSKext::getNumDependencies(void)
8999 {
9000 	if (!dependencies) {
9001 		return 0;
9002 	}
9003 	return dependencies->getCount();
9004 }
9005 
9006 /*********************************************************************
9007 *********************************************************************/
9008 OSArray *
9009 OSKext::getDependencies(void)
9010 {
9011 	return dependencies.get();
9012 }
9013 
9014 bool
9015 OSKext::hasDependency(const OSSymbol * depID)
9016 {
9017 	bool result __block;
9018 
9019 	if (depID == getIdentifier()) {
9020 		return true;
9021 	}
9022 	if (!dependencies) {
9023 		return false;
9024 	}
9025 	result = false;
9026 	dependencies->iterateObjects(^bool (OSObject * obj) {
9027 		OSKext * kext;
9028 		kext = OSDynamicCast(OSKext, obj);
9029 		if (!kext) {
9030 		        return false;
9031 		}
9032 		result = (depID == kext->getIdentifier());
9033 		return result;
9034 	});
9035 	return result;
9036 }
9037 
9038 #if PRAGMA_MARK
9039 #pragma mark OSMetaClass Support
9040 #endif
9041 /*********************************************************************
9042 *********************************************************************/
9043 OSReturn
9044 OSKext::addClass(
9045 	OSMetaClass * aClass,
9046 	uint32_t      numClasses)
9047 {
9048 	OSReturn result = kOSMetaClassNoInsKModSet;
9049 
9050 	if (!metaClasses) {
9051 		metaClasses = OSSet::withCapacity(numClasses);
9052 		if (!metaClasses) {
9053 			goto finish;
9054 		}
9055 	}
9056 
9057 	if (metaClasses->containsObject(aClass)) {
9058 		OSKextLog(this,
9059 		    kOSKextLogWarningLevel |
9060 		    kOSKextLogLoadFlag,
9061 		    "Notice - kext %s has already registered class %s.",
9062 		    getIdentifierCString(),
9063 		    aClass->getClassName());
9064 		result = kOSReturnSuccess;
9065 		goto finish;
9066 	}
9067 
9068 	if (!metaClasses->setObject(aClass)) {
9069 		goto finish;
9070 	} else {
9071 		OSKextLog(this,
9072 		    kOSKextLogDetailLevel |
9073 		    kOSKextLogLoadFlag,
9074 		    "Kext %s registered class %s.",
9075 		    getIdentifierCString(),
9076 		    aClass->getClassName());
9077 	}
9078 
9079 	if (!flags.autounloadEnabled) {
9080 		const OSMetaClass * metaScan  = NULL;        // do not release
9081 
9082 		for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
9083 			if (metaScan == OSTypeID(IOService)) {
9084 				OSKextLog(this,
9085 				    kOSKextLogProgressLevel |
9086 				    kOSKextLogLoadFlag,
9087 				    "Kext %s has IOService subclass %s; enabling autounload.",
9088 				    getIdentifierCString(),
9089 				    aClass->getClassName());
9090 
9091 				flags.autounloadEnabled = (0 == flags.unloadUnsupported);
9092 				break;
9093 			}
9094 		}
9095 	}
9096 
9097 	notifyAddClassObservers(this, aClass, flags);
9098 
9099 	result = kOSReturnSuccess;
9100 
9101 finish:
9102 	if (result != kOSReturnSuccess) {
9103 		OSKextLog(this,
9104 		    kOSKextLogErrorLevel |
9105 		    kOSKextLogLoadFlag,
9106 		    "Kext %s failed to register class %s.",
9107 		    getIdentifierCString(),
9108 		    aClass->getClassName());
9109 	}
9110 
9111 	return result;
9112 }
9113 
9114 /*********************************************************************
9115 *********************************************************************/
9116 OSReturn
9117 OSKext::removeClass(
9118 	OSMetaClass * aClass)
9119 {
9120 	OSReturn result = kOSMetaClassNoKModSet;
9121 
9122 	if (!metaClasses) {
9123 		goto finish;
9124 	}
9125 
9126 	if (!metaClasses->containsObject(aClass)) {
9127 		OSKextLog(this,
9128 		    kOSKextLogWarningLevel |
9129 		    kOSKextLogLoadFlag,
9130 		    "Notice - kext %s asked to unregister unknown class %s.",
9131 		    getIdentifierCString(),
9132 		    aClass->getClassName());
9133 		result = kOSReturnSuccess;
9134 		goto finish;
9135 	}
9136 
9137 	OSKextLog(this,
9138 	    kOSKextLogDetailLevel |
9139 	    kOSKextLogLoadFlag,
9140 	    "Kext %s unregistering class %s.",
9141 	    getIdentifierCString(),
9142 	    aClass->getClassName());
9143 
9144 	metaClasses->removeObject(aClass);
9145 
9146 	notifyRemoveClassObservers(this, aClass, flags);
9147 
9148 	result = kOSReturnSuccess;
9149 
9150 finish:
9151 	if (result != kOSReturnSuccess) {
9152 		OSKextLog(this,
9153 		    kOSKextLogErrorLevel |
9154 		    kOSKextLogLoadFlag,
9155 		    "Failed to unregister kext %s class %s.",
9156 		    getIdentifierCString(),
9157 		    aClass->getClassName());
9158 	}
9159 	return result;
9160 }
9161 
9162 /*********************************************************************
9163 *********************************************************************/
9164 OSSet *
9165 OSKext::getMetaClasses(void)
9166 {
9167 	return metaClasses.get();
9168 }
9169 
9170 /*********************************************************************
9171 *********************************************************************/
9172 bool
9173 OSKext::hasOSMetaClassInstances(void)
9174 {
9175 	bool                   result        = false;
9176 	OSSharedPtr<OSCollectionIterator> classIterator;
9177 	OSMetaClass          * checkClass    = NULL;        // do not release
9178 
9179 	if (!metaClasses) {
9180 		goto finish;
9181 	}
9182 
9183 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9184 	if (!classIterator) {
9185 		// xxx - log alloc failure?
9186 		goto finish;
9187 	}
9188 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9189 		if (checkClass->getInstanceCount()) {
9190 			result = true;
9191 			goto finish;
9192 		}
9193 	}
9194 
9195 finish:
9196 	return result;
9197 }
9198 
9199 /*********************************************************************
9200 *********************************************************************/
9201 /* static */
9202 void
9203 OSKext::reportOSMetaClassInstances(
9204 	const char     * kextIdentifier,
9205 	OSKextLogSpec    msgLogSpec)
9206 {
9207 	OSSharedPtr<OSKext> theKext;
9208 
9209 	theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
9210 	if (!theKext) {
9211 		goto finish;
9212 	}
9213 
9214 	theKext->reportOSMetaClassInstances(msgLogSpec);
9215 finish:
9216 	return;
9217 }
9218 
9219 /*********************************************************************
9220 *********************************************************************/
9221 void
9222 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
9223 {
9224 	OSSharedPtr<OSCollectionIterator> classIterator;
9225 	OSMetaClass          * checkClass    = NULL;        // do not release
9226 
9227 	if (!metaClasses) {
9228 		goto finish;
9229 	}
9230 
9231 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9232 	if (!classIterator) {
9233 		goto finish;
9234 	}
9235 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9236 		if (checkClass->getInstanceCount()) {
9237 			OSKextLog(this,
9238 			    msgLogSpec,
9239 			    "    Kext %s class %s has %d instance%s.",
9240 			    getIdentifierCString(),
9241 			    checkClass->getClassName(),
9242 			    checkClass->getInstanceCount(),
9243 			    checkClass->getInstanceCount() == 1 ? "" : "s");
9244 		}
9245 	}
9246 
9247 finish:
9248 	return;
9249 }
9250 
9251 #if PRAGMA_MARK
9252 #pragma mark User-Space Requests
9253 #endif
9254 
9255 static kern_return_t
9256 patchDextLaunchRequests(task_t calling_task, OSArray *requests)
9257 {
9258 	OSReturn result = kOSReturnSuccess;
9259 	for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) {
9260 		OSDictionary * request = NULL;         //do not release
9261 		IOUserServerCheckInToken * token = NULL;         //do not release
9262 		OSString * requestPredicate = NULL;         //do not release
9263 		OSSharedPtr<OSNumber> portNameNumber;
9264 		mach_port_name_t portName = 0;
9265 		request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex));
9266 		if (!request) {
9267 			OSKextLog(/* kext */ NULL,
9268 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9269 			    "Elements of request should be of type OSDictionary");
9270 			result = kOSKextReturnInternalError;
9271 			goto finish;
9272 		}
9273 		requestPredicate = _OSKextGetRequestPredicate(request);
9274 		if (!requestPredicate) {
9275 			OSKextLog(/* kext */ NULL,
9276 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9277 			    "Failed to get request predicate");
9278 			result = kOSKextReturnInternalError;
9279 			goto finish;
9280 		}
9281 		// is this a dext launch?
9282 		if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) {
9283 			token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken));
9284 			if (!token) {
9285 				OSKextLog(/* kext */ NULL,
9286 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9287 				    "Could not find a IOUserServerCheckInToken in daemon launch request.");
9288 				result = kOSKextReturnInternalError;
9289 				goto finish;
9290 			}
9291 			portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT);
9292 			if (portName == 0 || portName == MACH_PORT_DEAD) {
9293 				OSKextLog(/* kext */ NULL,
9294 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9295 				    "Could not create send right for object.");
9296 				result = kOSKextReturnInternalError;
9297 				goto finish;
9298 			}
9299 			// Store the mach port name as a OSNumber
9300 			portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName));
9301 			if (!portNameNumber) {
9302 				OSKextLog(/* kext */ NULL,
9303 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9304 				    "Could not create OSNumber object.");
9305 				result = kOSKextReturnNoMemory;
9306 				goto finish;
9307 			}
9308 			if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) {
9309 				OSKextLog(/* kext */ NULL,
9310 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9311 				    "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken);
9312 				result = kOSKextReturnNoMemory;
9313 				goto finish;
9314 			}
9315 		}
9316 finish:
9317 		if (result != kOSReturnSuccess) {
9318 			break;
9319 		}
9320 	}
9321 	return result;
9322 }
9323 
9324 /*********************************************************************
9325 * XXX - this function is a big ugly mess
9326 *********************************************************************/
9327 /* static */
9328 OSReturn
9329 OSKext::handleRequest(
9330 	host_priv_t     hostPriv,
9331 	OSKextLogSpec   clientLogFilter,
9332 	char          * requestBuffer,
9333 	uint32_t        requestLength,
9334 	char         ** responseOut,
9335 	uint32_t      * responseLengthOut,
9336 	char         ** logInfoOut,
9337 	uint32_t      * logInfoLengthOut)
9338 {
9339 	OSReturn       result             = kOSReturnError;
9340 	kern_return_t  kmem_result        = KERN_FAILURE;
9341 
9342 	char         * response           = NULL;        // returned by reference
9343 	uint32_t       responseLength     = 0;
9344 
9345 	bool           taskCanManageAllKCs   = false;
9346 	bool           taskOnlyManagesBootKC = false;
9347 
9348 	OSSharedPtr<OSObject>     parsedXML;
9349 	OSDictionary            * requestDict    = NULL;        // do not release
9350 	OSSharedPtr<OSString>     errorString;
9351 
9352 	OSSharedPtr<OSObject>     responseObject;
9353 
9354 	OSSharedPtr<OSSerialize>  serializer;
9355 
9356 	OSSharedPtr<OSArray>      logInfoArray;
9357 
9358 	OSString     * predicate          = NULL;        // do not release
9359 	OSString     * kextIdentifier     = NULL;        // do not release
9360 	OSArray      * kextIdentifiers    = NULL;        // do not release
9361 	OSKext       * theKext            = NULL;        // do not release
9362 	OSBoolean    * boolArg            = NULL;        // do not release
9363 
9364 	IORecursiveLockLock(sKextLock);
9365 
9366 	if (responseOut) {
9367 		*responseOut = NULL;
9368 		*responseLengthOut = 0;
9369 	}
9370 	if (logInfoOut) {
9371 		*logInfoOut = NULL;
9372 		*logInfoLengthOut = 0;
9373 	}
9374 
9375 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
9376 
9377 	/* XML must be nul-terminated.
9378 	 */
9379 	if (requestBuffer[requestLength - 1] != '\0') {
9380 		OSKextLog(/* kext */ NULL,
9381 		    kOSKextLogErrorLevel |
9382 		    kOSKextLogIPCFlag,
9383 		    "Invalid request from user space (not nul-terminated).");
9384 		result = kOSKextReturnBadData;
9385 		goto finish;
9386 	}
9387 	parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString);
9388 	if (parsedXML) {
9389 		requestDict = OSDynamicCast(OSDictionary, parsedXML.get());
9390 	}
9391 	if (!requestDict) {
9392 		const char * errorCString = "(unknown error)";
9393 
9394 		if (errorString && errorString->getCStringNoCopy()) {
9395 			errorCString = errorString->getCStringNoCopy();
9396 		} else if (parsedXML) {
9397 			errorCString = "not a dictionary";
9398 		}
9399 		OSKextLog(/* kext */ NULL,
9400 		    kOSKextLogErrorLevel |
9401 		    kOSKextLogIPCFlag,
9402 		    "Error unserializing request from user space: %s.",
9403 		    errorCString);
9404 		result = kOSKextReturnSerialization;
9405 		goto finish;
9406 	}
9407 
9408 	predicate = _OSKextGetRequestPredicate(requestDict);
9409 	if (!predicate) {
9410 		OSKextLog(/* kext */ NULL,
9411 		    kOSKextLogErrorLevel |
9412 		    kOSKextLogIPCFlag,
9413 		    "Recieved kext request from user space with no predicate.");
9414 		result = kOSKextReturnInvalidArgument;
9415 		goto finish;
9416 	}
9417 
9418 	OSKextLog(/* kext */ NULL,
9419 	    kOSKextLogDebugLevel |
9420 	    kOSKextLogIPCFlag,
9421 	    "Received '%s' request from user space.",
9422 	    predicate->getCStringNoCopy());
9423 
9424 	/*
9425 	 * All management of file sets requires an entitlement
9426 	 */
9427 	result = kOSKextReturnNotPrivileged;
9428 	if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
9429 	    predicate->isEqualTo(kKextRequestPredicateStart) ||
9430 	    predicate->isEqualTo(kKextRequestPredicateStop) ||
9431 	    predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
9432 	    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
9433 	    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
9434 	    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
9435 	    predicate->isEqualTo(kKextRequestPredicateLoadFromKC) ||
9436 	    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
9437 	    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
9438 	    predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
9439 		if (hostPriv == HOST_PRIV_NULL) {
9440 			OSKextLog(/* kext */ NULL,
9441 			    kOSKextLogErrorLevel |
9442 			    kOSKextLogIPCFlag,
9443 			    "Access Failure - must be root user.");
9444 			goto finish;
9445 		}
9446 		taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE;
9447 		taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE;
9448 
9449 		if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) {
9450 			OSKextLog(/* kext */ NULL,
9451 			    kOSKextLogErrorLevel |
9452 			    kOSKextLogIPCFlag,
9453 			    "Access Failure - client not entitled to manage file sets.");
9454 			goto finish;
9455 		}
9456 
9457 		/*
9458 		 * The OnlyBootKC entitlement restricts the
9459 		 * collection-management entitlement to only managing kexts in
9460 		 * the BootKC. All other predicates that alter global state or
9461 		 * add new KCs are disallowed.
9462 		 */
9463 		if (taskOnlyManagesBootKC &&
9464 		    (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
9465 		    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
9466 		    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
9467 		    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
9468 		    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
9469 		    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
9470 		    predicate->isEqualTo(kKextRequestPredicateDaemonReady))) {
9471 			OSKextLog(/* kext */ NULL,
9472 			    kOSKextLogErrorLevel |
9473 			    kOSKextLogIPCFlag,
9474 			    "Access Failure - client not entitled to manage non-primary KCs");
9475 			goto finish;
9476 		}
9477 
9478 		/*
9479 		 * If we get here, then the process either has the full KC
9480 		 * management entitlement, or it has the BootKC-only
9481 		 * entitlement and the request is about the BootKC.
9482 		 */
9483 	}
9484 
9485 	/* Get common args in anticipation of use.
9486 	 */
9487 	kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
9488 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
9489 	kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
9490 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
9491 	if (kextIdentifier) {
9492 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
9493 	}
9494 	boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
9495 		    requestDict, kKextRequestArgumentValueKey));
9496 
9497 	if (taskOnlyManagesBootKC &&
9498 	    theKext &&
9499 	    theKext->isInFileset() &&
9500 	    theKext->kc_type != KCKindPrimary) {
9501 		OSKextLog(/* kext */ NULL,
9502 		    kOSKextLogErrorLevel |
9503 		    kOSKextLogIPCFlag,
9504 		    "Access Failure - client not entitled to manage kext in non-primary KC");
9505 		result = kOSKextReturnNotPrivileged;
9506 		goto finish;
9507 	}
9508 
9509 	result = kOSKextReturnInvalidArgument;
9510 
9511 	if (predicate->isEqualTo(kKextRequestPredicateStart)) {
9512 		if (!kextIdentifier) {
9513 			OSKextLog(/* kext */ NULL,
9514 			    kOSKextLogErrorLevel |
9515 			    kOSKextLogIPCFlag,
9516 			    "Invalid arguments to kext start request.");
9517 		} else if (!theKext) {
9518 			OSKextLog(/* kext */ NULL,
9519 			    kOSKextLogErrorLevel |
9520 			    kOSKextLogIPCFlag,
9521 			    "Kext %s not found for start request.",
9522 			    kextIdentifier->getCStringNoCopy());
9523 			result = kOSKextReturnNotFound;
9524 		} else {
9525 			result = theKext->start();
9526 		}
9527 	} else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
9528 		if (!kextIdentifier) {
9529 			OSKextLog(/* kext */ NULL,
9530 			    kOSKextLogErrorLevel |
9531 			    kOSKextLogIPCFlag,
9532 			    "Invalid arguments to kext stop request.");
9533 		} else if (!theKext) {
9534 			OSKextLog(/* kext */ NULL,
9535 			    kOSKextLogErrorLevel |
9536 			    kOSKextLogIPCFlag,
9537 			    "Kext %s not found for stop request.",
9538 			    kextIdentifier->getCStringNoCopy());
9539 			result = kOSKextReturnNotFound;
9540 		} else {
9541 			result = theKext->stop();
9542 		}
9543 	} else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) {
9544 		result = OSKext::setMissingAuxKCBundles(requestDict);
9545 	} else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) {
9546 		if (!kextIdentifier) {
9547 			OSKextLog(/* kext */ NULL,
9548 			    kOSKextLogErrorLevel |
9549 			    kOSKextLogIPCFlag,
9550 			    "Invalid arguments to AuxKC Bundle Available request.");
9551 		} else {
9552 			result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict);
9553 		}
9554 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) {
9555 		if (!kextIdentifier) {
9556 			OSKextLog(/* kext */ NULL,
9557 			    kOSKextLogErrorLevel |
9558 			    kOSKextLogIPCFlag,
9559 			    "Invalid arguments to kext load from KC request.");
9560 		} else if (!theKext) {
9561 			OSKextLog(/* kext */ NULL,
9562 			    kOSKextLogErrorLevel |
9563 			    kOSKextLogIPCFlag,
9564 			    "Kext %s not found for load from KC request.",
9565 			    kextIdentifier->getCStringNoCopy());
9566 			result = kOSKextReturnNotFound;
9567 		} else if (!theKext->isInFileset()) {
9568 			OSKextLog(/* kext */ NULL,
9569 			    kOSKextLogErrorLevel |
9570 			    kOSKextLogIPCFlag,
9571 			    "Kext %s does not exist in a KC: refusing to load.",
9572 			    kextIdentifier->getCStringNoCopy());
9573 			result = kOSKextReturnNotLoadable;
9574 		} else {
9575 			result = OSKext::loadKextFromKC(theKext, requestDict);
9576 		}
9577 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) {
9578 		if (!kextIdentifier) {
9579 			OSKextLog(/* kext */ NULL,
9580 			    kOSKextLogErrorLevel |
9581 			    kOSKextLogIPCFlag,
9582 			    "Invalid arguments to codeless kext load interface (missing identifier).");
9583 		} else {
9584 			result = OSKext::loadCodelessKext(kextIdentifier, requestDict);
9585 		}
9586 	} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
9587 		if (!kextIdentifier) {
9588 			OSKextLog(/* kext */ NULL,
9589 			    kOSKextLogErrorLevel |
9590 			    kOSKextLogIPCFlag,
9591 			    "Invalid arguments to kext unload request.");
9592 		} else if (!theKext) {
9593 			OSKextLog(/* kext */ NULL,
9594 			    kOSKextLogErrorLevel |
9595 			    kOSKextLogIPCFlag,
9596 			    "Kext %s not found for unload request.",
9597 			    kextIdentifier->getCStringNoCopy());
9598 			result = kOSKextReturnNotFound;
9599 		} else {
9600 			OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
9601 			    _OSKextGetRequestArgument(requestDict,
9602 			    kKextRequestArgumentTerminateIOServicesKey));
9603 			result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
9604 		}
9605 	} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
9606 		result = OSKext::dispatchResource(requestDict);
9607 	} else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
9608 		OSNumber     *lookupNum   = NULL;
9609 		lookupNum = OSDynamicCast(OSNumber,
9610 		    _OSKextGetRequestArgument(requestDict,
9611 		    kKextRequestArgumentLookupAddressKey));
9612 
9613 		responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
9614 		if (responseObject) {
9615 			result = kOSReturnSuccess;
9616 		} else {
9617 			goto finish;
9618 		}
9619 	} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
9620 	    predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) ||
9621 	    predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
9622 		OSBoolean    * delayAutounloadBool = NULL;
9623 		OSObject     * infoKeysRaw         = NULL;
9624 		OSArray      * infoKeys            = NULL;
9625 		uint32_t       infoKeysCount       = 0;
9626 
9627 		delayAutounloadBool = OSDynamicCast(OSBoolean,
9628 		    _OSKextGetRequestArgument(requestDict,
9629 		    kKextRequestArgumentDelayAutounloadKey));
9630 
9631 		/* If asked to delay autounload, reset the timer if it's currently set.
9632 		 * (That is, don't schedule an unload if one isn't already pending.
9633 		 */
9634 		if (delayAutounloadBool == kOSBooleanTrue) {
9635 			OSKext::considerUnloads(/* rescheduleOnly? */ true);
9636 		}
9637 
9638 		infoKeysRaw = _OSKextGetRequestArgument(requestDict,
9639 		    kKextRequestArgumentInfoKeysKey);
9640 		infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
9641 		if (infoKeysRaw && !infoKeys) {
9642 			OSKextLog(/* kext */ NULL,
9643 			    kOSKextLogErrorLevel |
9644 			    kOSKextLogIPCFlag,
9645 			    "Invalid arguments to kext info request.");
9646 			goto finish;
9647 		}
9648 
9649 		if (infoKeys) {
9650 			infoKeysCount = infoKeys->getCount();
9651 			for (uint32_t i = 0; i < infoKeysCount; i++) {
9652 				if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
9653 					OSKextLog(/* kext */ NULL,
9654 					    kOSKextLogErrorLevel |
9655 					    kOSKextLogIPCFlag,
9656 					    "Invalid arguments to kext info request.");
9657 					goto finish;
9658 				}
9659 			}
9660 		}
9661 
9662 		if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
9663 			responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
9664 		} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
9665 			responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
9666 		} else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
9667 			responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys);
9668 		}
9669 
9670 		if (!responseObject) {
9671 			result = kOSKextReturnInternalError;
9672 		} else {
9673 			OSKextLog(/* kext */ NULL,
9674 			    kOSKextLogDebugLevel |
9675 			    kOSKextLogIPCFlag,
9676 			    "Returning loaded kext info.");
9677 			result = kOSReturnSuccess;
9678 		}
9679 	} else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
9680 		/* Hand the current sKernelRequests array to the caller
9681 		 * (who must release it), and make a new one.
9682 		 */
9683 		responseObject = os::move(sKernelRequests);
9684 		sKernelRequests = OSArray::withCapacity(0);
9685 		sPostedKextLoadIdentifiers->flushCollection();
9686 		OSKextLog(/* kext */ NULL,
9687 		    kOSKextLogDebugLevel |
9688 		    kOSKextLogIPCFlag,
9689 		    "Returning kernel requests.");
9690 		result = kOSReturnSuccess;
9691 	} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
9692 		/* Return the set of all requested bundle identifiers */
9693 		responseObject = sAllKextLoadIdentifiers;
9694 		OSKextLog(/* kext */ NULL,
9695 		    kOSKextLogDebugLevel |
9696 		    kOSKextLogIPCFlag,
9697 		    "Returning load requests.");
9698 		result = kOSReturnSuccess;
9699 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) {
9700 		printf("KextLog: Loading FileSet KC(s)\n");
9701 		result = OSKext::loadFileSetKexts(requestDict);
9702 	} else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
9703 		printf("KextLog: " kIOKitDaemonName " is %s\n", sIOKitDaemonActive ? "active" : "not active");
9704 		result = (sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot) ? kOSReturnSuccess : kIOReturnNotReady;
9705 	} else {
9706 		OSKextLog(/* kext */ NULL,
9707 		    kOSKextLogDebugLevel |
9708 		    kOSKextLogIPCFlag,
9709 		    "Received '%s' invalid request from user space.",
9710 		    predicate->getCStringNoCopy());
9711 		goto finish;
9712 	}
9713 
9714 	/**********
9715 	 * Now we have handle the request, or not. Gather up the response & logging
9716 	 * info to ship to user space.
9717 	 *********/
9718 
9719 	/* Note: Nothing in OSKext is supposed to retain requestDict,
9720 	 * but you never know....
9721 	 */
9722 	if (requestDict->getRetainCount() > 1) {
9723 		OSKextLog(/* kext */ NULL,
9724 		    kOSKextLogWarningLevel |
9725 		    kOSKextLogIPCFlag,
9726 		    "Request from user space still retained by a kext; "
9727 		    "probable memory leak.");
9728 	}
9729 
9730 	if (responseOut && responseObject) {
9731 		serializer = OSSerialize::withCapacity(0);
9732 		if (!serializer) {
9733 			result = kOSKextReturnNoMemory;
9734 			goto finish;
9735 		}
9736 		/*
9737 		 * Before serializing the kernel requests, patch the dext launch requests so
9738 		 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the
9739 		 * IOUserServerCheckInToken kernel object.
9740 		 */
9741 		if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
9742 			OSArray * requests = OSDynamicCast(OSArray, responseObject.get());
9743 			task_t calling_task = current_task();
9744 			if (!requests) {
9745 				OSKextLog(/* kext */ NULL,
9746 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9747 				    "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests);
9748 				result = kOSKextReturnInternalError;
9749 				goto finish;
9750 			}
9751 			result = patchDextLaunchRequests(calling_task, requests);
9752 			if (result != kOSReturnSuccess) {
9753 				OSKextLog(/* kext */ NULL,
9754 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9755 				    "Failed to patch dext launch requests.");
9756 				goto finish;
9757 			}
9758 		}
9759 
9760 		if (!responseObject->serialize(serializer.get())) {
9761 			OSKextLog(/* kext */ NULL,
9762 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9763 			    "Failed to serialize response to request from user space.");
9764 			result = kOSKextReturnSerialization;
9765 			goto finish;
9766 		}
9767 
9768 		response = (char *)serializer->text();
9769 		responseLength = serializer->getLength();
9770 	}
9771 
9772 	if (responseOut && response) {
9773 		char * buffer;
9774 
9775 		/* This kmem_alloc sets the return value of the function.
9776 		 */
9777 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
9778 		    round_page(responseLength), KMA_DATA, VM_KERN_MEMORY_OSKEXT);
9779 		if (kmem_result != KERN_SUCCESS) {
9780 			OSKextLog(/* kext */ NULL,
9781 			    kOSKextLogErrorLevel |
9782 			    kOSKextLogIPCFlag,
9783 			    "Failed to copy response to request from user space.");
9784 			result = kmem_result;
9785 			goto finish;
9786 		} else {
9787 			/* 11981737 - clear uninitialized data in last page */
9788 			bzero((void *)(buffer + responseLength),
9789 			    (round_page(responseLength) - responseLength));
9790 			memcpy(buffer, response, responseLength);
9791 			*responseOut = buffer;
9792 			*responseLengthOut = responseLength;
9793 		}
9794 	}
9795 
9796 finish:
9797 
9798 	/* Gather up the collected log messages for user space. Any messages
9799 	 * messages past this call will not make it up as log messages but
9800 	 * will be in the system log. Note that we ignore the return of the
9801 	 * serialize; it has no bearing on the operation at hand even if we
9802 	 * fail to get the log messages.
9803 	 */
9804 	logInfoArray = OSKext::clearUserSpaceLogFilter();
9805 
9806 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
9807 		(void)OSKext::serializeLogInfo(logInfoArray.get(),
9808 		    logInfoOut, logInfoLengthOut);
9809 	}
9810 
9811 	IORecursiveLockUnlock(sKextLock);
9812 
9813 	return result;
9814 }
9815 
9816 #if PRAGMA_MARK
9817 #pragma mark Linked Kext Collection Support
9818 #endif
9819 
9820 static int
9821 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount)
9822 {
9823 	for (int i = 0; i < segCount; i++) {
9824 		vm_offset_t segStart = segAddrs[i];
9825 		vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i];
9826 
9827 		if (theAddr >= segStart && theAddr < segEnd) {
9828 			return i;
9829 		}
9830 	}
9831 	return -1;
9832 }
9833 
9834 static void
9835 __slideOldKaslrOffsets(kernel_mach_header_t *mh,
9836     kernel_segment_command_t *kextTextSeg,
9837     OSData *kaslrOffsets)
9838 {
9839 	static const char *plk_segNames[] = {
9840 		"__TEXT",
9841 		"__TEXT_EXEC",
9842 		"__DATA",
9843 		"__DATA_CONST",
9844 		"__LINKEDIT",
9845 		"__PRELINK_TEXT",
9846 		"__PLK_TEXT_EXEC",
9847 		"__PRELINK_DATA",
9848 		"__PLK_DATA_CONST",
9849 		"__PLK_LLVM_COV",
9850 		"__PLK_LINKEDIT",
9851 		"__PRELINK_INFO"
9852 	};
9853 	static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0]));
9854 
9855 	unsigned long plk_segSizes[num_plk_seg];
9856 	vm_offset_t   plk_segAddrs[num_plk_seg];
9857 
9858 	for (size_t i = 0; i < num_plk_seg; i++) {
9859 		plk_segSizes[i] = 0;
9860 		plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]);
9861 	}
9862 
9863 	uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr;
9864 
9865 	int slidKextAddrCount = 0;
9866 	int badSlideAddr = 0;
9867 	int badSlideTarget = 0;
9868 
9869 	struct kaslrPackedOffsets {
9870 		uint32_t    count;          /* number of offsets */
9871 		uint32_t    offsetsArray[];        /* offsets to slide */
9872 	};
9873 	const struct kaslrPackedOffsets *myOffsets = NULL;
9874 	myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy();
9875 
9876 	for (uint32_t j = 0; j < myOffsets->count; j++) {
9877 		uint64_t   slideOffset = (uint64_t)myOffsets->offsetsArray[j];
9878 		vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset);
9879 		int        slideAddrSegIndex = -1;
9880 		int        addrToSlideSegIndex = -1;
9881 
9882 		slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
9883 		if (slideAddrSegIndex >= 0) {
9884 			addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
9885 			if (addrToSlideSegIndex < 0) {
9886 				badSlideTarget++;
9887 				continue;
9888 			}
9889 		} else {
9890 			badSlideAddr++;
9891 			continue;
9892 		}
9893 
9894 		slidKextAddrCount++;
9895 		*slideAddr = ml_static_slide(*slideAddr);
9896 	}         // for ...
9897 }
9898 
9899 
9900 
9901 /********************************************************************
9902 * addKextsFromKextCollection
9903 *
9904 * Input: MachO header of kext collection. The MachO is assumed to
9905 *        have a section named 'info_seg_name,info_sect_name' that
9906 *        contains a serialized XML info dictionary. This dictionary
9907 *        contains a UUID, possibly a set of relocations (for older
9908 *        kxld-built binaries), and an array of kext personalities.
9909 *
9910 ********************************************************************/
9911 bool
9912 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
9913     OSDictionary *infoDict, const char *text_seg_name,
9914     OSData **kcUUID, kc_kind_t type)
9915 {
9916 	bool result = false;
9917 
9918 	OSArray *kextArray     = NULL;        // do not release
9919 	OSData *infoDictKCUUID = NULL;         // do not release
9920 	OSData *kaslrOffsets   = NULL;        // do not release
9921 
9922 	IORegistryEntry *registryRoot = NULL;         // do not release
9923 	OSSharedPtr<OSNumber> kcKextCount;
9924 
9925 	/* extract the KC UUID from the dictionary */
9926 	infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
9927 	if (infoDictKCUUID) {
9928 		if (infoDictKCUUID->getLength() != sizeof(uuid_t)) {
9929 			panic("kcUUID length is %d, expected %lu",
9930 			    infoDictKCUUID->getLength(), sizeof(uuid_t));
9931 		}
9932 	}
9933 
9934 	/* locate the array of kext dictionaries */
9935 	kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey));
9936 	if (!kextArray) {
9937 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9938 		    "The given KC has no kext info dictionaries");
9939 		goto finish;
9940 	}
9941 
9942 	/*
9943 	 * old-style KASLR offsets may be present in the info dictionary. If
9944 	 * we find them, use them and eventually slide them.
9945 	 */
9946 	kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey));
9947 
9948 	/*
9949 	 * Before processing any kexts, locate the special kext bundle which
9950 	 * contains a list of kexts that we are to prevent from loading.
9951 	 */
9952 	createExcludeListFromPrelinkInfo(kextArray);
9953 
9954 	/*
9955 	 * Create OSKext objects for each kext we find in the array of kext
9956 	 * info plist dictionaries.
9957 	 */
9958 	for (int i = 0; i < (int)kextArray->getCount(); ++i) {
9959 		OSDictionary *kextDict = NULL;
9960 		kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i));
9961 		if (!kextDict) {
9962 			OSKextLog(/* kext */ NULL,
9963 			    kOSKextLogErrorLevel |
9964 			    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
9965 			    "Kext info dictionary for kext #%d isn't a dictionary?", i);
9966 			continue;
9967 		}
9968 
9969 		/*
9970 		 * Create the kext for the entry, then release it, because the
9971 		 * kext system keeps a reference around until the kext is
9972 		 * explicitly removed.  Any creation/registration failures are
9973 		 * already logged for us.
9974 		 */
9975 		withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type);
9976 	}
9977 
9978 	/*
9979 	 * slide old-style kxld relocations
9980 	 * NOTE: this is still used on embedded KCs built with kcgen
9981 	 * TODO: Remove this once we use the new kext linker everywhere!
9982 	 */
9983 	if (kaslrOffsets && vm_kernel_slide > 0) {
9984 		kernel_segment_command_t *text_segment = NULL;
9985 		text_segment = getsegbynamefromheader(mh, text_seg_name);
9986 		if (!text_segment) {
9987 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9988 			    "Can't find a TEXT segment named '%s' in macho header", text_seg_name);
9989 			goto finish;
9990 		}
9991 
9992 		__slideOldKaslrOffsets(mh, text_segment, kaslrOffsets);
9993 		/* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */
9994 		setAllVMAttributes();
9995 	}
9996 
9997 	/* Store the number of prelinked kexts in the registry so we can tell
9998 	 * when the system has been started from a prelinked kernel.
9999 	 */
10000 	registryRoot = IORegistryEntry::getRegistryRoot();
10001 	assert(registryRoot);
10002 
10003 	kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t));
10004 	assert(kcKextCount);
10005 	if (kcKextCount) {
10006 		OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey);
10007 		OSNumber *num;
10008 		num = OSDynamicCast(OSNumber, prop.get());
10009 		if (num) {
10010 			kcKextCount->addValue(num->unsigned64BitValue());
10011 		}
10012 		registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get());
10013 	}
10014 
10015 	OSKextLog(/* kext */ NULL,
10016 	    kOSKextLogProgressLevel |
10017 	    kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
10018 	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10019 	    "%u prelinked kexts", infoDict->getCount());
10020 
10021 
10022 	if (kcUUID && infoDictKCUUID) {
10023 		*kcUUID = OSData::withData(infoDictKCUUID).detach();
10024 	}
10025 
10026 	result = true;
10027 
10028 finish:
10029 	return result;
10030 }
10031 
10032 bool
10033 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10034     OSDictionary *infoDict, const char *text_seg_name,
10035     OSSharedPtr<OSData> &kcUUID, kc_kind_t type)
10036 {
10037 	OSData  *result = NULL;
10038 	bool success = addKextsFromKextCollection(mh,
10039 	    infoDict,
10040 	    text_seg_name,
10041 	    &result,
10042 	    type);
10043 	if (success) {
10044 		kcUUID.reset(result, OSNoRetain);
10045 	}
10046 	return success;
10047 }
10048 
10049 static OSSharedPtr<OSObject> deferredAuxKCXML;
10050 bool
10051 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh,
10052     OSSharedPtr<OSObject> &parsedXML, kc_kind_t type)
10053 {
10054 	if (type != KCKindAuxiliary) {
10055 		return false;
10056 	}
10057 
10058 	kernel_mach_header_t *_mh;
10059 	_mh = (kernel_mach_header_t*)PE_get_kc_header(type);
10060 	if (!_mh || _mh != mh) {
10061 		return false;
10062 	}
10063 
10064 	if (deferredAuxKCXML) {
10065 		/* only allow this to be called once */
10066 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10067 		    "An Aux KC has already been registered for deferred processing.");
10068 		return false;
10069 	}
10070 
10071 	OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
10072 	if (!infoDict) {
10073 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10074 		    "The Aux KC has info dictionary");
10075 		return false;
10076 	}
10077 
10078 	OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10079 	if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) {
10080 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10081 		    "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey);
10082 		return false;
10083 	}
10084 
10085 	/*
10086 	 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid
10087 	 * sysctl can return the UUID to user space which will check this
10088 	 * value for errors.
10089 	 */
10090 	memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(),
10091 	    kcUUID->getLength());
10092 	uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
10093 	auxkc_uuid_valid = TRUE;
10094 
10095 	deferredAuxKCXML = parsedXML;
10096 
10097 	return true;
10098 }
10099 
10100 OSSharedPtr<OSObject>
10101 OSKext::consumeDeferredKextCollection(kc_kind_t type)
10102 {
10103 	if (type != KCKindAuxiliary || !deferredAuxKCXML) {
10104 		return NULL;
10105 	}
10106 
10107 	return os::move(deferredAuxKCXML);
10108 }
10109 
10110 #if PRAGMA_MARK
10111 #pragma mark Profile-Guided-Optimization Support
10112 #endif
10113 
10114 // #include <InstrProfiling.h>
10115 extern "C" {
10116 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
10117     const char *DataEnd,
10118     const char *CountersBegin,
10119     const char *CountersEnd,
10120     const char *NamesBegin,
10121     const char *NamesEnd);
10122 int __llvm_profile_write_buffer_internal(char *Buffer,
10123     const char *DataBegin,
10124     const char *DataEnd,
10125     const char *CountersBegin,
10126     const char *CountersEnd,
10127     const char *NamesBegin,
10128     const char *NamesEnd);
10129 }
10130 
10131 
10132 static
10133 void
10134 OSKextPgoMetadataPut(char *pBuffer,
10135     size_t *position,
10136     size_t bufferSize,
10137     uint32_t *num_pairs,
10138     const char *key,
10139     const char *value)
10140 {
10141 	size_t strlen_key = strlen(key);
10142 	size_t strlen_value = strlen(value);
10143 	size_t len = strlen(key) + 1 + strlen(value) + 1;
10144 	char *pos = pBuffer + *position;
10145 	*position += len;
10146 	if (pBuffer && bufferSize && *position <= bufferSize) {
10147 		memcpy(pos, key, strlen_key); pos += strlen_key;
10148 		*(pos++) = '=';
10149 		memcpy(pos, value, strlen_value); pos += strlen_value;
10150 		*(pos++) = 0;
10151 		if (num_pairs) {
10152 			(*num_pairs)++;
10153 		}
10154 	}
10155 }
10156 
10157 
10158 static
10159 void
10160 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
10161 {
10162 	*position += strlen(key) + 1 + value_max + 1;
10163 }
10164 
10165 
10166 static
10167 void
10168 OSKextPgoMetadataPutAll(OSKext *kext,
10169     uuid_t instance_uuid,
10170     char *pBuffer,
10171     size_t *position,
10172     size_t bufferSize,
10173     uint32_t *num_pairs)
10174 {
10175 	_static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
10176 	//log_10 2^16 ≈ 4.82
10177 	const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
10178 	const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
10179 
10180 	if (!pBuffer) {
10181 		OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
10182 		OSKextPgoMetadataPutMax(position, "UUID", 36);
10183 		OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
10184 	} else {
10185 		uuid_string_t instance_uuid_string;
10186 		uuid_unparse(instance_uuid, instance_uuid_string);
10187 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10188 		    "INSTANCE", instance_uuid_string);
10189 
10190 		OSSharedPtr<OSData> uuid_data;
10191 		uuid_t uuid;
10192 		uuid_string_t uuid_string;
10193 		uuid_data = kext->copyUUID();
10194 		if (uuid_data) {
10195 			memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
10196 			uuid_unparse(uuid, uuid_string);
10197 			OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10198 			    "UUID", uuid_string);
10199 		}
10200 
10201 		clock_sec_t secs;
10202 		clock_usec_t usecs;
10203 		clock_get_calendar_microtime(&secs, &usecs);
10204 		assert(usecs < 1000000);
10205 		char timestamp[max_timestamp_string_size + 1];
10206 		_static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
10207 		snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
10208 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10209 		    "TIMESTAMP", timestamp);
10210 	}
10211 
10212 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10213 	    "NAME", kext->getIdentifierCString());
10214 
10215 	char versionCString[kOSKextVersionMaxLength];
10216 	OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
10217 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10218 	    "VERSION", versionCString);
10219 }
10220 
10221 static
10222 size_t
10223 OSKextPgoMetadataSize(OSKext *kext)
10224 {
10225 	size_t position = 0;
10226 	uuid_t fakeuuid = {};
10227 	OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
10228 	return position;
10229 }
10230 
10231 int
10232 OSKextGrabPgoDataLocked(OSKext *kext,
10233     bool metadata,
10234     uuid_t instance_uuid,
10235     uint64_t *pSize,
10236     char *pBuffer,
10237     uint64_t bufferSize)
10238 {
10239 	int err = 0;
10240 
10241 	kernel_section_t *sect_prf_data = NULL;
10242 	kernel_section_t *sect_prf_name = NULL;
10243 	kernel_section_t *sect_prf_cnts = NULL;
10244 	uint64_t size;
10245 	size_t metadata_size = 0;
10246 	size_t offset_to_pairs = 0;
10247 
10248 	sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
10249 	sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
10250 	if (!sect_prf_name) {
10251 		// kextcache sometimes truncates the section name to 15 chars
10252 		// <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
10253 		sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
10254 	}
10255 	sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
10256 
10257 	if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
10258 		err = ENOTSUP;
10259 		goto out;
10260 	}
10261 
10262 	size = __llvm_profile_get_size_for_buffer_internal(
10263 		(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
10264 		(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
10265 		(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
10266 
10267 	if (metadata) {
10268 		metadata_size = OSKextPgoMetadataSize(kext);
10269 		size += metadata_size;
10270 		size += sizeof(pgo_metadata_footer);
10271 	}
10272 
10273 
10274 	if (pSize) {
10275 		*pSize = size;
10276 	}
10277 
10278 	if (pBuffer && bufferSize) {
10279 		if (bufferSize < size) {
10280 			err = ERANGE;
10281 			goto out;
10282 		}
10283 
10284 		err = __llvm_profile_write_buffer_internal(
10285 			pBuffer,
10286 			(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
10287 			(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
10288 			(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
10289 
10290 		if (err) {
10291 			err = EIO;
10292 			goto out;
10293 		}
10294 
10295 		if (metadata) {
10296 			offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size;
10297 			if (offset_to_pairs > UINT32_MAX) {
10298 				err = E2BIG;
10299 				goto out;
10300 			}
10301 
10302 			char *end_of_buffer = pBuffer + size;
10303 			struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
10304 			char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
10305 
10306 			size_t metadata_position = 0;
10307 			uint32_t num_pairs = 0;
10308 			OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
10309 			while (metadata_position < metadata_size) {
10310 				metadata_buffer[metadata_position++] = 0;
10311 			}
10312 
10313 			struct pgo_metadata_footer footer;
10314 			footer.magic = htonl(0x6d657461);
10315 			footer.number_of_pairs = htonl( num_pairs );
10316 			footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs );
10317 			memcpy(footerp, &footer, sizeof(footer));
10318 		}
10319 	}
10320 
10321 out:
10322 	return err;
10323 }
10324 
10325 
10326 int
10327 OSKextGrabPgoData(uuid_t uuid,
10328     uint64_t *pSize,
10329     char *pBuffer,
10330     uint64_t bufferSize,
10331     int wait_for_unload,
10332     int metadata)
10333 {
10334 	int err = 0;
10335 	OSSharedPtr<OSKext> kext;
10336 
10337 
10338 	IORecursiveLockLock(sKextLock);
10339 
10340 	kext = OSKext::lookupKextWithUUID(uuid);
10341 	if (!kext) {
10342 		err = ENOENT;
10343 		goto out;
10344 	}
10345 
10346 	if (wait_for_unload) {
10347 		OSKextGrabPgoStruct s;
10348 
10349 		s.metadata = metadata;
10350 		s.pSize = pSize;
10351 		s.pBuffer = pBuffer;
10352 		s.bufferSize = bufferSize;
10353 		s.err = EINTR;
10354 
10355 		struct list_head *prev = &kext->pendingPgoHead;
10356 		struct list_head *next = kext->pendingPgoHead.next;
10357 
10358 		s.list_head.prev = prev;
10359 		s.list_head.next = next;
10360 
10361 		prev->next = &s.list_head;
10362 		next->prev = &s.list_head;
10363 
10364 		kext.reset();
10365 
10366 		IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
10367 
10368 		prev = s.list_head.prev;
10369 		next = s.list_head.next;
10370 
10371 		prev->next = next;
10372 		next->prev = prev;
10373 
10374 		err = s.err;
10375 	} else {
10376 		err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
10377 	}
10378 
10379 out:
10380 
10381 	IORecursiveLockUnlock(sKextLock);
10382 
10383 	return err;
10384 }
10385 
10386 void
10387 OSKextResetPgoCountersLock()
10388 {
10389 	IORecursiveLockLock(sKextLock);
10390 }
10391 
10392 void
10393 OSKextResetPgoCountersUnlock()
10394 {
10395 	IORecursiveLockUnlock(sKextLock);
10396 }
10397 
10398 
10399 extern unsigned int not_in_kdp;
10400 
10401 void
10402 OSKextResetPgoCounters()
10403 {
10404 	assert(!not_in_kdp);
10405 	uint32_t count = sLoadedKexts->getCount();
10406 	for (uint32_t i = 0; i < count; i++) {
10407 		OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
10408 		kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
10409 		if (!sect_prf_cnts) {
10410 			continue;
10411 		}
10412 		memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
10413 	}
10414 }
10415 
10416 OSSharedPtr<OSDictionary>
10417 OSKext::copyLoadedKextInfoByUUID(
10418 	OSArray * kextIdentifiers,
10419 	OSArray * infoKeys)
10420 {
10421 	OSSharedPtr<OSDictionary> result;
10422 	OSSharedPtr<OSDictionary> kextInfo;
10423 	uint32_t       max_count, i, j;
10424 	uint32_t       idCount = 0;
10425 	uint32_t       idIndex = 0;
10426 	IORecursiveLockLock(sKextLock);
10427 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
10428 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
10429 
10430 #if CONFIG_MACF
10431 	/* Is the calling process allowed to query kext info? */
10432 	if (current_task() != kernel_task) {
10433 		int                 macCheckResult      = 0;
10434 		kauth_cred_t        cred                = NULL;
10435 
10436 		cred = kauth_cred_get_with_ref();
10437 		macCheckResult = mac_kext_check_query(cred);
10438 		kauth_cred_unref(&cred);
10439 
10440 		if (macCheckResult != 0) {
10441 			OSKextLog(/* kext */ NULL,
10442 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10443 			    "Failed to query kext info (MAC policy error 0x%x).",
10444 			    macCheckResult);
10445 			goto finish;
10446 		}
10447 	}
10448 #endif
10449 
10450 	/* Empty list of UUIDs is equivalent to no list (get all).
10451 	 */
10452 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
10453 		kextIdentifiers = NULL;
10454 	} else if (kextIdentifiers) {
10455 		idCount = kextIdentifiers->getCount();
10456 	}
10457 
10458 	/* Same for keys.
10459 	 */
10460 	if (infoKeys && !infoKeys->getCount()) {
10461 		infoKeys = NULL;
10462 	}
10463 
10464 	max_count = count[0] + count[1];
10465 	result = OSDictionary::withCapacity(max_count);
10466 	if (!result) {
10467 		goto finish;
10468 	}
10469 
10470 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
10471 		for (i = 0; i < count[j]; i++) {
10472 			OSKext       *thisKext     = NULL;        // do not release
10473 			Boolean       includeThis  = true;
10474 			uuid_t        thisKextUUID;
10475 			uuid_t        thisKextTextUUID;
10476 			OSSharedPtr<OSData> uuid_data;
10477 			uuid_string_t uuid_key;
10478 
10479 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
10480 			if (!thisKext) {
10481 				continue;
10482 			}
10483 
10484 			uuid_data = thisKext->copyUUID();
10485 			if (!uuid_data) {
10486 				continue;
10487 			}
10488 
10489 			memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
10490 
10491 			uuid_unparse(thisKextUUID, uuid_key);
10492 
10493 			uuid_data = thisKext->copyTextUUID();
10494 			if (!uuid_data) {
10495 				continue;
10496 			}
10497 			memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
10498 
10499 			/* Skip current kext if we have a list of UUIDs and
10500 			 * it isn't in the list.
10501 			 */
10502 			if (kextIdentifiers) {
10503 				includeThis = false;
10504 
10505 				for (idIndex = 0; idIndex < idCount; idIndex++) {
10506 					const OSString* wantedUUID = OSDynamicCast(OSString,
10507 					    kextIdentifiers->getObject(idIndex));
10508 
10509 					uuid_t uuid;
10510 					uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
10511 
10512 					if ((0 == uuid_compare(uuid, thisKextUUID))
10513 					    || (0 == uuid_compare(uuid, thisKextTextUUID))) {
10514 						includeThis = true;
10515 						/* Only need to find the first kext if multiple match,
10516 						 * ie. asking for the kernel uuid does not need to find
10517 						 * interface kexts or builtin static kexts.
10518 						 */
10519 						kextIdentifiers->removeObject(idIndex);
10520 						uuid_unparse(uuid, uuid_key);
10521 						break;
10522 					}
10523 				}
10524 			}
10525 
10526 			if (!includeThis) {
10527 				continue;
10528 			}
10529 
10530 			kextInfo = thisKext->copyInfo(infoKeys);
10531 			if (kextInfo) {
10532 				result->setObject(uuid_key, kextInfo.get());
10533 			}
10534 
10535 			if (kextIdentifiers && !kextIdentifiers->getCount()) {
10536 				goto finish;
10537 			}
10538 		}
10539 	}
10540 
10541 finish:
10542 	IORecursiveLockUnlock(sKextLock);
10543 
10544 	return result;
10545 }
10546 
10547 /*********************************************************************
10548 *********************************************************************/
10549 /* static */
10550 OSSharedPtr<OSDictionary>
10551 OSKext::copyKextCollectionInfo(
10552 	OSDictionary *requestDict,
10553 	OSArray  *infoKeys)
10554 {
10555 	OSSharedPtr<OSDictionary> result;
10556 	OSString *collectionType = NULL;
10557 	OSObject *rawLoadedState = NULL;
10558 	OSString *loadedState    = NULL;
10559 
10560 	kc_kind_t kc_request_kind = KCKindUnknown;
10561 	bool onlyLoaded = false;
10562 	bool onlyUnloaded = false;
10563 
10564 #if CONFIG_MACF
10565 	/* Is the calling process allowed to query kext info? */
10566 	if (current_task() != kernel_task) {
10567 		int                 macCheckResult      = 0;
10568 		kauth_cred_t        cred                = NULL;
10569 
10570 		cred = kauth_cred_get_with_ref();
10571 		macCheckResult = mac_kext_check_query(cred);
10572 		kauth_cred_unref(&cred);
10573 
10574 		if (macCheckResult != 0) {
10575 			OSKextLog(/* kext */ NULL,
10576 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10577 			    "Failed to query kext info (MAC policy error 0x%x).",
10578 			    macCheckResult);
10579 			goto finish;
10580 		}
10581 	}
10582 #endif
10583 
10584 	if (infoKeys && !infoKeys->getCount()) {
10585 		infoKeys = NULL;
10586 	}
10587 
10588 	collectionType = OSDynamicCast(OSString,
10589 	    _OSKextGetRequestArgument(requestDict,
10590 	    kKextRequestArgumentCollectionTypeKey));
10591 	if (!collectionType) {
10592 		OSKextLog(/* kext */ NULL,
10593 		    kOSKextLogErrorLevel |
10594 		    kOSKextLogIPCFlag,
10595 		    "Invalid '%s' argument to kext collection info request.",
10596 		    kKextRequestArgumentCollectionTypeKey);
10597 		goto finish;
10598 	}
10599 	if (collectionType->isEqualTo(kKCTypePrimary)) {
10600 		kc_request_kind = KCKindPrimary;
10601 	} else if (collectionType->isEqualTo(kKCTypeSystem)) {
10602 		kc_request_kind = KCKindPageable;
10603 	} else if (collectionType->isEqualTo(kKCTypeAuxiliary)) {
10604 		kc_request_kind = KCKindAuxiliary;
10605 	} else if (collectionType->isEqualTo(kKCTypeCodeless)) {
10606 		kc_request_kind = KCKindNone;
10607 	} else if (!collectionType->isEqualTo(kKCTypeAny)) {
10608 		OSKextLog(/* kext */ NULL,
10609 		    kOSKextLogErrorLevel |
10610 		    kOSKextLogIPCFlag,
10611 		    "Invalid '%s' argument value '%s' to kext collection info request.",
10612 		    kKextRequestArgumentCollectionTypeKey,
10613 		    collectionType->getCStringNoCopy());
10614 		goto finish;
10615 	}
10616 
10617 	rawLoadedState = _OSKextGetRequestArgument(requestDict,
10618 	    kKextRequestArgumentLoadedStateKey);
10619 	if (rawLoadedState) {
10620 		loadedState = OSDynamicCast(OSString, rawLoadedState);
10621 		if (!loadedState) {
10622 			OSKextLog(/* kext */ NULL,
10623 			    kOSKextLogErrorLevel |
10624 			    kOSKextLogIPCFlag,
10625 			    "Invalid '%s' argument to kext collection info request.",
10626 			    kKextRequestArgumentLoadedStateKey);
10627 			goto finish;
10628 		}
10629 	}
10630 	if (loadedState) {
10631 		if (loadedState->isEqualTo("Loaded")) {
10632 			onlyLoaded = true;
10633 		} else if (loadedState->isEqualTo("Unloaded")) {
10634 			onlyUnloaded = true;
10635 		} else if (!loadedState->isEqualTo("Any")) {
10636 			OSKextLog(/* kext */ NULL,
10637 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10638 			    "Invalid '%s' argument value '%s' for '%s' collection info",
10639 			    kKextRequestArgumentLoadedStateKey,
10640 			    loadedState->getCStringNoCopy(),
10641 			    collectionType->getCStringNoCopy());
10642 			goto finish;
10643 		}
10644 	}
10645 
10646 	result = OSDictionary::withCapacity(sKextsByID->getCount());
10647 	if (!result) {
10648 		goto finish;
10649 	}
10650 
10651 	IORecursiveLockLock(sKextLock);
10652 	{         // start block scope
10653 		sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
10654 		{
10655 			OSKext       *thisKext    = NULL;  // do not release
10656 			OSSharedPtr<OSDictionary> kextInfo;
10657 
10658 			(void)thisKextID;
10659 
10660 			thisKext = OSDynamicCast(OSKext, obj);
10661 			if (!thisKext) {
10662 			        return false;
10663 			}
10664 
10665 			/*
10666 			 * skip the kext if it came from the wrong collection type
10667 			 * (and the caller requested a specific type)
10668 			 */
10669 			if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) {
10670 			        return false;
10671 			}
10672 
10673 			/*
10674 			 * respect the caller's desire to find only loaded or
10675 			 * unloaded kexts
10676 			 */
10677 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10678 			        return false;
10679 			}
10680 			if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10681 			        return false;
10682 			}
10683 
10684 			kextInfo = thisKext->copyInfo(infoKeys);
10685 			if (kextInfo) {
10686 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
10687 			}
10688 			return false;
10689 		});
10690 	} // end block scope
10691 	IORecursiveLockUnlock(sKextLock);
10692 
10693 finish:
10694 	return result;
10695 }
10696 
10697 /*********************************************************************
10698 *********************************************************************/
10699 /* static */
10700 OSSharedPtr<OSDictionary>
10701 OSKext::copyLoadedKextInfo(
10702 	OSArray * kextIdentifiers,
10703 	OSArray * infoKeys)
10704 {
10705 	OSSharedPtr<OSDictionary> result;
10706 	uint32_t       idCount = 0;
10707 	bool           onlyLoaded;
10708 
10709 	IORecursiveLockLock(sKextLock);
10710 
10711 #if CONFIG_MACF
10712 	/* Is the calling process allowed to query kext info? */
10713 	if (current_task() != kernel_task) {
10714 		int                 macCheckResult      = 0;
10715 		kauth_cred_t        cred                = NULL;
10716 
10717 		cred = kauth_cred_get_with_ref();
10718 		macCheckResult = mac_kext_check_query(cred);
10719 		kauth_cred_unref(&cred);
10720 
10721 		if (macCheckResult != 0) {
10722 			OSKextLog(/* kext */ NULL,
10723 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10724 			    "Failed to query kext info (MAC policy error 0x%x).",
10725 			    macCheckResult);
10726 			goto finish;
10727 		}
10728 	}
10729 #endif
10730 
10731 	/* Empty list of bundle ids is equivalent to no list (get all).
10732 	 */
10733 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
10734 		kextIdentifiers = NULL;
10735 	} else if (kextIdentifiers) {
10736 		idCount = kextIdentifiers->getCount();
10737 	}
10738 
10739 	/* Same for keys.
10740 	 */
10741 	if (infoKeys && !infoKeys->getCount()) {
10742 		infoKeys = NULL;
10743 	}
10744 
10745 	onlyLoaded =  (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
10746 
10747 	result = OSDictionary::withCapacity(128);
10748 	if (!result) {
10749 		goto finish;
10750 	}
10751 
10752 #if 0
10753 	OSKextLog(/* kext */ NULL,
10754 	    kOSKextLogErrorLevel |
10755 	    kOSKextLogGeneralFlag,
10756 	    "kaslr: vm_kernel_slide 0x%lx \n",
10757 	    vm_kernel_slide);
10758 	OSKextLog(/* kext */ NULL,
10759 	    kOSKextLogErrorLevel |
10760 	    kOSKextLogGeneralFlag,
10761 	    "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
10762 	    vm_kernel_stext, vm_kernel_etext);
10763 	OSKextLog(/* kext */ NULL,
10764 	    kOSKextLogErrorLevel |
10765 	    kOSKextLogGeneralFlag,
10766 	    "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
10767 	    vm_kernel_base, vm_kernel_top);
10768 	OSKextLog(/* kext */ NULL,
10769 	    kOSKextLogErrorLevel |
10770 	    kOSKextLogGeneralFlag,
10771 	    "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
10772 	    vm_kext_base, vm_kext_top);
10773 	OSKextLog(/* kext */ NULL,
10774 	    kOSKextLogErrorLevel |
10775 	    kOSKextLogGeneralFlag,
10776 	    "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
10777 	    vm_prelink_stext, vm_prelink_etext);
10778 	OSKextLog(/* kext */ NULL,
10779 	    kOSKextLogErrorLevel |
10780 	    kOSKextLogGeneralFlag,
10781 	    "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
10782 	    vm_prelink_sinfo, vm_prelink_einfo);
10783 	OSKextLog(/* kext */ NULL,
10784 	    kOSKextLogErrorLevel |
10785 	    kOSKextLogGeneralFlag,
10786 	    "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
10787 	    vm_slinkedit, vm_elinkedit);
10788 #endif
10789 	{         // start block scope
10790 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
10791 		{
10792 			OSKext       * thisKext     = NULL;        // do not release
10793 			Boolean        includeThis  = true;
10794 			OSSharedPtr<OSDictionary> kextInfo;
10795 
10796 			thisKext = OSDynamicCast(OSKext, obj);
10797 			if (!thisKext) {
10798 			        return false;
10799 			}
10800 
10801 			/* Skip current kext if not yet started and caller didn't request all.
10802 			 */
10803 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10804 			        return false;
10805 			}
10806 
10807 			/* Skip current kext if we have a list of bundle IDs and
10808 			 * it isn't in the list.
10809 			 */
10810 			if (kextIdentifiers) {
10811 			        includeThis = false;
10812 
10813 			        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
10814 			                const OSString * thisRequestID = OSDynamicCast(OSString,
10815 			                kextIdentifiers->getObject(idIndex));
10816 			                if (thisKextID->isEqualTo(thisRequestID)) {
10817 			                        includeThis = true;
10818 			                        break;
10819 					}
10820 				}
10821 			}
10822 
10823 			if (!includeThis) {
10824 			        return false;
10825 			}
10826 
10827 			kextInfo = thisKext->copyInfo(infoKeys);
10828 			if (kextInfo) {
10829 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
10830 			}
10831 			return false;
10832 		});
10833 	}         // end block scope
10834 
10835 finish:
10836 	IORecursiveLockUnlock(sKextLock);
10837 
10838 	return result;
10839 }
10840 
10841 /*********************************************************************
10842 * Any info that needs to do allocations must goto finish on alloc
10843 * failure. Info that is just a lookup should just not set the object
10844 * if the info does not exist.
10845 *********************************************************************/
10846 #define _OSKextLoadInfoDictCapacity   (12)
10847 
10848 OSSharedPtr<OSDictionary>
10849 OSKext::copyInfo(OSArray * infoKeys)
10850 {
10851 	OSSharedPtr<OSDictionary>  result;
10852 	bool                       success                     = false;
10853 	OSSharedPtr<OSData>        headerData;
10854 	OSSharedPtr<OSData>        logData;
10855 	OSSharedPtr<OSNumber>      cpuTypeNumber;
10856 	OSSharedPtr<OSNumber>      cpuSubtypeNumber;
10857 	OSString                 * versionString               = NULL;        // do not release
10858 	OSString                 * bundleType                  = NULL;        // do not release
10859 	uint32_t                   executablePathCStringSize   = 0;
10860 	char                     * executablePathCString       = NULL;        // must kfree
10861 	OSSharedPtr<OSString>      executablePathString;
10862 	OSSharedPtr<OSData>        uuid;
10863 	OSSharedPtr<OSArray>       dependencyLoadTags;
10864 	OSSharedPtr<OSCollectionIterator>      metaClassIterator;
10865 	OSSharedPtr<OSArray>       metaClassInfo;
10866 	OSSharedPtr<OSDictionary>  metaClassDict;
10867 	OSMetaClass              * thisMetaClass               = NULL;        // do not release
10868 	OSSharedPtr<OSString>      metaClassName;
10869 	OSSharedPtr<OSString>      superclassName;
10870 	kc_format_t                kcformat;
10871 	uint32_t                   count, i;
10872 
10873 	result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
10874 	if (!result) {
10875 		goto finish;
10876 	}
10877 
10878 
10879 	/* Empty keys means no keys, but NULL is quicker to check.
10880 	 */
10881 	if (infoKeys && !infoKeys->getCount()) {
10882 		infoKeys = NULL;
10883 	}
10884 
10885 	if (!PE_get_primary_kc_format(&kcformat)) {
10886 		goto finish;
10887 	}
10888 
10889 	/* Headers, CPU type, and CPU subtype.
10890 	 */
10891 	if (!infoKeys ||
10892 	    _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
10893 	    _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
10894 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
10895 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
10896 		if (linkedExecutable && !isInterface()) {
10897 			kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
10898 			    linkedExecutable->getBytesNoCopy();
10899 
10900 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX
10901 			// do not return macho header info on shipping embedded - 19095897
10902 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
10903 				kernel_mach_header_t *  temp_kext_mach_hdr;
10904 				struct load_command *   lcp;
10905 
10906 				headerData = OSData::withBytes(kext_mach_hdr,
10907 				    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
10908 				if (!headerData) {
10909 					goto finish;
10910 				}
10911 
10912 				// unslide any vmaddrs we return to userspace - 10726716
10913 				temp_kext_mach_hdr = (kernel_mach_header_t *)
10914 				    headerData->getBytesNoCopy();
10915 				if (temp_kext_mach_hdr == NULL) {
10916 					goto finish;
10917 				}
10918 
10919 				lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
10920 				for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
10921 					if (lcp->cmd == LC_SEGMENT_KERNEL) {
10922 						kernel_segment_command_t *  segp;
10923 						kernel_section_t *          secp;
10924 
10925 						segp = (kernel_segment_command_t *) lcp;
10926 						// 10543468 - if we jettisoned __LINKEDIT clear size info
10927 						if (flags.jettisonLinkeditSeg) {
10928 							if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
10929 								segp->vmsize = 0;
10930 								segp->fileoff = 0;
10931 								segp->filesize = 0;
10932 							}
10933 						}
10934 
10935 #if __arm__ || __arm64__
10936 						// iBoot disregards zero-size segments, just set their addresses to gVirtBase
10937 						// and unslide them to avoid vm assertion failures / kernel logging breakage.
10938 						if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) {
10939 							segp->vmaddr = gVirtBase;
10940 							for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
10941 								secp->size = 0; // paranoia :)
10942 								secp->addr = gVirtBase;
10943 							}
10944 						}
10945 #endif
10946 
10947 #if 0
10948 						OSKextLog(/* kext */ NULL,
10949 						    kOSKextLogErrorLevel |
10950 						    kOSKextLogGeneralFlag,
10951 						    "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
10952 						    __FUNCTION__, segp->segname, segp->vmaddr,
10953 						    VM_KERNEL_UNSLIDE(segp->vmaddr),
10954 						    segp->vmsize, segp->nsects);
10955 						if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
10956 						    (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
10957 						    (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
10958 						    (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
10959 						    (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
10960 							OSKextLog(/* kext */ NULL,
10961 							    kOSKextLogErrorLevel |
10962 							    kOSKextLogGeneralFlag,
10963 							    "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
10964 							    __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
10965 						}
10966 #endif
10967 						segp->vmaddr = ml_static_unslide(segp->vmaddr);
10968 
10969 						for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
10970 							secp->addr = ml_static_unslide(secp->addr);
10971 						}
10972 					}
10973 					lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
10974 				}
10975 				result->setObject(kOSBundleMachOHeadersKey, headerData.get());
10976 			}
10977 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX
10978 
10979 			if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
10980 				osLogDataHeaderRef *header;
10981 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
10982 
10983 				void *os_log_data               = NULL;
10984 				void *cstring_data              = NULL;
10985 				void *asan_cstring_data         = NULL;
10986 				unsigned long os_log_size       = 0;
10987 				unsigned long cstring_size      = 0;
10988 				unsigned long asan_cstring_size = 0;
10989 				uint32_t os_log_offset          = 0;
10990 				uint32_t cstring_offset         = 0;
10991 				uint32_t asan_cstring_offset    = 0;
10992 				bool res;
10993 
10994 				os_log_data         = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
10995 				os_log_offset       = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr;
10996 				cstring_data        = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
10997 				cstring_offset      = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr;
10998 				asan_cstring_data   = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size);
10999 				asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr;
11000 
11001 				header             = (osLogDataHeaderRef *) headerBytes;
11002 				header->version    = OS_LOG_HDR_VERSION;
11003 				header->sect_count = NUM_OS_LOG_SECTIONS;
11004 				header->sections[OS_LOG_SECT_IDX].sect_offset       = os_log_offset;
11005 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) os_log_size;
11006 				header->sections[CSTRING_SECT_IDX].sect_offset      = cstring_offset;
11007 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) cstring_size;
11008 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset;
11009 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) asan_cstring_size;
11010 
11011 
11012 				logData = OSData::withValue(*header);
11013 				if (!logData) {
11014 					goto finish;
11015 				}
11016 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
11017 				if (!res) {
11018 					goto finish;
11019 				}
11020 				if (os_log_data) {
11021 					res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
11022 					if (!res) {
11023 						goto finish;
11024 					}
11025 				}
11026 				if (cstring_data) {
11027 					res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
11028 					if (!res) {
11029 						goto finish;
11030 					}
11031 				}
11032 				if (asan_cstring_data) {
11033 					res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size);
11034 					if (!res) {
11035 						goto finish;
11036 					}
11037 				}
11038 				result->setObject(kOSBundleLogStringsKey, logData.get());
11039 			}
11040 
11041 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
11042 				cpuTypeNumber = OSNumber::withNumber(
11043 					(uint64_t) kext_mach_hdr->cputype,
11044 					8 * sizeof(kext_mach_hdr->cputype));
11045 				if (!cpuTypeNumber) {
11046 					goto finish;
11047 				}
11048 				result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get());
11049 			}
11050 
11051 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
11052 				cpuSubtypeNumber = OSNumber::withNumber(
11053 					(uint64_t) kext_mach_hdr->cpusubtype,
11054 					8 * sizeof(kext_mach_hdr->cpusubtype));
11055 				if (!cpuSubtypeNumber) {
11056 					goto finish;
11057 				}
11058 				result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get());
11059 			}
11060 		} else {
11061 			if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
11062 				osLogDataHeaderRef *header;
11063 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
11064 				bool res;
11065 
11066 				header             = (osLogDataHeaderRef *) headerBytes;
11067 				header->version    = OS_LOG_HDR_VERSION;
11068 				header->sect_count = NUM_OS_LOG_SECTIONS;
11069 				header->sections[OS_LOG_SECT_IDX].sect_offset       = 0;
11070 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) 0;
11071 				header->sections[CSTRING_SECT_IDX].sect_offset      = 0;
11072 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) 0;
11073 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0;
11074 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) 0;
11075 
11076 				logData = OSData::withValue(*header);
11077 				if (!logData) {
11078 					goto finish;
11079 				}
11080 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
11081 				if (!res) {
11082 					goto finish;
11083 				}
11084 				result->setObject(kOSBundleLogStringsKey, logData.get());
11085 			}
11086 		}
11087 	}
11088 
11089 	/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
11090 	 */
11091 	result->setObject(kCFBundleIdentifierKey, bundleID.get());
11092 
11093 	/* CFBundlePackageType
11094 	 */
11095 	bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL;
11096 	if (bundleType) {
11097 		result->setObject(kCFBundlePackageTypeKey, bundleType);
11098 	}
11099 
11100 	/* CFBundleVersion.
11101 	 */
11102 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
11103 		versionString = OSDynamicCast(OSString,
11104 		    getPropertyForHostArch(kCFBundleVersionKey));
11105 		if (versionString) {
11106 			result->setObject(kCFBundleVersionKey, versionString);
11107 		}
11108 	}
11109 
11110 	/* OSBundleCompatibleVersion.
11111 	 */
11112 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
11113 		versionString = OSDynamicCast(OSString,
11114 		    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
11115 		if (versionString) {
11116 			result->setObject(kOSBundleCompatibleVersionKey, versionString);
11117 		}
11118 	}
11119 
11120 	/* Path.
11121 	 */
11122 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
11123 		if (path) {
11124 			result->setObject(kOSBundlePathKey, path.get());
11125 		}
11126 	}
11127 
11128 
11129 	/* OSBundleExecutablePath.
11130 	 */
11131 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
11132 		if (path && executableRelPath) {
11133 			uint32_t pathLength = path->getLength();         // gets incremented below
11134 
11135 			// +1 for slash, +1 for \0
11136 			executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
11137 
11138 			executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
11139 			    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);         // +1 for \0
11140 			if (!executablePathCString) {
11141 				goto finish;
11142 			}
11143 			strlcpy(executablePathCString, path->getCStringNoCopy(),
11144 			    executablePathCStringSize);
11145 			executablePathCString[pathLength++] = '/';
11146 			executablePathCString[pathLength++] = '\0';
11147 			strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
11148 			    executablePathCStringSize);
11149 
11150 			executablePathString = OSString::withCString(executablePathCString);
11151 
11152 			if (!executablePathString) {
11153 				goto finish;
11154 			}
11155 
11156 			result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
11157 		} else if (flags.builtin) {
11158 			result->setObject(kOSBundleExecutablePathKey, bundleID.get());
11159 		} else if (isDriverKit()) {
11160 			if (path) {
11161 				// +1 for slash, +1 for \0
11162 				uint32_t pathLength = path->getLength();
11163 				executablePathCStringSize = pathLength + 2;
11164 
11165 				executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
11166 				    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
11167 				if (!executablePathCString) {
11168 					goto finish;
11169 				}
11170 				strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
11171 				executablePathCString[pathLength++] = '/';
11172 				executablePathCString[pathLength++] = '\0';
11173 
11174 				executablePathString = OSString::withCString(executablePathCString);
11175 
11176 				if (!executablePathString) {
11177 					goto finish;
11178 				}
11179 
11180 				result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
11181 			}
11182 		}
11183 	}
11184 
11185 	/* UUID, if the kext has one.
11186 	 */
11187 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
11188 		uuid = copyUUID();
11189 		if (uuid) {
11190 			result->setObject(kOSBundleUUIDKey, uuid.get());
11191 		}
11192 	}
11193 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
11194 		uuid = copyTextUUID();
11195 		if (uuid) {
11196 			result->setObject(kOSBundleTextUUIDKey, uuid.get());
11197 		}
11198 	}
11199 
11200 	/*
11201 	 * Info.plist digest
11202 	 */
11203 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) {
11204 		OSData *digest;
11205 		digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL;
11206 		if (digest) {
11207 			result->setObject(kOSKextInfoPlistDigestKey, digest);
11208 		}
11209 	}
11210 
11211 	/*
11212 	 * Collection type
11213 	 */
11214 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) {
11215 		result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString()));
11216 	}
11217 
11218 	/*
11219 	 * Collection availability
11220 	 */
11221 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) {
11222 		result->setObject(kOSKextAuxKCAvailabilityKey,
11223 		    isLoadable() ? kOSBooleanTrue : kOSBooleanFalse);
11224 	}
11225 
11226 	/*
11227 	 * Allows user load
11228 	 */
11229 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) {
11230 		OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey));
11231 		if (allowUserLoad) {
11232 			result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad);
11233 		}
11234 	}
11235 
11236 	/*
11237 	 * Bundle Dependencies (OSBundleLibraries)
11238 	 */
11239 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) {
11240 		OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey));
11241 		if (libraries) {
11242 			result->setObject(kOSBundleLibrariesKey, libraries);
11243 		}
11244 	}
11245 
11246 	/*****
11247 	 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
11248 	 */
11249 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
11250 		result->setObject(kOSKernelResourceKey,
11251 		    isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
11252 	}
11253 
11254 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
11255 		result->setObject(kOSBundleIsInterfaceKey,
11256 		    isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
11257 	}
11258 
11259 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
11260 		result->setObject(kOSBundlePrelinkedKey,
11261 		    isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
11262 	}
11263 
11264 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
11265 		result->setObject(kOSBundleStartedKey,
11266 		    isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
11267 	}
11268 
11269 	/* LoadTag (Index).
11270 	 */
11271 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
11272 		OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
11273 		    /* numBits */ 8 * sizeof(loadTag));
11274 		if (!scratchNumber) {
11275 			goto finish;
11276 		}
11277 		result->setObject(kOSBundleLoadTagKey, scratchNumber.get());
11278 	}
11279 
11280 	/* LoadAddress, LoadSize.
11281 	 */
11282 	if (!infoKeys ||
11283 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
11284 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
11285 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
11286 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
11287 	    _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
11288 		bool is_dext = isDriverKit();
11289 		if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
11290 			/* These go to userspace via serialization, so we don't want any doubts
11291 			 * about their size.
11292 			 */
11293 			uint64_t    loadAddress     = 0;
11294 			uint32_t    loadSize        = 0;
11295 			uint32_t    wiredSize       = 0;
11296 			uint64_t    execLoadAddress = 0;
11297 			uint32_t    execLoadSize    = 0;
11298 
11299 			/* Interfaces always report 0 load address & size.
11300 			 * Just the way they roll.
11301 			 *
11302 			 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
11303 			 * xxx - shouldn't have one!
11304 			 */
11305 
11306 			if (flags.builtin || linkedExecutable) {
11307 				kernel_mach_header_t     *mh  = NULL;
11308 				kernel_segment_command_t *seg = NULL;
11309 
11310 				if (flags.builtin) {
11311 					loadAddress = kmod_info->address;
11312 					loadSize    = (uint32_t)kmod_info->size;
11313 				} else {
11314 					loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
11315 					loadSize = linkedExecutable->getLength();
11316 				}
11317 				mh = (kernel_mach_header_t *)loadAddress;
11318 				loadAddress = ml_static_unslide(loadAddress);
11319 
11320 				/* Walk through the kext, looking for the first executable
11321 				 * segment in case we were asked for its size/address.
11322 				 */
11323 				for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
11324 					if (seg->initprot & VM_PROT_EXECUTE) {
11325 						execLoadAddress = ml_static_unslide(seg->vmaddr);
11326 						execLoadSize = (uint32_t)seg->vmsize;
11327 						break;
11328 					}
11329 				}
11330 
11331 				/* If we have a kmod_info struct, calculated the wired size
11332 				 * from that. Otherwise it's the full load size.
11333 				 */
11334 				if (kmod_info) {
11335 					wiredSize = loadSize - (uint32_t)kmod_info->hdr_size;
11336 				} else {
11337 					wiredSize = loadSize;
11338 				}
11339 			} else if (is_dext) {
11340 				/*
11341 				 * DriverKit userspace executables do not have a kernel linkedExecutable,
11342 				 * so we "fake" their address range with the LoadTag.
11343 				 */
11344 				if (loadTag) {
11345 					loadAddress = execLoadAddress = loadTag;
11346 					loadSize = execLoadSize = 1;
11347 				}
11348 			}
11349 
11350 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
11351 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11352 					(unsigned long long)(loadAddress),
11353 					/* numBits */ 8 * sizeof(loadAddress));
11354 				if (!scratchNumber) {
11355 					goto finish;
11356 				}
11357 				result->setObject(kOSBundleLoadAddressKey, scratchNumber.get());
11358 			}
11359 			if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) {
11360 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
11361 				    && loadAddress && loadSize) {
11362 					void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary);
11363 					if (!baseAddress) {
11364 						goto finish;
11365 					}
11366 
11367 					OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11368 						(unsigned long long)ml_static_unslide((vm_offset_t)baseAddress),
11369 						/* numBits */ 8 * sizeof(loadAddress));
11370 					if (!scratchNumber) {
11371 						goto finish;
11372 					}
11373 					result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get());
11374 				}
11375 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
11376 				    && (this == sKernelKext) && gBuiltinKmodsCount) {
11377 					result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
11378 				}
11379 			}
11380 
11381 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
11382 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11383 					(unsigned long long)(execLoadAddress),
11384 					/* numBits */ 8 * sizeof(execLoadAddress));
11385 				if (!scratchNumber) {
11386 					goto finish;
11387 				}
11388 				result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get());
11389 			}
11390 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
11391 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11392 					(unsigned long long)(loadSize),
11393 					/* numBits */ 8 * sizeof(loadSize));
11394 				if (!scratchNumber) {
11395 					goto finish;
11396 				}
11397 				result->setObject(kOSBundleLoadSizeKey, scratchNumber.get());
11398 			}
11399 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
11400 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11401 					(unsigned long long)(execLoadSize),
11402 					/* numBits */ 8 * sizeof(execLoadSize));
11403 				if (!scratchNumber) {
11404 					goto finish;
11405 				}
11406 				result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get());
11407 			}
11408 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
11409 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11410 					(unsigned long long)(wiredSize),
11411 					/* numBits */ 8 * sizeof(wiredSize));
11412 				if (!scratchNumber) {
11413 					goto finish;
11414 				}
11415 				result->setObject(kOSBundleWiredSizeKey, scratchNumber.get());
11416 			}
11417 		}
11418 	}
11419 
11420 	/* OSBundleDependencies. In descending order for
11421 	 * easy compatibility with kextstat(8).
11422 	 */
11423 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
11424 		if ((count = getNumDependencies())) {
11425 			dependencyLoadTags = OSArray::withCapacity(count);
11426 			result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get());
11427 
11428 			i = count - 1;
11429 			do {
11430 				OSKext * dependency = OSDynamicCast(OSKext,
11431 				    dependencies->getObject(i));
11432 
11433 				if (!dependency) {
11434 					continue;
11435 				}
11436 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11437 					(unsigned long long)dependency->getLoadTag(),
11438 					/* numBits*/ 8 * sizeof(loadTag));
11439 				if (!scratchNumber) {
11440 					goto finish;
11441 				}
11442 				dependencyLoadTags->setObject(scratchNumber.get());
11443 			} while (i--);
11444 		}
11445 	}
11446 
11447 	/* OSBundleMetaClasses.
11448 	 */
11449 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
11450 		if (metaClasses && metaClasses->getCount()) {
11451 			metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get());
11452 			metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
11453 			if (!metaClassIterator || !metaClassInfo) {
11454 				goto finish;
11455 			}
11456 			result->setObject(kOSBundleClassesKey, metaClassInfo.get());
11457 
11458 			while ((thisMetaClass = OSDynamicCast(OSMetaClass,
11459 			    metaClassIterator->getNextObject()))) {
11460 				metaClassDict = OSDictionary::withCapacity(3);
11461 				if (!metaClassDict) {
11462 					goto finish;
11463 				}
11464 
11465 				metaClassName = OSString::withCString(thisMetaClass->getClassName());
11466 				if (thisMetaClass->getSuperClass()) {
11467 					superclassName = OSString::withCString(
11468 						thisMetaClass->getSuperClass()->getClassName());
11469 				}
11470 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
11471 				    8 * sizeof(unsigned int));
11472 
11473 				/* Bail if any of the essentials is missing. The root class lacks a superclass,
11474 				 * of course.
11475 				 */
11476 				if (!metaClassDict || !metaClassName || !scratchNumber) {
11477 					goto finish;
11478 				}
11479 
11480 				metaClassInfo->setObject(metaClassDict.get());
11481 				metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get());
11482 				if (superclassName) {
11483 					metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get());
11484 				}
11485 				metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get());
11486 			}
11487 		}
11488 	}
11489 
11490 	/* OSBundleRetainCount.
11491 	 */
11492 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
11493 		{
11494 			int kextRetainCount = getRetainCount() - 1;
11495 			if (isLoaded()) {
11496 				kextRetainCount--;
11497 			}
11498 			OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11499 				(int)kextRetainCount,
11500 				/* numBits*/ 8 * sizeof(int));
11501 			if (scratchNumber) {
11502 				result->setObject(kOSBundleRetainCountKey, scratchNumber.get());
11503 			}
11504 		}
11505 	}
11506 
11507 	success = true;
11508 
11509 finish:
11510 	if (executablePathCString) {
11511 		kfree_data(executablePathCString, executablePathCStringSize);
11512 	}
11513 	if (!success) {
11514 		result.reset();
11515 	}
11516 	return result;
11517 }
11518 
11519 /*********************************************************************
11520 *********************************************************************/
11521 /* static */
11522 bool
11523 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
11524 {
11525 	bool ok;
11526 	OSSharedPtr<OSKext> kext;
11527 
11528 	IORecursiveLockLock(sKextLock);
11529 	kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain);
11530 	IORecursiveLockUnlock(sKextLock);
11531 
11532 	if (!kext || !kext->path || !kext->userExecutableRelPath) {
11533 		return false;
11534 	}
11535 	snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
11536 	    kext->path->getCStringNoCopy(),
11537 	    kext->userExecutableRelPath->getCStringNoCopy());
11538 	ok = true;
11539 
11540 	return ok;
11541 }
11542 
11543 /*********************************************************************
11544 *********************************************************************/
11545 /* static */
11546 OSReturn
11547 OSKext::requestResource(
11548 	const char                    * kextIdentifierCString,
11549 	const char                    * resourceNameCString,
11550 	OSKextRequestResourceCallback   callback,
11551 	void                          * context,
11552 	OSKextRequestTag              * requestTagOut)
11553 {
11554 	OSReturn                        result = kOSReturnError;
11555 	OSSharedPtr<OSKext>             callbackKext;        // looked up
11556 
11557 	OSKextRequestTag   requestTag      = -1;
11558 	OSSharedPtr<OSNumber>           requestTagNum;
11559 	OSSharedPtr<OSDictionary>       requestDict;
11560 	OSSharedPtr<OSString>           kextIdentifier;
11561 	OSSharedPtr<OSString>           resourceName;
11562 
11563 	OSSharedPtr<OSDictionary>       callbackRecord;
11564 	OSSharedPtr<OSValueObject<OSKextRequestResourceCallback> > callbackWrapper;
11565 
11566 	OSSharedPtr<OSValueObject<void *> > contextWrapper;
11567 
11568 	IORecursiveLockLock(sKextLock);
11569 
11570 	if (requestTagOut) {
11571 		*requestTagOut = kOSKextRequestTagInvalid;
11572 	}
11573 
11574 	/* If requests to user space are disabled, don't go any further */
11575 	if (!sKernelRequestsEnabled) {
11576 		OSKextLog(/* kext */ NULL,
11577 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11578 		    "Can't request resource %s for %s - requests to user space are disabled.",
11579 		    resourceNameCString,
11580 		    kextIdentifierCString);
11581 		result = kOSKextReturnDisabled;
11582 		goto finish;
11583 	}
11584 
11585 	if (!kextIdentifierCString || !resourceNameCString || !callback) {
11586 		result = kOSKextReturnInvalidArgument;
11587 		goto finish;
11588 	}
11589 
11590 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
11591 	if (!callbackKext) {
11592 		OSKextLog(/* kext */ NULL,
11593 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11594 		    "Resource request has bad callback address.");
11595 		result = kOSKextReturnInvalidArgument;
11596 		goto finish;
11597 	}
11598 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
11599 		OSKextLog(/* kext */ NULL,
11600 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11601 		    "Resource request callback is in a kext that is not started.");
11602 		result = kOSKextReturnInvalidArgument;
11603 		goto finish;
11604 	}
11605 
11606 	/* Do not allow any new requests to be made on a kext that is unloading.
11607 	 */
11608 	if (callbackKext->flags.stopping) {
11609 		result = kOSKextReturnStopping;
11610 		goto finish;
11611 	}
11612 
11613 	/* If we're wrapped the next available request tag around to the negative
11614 	 * numbers, we can't service any more requests.
11615 	 */
11616 	if (sNextRequestTag == kOSKextRequestTagInvalid) {
11617 		OSKextLog(/* kext */ NULL,
11618 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11619 		    "No more request tags available; restart required.");
11620 		result = kOSKextReturnNoResources;
11621 		goto finish;
11622 	}
11623 	requestTag = sNextRequestTag++;
11624 
11625 	result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
11626 	    requestDict);
11627 	if (result != kOSReturnSuccess) {
11628 		goto finish;
11629 	}
11630 
11631 	kextIdentifier = OSString::withCString(kextIdentifierCString);
11632 	resourceName   = OSString::withCString(resourceNameCString);
11633 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
11634 	    8 * sizeof(requestTag));
11635 	if (!kextIdentifier ||
11636 	    !resourceName ||
11637 	    !requestTagNum ||
11638 	    !_OSKextSetRequestArgument(requestDict.get(),
11639 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) ||
11640 	    !_OSKextSetRequestArgument(requestDict.get(),
11641 	    kKextRequestArgumentNameKey, resourceName.get()) ||
11642 	    !_OSKextSetRequestArgument(requestDict.get(),
11643 	    kKextRequestArgumentRequestTagKey, requestTagNum.get())) {
11644 		result = kOSKextReturnNoMemory;
11645 		goto finish;
11646 	}
11647 
11648 	callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection());
11649 	if (!callbackRecord) {
11650 		result = kOSKextReturnNoMemory;
11651 		goto finish;
11652 	}
11653 	// we validate callback address at call time
11654 	callbackWrapper = OSValueObjectWithValue(callback);
11655 	if (context) {
11656 		contextWrapper = OSValueObjectWithValue(context);
11657 	}
11658 	if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
11659 	    kKextRequestArgumentCallbackKey, callbackWrapper.get())) {
11660 		result = kOSKextReturnNoMemory;
11661 		goto finish;
11662 	}
11663 
11664 	if (context) {
11665 		if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
11666 		    kKextRequestArgumentContextKey, contextWrapper.get())) {
11667 			result = kOSKextReturnNoMemory;
11668 			goto finish;
11669 		}
11670 	}
11671 
11672 	/* Only post the requests after all the other potential failure points
11673 	 * have been passed.
11674 	 */
11675 	if (!sKernelRequests->setObject(requestDict.get()) ||
11676 	    !sRequestCallbackRecords->setObject(callbackRecord.get())) {
11677 		result = kOSKextReturnNoMemory;
11678 		goto finish;
11679 	}
11680 
11681 	OSKext::pingIOKitDaemon();
11682 
11683 	result = kOSReturnSuccess;
11684 	if (requestTagOut) {
11685 		*requestTagOut = requestTag;
11686 	}
11687 
11688 finish:
11689 
11690 	/* If we didn't succeed, yank the request & callback
11691 	 * from their holding arrays.
11692 	 */
11693 	if (result != kOSReturnSuccess) {
11694 		unsigned int index;
11695 
11696 		index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0);
11697 		if (index != (unsigned int)-1) {
11698 			sKernelRequests->removeObject(index);
11699 		}
11700 		index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0);
11701 		if (index != (unsigned int)-1) {
11702 			sRequestCallbackRecords->removeObject(index);
11703 		}
11704 	}
11705 
11706 	OSKext::considerUnloads(/* rescheduleOnly? */ true);
11707 
11708 	IORecursiveLockUnlock(sKextLock);
11709 
11710 	return result;
11711 }
11712 
11713 OSReturn
11714 OSKext::requestDaemonLaunch(
11715 	OSString *kextIdentifier,
11716 	OSString *serverName,
11717 	OSNumber *serverTag,
11718 	IOUserServerCheckInToken * checkInToken)
11719 {
11720 	OSReturn       result        = kOSReturnError;
11721 	OSSharedPtr<OSDictionary> requestDict;
11722 
11723 	if (!kextIdentifier || !serverName || !serverTag || !checkInToken) {
11724 		return kOSKextReturnInvalidArgument;
11725 	}
11726 
11727 	IORecursiveLockLock(sKextLock);
11728 
11729 	OSKextLog(/* kext */ NULL,
11730 	    kOSKextLogDebugLevel |
11731 	    kOSKextLogGeneralFlag,
11732 	    "Requesting daemon launch for %s with serverName %s and tag %llu",
11733 	    kextIdentifier->getCStringNoCopy(),
11734 	    serverName->getCStringNoCopy(),
11735 	    serverTag->unsigned64BitValue()
11736 	    );
11737 
11738 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict);
11739 	if (result != kOSReturnSuccess) {
11740 		goto finish;
11741 	}
11742 
11743 	if (!_OSKextSetRequestArgument(requestDict.get(),
11744 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
11745 	    !_OSKextSetRequestArgument(requestDict.get(),
11746 	    kKextRequestArgumentDriverExtensionServerName, serverName) ||
11747 	    !_OSKextSetRequestArgument(requestDict.get(),
11748 	    kKextRequestArgumentDriverExtensionServerTag, serverTag) ||
11749 	    !_OSKextSetRequestArgument(requestDict.get(),
11750 	    kKextRequestArgumentCheckInToken, checkInToken)) {
11751 		result = kOSKextReturnNoMemory;
11752 		goto finish;
11753 	}
11754 
11755 	/* Only post the requests after all the other potential failure points
11756 	 * have been passed.
11757 	 */
11758 	if (!sKernelRequests->setObject(requestDict.get())) {
11759 		result = kOSKextReturnNoMemory;
11760 		goto finish;
11761 	}
11762 	OSKext::pingIOKitDaemon();
11763 
11764 	result = kOSReturnSuccess;
11765 finish:
11766 	IORecursiveLockUnlock(sKextLock);
11767 	return result;
11768 }
11769 
11770 /*********************************************************************
11771 * Assumes sKextLock is held.
11772 *********************************************************************/
11773 /* static */
11774 OSReturn
11775 OSKext::dequeueCallbackForRequestTag(
11776 	OSKextRequestTag    requestTag,
11777 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
11778 {
11779 	OSDictionary * callbackRecordOutRaw = NULL;
11780 	OSReturn result;
11781 
11782 	result = dequeueCallbackForRequestTag(requestTag,
11783 	    &callbackRecordOutRaw);
11784 
11785 	if (kOSReturnSuccess == result) {
11786 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
11787 	}
11788 
11789 	return result;
11790 }
11791 OSReturn
11792 OSKext::dequeueCallbackForRequestTag(
11793 	OSKextRequestTag    requestTag,
11794 	OSDictionary     ** callbackRecordOut)
11795 {
11796 	OSReturn   result = kOSReturnError;
11797 	OSSharedPtr<OSNumber> requestTagNum;
11798 
11799 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
11800 	    8 * sizeof(requestTag));
11801 	if (!requestTagNum) {
11802 		goto finish;
11803 	}
11804 
11805 	result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(),
11806 	    callbackRecordOut);
11807 
11808 finish:
11809 	return result;
11810 }
11811 
11812 /*********************************************************************
11813 * Assumes sKextLock is held.
11814 *********************************************************************/
11815 /* static */
11816 OSReturn
11817 OSKext::dequeueCallbackForRequestTag(
11818 	OSNumber     *    requestTagNum,
11819 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
11820 {
11821 	OSDictionary * callbackRecordOutRaw = NULL;
11822 	OSReturn result;
11823 
11824 	result = dequeueCallbackForRequestTag(requestTagNum,
11825 	    &callbackRecordOutRaw);
11826 
11827 	if (kOSReturnSuccess == result) {
11828 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
11829 	}
11830 
11831 	return result;
11832 }
11833 OSReturn
11834 OSKext::dequeueCallbackForRequestTag(
11835 	OSNumber     *    requestTagNum,
11836 	OSDictionary ** callbackRecordOut)
11837 {
11838 	OSReturn        result          = kOSKextReturnInvalidArgument;
11839 	OSDictionary  * callbackRecord  = NULL;        // retain if matched!
11840 	OSNumber      * callbackTagNum  = NULL;        // do not release
11841 	unsigned int    count, i;
11842 
11843 	result = kOSReturnError;
11844 	count = sRequestCallbackRecords->getCount();
11845 	for (i = 0; i < count; i++) {
11846 		callbackRecord = OSDynamicCast(OSDictionary,
11847 		    sRequestCallbackRecords->getObject(i));
11848 		if (!callbackRecord) {
11849 			goto finish;
11850 		}
11851 
11852 		/* If we don't find a tag, we basically have a leak here. Maybe
11853 		 * we should just remove it.
11854 		 */
11855 		callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
11856 			    callbackRecord, kKextRequestArgumentRequestTagKey));
11857 		if (!callbackTagNum) {
11858 			goto finish;
11859 		}
11860 
11861 		/* We could be even more paranoid and check that all the incoming
11862 		 * args match what's in the callback record.
11863 		 */
11864 		if (callbackTagNum->isEqualTo(requestTagNum)) {
11865 			if (callbackRecordOut) {
11866 				*callbackRecordOut = callbackRecord;
11867 				callbackRecord->retain();
11868 			}
11869 			sRequestCallbackRecords->removeObject(i);
11870 			result = kOSReturnSuccess;
11871 			goto finish;
11872 		}
11873 	}
11874 	result = kOSKextReturnNotFound;
11875 
11876 finish:
11877 	return result;
11878 }
11879 
11880 
11881 /*********************************************************************
11882 * Busy timeout triage
11883 *********************************************************************/
11884 /* static */
11885 bool
11886 OSKext::pendingIOKitDaemonRequests(void)
11887 {
11888 	return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
11889 }
11890 
11891 extern "C" int vm_enable_driverkit_shared_region;
11892 
11893 /*********************************************************************
11894 * Acquires and releases sKextLock
11895 *
11896 * This function is designed to be called exactly once on boot by
11897 * the IOKit management daemon, kernelmanagerd. It gathers all codeless
11898 * kext and dext personalities, and then attempts to map a System
11899 * (pageable) KC and an Auxiliary (aux) KC.
11900 *
11901 * Even if the pageable or aux KC fail to load - this function will
11902 * not allow a second call. This avoids security issues where
11903 * kernelmanagerd has been compromised or the pageable kc has been
11904 * tampered with and the attacker attempts to re-load a malicious
11905 * variant.
11906 *
11907 * Return: if a KC fails to load the return value will contain:
11908 *         kOSKextReturnKCLoadFailure. If the pageable KC fails,
11909 *         the return value will contain kOSKextReturnKCLoadFailureSystemKC.
11910 *         Similarly, if the aux kc load fails, the return value will
11911 *         contain kOSKextReturnKCLoadFailureAuxKC. The two values
11912 *         compose with each other and with kOSKextReturnKCLoadFailure.
11913 *********************************************************************/
11914 /* static */
11915 OSReturn
11916 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused)
11917 {
11918 	static bool daemon_ready = false;
11919 
11920 	OSReturn ret = kOSKextReturnInvalidArgument;
11921 	OSReturn kcerr = 0;
11922 	bool start_matching = false;
11923 
11924 	bool allow_fileset_load = !daemon_ready;
11925 #if !(defined(__x86_64__) || defined(__i386__))
11926 	/* never allow KCs full of kexts on non-x86 machines */
11927 	allow_fileset_load = false;
11928 #endif
11929 
11930 	/*
11931 	 * Change with 70582300
11932 	 */
11933 #if 0 || !defined(VM_MAPPED_KEXTS)
11934 	/*
11935 	 * On platforms that don't support the SystemKC or a file-backed
11936 	 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter
11937 	 * needs to be queried before we load any codeless kexts or release
11938 	 * any 3rd party kexts to run. On platforms that support a file-backed
11939 	 * AuxKC, this process is done via the kext audit mechanism.
11940 	 */
11941 
11942 	printf("KextLog: waiting for kext receipt to be queried.\n");
11943 	while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) {
11944 		IOSleep(30);
11945 	}
11946 #endif /* !VM_MAPPED_KEXTS */
11947 
11948 	/*
11949 	 * Get the args from the request. Right now we need the file
11950 	 * name for the pageable and the aux kext collection file sets.
11951 	 */
11952 	OSDictionary * requestArgs                = NULL;        // do not release
11953 	OSString     * pageable_filepath          = NULL;        // do not release
11954 	OSString     * aux_filepath               = NULL;        // do not release
11955 	OSArray      * codeless_kexts             = NULL;        // do not release
11956 	OSNumber     * enable_dk_shared_region    = NULL;        // do not release
11957 
11958 	kernel_mach_header_t *akc_mh              = NULL;
11959 
11960 	requestArgs = OSDynamicCast(OSDictionary,
11961 	    requestDict->getObject(kKextRequestArgumentsKey));
11962 
11963 	if (requestArgs == NULL) {
11964 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
11965 		    "KextLog: No arguments in plist for loading fileset kext\n");
11966 		printf("KextLog: No arguments in plist for loading fileset kext\n");
11967 		return ret;
11968 	}
11969 
11970 	ret = kOSKextReturnDisabled;
11971 
11972 	IORecursiveLockLock(sKextLock);
11973 
11974 	if (!sLoadEnabled) {
11975 		OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11976 		    "KextLog: Kext loading is disabled (attempt to load KCs).");
11977 		IORecursiveLockUnlock(sKextLock);
11978 		return ret;
11979 	}
11980 
11981 	pageable_filepath = OSDynamicCast(OSString,
11982 	    requestArgs->getObject(kKextRequestArgumentPageableKCFilename));
11983 
11984 	if (allow_fileset_load && pageable_filepath != NULL) {
11985 		printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy());
11986 
11987 		ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable);
11988 		if (ret) {
11989 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
11990 			    "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
11991 
11992 			printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
11993 			ret = kOSKextReturnKCLoadFailure;
11994 			kcerr |= kOSKextReturnKCLoadFailureSystemKC;
11995 			goto try_auxkc;
11996 		}
11997 		/*
11998 		 * Even if the AuxKC fails to load, we still want to send
11999 		 * the System KC personalities to the catalog for matching
12000 		 */
12001 		start_matching = true;
12002 	} else if (pageable_filepath != NULL) {
12003 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
12004 		    "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy());
12005 		ret = kOSKextReturnUnsupported;
12006 	}
12007 
12008 try_auxkc:
12009 	akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
12010 	if (akc_mh) {
12011 		/*
12012 		 * If we try to load a deferred AuxKC, then don't ever attempt
12013 		 * a filesystem map of a file
12014 		 */
12015 		allow_fileset_load = false;
12016 
12017 		/*
12018 		 * This function is only called once per boot, so we haven't
12019 		 * yet loaded an AuxKC. If we have registered the AuxKC mach
12020 		 * header, that means that the kext collection has been placed
12021 		 * in memory for us by the booter, and is waiting for us to
12022 		 * process it.  Grab the deferred XML plist of info
12023 		 * dictionaries and add all the kexts.
12024 		 */
12025 		OSSharedPtr<OSObject>  parsedXML;
12026 		OSSharedPtr<OSData>    loaded_kcUUID;
12027 		OSDictionary          *infoDict;
12028 		parsedXML = consumeDeferredKextCollection(KCKindAuxiliary);
12029 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
12030 #if !defined(VM_MAPPED_KEXTS)
12031 		/*
12032 		 * On platforms where we don't dynamically wire-down / page-in
12033 		 * kext memory, we need to maintain the invariant that if the
12034 		 * AuxKC in memory does not contain a kext receipt, then we
12035 		 * should not load any of the kexts.
12036 		 */
12037 		size_t receipt_sz = 0;
12038 		if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) {
12039 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12040 			    "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt");
12041 			ret = kOSKextReturnKCLoadFailure;
12042 			goto try_codeless;
12043 		}
12044 #endif
12045 		if (infoDict) {
12046 			bool added;
12047 			printf("KextLog: Adding kexts from in-memory AuxKC\n");
12048 			added = OSKext::addKextsFromKextCollection(akc_mh, infoDict,
12049 			    kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary);
12050 			if (!loaded_kcUUID) {
12051 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12052 				    "KextLog: WARNING: did not find UUID in deferred Aux KC!");
12053 			} else if (!added) {
12054 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12055 				    "KextLog: WARNING: Failed to load AuxKC from memory.");
12056 			}
12057 			/* only return success if the pageable load (above) was successful */
12058 			if (ret != kOSKextReturnKCLoadFailure) {
12059 				ret = kOSReturnSuccess;
12060 			}
12061 			/* the registration of the AuxKC parsed out the KC's UUID already */
12062 		} else {
12063 			if (daemon_ready) {
12064 				/*
12065 				 * Complain, but don't return an error if this isn't the first time the
12066 				 * IOKit daemon is checking in. If the daemon ever restarts, we will
12067 				 * hit this case because we've already consumed the deferred personalities.
12068 				 * We return success here so that a call to this function from a restarted
12069 				 * daemon with no codeless kexts will succeed.
12070 				 */
12071 				OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
12072 				    "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart");
12073 				if (ret != kOSKextReturnKCLoadFailure) {
12074 					ret = kOSReturnSuccess;
12075 				}
12076 			} else {
12077 				/* this is a real error case */
12078 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12079 				    "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary");
12080 				printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n");
12081 				ret = kOSKextReturnKCLoadFailure;
12082 				kcerr |= kOSKextReturnKCLoadFailureAuxKC;
12083 			}
12084 		}
12085 	}
12086 
12087 	aux_filepath = OSDynamicCast(OSString,
12088 	    requestArgs->getObject(kKextRequestArgumentAuxKCFilename));
12089 	if (allow_fileset_load && aux_filepath != NULL) {
12090 		printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy());
12091 
12092 		ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary);
12093 		if (ret) {
12094 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12095 			    "KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
12096 
12097 			printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
12098 			ret = kOSKextReturnKCLoadFailure;
12099 			kcerr |= kOSKextReturnKCLoadFailureAuxKC;
12100 			goto try_codeless;
12101 		}
12102 		start_matching = true;
12103 	} else if (aux_filepath != NULL) {
12104 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
12105 		    "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy());
12106 		if (ret != kOSKextReturnKCLoadFailure) {
12107 			ret = kOSKextReturnUnsupported;
12108 		}
12109 	}
12110 
12111 try_codeless:
12112 	/*
12113 	 * Load codeless kexts last so that there is no possibilty of a
12114 	 * codeless kext bundle ID preventing a kext in the system KC from
12115 	 * loading
12116 	 */
12117 	codeless_kexts = OSDynamicCast(OSArray,
12118 	    requestArgs->getObject(kKextRequestArgumentCodelessPersonalities));
12119 	if (codeless_kexts != NULL) {
12120 		uint32_t count = codeless_kexts->getCount();
12121 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12122 		    "KextLog: loading %d codeless kexts/dexts", count);
12123 		for (uint32_t i = 0; i < count; i++) {
12124 			OSDictionary *infoDict;
12125 			infoDict = OSDynamicCast(OSDictionary,
12126 			    codeless_kexts->getObject(i));
12127 			if (!infoDict) {
12128 				continue;
12129 			}
12130 			// instantiate a new kext, and don't hold a reference
12131 			// (the kext subsystem will hold one implicitly)
12132 			OSKext::withCodelessInfo(infoDict);
12133 		}
12134 		/* ignore errors that are not KC load failures */
12135 		if (ret != kOSKextReturnKCLoadFailure) {
12136 			ret = kOSReturnSuccess;
12137 		}
12138 		start_matching = true;
12139 	}
12140 
12141 	enable_dk_shared_region = OSDynamicCast(OSNumber,
12142 	    requestArgs->getObject(kKextRequestEnableDriverKitSharedRegionKey));
12143 	if (enable_dk_shared_region != NULL && enable_dk_shared_region->unsigned64BitValue() == 1) {
12144 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12145 		    "KextLog: Enabling DriverKit shared region.");
12146 		vm_enable_driverkit_shared_region = 1;
12147 	}
12148 
12149 	/* send personalities to the IOCatalog once */
12150 	if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) {
12151 		OSKext::sendAllKextPersonalitiesToCatalog(true);
12152 		/*
12153 		 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark
12154 		 * things as active and start all the delayed matching: the
12155 		 * dext and codeless kext personalities should have all been
12156 		 * delivered via this one call.
12157 		 */
12158 		if (!daemon_ready) {
12159 			OSKext::setIOKitDaemonActive();
12160 			OSKext::setDeferredLoadSucceeded(TRUE);
12161 			IOService::iokitDaemonLaunched();
12162 		}
12163 		if (sOSKextWasResetAfterUserspaceReboot) {
12164 			sOSKextWasResetAfterUserspaceReboot = false;
12165 			OSKext::setIOKitDaemonActive();
12166 			IOService::startDeferredMatches();
12167 		}
12168 	}
12169 
12170 	if (ret == kOSKextReturnKCLoadFailure) {
12171 		ret |= kcerr;
12172 	}
12173 
12174 	/*
12175 	 * Only allow this function to attempt to load the pageable and
12176 	 * aux KCs once per boot.
12177 	 */
12178 	daemon_ready = true;
12179 
12180 	IORecursiveLockUnlock(sKextLock);
12181 
12182 	return ret;
12183 }
12184 
12185 OSReturn
12186 OSKext::resetMutableSegments(void)
12187 {
12188 	kernel_segment_command_t *seg = NULL;
12189 	kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
12190 	u_int index = 0;
12191 	OSKextSavedMutableSegment *savedSegment = NULL;
12192 	uintptr_t kext_slide = PE_get_kc_slide(kc_type);
12193 	OSReturn err;
12194 
12195 	if (!savedMutableSegments) {
12196 		OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
12197 		    "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString());
12198 		err = kOSKextReturnInternalError;
12199 		goto finish;
12200 	}
12201 
12202 	for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) {
12203 		if (!segmentIsMutable(seg)) {
12204 			continue;
12205 		}
12206 		uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
12207 		uint64_t vmsize = seg->vmsize;
12208 		err = kOSKextReturnInternalError;
12209 		for (index = 0; index < savedMutableSegments->getCount(); index++) {
12210 			savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index));
12211 			assert(savedSegment);
12212 			if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) {
12213 				OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
12214 				    "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12215 				err = savedSegment->restoreContents(seg);
12216 				if (err != kOSReturnSuccess) {
12217 					panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12218 				}
12219 			}
12220 		}
12221 		if (err != kOSReturnSuccess) {
12222 			panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12223 		}
12224 	}
12225 	err = kOSReturnSuccess;
12226 finish:
12227 	return err;
12228 }
12229 
12230 
12231 /*********************************************************************
12232 * Assumes sKextLock is held.
12233 *********************************************************************/
12234 /* static */
12235 OSReturn
12236 OSKext::loadKCFileSet(
12237 	const char *filepath,
12238 	kc_kind_t   type)
12239 {
12240 #if VM_MAPPED_KEXTS
12241 	/* we only need to load filesets on systems that support VM_MAPPED kexts */
12242 	OSReturn err;
12243 	struct vnode *vp = NULL;
12244 	void *fileset_control;
12245 	off_t fsize;
12246 	bool pageable = (type == KCKindPageable);
12247 
12248 	if ((pageable && pageableKCloaded) ||
12249 	    (!pageable && auxKCloaded)) {
12250 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12251 		    "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux"));
12252 
12253 		return kOSKextReturnInvalidArgument;
12254 	}
12255 
12256 	/* Do not allow AuxKC to load if Pageable KC is not loaded */
12257 	if (!pageable && !pageableKCloaded) {
12258 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12259 		    "Trying to load the Aux KC without loading the Pageable KC");
12260 		return kOSKextReturnInvalidArgument;
12261 	}
12262 
12263 	fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize);
12264 
12265 	if (fileset_control == NULL) {
12266 		printf("Could not get memory control object for file %s", filepath);
12267 
12268 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12269 		    "Could not get memory control object for file %s", filepath);
12270 		return kOSKextReturnInvalidArgument;
12271 	}
12272 	if (vp == NULL) {
12273 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12274 		    "Could not find vnode for file %s", filepath);
12275 		return kOSKextReturnInvalidArgument;
12276 	}
12277 
12278 	kernel_mach_header_t *mh = NULL;
12279 	uintptr_t slide = 0;
12280 
12281 #if CONFIG_CSR
12282 	/*
12283 	 * When SIP is enabled, the KC we map must be SIP-protected
12284 	 */
12285 	if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) {
12286 		struct vnode_attr va;
12287 		int error;
12288 		VATTR_INIT(&va);
12289 		VATTR_WANTED(&va, va_flags);
12290 		error = vnode_getattr(vp, &va, vfs_context_current());
12291 		if (error) {
12292 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12293 			    "vnode_getattr(%s) failed (error=%d)", filepath, error);
12294 			err = kOSKextReturnInternalError;
12295 			goto finish;
12296 		}
12297 		if (!(va.va_flags & SF_RESTRICTED)) {
12298 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12299 			    "Path to KC '%s' is not SIP-protected", filepath);
12300 			err = kOSKextReturnInvalidArgument;
12301 			goto finish;
12302 		}
12303 	}
12304 #endif
12305 
12306 	err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL);
12307 	if (err) {
12308 		printf("KextLog: mapKCFileSet returned %d\n", err);
12309 
12310 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12311 		    "mapKCFileSet returned %d\n", err);
12312 
12313 		err = kOSKextReturnInvalidArgument;
12314 	}
12315 
12316 #if CONFIG_CSR
12317 finish:
12318 #endif
12319 	/* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */
12320 	assert(vp != NULL);
12321 	if (err == kOSReturnSuccess) {
12322 		PE_set_kc_vp(type, vp);
12323 		if (pageable) {
12324 			pageableKCloaded = true;
12325 		} else {
12326 			auxKCloaded = true;
12327 		}
12328 	} else {
12329 		vnode_put(vp);
12330 	}
12331 
12332 	return err;
12333 #else
12334 	(void)filepath;
12335 	(void)type;
12336 	return kOSKextReturnUnsupported;
12337 #endif // VM_MAPPED_KEXTS
12338 }
12339 
12340 #if defined(__x86_64__) || defined(__i386__)
12341 /*********************************************************************
12342 * Assumes sKextLock is held.
12343 *********************************************************************/
12344 /* static */
12345 OSReturn
12346 OSKext::mapKCFileSet(
12347 	void                 *control,
12348 	vm_size_t            fsize,
12349 	kernel_mach_header_t **mhp,
12350 	off_t                file_offset,
12351 	uintptr_t            *slidep,
12352 	bool                 pageable,
12353 	void                 *map_entry_list)
12354 {
12355 	bool fileset_load = false;
12356 	kern_return_t ret;
12357 	OSReturn err;
12358 	kernel_section_t *infoPlistSection = NULL;
12359 	OSDictionary *infoDict = NULL;
12360 
12361 	OSSharedPtr<OSObject> parsedXML;
12362 	OSSharedPtr<OSString> errorString;
12363 	OSSharedPtr<OSData> loaded_kcUUID;
12364 
12365 	/* Check if initial load for file set */
12366 	if (*mhp == NULL) {
12367 		fileset_load = true;
12368 
12369 		/* Get a page aligned address from kext map to map the file */
12370 		vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize);
12371 		if (pagealigned_addr == 0) {
12372 			return kOSKextReturnNoMemory;
12373 		}
12374 
12375 		*mhp = (kernel_mach_header_t *)pagealigned_addr;
12376 
12377 		/* Allocate memory for bailout mechanism */
12378 		map_entry_list = allocate_kcfileset_map_entry_list();
12379 		if (map_entry_list == NULL) {
12380 			return kOSKextReturnNoMemory;
12381 		}
12382 	}
12383 
12384 	uintptr_t *slideptr = fileset_load ? slidep : NULL;
12385 	err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list);
12386 	/* mhp and slideptr are updated by mapKCTextSegment */
12387 	if (err) {
12388 		if (fileset_load) {
12389 			deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12390 		}
12391 		return err;
12392 	}
12393 
12394 	/* Initialize the kc header globals */
12395 	if (fileset_load) {
12396 		if (pageable) {
12397 			PE_set_kc_header(KCKindPageable, *mhp, *slidep);
12398 		} else {
12399 			PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep);
12400 		}
12401 	}
12402 
12403 	/* Iterate through all the segments and map necessary segments */
12404 	struct load_command *lcp = (struct load_command *) (*mhp + 1);
12405 	for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) {
12406 		vm_map_offset_t start;
12407 		kernel_mach_header_t *k_mh = NULL;
12408 		kernel_segment_command_t * seg = NULL;
12409 		struct fileset_entry_command *fse = NULL;
12410 
12411 		if (lcp->cmd == LC_SEGMENT_KERNEL) {
12412 			seg = (kernel_segment_command_t *)lcp;
12413 			start = ((uintptr_t)(seg->vmaddr)) + *slidep;
12414 		} else if (lcp->cmd == LC_FILESET_ENTRY) {
12415 			fse = (struct fileset_entry_command *)lcp;
12416 			k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep);
12417 
12418 			/* Map the segments of the mach-o binary */
12419 			err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list);
12420 			if (err) {
12421 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12422 				return kOSKextReturnInvalidArgument;
12423 			}
12424 			continue;
12425 		} else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) {
12426 			/* Check if the Aux KC is built pageable style */
12427 			if (!pageable && !fileset_load && !auxKCloaded) {
12428 				resetAuxKCSegmentOnUnload = true;
12429 			}
12430 			continue;
12431 		} else {
12432 			continue;
12433 		}
12434 
12435 		if (fileset_load) {
12436 			if (seg->vmsize == 0) {
12437 				continue;
12438 			}
12439 
12440 			/* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */
12441 			if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 &&
12442 			    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 &&
12443 			    strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 &&
12444 			    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) {
12445 				continue;
12446 			}
12447 		} else {
12448 			if (seg->vmsize == 0) {
12449 				continue;
12450 			}
12451 
12452 			/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
12453 			if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
12454 			    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
12455 			    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
12456 				continue;
12457 			}
12458 		}
12459 
12460 		ret = vm_map_kcfileset_segment(
12461 			&start, seg->vmsize,
12462 			(memory_object_control_t)control, seg->fileoff, seg->maxprot);
12463 
12464 		if (ret != KERN_SUCCESS) {
12465 			if (fileset_load) {
12466 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12467 			}
12468 			return kOSKextReturnInvalidArgument;
12469 		}
12470 		add_kcfileset_map_entry(map_entry_list, start, seg->vmsize);
12471 	}
12472 
12473 	/* Return if regular mach-o */
12474 	if (!fileset_load) {
12475 		return 0;
12476 	}
12477 
12478 	/*
12479 	 * Fixup for the Pageable KC and the Aux KC is done by
12480 	 * i386_slide_kext_collection_mh_addrs, but it differs in
12481 	 * following ways:
12482 	 *
12483 	 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands.
12484 	 * The fixup of kext segments and kext load commands are done at kext
12485 	 * load time by calling i386_slide_individual_kext.
12486 	 *
12487 	 * AuxKC old style: Fixup all the segments and all the load commands.
12488 	 *
12489 	 * AuxKC pageable style: Same as the Pageable KC.
12490 	 */
12491 	bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false));
12492 	ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header);
12493 	if (ret != KERN_SUCCESS) {
12494 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12495 		return kOSKextReturnInvalidArgument;
12496 	}
12497 
12498 	/* Get the prelink info dictionary */
12499 	infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection);
12500 	parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
12501 	if (parsedXML) {
12502 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
12503 	}
12504 
12505 	if (!infoDict) {
12506 		const char *errorCString = "(unknown error)";
12507 
12508 		if (errorString && errorString->getCStringNoCopy()) {
12509 			errorCString = errorString->getCStringNoCopy();
12510 		} else if (parsedXML) {
12511 			errorCString = "not a dictionary";
12512 		}
12513 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12514 		    "Error unserializing kext info plist section: %s.", errorCString);
12515 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12516 		return kOSKextReturnInvalidArgument;
12517 	}
12518 
12519 	/* Validate that the Kext Collection is prelinked to the loaded KC */
12520 	err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary);
12521 	if (err) {
12522 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12523 		return kOSKextReturnInvalidArgument;
12524 	}
12525 
12526 	/* Set Protection of Segments */
12527 	OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary);
12528 
12529 	OSKext::addKextsFromKextCollection(*mhp,
12530 	    infoDict, kPrelinkTextSegment,
12531 	    loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary);
12532 
12533 	/* Copy in the KC UUID */
12534 	if (!loaded_kcUUID) {
12535 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12536 		    "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux");
12537 	} else if (pageable) {
12538 		pageablekc_uuid_valid = TRUE;
12539 		memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
12540 		uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string);
12541 	} else {
12542 		auxkc_uuid_valid = TRUE;
12543 		memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
12544 		uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
12545 	}
12546 
12547 	deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable);
12548 
12549 	return 0;
12550 }
12551 
12552 /*********************************************************************
12553 * Assumes sKextLock is held.
12554 *********************************************************************/
12555 /* static */
12556 OSReturn
12557 OSKext::mapKCTextSegment(
12558 	void                 *control,
12559 	kernel_mach_header_t **mhp,
12560 	off_t                file_offset,
12561 	uintptr_t            *slidep,
12562 	void                 *map_entry_list)
12563 {
12564 	kern_return_t ret;
12565 	vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t),
12566 	    PAGE_MASK);
12567 	vm_map_offset_t load_command_map_size = 0;
12568 	kernel_mach_header_t *base_mh = *mhp;
12569 
12570 	/* Map the mach header at start of fileset for now (vmaddr = 0) */
12571 	ret = vm_map_kcfileset_segment(
12572 		(vm_map_offset_t *)&base_mh, mach_header_map_size,
12573 		(memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE));
12574 
12575 	if (ret != KERN_SUCCESS) {
12576 		printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret);
12577 
12578 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12579 		    "Failed to map mach header of kc fileset with error %d", ret);
12580 		return kOSKextReturnInvalidArgument;
12581 	}
12582 
12583 	if (slidep) {
12584 		/* Verify that it's an MH_FILESET */
12585 		if (base_mh->filetype != MH_FILESET) {
12586 			printf("Kext Log: mapKCTextSegment mach header filetype"
12587 			    " is not an MH_FILESET, it is %x", base_mh->filetype);
12588 
12589 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12590 			    "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype);
12591 
12592 			/* Unmap the mach header */
12593 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12594 			return kOSKextReturnInvalidArgument;
12595 		}
12596 	}
12597 
12598 	/* Map the remaining pages of load commands */
12599 	if (base_mh->sizeofcmds > mach_header_map_size) {
12600 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
12601 		load_command_map_size = base_mh->sizeofcmds - mach_header_map_size;
12602 
12603 		/* Map the load commands */
12604 		ret = vm_map_kcfileset_segment(
12605 			&load_command_addr, load_command_map_size,
12606 			(memory_object_control_t)control, file_offset + mach_header_map_size,
12607 			(VM_PROT_READ | VM_PROT_WRITE));
12608 
12609 		if (ret != KERN_SUCCESS) {
12610 			printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret);
12611 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12612 			    "Failed to map load commands of kc fileset with error %d", ret);
12613 
12614 			/* Unmap the mach header */
12615 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12616 			return kOSKextReturnInvalidArgument;
12617 		}
12618 	}
12619 
12620 	kernel_segment_command_t *text_seg;
12621 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT);
12622 
12623 	/* Calculate the slide and vm addr of mach header */
12624 	if (slidep) {
12625 		*mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr);
12626 		*slidep = ((uintptr_t)*mhp) - text_seg->vmaddr;
12627 	}
12628 
12629 	/* Cache the text segment size and file offset before unmapping */
12630 	vm_map_offset_t text_segment_size = text_seg->vmsize;
12631 	vm_object_offset_t text_segment_fileoff = text_seg->fileoff;
12632 	vm_prot_t text_maxprot = text_seg->maxprot;
12633 
12634 	/* Unmap the first page and loadcommands and map the text segment */
12635 	ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12636 	assert(ret == KERN_SUCCESS);
12637 
12638 	if (load_command_map_size) {
12639 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
12640 		ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size);
12641 		assert(ret == KERN_SUCCESS);
12642 	}
12643 
12644 	/* Map the text segment at actual vm addr specified in fileset */
12645 	ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size,
12646 	    (memory_object_control_t)control, text_segment_fileoff, text_maxprot);
12647 	if (ret != KERN_SUCCESS) {
12648 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12649 		    "Failed to map Text segment of kc fileset with error %d", ret);
12650 		return kOSKextReturnInvalidArgument;
12651 	}
12652 
12653 	add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size);
12654 	return 0;
12655 }
12656 
12657 /*********************************************************************
12658 * Assumes sKextLock is held.
12659 *********************************************************************/
12660 /* static */
12661 OSReturn
12662 OSKext::protectKCFileSet(
12663 	kernel_mach_header_t *mh,
12664 	kc_kind_t            type)
12665 {
12666 	vm_map_t                    kext_map        = g_kext_map;
12667 	kernel_segment_command_t  * seg             = NULL;
12668 	vm_map_offset_t             start           = 0;
12669 	vm_map_offset_t             end             = 0;
12670 	OSReturn                    ret             = 0;
12671 
12672 	/* Set VM permissions */
12673 	seg = firstsegfromheader((kernel_mach_header_t *)mh);
12674 	while (seg) {
12675 		start = round_page(seg->vmaddr);
12676 		end = trunc_page(seg->vmaddr + seg->vmsize);
12677 
12678 		/*
12679 		 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS
12680 		 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT
12681 		 * for the Aux KC as well.
12682 		 */
12683 		if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 ||
12684 		    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 ||
12685 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 ||
12686 		    (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload &&
12687 		    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) {
12688 			ret = OSKext_protect((kernel_mach_header_t *)mh,
12689 			    kext_map, start, end, seg->maxprot, TRUE, type);
12690 			if (ret != KERN_SUCCESS) {
12691 				printf("OSKext protect failed with error %d", ret);
12692 				return kOSKextReturnInvalidArgument;
12693 			}
12694 
12695 			ret = OSKext_protect((kernel_mach_header_t *)mh,
12696 			    kext_map, start, end, seg->initprot, FALSE, type);
12697 			if (ret != KERN_SUCCESS) {
12698 				printf("OSKext protect failed with error %d", ret);
12699 				return kOSKextReturnInvalidArgument;
12700 			}
12701 
12702 			ret = OSKext_wire((kernel_mach_header_t *)mh,
12703 			    kext_map, start, end, seg->initprot, FALSE, type);
12704 			if (ret != KERN_SUCCESS) {
12705 				printf("OSKext wire failed with error %d", ret);
12706 				return kOSKextReturnInvalidArgument;
12707 			}
12708 		}
12709 
12710 		seg = nextsegfromheader((kernel_mach_header_t *) mh, seg);
12711 	}
12712 
12713 	return 0;
12714 }
12715 
12716 /*********************************************************************
12717 * Assumes sKextLock is held.
12718 *********************************************************************/
12719 /* static */
12720 void
12721 OSKext::freeKCFileSetcontrol(void)
12722 {
12723 	PE_reset_all_kc_vp();
12724 }
12725 
12726 /*********************************************************************
12727 * Assumes sKextLock is held.
12728 *
12729 * resetKCFileSetSegments: Kext start function expects data segment to
12730 * be pristine on every load, unmap the dirty segments on unload and
12731 * remap them from FileSet on disk. Remap all segments of kext since
12732 * fixups are done per kext and not per segment.
12733 *********************************************************************/
12734 OSReturn
12735 OSKext::resetKCFileSetSegments(void)
12736 {
12737 	kernel_segment_command_t *seg = NULL;
12738 	kernel_segment_command_t *text_seg;
12739 	uint32_t text_fileoff;
12740 	kernel_mach_header_t *k_mh = NULL;
12741 	uintptr_t slide;
12742 	struct vnode *vp = NULL;
12743 	void *fileset_control = NULL;
12744 	bool pageable = (kc_type == KCKindPageable);
12745 	OSReturn err;
12746 	kern_return_t kr;
12747 
12748 	/* Check the vnode reference is still available */
12749 	vp = (struct vnode *)PE_get_kc_vp(kc_type);
12750 	if (vp == NULL) {
12751 		OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
12752 		    "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString());
12753 		return kOSKextReturnInternalError;
12754 	}
12755 
12756 	fileset_control = ubc_getobject(vp, 0);
12757 	assert(fileset_control != NULL);
12758 
12759 	OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
12760 	    "Kext %s resetting all segments", getIdentifierCString());
12761 
12762 	k_mh = (kernel_mach_header_t *)kmod_info->address;
12763 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT);
12764 	text_fileoff = text_seg->fileoff;
12765 	slide = PE_get_kc_slide(kc_type);
12766 
12767 	seg = firstsegfromheader((kernel_mach_header_t *)k_mh);
12768 	while (seg) {
12769 		if (seg->vmsize == 0) {
12770 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12771 			continue;
12772 		}
12773 
12774 		/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
12775 		if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
12776 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
12777 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
12778 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12779 			continue;
12780 		}
12781 
12782 		kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize);
12783 		assert(kr == KERN_SUCCESS);
12784 		seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12785 	}
12786 
12787 	/* Unmap the text segment */
12788 	kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize);
12789 	assert(kr == KERN_SUCCESS);
12790 
12791 	/* Map all the segments of the kext */
12792 	err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL);
12793 	if (err) {
12794 		panic("Could not reset segments of a mapped kext, error %x", err);
12795 	}
12796 
12797 	/* Update address in kmod_info, since it has been reset */
12798 	if (kmod_info->address) {
12799 		kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide);
12800 	}
12801 
12802 	return 0;
12803 }
12804 
12805 /*********************************************************************
12806 * Mechanism to track all segment mapping while mapping KC fileset.
12807 *********************************************************************/
12808 
12809 struct kcfileset_map_entry {
12810 	vm_map_offset_t me_start;
12811 	vm_map_offset_t me_size;
12812 };
12813 
12814 struct kcfileset_map_entry_list {
12815 	int                        kme_list_count;
12816 	int                        kme_list_index;
12817 	struct kcfileset_map_entry kme_list[];
12818 };
12819 
12820 #define KCFILESET_MAP_ENTRY_MAX (16380)
12821 
12822 static void *
12823 allocate_kcfileset_map_entry_list(void)
12824 {
12825 	struct kcfileset_map_entry_list *entry_list;
12826 
12827 	entry_list = kalloc_type(struct kcfileset_map_entry_list,
12828 	    struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO);
12829 
12830 	entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX;
12831 	entry_list->kme_list_index = 0;
12832 	return entry_list;
12833 }
12834 
12835 static void
12836 add_kcfileset_map_entry(
12837 	void            *map_entry_list,
12838 	vm_map_offset_t start,
12839 	vm_map_offset_t size)
12840 {
12841 	if (map_entry_list == NULL) {
12842 		return;
12843 	}
12844 
12845 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
12846 
12847 	if (entry_list->kme_list_index >= entry_list->kme_list_count) {
12848 		panic("Ran out of map kc fileset list");
12849 	}
12850 
12851 	entry_list->kme_list[entry_list->kme_list_index].me_start = start;
12852 	entry_list->kme_list[entry_list->kme_list_index].me_size = size;
12853 
12854 	entry_list->kme_list_index++;
12855 }
12856 
12857 static void
12858 deallocate_kcfileset_map_entry_list_and_unmap_entries(
12859 	void      *map_entry_list,
12860 	boolean_t unmap_entries,
12861 	bool      pageable)
12862 {
12863 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
12864 
12865 	if (unmap_entries) {
12866 		for (int i = 0; i < entry_list->kme_list_index; i++) {
12867 			kern_return_t ret;
12868 			ret = vm_unmap_kcfileset_segment(
12869 				&(entry_list->kme_list[i].me_start),
12870 				entry_list->kme_list[i].me_size);
12871 			assert(ret == KERN_SUCCESS);
12872 		}
12873 
12874 		PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary);
12875 	}
12876 
12877 	kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry,
12878 	    KCFILESET_MAP_ENTRY_MAX, entry_list);
12879 }
12880 
12881 /*********************************************************************
12882 * Mechanism to map kext segment.
12883 *********************************************************************/
12884 
12885 kern_return_t
12886 vm_map_kcfileset_segment(
12887 	vm_map_offset_t    *start,
12888 	vm_map_offset_t    size,
12889 	void               *control,
12890 	vm_object_offset_t fileoffset,
12891 	vm_prot_t          max_prot)
12892 {
12893 	vm_map_kernel_flags_t vmk_flags = VM_MAP_KERNEL_FLAGS_NONE;
12894 	vmk_flags.vmkf_no_copy_on_read = 1;
12895 	vmk_flags.vmkf_cs_enforcement = 0;
12896 	vmk_flags.vmkf_cs_enforcement_override = 1;
12897 	kern_return_t ret;
12898 
12899 	/* Add Write to max prot to allow fixups */
12900 	max_prot = max_prot | VM_PROT_WRITE;
12901 
12902 	/*
12903 	 * Map the segments from file as COPY mappings to
12904 	 * make sure changes on disk to the file does not affect
12905 	 * mapped segments.
12906 	 */
12907 	ret = vm_map_enter_mem_object_control(
12908 		g_kext_map,
12909 		start,
12910 		size,
12911 		(mach_vm_offset_t)0,
12912 		VM_FLAGS_FIXED,
12913 		vmk_flags,
12914 		VM_KERN_MEMORY_OSKEXT,
12915 		(memory_object_control_t)control,
12916 		fileoffset,
12917 		TRUE,         /* copy */
12918 		(VM_PROT_READ | VM_PROT_WRITE), max_prot,
12919 		VM_INHERIT_NONE);
12920 
12921 	return ret;
12922 }
12923 
12924 kern_return_t
12925 vm_unmap_kcfileset_segment(
12926 	vm_map_offset_t    *start,
12927 	vm_map_offset_t    size)
12928 {
12929 	return mach_vm_deallocate(g_kext_map, *start, size);
12930 }
12931 
12932 #endif //(__x86_64__) || defined(__i386__)
12933 
12934 /*********************************************************************
12935 * Assumes sKextLock is held.
12936 *********************************************************************/
12937 /* static */
12938 OSReturn
12939 OSKext::validateKCFileSetUUID(
12940 	OSDictionary         *infoDict,
12941 	kc_kind_t            type)
12942 {
12943 	OSReturn ret           = kOSReturnSuccess;
12944 
12945 	if (!kernelcache_uuid_valid) {
12946 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12947 		    "validateKCFileSetUUID Boot KC UUID was not set at boot.");
12948 		ret = kOSKextReturnInvalidArgument;
12949 		goto finish;
12950 	}
12951 	ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey);
12952 	if (ret != 0) {
12953 		goto finish;
12954 	}
12955 
12956 #if defined(__x86_64__) || defined(__i386__)
12957 	/* Check if the Aux KC is prelinked to correct Pageable KC */
12958 	if (type == KCKindAuxiliary) {
12959 		if (!pageablekc_uuid_valid) {
12960 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12961 			    "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC.");
12962 			ret = kOSKextReturnInvalidArgument;
12963 			goto finish;
12964 		}
12965 		ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey);
12966 		if (ret != 0) {
12967 			goto finish;
12968 		}
12969 	}
12970 #endif //(__x86_64__) || defined(__i386__)
12971 
12972 	printf("KextLog: Collection UUID matches with loaded KCs.\n");
12973 finish:
12974 	return ret;
12975 }
12976 
12977 /*********************************************************************
12978 * Assumes sKextLock is held.
12979 *********************************************************************/
12980 /* static */
12981 OSReturn
12982 OSKext::validateKCUUIDfromPrelinkInfo(
12983 	uuid_t               *loaded_kcuuid,
12984 	kc_kind_t             type,
12985 	OSDictionary         *infoDict,
12986 	const char           *uuid_key)
12987 {
12988 	/* extract the UUID from the dictionary */
12989 	OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key));
12990 	if (!prelinkinfoKCUUID) {
12991 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12992 		    "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key);
12993 		return kOSKextReturnInvalidArgument;
12994 	}
12995 
12996 	if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) {
12997 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12998 		    "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength());
12999 		return kOSKextReturnInvalidArgument;
13000 	}
13001 
13002 	if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(),
13003 	    prelinkinfoKCUUID->getLength())) {
13004 		OSData       *info_dict_uuid;
13005 		uuid_string_t info_dict_uuid_str = {};
13006 		uuid_string_t expected_uuid_str = {};
13007 		uuid_string_t given_uuid_str = {};
13008 		uuid_t        given_uuid;
13009 
13010 		/* extract the KC UUID from the dictionary */
13011 		info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
13012 		if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) {
13013 			uuid_t tmp_uuid;
13014 			memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid));
13015 			uuid_unparse(tmp_uuid, info_dict_uuid_str);
13016 		}
13017 
13018 		uuid_unparse(*loaded_kcuuid, expected_uuid_str);
13019 		memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid));
13020 		uuid_unparse(given_uuid, given_uuid_str);
13021 
13022 		printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
13023 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
13024 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13025 		    "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
13026 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
13027 		if (type == KCKindPageable && sPanicOnKCMismatch) {
13028 			panic("System KC UUID %s linked against %s, but %s is loaded",
13029 			    info_dict_uuid_str, given_uuid_str, expected_uuid_str);
13030 		}
13031 		return kOSKextReturnInvalidArgument;
13032 	}
13033 
13034 	return 0;
13035 }
13036 
13037 /*********************************************************************
13038 * Assumes sKextLock is held.
13039 *********************************************************************/
13040 /* static */
13041 OSReturn
13042 OSKext::dispatchResource(OSDictionary * requestDict)
13043 {
13044 	OSReturn                        result          = kOSReturnError;
13045 	OSSharedPtr<OSDictionary>       callbackRecord;
13046 	OSNumber                      * requestTag      = NULL;        // do not release
13047 	OSNumber                      * requestResult   = NULL;        // do not release
13048 	OSData                        * dataObj         = NULL;        // do not release
13049 	uint32_t                        dataLength      = 0;
13050 	const void                    * dataPtr         = NULL;        // do not free
13051 	OSValueObject<OSKextRequestResourceCallback> * callbackWrapper = nullptr; // do not release
13052 	OSKextRequestResourceCallback   callback        = NULL;
13053 	OSValueObject<void *>         * contextWrapper  = nullptr;     // do not release
13054 	void                          * context         = NULL;        // do not free
13055 	OSSharedPtr<OSKext>             callbackKext;
13056 
13057 	/* Get the args from the request. Right now we need the tag
13058 	 * to look up the callback record, and the result for invoking the callback.
13059 	 */
13060 	requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
13061 	    kKextRequestArgumentRequestTagKey));
13062 	requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
13063 	    kKextRequestArgumentResultKey));
13064 	if (!requestTag || !requestResult) {
13065 		result = kOSKextReturnInvalidArgument;
13066 		goto finish;
13067 	}
13068 
13069 	/* Look for a callback record matching this request's tag.
13070 	 */
13071 	result = dequeueCallbackForRequestTag(requestTag, callbackRecord);
13072 	if (result != kOSReturnSuccess) {
13073 		goto finish;
13074 	}
13075 
13076 	/*****
13077 	 * Get the context pointer of the callback record (if there is one).
13078 	 */
13079 	contextWrapper = OSDynamicCast(OSValueObject<void *>, _OSKextGetRequestArgument(
13080 		    callbackRecord.get(), kKextRequestArgumentContextKey));
13081 	context = _OSKextExtractPointer(contextWrapper);
13082 	if (contextWrapper && !context) {
13083 		goto finish;
13084 	}
13085 
13086 	callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
13087 	    _OSKextGetRequestArgument(callbackRecord.get(),
13088 	    kKextRequestArgumentCallbackKey));
13089 	callback = _OSKextExtractCallbackPointer(callbackWrapper);
13090 	if (!callback) {
13091 		goto finish;
13092 	}
13093 
13094 	/* Check for a data obj. We might not have one and that's ok, that means
13095 	 * we didn't find the requested resource, and we still have to tell the
13096 	 * caller that via the callback.
13097 	 */
13098 	dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
13099 	    kKextRequestArgumentValueKey));
13100 	if (dataObj) {
13101 		dataPtr = dataObj->getBytesNoCopy();
13102 		dataLength = dataObj->getLength();
13103 	}
13104 
13105 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
13106 	if (!callbackKext) {
13107 		OSKextLog(/* kext */ NULL,
13108 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13109 		    "Can't invoke callback for resource request; ");
13110 		goto finish;
13111 	}
13112 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
13113 		OSKextLog(/* kext */ NULL,
13114 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13115 		    "Can't invoke kext resource callback; ");
13116 		goto finish;
13117 	}
13118 
13119 	(void)callback(requestTag->unsigned32BitValue(),
13120 	    (OSReturn)requestResult->unsigned32BitValue(),
13121 	    dataPtr, dataLength, context);
13122 
13123 	result = kOSReturnSuccess;
13124 
13125 finish:
13126 	return result;
13127 }
13128 
13129 /*********************************************************************
13130 * Assumes sKextLock is held.
13131 *********************************************************************/
13132 /* static */
13133 OSReturn
13134 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict)
13135 {
13136 	OSSharedPtr<OSDictionary> missingIDs;
13137 	OSArray *bundleIDList     = NULL; // do not release
13138 
13139 	bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
13140 		    requestDict, kKextRequestArgumentMissingBundleIDs));
13141 	if (!bundleIDList) {
13142 		return kOSKextReturnInvalidArgument;
13143 	}
13144 
13145 	missingIDs = OSDictionary::withCapacity(bundleIDList->getCount());
13146 	if (!missingIDs) {
13147 		return kOSKextReturnNoMemory;
13148 	}
13149 
13150 	uint32_t count, i;
13151 	count = bundleIDList->getCount();
13152 	for (i = 0; i < count; i++) {
13153 		OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i));
13154 		if (thisID) {
13155 			missingIDs->setObject(thisID, kOSBooleanFalse);
13156 		}
13157 	}
13158 
13159 	sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain);
13160 
13161 	return kOSReturnSuccess;
13162 }
13163 
13164 /*********************************************************************
13165 * Assumes sKextLock is held.
13166 *********************************************************************/
13167 /* static */
13168 OSReturn
13169 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict)
13170 {
13171 	bool loadable = true;
13172 	if (!kextIdentifier) {
13173 		return kOSKextReturnInvalidArgument;
13174 	}
13175 
13176 	if (requestDict) {
13177 		OSBoolean *loadableArg;
13178 		loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
13179 			    requestDict, kKextRequestArgumentBundleAvailability));
13180 		/* If we find the "Bundle Available" arg, and it's false, then
13181 		 * mark the bundle ID as _not_ loadable
13182 		 */
13183 		if (loadableArg && !loadableArg->getValue()) {
13184 			loadable = false;
13185 		}
13186 	}
13187 
13188 	if (!sNonLoadableKextsByID) {
13189 		sNonLoadableKextsByID = OSDictionary::withCapacity(1);
13190 	}
13191 
13192 	sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable));
13193 
13194 	OSKextLog(/* kext */ NULL,
13195 	    kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13196 	    "KextLog: AuxKC bundle %s marked as %s",
13197 	    kextIdentifier->getCStringNoCopy(),
13198 	    (loadable ? "loadable" : "NOT loadable"));
13199 
13200 	return kOSReturnSuccess;
13201 }
13202 
13203 /*********************************************************************
13204 *********************************************************************/
13205 /* static */
13206 void
13207 OSKext::invokeRequestCallback(
13208 	OSDictionary * callbackRecord,
13209 	OSReturn       callbackResult)
13210 {
13211 	OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
13212 	OSSharedPtr<OSNumber> resultNum;
13213 
13214 	if (!predicate) {
13215 		goto finish;
13216 	}
13217 
13218 	resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
13219 	    8 * sizeof(callbackResult));
13220 	if (!resultNum) {
13221 		goto finish;
13222 	}
13223 
13224 	/* Insert the result into the callback record and dispatch it as if it
13225 	 * were the reply coming down from user space.
13226 	 */
13227 	_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
13228 	    resultNum.get());
13229 
13230 	if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
13231 		/* This removes the pending callback record.
13232 		 */
13233 		OSKext::dispatchResource(callbackRecord);
13234 	}
13235 
13236 finish:
13237 	return;
13238 }
13239 
13240 /*********************************************************************
13241 * Assumes sKextLock is held.
13242 *********************************************************************/
13243 /* static */
13244 OSReturn
13245 OSKext::cancelRequest(
13246 	OSKextRequestTag    requestTag,
13247 	void             ** contextOut)
13248 {
13249 	OSReturn       result         = kOSKextReturnNoMemory;
13250 	OSSharedPtr<OSDictionary> callbackRecord;
13251 	OSValueObject<void *> * contextWrapper = nullptr; // do not release
13252 
13253 	IORecursiveLockLock(sKextLock);
13254 	result = OSKext::dequeueCallbackForRequestTag(requestTag,
13255 	    callbackRecord);
13256 	IORecursiveLockUnlock(sKextLock);
13257 
13258 	if (result == kOSReturnSuccess && contextOut) {
13259 		contextWrapper = OSDynamicCast(OSValueObject<void *>,
13260 		    _OSKextGetRequestArgument(callbackRecord.get(),
13261 		    kKextRequestArgumentContextKey));
13262 		*contextOut = _OSKextExtractPointer(contextWrapper);
13263 	}
13264 
13265 	return result;
13266 }
13267 
13268 /*********************************************************************
13269 * Assumes sKextLock is held.
13270 *********************************************************************/
13271 void
13272 OSKext::invokeOrCancelRequestCallbacks(
13273 	OSReturn callbackResult,
13274 	bool     invokeFlag)
13275 {
13276 	unsigned int count, i;
13277 
13278 	count = sRequestCallbackRecords->getCount();
13279 	if (!count) {
13280 		goto finish;
13281 	}
13282 
13283 	i = count - 1;
13284 	do {
13285 		OSDictionary * request = OSDynamicCast(OSDictionary,
13286 		    sRequestCallbackRecords->getObject(i));
13287 
13288 		if (!request) {
13289 			continue;
13290 		}
13291 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
13292 		    _OSKextGetRequestArgument(request,
13293 		    kKextRequestArgumentCallbackKey));
13294 
13295 		if (!callbackWrapper) {
13296 			sRequestCallbackRecords->removeObject(i);
13297 			continue;
13298 		}
13299 
13300 		vm_address_t callbackAddress = (vm_address_t)
13301 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
13302 
13303 		if ((kmod_info->address <= callbackAddress) &&
13304 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
13305 			if (invokeFlag) {
13306 				/* This removes the callback record.
13307 				 */
13308 				invokeRequestCallback(request, callbackResult);
13309 			} else {
13310 				sRequestCallbackRecords->removeObject(i);
13311 			}
13312 		}
13313 	} while (i--);
13314 
13315 finish:
13316 	return;
13317 }
13318 
13319 /*********************************************************************
13320 * Assumes sKextLock is held.
13321 *********************************************************************/
13322 uint32_t
13323 OSKext::countRequestCallbacks(void)
13324 {
13325 	uint32_t     result = 0;
13326 	unsigned int count, i;
13327 
13328 	count = sRequestCallbackRecords->getCount();
13329 	if (!count) {
13330 		goto finish;
13331 	}
13332 
13333 	i = count - 1;
13334 	do {
13335 		OSDictionary * request = OSDynamicCast(OSDictionary,
13336 		    sRequestCallbackRecords->getObject(i));
13337 
13338 		if (!request) {
13339 			continue;
13340 		}
13341 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
13342 		    _OSKextGetRequestArgument(request,
13343 		    kKextRequestArgumentCallbackKey));
13344 
13345 		if (!callbackWrapper) {
13346 			continue;
13347 		}
13348 
13349 		vm_address_t callbackAddress = (vm_address_t)
13350 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
13351 
13352 		if ((kmod_info->address <= callbackAddress) &&
13353 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
13354 			result++;
13355 		}
13356 	} while (i--);
13357 
13358 finish:
13359 	return result;
13360 }
13361 
13362 /*********************************************************************
13363 *********************************************************************/
13364 static OSReturn
13365 _OSKextCreateRequest(
13366 	const char    * predicate,
13367 	OSSharedPtr<OSDictionary> & requestR)
13368 {
13369 	OSReturn result = kOSKextReturnNoMemory;
13370 	OSSharedPtr<OSDictionary> request;
13371 
13372 	request = OSDictionary::withCapacity(2);
13373 	if (!request) {
13374 		goto finish;
13375 	}
13376 	result = _OSDictionarySetCStringValue(request.get(),
13377 	    kKextRequestPredicateKey, predicate);
13378 	if (result != kOSReturnSuccess) {
13379 		goto finish;
13380 	}
13381 	result = kOSReturnSuccess;
13382 
13383 finish:
13384 	if (result == kOSReturnSuccess) {
13385 		requestR = os::move(request);
13386 	}
13387 
13388 	return result;
13389 }
13390 
13391 /*********************************************************************
13392 *********************************************************************/
13393 static OSString *
13394 _OSKextGetRequestPredicate(OSDictionary * requestDict)
13395 {
13396 	return OSDynamicCast(OSString,
13397 	           requestDict->getObject(kKextRequestPredicateKey));
13398 }
13399 
13400 /*********************************************************************
13401 *********************************************************************/
13402 static OSObject *
13403 _OSKextGetRequestArgument(
13404 	OSDictionary * requestDict,
13405 	const char   * argName)
13406 {
13407 	OSDictionary * args = OSDynamicCast(OSDictionary,
13408 	    requestDict->getObject(kKextRequestArgumentsKey));
13409 	if (args) {
13410 		return args->getObject(argName);
13411 	}
13412 	return NULL;
13413 }
13414 
13415 /*********************************************************************
13416 *********************************************************************/
13417 static bool
13418 _OSKextSetRequestArgument(
13419 	OSDictionary    * requestDict,
13420 	const char      * argName,
13421 	OSMetaClassBase * value)
13422 {
13423 	OSDictionary * args = OSDynamicCast(OSDictionary,
13424 	    requestDict->getObject(kKextRequestArgumentsKey));
13425 	OSSharedPtr<OSDictionary> newArgs;
13426 	if (!args) {
13427 		newArgs = OSDictionary::withCapacity(2);
13428 		args = newArgs.get();
13429 		if (!args) {
13430 			goto finish;
13431 		}
13432 		requestDict->setObject(kKextRequestArgumentsKey, args);
13433 	}
13434 	if (args) {
13435 		return args->setObject(argName, value);
13436 	}
13437 finish:
13438 	return false;
13439 }
13440 
13441 /*********************************************************************
13442 *********************************************************************/
13443 template <typename T>
13444 static T *
13445 _OSKextExtractPointer(OSValueObject<T *> * wrapper)
13446 {
13447 	if (!wrapper) {
13448 		return nullptr;
13449 	}
13450 	return wrapper->getRef();
13451 }
13452 
13453 /*********************************************************************
13454 *********************************************************************/
13455 static OSKextRequestResourceCallback
13456 _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper)
13457 {
13458 	if (!wrapper) {
13459 		return nullptr;
13460 	}
13461 	return wrapper->getRef();
13462 }
13463 
13464 
13465 /*********************************************************************
13466 *********************************************************************/
13467 static OSReturn
13468 _OSDictionarySetCStringValue(
13469 	OSDictionary * dict,
13470 	const char   * cKey,
13471 	const char   * cValue)
13472 {
13473 	OSReturn result = kOSKextReturnNoMemory;
13474 	OSSharedPtr<const OSSymbol> key;
13475 	OSSharedPtr<OSString> value;
13476 
13477 	key = OSSymbol::withCString(cKey);
13478 	value = OSString::withCString(cValue);
13479 	if (!key || !value) {
13480 		goto finish;
13481 	}
13482 	if (dict->setObject(key.get(), value.get())) {
13483 		result = kOSReturnSuccess;
13484 	}
13485 
13486 finish:
13487 	return result;
13488 }
13489 
13490 /*********************************************************************
13491 *********************************************************************/
13492 static bool
13493 _OSArrayContainsCString(
13494 	OSArray    * array,
13495 	const char * cString)
13496 {
13497 	bool             result = false;
13498 	OSSharedPtr<const OSSymbol> symbol;
13499 	uint32_t         count, i;
13500 
13501 	if (!array || !cString) {
13502 		goto finish;
13503 	}
13504 
13505 	symbol = OSSymbol::withCStringNoCopy(cString);
13506 	if (!symbol) {
13507 		goto finish;
13508 	}
13509 
13510 	count = array->getCount();
13511 	for (i = 0; i < count; i++) {
13512 		OSObject * thisObject = array->getObject(i);
13513 		if (symbol->isEqualTo(thisObject)) {
13514 			result = true;
13515 			goto finish;
13516 		}
13517 	}
13518 
13519 finish:
13520 	return result;
13521 }
13522 
13523 #if CONFIG_KXLD
13524 /*********************************************************************
13525 * We really only care about boot / system start up related kexts.
13526 * We return true if we're less than REBUILD_MAX_TIME since start up,
13527 * otherwise return false.
13528 *********************************************************************/
13529 bool
13530 _OSKextInPrelinkRebuildWindow(void)
13531 {
13532 	static bool     outside_the_window = false;
13533 	AbsoluteTime    my_abstime;
13534 	UInt64          my_ns;
13535 	SInt32          my_secs;
13536 
13537 	if (outside_the_window) {
13538 		return false;
13539 	}
13540 	clock_get_uptime(&my_abstime);
13541 	absolutetime_to_nanoseconds(my_abstime, &my_ns);
13542 	my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
13543 	if (my_secs > REBUILD_MAX_TIME) {
13544 		outside_the_window = true;
13545 		return false;
13546 	}
13547 	return true;
13548 }
13549 #endif /* CONFIG_KXLD */
13550 
13551 /*********************************************************************
13552 *********************************************************************/
13553 bool
13554 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
13555 {
13556 	int unLoadedCount, i;
13557 	bool result = false;
13558 
13559 	IORecursiveLockLock(sKextLock);
13560 
13561 	if (sUnloadedPrelinkedKexts == NULL) {
13562 		goto finish;
13563 	}
13564 	unLoadedCount = sUnloadedPrelinkedKexts->getCount();
13565 	if (unLoadedCount == 0) {
13566 		goto finish;
13567 	}
13568 
13569 	for (i = 0; i < unLoadedCount; i++) {
13570 		const OSSymbol *    myBundleID;        // do not release
13571 
13572 		myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
13573 		if (!myBundleID) {
13574 			continue;
13575 		}
13576 		if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
13577 			result = true;
13578 			break;
13579 		}
13580 	}
13581 finish:
13582 	IORecursiveLockUnlock(sKextLock);
13583 	return result;
13584 }
13585 
13586 #if PRAGMA_MARK
13587 #pragma mark Personalities (IOKit Drivers)
13588 #endif
13589 /*********************************************************************
13590 *********************************************************************/
13591 /* static */
13592 OSSharedPtr<OSArray>
13593 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
13594 {
13595 	OSSharedPtr<OSArray>              result;
13596 	OSSharedPtr<OSCollectionIterator> kextIterator;
13597 	OSSharedPtr<OSArray>              personalities;
13598 
13599 	OSString             * kextID                = NULL;        // do not release
13600 	OSKext               * theKext               = NULL;        // do not release
13601 
13602 	IORecursiveLockLock(sKextLock);
13603 
13604 	/* Let's conservatively guess that any given kext has around 3
13605 	 * personalities for now.
13606 	 */
13607 	result = OSArray::withCapacity(sKextsByID->getCount() * 3);
13608 	if (!result) {
13609 		goto finish;
13610 	}
13611 
13612 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
13613 	if (!kextIterator) {
13614 		goto finish;
13615 	}
13616 
13617 	while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
13618 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
13619 		if (theKext->flags.requireExplicitLoad) {
13620 			OSKextLog(theKext,
13621 			    kOSKextLogDebugLevel |
13622 			    kOSKextLogLoadFlag,
13623 			    "Kext %s requires an explicit kextload; "
13624 			    "omitting its personalities.",
13625 			    theKext->getIdentifierCString());
13626 		} else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
13627 			personalities = theKext->copyPersonalitiesArray();
13628 			if (!personalities) {
13629 				continue;
13630 			}
13631 			result->merge(personalities.get());
13632 		} else {
13633 			// xxx - check for better place to put this log msg
13634 			OSKextLog(theKext,
13635 			    kOSKextLogWarningLevel |
13636 			    kOSKextLogLoadFlag,
13637 			    "Kext %s is not loadable during safe boot; "
13638 			    "omitting its personalities.",
13639 			    theKext->getIdentifierCString());
13640 		}
13641 	}
13642 
13643 finish:
13644 	IORecursiveLockUnlock(sKextLock);
13645 
13646 	return result;
13647 }
13648 
13649 /*********************************************************************
13650 *********************************************************************/
13651 /* static */
13652 void
13653 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
13654 {
13655 	int numPersonalities = 0;
13656 
13657 	OSKextLog(/* kext */ NULL,
13658 	    kOSKextLogStepLevel |
13659 	    kOSKextLogLoadFlag,
13660 	    "Sending all eligible registered kexts' personalities "
13661 	    "to the IOCatalogue %s.",
13662 	    startMatching ? "and starting matching" : "but not starting matching");
13663 
13664 	OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities(
13665 		/* filterSafeBootFlag */ true);
13666 
13667 	if (personalities) {
13668 		gIOCatalogue->addDrivers(personalities.get(), startMatching);
13669 		numPersonalities = personalities->getCount();
13670 	}
13671 
13672 	OSKextLog(/* kext */ NULL,
13673 	    kOSKextLogStepLevel |
13674 	    kOSKextLogLoadFlag,
13675 	    "%d kext personalit%s sent to the IOCatalogue; %s.",
13676 	    numPersonalities, numPersonalities > 0 ? "ies" : "y",
13677 	    startMatching ? "matching started" : "matching not started");
13678 	return;
13679 }
13680 
13681 /*********************************************************************
13682 * Do not make a deep copy, just convert the IOKitPersonalities dict
13683 * to an array for sending to the IOCatalogue.
13684 *********************************************************************/
13685 OSSharedPtr<OSArray>
13686 OSKext::copyPersonalitiesArray(void)
13687 {
13688 	OSSharedPtr<OSArray>              result;
13689 	OSDictionary         * personalities               = NULL;        // do not release
13690 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
13691 
13692 	OSString             * personalityName             = NULL;        // do not release
13693 	OSString             * personalityBundleIdentifier = NULL;        // do not release
13694 
13695 	personalities = OSDynamicCast(OSDictionary,
13696 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
13697 	if (!personalities) {
13698 		goto finish;
13699 	}
13700 
13701 	result = OSArray::withCapacity(personalities->getCount());
13702 	if (!result) {
13703 		goto finish;
13704 	}
13705 
13706 	personalitiesIterator =
13707 	    OSCollectionIterator::withCollection(personalities);
13708 	if (!personalitiesIterator) {
13709 		goto finish;
13710 	}
13711 	while ((personalityName = OSDynamicCast(OSString,
13712 	    personalitiesIterator->getNextObject()))) {
13713 		OSDictionary * personality = OSDynamicCast(OSDictionary,
13714 		    personalities->getObject(personalityName));
13715 
13716 		if (personality) {
13717 			/******
13718 			 * If the personality doesn't have a CFBundleIdentifier, or if it
13719 			 * differs from the kext's, insert the kext's ID so we can find it.
13720 			 * The publisher ID is used to remove personalities from bundles
13721 			 * correctly.
13722 			 */
13723 			personalityBundleIdentifier = OSDynamicCast(OSString,
13724 			    personality->getObject(kCFBundleIdentifierKey));
13725 
13726 			if (!personalityBundleIdentifier) {
13727 				personality->setObject(kCFBundleIdentifierKey, bundleID.get());
13728 			} else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) {
13729 				personality->setObject(kIOPersonalityPublisherKey, bundleID.get());
13730 			}
13731 		}
13732 
13733 		result->setObject(personality);
13734 	}
13735 
13736 finish:
13737 	return result;
13738 }
13739 
13740 /*********************************************************************
13741 *   Might want to change this to a bool return?
13742 *********************************************************************/
13743 OSReturn
13744 OSKext::sendPersonalitiesToCatalog(
13745 	bool      startMatching,
13746 	OSArray * personalityNames)
13747 {
13748 	OSReturn       result              = kOSReturnSuccess;
13749 	OSSharedPtr<OSArray> personalitiesToSend;
13750 	OSDictionary * kextPersonalities   = NULL;        // do not release
13751 	int            count, i;
13752 
13753 	if (!sLoadEnabled) {
13754 		OSKextLog(this,
13755 		    kOSKextLogErrorLevel |
13756 		    kOSKextLogLoadFlag,
13757 		    "Kext loading is disabled (attempt to start matching for kext %s).",
13758 		    getIdentifierCString());
13759 		result = kOSKextReturnDisabled;
13760 		goto finish;
13761 	}
13762 
13763 	if (sSafeBoot && !isLoadableInSafeBoot()) {
13764 		OSKextLog(this,
13765 		    kOSKextLogErrorLevel |
13766 		    kOSKextLogLoadFlag,
13767 		    "Kext %s is not loadable during safe boot; "
13768 		    "not sending personalities to the IOCatalogue.",
13769 		    getIdentifierCString());
13770 		result = kOSKextReturnNotLoadable;
13771 		goto finish;
13772 	}
13773 
13774 	if (!personalityNames || !personalityNames->getCount()) {
13775 		personalitiesToSend = copyPersonalitiesArray();
13776 	} else {
13777 		kextPersonalities = OSDynamicCast(OSDictionary,
13778 		    getPropertyForHostArch(kIOKitPersonalitiesKey));
13779 		if (!kextPersonalities || !kextPersonalities->getCount()) {
13780 			// not an error
13781 			goto finish;
13782 		}
13783 		personalitiesToSend = OSArray::withCapacity(0);
13784 		if (!personalitiesToSend) {
13785 			result = kOSKextReturnNoMemory;
13786 			goto finish;
13787 		}
13788 		count = personalityNames->getCount();
13789 		for (i = 0; i < count; i++) {
13790 			OSString * name = OSDynamicCast(OSString,
13791 			    personalityNames->getObject(i));
13792 			if (!name) {
13793 				continue;
13794 			}
13795 			OSDictionary * personality = OSDynamicCast(OSDictionary,
13796 			    kextPersonalities->getObject(name));
13797 			if (personality) {
13798 				personalitiesToSend->setObject(personality);
13799 			}
13800 		}
13801 	}
13802 	if (personalitiesToSend) {
13803 		unsigned numPersonalities = personalitiesToSend->getCount();
13804 		OSKextLog(this,
13805 		    kOSKextLogStepLevel |
13806 		    kOSKextLogLoadFlag,
13807 		    "Kext %s sending %d personalit%s to the IOCatalogue%s.",
13808 		    getIdentifierCString(),
13809 		    numPersonalities,
13810 		    numPersonalities > 1 ? "ies" : "y",
13811 		    startMatching ? " and starting matching" : " but not starting matching");
13812 		gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching);
13813 	}
13814 finish:
13815 	return result;
13816 }
13817 
13818 /*********************************************************************
13819 * xxx - We should allow removing the kext's declared personalities,
13820 * xxx - even with other bundle identifiers.
13821 *********************************************************************/
13822 void
13823 OSKext::removePersonalitiesFromCatalog(void)
13824 {
13825 	OSSharedPtr<OSDictionary> personality;
13826 
13827 	personality = OSDictionary::withCapacity(1);
13828 	if (!personality) {
13829 		goto finish;
13830 	}
13831 	personality->setObject(kCFBundleIdentifierKey, getIdentifier());
13832 
13833 	OSKextLog(this,
13834 	    kOSKextLogStepLevel |
13835 	    kOSKextLogLoadFlag,
13836 	    "Kext %s removing all personalities naming it from the IOCatalogue.",
13837 	    getIdentifierCString());
13838 
13839 	/* Have the IOCatalog remove all personalities matching this kext's
13840 	 * bundle ID and trigger matching anew.
13841 	 */
13842 	gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true);
13843 
13844 finish:
13845 	return;
13846 }
13847 
13848 
13849 #if PRAGMA_MARK
13850 #pragma mark Logging
13851 #endif
13852 /*********************************************************************
13853 * Do not call any function that takes sKextLock here!
13854 *********************************************************************/
13855 /* static */
13856 OSKextLogSpec
13857 OSKext::setUserSpaceLogFilter(
13858 	OSKextLogSpec   newUserLogFilter,
13859 	bool            captureFlag)
13860 {
13861 	OSKextLogSpec result;
13862 	bool          allocError = false;
13863 
13864 	/* Do not call any function that takes sKextLoggingLock during
13865 	 * this critical block. That means do logging after.
13866 	 */
13867 	IOLockLock(sKextLoggingLock);
13868 
13869 	result = sUserSpaceKextLogFilter;
13870 	sUserSpaceKextLogFilter = newUserLogFilter;
13871 
13872 	if (newUserLogFilter && captureFlag &&
13873 	    !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
13874 		// xxx - do some measurements for a good initial capacity?
13875 		sUserSpaceLogSpecArray = OSArray::withCapacity(0);
13876 		sUserSpaceLogMessageArray = OSArray::withCapacity(0);
13877 
13878 		if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
13879 			allocError = true;
13880 		}
13881 	}
13882 
13883 	IOLockUnlock(sKextLoggingLock);
13884 
13885 	/* If the config flag itself is changing, log the state change
13886 	 * going both ways, before setting up the user-space log arrays,
13887 	 * so that this is only logged in the kernel.
13888 	 */
13889 	if (result != newUserLogFilter) {
13890 		OSKextLog(/* kext */ NULL,
13891 		    kOSKextLogDebugLevel |
13892 		    kOSKextLogGeneralFlag,
13893 		    "User-space log flags changed from 0x%x to 0x%x.",
13894 		    result, newUserLogFilter);
13895 	}
13896 	if (allocError) {
13897 		OSKextLog(/* kext */ NULL,
13898 		    kOSKextLogErrorLevel |
13899 		    kOSKextLogGeneralFlag,
13900 		    "Failed to allocate user-space log message arrays.");
13901 	}
13902 
13903 	return result;
13904 }
13905 
13906 /*********************************************************************
13907 * Do not call any function that takes sKextLock here!
13908 *********************************************************************/
13909 /* static */
13910 OSSharedPtr<OSArray>
13911 OSKext::clearUserSpaceLogFilter(void)
13912 {
13913 	OSSharedPtr<OSArray>       result;
13914 	OSKextLogSpec   oldLogFilter;
13915 	OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
13916 
13917 	/* Do not call any function that takes sKextLoggingLock during
13918 	 * this critical block. That means do logging after.
13919 	 */
13920 	IOLockLock(sKextLoggingLock);
13921 
13922 	result = OSArray::withCapacity(2);
13923 	if (result) {
13924 		result->setObject(sUserSpaceLogSpecArray.get());
13925 		result->setObject(sUserSpaceLogMessageArray.get());
13926 	}
13927 	sUserSpaceLogSpecArray.reset();
13928 	sUserSpaceLogMessageArray.reset();
13929 
13930 	oldLogFilter = sUserSpaceKextLogFilter;
13931 	sUserSpaceKextLogFilter = newLogFilter;
13932 
13933 	IOLockUnlock(sKextLoggingLock);
13934 
13935 	/* If the config flag itself is changing, log the state change
13936 	 * going both ways, after tearing down the user-space log
13937 	 * arrays, so this is only logged within the kernel.
13938 	 */
13939 	if (oldLogFilter != newLogFilter) {
13940 		OSKextLog(/* kext */ NULL,
13941 		    kOSKextLogDebugLevel |
13942 		    kOSKextLogGeneralFlag,
13943 		    "User-space log flags changed from 0x%x to 0x%x.",
13944 		    oldLogFilter, newLogFilter);
13945 	}
13946 
13947 	return result;
13948 }
13949 
13950 
13951 /*********************************************************************
13952 * Do not call any function that takes sKextLock here!
13953 *********************************************************************/
13954 /* static */
13955 OSKextLogSpec
13956 OSKext::getUserSpaceLogFilter(void)
13957 {
13958 	OSKextLogSpec result;
13959 
13960 	IOLockLock(sKextLoggingLock);
13961 	result = sUserSpaceKextLogFilter;
13962 	IOLockUnlock(sKextLoggingLock);
13963 
13964 	return result;
13965 }
13966 
13967 /*********************************************************************
13968 * This function is called by OSMetaClass during kernel C++ setup.
13969 * Be careful what you access here; assume only OSKext::initialize()
13970 * has been called.
13971 *
13972 * Do not call any function that takes sKextLock here!
13973 *********************************************************************/
13974 #define VTRESET   "\033[0m"
13975 
13976 #define VTBOLD    "\033[1m"
13977 #define VTUNDER   "\033[4m"
13978 
13979 #define VTRED     "\033[31m"
13980 #define VTGREEN   "\033[32m"
13981 #define VTYELLOW  "\033[33m"
13982 #define VTBLUE    "\033[34m"
13983 #define VTMAGENTA "\033[35m"
13984 #define VTCYAN    "\033[36m"
13985 
13986 inline const char *
13987 colorForFlags(OSKextLogSpec flags)
13988 {
13989 	OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
13990 
13991 	switch (logLevel) {
13992 	case kOSKextLogErrorLevel:
13993 		return VTRED VTBOLD;
13994 	case kOSKextLogWarningLevel:
13995 		return VTRED;
13996 	case kOSKextLogBasicLevel:
13997 		return VTYELLOW VTUNDER;
13998 	case kOSKextLogProgressLevel:
13999 		return VTYELLOW;
14000 	case kOSKextLogStepLevel:
14001 		return VTGREEN;
14002 	case kOSKextLogDetailLevel:
14003 		return VTCYAN;
14004 	case kOSKextLogDebugLevel:
14005 		return VTMAGENTA;
14006 	default:
14007 		return "";         // white
14008 	}
14009 }
14010 
14011 inline bool
14012 logSpecMatch(
14013 	OSKextLogSpec msgLogSpec,
14014 	OSKextLogSpec logFilter)
14015 {
14016 	OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
14017 	OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
14018 	OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
14019 
14020 	OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
14021 	OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
14022 	OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
14023 
14024 	/* Explicit messages always get logged.
14025 	 */
14026 	if (msgLevel == kOSKextLogExplicitLevel) {
14027 		return true;
14028 	}
14029 
14030 	/* Warnings and errors are logged regardless of the flags.
14031 	 */
14032 	if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
14033 		return true;
14034 	}
14035 
14036 	/* A verbose message that isn't for a logging-enabled kext and isn't global
14037 	 * does *not* get logged.
14038 	 */
14039 	if (!msgKextGlobal && !filterKextGlobal) {
14040 		return false;
14041 	}
14042 
14043 	/* Warnings and errors are logged regardless of the flags.
14044 	 * All other messages must fit the flags and
14045 	 * have a level at or below the filter.
14046 	 *
14047 	 */
14048 	if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
14049 		return true;
14050 	}
14051 	return false;
14052 }
14053 
14054 extern "C" {
14055 void
14056 OSKextLog(
14057 	OSKext         * aKext,
14058 	OSKextLogSpec    msgLogSpec,
14059 	const char     * format, ...)
14060 {
14061 	va_list argList;
14062 
14063 	va_start(argList, format);
14064 	OSKextVLog(aKext, msgLogSpec, format, argList);
14065 	va_end(argList);
14066 }
14067 
14068 void
14069 OSKextVLog(
14070 	OSKext         * aKext,
14071 	OSKextLogSpec    msgLogSpec,
14072 	const char     * format,
14073 	va_list          srcArgList)
14074 {
14075 	extern int       disableConsoleOutput;
14076 
14077 	bool             logForKernel       = false;
14078 	bool             logForUser         = false;
14079 	va_list          argList;
14080 	char             stackBuffer[120];
14081 	uint32_t         length            = 0;
14082 	char           * allocBuffer       = NULL;        // must kfree
14083 	OSSharedPtr<OSNumber> logSpecNum;
14084 	OSSharedPtr<OSString> logString;
14085 	char           * buffer            = stackBuffer;        // do not free
14086 
14087 	IOLockLock(sKextLoggingLock);
14088 
14089 	/* Set the kext/global bit in the message spec if we have no
14090 	 * kext or if the kext requests logging.
14091 	 */
14092 	if (!aKext || aKext->flags.loggingEnabled) {
14093 		msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
14094 	}
14095 
14096 	logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
14097 	if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
14098 		logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
14099 	}
14100 
14101 	if (!(logForKernel || logForUser)) {
14102 		goto finish;
14103 	}
14104 
14105 	/* No goto from here until past va_end()!
14106 	 */
14107 	va_copy(argList, srcArgList);
14108 	length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
14109 	va_end(argList);
14110 
14111 	if (length + 1 >= sizeof(stackBuffer)) {
14112 		allocBuffer = (char *)kalloc_data_tag(length + 1,
14113 		    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
14114 		if (!allocBuffer) {
14115 			goto finish;
14116 		}
14117 
14118 		/* No goto from here until past va_end()!
14119 		 */
14120 		va_copy(argList, srcArgList);
14121 		vsnprintf(allocBuffer, length + 1, format, argList);
14122 		va_end(argList);
14123 
14124 		buffer = allocBuffer;
14125 	}
14126 
14127 	/* If user space wants the log message, queue it up.
14128 	 */
14129 	if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
14130 		logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
14131 		logString = OSString::withCString(buffer);
14132 		if (logSpecNum && logString) {
14133 			sUserSpaceLogSpecArray->setObject(logSpecNum.get());
14134 			sUserSpaceLogMessageArray->setObject(logString.get());
14135 		}
14136 	}
14137 
14138 	/* Always log messages from the kernel according to the kernel's
14139 	 * log flags.
14140 	 */
14141 	if (logForKernel) {
14142 		/* If we are in console mode and have a custom log filter,
14143 		 * colorize the log message.
14144 		 */
14145 		if (!disableConsoleOutput && sBootArgLogFilterFound) {
14146 			const char * color = "";         // do not free
14147 			color = colorForFlags(msgLogSpec);
14148 			printf("%s%s%s\n", colorForFlags(msgLogSpec),
14149 			    buffer, color[0] ? VTRESET : "");
14150 		} else {
14151 			printf("%s\n", buffer);
14152 		}
14153 	}
14154 
14155 finish:
14156 	IOLockUnlock(sKextLoggingLock);
14157 
14158 	if (allocBuffer) {
14159 		kfree_data(allocBuffer, length + 1);
14160 	}
14161 	return;
14162 }
14163 
14164 #if KASLR_IOREG_DEBUG
14165 
14166 #define IOLOG_INDENT( the_indention ) \
14167 { \
14168     int     i; \
14169     for ( i = 0; i < (the_indention); i++ ) { \
14170 	IOLog(" "); \
14171     } \
14172 }
14173 
14174 extern vm_offset_t       vm_kernel_stext;
14175 extern vm_offset_t       vm_kernel_etext;
14176 extern mach_vm_offset_t kext_alloc_base;
14177 extern mach_vm_offset_t kext_alloc_max;
14178 
14179 bool ScanForAddrInObject(OSObject * theObject,
14180     int indent );
14181 
14182 bool
14183 ScanForAddrInObject(OSObject * theObject,
14184     int indent)
14185 {
14186 	const OSMetaClass *     myTypeID;
14187 	OSSharedPtr<OSCollectionIterator>  myIter;
14188 	OSSymbol *              myKey;
14189 	OSObject *              myValue;
14190 	bool                    myResult = false;
14191 
14192 	if (theObject == NULL) {
14193 		IOLog("%s: theObject is NULL \n",
14194 		    __FUNCTION__);
14195 		return myResult;
14196 	}
14197 
14198 	myTypeID = OSTypeIDInst(theObject);
14199 
14200 	if (myTypeID == OSTypeID(OSDictionary)) {
14201 		OSDictionary *      myDictionary;
14202 
14203 		myDictionary = OSDynamicCast(OSDictionary, theObject);
14204 		myIter = OSCollectionIterator::withCollection( myDictionary );
14205 		if (myIter == NULL) {
14206 			return myResult;
14207 		}
14208 
14209 		// !! reset the iterator
14210 		myIter->reset();
14211 
14212 		while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
14213 			bool    myTempResult;
14214 
14215 			myValue = myDictionary->getObject(myKey);
14216 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
14217 			if (myTempResult) {
14218 				// if we ever get a true result return true
14219 				myResult = true;
14220 				IOLOG_INDENT(indent);
14221 				IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
14222 			}
14223 		}
14224 
14225 		// !! release the iterator
14226 		myIter.reset();
14227 	} else if (myTypeID == OSTypeID(OSArray)) {
14228 		OSArray *   myArray;
14229 
14230 		myArray = OSDynamicCast(OSArray, theObject);
14231 		myIter = OSCollectionIterator::withCollection(myArray);
14232 		if (myIter == NULL) {
14233 			return myResult;
14234 		}
14235 		// !! reset the iterator
14236 		myIter->reset();
14237 
14238 		while ((myValue = myIter->getNextObject())) {
14239 			bool        myTempResult;
14240 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
14241 			if (myTempResult) {
14242 				// if we ever get a true result return true
14243 				myResult = true;
14244 				IOLOG_INDENT(indent);
14245 				IOLog("OSArray: \n");
14246 			}
14247 		}
14248 		// !! release the iterator
14249 		myIter.reset();
14250 	} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
14251 		// should we look for addresses in strings?
14252 	} else if (myTypeID == OSTypeID(OSData)) {
14253 		void * *        myPtrPtr;
14254 		unsigned int    myLen;
14255 		OSData *        myDataObj;
14256 
14257 		myDataObj =    OSDynamicCast(OSData, theObject);
14258 		myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
14259 		myLen = myDataObj->getLength();
14260 
14261 		if (myPtrPtr && myLen && myLen > 7) {
14262 			int     i;
14263 			int     myPtrCount = (myLen / sizeof(void *));
14264 
14265 			for (i = 0; i < myPtrCount; i++) {
14266 				UInt64 numberValue = (UInt64) * (myPtrPtr);
14267 
14268 				if (kext_alloc_max != 0 &&
14269 				    numberValue >= kext_alloc_base &&
14270 				    numberValue < kext_alloc_max) {
14271 					OSSharedPtr<OSKext> myKext;
14272 					// IOLog("found OSData %p in kext map %p to %p  \n",
14273 					//       *(myPtrPtr),
14274 					//       (void *) kext_alloc_base,
14275 					//       (void *) kext_alloc_max);
14276 
14277 					myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
14278 					if (myKext) {
14279 						IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
14280 						    *(myPtrPtr),
14281 						    myKext->getIdentifierCString());
14282 					}
14283 					myResult = true;
14284 				}
14285 				if (vm_kernel_etext != 0 &&
14286 				    numberValue >= vm_kernel_stext &&
14287 				    numberValue < vm_kernel_etext) {
14288 					IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
14289 					    *(myPtrPtr),
14290 					    (void *) vm_kernel_stext,
14291 					    (void *) vm_kernel_etext);
14292 					myResult = true;
14293 				}
14294 				myPtrPtr++;
14295 			}
14296 		}
14297 	} else if (myTypeID == OSTypeID(OSBoolean)) {
14298 		// do nothing here...
14299 	} else if (myTypeID == OSTypeID(OSNumber)) {
14300 		OSNumber * number = OSDynamicCast(OSNumber, theObject);
14301 
14302 		UInt64 numberValue = number->unsigned64BitValue();
14303 
14304 		if (kext_alloc_max != 0 &&
14305 		    numberValue >= kext_alloc_base &&
14306 		    numberValue < kext_alloc_max) {
14307 			OSSharedPtr<OSKext> myKext;
14308 			IOLog("found OSNumber in kext map %p to %p  \n",
14309 			    (void *) kext_alloc_base,
14310 			    (void *) kext_alloc_max);
14311 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
14312 
14313 			myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
14314 			if (myKext) {
14315 				IOLog("found in kext \"%s\"  \n",
14316 				    myKext->getIdentifierCString());
14317 			}
14318 
14319 			myResult = true;
14320 		}
14321 		if (vm_kernel_etext != 0 &&
14322 		    numberValue >= vm_kernel_stext &&
14323 		    numberValue < vm_kernel_etext) {
14324 			IOLog("found OSNumber in kernel text segment %p to %p  \n",
14325 			    (void *) vm_kernel_stext,
14326 			    (void *) vm_kernel_etext);
14327 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
14328 			myResult = true;
14329 		}
14330 	}
14331 #if 0
14332 	else {
14333 		const OSMetaClass* myMetaClass = NULL;
14334 
14335 		myMetaClass = theObject->getMetaClass();
14336 		if (myMetaClass) {
14337 			IOLog("class %s \n", myMetaClass->getClassName());
14338 		} else {
14339 			IOLog("Unknown object \n" );
14340 		}
14341 	}
14342 #endif
14343 
14344 	return myResult;
14345 }
14346 #endif // KASLR_KEXT_DEBUG
14347 };         /* extern "C" */
14348 
14349 #if PRAGMA_MARK
14350 #pragma mark Backtrace Dump & kmod_get_info() support
14351 #endif
14352 /*********************************************************************
14353 * This function must be safe to call in panic context.
14354 *********************************************************************/
14355 /* static */
14356 void
14357 OSKext::printKextsInBacktrace(
14358 	vm_offset_t  * addr __unused,
14359 	unsigned int   cnt __unused,
14360 	int         (* printf_func)(const char *fmt, ...) __unused,
14361 	uint32_t       flags __unused)
14362 {
14363 	addr64_t    summary_page = 0;
14364 	addr64_t    last_summary_page = 0;
14365 	bool        found_kmod = false;
14366 	u_int       i = 0;
14367 
14368 	if (kPrintKextsLock & flags) {
14369 		if (!sKextSummariesLock) {
14370 			return;
14371 		}
14372 		IOLockLock(sKextSummariesLock);
14373 	}
14374 
14375 	if (!gLoadedKextSummaries) {
14376 		(*printf_func)("         can't perform kext scan: no kext summary");
14377 		goto finish;
14378 	}
14379 
14380 	summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
14381 	last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
14382 	for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
14383 		if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
14384 			(*printf_func)("         can't perform kext scan: "
14385 			    "missing kext summary page %p", summary_page);
14386 			goto finish;
14387 		}
14388 	}
14389 
14390 	for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14391 		OSKextLoadedKextSummary * summary;
14392 
14393 		summary = gLoadedKextSummaries->summaries + i;
14394 		if (!summary->address) {
14395 			continue;
14396 		}
14397 
14398 		if (!summaryIsInBacktrace(summary, addr, cnt)) {
14399 			continue;
14400 		}
14401 
14402 		if (!found_kmod) {
14403 			if (!(kPrintKextsTerse & flags)) {
14404 				(*printf_func)("      Kernel Extensions in backtrace:\n");
14405 			}
14406 			found_kmod = true;
14407 		}
14408 
14409 		printSummary(summary, printf_func, flags);
14410 	}
14411 
14412 finish:
14413 	if (kPrintKextsLock & flags) {
14414 		IOLockUnlock(sKextSummariesLock);
14415 	}
14416 
14417 	return;
14418 }
14419 
14420 /*********************************************************************
14421 * This function must be safe to call in panic context.
14422 *********************************************************************/
14423 /* static */
14424 boolean_t
14425 OSKext::summaryIsInBacktrace(
14426 	OSKextLoadedKextSummary   * summary,
14427 	vm_offset_t               * addr,
14428 	unsigned int                cnt)
14429 {
14430 	u_int i = 0;
14431 
14432 	for (i = 0; i < cnt; i++) {
14433 		vm_offset_t kscan_addr = addr[i];
14434 #if  __has_feature(ptrauth_calls)
14435 		kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr);
14436 #endif /*  __has_feature(ptrauth_calls) */
14437 		if ((kscan_addr >= summary->text_exec_address) &&
14438 		    (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) {
14439 			return TRUE;
14440 		}
14441 	}
14442 
14443 	return FALSE;
14444 }
14445 
14446 /*
14447  * Get the kext summary object for the kext where 'addr' lies. Must be called with
14448  * sKextSummariesLock held.
14449  */
14450 OSKextLoadedKextSummary *
14451 OSKext::summaryForAddress(uintptr_t addr)
14452 {
14453 #if  __has_feature(ptrauth_calls)
14454 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
14455 #endif /*  __has_feature(ptrauth_calls) */
14456 	for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14457 		OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
14458 		if (!summary->address) {
14459 			continue;
14460 		}
14461 
14462 #if VM_MAPPED_KEXTS
14463 		/* On our platforms that use VM_MAPPED_KEXTS, we currently do not
14464 		 * support split kexts, but we also may unmap the kexts, which can
14465 		 * race with the above codepath (see OSKext::unload).  As such,
14466 		 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
14467 		 */
14468 		if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
14469 			return summary;
14470 		}
14471 #else
14472 		kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
14473 		kernel_segment_command_t *seg;
14474 
14475 		for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
14476 			if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
14477 				return summary;
14478 			}
14479 		}
14480 #endif
14481 	}
14482 
14483 	/* addr did not map to any kext */
14484 	return NULL;
14485 }
14486 
14487 /* static */
14488 void *
14489 OSKext::kextForAddress(const void *address)
14490 {
14491 	void                * image = NULL;
14492 	OSKextActiveAccount * active;
14493 	OSKext              * kext = NULL;
14494 	uint32_t              baseIdx;
14495 	uint32_t              lim;
14496 	uintptr_t             addr = (uintptr_t) address;
14497 	size_t                i;
14498 
14499 	if (!addr) {
14500 		return NULL;
14501 	}
14502 #if  __has_feature(ptrauth_calls)
14503 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
14504 #endif /*  __has_feature(ptrauth_calls) */
14505 
14506 	if (sKextAccountsCount) {
14507 		IOSimpleLockLock(sKextAccountsLock);
14508 		// bsearch sKextAccounts list
14509 		for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
14510 			active = &sKextAccounts[baseIdx + (lim >> 1)];
14511 			if ((addr >= active->address) && (addr < active->address_end)) {
14512 				kext = active->account->kext;
14513 				if (kext && kext->kmod_info) {
14514 					image = (void *) kext->kmod_info->address;
14515 				}
14516 				break;
14517 			} else if (addr > active->address) {
14518 				// move right
14519 				baseIdx += (lim >> 1) + 1;
14520 				lim--;
14521 			}
14522 			// else move left
14523 		}
14524 		IOSimpleLockUnlock(sKextAccountsLock);
14525 	}
14526 	if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) {
14527 		image = (void *) &_mh_execute_header;
14528 	}
14529 	if (!image && gLoadedKextSummaries) {
14530 		IOLockLock(sKextSummariesLock);
14531 		for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) {
14532 			OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
14533 			if (addr >= summary->address && addr < summary->address + summary->size) {
14534 				image = (void *)summary->address;
14535 			}
14536 		}
14537 		IOLockUnlock(sKextSummariesLock);
14538 	}
14539 
14540 	return image;
14541 }
14542 
14543 /*
14544  * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t *
14545  * Safe to call in panic context.
14546  */
14547 static OSKextLoadedKextSummary *
14548 findSummary(uint32_t tagID)
14549 {
14550 	OSKextLoadedKextSummary * summary;
14551 	for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14552 		summary = gLoadedKextSummaries->summaries + i;
14553 		if (summary->loadTag == tagID) {
14554 			return summary;
14555 		}
14556 	}
14557 	return NULL;
14558 }
14559 
14560 /*********************************************************************
14561 * This function must be safe to call in panic context.
14562 *********************************************************************/
14563 void
14564 OSKext::printSummary(
14565 	OSKextLoadedKextSummary * summary,
14566 	int                    (* printf_func)(const char *fmt, ...),
14567 	uint32_t                  flags)
14568 {
14569 	kmod_reference_t * kmod_ref = NULL;
14570 	uuid_string_t uuid;
14571 	char version[kOSKextVersionMaxLength];
14572 	uint64_t tmpAddr;
14573 	uint64_t tmpSize;
14574 	OSKextLoadedKextSummary *dependencySummary;
14575 
14576 	if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
14577 		strlcpy(version, "unknown version", sizeof(version));
14578 	}
14579 	(void) uuid_unparse(summary->uuid, uuid);
14580 
14581 #if defined(__arm__) || defined(__arm64__)
14582 	tmpAddr = summary->text_exec_address;
14583 	tmpSize = summary->text_exec_size;
14584 #else
14585 	tmpAddr = summary->address;
14586 	tmpSize = summary->size;
14587 #endif
14588 	if (kPrintKextsUnslide & flags) {
14589 		tmpAddr = ml_static_unslide(tmpAddr);
14590 	}
14591 	(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
14592 	    (kPrintKextsTerse & flags) ? "" : "         ",
14593 	    summary->name, version, uuid,
14594 	    tmpAddr, tmpAddr + tmpSize - 1);
14595 
14596 	if (kPrintKextsTerse & flags) {
14597 		return;
14598 	}
14599 
14600 	/* print dependency info */
14601 	for (kmod_ref = (kmod_reference_t *) summary->reference_list;
14602 	    kmod_ref;
14603 	    kmod_ref = kmod_ref->next) {
14604 		kmod_info_t * rinfo;
14605 
14606 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
14607 			(*printf_func)("            kmod dependency scan stopped "
14608 			    "due to missing dependency page: %p\n",
14609 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
14610 			break;
14611 		}
14612 		rinfo = kmod_ref->info;
14613 
14614 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
14615 			(*printf_func)("            kmod dependency scan stopped "
14616 			    "due to missing kmod page: %p\n",
14617 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
14618 			break;
14619 		}
14620 
14621 		if (!rinfo->address) {
14622 			continue;         // skip fake entries for built-ins
14623 		}
14624 
14625 		dependencySummary = findSummary(rinfo->id);
14626 		uuid[0] = 0x00;
14627 		tmpAddr = rinfo->address;
14628 		tmpSize = rinfo->size;
14629 		if (dependencySummary) {
14630 			(void) uuid_unparse(dependencySummary->uuid, uuid);
14631 #if defined(__arm__) || defined(__arm64__)
14632 			tmpAddr = dependencySummary->text_exec_address;
14633 			tmpSize = dependencySummary->text_exec_size;
14634 #endif
14635 		}
14636 
14637 		if (kPrintKextsUnslide & flags) {
14638 			tmpAddr = ml_static_unslide(tmpAddr);
14639 		}
14640 		(*printf_func)("            dependency: %s(%s)[%s]@%p->%p\n",
14641 		    rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1);
14642 	}
14643 	return;
14644 }
14645 
14646 
14647 #if !defined(__arm__) && !defined(__arm64__)
14648 /*******************************************************************************
14649 * substitute() looks at an input string (a pointer within a larger buffer)
14650 * for a match to a substring, and on match it writes the marker & substitution
14651 * character to an output string, updating the scan (from) and
14652 * output (to) indexes as appropriate.
14653 *******************************************************************************/
14654 static int substitute(
14655 	const char * scan_string,
14656 	char       * string_out,
14657 	uint32_t   * to_index,
14658 	uint32_t   * from_index,
14659 	const char * substring,
14660 	char         marker,
14661 	char         substitution);
14662 
14663 /* string_out must be at least KMOD_MAX_NAME bytes.
14664  */
14665 static int
14666 substitute(
14667 	const char * scan_string,
14668 	char       * string_out,
14669 	uint32_t   * to_index,
14670 	uint32_t   * from_index,
14671 	const char * substring,
14672 	char         marker,
14673 	char         substitution)
14674 {
14675 	size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
14676 
14677 	/* On a substring match, append the marker (if there is one) and then
14678 	 * the substitution character, updating the output (to) index accordingly.
14679 	 * Then update the input (from) length by the length of the substring
14680 	 * that got replaced.
14681 	 */
14682 	if (!strncmp(scan_string, substring, substring_length)) {
14683 		if (marker) {
14684 			string_out[(*to_index)++] = marker;
14685 		}
14686 		string_out[(*to_index)++] = substitution;
14687 		(*from_index) += substring_length;
14688 		return 1;
14689 	}
14690 	return 0;
14691 }
14692 
14693 /*******************************************************************************
14694 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
14695 * KMOD_MAX_NAME characters and performs various substitutions of common
14696 * prefixes & substrings as defined by tables in kext_panic_report.h.
14697 *******************************************************************************/
14698 static void compactIdentifier(
14699 	const char * identifier,
14700 	char       * identifier_out,
14701 	char      ** identifier_out_end);
14702 
14703 static void
14704 compactIdentifier(
14705 	const char * identifier,
14706 	char       * identifier_out,
14707 	char      ** identifier_out_end)
14708 {
14709 	uint32_t       from_index, to_index;
14710 	uint32_t       scan_from_index = 0;
14711 	uint32_t       scan_to_index   = 0;
14712 	subs_entry_t * subs_entry    = NULL;
14713 	int            did_sub       = 0;
14714 
14715 	from_index = to_index = 0;
14716 	identifier_out[0] = '\0';
14717 
14718 	/* Replace certain identifier prefixes with shorter @+character sequences.
14719 	 * Check the return value of substitute() so we only replace the prefix.
14720 	 */
14721 	for (subs_entry = &kext_identifier_prefix_subs[0];
14722 	    subs_entry->substring && !did_sub;
14723 	    subs_entry++) {
14724 		did_sub = substitute(identifier, identifier_out,
14725 		    &scan_to_index, &scan_from_index,
14726 		    subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
14727 	}
14728 	did_sub = 0;
14729 
14730 	/* Now scan through the identifier looking for the common substrings
14731 	 * and replacing them with shorter !+character sequences via substitute().
14732 	 */
14733 	for (/* see above */;
14734 	    scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
14735 	    /* see loop */) {
14736 		const char   * scan_string = &identifier[scan_from_index];
14737 
14738 		did_sub = 0;
14739 
14740 		if (scan_from_index) {
14741 			for (subs_entry = &kext_identifier_substring_subs[0];
14742 			    subs_entry->substring && !did_sub;
14743 			    subs_entry++) {
14744 				did_sub = substitute(scan_string, identifier_out,
14745 				    &scan_to_index, &scan_from_index,
14746 				    subs_entry->substring, '!', subs_entry->substitute);
14747 			}
14748 		}
14749 
14750 		/* If we didn't substitute, copy the input character to the output.
14751 		 */
14752 		if (!did_sub) {
14753 			identifier_out[scan_to_index++] = identifier[scan_from_index++];
14754 		}
14755 	}
14756 
14757 	identifier_out[scan_to_index] = '\0';
14758 	if (identifier_out_end) {
14759 		*identifier_out_end = &identifier_out[scan_to_index];
14760 	}
14761 
14762 	return;
14763 }
14764 #endif /* !defined(__arm__) && !defined(__arm64__) */
14765 
14766 /*******************************************************************************
14767 * assemble_identifier_and_version() adds to a string buffer a compacted
14768 * bundle identifier followed by a version string.
14769 *******************************************************************************/
14770 
14771 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
14772  */
14773 static size_t assemble_identifier_and_version(
14774 	kmod_info_t * kmod_info,
14775 	char        * identPlusVers,
14776 	size_t        bufSize);
14777 
14778 static size_t
14779 assemble_identifier_and_version(
14780 	kmod_info_t * kmod_info,
14781 	char        * identPlusVers,
14782 	size_t        bufSize)
14783 {
14784 	size_t result = 0;
14785 
14786 #if defined(__arm__) || defined(__arm64__)
14787 	result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME);
14788 #else
14789 	compactIdentifier(kmod_info->name, identPlusVers, NULL);
14790 	result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
14791 #endif
14792 	identPlusVers[result++] = '\t';         // increment for real char
14793 	identPlusVers[result] = '\0';         // don't increment for nul char
14794 	result = strlcat(identPlusVers, kmod_info->version, bufSize);
14795 	if (result >= bufSize) {
14796 		identPlusVers[bufSize - 1] = '\0';
14797 		result = bufSize - 1;
14798 	}
14799 
14800 	return result;
14801 }
14802 
14803 /*******************************************************************************
14804 * Assumes sKextLock is held.
14805 *******************************************************************************/
14806 /* static */
14807 int
14808 OSKext::saveLoadedKextPanicListTyped(
14809 	const char * prefix,
14810 	int          invertFlag,
14811 	int          libsFlag,
14812 	char       * paniclist,
14813 	uint32_t     list_size)
14814 {
14815 	int             result = -1;
14816 	unsigned int    count, i;
14817 
14818 	count = sLoadedKexts->getCount();
14819 	if (!count) {
14820 		goto finish;
14821 	}
14822 
14823 	i = count - 1;
14824 	do {
14825 		OSObject    * rawKext = sLoadedKexts->getObject(i);
14826 		OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
14827 		int           match;
14828 		size_t        identPlusVersLength;
14829 		size_t        tempLen;
14830 		char          identPlusVers[2 * KMOD_MAX_NAME];
14831 
14832 		if (!rawKext) {
14833 			printf("OSKext::saveLoadedKextPanicListTyped - "
14834 			    "NULL kext in loaded kext list; continuing\n");
14835 			continue;
14836 		}
14837 
14838 		if (!theKext) {
14839 			printf("OSKext::saveLoadedKextPanicListTyped - "
14840 			    "Kext type cast failed in loaded kext list; continuing\n");
14841 			continue;
14842 		}
14843 
14844 		/* Skip all built-in kexts.
14845 		 */
14846 		if (theKext->isKernelComponent()) {
14847 			continue;
14848 		}
14849 
14850 		kmod_info_t * kmod_info = theKext->kmod_info;
14851 
14852 		/* Filter for kmod name (bundle identifier).
14853 		 */
14854 		match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
14855 		if ((match && invertFlag) || (!match && !invertFlag)) {
14856 			continue;
14857 		}
14858 
14859 		/* Filter for libraries (kexts that have a compatible version).
14860 		 */
14861 		if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
14862 		    (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
14863 			continue;
14864 		}
14865 
14866 		if (!kmod_info ||
14867 		    !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
14868 			printf("kext scan stopped due to missing kmod_info page: %p\n",
14869 			    kmod_info);
14870 			goto finish;
14871 		}
14872 
14873 		identPlusVersLength = assemble_identifier_and_version(kmod_info,
14874 		    identPlusVers,
14875 		    sizeof(identPlusVers));
14876 		if (!identPlusVersLength) {
14877 			printf("error saving loaded kext info\n");
14878 			goto finish;
14879 		}
14880 
14881 		/* make sure everything fits and we null terminate.
14882 		 */
14883 		tempLen = strlcat(paniclist, identPlusVers, list_size);
14884 		if (tempLen >= list_size) {
14885 			// panic list is full, keep it and null terminate
14886 			paniclist[list_size - 1] = 0x00;
14887 			result = 0;
14888 			goto finish;
14889 		}
14890 		tempLen = strlcat(paniclist, "\n", list_size);
14891 		if (tempLen >= list_size) {
14892 			// panic list is full, keep it and null terminate
14893 			paniclist[list_size - 1] = 0x00;
14894 			result = 0;
14895 			goto finish;
14896 		}
14897 	} while (i--);
14898 
14899 	result = 0;
14900 finish:
14901 
14902 	return result;
14903 }
14904 
14905 /*********************************************************************
14906 *********************************************************************/
14907 /* static */
14908 void
14909 OSKext::saveLoadedKextPanicList(void)
14910 {
14911 	char     * newlist        = NULL;
14912 	uint32_t   newlist_size   = 0;
14913 
14914 	newlist_size = KEXT_PANICLIST_SIZE;
14915 	newlist = (char *)kalloc_data_tag(newlist_size,
14916 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
14917 
14918 	if (!newlist) {
14919 		OSKextLog(/* kext */ NULL,
14920 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
14921 		    "Couldn't allocate kext panic log buffer.");
14922 		goto finish;
14923 	}
14924 
14925 	newlist[0] = '\0';
14926 
14927 	// non-"com.apple." kexts
14928 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
14929 	    /* libs? */ -1, newlist, newlist_size) != 0) {
14930 		goto finish;
14931 	}
14932 	// "com.apple." nonlibrary kexts
14933 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
14934 	    /* libs? */ 0, newlist, newlist_size) != 0) {
14935 		goto finish;
14936 	}
14937 	// "com.apple." library kexts
14938 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
14939 	    /* libs? */ 1, newlist, newlist_size) != 0) {
14940 		goto finish;
14941 	}
14942 
14943 	if (loaded_kext_paniclist) {
14944 		kfree_data(loaded_kext_paniclist, loaded_kext_paniclist_size);
14945 	}
14946 	loaded_kext_paniclist = newlist;
14947 	newlist = NULL;
14948 	loaded_kext_paniclist_size = newlist_size;
14949 
14950 finish:
14951 	if (newlist) {
14952 		kfree_data(newlist, newlist_size);
14953 	}
14954 	return;
14955 }
14956 
14957 /*********************************************************************
14958 * Assumes sKextLock is held.
14959 *********************************************************************/
14960 void
14961 OSKext::savePanicString(bool isLoading)
14962 {
14963 	u_long len;
14964 
14965 	if (!kmod_info) {
14966 		return;         // do not goto finish here b/c of lock
14967 	}
14968 
14969 	len = assemble_identifier_and_version( kmod_info,
14970 	    (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
14971 	    (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
14972 	if (!len) {
14973 		printf("error saving unloaded kext info\n");
14974 		goto finish;
14975 	}
14976 
14977 	if (isLoading) {
14978 		last_loaded_strlen = len;
14979 		last_loaded_address = (void *)kmod_info->address;
14980 		last_loaded_size = kmod_info->size;
14981 		clock_get_uptime(&last_loaded_timestamp);
14982 	} else {
14983 		last_unloaded_strlen = len;
14984 		last_unloaded_address = (void *)kmod_info->address;
14985 		last_unloaded_size = kmod_info->size;
14986 		clock_get_uptime(&last_unloaded_timestamp);
14987 	}
14988 
14989 finish:
14990 	return;
14991 }
14992 
14993 /*********************************************************************
14994 *********************************************************************/
14995 /* static */
14996 void
14997 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
14998 {
14999 	if (last_loaded_strlen) {
15000 		printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n",
15001 		    AbsoluteTime_to_scalar(&last_loaded_timestamp),
15002 		    last_loaded_strlen, last_loaded_str_buf,
15003 		    last_loaded_address, last_loaded_size);
15004 	}
15005 
15006 	if (last_unloaded_strlen) {
15007 		printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n",
15008 		    AbsoluteTime_to_scalar(&last_unloaded_timestamp),
15009 		    last_unloaded_strlen, last_unloaded_str_buf,
15010 		    last_unloaded_address, last_unloaded_size);
15011 	}
15012 
15013 	printf_func("loaded kexts:\n");
15014 	if (loaded_kext_paniclist &&
15015 	    pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
15016 	    loaded_kext_paniclist[0]) {
15017 		printf_func("%.*s",
15018 		    strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
15019 		    loaded_kext_paniclist);
15020 	} else {
15021 		printf_func("(none)\n");
15022 	}
15023 	return;
15024 }
15025 
15026 /*********************************************************************
15027 * Assumes sKextLock is held.
15028 *********************************************************************/
15029 /* static */
15030 void
15031 OSKext::updateLoadedKextSummaries(void)
15032 {
15033 	kern_return_t result = KERN_FAILURE;
15034 	OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
15035 	OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
15036 	OSKext *aKext;
15037 	vm_map_offset_t start, end;
15038 	size_t summarySize = 0;
15039 	size_t size;
15040 	u_int count;
15041 	u_int maxKexts;
15042 	u_int i, j;
15043 	OSKextActiveAccount * accountingList;
15044 	OSKextActiveAccount * prevAccountingList;
15045 	uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
15046 
15047 	prevAccountingList = NULL;
15048 	prevAccountingListCount = 0;
15049 
15050 #if DEVELOPMENT || DEBUG
15051 	if (IORecursiveLockHaveLock(sKextLock) == false) {
15052 		panic("sKextLock must be held");
15053 	}
15054 #endif
15055 
15056 	IOLockLock(sKextSummariesLock);
15057 
15058 	count = sLoadedKexts->getCount();
15059 	for (i = 0, maxKexts = 0; i < count; ++i) {
15060 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
15061 		maxKexts += (aKext && aKext->isExecutable());
15062 	}
15063 
15064 	if (!maxKexts) {
15065 		goto finish;
15066 	}
15067 	if (maxKexts < kOSKextTypicalLoadCount) {
15068 		maxKexts = kOSKextTypicalLoadCount;
15069 	}
15070 
15071 	/* Calculate the size needed for the new summary headers.
15072 	 */
15073 
15074 	size = sizeof(*gLoadedKextSummaries);
15075 	size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
15076 	size = round_page(size);
15077 
15078 	if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
15079 		if (gLoadedKextSummaries) {
15080 			kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
15081 			gLoadedKextSummaries = NULL;
15082 			gLoadedKextSummariesTimestamp = mach_absolute_time();
15083 			sLoadedKextSummariesAllocSize = 0;
15084 		}
15085 		result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size,
15086 		    KMA_DATA, VM_KERN_MEMORY_OSKEXT);
15087 		if (result != KERN_SUCCESS) {
15088 			goto finish;
15089 		}
15090 		summaryHeader = summaryHeaderAlloc;
15091 		summarySize = size;
15092 	} else {
15093 		summaryHeader = gLoadedKextSummaries;
15094 		summarySize = sLoadedKextSummariesAllocSize;
15095 
15096 		start = (vm_map_offset_t) summaryHeader;
15097 		end = start + summarySize;
15098 		result = vm_map_protect(kernel_map,
15099 		    start,
15100 		    end,
15101 		    VM_PROT_DEFAULT,
15102 		    FALSE);
15103 		if (result != KERN_SUCCESS) {
15104 			goto finish;
15105 		}
15106 	}
15107 
15108 	/* Populate the summary header.
15109 	 */
15110 
15111 	bzero(summaryHeader, summarySize);
15112 	summaryHeader->version = kOSKextLoadedKextSummaryVersion;
15113 	summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
15114 
15115 	/* Populate each kext summary.
15116 	 */
15117 
15118 	count = sLoadedKexts->getCount();
15119 	accountingListAlloc = 0;
15120 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
15121 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
15122 		if (!aKext || !aKext->isExecutable()) {
15123 			continue;
15124 		}
15125 
15126 		aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
15127 		summaryHeader->numSummaries++;
15128 		accountingListAlloc++;
15129 	}
15130 
15131 	accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
15132 	accountingListCount = 0;
15133 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
15134 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
15135 		if (!aKext || !aKext->isExecutable()) {
15136 			continue;
15137 		}
15138 
15139 		OSKextActiveAccount activeAccount;
15140 		aKext->updateActiveAccount(&activeAccount);
15141 		// order by address
15142 		for (idx = 0; idx < accountingListCount; idx++) {
15143 			if (activeAccount.address < accountingList[idx].address) {
15144 				break;
15145 			}
15146 		}
15147 		bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
15148 		accountingList[idx] = activeAccount;
15149 		accountingListCount++;
15150 	}
15151 	assert(accountingListCount == accountingListAlloc);
15152 	/* Write protect the buffer and move it into place.
15153 	 */
15154 
15155 	start = (vm_map_offset_t) summaryHeader;
15156 	end = start + summarySize;
15157 
15158 	result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
15159 	if (result != KERN_SUCCESS) {
15160 		goto finish;
15161 	}
15162 
15163 	gLoadedKextSummaries = summaryHeader;
15164 	gLoadedKextSummariesTimestamp = mach_absolute_time();
15165 	sLoadedKextSummariesAllocSize = summarySize;
15166 	summaryHeaderAlloc = NULL;
15167 
15168 	/* Call the magic breakpoint function through a static function pointer so
15169 	 * the compiler can't optimize the function away.
15170 	 */
15171 	if (sLoadedKextSummariesUpdated) {
15172 		(*sLoadedKextSummariesUpdated)();
15173 	}
15174 
15175 	IOSimpleLockLock(sKextAccountsLock);
15176 	prevAccountingList      = sKextAccounts;
15177 	prevAccountingListCount = sKextAccountsCount;
15178 	sKextAccounts           = accountingList;
15179 	sKextAccountsCount      = accountingListCount;
15180 	IOSimpleLockUnlock(sKextAccountsLock);
15181 
15182 finish:
15183 	IOLockUnlock(sKextSummariesLock);
15184 
15185 	/* If we had to allocate a new buffer but failed to generate the summaries,
15186 	 * free that now.
15187 	 */
15188 	if (summaryHeaderAlloc) {
15189 		kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
15190 	}
15191 	if (prevAccountingList) {
15192 		IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
15193 	}
15194 
15195 	return;
15196 }
15197 
15198 /*********************************************************************
15199 *********************************************************************/
15200 void
15201 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
15202 {
15203 	OSSharedPtr<OSData> uuid;
15204 
15205 	strlcpy(summary->name, getIdentifierCString(),
15206 	    sizeof(summary->name));
15207 
15208 	uuid = copyUUID();
15209 	if (uuid) {
15210 		memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
15211 	}
15212 
15213 	if (flags.builtin) {
15214 //      this value will stop lldb from parsing the mach-o header
15215 //      summary->address = UINT64_MAX;
15216 //      summary->size = 0;
15217 		summary->address = kmod_info->address;
15218 		summary->size = kmod_info->size;
15219 	} else {
15220 		summary->address = kmod_info->address;
15221 		summary->size = kmod_info->size;
15222 	}
15223 	summary->version = getVersion();
15224 	summary->loadTag = kmod_info->id;
15225 	summary->flags = 0;
15226 	summary->reference_list = (uint64_t) kmod_info->reference_list;
15227 
15228 	summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size);
15229 	if (summary->text_exec_address == 0) {
15230 		// Fallback to __TEXT
15231 		summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size);
15232 	}
15233 	return;
15234 }
15235 
15236 /*********************************************************************
15237 *********************************************************************/
15238 
15239 void
15240 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
15241 {
15242 	kernel_mach_header_t     *hdr = NULL;
15243 	kernel_segment_command_t *seg = NULL;
15244 
15245 	bzero(accountp, sizeof(*accountp));
15246 
15247 	hdr = (kernel_mach_header_t *)kmod_info->address;
15248 	if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) {
15249 		/*
15250 		 * If this kext supports split segments (or is in a new
15251 		 * MH_FILESET kext collection), use the first
15252 		 * executable segment as the range for instructions
15253 		 * (and thus for backtracing.
15254 		 */
15255 		for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
15256 			if (seg->initprot & VM_PROT_EXECUTE) {
15257 				break;
15258 			}
15259 		}
15260 	}
15261 	if (seg) {
15262 		accountp->address = seg->vmaddr;
15263 		if (accountp->address) {
15264 			accountp->address_end = seg->vmaddr + seg->vmsize;
15265 		}
15266 	} else {
15267 		/* For non-split kexts and for kexts without executable
15268 		 * segments, just use the kmod_info range (as the kext
15269 		 * is either all in one range or should not show up in
15270 		 * instruction backtraces).
15271 		 */
15272 		accountp->address = kmod_info->address;
15273 		if (accountp->address) {
15274 			accountp->address_end = kmod_info->address + kmod_info->size;
15275 		}
15276 	}
15277 
15278 	accountp->account = this->account;
15279 }
15280 
15281 bool
15282 OSKext::isDriverKit(void)
15283 {
15284 	OSString *bundleType;
15285 
15286 	if (infoDict) {
15287 		bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
15288 		if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
15289 			return TRUE;
15290 		}
15291 	}
15292 	return FALSE;
15293 }
15294 
15295 bool
15296 OSKext::isInFileset(void)
15297 {
15298 	if (!kmod_info) {
15299 		goto check_prelinked;
15300 	}
15301 
15302 	if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) {
15303 		return true;
15304 	}
15305 
15306 check_prelinked:
15307 	if (isPrelinked()) {
15308 		/*
15309 		 * If we haven't setup kmod_info yet, but we know
15310 		 * we're loading a prelinked kext in an MH_FILESET KC,
15311 		 * then return true
15312 		 */
15313 		kc_format_t kc_format;
15314 		if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
15315 			return true;
15316 		}
15317 	}
15318 	return false;
15319 }
15320 
15321 bool
15322 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg)
15323 {
15324 	kern_return_t result;
15325 	if (!super::init()) {
15326 		return false;
15327 	}
15328 	if (seg == nullptr) {
15329 		return false;
15330 	}
15331 	result = kmem_alloc(kernel_map, (vm_offset_t *)&data, seg->vmsize,
15332 	    KMA_PAGEABLE, VM_KERN_MEMORY_KEXT);
15333 	if (result != KERN_SUCCESS) {
15334 		return false;
15335 	}
15336 	memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize);
15337 	savedSegment = seg;
15338 	vmsize = seg->vmsize;
15339 	vmaddr = seg->vmaddr;
15340 	return true;
15341 }
15342 
15343 OSSharedPtr<OSKextSavedMutableSegment>
15344 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg)
15345 {
15346 	OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>();
15347 	if (me && !me->initWithSegment(seg)) {
15348 		return nullptr;
15349 	}
15350 	return me;
15351 }
15352 
15353 void
15354 OSKextSavedMutableSegment::free(void)
15355 {
15356 	if (data) {
15357 		kmem_free(kernel_map, (vm_offset_t)data, vmsize);
15358 	}
15359 }
15360 
15361 vm_offset_t
15362 OSKextSavedMutableSegment::getVMAddr() const
15363 {
15364 	return vmaddr;
15365 }
15366 
15367 vm_offset_t
15368 OSKextSavedMutableSegment::getVMSize() const
15369 {
15370 	return vmsize;
15371 }
15372 
15373 OSReturn
15374 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg)
15375 {
15376 	if (seg != savedSegment) {
15377 		return kOSKextReturnInvalidArgument;
15378 	}
15379 	if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) {
15380 		return kOSKextReturnInvalidArgument;
15381 	}
15382 	memcpy((void *)seg->vmaddr, data, vmsize);
15383 	return kOSReturnSuccess;
15384 }
15385 
15386 extern "C" kern_return_t
15387 OSKextSetReceiptQueried(void)
15388 {
15389 	OSKextLog(/* kext */ NULL,
15390 	    kOSKextLogStepLevel | kOSKextLogGeneralFlag,
15391 	    "Setting kext receipt as queried");
15392 
15393 	IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue);
15394 	return KERN_SUCCESS;
15395 }
15396 
15397 extern "C" const vm_allocation_site_t *
15398 OSKextGetAllocationSiteForCaller(uintptr_t address)
15399 {
15400 	OSKextActiveAccount *  active;
15401 	vm_allocation_site_t * site;
15402 	vm_allocation_site_t * releasesite;
15403 
15404 	uint32_t baseIdx;
15405 	uint32_t lim;
15406 #if  __has_feature(ptrauth_calls)
15407 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
15408 #endif /*  __has_feature(ptrauth_calls) */
15409 
15410 	IOSimpleLockLock(sKextAccountsLock);
15411 	site = releasesite = NULL;
15412 
15413 	// bsearch sKextAccounts list
15414 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15415 		active = &sKextAccounts[baseIdx + (lim >> 1)];
15416 		if ((address >= active->address) && (address < active->address_end)) {
15417 			site = &active->account->site;
15418 			if (!site->tag) {
15419 				vm_tag_alloc_locked(site, &releasesite);
15420 			}
15421 			break;
15422 		} else if (address > active->address) {
15423 			// move right
15424 			baseIdx += (lim >> 1) + 1;
15425 			lim--;
15426 		}
15427 		// else move left
15428 	}
15429 	IOSimpleLockUnlock(sKextAccountsLock);
15430 	if (releasesite) {
15431 		kern_allocation_name_release(releasesite);
15432 	}
15433 
15434 	return site;
15435 }
15436 
15437 #if DEVELOPMENT || DEBUG
15438 extern "C" void
15439 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *))
15440 {
15441 	OSKextActiveAccount *  active;
15442 
15443 	uint32_t baseIdx;
15444 	uint32_t lim;
15445 #if  __has_feature(ptrauth_calls)
15446 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
15447 #endif /*  __has_feature(ptrauth_calls) */
15448 
15449 	IOSimpleLockLock(sKextAccountsLock);
15450 
15451 	// bsearch sKextAccounts list
15452 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15453 		active = &sKextAccounts[baseIdx + (lim >> 1)];
15454 		if ((address >= active->address) && (address < active->address_end)) {
15455 			cb(&active->account->task_refgrp);
15456 			break;
15457 		} else if (address > active->address) {
15458 			// move right
15459 			baseIdx += (lim >> 1) + 1;
15460 			lim--;
15461 		}
15462 		// else move left
15463 	}
15464 	IOSimpleLockUnlock(sKextAccountsLock);
15465 }
15466 #endif /* DEVELOPMENT || DEBUG */
15467 
15468 extern "C" uint32_t
15469 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
15470 {
15471 	OSKextAccount * account = (typeof(account))site;
15472 	const char    * kname;
15473 
15474 	if (name) {
15475 		if (account->kext) {
15476 			kname = account->kext->getIdentifierCString();
15477 		} else {
15478 			kname = "<>";
15479 		}
15480 		strlcpy(name, kname, namelen);
15481 	}
15482 
15483 	return account->loadTag;
15484 }
15485 
15486 extern "C" void
15487 OSKextFreeSite(vm_allocation_site_t * site)
15488 {
15489 	OSKextAccount * freeAccount = (typeof(freeAccount))site;
15490 	IOFreeType(freeAccount, OSKextAccount);
15491 }
15492 
15493 /*********************************************************************
15494 *********************************************************************/
15495 
15496 #if CONFIG_IMAGEBOOT
15497 int
15498 OSKextGetUUIDForName(const char *name, uuid_t uuid)
15499 {
15500 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name);
15501 	if (!kext) {
15502 		return 1;
15503 	}
15504 
15505 	OSSharedPtr<OSData> uuid_data = kext->copyUUID();
15506 	if (uuid_data) {
15507 		memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
15508 		return 0;
15509 	}
15510 
15511 	return 1;
15512 }
15513 #endif
15514 
15515 static int
15516 sysctl_willuserspacereboot
15517 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
15518 {
15519 	int new_value = 0, old_value = 0, changed = 0;
15520 	int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
15521 	if (error) {
15522 		return error;
15523 	}
15524 	if (changed) {
15525 		OSKext::willUserspaceReboot();
15526 	}
15527 	return 0;
15528 }
15529 
15530 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot,
15531     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
15532     NULL, 0, sysctl_willuserspacereboot, "I", "");
15533