xref: /xnu-8020.101.4/libkern/c++/OSKext.cpp (revision e7776783b89a353188416a9a346c6cdb4928faad)
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, 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, VM_KERN_MEMORY_OSKEXT)) {
3421 		/* How's this for cheesy? The kernel is only asked to extract
3422 		 * kext plists so we tailor the log messages.
3423 		 */
3424 		if (isKernel()) {
3425 			OSKextLog(this,
3426 			    kOSKextLogErrorLevel |
3427 			    kOSKextLogArchiveFlag,
3428 			    "Allocation failure extracting %s from mkext.", name);
3429 		} else {
3430 			OSKextLog(this,
3431 			    kOSKextLogErrorLevel |
3432 			    kOSKextLogArchiveFlag,
3433 			    "Allocation failure extracting %s from mkext for kext %s.",
3434 			    name, getIdentifierCString());
3435 		}
3436 
3437 		goto finish;
3438 	}
3439 	uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3440 	if (!uncompressedData) {
3441 		if (isKernel()) {
3442 			OSKextLog(this,
3443 			    kOSKextLogErrorLevel |
3444 			    kOSKextLogArchiveFlag,
3445 			    "Allocation failure extracting %s from mkext.", name);
3446 		} else {
3447 			OSKextLog(this,
3448 			    kOSKextLogErrorLevel |
3449 			    kOSKextLogArchiveFlag,
3450 			    "Allocation failure extracting %s from mkext for kext %s.",
3451 			    name, getIdentifierCString());
3452 		}
3453 		goto finish;
3454 	}
3455 	uncompressedData->setDeallocFunction(&osdata_kmem_free);
3456 
3457 	if (isKernel()) {
3458 		OSKextLog(this,
3459 		    kOSKextLogDetailLevel |
3460 		    kOSKextLogArchiveFlag,
3461 		    "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3462 		    name, compressedSize, fullSize);
3463 	} else {
3464 		OSKextLog(this,
3465 		    kOSKextLogDetailLevel |
3466 		    kOSKextLogArchiveFlag,
3467 		    "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3468 		    getIdentifierCString(), name, compressedSize, fullSize);
3469 	}
3470 
3471 	bzero(&zstream, sizeof(zstream));
3472 	zstream.next_in   = (UInt8 *)data;
3473 	zstream.avail_in  = compressedSize;
3474 
3475 	zstream.next_out  = uncompressedDataBuffer;
3476 	zstream.avail_out = fullSize;
3477 
3478 	zstream.zalloc    = z_alloc;
3479 	zstream.zfree     = z_free;
3480 
3481 	zlib_result = inflateInit(&zstream);
3482 	if (Z_OK != zlib_result) {
3483 		if (isKernel()) {
3484 			OSKextLog(this,
3485 			    kOSKextLogErrorLevel |
3486 			    kOSKextLogArchiveFlag,
3487 			    "Mkext error; zlib inflateInit failed (%d) for %s.",
3488 			    zlib_result, name);
3489 		} else {
3490 			OSKextLog(this,
3491 			    kOSKextLogErrorLevel |
3492 			    kOSKextLogArchiveFlag,
3493 			    "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3494 			    getIdentifierCString(), zlib_result, name);
3495 		}
3496 		goto finish;
3497 	} else {
3498 		zstream_inited = true;
3499 	}
3500 
3501 	zlib_result = inflate(&zstream, Z_FINISH);
3502 
3503 	if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3504 		uncompressedSize = zstream.total_out;
3505 	} else {
3506 		if (isKernel()) {
3507 			OSKextLog(this,
3508 			    kOSKextLogErrorLevel |
3509 			    kOSKextLogArchiveFlag,
3510 			    "Mkext error; zlib inflate failed (%d) for %s.",
3511 			    zlib_result, name);
3512 		} else {
3513 			OSKextLog(this,
3514 			    kOSKextLogErrorLevel |
3515 			    kOSKextLogArchiveFlag,
3516 			    "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3517 			    getIdentifierCString(), zlib_result, name);
3518 		}
3519 		if (zstream.msg) {
3520 			OSKextLog(this,
3521 			    kOSKextLogErrorLevel |
3522 			    kOSKextLogArchiveFlag,
3523 			    "zlib error: %s.", zstream.msg);
3524 		}
3525 		goto finish;
3526 	}
3527 
3528 	if (uncompressedSize != fullSize) {
3529 		if (isKernel()) {
3530 			OSKextLog(this,
3531 			    kOSKextLogErrorLevel |
3532 			    kOSKextLogArchiveFlag,
3533 			    "Mkext error; zlib inflate discrepancy for %s, "
3534 			    "uncompressed size != original size.", name);
3535 		} else {
3536 			OSKextLog(this,
3537 			    kOSKextLogErrorLevel |
3538 			    kOSKextLogArchiveFlag,
3539 			    "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3540 			    "uncompressed size != original size.",
3541 			    getIdentifierCString(), name);
3542 		}
3543 		goto finish;
3544 	}
3545 
3546 	result = os::move(uncompressedData);
3547 
3548 finish:
3549 	/* Don't bother checking return, nothing we can do on fail.
3550 	 */
3551 	if (zstream_inited) {
3552 		inflateEnd(&zstream);
3553 	}
3554 
3555 	return result;
3556 }
3557 
3558 /*********************************************************************
3559 *********************************************************************/
3560 /* static */
3561 OSReturn
loadFromMkext(OSKextLogSpec clientLogFilter,char * mkextBuffer,uint32_t mkextBufferLength,char ** logInfoOut,uint32_t * logInfoLengthOut)3562 OSKext::loadFromMkext(
3563 	OSKextLogSpec   clientLogFilter,
3564 	char          * mkextBuffer,
3565 	uint32_t        mkextBufferLength,
3566 	char         ** logInfoOut,
3567 	uint32_t      * logInfoLengthOut)
3568 {
3569 	OSReturn         result                      = kOSReturnError;
3570 	OSReturn         tempResult                  = kOSReturnError;
3571 
3572 	OSSharedPtr<OSData>        mkextData;
3573 	OSSharedPtr<OSDictionary>  mkextPlist;
3574 
3575 	OSSharedPtr<OSArray>       logInfoArray;
3576 	OSSharedPtr<OSSerialize>   serializer;
3577 
3578 	OSString       * predicate                   = NULL;        // do not release
3579 	OSDictionary   * requestArgs                 = NULL;        // do not release
3580 
3581 	OSString       * kextIdentifier              = NULL;        // do not release
3582 	OSNumber       * startKextExcludeNum         = NULL;        // do not release
3583 	OSNumber       * startMatchingExcludeNum     = NULL;        // do not release
3584 	OSBoolean      * delayAutounloadBool         = NULL;        // do not release
3585 	OSArray        * personalityNames            = NULL;        // do not release
3586 
3587 	/* Default values for these two options: regular autounload behavior,
3588 	 * load all kexts, send no personalities.
3589 	 */
3590 	Boolean            delayAutounload           = false;
3591 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
3592 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3593 
3594 	IORecursiveLockLock(sKextLock);
3595 
3596 	if (logInfoOut) {
3597 		*logInfoOut = NULL;
3598 		*logInfoLengthOut = 0;
3599 	}
3600 
3601 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3602 
3603 	OSKextLog(/* kext */ NULL,
3604 	    kOSKextLogDebugLevel |
3605 	    kOSKextLogIPCFlag,
3606 	    "Received kext load request from user space.");
3607 
3608 	/* Regardless of processing, the fact that we have gotten here means some
3609 	 * user-space program is up and talking to us, so we'll switch our kext
3610 	 * registration to reflect that.
3611 	 */
3612 	if (!sUserLoadsActive) {
3613 		OSKextLog(/* kext */ NULL,
3614 		    kOSKextLogProgressLevel |
3615 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3616 		    "Switching to late startup (user-space) kext loading policy.");
3617 
3618 		sUserLoadsActive = true;
3619 	}
3620 
3621 	if (!sLoadEnabled) {
3622 		OSKextLog(/* kext */ NULL,
3623 		    kOSKextLogErrorLevel |
3624 		    kOSKextLogLoadFlag,
3625 		    "Kext loading is disabled.");
3626 		result = kOSKextReturnDisabled;
3627 		goto finish;
3628 	}
3629 
3630 	/* Note that we do not set a dealloc function on this OSData
3631 	 * object! No references to it can remain after the loadFromMkext()
3632 	 * call since we are in a MIG function, and will vm_deallocate()
3633 	 * the buffer.
3634 	 */
3635 	mkextData = OSData::withBytesNoCopy(mkextBuffer,
3636 	    mkextBufferLength);
3637 	if (!mkextData) {
3638 		OSKextLog(/* kext */ NULL,
3639 		    kOSKextLogErrorLevel |
3640 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3641 		    "Failed to create wrapper for kext load request.");
3642 		result = kOSKextReturnNoMemory;
3643 		goto finish;
3644 	}
3645 
3646 	result = readMkext2Archive(mkextData.get(), mkextPlist, NULL);
3647 	if (result != kOSReturnSuccess) {
3648 		OSKextLog(/* kext */ NULL,
3649 		    kOSKextLogErrorLevel |
3650 		    kOSKextLogLoadFlag,
3651 		    "Failed to read kext load request.");
3652 		goto finish;
3653 	}
3654 
3655 	predicate = _OSKextGetRequestPredicate(mkextPlist.get());
3656 	if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3657 		OSKextLog(/* kext */ NULL,
3658 		    kOSKextLogErrorLevel |
3659 		    kOSKextLogLoadFlag,
3660 		    "Received kext load request with no predicate; skipping.");
3661 		result = kOSKextReturnInvalidArgument;
3662 		goto finish;
3663 	}
3664 
3665 	requestArgs = OSDynamicCast(OSDictionary,
3666 	    mkextPlist->getObject(kKextRequestArgumentsKey));
3667 	if (!requestArgs || !requestArgs->getCount()) {
3668 		OSKextLog(/* kext */ NULL,
3669 		    kOSKextLogErrorLevel |
3670 		    kOSKextLogLoadFlag,
3671 		    "Received kext load request with no arguments.");
3672 		result = kOSKextReturnInvalidArgument;
3673 		goto finish;
3674 	}
3675 
3676 	kextIdentifier = OSDynamicCast(OSString,
3677 	    requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3678 
3679 	if (!kextIdentifier) {
3680 		OSKextLog(/* kext */ NULL,
3681 		    kOSKextLogErrorLevel |
3682 		    kOSKextLogLoadFlag,
3683 		    "Received kext load request with no kext identifier.");
3684 		result = kOSKextReturnInvalidArgument;
3685 		goto finish;
3686 	}
3687 
3688 	startKextExcludeNum = OSDynamicCast(OSNumber,
3689 	    requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3690 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
3691 	    requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3692 	delayAutounloadBool = OSDynamicCast(OSBoolean,
3693 	    requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3694 	personalityNames = OSDynamicCast(OSArray,
3695 	    requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3696 
3697 	if (delayAutounloadBool) {
3698 		delayAutounload = delayAutounloadBool->getValue();
3699 	}
3700 	if (startKextExcludeNum) {
3701 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3702 	}
3703 	if (startMatchingExcludeNum) {
3704 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3705 	}
3706 
3707 	OSKextLog(/* kext */ NULL,
3708 	    kOSKextLogProgressLevel |
3709 	    kOSKextLogIPCFlag,
3710 	    "Received request from user space to load kext %s.",
3711 	    kextIdentifier->getCStringNoCopy());
3712 
3713 	/* Load the kext, with no deferral, since this is a load from outside
3714 	 * the kernel.
3715 	 * xxx - Would like a better way to handle the default values for the
3716 	 * xxx - start/match opt args.
3717 	 */
3718 	result = OSKext::loadKextWithIdentifier(
3719 		kextIdentifier,
3720 		/* kextRef */ NULL,
3721 		/* allowDefer */ false,
3722 		delayAutounload,
3723 		startKextExcludeLevel,
3724 		startMatchingExcludeLevel,
3725 		personalityNames);
3726 	if (result != kOSReturnSuccess) {
3727 		goto finish;
3728 	}
3729 	/* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue
3730 	 * for matching via a separate IOKit calldown.
3731 	 */
3732 
3733 finish:
3734 
3735 	/* Gather up the collected log messages for user space. Any
3736 	 * error messages past this call will not make it up as log messages
3737 	 * but will be in the system log.
3738 	 */
3739 	logInfoArray = OSKext::clearUserSpaceLogFilter();
3740 
3741 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
3742 		tempResult = OSKext::serializeLogInfo(logInfoArray.get(),
3743 		    logInfoOut, logInfoLengthOut);
3744 		if (tempResult != kOSReturnSuccess) {
3745 			result = tempResult;
3746 		}
3747 	}
3748 
3749 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3750 
3751 	IORecursiveLockUnlock(sKextLock);
3752 
3753 	/* Note: mkextDataObject will have been retained by every kext w/an
3754 	 * executable in it. That should all have been flushed out at the
3755 	 * and of the load operation, but you never know....
3756 	 */
3757 	if (mkextData && mkextData->getRetainCount() > 1) {
3758 		OSKextLog(/* kext */ NULL,
3759 		    kOSKextLogErrorLevel |
3760 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3761 		    "Kext load request buffer from user space still retained by a kext; "
3762 		    "probable memory leak.");
3763 	}
3764 
3765 	return result;
3766 }
3767 
3768 #endif // CONFIG_KXLD
3769 
3770 /*********************************************************************
3771 *********************************************************************/
3772 /* static */
3773 OSReturn
serializeLogInfo(OSArray * logInfoArray,char ** logInfoOut,uint32_t * logInfoLengthOut)3774 OSKext::serializeLogInfo(
3775 	OSArray   * logInfoArray,
3776 	char     ** logInfoOut,
3777 	uint32_t  * logInfoLengthOut)
3778 {
3779 	OSReturn        result      = kOSReturnError;
3780 	char          * buffer      = NULL;
3781 	kern_return_t   kmem_result = KERN_FAILURE;
3782 	OSSharedPtr<OSSerialize>  serializer;
3783 	char         * logInfo            = NULL;        // returned by reference
3784 	uint32_t       logInfoLength      = 0;
3785 
3786 	if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
3787 		OSKextLog(/* kext */ NULL,
3788 		    kOSKextLogErrorLevel |
3789 		    kOSKextLogIPCFlag,
3790 		    "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3791 		/* Bad programmer. */
3792 		result = kOSKextReturnInvalidArgument;
3793 		goto finish;
3794 	}
3795 
3796 	serializer = OSSerialize::withCapacity(0);
3797 	if (!serializer) {
3798 		OSKextLog(/* kext */ NULL,
3799 		    kOSKextLogErrorLevel |
3800 		    kOSKextLogIPCFlag,
3801 		    "Failed to create serializer on log info for request from user space.");
3802 		/* Incidental error; we're going to (try to) allow the request
3803 		 * itself to succeed. */
3804 	}
3805 
3806 	if (!logInfoArray->serialize(serializer.get())) {
3807 		OSKextLog(/* kext */ NULL,
3808 		    kOSKextLogErrorLevel |
3809 		    kOSKextLogIPCFlag,
3810 		    "Failed to serialize log info for request from user space.");
3811 		/* Incidental error; we're going to (try to) allow the request
3812 		 * itself to succeed. */
3813 	} else {
3814 		logInfo = serializer->text();
3815 		logInfoLength = serializer->getLength();
3816 
3817 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT);
3818 		if (kmem_result != KERN_SUCCESS) {
3819 			OSKextLog(/* kext */ NULL,
3820 			    kOSKextLogErrorLevel |
3821 			    kOSKextLogIPCFlag,
3822 			    "Failed to copy log info for request from user space.");
3823 			/* Incidental error; we're going to (try to) allow the request
3824 			 * to succeed. */
3825 		} else {
3826 			/* 11981737 - clear uninitialized data in last page */
3827 			bzero((void *)(buffer + logInfoLength),
3828 			    (round_page(logInfoLength) - logInfoLength));
3829 			memcpy(buffer, logInfo, logInfoLength);
3830 			*logInfoOut = buffer;
3831 			*logInfoLengthOut = logInfoLength;
3832 		}
3833 	}
3834 
3835 	result = kOSReturnSuccess;
3836 finish:
3837 	return result;
3838 }
3839 
3840 #if PRAGMA_MARK
3841 #pragma mark Instance Management Methods
3842 #endif
3843 /*********************************************************************
3844 *********************************************************************/
3845 OSSharedPtr<OSKext>
lookupKextWithIdentifier(const char * kextIdentifier)3846 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
3847 {
3848 	OSSharedPtr<OSKext> foundKext;
3849 
3850 	IORecursiveLockLock(sKextLock);
3851 	foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain);
3852 	IORecursiveLockUnlock(sKextLock);
3853 
3854 	return foundKext;
3855 }
3856 
3857 /*********************************************************************
3858 *********************************************************************/
3859 OSSharedPtr<OSKext>
lookupKextWithIdentifier(OSString * kextIdentifier)3860 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
3861 {
3862 	return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
3863 }
3864 
3865 /*********************************************************************
3866 *********************************************************************/
3867 OSSharedPtr<OSKext>
lookupKextWithLoadTag(uint32_t aTag)3868 OSKext::lookupKextWithLoadTag(uint32_t aTag)
3869 {
3870 	OSSharedPtr<OSKext> foundKext;             // returned
3871 	uint32_t i, j;
3872 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
3873 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3874 
3875 	IORecursiveLockLock(sKextLock);
3876 
3877 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3878 		for (i = 0; i < count[j]; i++) {
3879 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3880 			if (thisKext->getLoadTag() == aTag) {
3881 				foundKext.reset(thisKext, OSRetain);
3882 				goto finish;
3883 			}
3884 		}
3885 	}
3886 
3887 finish:
3888 	IORecursiveLockUnlock(sKextLock);
3889 
3890 	return foundKext;
3891 }
3892 
3893 /*********************************************************************
3894 *********************************************************************/
3895 OSSharedPtr<OSKext>
lookupKextWithAddress(vm_address_t address)3896 OSKext::lookupKextWithAddress(vm_address_t address)
3897 {
3898 	OSSharedPtr<OSKext> foundKext;             // returned
3899 	uint32_t count, i;
3900 	kmod_info_t *kmod_info;
3901 	vm_address_t originalAddress;
3902 #if defined(__arm64__)
3903 	uint64_t   textExecBase;
3904 	size_t     textExecSize;
3905 #endif /* defined(__arm64__) */
3906 
3907 	originalAddress = address;
3908 #if  __has_feature(ptrauth_calls)
3909 	address = (vm_address_t)VM_KERNEL_STRIP_PTR(address);
3910 #endif /*  __has_feature(ptrauth_calls) */
3911 
3912 	IORecursiveLockLock(sKextLock);
3913 
3914 	count = sLoadedKexts->getCount();
3915 	for (i = 0; i < count; i++) {
3916 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3917 		if (thisKext == sKernelKext) {
3918 			continue;
3919 		}
3920 		if (thisKext->kmod_info && thisKext->kmod_info->address) {
3921 			kmod_info = thisKext->kmod_info;
3922 			vm_address_t kext_start = kmod_info->address;
3923 			vm_address_t kext_end = kext_start + kmod_info->size;
3924 			if ((kext_start <= address) && (address < kext_end)) {
3925 				foundKext.reset(thisKext, OSRetain);
3926 				goto finish;
3927 			}
3928 #if defined(__arm64__)
3929 			textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize);
3930 			if ((textExecBase <= address) && (address < textExecBase + textExecSize)) {
3931 				foundKext.reset(thisKext, OSRetain);
3932 				goto finish;
3933 			}
3934 #endif /* defined (__arm64__) */
3935 		}
3936 	}
3937 	if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) {
3938 		foundKext.reset(sKernelKext, OSRetain);
3939 		goto finish;
3940 	}
3941 	/*
3942 	 * DriverKit userspace executables do not have a kernel linkedExecutable,
3943 	 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address
3944 	 * here, so use the original address passed to this method.
3945 	 *
3946 	 * This is supposed to be used for logging reasons only. When logd
3947 	 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
3948 	 * remove it here before checking it against the LoadTag.
3949 	 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
3950 	 */
3951 
3952 	address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
3953 	count = sLoadedDriverKitKexts->getCount();
3954 	for (i = 0; i < count; i++) {
3955 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
3956 		if (thisKext->getLoadTag() == address) {
3957 			foundKext.reset(thisKext, OSRetain);
3958 		}
3959 	}
3960 
3961 finish:
3962 	IORecursiveLockUnlock(sKextLock);
3963 
3964 	return foundKext;
3965 }
3966 
3967 OSSharedPtr<OSData>
copyKextUUIDForAddress(OSNumber * address)3968 OSKext::copyKextUUIDForAddress(OSNumber *address)
3969 {
3970 	OSSharedPtr<OSData>   uuid;
3971 	OSSharedPtr<OSKext>   kext;
3972 
3973 	if (!address) {
3974 		return NULL;
3975 	}
3976 
3977 #if CONFIG_MACF
3978 	/* Is the calling process allowed to query kext info? */
3979 	if (current_task() != kernel_task) {
3980 		int macCheckResult = 0;
3981 		kauth_cred_t cred = NULL;
3982 
3983 		cred = kauth_cred_get_with_ref();
3984 		macCheckResult = mac_kext_check_query(cred);
3985 		kauth_cred_unref(&cred);
3986 
3987 		if (macCheckResult != 0) {
3988 			OSKextLog(/* kext */ NULL,
3989 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
3990 			    "Failed to query kext UUID (MAC policy error 0x%x).",
3991 			    macCheckResult);
3992 			return NULL;
3993 		}
3994 	}
3995 #endif
3996 
3997 	uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue());
3998 	if (slidAddress != 0) {
3999 		kext = lookupKextWithAddress(slidAddress);
4000 		if (kext) {
4001 			uuid = kext->copyTextUUID();
4002 		}
4003 	}
4004 
4005 	if (!uuid) {
4006 		/*
4007 		 * If we still don't have a UUID, then we failed to match the slid + stripped address with
4008 		 * a kext. This might have happened because the log message came from a dext.
4009 		 *
4010 		 * Try again with the original address.
4011 		 */
4012 		kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue());
4013 		if (kext && kext->isDriverKit()) {
4014 			uuid = kext->copyTextUUID();
4015 		}
4016 	}
4017 
4018 	return uuid;
4019 }
4020 
4021 /*********************************************************************
4022 *********************************************************************/
4023 OSSharedPtr<OSKext>
lookupKextWithUUID(uuid_t wanted)4024 OSKext::lookupKextWithUUID(uuid_t wanted)
4025 {
4026 	OSSharedPtr<OSKext> foundKext;             // returned
4027 	uint32_t j, i;
4028 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4029 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4030 
4031 
4032 	IORecursiveLockLock(sKextLock);
4033 
4034 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4035 		for (i = 0; i < count[j]; i++) {
4036 			OSKext   * thisKext     = NULL;
4037 
4038 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4039 			if (!thisKext) {
4040 				continue;
4041 			}
4042 
4043 			OSSharedPtr<OSData> uuid_data = thisKext->copyUUID();
4044 			if (!uuid_data) {
4045 				continue;
4046 			}
4047 
4048 			uuid_t uuid;
4049 			memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
4050 
4051 			if (0 == uuid_compare(wanted, uuid)) {
4052 				foundKext.reset(thisKext, OSRetain);
4053 				goto finish;
4054 			}
4055 		}
4056 	}
4057 finish:
4058 	IORecursiveLockUnlock(sKextLock);
4059 
4060 	return foundKext;
4061 }
4062 
4063 
4064 
4065 
4066 /*********************************************************************
4067 *********************************************************************/
4068 /* static */
4069 bool
isKextWithIdentifierLoaded(const char * kextIdentifier)4070 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
4071 {
4072 	bool result = false;
4073 	OSKext * foundKext = NULL;             // returned
4074 
4075 	IORecursiveLockLock(sKextLock);
4076 
4077 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4078 	if (foundKext && foundKext->isLoaded()) {
4079 		result = true;
4080 	}
4081 
4082 	IORecursiveLockUnlock(sKextLock);
4083 
4084 	return result;
4085 }
4086 
4087 /*********************************************************************
4088 * xxx - should spawn a separate thread so a kext can safely have
4089 * xxx - itself unloaded.
4090 *********************************************************************/
4091 /* static */
4092 OSReturn
removeKext(OSKext * aKext,__unused bool terminateServicesAndRemovePersonalitiesFlag)4093 OSKext::removeKext(
4094 	OSKext * aKext,
4095 #if CONFIG_EMBEDDED
4096 	__unused
4097 #endif
4098 	bool     terminateServicesAndRemovePersonalitiesFlag)
4099 {
4100 #if CONFIG_EMBEDDED
4101 	OSKextLog(aKext,
4102 	    kOSKextLogErrorLevel |
4103 	    kOSKextLogKextBookkeepingFlag,
4104 	    "removeKext() called for %s, not supported on embedded",
4105 	    aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
4106 
4107 	return kOSReturnSuccess;
4108 #else /* CONFIG_EMBEDDED */
4109 
4110 	OSReturn result    = kOSKextReturnInUse;
4111 	OSKext * checkKext = NULL;         // do not release
4112 #if CONFIG_MACF
4113 	int macCheckResult = 0;
4114 	kauth_cred_t cred  = NULL;
4115 #endif
4116 
4117 	IORecursiveLockLock(sKextLock);
4118 
4119 	/* If the kext has no identifier, it failed to init
4120 	 * so isn't in sKextsByID and it isn't loaded.
4121 	 */
4122 	if (!aKext->getIdentifier()) {
4123 		result = kOSReturnSuccess;
4124 		goto finish;
4125 	}
4126 
4127 	checkKext = OSDynamicCast(OSKext,
4128 	    sKextsByID->getObject(aKext->getIdentifier()));
4129 	if (checkKext != aKext) {
4130 		result = kOSKextReturnNotFound;
4131 		goto finish;
4132 	}
4133 
4134 	if (aKext->isLoaded()) {
4135 #if CONFIG_MACF
4136 		if (current_task() != kernel_task) {
4137 			cred = kauth_cred_get_with_ref();
4138 			macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
4139 			kauth_cred_unref(&cred);
4140 		}
4141 
4142 		if (macCheckResult != 0) {
4143 			result = kOSReturnError;
4144 			OSKextLog(aKext,
4145 			    kOSKextLogErrorLevel |
4146 			    kOSKextLogKextBookkeepingFlag,
4147 			    "Failed to remove kext %s (MAC policy error 0x%x).",
4148 			    aKext->getIdentifierCString(), macCheckResult);
4149 			goto finish;
4150 		}
4151 #endif
4152 
4153 		/* make sure there are no resource requests in flight - 17187548 */
4154 		if (aKext->countRequestCallbacks()) {
4155 			goto finish;
4156 		}
4157 		if (aKext->flags.unloadUnsupported) {
4158 			result = kOSKextReturnInUse;
4159 			OSKextLog(aKext,
4160 			    kOSKextLogErrorLevel |
4161 			    kOSKextLogKextBookkeepingFlag,
4162 			    "Can't remove kext %s; unsupported by cache.",
4163 			    aKext->getIdentifierCString());
4164 			goto finish;
4165 		}
4166 
4167 		/* If we are terminating, send the request to the IOCatalogue
4168 		 * (which will actually call us right back but that's ok we have
4169 		 * a recursive lock don't you know) but do not ask the IOCatalogue
4170 		 * to call back with an unload, we'll do that right here.
4171 		 */
4172 		if (terminateServicesAndRemovePersonalitiesFlag) {
4173 			result = gIOCatalogue->terminateDriversForModule(
4174 				aKext->getIdentifierCString(), /* unload */ false);
4175 			if (result != kOSReturnSuccess) {
4176 				OSKextLog(aKext,
4177 				    kOSKextLogErrorLevel |
4178 				    kOSKextLogKextBookkeepingFlag,
4179 				    "Can't remove kext %s; services failed to terminate - 0x%x.",
4180 				    aKext->getIdentifierCString(), result);
4181 				goto finish;
4182 			}
4183 		}
4184 
4185 		result = aKext->unload();
4186 		if (result != kOSReturnSuccess) {
4187 			goto finish;
4188 		}
4189 	}
4190 
4191 	/* Remove personalities as requested. This is a bit redundant for a loaded
4192 	 * kext as IOCatalogue::terminateDriversForModule() removes driver
4193 	 * personalities, but it doesn't restart matching, which we always want
4194 	 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
4195 	 * that happens.
4196 	 */
4197 	if (terminateServicesAndRemovePersonalitiesFlag) {
4198 		aKext->removePersonalitiesFromCatalog();
4199 	}
4200 
4201 	if (aKext->isInFileset()) {
4202 		OSKextLog(aKext,
4203 		    kOSKextLogProgressLevel |
4204 		    kOSKextLogKextBookkeepingFlag,
4205 		    "Fileset kext %s unloaded.",
4206 		    aKext->getIdentifierCString());
4207 	} else {
4208 		OSKextLog(aKext,
4209 		    kOSKextLogProgressLevel |
4210 		    kOSKextLogKextBookkeepingFlag,
4211 		    "Removing kext %s.",
4212 		    aKext->getIdentifierCString());
4213 
4214 		sKextsByID->removeObject(aKext->getIdentifier());
4215 	}
4216 	result = kOSReturnSuccess;
4217 
4218 finish:
4219 	IORecursiveLockUnlock(sKextLock);
4220 	return result;
4221 #endif /* CONFIG_EMBEDDED */
4222 }
4223 
4224 /*********************************************************************
4225 *********************************************************************/
4226 /* static */
4227 OSReturn
removeKextWithIdentifier(const char * kextIdentifier,bool terminateServicesAndRemovePersonalitiesFlag)4228 OSKext::removeKextWithIdentifier(
4229 	const char * kextIdentifier,
4230 	bool         terminateServicesAndRemovePersonalitiesFlag)
4231 {
4232 	OSReturn result = kOSReturnError;
4233 
4234 	IORecursiveLockLock(sKextLock);
4235 
4236 	OSKext * aKext = OSDynamicCast(OSKext,
4237 	    sKextsByID->getObject(kextIdentifier));
4238 	if (!aKext) {
4239 		result = kOSKextReturnNotFound;
4240 		OSKextLog(/* kext */ NULL,
4241 		    kOSKextLogErrorLevel |
4242 		    kOSKextLogKextBookkeepingFlag,
4243 		    "Can't remove kext %s - not found.",
4244 		    kextIdentifier);
4245 		goto finish;
4246 	}
4247 
4248 	result = OSKext::removeKext(aKext,
4249 	    terminateServicesAndRemovePersonalitiesFlag);
4250 
4251 finish:
4252 	IORecursiveLockUnlock(sKextLock);
4253 
4254 	return result;
4255 }
4256 
4257 /*********************************************************************
4258 *********************************************************************/
4259 /* static */
4260 OSReturn
removeKextWithLoadTag(OSKextLoadTag loadTag,bool terminateServicesAndRemovePersonalitiesFlag)4261 OSKext::removeKextWithLoadTag(
4262 	OSKextLoadTag loadTag,
4263 	bool          terminateServicesAndRemovePersonalitiesFlag)
4264 {
4265 	OSReturn result    = kOSReturnError;
4266 	OSKext * foundKext = NULL;
4267 	uint32_t i, j;
4268 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4269 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4270 
4271 
4272 	IORecursiveLockLock(sKextLock);
4273 
4274 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4275 		for (i = 0; i < count[j]; i++) {
4276 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4277 			if (thisKext->loadTag == loadTag) {
4278 				foundKext = thisKext;
4279 				break;
4280 			}
4281 		}
4282 	}
4283 
4284 	if (!foundKext) {
4285 		result = kOSKextReturnNotFound;
4286 		OSKextLog(/* kext */ NULL,
4287 		    kOSKextLogErrorLevel |
4288 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4289 		    "Can't remove kext with load tag %d - not found.",
4290 		    loadTag);
4291 		goto finish;
4292 	}
4293 
4294 	result = OSKext::removeKext(foundKext,
4295 	    terminateServicesAndRemovePersonalitiesFlag);
4296 
4297 finish:
4298 	IORecursiveLockUnlock(sKextLock);
4299 
4300 	return result;
4301 }
4302 
4303 /*********************************************************************
4304 *********************************************************************/
4305 OSSharedPtr<OSDictionary>
copyKexts(void)4306 OSKext::copyKexts(void)
4307 {
4308 	OSSharedPtr<OSDictionary> result;
4309 
4310 	IORecursiveLockLock(sKextLock);
4311 	result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection());
4312 	IORecursiveLockUnlock(sKextLock);
4313 
4314 	return result;
4315 }
4316 
4317 /*********************************************************************
4318 *********************************************************************/
4319 #define BOOTER_KEXT_PREFIX   "Driver-"
4320 
4321 typedef struct _DeviceTreeBuffer {
4322 	uint32_t paddr;
4323 	uint32_t length;
4324 } _DeviceTreeBuffer;
4325 
4326 /*********************************************************************
4327 * Create a dictionary of excluded kexts from the given booter data.
4328 *********************************************************************/
4329 /* static */
4330 void
createExcludeListFromBooterData(OSDictionary * theDictionary,OSCollectionIterator * theIterator)4331 OSKext::createExcludeListFromBooterData(
4332 	OSDictionary *          theDictionary,
4333 	OSCollectionIterator *  theIterator )
4334 {
4335 	OSString                  * deviceTreeName      = NULL;        // do not release
4336 	const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;        // do not release
4337 	char                      * booterDataPtr       = NULL;        // do not release
4338 	_BooterKextFileInfo       * kextFileInfo        = NULL;        // do not release
4339 	char                      * infoDictAddr        = NULL;        // do not release
4340 	OSSharedPtr<OSObject>       parsedXML;
4341 	OSDictionary              * theInfoDict         = NULL;        // do not release
4342 
4343 	theIterator->reset();
4344 
4345 	/* look for AppleKextExcludeList.kext */
4346 	while ((deviceTreeName =
4347 	    OSDynamicCast(OSString, theIterator->getNextObject()))) {
4348 		const char *    devTreeNameCString;
4349 		OSData *        deviceTreeEntry;        // do not release
4350 		OSString *      myBundleID;        // do not release
4351 
4352 		deviceTreeEntry =
4353 		    OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
4354 		if (!deviceTreeEntry) {
4355 			continue;
4356 		}
4357 
4358 		/* Make sure it is a kext */
4359 		devTreeNameCString = deviceTreeName->getCStringNoCopy();
4360 		if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
4361 		    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
4362 			OSKextLog(NULL,
4363 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4364 			    "\"%s\" not a kext",
4365 			    devTreeNameCString);
4366 			continue;
4367 		}
4368 
4369 		deviceTreeBuffer = (const _DeviceTreeBuffer *)
4370 		    deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
4371 		if (!deviceTreeBuffer) {
4372 			continue;
4373 		}
4374 
4375 		booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
4376 		if (!booterDataPtr) {
4377 			continue;
4378 		}
4379 
4380 		kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
4381 		if (!kextFileInfo->infoDictPhysAddr ||
4382 		    !kextFileInfo->infoDictLength) {
4383 			continue;
4384 		}
4385 
4386 		infoDictAddr = (char *)
4387 		    ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
4388 		if (!infoDictAddr) {
4389 			continue;
4390 		}
4391 
4392 		parsedXML = OSUnserializeXML(infoDictAddr);
4393 		if (!parsedXML) {
4394 			continue;
4395 		}
4396 
4397 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
4398 		if (!theInfoDict) {
4399 			continue;
4400 		}
4401 
4402 		myBundleID =
4403 		    OSDynamicCast(OSString,
4404 		    theInfoDict->getObject(kCFBundleIdentifierKey));
4405 		if (myBundleID &&
4406 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4407 			boolean_t updated = updateExcludeList(theInfoDict);
4408 			if (!updated) {
4409 				/* 25322874 */
4410 				panic("Missing OSKextExcludeList dictionary");
4411 			}
4412 			break;
4413 		}
4414 	}         // while ( (deviceTreeName = ...) )
4415 
4416 	return;
4417 }
4418 
4419 /*********************************************************************
4420 * Create a dictionary of excluded kexts from the given prelink
4421 * info (kernelcache).
4422 *********************************************************************/
4423 /* static */
4424 void
createExcludeListFromPrelinkInfo(OSArray * theInfoArray)4425 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
4426 {
4427 	OSDictionary *  myInfoDict = NULL;        // do not release
4428 	OSString *      myBundleID;        // do not release
4429 	u_int           i;
4430 
4431 	/* Find the Apple Kext Exclude List. */
4432 	for (i = 0; i < theInfoArray->getCount(); i++) {
4433 		myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
4434 		if (!myInfoDict) {
4435 			continue;
4436 		}
4437 		myBundleID =
4438 		    OSDynamicCast(OSString,
4439 		    myInfoDict->getObject(kCFBundleIdentifierKey));
4440 		if (myBundleID &&
4441 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4442 			boolean_t updated = updateExcludeList(myInfoDict);
4443 			if (!updated) {
4444 				/* 25322874 */
4445 				panic("Missing OSKextExcludeList dictionary");
4446 			}
4447 			break;
4448 		}
4449 	}         // for (i = 0; i < theInfoArray->getCount()...
4450 
4451 	return;
4452 }
4453 
4454 /* static */
4455 boolean_t
updateExcludeList(OSDictionary * infoDict)4456 OSKext::updateExcludeList(OSDictionary *infoDict)
4457 {
4458 	OSDictionary *myTempDict = NULL;         // do not free
4459 	OSString     *myTempString = NULL;        // do not free
4460 	OSKextVersion newVersion = 0;
4461 	boolean_t updated = false;
4462 
4463 	if (!infoDict) {
4464 		return false;
4465 	}
4466 
4467 	myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
4468 	if (!myTempDict) {
4469 		return false;
4470 	}
4471 
4472 	myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
4473 	if (!myTempString) {
4474 		return false;
4475 	}
4476 
4477 	newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
4478 	if (newVersion == 0) {
4479 		return false;
4480 	}
4481 
4482 	IORecursiveLockLock(sKextLock);
4483 
4484 	if (newVersion > sExcludeListVersion) {
4485 		sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
4486 		sExcludeListVersion = newVersion;
4487 		updated = true;
4488 	}
4489 
4490 	IORecursiveLockUnlock(sKextLock);
4491 	return updated;
4492 }
4493 
4494 #if PRAGMA_MARK
4495 #pragma mark Accessors
4496 #endif
4497 /*********************************************************************
4498 *********************************************************************/
4499 const OSSymbol *
getIdentifier(void)4500 OSKext::getIdentifier(void)
4501 {
4502 	return bundleID.get();
4503 }
4504 
4505 /*********************************************************************
4506 * A kext must have a bundle identifier to even survive initialization;
4507 * this is guaranteed to exist past then.
4508 *********************************************************************/
4509 const char *
getIdentifierCString(void)4510 OSKext::getIdentifierCString(void)
4511 {
4512 	return bundleID->getCStringNoCopy();
4513 }
4514 
4515 /*********************************************************************
4516 *********************************************************************/
4517 OSKextVersion
getVersion(void)4518 OSKext::getVersion(void)
4519 {
4520 	return version;
4521 }
4522 
4523 /*********************************************************************
4524 *********************************************************************/
4525 OSKextVersion
getCompatibleVersion(void)4526 OSKext::getCompatibleVersion(void)
4527 {
4528 	return compatibleVersion;
4529 }
4530 
4531 /*********************************************************************
4532 *********************************************************************/
4533 bool
isLibrary(void)4534 OSKext::isLibrary(void)
4535 {
4536 	return getCompatibleVersion() > 0;
4537 }
4538 
4539 /*********************************************************************
4540 *********************************************************************/
4541 bool
isCompatibleWithVersion(OSKextVersion aVersion)4542 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
4543 {
4544 	if ((compatibleVersion > -1 && version > -1) &&
4545 	    (compatibleVersion <= version && aVersion <= version)) {
4546 		return true;
4547 	}
4548 	return false;
4549 }
4550 
4551 /*********************************************************************
4552 *********************************************************************/
4553 bool
declaresExecutable(void)4554 OSKext::declaresExecutable(void)
4555 {
4556 	if (isDriverKit()) {
4557 		return false;
4558 	}
4559 	return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
4560 }
4561 
4562 /*********************************************************************
4563 *********************************************************************/
4564 OSData *
getExecutable(void)4565 OSKext::getExecutable(void)
4566 {
4567 	OSData * result              = NULL;
4568 	OSSharedPtr<OSData> extractedExecutable;
4569 
4570 	if (flags.builtin) {
4571 		return sKernelKext->linkedExecutable.get();
4572 	}
4573 
4574 	result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
4575 	if (result) {
4576 		return result;
4577 	}
4578 
4579 #if CONFIG_KXLD
4580 	OSData * mkextExecutableRef  = NULL;        // do not release
4581 	mkextExecutableRef = OSDynamicCast(OSData,
4582 	    getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
4583 
4584 	if (mkextExecutableRef) {
4585 		MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
4586 		    mkextExecutableRef->getBytesNoCopy();
4587 		uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
4588 		if (mkextVersion == MKEXT_VERS_2) {
4589 			mkext2_file_entry * fileinfo =
4590 			    (mkext2_file_entry *)mkextEntryRef->fileinfo;
4591 			uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
4592 			uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
4593 			extractedExecutable = extractMkext2FileData(
4594 				MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
4595 				compressedSize, fullSize);
4596 		} else {
4597 			OSKextLog(this, kOSKextLogErrorLevel |
4598 			    kOSKextLogArchiveFlag,
4599 			    "Kext %s - unknown mkext version 0x%x for executable.",
4600 			    getIdentifierCString(), mkextVersion);
4601 		}
4602 
4603 		/* Regardless of success, remove the mkext executable,
4604 		 * and drop one reference on the mkext.  (setExecutable() does not
4605 		 * replace, it removes, or panics if asked to replace.)
4606 		 */
4607 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4608 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4609 
4610 		if (extractedExecutable && extractedExecutable->getLength()) {
4611 			if (!setExecutable(extractedExecutable.get())) {
4612 				goto finish;
4613 			}
4614 			result = extractedExecutable.get();
4615 		} else {
4616 			goto finish;
4617 		}
4618 	}
4619 
4620 finish:
4621 #endif // CONFIG_KXLD
4622 	return result;
4623 }
4624 
4625 /*********************************************************************
4626 *********************************************************************/
4627 bool
isInterface(void)4628 OSKext::isInterface(void)
4629 {
4630 	return flags.interface;
4631 }
4632 
4633 /*********************************************************************
4634 *********************************************************************/
4635 bool
isKernel(void)4636 OSKext::isKernel(void)
4637 {
4638 	return this == sKernelKext;
4639 }
4640 
4641 /*********************************************************************
4642 *********************************************************************/
4643 bool
isKernelComponent(void)4644 OSKext::isKernelComponent(void)
4645 {
4646 	return flags.kernelComponent ? true : false;
4647 }
4648 
4649 /*********************************************************************
4650 *********************************************************************/
4651 bool
isExecutable(void)4652 OSKext::isExecutable(void)
4653 {
4654 	return !isKernel() && !isInterface() && declaresExecutable();
4655 }
4656 
4657 /*********************************************************************
4658 * We might want to check this recursively for all dependencies,
4659 * since a subtree of dependencies could get loaded before we hit
4660 * a dependency that isn't safe-boot-loadable.
4661 *
4662 * xxx - Might want to return false if OSBundleEnableKextLogging or
4663 * OSBundleDebugLevel
4664 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4665 * the point except it's usually development drivers, which might
4666 * cause panics on startup, that have those properties). Heh; could
4667 * use a "kx" boot-arg!
4668 *********************************************************************/
4669 bool
isLoadableInSafeBoot(void)4670 OSKext::isLoadableInSafeBoot(void)
4671 {
4672 	bool       result   = false;
4673 	OSString * required = NULL;         // do not release
4674 
4675 	if (isKernel()) {
4676 		result = true;
4677 		goto finish;
4678 	}
4679 
4680 	if (isDriverKit()) {
4681 		result = true;
4682 		goto finish;
4683 	}
4684 
4685 	required = OSDynamicCast(OSString,
4686 	    getPropertyForHostArch(kOSBundleRequiredKey));
4687 	if (!required) {
4688 		goto finish;
4689 	}
4690 	if (required->isEqualTo(kOSBundleRequiredRoot) ||
4691 	    required->isEqualTo(kOSBundleRequiredLocalRoot) ||
4692 	    required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
4693 	    required->isEqualTo(kOSBundleRequiredSafeBoot) ||
4694 	    required->isEqualTo(kOSBundleRequiredConsole)) {
4695 		result = true;
4696 	}
4697 
4698 finish:
4699 	return result;
4700 }
4701 
4702 /*********************************************************************
4703 *********************************************************************/
4704 bool
isPrelinked(void)4705 OSKext::isPrelinked(void)
4706 {
4707 	return flags.prelinked ? true : false;
4708 }
4709 
4710 /*********************************************************************
4711 *********************************************************************/
4712 bool
isLoaded(void)4713 OSKext::isLoaded(void)
4714 {
4715 	return flags.loaded ? true : false;
4716 }
4717 
4718 /*********************************************************************
4719 *********************************************************************/
4720 bool
isStarted(void)4721 OSKext::isStarted(void)
4722 {
4723 	return flags.started ? true : false;
4724 }
4725 
4726 /*********************************************************************
4727 *********************************************************************/
4728 bool
isCPPInitialized(void)4729 OSKext::isCPPInitialized(void)
4730 {
4731 	return flags.CPPInitialized;
4732 }
4733 
4734 /*********************************************************************
4735 *********************************************************************/
4736 void
setCPPInitialized(bool initialized)4737 OSKext::setCPPInitialized(bool initialized)
4738 {
4739 	flags.CPPInitialized = initialized;
4740 }
4741 
4742 /*********************************************************************
4743 *********************************************************************/
4744 uint32_t
getLoadTag(void)4745 OSKext::getLoadTag(void)
4746 {
4747 	return loadTag;
4748 }
4749 
4750 /*********************************************************************
4751 *********************************************************************/
4752 void
getSizeInfo(uint32_t * loadSize,uint32_t * wiredSize)4753 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
4754 {
4755 	if (linkedExecutable) {
4756 		*loadSize = linkedExecutable->getLength();
4757 
4758 		/* If we have a kmod_info struct, calculated the wired size
4759 		 * from that. Otherwise it's the full load size.
4760 		 */
4761 		if (kmod_info) {
4762 			*wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size;
4763 		} else {
4764 			*wiredSize = *loadSize;
4765 		}
4766 	} else {
4767 		*wiredSize = 0;
4768 		*loadSize = 0;
4769 	}
4770 }
4771 
4772 /*********************************************************************
4773 *********************************************************************/
4774 OSSharedPtr<OSData>
copyUUID(void)4775 OSKext::copyUUID(void)
4776 {
4777 	OSSharedPtr<OSData>          result;
4778 	OSData                     * theExecutable = NULL;        // do not release
4779 	const kernel_mach_header_t * header;
4780 
4781 	/* An interface kext doesn't have a linked executable with an LC_UUID,
4782 	 * we create one when it's linked.
4783 	 */
4784 	if (interfaceUUID) {
4785 		result = interfaceUUID;
4786 		goto finish;
4787 	}
4788 
4789 	if (flags.builtin || isInterface()) {
4790 		return sKernelKext->copyUUID();
4791 	}
4792 
4793 	if (isDriverKit() && infoDict) {
4794 		return driverKitUUID;
4795 	}
4796 
4797 	/* For real kexts, try to get the UUID from the linked executable,
4798 	 * or if is hasn't been linked yet, the unrelocated executable.
4799 	 */
4800 	theExecutable = linkedExecutable.get();
4801 	if (!theExecutable) {
4802 		theExecutable = getExecutable();
4803 	}
4804 
4805 	if (!theExecutable) {
4806 		goto finish;
4807 	}
4808 
4809 	header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
4810 	result = copyMachoUUID(header);
4811 
4812 finish:
4813 	return result;
4814 }
4815 
4816 /*********************************************************************
4817 *********************************************************************/
4818 OSSharedPtr<OSData>
copyTextUUID(void)4819 OSKext::copyTextUUID(void)
4820 {
4821 	if (flags.builtin) {
4822 		return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
4823 	}
4824 	return copyUUID();
4825 }
4826 
4827 /*********************************************************************
4828 *********************************************************************/
4829 OSSharedPtr<OSData>
copyMachoUUID(const kernel_mach_header_t * header)4830 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
4831 {
4832 	OSSharedPtr<OSData>                     result;
4833 	const struct load_command  * load_cmd      = NULL;
4834 	const struct uuid_command  * uuid_cmd      = NULL;
4835 	uint32_t                     i;
4836 
4837 	load_cmd = (const struct load_command *)&header[1];
4838 
4839 	if (header->magic != MH_MAGIC_KERNEL) {
4840 		OSKextLog(NULL,
4841 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4842 		    "%s: bad header %p",
4843 		    __func__,
4844 		    header);
4845 		goto finish;
4846 	}
4847 
4848 	for (i = 0; i < header->ncmds; i++) {
4849 		if (load_cmd->cmd == LC_UUID) {
4850 			uuid_cmd = (struct uuid_command *)load_cmd;
4851 			result = OSData::withValue(uuid_cmd->uuid);
4852 			goto finish;
4853 		}
4854 		load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
4855 	}
4856 
4857 finish:
4858 	return result;
4859 }
4860 
4861 void
setDriverKitUUID(OSData * uuid)4862 OSKext::setDriverKitUUID(OSData *uuid)
4863 {
4864 	if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
4865 		OSSafeReleaseNULL(uuid);
4866 	}
4867 }
4868 
4869 /*********************************************************************
4870 *********************************************************************/
4871 #if defined (__arm__)
4872 #include <arm/arch.h>
4873 #endif
4874 
4875 #if   defined (__x86_64__)
4876 #define ARCHNAME "x86_64"
4877 #elif defined (__arm64__)
4878 #define ARCHNAME "arm64"
4879 #elif defined (__arm__)
4880 
4881 #if defined (__ARM_ARCH_7S__)
4882 #define ARCHNAME "armv7s"
4883 #elif defined (__ARM_ARCH_7F__)
4884 #define ARCHNAME "armv7f"
4885 #elif defined (__ARM_ARCH_7K__)
4886 #define ARCHNAME "armv7k"
4887 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
4888 #define ARCHNAME "armv7"
4889 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
4890 #define ARCHNAME "armv6"
4891 #endif
4892 
4893 #elif defined (__arm64__)
4894 #define ARCHNAME "arm64"
4895 #else
4896 #error architecture not supported
4897 #endif
4898 
4899 #define ARCH_SEPARATOR_CHAR  '_'
4900 
4901 static char *
makeHostArchKey(const char * key,size_t * keySizeOut)4902 makeHostArchKey(const char * key, size_t * keySizeOut)
4903 {
4904 	char     * result = NULL;
4905 	size_t     keyLength = strlen(key);
4906 	size_t     keySize;
4907 
4908 	/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4909 	 */
4910 	keySize = 1 + 1 + keyLength + strlen(ARCHNAME);
4911 	result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
4912 
4913 	if (!result) {
4914 		goto finish;
4915 	}
4916 	strlcpy(result, key, keySize);
4917 	result[keyLength++] = ARCH_SEPARATOR_CHAR;
4918 	result[keyLength] = '\0';
4919 	strlcat(result, ARCHNAME, keySize);
4920 	*keySizeOut = keySize;
4921 
4922 finish:
4923 	return result;
4924 }
4925 
4926 /*********************************************************************
4927 *********************************************************************/
4928 OSObject *
getPropertyForHostArch(const char * key)4929 OSKext::getPropertyForHostArch(const char * key)
4930 {
4931 	OSObject * result           = NULL;// do not release
4932 	size_t     hostArchKeySize  = 0;
4933 	char     * hostArchKey      = NULL;// must kfree
4934 
4935 	if (!key || !infoDict) {
4936 		goto finish;
4937 	}
4938 
4939 	/* Some properties are not allowed to be arch-variant:
4940 	 * - Any CFBundle... property.
4941 	 * - OSBundleIsInterface.
4942 	 * - OSKernelResource.
4943 	 */
4944 	if (STRING_HAS_PREFIX(key, "OS") ||
4945 	    STRING_HAS_PREFIX(key, "IO")) {
4946 		hostArchKey = makeHostArchKey(key, &hostArchKeySize);
4947 		if (!hostArchKey) {
4948 			OSKextLog(/* kext (this isn't about a kext) */ NULL,
4949 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4950 			    "Allocation failure.");
4951 			goto finish;
4952 		}
4953 		result = infoDict->getObject(hostArchKey);
4954 	}
4955 
4956 	if (!result) {
4957 		result = infoDict->getObject(key);
4958 	}
4959 
4960 finish:
4961 	if (hostArchKey) {
4962 		kfree_data(hostArchKey, hostArchKeySize);
4963 	}
4964 	return result;
4965 }
4966 
4967 #if PRAGMA_MARK
4968 #pragma mark Load/Start/Stop/Unload
4969 #endif
4970 
4971 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4972 
4973 /*********************************************************************
4974 * sExcludeListByID is a dictionary with keys / values of:
4975 *  key = bundleID string of kext we will not allow to load
4976 *  value = version string(s) of the kext that is to be denied loading.
4977 *      The version strings can be comma delimited.  For example if kext
4978 *      com.foocompany.fookext has two versions that we want to deny
4979 *      loading then the version strings might look like:
4980 *      1.0.0, 1.0.1
4981 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4982 *      not load the kext.
4983 *
4984 *      Value may also be in the form of "LE 2.0.0" (version numbers
4985 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4986 *      number less than 2.0.0 will not load)
4987 *
4988 *      NOTE - we cannot use the characters "<=" or "<" because we have code
4989 *      that serializes plists and treats '<' as a special character.
4990 *********************************************************************/
4991 bool
isInExcludeList(void)4992 OSKext::isInExcludeList(void)
4993 {
4994 	OSString *      versionString           = NULL;        // do not release
4995 	char *          versionCString          = NULL;        // do not free
4996 	size_t          i;
4997 	boolean_t       wantLessThan = false;
4998 	boolean_t       wantLessThanEqualTo = false;
4999 	boolean_t       isInExcludeList = true;
5000 	char            myBuffer[32];
5001 
5002 	IORecursiveLockLock(sKextLock);
5003 
5004 	if (!sExcludeListByID) {
5005 		isInExcludeList = false;
5006 	} else {
5007 		/* look up by bundleID in our exclude list and if found get version
5008 		 * string (or strings) that we will not allow to load
5009 		 */
5010 		versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get()));
5011 		if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
5012 			isInExcludeList = false;
5013 		}
5014 	}
5015 
5016 	IORecursiveLockUnlock(sKextLock);
5017 
5018 	if (!isInExcludeList) {
5019 		return false;
5020 	}
5021 
5022 	/* parse version strings */
5023 	versionCString = (char *) versionString->getCStringNoCopy();
5024 
5025 	/* look for "LT" or "LE" form of version string, must be in first two
5026 	 * positions.
5027 	 */
5028 	if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
5029 		wantLessThan = true;
5030 		versionCString += 2;
5031 	} else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
5032 		wantLessThanEqualTo = true;
5033 		versionCString += 2;
5034 	}
5035 
5036 	for (i = 0; *versionCString != 0x00; versionCString++) {
5037 		/* skip whitespace */
5038 		if (isWhiteSpace(*versionCString)) {
5039 			continue;
5040 		}
5041 
5042 		/* peek ahead for version string separator or null terminator */
5043 		if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
5044 			/* OK, we have a version string */
5045 			myBuffer[i++] = *versionCString;
5046 			myBuffer[i] = 0x00;
5047 
5048 			OSKextVersion excludeVers;
5049 			excludeVers = OSKextParseVersionString(myBuffer);
5050 
5051 			if (wantLessThanEqualTo) {
5052 				if (version <= excludeVers) {
5053 					return true;
5054 				}
5055 			} else if (wantLessThan) {
5056 				if (version < excludeVers) {
5057 					return true;
5058 				}
5059 			} else if (version == excludeVers) {
5060 				return true;
5061 			}
5062 
5063 			/* reset for the next (if any) version string */
5064 			i = 0;
5065 			wantLessThan = false;
5066 			wantLessThanEqualTo = false;
5067 		} else {
5068 			/* save valid version character */
5069 			myBuffer[i++] = *versionCString;
5070 
5071 			/* make sure bogus version string doesn't overrun local buffer */
5072 			if (i >= sizeof(myBuffer)) {
5073 				break;
5074 			}
5075 		}
5076 	}
5077 
5078 	return false;
5079 }
5080 
5081 /*********************************************************************
5082 * sNonLoadableKextsByID is a dictionary with keys / values of:
5083 *  key = bundleID string of kext we will not allow to load
5084 *  value = boolean (true == loadable, false == not loadable)
5085 *
5086 *  Only kexts which are in the AuxKC will be marked as "not loadble,"
5087 *  i.e., the value for the kext's bundleID will be false. All kexts in
5088 *  the primary and system KCs will always be marked as "loadable."
5089 *
5090 *  This list ultimately comes from kexts which have been uninstalled
5091 *  in user space by deleting the kext from disk, but which have not
5092 *  yet been removed from the AuxKC. Because the user could choose to
5093 *  re-install the exact same version of the kext, we need to keep
5094 *  a dictionary of boolean values so that user space only needs to
5095 *  keep a simple list of "uninstalled" or "missing" bundles. When
5096 *  a bundle is re-installed, the iokit daemon can use the
5097 *  AucKCBundleAvailable  predicate to set the individual kext's
5098 *  availability to true.
5099 *********************************************************************/
5100 bool
isLoadable(void)5101 OSKext::isLoadable(void)
5102 {
5103 	bool isLoadable = true;
5104 
5105 	if (kc_type != KCKindAuxiliary) {
5106 		/* this filtering only applies to kexts in the auxkc */
5107 		return true;
5108 	}
5109 
5110 	IORecursiveLockLock(sKextLock);
5111 
5112 	if (sNonLoadableKextsByID) {
5113 		/* look up by bundleID in our exclude list and if found get version
5114 		 * string (or strings) that we will not allow to load
5115 		 */
5116 		OSBoolean *loadableVal;
5117 		loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get()));
5118 		if (loadableVal && !loadableVal->getValue()) {
5119 			isLoadable = false;
5120 		}
5121 	}
5122 	IORecursiveLockUnlock(sKextLock);
5123 
5124 	return isLoadable;
5125 }
5126 
5127 /*********************************************************************
5128 *********************************************************************/
5129 /* static */
5130 OSReturn
loadKextWithIdentifier(const char * kextIdentifierCString,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5131 OSKext::loadKextWithIdentifier(
5132 	const char       * kextIdentifierCString,
5133 	Boolean            allowDeferFlag,
5134 	Boolean            delayAutounloadFlag,
5135 	OSKextExcludeLevel startOpt,
5136 	OSKextExcludeLevel startMatchingOpt,
5137 	OSArray          * personalityNames)
5138 {
5139 	OSReturn   result         = kOSReturnError;
5140 	OSSharedPtr<OSString> kextIdentifier;
5141 
5142 	kextIdentifier = OSString::withCString(kextIdentifierCString);
5143 	if (!kextIdentifier) {
5144 		result = kOSKextReturnNoMemory;
5145 		goto finish;
5146 	}
5147 	result = OSKext::loadKextWithIdentifier(kextIdentifier.get(),
5148 	    NULL /* kextRef */,
5149 	    allowDeferFlag, delayAutounloadFlag,
5150 	    startOpt, startMatchingOpt, personalityNames);
5151 
5152 finish:
5153 	return result;
5154 }
5155 
5156 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSSharedPtr<OSObject> & kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5157 OSKext::loadKextWithIdentifier(
5158 	OSString          * kextIdentifier,
5159 	OSSharedPtr<OSObject>         &kextRef,
5160 	Boolean             allowDeferFlag,
5161 	Boolean             delayAutounloadFlag,
5162 	OSKextExcludeLevel  startOpt,
5163 	OSKextExcludeLevel  startMatchingOpt,
5164 	OSArray           * personalityNames)
5165 {
5166 	OSObject * kextRefRaw = NULL;
5167 	OSReturn result;
5168 
5169 	result = loadKextWithIdentifier(kextIdentifier,
5170 	    &kextRefRaw,
5171 	    allowDeferFlag,
5172 	    delayAutounloadFlag,
5173 	    startOpt,
5174 	    startMatchingOpt,
5175 	    personalityNames);
5176 	if ((kOSReturnSuccess == result) && kextRefRaw) {
5177 		kextRef.reset(kextRefRaw, OSNoRetain);
5178 	}
5179 	return result;
5180 }
5181 
5182 /*********************************************************************
5183 *********************************************************************/
5184 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSObject ** kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5185 OSKext::loadKextWithIdentifier(
5186 	OSString          * kextIdentifier,
5187 	OSObject         ** kextRef,
5188 	Boolean             allowDeferFlag,
5189 	Boolean             delayAutounloadFlag,
5190 	OSKextExcludeLevel  startOpt,
5191 	OSKextExcludeLevel  startMatchingOpt,
5192 	OSArray           * personalityNames)
5193 {
5194 	OSReturn          result               = kOSReturnError;
5195 	OSReturn          pingResult           = kOSReturnError;
5196 	OSKext          * theKext              = NULL;        // do not release
5197 	OSSharedPtr<OSDictionary>   loadRequest;
5198 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5199 
5200 	if (kextRef) {
5201 		*kextRef = NULL;
5202 	}
5203 
5204 	IORecursiveLockLock(sKextLock);
5205 
5206 	if (!kextIdentifier) {
5207 		result = kOSKextReturnInvalidArgument;
5208 		goto finish;
5209 	}
5210 
5211 	OSKext::recordIdentifierRequest(kextIdentifier);
5212 
5213 	theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
5214 	if (!theKext) {
5215 		if (!allowDeferFlag) {
5216 			OSKextLog(/* kext */ NULL,
5217 			    kOSKextLogErrorLevel |
5218 			    kOSKextLogLoadFlag,
5219 			    "Can't load kext %s - not found.",
5220 			    kextIdentifier->getCStringNoCopy());
5221 			goto finish;
5222 		}
5223 
5224 		if (!sKernelRequestsEnabled) {
5225 			OSKextLog(theKext,
5226 			    kOSKextLogErrorLevel |
5227 			    kOSKextLogLoadFlag,
5228 			    "Can't load kext %s - requests to user space are disabled.",
5229 			    kextIdentifier->getCStringNoCopy());
5230 			result = kOSKextReturnDisabled;
5231 			goto finish;
5232 		}
5233 
5234 		/* Create a new request unless one is already sitting
5235 		 * in sKernelRequests for this bundle identifier
5236 		 */
5237 		kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5238 		if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5239 			result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
5240 			    loadRequest);
5241 			if (result != kOSReturnSuccess) {
5242 				goto finish;
5243 			}
5244 			if (!_OSKextSetRequestArgument(loadRequest.get(),
5245 			    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
5246 				result = kOSKextReturnNoMemory;
5247 				goto finish;
5248 			}
5249 			if (!sKernelRequests->setObject(loadRequest.get())) {
5250 				result = kOSKextReturnNoMemory;
5251 				goto finish;
5252 			}
5253 
5254 			if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
5255 				result = kOSKextReturnNoMemory;
5256 				goto finish;
5257 			}
5258 
5259 			OSKextLog(theKext,
5260 			    kOSKextLogDebugLevel |
5261 			    kOSKextLogLoadFlag,
5262 			    "Kext %s not found; queued load request to user space.",
5263 			    kextIdentifier->getCStringNoCopy());
5264 		}
5265 
5266 		pingResult = OSKext::pingIOKitDaemon();
5267 		if (pingResult == kOSKextReturnDisabled) {
5268 			OSKextLog(/* kext */ NULL,
5269 			    ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
5270 			    kOSKextLogLoadFlag,
5271 			    "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.",
5272 			    kextIdentifier->getCStringNoCopy());
5273 		}
5274 
5275 		result = kOSKextReturnDeferred;
5276 		goto finish;
5277 	}
5278 
5279 	result = theKext->load(startOpt, startMatchingOpt, personalityNames);
5280 
5281 	if (result != kOSReturnSuccess) {
5282 		OSKextLog(theKext,
5283 		    kOSKextLogErrorLevel |
5284 		    kOSKextLogLoadFlag,
5285 		    "Failed to load kext %s (error 0x%x).",
5286 		    kextIdentifier->getCStringNoCopy(), (int)result);
5287 
5288 		if (theKext->kc_type == KCKindUnknown) {
5289 			OSKext::removeKext(theKext,
5290 			    /* terminateService/removePersonalities */ true);
5291 		}
5292 		goto finish;
5293 	}
5294 
5295 	if (delayAutounloadFlag) {
5296 		OSKextLog(theKext,
5297 		    kOSKextLogProgressLevel |
5298 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5299 		    "Setting delayed autounload for %s.",
5300 		    kextIdentifier->getCStringNoCopy());
5301 		theKext->flags.delayAutounload = 1;
5302 	}
5303 
5304 finish:
5305 	if ((kOSReturnSuccess == result) && kextRef) {
5306 		*kextRef = theKext;
5307 		theKext->matchingRefCount++;
5308 		theKext->retain();
5309 	}
5310 
5311 	IORecursiveLockUnlock(sKextLock);
5312 
5313 	return result;
5314 }
5315 
5316 /*********************************************************************
5317 *********************************************************************/
5318 /* static */
5319 OSReturn
loadKextFromKC(OSKext * theKext,OSDictionary * requestDict)5320 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict)
5321 {
5322 	OSReturn  result = kOSReturnError;
5323 
5324 	OSBoolean *delayAutounloadBool     = NULL; // do not release
5325 	OSNumber  *startKextExcludeNum     = NULL; // do not release
5326 	OSNumber  *startMatchingExcludeNum = NULL; // do not release
5327 	OSArray   *personalityNames        = NULL; // do not release
5328 
5329 	/*
5330 	 * Default values for these options:
5331 	 *      regular autounload behavior
5332 	 *      start the kext
5333 	 *      send all personalities to the catalog
5334 	 */
5335 	Boolean            delayAutounload           = false;
5336 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
5337 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone;
5338 
5339 	IORecursiveLockLock(sKextLock);
5340 
5341 	OSKextLog(/* kext */ NULL,
5342 	    kOSKextLogDebugLevel |
5343 	    kOSKextLogIPCFlag,
5344 	    "Received kext KC load request from user space.");
5345 
5346 	/* Regardless of processing, the fact that we have gotten here means some
5347 	 * user-space program is up and talking to us, so we'll switch our kext
5348 	 * registration to reflect that.
5349 	 */
5350 	if (!sUserLoadsActive) {
5351 		OSKextLog(/* kext */ NULL,
5352 		    kOSKextLogProgressLevel |
5353 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5354 		    "Switching to late startup (user-space) kext loading policy.");
5355 		sUserLoadsActive = true;
5356 	}
5357 
5358 	delayAutounloadBool = OSDynamicCast(OSBoolean,
5359 	    _OSKextGetRequestArgument(requestDict,
5360 	    kKextRequestArgumentDelayAutounloadKey));
5361 	startKextExcludeNum = OSDynamicCast(OSNumber,
5362 	    _OSKextGetRequestArgument(requestDict,
5363 	    kKextRequestArgumentStartExcludeKey));
5364 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
5365 	    _OSKextGetRequestArgument(requestDict,
5366 	    kKextRequestArgumentStartMatchingExcludeKey));
5367 	personalityNames = OSDynamicCast(OSArray,
5368 	    _OSKextGetRequestArgument(requestDict,
5369 	    kKextRequestArgumentPersonalityNamesKey));
5370 
5371 	if (delayAutounloadBool) {
5372 		delayAutounload = delayAutounloadBool->getValue();
5373 	}
5374 	if (startKextExcludeNum) {
5375 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
5376 	}
5377 	if (startMatchingExcludeNum) {
5378 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
5379 	}
5380 
5381 	OSKextLog(/* kext */ NULL,
5382 	    kOSKextLogProgressLevel |
5383 	    kOSKextLogIPCFlag,
5384 	    "Received request from user space to load KC kext %s.",
5385 	    theKext->getIdentifierCString());
5386 
5387 	/* this could be in the Auxiliary KC, so record the load request */
5388 	OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier()));
5389 
5390 	/*
5391 	 * Load the kext
5392 	 */
5393 	result = theKext->load(startKextExcludeLevel,
5394 	    startMatchingExcludeLevel, personalityNames);
5395 
5396 	if (result != kOSReturnSuccess) {
5397 		OSKextLog(theKext,
5398 		    kOSKextLogErrorLevel |
5399 		    kOSKextLogLoadFlag,
5400 		    "Failed to load kext %s (error 0x%x).",
5401 		    theKext->getIdentifierCString(), (int)result);
5402 
5403 		OSKext::removeKext(theKext,
5404 		    /* terminateService/removePersonalities */ true);
5405 		goto finish;
5406 	} else {
5407 		OSKextLog(theKext,
5408 		    kOSKextLogProgressLevel |
5409 		    kOSKextLogLoadFlag,
5410 		    "Kext %s Loaded successfully from %s KC",
5411 		    theKext->getIdentifierCString(), theKext->getKCTypeString());
5412 	}
5413 
5414 	if (delayAutounload) {
5415 		OSKextLog(theKext,
5416 		    kOSKextLogProgressLevel |
5417 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5418 		    "Setting delayed autounload for %s.",
5419 		    theKext->getIdentifierCString());
5420 		theKext->flags.delayAutounload = 1;
5421 	}
5422 
5423 finish:
5424 	IORecursiveLockUnlock(sKextLock);
5425 
5426 	return result;
5427 }
5428 
5429 /*********************************************************************
5430 *********************************************************************/
5431 /* static */
5432 OSReturn
loadCodelessKext(OSString * kextIdentifier,OSDictionary * requestDict)5433 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict)
5434 {
5435 	OSReturn  result = kOSReturnError;
5436 	OSDictionary *anInfoDict = NULL; // do not release
5437 
5438 	anInfoDict = OSDynamicCast(OSDictionary,
5439 	    _OSKextGetRequestArgument(requestDict,
5440 	    kKextRequestArgumentCodelessInfoKey));
5441 	if (anInfoDict == NULL) {
5442 		OSKextLog(/* kext */ NULL,
5443 		    kOSKextLogErrorLevel |
5444 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5445 		    "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.",
5446 		    kextIdentifier->getCStringNoCopy());
5447 		return kOSKextReturnInvalidArgument;
5448 	}
5449 
5450 	IORecursiveLockLock(sKextLock);
5451 
5452 	OSKextLog(/* kext */ NULL,
5453 	    kOSKextLogProgressLevel |
5454 	    kOSKextLogIPCFlag,
5455 	    "Received request from user space to load codeless kext %s.",
5456 	    kextIdentifier->getCStringNoCopy());
5457 
5458 	{
5459 		// instantiate a new kext, and don't hold a reference
5460 		// (the kext subsystem will hold one implicitly)
5461 		OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict);
5462 		if (!newKext) {
5463 			OSKextLog(/* kext */ NULL,
5464 			    kOSKextLogErrorLevel |
5465 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5466 			    "Could not instantiate codeless kext.");
5467 			result = kOSKextReturnNotLoadable;
5468 			goto finish;
5469 		}
5470 		if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) {
5471 			OSKextLog(/* kext */ NULL,
5472 			    kOSKextLogErrorLevel |
5473 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
5474 			    "Codeless kext identifiers don't match '%s' != '%s'",
5475 			    kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString());
5476 
5477 			OSKext::removeKext(newKext.get(), false);
5478 			result = kOSKextReturnInvalidArgument;
5479 			goto finish;
5480 		}
5481 
5482 		/* Record the request for the codeless kext */
5483 		OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier()));
5484 
5485 		result = kOSReturnSuccess;
5486 		/* Send the kext's personalities to the IOCatalog. This is an explicit load. */
5487 		result = newKext->sendPersonalitiesToCatalog(true, NULL);
5488 	}
5489 
5490 finish:
5491 	IORecursiveLockUnlock(sKextLock);
5492 
5493 	return result;
5494 }
5495 
5496 /*********************************************************************
5497 *********************************************************************/
5498 /* static */
5499 void
dropMatchingReferences(OSSet * kexts)5500 OSKext::dropMatchingReferences(
5501 	OSSet * kexts)
5502 {
5503 	IORecursiveLockLock(sKextLock);
5504 	kexts->iterateObjects(^bool (OSObject * obj) {
5505 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
5506 		if (!thisKext) {
5507 		        return false;
5508 		}
5509 		thisKext->matchingRefCount--;
5510 		return false;
5511 	});
5512 	IORecursiveLockUnlock(sKextLock);
5513 }
5514 
5515 /*********************************************************************
5516 *********************************************************************/
5517 /* static */
5518 void
recordIdentifierRequest(OSString * kextIdentifier)5519 OSKext::recordIdentifierRequest(
5520 	OSString * kextIdentifier)
5521 {
5522 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5523 	bool             fail                 = false;
5524 
5525 	if (!sAllKextLoadIdentifiers || !kextIdentifier) {
5526 		goto finish;
5527 	}
5528 
5529 	kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5530 	if (!kextIdentifierSymbol) {
5531 		// xxx - this is really a basic alloc failure
5532 		fail = true;
5533 		goto finish;
5534 	}
5535 
5536 	IORecursiveLockLock(sKextLock);
5537 	if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5538 		if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
5539 			fail = true;
5540 		} else {
5541 			// xxx - need to find a way to associate this whole func w/the kext
5542 			OSKextLog(/* kext */ NULL,
5543 			    // xxx - check level
5544 			    kOSKextLogStepLevel |
5545 			    kOSKextLogArchiveFlag,
5546 			    "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
5547 			    kextIdentifier->getCStringNoCopy());
5548 		}
5549 	}
5550 	IORecursiveLockUnlock(sKextLock);
5551 
5552 finish:
5553 
5554 	if (fail) {
5555 		OSKextLog(/* kext */ NULL,
5556 		    kOSKextLogErrorLevel |
5557 		    kOSKextLogArchiveFlag,
5558 		    "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
5559 		    kextIdentifier->getCStringNoCopy());
5560 	}
5561 	return;
5562 }
5563 
5564 /*********************************************************************
5565 *********************************************************************/
5566 OSReturn
load(OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5567 OSKext::load(
5568 	OSKextExcludeLevel   startOpt,
5569 	OSKextExcludeLevel   startMatchingOpt,
5570 	OSArray            * personalityNames)
5571 {
5572 	OSReturn             result                       = kOSReturnError;
5573 	OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
5574 	OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
5575 	unsigned int         i, count;
5576 	Boolean              alreadyLoaded                = false;
5577 	OSKext             * lastLoadedKext               = NULL;        // do not release
5578 
5579 	if (isInExcludeList()) {
5580 		OSKextLog(this,
5581 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
5582 		    kOSKextLogLoadFlag,
5583 		    "Kext %s is in exclude list, not loadable",
5584 		    getIdentifierCString());
5585 
5586 		result = kOSKextReturnNotLoadable;
5587 		goto finish;
5588 	}
5589 	if (!isLoadable()) {
5590 		OSKextLog(this,
5591 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
5592 		    kOSKextLogLoadFlag,
5593 		    "Kext %s is not loadable",
5594 		    getIdentifierCString());
5595 
5596 		result = kOSKextReturnNotLoadable;
5597 		goto finish;
5598 	}
5599 
5600 	if (isLoaded()) {
5601 		alreadyLoaded = true;
5602 		result = kOSReturnSuccess;
5603 
5604 		OSKextLog(this,
5605 		    kOSKextLogDebugLevel |
5606 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5607 		    "Kext %s is already loaded.",
5608 		    getIdentifierCString());
5609 		goto loaded;
5610 	}
5611 
5612 #if CONFIG_MACF
5613 	/*
5614 	 * On kxld and on embedded, only call into the MAC hook when on a
5615 	 * user thread, for access control over userspace kextloads.
5616 	 *
5617 	 * On non-kxld systems, additionally check the MAC hook for kexts in
5618 	 * the Pageable and Aux KCs, regardless of whether we are on a user
5619 	 * thread or not. This means on Apple silicon devices that the MAC
5620 	 * hook will only be useful to block 3rd party kexts loaded via
5621 	 * matching, and any kexts loaded from userspace kextloads.
5622 	 *
5623 	 * Note that this should _not_ be called on kexts loaded from the
5624 	 * kernel bootstrap thread as the kernel proc's cred struct is not
5625 	 * yet initialized! This won't happen on macOS because all the kexts
5626 	 * in the BootKC are self-contained and their kc_type = KCKindPrimary.
5627 	 */
5628 	if (current_task() != kernel_task
5629 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD
5630 	    || (kc_type != KCKindPrimary && kc_type != KCKindUnknown)
5631 #endif
5632 	    ) {
5633 		int                 macCheckResult      = 0;
5634 		kauth_cred_t        cred                = NULL;
5635 
5636 		cred = kauth_cred_get_with_ref();
5637 		macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
5638 		kauth_cred_unref(&cred);
5639 
5640 		if (macCheckResult != 0) {
5641 			result = kOSReturnError;
5642 			OSKextLog(this,
5643 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5644 			    "Failed to load kext %s (MAC policy error 0x%x).",
5645 			    getIdentifierCString(), macCheckResult);
5646 			goto finish;
5647 		}
5648 	}
5649 #endif /* CONFIG_MACF */
5650 
5651 	if (!sLoadEnabled) {
5652 		OSKextLog(this,
5653 		    kOSKextLogErrorLevel |
5654 		    kOSKextLogLoadFlag,
5655 		    "Kext loading is disabled (attempt to load kext %s).",
5656 		    getIdentifierCString());
5657 		result = kOSKextReturnDisabled;
5658 		goto finish;
5659 	}
5660 
5661 	/* If we've pushed the next available load tag to the invalid value,
5662 	 * we can't load any more kexts.
5663 	 */
5664 	if (sNextLoadTag == kOSKextInvalidLoadTag) {
5665 		OSKextLog(this,
5666 		    kOSKextLogErrorLevel |
5667 		    kOSKextLogLoadFlag,
5668 		    "Can't load kext %s - no more load tags to assign.",
5669 		    getIdentifierCString());
5670 		result = kOSKextReturnNoResources;
5671 		goto finish;
5672 	}
5673 
5674 	/* This is a bit of a hack, because we shouldn't be handling
5675 	 * personalities within the load function.
5676 	 */
5677 	if (!declaresExecutable()) {
5678 		/* There is a special case where a non-executable kext can be loaded: the
5679 		 * AppleKextExcludeList.  Detect that special kext by bundle identifier and
5680 		 * load its metadata into the global data structures, if appropriate
5681 		 */
5682 		if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
5683 			boolean_t updated = updateExcludeList(infoDict.get());
5684 			if (updated) {
5685 				OSKextLog(this,
5686 				    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
5687 				    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
5688 			}
5689 		}
5690 
5691 		if (isDriverKit()) {
5692 			if (loadTag == 0) {
5693 				sLoadedDriverKitKexts->setObject(this);
5694 				loadTag = sNextLoadTag++;
5695 			}
5696 		}
5697 		result = kOSReturnSuccess;
5698 		goto loaded;
5699 	}
5700 
5701 	/* Are we in safe boot?
5702 	 */
5703 	if (sSafeBoot && !isLoadableInSafeBoot()) {
5704 		OSKextLog(this,
5705 		    kOSKextLogErrorLevel |
5706 		    kOSKextLogLoadFlag,
5707 		    "Can't load kext %s - not loadable during safe boot.",
5708 		    getIdentifierCString());
5709 		result = kOSKextReturnBootLevel;
5710 		goto finish;
5711 	}
5712 
5713 	OSKextLog(this,
5714 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5715 	    "Loading kext %s.",
5716 	    getIdentifierCString());
5717 
5718 #if !VM_MAPPED_KEXTS
5719 	if (isPrelinked() == false) {
5720 		OSKextLog(this,
5721 		    kOSKextLogErrorLevel |
5722 		    kOSKextLogLoadFlag,
5723 		    "Can't load kext %s - not in a kext collection.",
5724 		    getIdentifierCString());
5725 		result = kOSKextReturnDisabled;
5726 		goto finish;
5727 	}
5728 #endif /* defined(__x86_64__) */
5729 
5730 #if CONFIG_KXLD
5731 	if (!sKxldContext) {
5732 		kern_return_t kxldResult;
5733 		kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
5734 		    &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
5735 		    /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
5736 		if (kxldResult) {
5737 			OSKextLog(this,
5738 			    kOSKextLogErrorLevel |
5739 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5740 			    "Can't load kext %s - failed to create link context.",
5741 			    getIdentifierCString());
5742 			result = kOSKextReturnNoMemory;
5743 			goto finish;
5744 		}
5745 	}
5746 #endif // CONFIG_KXLD
5747 
5748 	/* We only need to resolve dependencies once for the whole graph, but
5749 	 * resolveDependencies will just return if there's no work to do, so it's
5750 	 * safe to call it more than once.
5751 	 */
5752 	if (!resolveDependencies()) {
5753 		// xxx - check resolveDependencies() for log msg
5754 		OSKextLog(this,
5755 		    kOSKextLogErrorLevel |
5756 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5757 		    "Can't load kext %s - failed to resolve library dependencies.",
5758 		    getIdentifierCString());
5759 		result = kOSKextReturnDependencies;
5760 		goto finish;
5761 	}
5762 
5763 	/* If we are excluding just the kext being loaded now (and not its
5764 	 * dependencies), drop the exclusion level to none so dependencies
5765 	 * start and/or add their personalities.
5766 	 */
5767 	if (dependenciesStartOpt == kOSKextExcludeKext) {
5768 		dependenciesStartOpt = kOSKextExcludeNone;
5769 	}
5770 
5771 	if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
5772 		dependenciesStartMatchingOpt = kOSKextExcludeNone;
5773 	}
5774 
5775 	/* Load the dependencies, recursively.
5776 	 */
5777 	count = getNumDependencies();
5778 	for (i = 0; i < count; i++) {
5779 		OSKext * dependency = OSDynamicCast(OSKext,
5780 		    dependencies->getObject(i));
5781 		if (dependency == NULL) {
5782 			OSKextLog(this,
5783 			    kOSKextLogErrorLevel |
5784 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5785 			    "Internal error loading kext %s; dependency disappeared.",
5786 			    getIdentifierCString());
5787 			result = kOSKextReturnInternalError;
5788 			goto finish;
5789 		}
5790 
5791 		/* Dependencies must be started accorting to the opt,
5792 		 * but not given the personality names of the main kext.
5793 		 */
5794 		result = dependency->load(dependenciesStartOpt,
5795 		    dependenciesStartMatchingOpt,
5796 		    /* personalityNames */ NULL);
5797 		if (result != KERN_SUCCESS) {
5798 			OSKextLog(this,
5799 			    kOSKextLogErrorLevel |
5800 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5801 			    "Dependency %s of kext %s failed to load.",
5802 			    dependency->getIdentifierCString(),
5803 			    getIdentifierCString());
5804 
5805 			OSKext::removeKext(dependency,
5806 			    /* terminateService/removePersonalities */ true);
5807 			result = kOSKextReturnDependencyLoadError;
5808 
5809 			goto finish;
5810 		}
5811 	}
5812 
5813 	result = loadExecutable();
5814 	if (result != KERN_SUCCESS) {
5815 		goto finish;
5816 	}
5817 
5818 	pendingPgoHead.next = &pendingPgoHead;
5819 	pendingPgoHead.prev = &pendingPgoHead;
5820 
5821 	// The kernel PRNG is not initialized when the first kext is
5822 	// loaded, so use early random
5823 	uuid_generate_early_random(instance_uuid);
5824 	account = IOMallocType(OSKextAccount);
5825 
5826 	account->loadTag = kmod_info->id;
5827 	account->site.refcount = 0;
5828 	account->site.flags = VM_TAG_KMOD;
5829 
5830 #if DEVELOPMENT || DEBUG
5831 	/* Setup the task reference group. */
5832 	(void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name),
5833 	    "task_%s", getIdentifierCString());
5834 	account->task_refgrp.grp_name = account->task_refgrp_name;
5835 	account->task_refgrp.grp_parent = &task_external_refgrp;
5836 	os_ref_log_init(&account->task_refgrp);
5837 #endif /* DEVELOPMENT || DEBUG */
5838 
5839 	account->kext = this;
5840 	if (gIOSurfaceIdentifier == bundleID) {
5841 		vm_tag_alloc(&account->site);
5842 		gIOSurfaceTag = account->site.tag;
5843 	}
5844 
5845 	flags.loaded = true;
5846 
5847 	/* Add the kext to the list of loaded kexts and update the kmod_info
5848 	 * struct to point to that of the last loaded kext (which is the way
5849 	 * it's always been done, though I'd rather do them in order now).
5850 	 */
5851 	lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
5852 	sLoadedKexts->setObject(this);
5853 
5854 	/* Keep the kernel itself out of the kmod list.
5855 	 */
5856 	if (lastLoadedKext->isKernel()) {
5857 		lastLoadedKext = NULL;
5858 	}
5859 
5860 	if (lastLoadedKext) {
5861 		kmod_info->next = lastLoadedKext->kmod_info;
5862 	}
5863 
5864 	notifyKextLoadObservers(this, kmod_info);
5865 
5866 	/* Make the global kmod list point at the just-loaded kext. Note that the
5867 	 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
5868 	 * although we do report it in kextstat these days by using the newer
5869 	 * OSArray of loaded kexts, which does contain it.
5870 	 *
5871 	 * (The OSKext object representing the kernel doesn't even have a kmod_info
5872 	 * struct, though I suppose we could stick a pointer to it from the
5873 	 * static struct in OSRuntime.cpp.)
5874 	 */
5875 	kmod = kmod_info;
5876 
5877 	/* Save the list of loaded kexts in case we panic.
5878 	 */
5879 	OSKext::saveLoadedKextPanicList();
5880 
5881 	if (isExecutable()) {
5882 		OSKext::updateLoadedKextSummaries();
5883 		savePanicString(/* isLoading */ true);
5884 
5885 #if CONFIG_DTRACE
5886 		registerWithDTrace();
5887 #else
5888 		jettisonLinkeditSegment();
5889 #endif /* CONFIG_DTRACE */
5890 
5891 #if !VM_MAPPED_KEXTS
5892 		/* If there is a page (or more) worth of padding after the end
5893 		 * of the last data section but before the end of the data segment
5894 		 * then free it in the same manner the LinkeditSegment is freed
5895 		 */
5896 		jettisonDATASegmentPadding();
5897 #endif
5898 	}
5899 
5900 loaded:
5901 	if (isExecutable() && !flags.started) {
5902 		if (startOpt == kOSKextExcludeNone) {
5903 			result = start();
5904 			if (result != kOSReturnSuccess) {
5905 				OSKextLog(this,
5906 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5907 				    "Kext %s start failed (result 0x%x).",
5908 				    getIdentifierCString(), result);
5909 				result = kOSKextReturnStartStopError;
5910 			}
5911 		}
5912 	}
5913 
5914 	/* If not excluding matching, send the personalities to the kernel.
5915 	 * This never affects the result of the load operation.
5916 	 * This is a bit of a hack, because we shouldn't be handling
5917 	 * personalities within the load function.
5918 	 */
5919 	if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
5920 		result = sendPersonalitiesToCatalog(true, personalityNames);
5921 	}
5922 
5923 finish:
5924 
5925 	if (result != kOSReturnSuccess) {
5926 		OSKextLog(this,
5927 		    kOSKextLogErrorLevel |
5928 		    kOSKextLogLoadFlag,
5929 		    "Kext %s failed to load (0x%x).",
5930 		    getIdentifierCString(), (int)result);
5931 	} else if (!alreadyLoaded) {
5932 		OSKextLog(this,
5933 		    kOSKextLogProgressLevel |
5934 		    kOSKextLogLoadFlag,
5935 		    "Kext %s loaded.",
5936 		    getIdentifierCString());
5937 
5938 		queueKextNotification(kKextRequestPredicateLoadNotification,
5939 		    OSDynamicCast(OSString, bundleID.get()));
5940 	}
5941 	return result;
5942 }
5943 
5944 #if CONFIG_KXLD
5945 /*********************************************************************
5946 *
5947 *********************************************************************/
5948 static char *
strdup(const char * string)5949 strdup(const char * string)
5950 {
5951 	char * result = NULL;
5952 	size_t size;
5953 
5954 	if (!string) {
5955 		goto finish;
5956 	}
5957 
5958 	size = 1 + strlen(string);
5959 	result = (char *)kalloc_data_tag(size, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
5960 	if (!result) {
5961 		goto finish;
5962 	}
5963 
5964 	memcpy(result, string, size);
5965 
5966 finish:
5967 	return result;
5968 }
5969 #endif // CONFIG_KXLD
5970 
5971 /*********************************************************************
5972 *
5973 *********************************************************************/
5974 
5975 kernel_section_t *
lookupSection(const char * segname,const char * secname)5976 OSKext::lookupSection(const char *segname, const char *secname)
5977 {
5978 	kernel_section_t         * found_section = NULL;
5979 	kernel_mach_header_t     * mh            = NULL;
5980 	kernel_segment_command_t * seg           = NULL;
5981 	kernel_section_t         * sec           = NULL;
5982 
5983 	if (!linkedExecutable) {
5984 		return NULL;
5985 	}
5986 
5987 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5988 
5989 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5990 		if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
5991 			continue;
5992 		}
5993 
5994 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5995 			if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
5996 				found_section = sec;
5997 				goto out;
5998 			}
5999 		}
6000 	}
6001 
6002 out:
6003 	return found_section;
6004 }
6005 
6006 /*********************************************************************
6007 *
6008 *********************************************************************/
6009 
6010 OSReturn
slidePrelinkedExecutable(bool doCoalescedSlides)6011 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides)
6012 {
6013 	OSReturn                       result           = kOSKextReturnBadData;
6014 	kernel_mach_header_t         * mh               = NULL;
6015 	kernel_segment_command_t     * seg              = NULL;
6016 	kernel_segment_command_t     * linkeditSeg      = NULL;
6017 	kernel_section_t             * sec              = NULL;
6018 	char                         * linkeditBase     = NULL;
6019 	bool                           haveLinkeditBase = false;
6020 	char                         * relocBase        = NULL;
6021 	bool                           haveRelocBase    = false;
6022 	struct dysymtab_command      * dysymtab         = NULL;
6023 	struct linkedit_data_command * segmentSplitInfo = NULL;
6024 	struct symtab_command        * symtab           = NULL;
6025 	kernel_nlist_t               * sym              = NULL;
6026 	struct relocation_info       * reloc            = NULL;
6027 	uint32_t                       i                = 0;
6028 	int                            reloc_size;
6029 	vm_offset_t                    new_kextsize;
6030 
6031 	if (linkedExecutable == NULL || flags.builtin) {
6032 		result = kOSReturnSuccess;
6033 		goto finish;
6034 	}
6035 
6036 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6037 	if (kernel_mach_header_is_in_fileset(mh)) {
6038 		// kexts in filesets are slid as part of collection sliding
6039 		result = kOSReturnSuccess;
6040 		goto finish;
6041 	}
6042 
6043 	segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
6044 
6045 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6046 		if (!seg->vmaddr) {
6047 			continue;
6048 		}
6049 
6050 		seg->vmaddr = ml_static_slide(seg->vmaddr);
6051 
6052 #if KASLR_KEXT_DEBUG
6053 		IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
6054 		    seg->segname,
6055 		    (unsigned long)ml_static_unslide(seg->vmaddr),
6056 		    (unsigned long)seg->vmaddr);
6057 #endif
6058 
6059 		if (!haveRelocBase) {
6060 			relocBase = (char *) seg->vmaddr;
6061 			haveRelocBase = true;
6062 		}
6063 		if (!strcmp(seg->segname, "__LINKEDIT")) {
6064 			linkeditBase = (char *) seg->vmaddr - seg->fileoff;
6065 			haveLinkeditBase = true;
6066 			linkeditSeg = seg;
6067 		}
6068 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6069 			sec->addr = ml_static_slide(sec->addr);
6070 
6071 #if KASLR_KEXT_DEBUG
6072 			IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
6073 			    sec->sectname,
6074 			    (unsigned long)ml_static_unslide(sec->addr),
6075 			    (unsigned long)sec->addr);
6076 #endif
6077 		}
6078 	}
6079 
6080 	dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
6081 
6082 	symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
6083 
6084 	if (symtab != NULL && doCoalescedSlides == false) {
6085 		/* Some pseudo-kexts have symbol tables without segments.
6086 		 * Ignore them. */
6087 		if (symtab->nsyms > 0 && haveLinkeditBase) {
6088 			sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
6089 			for (i = 0; i < symtab->nsyms; i++) {
6090 				if (sym[i].n_type & N_STAB) {
6091 					continue;
6092 				}
6093 				sym[i].n_value = ml_static_slide(sym[i].n_value);
6094 
6095 #if KASLR_KEXT_DEBUG
6096 #define MAX_SYMS_TO_LOG 5
6097 				if (i < MAX_SYMS_TO_LOG) {
6098 					IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
6099 					    (unsigned long)ml_static_unslide(sym[i].n_value),
6100 					    (unsigned long)sym[i].n_value);
6101 				}
6102 #endif
6103 			}
6104 		}
6105 	}
6106 
6107 	if (dysymtab != NULL && doCoalescedSlides == false) {
6108 		if (dysymtab->nextrel > 0) {
6109 			OSKextLog(this,
6110 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6111 			    kOSKextLogLinkFlag,
6112 			    "Sliding kext %s: External relocations found.",
6113 			    getIdentifierCString());
6114 			goto finish;
6115 		}
6116 
6117 		if (dysymtab->nlocrel > 0) {
6118 			if (!haveLinkeditBase) {
6119 				OSKextLog(this,
6120 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6121 				    kOSKextLogLinkFlag,
6122 				    "Sliding kext %s: No linkedit segment.",
6123 				    getIdentifierCString());
6124 				goto finish;
6125 			}
6126 
6127 			if (!haveRelocBase) {
6128 				OSKextLog(this,
6129 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6130 				    kOSKextLogLinkFlag,
6131 #if __x86_64__
6132 				    "Sliding kext %s: No writable segments.",
6133 #else
6134 				    "Sliding kext %s: No segments.",
6135 #endif
6136 				    getIdentifierCString());
6137 				goto finish;
6138 			}
6139 
6140 			reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
6141 			reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
6142 
6143 			for (i = 0; i < dysymtab->nlocrel; i++) {
6144 				if (reloc[i].r_extern != 0
6145 				    || reloc[i].r_type != 0
6146 				    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
6147 				    ) {
6148 					OSKextLog(this,
6149 					    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6150 					    kOSKextLogLinkFlag,
6151 					    "Sliding kext %s: Unexpected relocation found.",
6152 					    getIdentifierCString());
6153 					goto finish;
6154 				}
6155 				if (reloc[i].r_pcrel != 0) {
6156 					continue;
6157 				}
6158 				uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
6159 				*relocAddr = ml_static_slide(*relocAddr);
6160 
6161 #if KASLR_KEXT_DEBUG
6162 #define MAX_DYSYMS_TO_LOG 5
6163 				if (i < MAX_DYSYMS_TO_LOG) {
6164 					IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
6165 					    (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
6166 					    (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
6167 				}
6168 #endif
6169 			}
6170 
6171 			/* We should free these relocations, not just delete the reference to them.
6172 			 * <rdar://problem/10535549> Free relocations from PIE kexts.
6173 			 *
6174 			 * For now, we do not free LINKEDIT for kexts with split segments.
6175 			 */
6176 			new_kextsize = round_page(kmod_info->size - reloc_size);
6177 			if (new_kextsize > UINT_MAX) {
6178 				OSKextLog(this,
6179 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6180 				    kOSKextLogLinkFlag,
6181 				    "Kext %s: new kext size is too large.",
6182 				    getIdentifierCString());
6183 				goto finish;
6184 			}
6185 			if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
6186 				vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
6187 				vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
6188 				vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
6189 				size_t          bytes_remaining = endofkext - endofrelocInfo;
6190 				OSSharedPtr<OSData>        new_osdata;
6191 
6192 				/* fix up symbol offsets if they are after the dsymtab local relocs */
6193 				if (symtab) {
6194 					if (dysymtab->locreloff < symtab->symoff) {
6195 						symtab->symoff -= reloc_size;
6196 					}
6197 					if (dysymtab->locreloff < symtab->stroff) {
6198 						symtab->stroff -= reloc_size;
6199 					}
6200 				}
6201 				if (dysymtab->locreloff < dysymtab->extreloff) {
6202 					dysymtab->extreloff -= reloc_size;
6203 				}
6204 
6205 				/* move data behind reloc info down to new offset */
6206 				if (endofrelocInfo < endofkext) {
6207 					memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
6208 				}
6209 
6210 				/* Create a new OSData for the smaller kext object and reflect
6211 				 * new linkedit segment size.
6212 				 */
6213 				linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
6214 				linkeditSeg->filesize = linkeditSeg->vmsize;
6215 
6216 				new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize);
6217 				if (new_osdata) {
6218 					/* Fix up kmod info and linkedExecutable.
6219 					 */
6220 					kmod_info->size = new_kextsize;
6221 #if VM_MAPPED_KEXTS
6222 					new_osdata->setDeallocFunction(osdata_kext_free);
6223 #else
6224 					new_osdata->setDeallocFunction(osdata_phys_free);
6225 #endif
6226 					linkedExecutable->setDeallocFunction(NULL);
6227 					linkedExecutable = os::move(new_osdata);
6228 
6229 #if VM_MAPPED_KEXTS
6230 					kext_free(new_endofkext, (endofkext - new_endofkext));
6231 #else
6232 					ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
6233 #endif
6234 				}
6235 			}
6236 			dysymtab->nlocrel = 0;
6237 			dysymtab->locreloff = 0;
6238 		}
6239 	}
6240 
6241 	result = kOSReturnSuccess;
6242 finish:
6243 	return result;
6244 }
6245 
6246 /*********************************************************************
6247 * called only by load()
6248 *********************************************************************/
6249 OSReturn
loadExecutable()6250 OSKext::loadExecutable()
6251 {
6252 	OSReturn              result             = kOSReturnError;
6253 	OSSharedPtr<OSArray>  linkDependencies;
6254 	uint32_t              num_kmod_refs      = 0;
6255 	OSData              * theExecutable      = NULL;        // do not release
6256 	OSString            * versString         = NULL;        // do not release
6257 	const char          * versCString        = NULL;        // do not free
6258 	const char          * string             = NULL;        // do not free
6259 
6260 #if CONFIG_KXLD
6261 	unsigned int          i;
6262 	uint32_t              numDirectDependencies   = 0;
6263 	kern_return_t         kxldResult;
6264 	KXLDDependency     *  kxlddeps           = NULL;        // must kfree
6265 	uint32_t              num_kxlddeps       = 0;
6266 	struct mach_header ** kxldHeaderPtr      = NULL;        // do not free
6267 	struct mach_header  * kxld_header        = NULL;        // xxx - need to free here?
6268 #endif // CONFIG_KXLD
6269 
6270 	/* We need the version string for a variety of bits below.
6271 	 */
6272 	versString = OSDynamicCast(OSString,
6273 	    getPropertyForHostArch(kCFBundleVersionKey));
6274 	if (!versString) {
6275 		goto finish;
6276 	}
6277 	versCString = versString->getCStringNoCopy();
6278 
6279 	if (isKernelComponent()) {
6280 		if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
6281 			if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
6282 				OSKextLog(this,
6283 				    kOSKextLogErrorLevel |
6284 				    kOSKextLogLoadFlag,
6285 				    "Kernel component %s has incorrect version %s; "
6286 				    "expected %s.",
6287 				    getIdentifierCString(),
6288 				    versCString, KERNEL6_VERSION);
6289 				result = kOSKextReturnInternalError;
6290 				goto finish;
6291 			} else if (strcmp(versCString, osrelease)) {
6292 				OSKextLog(this,
6293 				    kOSKextLogErrorLevel |
6294 				    kOSKextLogLoadFlag,
6295 				    "Kernel component %s has incorrect version %s; "
6296 				    "expected %s.",
6297 				    getIdentifierCString(),
6298 				    versCString, osrelease);
6299 				result = kOSKextReturnInternalError;
6300 				goto finish;
6301 			}
6302 		}
6303 	}
6304 
6305 #if defined(__x86_64__) || defined(__i386__)
6306 	if (flags.resetSegmentsFromVnode) {
6307 		/* Fixup the chains and slide the mach headers */
6308 		kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address;
6309 
6310 		if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) {
6311 			result = kOSKextReturnValidation;
6312 			goto finish;
6313 		}
6314 	}
6315 #endif //(__x86_64__) || defined(__i386__)
6316 
6317 	if (isPrelinked()) {
6318 		goto register_kmod;
6319 	}
6320 
6321 	/* <rdar://problem/21444003> all callers must be entitled */
6322 	if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) {
6323 		OSKextLog(this,
6324 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6325 		    "Not entitled to link kext '%s'",
6326 		    getIdentifierCString());
6327 		result = kOSKextReturnNotPrivileged;
6328 		goto finish;
6329 	}
6330 
6331 	theExecutable = getExecutable();
6332 	if (!theExecutable) {
6333 		if (declaresExecutable()) {
6334 			OSKextLog(this,
6335 			    kOSKextLogErrorLevel |
6336 			    kOSKextLogLoadFlag,
6337 			    "Can't load kext %s - executable is missing.",
6338 			    getIdentifierCString());
6339 			result = kOSKextReturnValidation;
6340 			goto finish;
6341 		}
6342 		goto register_kmod;
6343 	}
6344 
6345 	if (isInterface()) {
6346 		OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable);
6347 		if (executableCopy) {
6348 			setLinkedExecutable(executableCopy.get());
6349 		}
6350 		goto register_kmod;
6351 	}
6352 
6353 #if CONFIG_KXLD
6354 	numDirectDependencies = getNumDependencies();
6355 
6356 	if (flags.hasBleedthrough) {
6357 		linkDependencies = dependencies;
6358 	} else {
6359 		linkDependencies = OSArray::withArray(dependencies.get());
6360 		if (!linkDependencies) {
6361 			OSKextLog(this,
6362 			    kOSKextLogErrorLevel |
6363 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6364 			    "Can't allocate link dependencies to load kext %s.",
6365 			    getIdentifierCString());
6366 			goto finish;
6367 		}
6368 
6369 		for (i = 0; i < numDirectDependencies; ++i) {
6370 			OSKext * dependencyKext = OSDynamicCast(OSKext,
6371 			    dependencies->getObject(i));
6372 			dependencyKext->addBleedthroughDependencies(linkDependencies.get());
6373 		}
6374 	}
6375 
6376 	num_kxlddeps = linkDependencies->getCount();
6377 	if (!num_kxlddeps) {
6378 		OSKextLog(this,
6379 		    kOSKextLogErrorLevel |
6380 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6381 		    "Can't load kext %s - it has no library dependencies.",
6382 		    getIdentifierCString());
6383 		goto finish;
6384 	}
6385 
6386 	kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
6387 	if (!kxlddeps) {
6388 		OSKextLog(this,
6389 		    kOSKextLogErrorLevel |
6390 		    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6391 		    "Can't allocate link context to load kext %s.",
6392 		    getIdentifierCString());
6393 		goto finish;
6394 	}
6395 	bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
6396 
6397 	for (i = 0; i < num_kxlddeps; ++i) {
6398 		OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
6399 
6400 		if (dependency->isInterface()) {
6401 			OSKext *interfaceTargetKext = NULL;        //do not release
6402 			OSData * interfaceTarget = NULL;        //do not release
6403 
6404 			if (dependency->isKernelComponent()) {
6405 				interfaceTargetKext = sKernelKext;
6406 				interfaceTarget = sKernelKext->linkedExecutable.get();
6407 			} else {
6408 				interfaceTargetKext = OSDynamicCast(OSKext,
6409 				    dependency->dependencies->getObject(0));
6410 
6411 				interfaceTarget = interfaceTargetKext->linkedExecutable.get();
6412 			}
6413 
6414 			if (!interfaceTarget) {
6415 				// panic?
6416 				goto finish;
6417 			}
6418 
6419 			/* The names set here aren't actually logged yet <rdar://problem/7941514>,
6420 			 * it will be useful to have them in the debugger.
6421 			 * strdup() failing isn't critical right here so we don't check that.
6422 			 */
6423 			kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
6424 			kxlddeps[i].kext_size = interfaceTarget->getLength();
6425 			kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
6426 
6427 			if (dependency->linkedExecutable != NULL) {
6428 				kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
6429 				kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
6430 			} else {
6431 				kxlddeps[i].interface = (u_char *) NULL;
6432 				kxlddeps[i].interface_size = 0;
6433 			}
6434 			kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
6435 		} else {
6436 			kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
6437 			kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
6438 			kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
6439 		}
6440 
6441 		kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
6442 	}
6443 
6444 	kxldHeaderPtr = &kxld_header;
6445 
6446 #if DEBUG
6447 	OSKextLog(this,
6448 	    kOSKextLogExplicitLevel |
6449 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6450 	    "Kext %s - calling kxld_link_file:\n"
6451 	    "    kxld_context: %p\n"
6452 	    "    executable: %p    executable_length: %d\n"
6453 	    "    user_data: %p\n"
6454 	    "    kxld_dependencies: %p    num_dependencies: %d\n"
6455 	    "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
6456 	    getIdentifierCString(), sKxldContext,
6457 	    theExecutable->getBytesNoCopy(), theExecutable->getLength(),
6458 	    this, kxlddeps, num_kxlddeps,
6459 	    kxldHeaderPtr, &kmod_info);
6460 #endif
6461 
6462 	/* After this call, the linkedExecutable instance variable
6463 	 * should exist.
6464 	 */
6465 	kxldResult = kxld_link_file(sKxldContext,
6466 	    (u_char *)theExecutable->getBytesNoCopy(),
6467 	    theExecutable->getLength(),
6468 	    getIdentifierCString(), this, kxlddeps, num_kxlddeps,
6469 	    (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
6470 
6471 	if (kxldResult != KERN_SUCCESS) {
6472 		// xxx - add kxldResult here?
6473 		OSKextLog(this,
6474 		    kOSKextLogErrorLevel |
6475 		    kOSKextLogLoadFlag,
6476 		    "Can't load kext %s - link failed.",
6477 		    getIdentifierCString());
6478 		result = kOSKextReturnLinkError;
6479 		goto finish;
6480 	}
6481 
6482 	/* We've written data & instructions into kernel memory, so flush the data
6483 	 * cache and invalidate the instruction cache.
6484 	 * I/D caches are coherent on x86
6485 	 */
6486 #if !defined(__i386__) && !defined(__x86_64__)
6487 	flush_dcache(kmod_info->address, kmod_info->size, false);
6488 	invalidate_icache(kmod_info->address, kmod_info->size, false);
6489 #endif
6490 
6491 #else // !CONFIG_KXLD
6492 	OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6493 	    "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString());
6494 	result = kOSKextReturnLinkError;
6495 	goto finish;
6496 #endif // CONFIG_KXLD
6497 
6498 register_kmod:
6499 
6500 	if (isInterface()) {
6501 		/* Whip up a fake kmod_info entry for the interface kext.
6502 		 */
6503 		kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
6504 		if (!kmod_info) {
6505 			result = KERN_MEMORY_ERROR;
6506 			goto finish;
6507 		}
6508 
6509 		/* A pseudokext has almost nothing in its kmod_info struct.
6510 		 */
6511 		kmod_info->info_version = KMOD_INFO_VERSION;
6512 
6513 		/* An interface kext doesn't have a linkedExecutable, so save a
6514 		 * copy of the UUID out of the original executable via copyUUID()
6515 		 * while we still have the original executable.
6516 		 */
6517 		interfaceUUID = copyUUID();
6518 	}
6519 
6520 	kmod_info->id = loadTag = sNextLoadTag++;
6521 	kmod_info->reference_count = 0;         // KMOD_DECL... sets it to -1 (invalid).
6522 
6523 	/* Stamp the bundle ID and version from the OSKext over anything
6524 	 * resident inside the kmod_info.
6525 	 */
6526 	string = getIdentifierCString();
6527 	strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
6528 
6529 	string = versCString;
6530 	strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
6531 
6532 	/* Add the dependencies' kmod_info structs as kmod_references.
6533 	 */
6534 	num_kmod_refs = getNumDependencies();
6535 	if (num_kmod_refs) {
6536 		kmod_info->reference_list = kalloc_type_tag(kmod_reference_t,
6537 		    num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT);
6538 		if (!kmod_info->reference_list) {
6539 			result = KERN_MEMORY_ERROR;
6540 			goto finish;
6541 		}
6542 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
6543 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
6544 			OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
6545 			ref->info = refKext->kmod_info;
6546 			ref->info->reference_count++;
6547 
6548 			if (refIndex + 1 < num_kmod_refs) {
6549 				ref->next = kmod_info->reference_list + refIndex + 1;
6550 			}
6551 		}
6552 	}
6553 
6554 	if (kmod_info->hdr_size > UINT32_MAX) {
6555 		OSKextLog(this,
6556 		    kOSKextLogErrorLevel |
6557 		    kOSKextLogLoadFlag,
6558 #if __LP64__
6559 		    "Kext %s header size is too large (%lu > UINT32_MAX).",
6560 #else
6561 		    "Kext %s header size is too large (%u > UINT32_MAX).",
6562 #endif
6563 		    kmod_info->name,
6564 		    kmod_info->hdr_size);
6565 		result = KERN_FAILURE;
6566 		goto finish;
6567 	}
6568 
6569 	if (kmod_info->size > UINT32_MAX) {
6570 		OSKextLog(this,
6571 		    kOSKextLogErrorLevel |
6572 		    kOSKextLogLoadFlag,
6573 #if __LP64__
6574 		    "Kext %s size is too large (%lu > UINT32_MAX).",
6575 #else
6576 		    "Kext %s size is too large (%u > UINT32_MAX).",
6577 #endif
6578 		    kmod_info->name,
6579 		    kmod_info->size);
6580 		result = KERN_FAILURE;
6581 		goto finish;
6582 	}
6583 
6584 	if (!isInterface() && linkedExecutable) {
6585 		OSKextLog(this,
6586 		    kOSKextLogProgressLevel |
6587 		    kOSKextLogLoadFlag,
6588 		    "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
6589 		    kmod_info->name,
6590 		    (unsigned)kmod_info->size / PAGE_SIZE,
6591 		    (unsigned long)ml_static_unslide(kmod_info->address),
6592 		    (unsigned)kmod_info->id);
6593 	}
6594 
6595 	/* VM protections and wiring for the Aux KC are done at collection loading time */
6596 	if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) {
6597 		/* if prelinked and primary KC, VM protections are already set */
6598 		result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true);
6599 		if (result != KERN_SUCCESS) {
6600 			goto finish;
6601 		}
6602 	}
6603 
6604 #if KASAN
6605 	if (linkedExecutable) {
6606 		kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
6607 		    linkedExecutable->getLength(), getIdentifierCString());
6608 	}
6609 #else
6610 	if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
6611 		OSKextLog(this,
6612 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6613 		    "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
6614 		    getIdentifierCString()
6615 		    );
6616 		result = KERN_FAILURE;
6617 		goto finish;
6618 	}
6619 #endif
6620 
6621 	result = kOSReturnSuccess;
6622 
6623 finish:
6624 
6625 #if CONFIG_KXLD
6626 	/* Clear up locally allocated dependency info.
6627 	 */
6628 	for (i = 0; i < num_kxlddeps; ++i) {
6629 		size_t size;
6630 
6631 		if (kxlddeps[i].kext_name) {
6632 			size = 1 + strlen(kxlddeps[i].kext_name);
6633 			kfree_data(kxlddeps[i].kext_name, size);
6634 		}
6635 		if (kxlddeps[i].interface_name) {
6636 			size = 1 + strlen(kxlddeps[i].interface_name);
6637 			kfree_data(kxlddeps[i].interface_name, size);
6638 		}
6639 	}
6640 	if (kxlddeps) {
6641 		kfree_type(KXLDDependency, num_kxlddeps, kxlddeps);
6642 	}
6643 #endif // CONFIG_KXLD
6644 
6645 	/* We no longer need the unrelocated executable (which the linker
6646 	 * has altered anyhow).
6647 	 */
6648 	setExecutable(NULL);
6649 
6650 	if (result != kOSReturnSuccess) {
6651 		OSKextLog(this,
6652 		    kOSKextLogErrorLevel |
6653 		    kOSKextLogLoadFlag,
6654 		    "Failed to load executable for kext %s.",
6655 		    getIdentifierCString());
6656 
6657 		if (kmod_info && kmod_info->reference_list) {
6658 			kfree_type(kmod_reference_t, num_kmod_refs,
6659 			    kmod_info->reference_list);
6660 		}
6661 		if (isInterface()) {
6662 			kfree_type(kmod_info_t, kmod_info);
6663 			kmod_info = NULL;
6664 		}
6665 		if (kc_type == KCKindUnknown) {
6666 			kmod_info = NULL;
6667 			if (linkedExecutable) {
6668 				linkedExecutable.reset();
6669 			}
6670 		}
6671 	}
6672 
6673 	return result;
6674 }
6675 
6676 /* static */
6677 void
jettisonFileSetLinkeditSegment(kernel_mach_header_t * mh)6678 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh)
6679 {
6680 	kernel_segment_command_t *linkeditseg = NULL;
6681 
6682 	linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT);
6683 	if (linkeditseg == NULL) {
6684 		panic("FileSet booted with no Linkedit segment");
6685 	}
6686 
6687 #if VM_MAPPED_KEXTS
6688 	/* BootKC on x86_64 is not vm mapped */
6689 	ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize);
6690 
6691 	OSKextLog(/* kext */ NULL,
6692 	    kOSKextLogProgressLevel |
6693 	    kOSKextLogGeneralFlag,
6694 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
6695 	    linkeditseg->vmaddr, linkeditseg->vmsize);
6696 #else
6697 	/* BootKC on arm64 is not vm mapped, but is slid */
6698 	vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase));
6699 
6700 	ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize);
6701 
6702 	OSKextLog(/* kext */ NULL,
6703 	    kOSKextLogProgressLevel |
6704 	    kOSKextLogGeneralFlag,
6705 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
6706 	    (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize);
6707 #endif /* VM_MAPPED_KEXTS */
6708 }
6709 
6710 /*********************************************************************
6711 * The linkedit segment is used by the kext linker for dependency
6712 * resolution, and by dtrace for probe initialization. We can free it
6713 * for non-library kexts, since no kexts depend on non-library kexts
6714 * by definition, once dtrace has been initialized.
6715 *********************************************************************/
6716 void
jettisonLinkeditSegment(void)6717 OSKext::jettisonLinkeditSegment(void)
6718 {
6719 	kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
6720 	kernel_segment_command_t * linkedit = NULL;
6721 	vm_offset_t                start;
6722 	vm_size_t                  linkeditsize, kextsize;
6723 	OSSharedPtr<OSData>        data;
6724 
6725 	if (isInFileset()) {
6726 		return;
6727 	}
6728 
6729 #if NO_KEXTD
6730 	/* We can free symbol tables for all embedded kexts because we don't
6731 	 * support runtime kext linking.
6732 	 */
6733 	if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
6734 #else
6735 	if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
6736 #endif
6737 		goto finish;
6738 	}
6739 
6740 	/* Find the linkedit segment.  If it's not the last segment, then freeing
6741 	 * it will fragment the kext into multiple VM regions, which OSKext is not
6742 	 * designed to handle, so we'll have to skip it.
6743 	 */
6744 	linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
6745 	if (!linkedit) {
6746 		goto finish;
6747 	}
6748 
6749 	if (round_page(kmod_info->address + kmod_info->size) !=
6750 	    round_page(linkedit->vmaddr + linkedit->vmsize)) {
6751 		goto finish;
6752 	}
6753 
6754 	/* Create a new OSData for the smaller kext object.
6755 	 */
6756 	linkeditsize = round_page(linkedit->vmsize);
6757 	kextsize = kmod_info->size - linkeditsize;
6758 	start = linkedit->vmaddr;
6759 
6760 	if (kextsize > UINT_MAX) {
6761 		goto finish;
6762 	}
6763 	data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize);
6764 	if (!data) {
6765 		goto finish;
6766 	}
6767 
6768 	/* Fix the kmod info and linkedExecutable.
6769 	 */
6770 	kmod_info->size = kextsize;
6771 
6772 #if VM_MAPPED_KEXTS
6773 	data->setDeallocFunction(osdata_kext_free);
6774 #else
6775 	data->setDeallocFunction(osdata_phys_free);
6776 #endif
6777 	linkedExecutable->setDeallocFunction(NULL);
6778 	linkedExecutable = os::move(data);
6779 	flags.jettisonLinkeditSeg = 1;
6780 
6781 	/* Free the linkedit segment.
6782 	 */
6783 #if VM_MAPPED_KEXTS
6784 	kext_free(start, linkeditsize);
6785 #else
6786 	ml_static_mfree(start, linkeditsize);
6787 #endif
6788 
6789 finish:
6790 	return;
6791 }
6792 
6793 /*********************************************************************
6794 * If there are whole pages that are unused betweem the last section
6795 * of the DATA segment and the end of the DATA segment then we can free
6796 * them
6797 *********************************************************************/
6798 void
6799 OSKext::jettisonDATASegmentPadding(void)
6800 {
6801 	kernel_mach_header_t * mh;
6802 	kernel_segment_command_t * dataSeg;
6803 	kernel_section_t * sec, * lastSec;
6804 	vm_offset_t dataSegEnd, lastSecEnd;
6805 	vm_size_t padSize;
6806 
6807 	if (flags.builtin) {
6808 		return;
6809 	}
6810 	mh = (kernel_mach_header_t *)kmod_info->address;
6811 
6812 	if (isInFileset()) {
6813 		return;
6814 	}
6815 
6816 	dataSeg = getsegbynamefromheader(mh, SEG_DATA);
6817 	if (dataSeg == NULL) {
6818 		return;
6819 	}
6820 
6821 	lastSec = NULL;
6822 	sec = firstsect(dataSeg);
6823 	while (sec != NULL) {
6824 		lastSec = sec;
6825 		sec = nextsect(dataSeg, sec);
6826 	}
6827 
6828 	if (lastSec == NULL) {
6829 		return;
6830 	}
6831 
6832 	if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
6833 	    (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
6834 		return;
6835 	}
6836 
6837 	dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
6838 	lastSecEnd = round_page(lastSec->addr + lastSec->size);
6839 
6840 	if (dataSegEnd <= lastSecEnd) {
6841 		return;
6842 	}
6843 
6844 	padSize = dataSegEnd - lastSecEnd;
6845 
6846 	if (padSize >= PAGE_SIZE) {
6847 #if VM_MAPPED_KEXTS
6848 		kext_free(lastSecEnd, padSize);
6849 #else
6850 		ml_static_mfree(lastSecEnd, padSize);
6851 #endif
6852 	}
6853 }
6854 
6855 /*********************************************************************
6856 *********************************************************************/
6857 void
6858 OSKext::setLinkedExecutable(OSData * anExecutable)
6859 {
6860 	if (linkedExecutable) {
6861 		panic("Attempt to set linked executable on kext "
6862 		    "that already has one (%s).\n",
6863 		    getIdentifierCString());
6864 	}
6865 	linkedExecutable.reset(anExecutable, OSRetain);
6866 	return;
6867 }
6868 
6869 #if CONFIG_DTRACE
6870 /*********************************************************************
6871 * Go through all loaded kexts and tell them to register with dtrace.
6872 * The instance method only registers if necessary.
6873 *********************************************************************/
6874 /* static */
6875 void
6876 OSKext::registerKextsWithDTrace(void)
6877 {
6878 	uint32_t count = sLoadedKexts->getCount();
6879 	uint32_t i;
6880 
6881 	IORecursiveLockLock(sKextLock);
6882 
6883 	for (i = 0; i < count; i++) {
6884 		OSKext   * thisKext     = NULL;        // do not release
6885 
6886 		thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
6887 		if (!thisKext || !thisKext->isExecutable()) {
6888 			continue;
6889 		}
6890 
6891 		thisKext->registerWithDTrace();
6892 	}
6893 
6894 	IORecursiveLockUnlock(sKextLock);
6895 
6896 	return;
6897 }
6898 
6899 extern "C" {
6900 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
6901 extern int (*dtrace_modunload)(struct kmod_info *);
6902 };
6903 
6904 /*********************************************************************
6905 *********************************************************************/
6906 void
6907 OSKext::registerWithDTrace(void)
6908 {
6909 	/* Register kext with dtrace. A dtrace_modload failure should not
6910 	 * prevent a kext from loading, so we ignore the return code.
6911 	 */
6912 	if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
6913 		uint32_t modflag = 0;
6914 		OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
6915 
6916 #if XNU_TARGET_OS_OSX
6917 		if (!sKeepSymbols && kc_type == KCKindPrimary) {
6918 			if (forceInit == kOSBooleanTrue) {
6919 				OSKextLog(this,
6920 				    kOSKextLogBasicLevel |
6921 				    kOSKextLogGeneralFlag,
6922 				    "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s",
6923 				    getIdentifierCString());
6924 				forceInit = kOSBooleanFalse;
6925 			}
6926 			/* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */
6927 			modflag |= KMOD_DTRACE_NO_KERNEL_SYMS;
6928 		}
6929 #endif /* XNU_TARGET_OS_OSX */
6930 		if (forceInit == kOSBooleanTrue) {
6931 			modflag |= KMOD_DTRACE_FORCE_INIT;
6932 		}
6933 		if (flags.builtin) {
6934 			modflag |= KMOD_DTRACE_STATIC_KEXT;
6935 		}
6936 
6937 		(void)(*dtrace_modload)(kmod_info, modflag);
6938 		flags.dtraceInitialized = true;
6939 		jettisonLinkeditSegment();
6940 	}
6941 	return;
6942 }
6943 /*********************************************************************
6944 *********************************************************************/
6945 void
6946 OSKext::unregisterWithDTrace(void)
6947 {
6948 	/* Unregister kext with dtrace. A dtrace_modunload failure should not
6949 	 * prevent a kext from loading, so we ignore the return code.
6950 	 */
6951 	if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
6952 		(void)(*dtrace_modunload)(kmod_info);
6953 		flags.dtraceInitialized = false;
6954 	}
6955 	return;
6956 }
6957 #endif /* CONFIG_DTRACE */
6958 
6959 
6960 /*********************************************************************
6961 * called only by loadExecutable()
6962 *********************************************************************/
6963 #if !VM_MAPPED_KEXTS
6964 #if defined(__arm__) || defined(__arm64__)
6965 static inline kern_return_t
6966 OSKext_protect(
6967 	kernel_mach_header_t *kext_mh,
6968 	vm_map_t   map,
6969 	vm_map_offset_t    start,
6970 	vm_map_offset_t    end,
6971 	vm_prot_t  new_prot,
6972 	boolean_t  set_max,
6973 	kc_kind_t  kc_type)
6974 {
6975 #pragma unused(kext_mh,map,kc_type)
6976 	assert(map == kernel_map);         // we can handle KEXTs arising from the PRELINK segment and no others
6977 	assert(start <= end);
6978 	if (start >= end) {
6979 		return KERN_SUCCESS;         // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
6980 	} else if (set_max) {
6981 		return KERN_SUCCESS;         // Punt set_max, as there's no mechanism to record that state
6982 	} else {
6983 		return ml_static_protect(start, end - start, new_prot);
6984 	}
6985 }
6986 
6987 static inline kern_return_t
6988 OSKext_wire(
6989 	kernel_mach_header_t *kext_mh,
6990 	vm_map_t   map,
6991 	vm_map_offset_t    start,
6992 	vm_map_offset_t    end,
6993 	vm_prot_t  access_type,
6994 	boolean_t       user_wire,
6995 	kc_kind_t       kc_type)
6996 {
6997 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type)
6998 	return KERN_SUCCESS;         // No-op as PRELINK kexts are cemented into physical memory at boot
6999 }
7000 #else
7001 #error Unrecognized architecture
7002 #endif
7003 #else
7004 static inline kern_return_t
7005 OSKext_protect(
7006 	kernel_mach_header_t *kext_mh,
7007 	vm_map_t   map,
7008 	vm_map_offset_t    start,
7009 	vm_map_offset_t    end,
7010 	vm_prot_t  new_prot,
7011 	boolean_t  set_max,
7012 	kc_kind_t  kc_type)
7013 {
7014 	if (start == end) {         // 10538581
7015 		return KERN_SUCCESS;
7016 	}
7017 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7018 		/*
7019 		 * XXX: This will probably need to be different for AuxKC and
7020 		 * pageableKC!
7021 		 */
7022 		return ml_static_protect(start, end - start, new_prot);
7023 	}
7024 	return vm_map_protect(map, start, end, new_prot, set_max);
7025 }
7026 
7027 static inline kern_return_t
7028 OSKext_wire(
7029 	kernel_mach_header_t *kext_mh,
7030 	vm_map_t   map,
7031 	vm_map_offset_t    start,
7032 	vm_map_offset_t    end,
7033 	vm_prot_t  access_type,
7034 	boolean_t       user_wire,
7035 	kc_kind_t       kc_type)
7036 {
7037 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7038 		/* TODO: we may need to hook this for the pageableKC */
7039 		return KERN_SUCCESS;
7040 	}
7041 	return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
7042 }
7043 #endif
7044 
7045 OSReturn
7046 OSKext::setVMAttributes(bool protect, bool wire)
7047 {
7048 	vm_map_t                    kext_map        = NULL;
7049 	kernel_segment_command_t  * seg             = NULL;
7050 	vm_map_offset_t             start_protect   = 0;
7051 	vm_map_offset_t             start_wire      = 0;
7052 	vm_map_offset_t             end_protect     = 0;
7053 	vm_map_offset_t             end_wire        = 0;
7054 	OSReturn                    result          = kOSReturnError;
7055 
7056 	if (isInterface() || !declaresExecutable() || flags.builtin) {
7057 		result = kOSReturnSuccess;
7058 		goto finish;
7059 	}
7060 
7061 	/* Get the kext's vm map */
7062 	kext_map = kext_get_vm_map(kmod_info);
7063 	if (!kext_map) {
7064 		result = KERN_MEMORY_ERROR;
7065 		goto finish;
7066 	}
7067 
7068 #if !VM_MAPPED_KEXTS
7069 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
7070 		/* This is a split kext in a prelinked kernelcache; we'll let the
7071 		 * platform code take care of protecting it.  It is already wired.
7072 		 */
7073 		/* TODO: Should this still allow protections for the first segment
7074 		 * to go through, in the event that we have a mix of split and
7075 		 * unsplit kexts?
7076 		 */
7077 		result = KERN_SUCCESS;
7078 		goto finish;
7079 	}
7080 
7081 	if (isInFileset() && kc_type != KCKindPageable) {
7082 		// kexts in filesets have protections setup as part of collection loading
7083 		result = KERN_SUCCESS;
7084 		goto finish;
7085 	}
7086 #endif
7087 
7088 	/* Protect the headers as read-only; they do not need to be wired */
7089 	result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7090 	    kext_map, kmod_info->address,
7091 	    kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type)
7092 	    : KERN_SUCCESS;
7093 	if (result != KERN_SUCCESS) {
7094 		goto finish;
7095 	}
7096 
7097 	/* Set the VM protections and wire down each of the segments */
7098 	seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7099 	while (seg) {
7100 #if __arm__
7101 		/* We build all ARM kexts, so we can ensure they are aligned */
7102 		assert((seg->vmaddr & PAGE_MASK) == 0);
7103 		assert((seg->vmsize & PAGE_MASK) == 0);
7104 #endif
7105 
7106 		/*
7107 		 * For the non page aligned segments, the range calculation for protection
7108 		 * and wiring differ as follows:
7109 		 *
7110 		 * Protection: The non page aligned data at the start or at the end of the
7111 		 * segment is excluded from the protection. This exclusion is needed to make
7112 		 * sure OSKext_protect is not called twice on same page, if the page is shared
7113 		 * between two segments.
7114 		 *
7115 		 * Wiring: The non page aligned data at the start or at the end of the
7116 		 * segment is included in the wiring range, this inclusion is needed to make sure
7117 		 * all the data of the segment is wired.
7118 		 */
7119 		start_protect = round_page(seg->vmaddr);
7120 		end_protect = trunc_page(seg->vmaddr + seg->vmsize);
7121 
7122 		start_wire = trunc_page(seg->vmaddr);
7123 		end_wire = round_page(seg->vmaddr + seg->vmsize);
7124 
7125 		/*
7126 		 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared
7127 		 * across kexts and data from kexts is not page aligned
7128 		 */
7129 		if (protect && (end_protect > start_protect) &&
7130 		    ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 &&
7131 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) ||
7132 		    (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) {
7133 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7134 			    kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type);
7135 			if (result != KERN_SUCCESS) {
7136 				OSKextLog(this,
7137 				    kOSKextLogErrorLevel |
7138 				    kOSKextLogLoadFlag,
7139 				    "Kext %s failed to set maximum VM protections "
7140 				    "for segment %s - 0x%x.",
7141 				    getIdentifierCString(), seg->segname, (int)result);
7142 				goto finish;
7143 			}
7144 
7145 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7146 			    kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type);
7147 			if (result != KERN_SUCCESS) {
7148 				OSKextLog(this,
7149 				    kOSKextLogErrorLevel |
7150 				    kOSKextLogLoadFlag,
7151 				    "Kext %s failed to set initial VM protections "
7152 				    "for segment %s - 0x%x.",
7153 				    getIdentifierCString(), seg->segname, (int)result);
7154 				goto finish;
7155 			}
7156 		}
7157 
7158 		if (segmentShouldBeWired(seg) && wire) {
7159 			result = OSKext_wire((kernel_mach_header_t *)kmod_info->address,
7160 			    kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type);
7161 			if (result != KERN_SUCCESS) {
7162 				goto finish;
7163 			}
7164 		}
7165 
7166 		seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7167 	}
7168 
7169 finish:
7170 	return result;
7171 }
7172 
7173 /*********************************************************************
7174 *********************************************************************/
7175 boolean_t
7176 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
7177 {
7178 	return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) &&
7179 	       strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)));
7180 }
7181 
7182 /*********************************************************************
7183 *********************************************************************/
7184 OSReturn
7185 OSKext::validateKextMapping(bool startFlag)
7186 {
7187 	OSReturn                              result      = kOSReturnError;
7188 	const char                          * whichOp = startFlag ? "start" : "stop";
7189 	kern_return_t                         kern_result = 0;
7190 	vm_map_t                              kext_map    = NULL;
7191 	kernel_segment_command_t            * seg         = NULL;
7192 	mach_vm_address_t                     address     = 0;
7193 	mach_vm_size_t                        size        = 0;
7194 	uint32_t                              depth       = 0;
7195 	uint64_t                              kext_segbase = 0;
7196 	uint64_t                              kext_segsize = 0;
7197 	mach_msg_type_number_t                count;
7198 	vm_region_submap_short_info_data_64_t info;
7199 	uintptr_t                             kext_slide = PE_get_kc_slide(kc_type);
7200 
7201 	if (flags.builtin) {
7202 		return kOSReturnSuccess;
7203 	}
7204 
7205 	count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
7206 	bzero(&info, sizeof(info));
7207 
7208 	// xxx - do we need a distinct OSReturn value for these or is "bad data"
7209 	// xxx - sufficient?
7210 
7211 	/* Verify that the kmod_info and start/stop pointers are non-NULL.
7212 	 */
7213 	if (!kmod_info) {
7214 		OSKextLog(this,
7215 		    kOSKextLogErrorLevel |
7216 		    kOSKextLogLoadFlag,
7217 		    "Kext %s - NULL kmod_info pointer.",
7218 		    getIdentifierCString());
7219 		result = kOSKextReturnBadData;
7220 		goto finish;
7221 	}
7222 
7223 	if (startFlag) {
7224 		address = (mach_vm_address_t)kmod_info->start;
7225 	} else {
7226 		address = (mach_vm_address_t)kmod_info->stop;
7227 	}
7228 
7229 	if (!address) {
7230 		OSKextLog(this,
7231 		    kOSKextLogErrorLevel |
7232 		    kOSKextLogLoadFlag,
7233 		    "Kext %s - NULL module %s pointer.",
7234 		    getIdentifierCString(), whichOp);
7235 		result = kOSKextReturnBadData;
7236 		goto finish;
7237 	}
7238 
7239 	kext_map = kext_get_vm_map(kmod_info);
7240 	depth = (kernel_map == kext_map) ? 1 : 2;
7241 	if (isInFileset()) {
7242 #if defined(HAS_APPLE_PAC)
7243 		address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0);
7244 #endif /* defined(HAS_APPLE_PAC) */
7245 	}
7246 
7247 	/* Verify that the start/stop function lies within the kext's address range.
7248 	 */
7249 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) ||
7250 	    isInFileset()) {
7251 		/* This will likely be how we deal with split kexts; walk the segments to
7252 		 * check that the function lies inside one of the segments of this kext.
7253 		 */
7254 		for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7255 		    seg != NULL;
7256 		    seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
7257 			if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
7258 				kext_segbase = seg->vmaddr;
7259 				kext_segsize = seg->vmsize;
7260 				break;
7261 			}
7262 		}
7263 
7264 		if (!seg) {
7265 			OSKextLog(this,
7266 			    kOSKextLogErrorLevel |
7267 			    kOSKextLogLoadFlag,
7268 			    "Kext %s module %s pointer is outside of kext range "
7269 			    "(%s %p - kext starts at %p).",
7270 			    getIdentifierCString(),
7271 			    whichOp,
7272 			    whichOp,
7273 			    (void *)(((uintptr_t)address) - kext_slide),
7274 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide));
7275 			result = kOSKextReturnBadData;
7276 			goto finish;
7277 		}
7278 
7279 		seg = NULL;
7280 	} else {
7281 		if (address < kmod_info->address + kmod_info->hdr_size ||
7282 		    kmod_info->address + kmod_info->size <= address) {
7283 			OSKextLog(this,
7284 			    kOSKextLogErrorLevel |
7285 			    kOSKextLogLoadFlag,
7286 			    "Kext %s module %s pointer is outside of kext range "
7287 			    "(%s %p - kext at %p-%p).",
7288 			    getIdentifierCString(),
7289 			    whichOp,
7290 			    whichOp,
7291 			    (void *)(((uintptr_t)address) - kext_slide),
7292 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide),
7293 			    (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size));
7294 			result = kOSKextReturnBadData;
7295 			goto finish;
7296 		}
7297 	}
7298 
7299 	/* Only do these checks before calling the start function;
7300 	 * If anything goes wrong with the mapping while the kext is running,
7301 	 * we'll likely have panicked well before any attempt to stop the kext.
7302 	 */
7303 	if (startFlag) {
7304 		if (!isInFileset() || kc_type != KCKindPrimary) {
7305 			/*
7306 			 * Verify that the start/stop function is executable.
7307 			 */
7308 			kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
7309 			    (vm_region_recurse_info_t)&info, &count);
7310 			if (kern_result != KERN_SUCCESS) {
7311 				OSKextLog(this,
7312 				    kOSKextLogErrorLevel |
7313 				    kOSKextLogLoadFlag,
7314 				    "Kext %s - bad %s pointer %p.",
7315 				    getIdentifierCString(),
7316 				    whichOp, (void *)ml_static_unslide(address));
7317 				result = kOSKextReturnBadData;
7318 				goto finish;
7319 			}
7320 		} else {
7321 			/*
7322 			 * Since kexts loaded from the primary KC are held in memory
7323 			 * allocated by efiboot, we cannot use mach_vm_region_recurse() to
7324 			 * discover that memory's protection flags.  Instead, we need to
7325 			 * get that information from the kernel pmap itself.  Above, we
7326 			 * (potentially) saved the size of the segment in which the address
7327 			 * in question was located.  If we have a non-zero size, verify
7328 			 * that all pages in the (address, address + kext_segsize) range
7329 			 * are marked executable.  If we somehow did not record the size
7330 			 * (or the base) just verify the single page that includes the address.
7331 			 */
7332 			if (kext_segbase == 0 || kext_segsize == 0) {
7333 				kext_segbase = address & ~(uint64_t)PAGE_MASK;
7334 				kext_segsize = PAGE_SIZE;
7335 			}
7336 		}
7337 
7338 #if VM_MAPPED_KEXTS
7339 		if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) ||
7340 		    ((isInFileset() && kc_type == KCKindPrimary) &&
7341 		    ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) {
7342 			OSKextLog(this,
7343 			    kOSKextLogErrorLevel |
7344 			    kOSKextLogLoadFlag,
7345 			    "Kext %s - memory region containing module %s function "
7346 			    "is not executable.",
7347 			    getIdentifierCString(), whichOp);
7348 			result = kOSKextReturnBadData;
7349 			goto finish;
7350 		}
7351 #endif
7352 
7353 		/* Verify that the kext's segments are backed by physical memory.
7354 		 */
7355 		seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7356 		while (seg) {
7357 			if (!verifySegmentMapping(seg)) {
7358 				result = kOSKextReturnBadData;
7359 				goto finish;
7360 			}
7361 
7362 			seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7363 		}
7364 	}
7365 
7366 	result = kOSReturnSuccess;
7367 finish:
7368 	return result;
7369 }
7370 
7371 /*********************************************************************
7372 *********************************************************************/
7373 boolean_t
7374 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
7375 {
7376 	mach_vm_address_t address = 0;
7377 
7378 	if (seg->vmsize > UINT32_MAX) {
7379 		return false;
7380 	}
7381 
7382 	if (!segmentShouldBeWired(seg)) {
7383 		return true;
7384 	}
7385 
7386 	for (address = seg->vmaddr;
7387 	    address < round_page(seg->vmaddr + seg->vmsize);
7388 	    address += PAGE_SIZE) {
7389 		if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
7390 			OSKextLog(this,
7391 			    kOSKextLogErrorLevel |
7392 			    kOSKextLogLoadFlag,
7393 			    "Kext %s - page %p is not backed by physical memory.",
7394 			    getIdentifierCString(),
7395 			    (void *)address);
7396 			return false;
7397 		}
7398 	}
7399 
7400 	return true;
7401 }
7402 
7403 /*********************************************************************
7404 *********************************************************************/
7405 static void
7406 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
7407 {
7408 	uint64_t                            stamp = 0;
7409 	firehose_tracepoint_id_u            trace_id;
7410 	struct firehose_trace_uuid_info_s   uuid_info_s;
7411 	firehose_trace_uuid_info_t          uuid_info = &uuid_info_s;
7412 	size_t                              uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
7413 	OSSharedPtr<OSData>                 uuid_data;
7414 
7415 	stamp = firehose_tracepoint_time(firehose_activity_flags_default);
7416 	trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
7417 
7418 	uuid_data = aKext->copyTextUUID();
7419 	if (uuid_data) {
7420 		memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
7421 	}
7422 
7423 	uuid_info->ftui_size    = size;
7424 	if (aKext->isDriverKit()) {
7425 		uuid_info->ftui_address = address;
7426 	} else {
7427 		uuid_info->ftui_address = ml_static_unslide(address);
7428 	}
7429 	firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
7430 	return;
7431 }
7432 
7433 void
7434 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
7435 {
7436 	OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
7437 }
7438 
7439 /*********************************************************************
7440 *********************************************************************/
7441 OSReturn
7442 OSKext::start(bool startDependenciesFlag)
7443 {
7444 	OSReturn                            result = kOSReturnError;
7445 	kern_return_t                       (* startfunc)(kmod_info_t *, void *);
7446 	unsigned int                        i, count;
7447 	void                              * kmodStartData = NULL;
7448 
7449 	if (isStarted() || isInterface() || isKernelComponent()) {
7450 		result = kOSReturnSuccess;
7451 		goto finish;
7452 	}
7453 
7454 	if (!isLoaded()) {
7455 		OSKextLog(this,
7456 		    kOSKextLogErrorLevel |
7457 		    kOSKextLogLoadFlag,
7458 		    "Attempt to start nonloaded kext %s.",
7459 		    getIdentifierCString());
7460 		result = kOSKextReturnInvalidArgument;
7461 		goto finish;
7462 	}
7463 
7464 	if (!sLoadEnabled) {
7465 		OSKextLog(this,
7466 		    kOSKextLogErrorLevel |
7467 		    kOSKextLogLoadFlag,
7468 		    "Kext loading is disabled (attempt to start kext %s).",
7469 		    getIdentifierCString());
7470 		result = kOSKextReturnDisabled;
7471 		goto finish;
7472 	}
7473 
7474 	result = validateKextMapping(/* start? */ true);
7475 	if (result != kOSReturnSuccess) {
7476 		goto finish;
7477 	}
7478 
7479 	startfunc = kmod_info->start;
7480 
7481 	count = getNumDependencies();
7482 	for (i = 0; i < count; i++) {
7483 		OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
7484 		if (dependency == NULL) {
7485 			OSKextLog(this,
7486 			    kOSKextLogErrorLevel |
7487 			    kOSKextLogLoadFlag,
7488 			    "Kext %s start - internal error, dependency disappeared.",
7489 			    getIdentifierCString());
7490 			goto finish;
7491 		}
7492 		if (!dependency->isStarted()) {
7493 			if (startDependenciesFlag) {
7494 				OSReturn dependencyResult =
7495 				    dependency->start(startDependenciesFlag);
7496 				if (dependencyResult != KERN_SUCCESS) {
7497 					OSKextLog(this,
7498 					    kOSKextLogErrorLevel |
7499 					    kOSKextLogLoadFlag,
7500 					    "Kext %s start - dependency %s failed to start (error 0x%x).",
7501 					    getIdentifierCString(),
7502 					    dependency->getIdentifierCString(),
7503 					    dependencyResult);
7504 					goto finish;
7505 				}
7506 			} else {
7507 				OSKextLog(this,
7508 				    kOSKextLogErrorLevel |
7509 				    kOSKextLogLoadFlag,
7510 				    "Not starting %s - dependency %s not started yet.",
7511 				    getIdentifierCString(),
7512 				    dependency->getIdentifierCString());
7513 				result = kOSKextReturnStartStopError;         // xxx - make new return?
7514 				goto finish;
7515 			}
7516 		}
7517 	}
7518 
7519 	OSKextLog(this,
7520 	    kOSKextLogDetailLevel |
7521 	    kOSKextLogLoadFlag,
7522 	    "Kext %s calling module start function.",
7523 	    getIdentifierCString());
7524 
7525 	flags.starting = 1;
7526 
7527 	// Drop a log message so logd can grab the needed information to decode this kext
7528 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
7529 	result = OSRuntimeInitializeCPP(this);
7530 	if (result == KERN_SUCCESS) {
7531 		result = startfunc(kmod_info, kmodStartData);
7532 	}
7533 
7534 	flags.starting = 0;
7535 
7536 	/* On success overlap the setting of started/starting. On failure just
7537 	 * clear starting.
7538 	 */
7539 	if (result == KERN_SUCCESS) {
7540 		flags.started = 1;
7541 
7542 		// xxx - log start error from kernel?
7543 		OSKextLog(this,
7544 		    kOSKextLogProgressLevel |
7545 		    kOSKextLogLoadFlag,
7546 		    "Kext %s is now started.",
7547 		    getIdentifierCString());
7548 	} else {
7549 		invokeOrCancelRequestCallbacks(
7550 			/* result not actually used */ kOSKextReturnStartStopError,
7551 			/* invokeFlag */ false);
7552 		OSKextLog(this,
7553 		    kOSKextLogWarningLevel |
7554 		    kOSKextLogLoadFlag,
7555 		    "Kext %s did not start (return code 0x%x).",
7556 		    getIdentifierCString(), result);
7557 	}
7558 
7559 finish:
7560 	return result;
7561 }
7562 
7563 /*********************************************************************
7564 *********************************************************************/
7565 /* static */
7566 bool
7567 OSKext::canUnloadKextWithIdentifier(
7568 	OSString * kextIdentifier,
7569 	bool       checkClassesFlag)
7570 {
7571 	bool     result = false;
7572 	OSKext * aKext  = NULL;        // do not release
7573 
7574 	IORecursiveLockLock(sKextLock);
7575 
7576 	aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
7577 
7578 	if (!aKext) {
7579 		goto finish;         // can't unload what's not loaded
7580 	}
7581 
7582 	if (aKext->isLoaded()) {
7583 		if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
7584 			goto finish;
7585 		}
7586 		if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
7587 			goto finish;
7588 		}
7589 	}
7590 
7591 	result = true;
7592 
7593 finish:
7594 	IORecursiveLockUnlock(sKextLock);
7595 	return result;
7596 }
7597 
7598 /*********************************************************************
7599 *********************************************************************/
7600 OSReturn
7601 OSKext::stop(void)
7602 {
7603 	OSReturn result = kOSReturnError;
7604 	kern_return_t (*stopfunc)(kmod_info_t *, void *);
7605 
7606 	if (!isStarted() || isInterface()) {
7607 		result = kOSReturnSuccess;
7608 		goto finish;
7609 	}
7610 
7611 	if (!isLoaded()) {
7612 		OSKextLog(this,
7613 		    kOSKextLogErrorLevel |
7614 		    kOSKextLogLoadFlag,
7615 		    "Attempt to stop nonloaded kext %s.",
7616 		    getIdentifierCString());
7617 		result = kOSKextReturnInvalidArgument;
7618 		goto finish;
7619 	}
7620 
7621 	/* Refuse to stop if we have clients or instances. It is up to
7622 	 * the caller to make sure those aren't true.
7623 	 */
7624 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7625 		OSKextLog(this,
7626 		    kOSKextLogErrorLevel |
7627 		    kOSKextLogLoadFlag,
7628 		    "Kext %s - C++ instances; can't stop.",
7629 		    getIdentifierCString());
7630 		result = kOSKextReturnInUse;
7631 		goto finish;
7632 	}
7633 
7634 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7635 		OSKextLog(this,
7636 		    kOSKextLogErrorLevel |
7637 		    kOSKextLogLoadFlag,
7638 		    "Kext %s - has references (linkage or tracking object); "
7639 		    "can't stop.",
7640 		    getIdentifierCString());
7641 		result = kOSKextReturnInUse;
7642 		goto finish;
7643 	}
7644 
7645 	/* Note: If validateKextMapping fails on the stop & unload path,
7646 	 * we are in serious trouble and a kernel panic is likely whether
7647 	 * we stop & unload the kext or not.
7648 	 */
7649 	result = validateKextMapping(/* start? */ false);
7650 	if (result != kOSReturnSuccess) {
7651 		goto finish;
7652 	}
7653 
7654 	stopfunc = kmod_info->stop;
7655 	if (stopfunc) {
7656 		OSKextLog(this,
7657 		    kOSKextLogDetailLevel |
7658 		    kOSKextLogLoadFlag,
7659 		    "Kext %s calling module stop function.",
7660 		    getIdentifierCString());
7661 
7662 		flags.stopping = 1;
7663 
7664 		result = stopfunc(kmod_info, /* userData */ NULL);
7665 		if (result == KERN_SUCCESS) {
7666 			result = OSRuntimeFinalizeCPP(this);
7667 		}
7668 
7669 		flags.stopping = 0;
7670 
7671 		if (result == KERN_SUCCESS) {
7672 			flags.started = 0;
7673 
7674 			OSKextLog(this,
7675 			    kOSKextLogDetailLevel |
7676 			    kOSKextLogLoadFlag,
7677 			    "Kext %s is now stopped and ready to unload.",
7678 			    getIdentifierCString());
7679 		} else {
7680 			OSKextLog(this,
7681 			    kOSKextLogErrorLevel |
7682 			    kOSKextLogLoadFlag,
7683 			    "Kext %s did not stop (return code 0x%x).",
7684 			    getIdentifierCString(), result);
7685 			result = kOSKextReturnStartStopError;
7686 		}
7687 	}
7688 
7689 finish:
7690 	// Drop a log message so logd can update this kext's metadata
7691 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
7692 	return result;
7693 }
7694 
7695 /*********************************************************************
7696 *********************************************************************/
7697 OSReturn
7698 OSKext::unload(void)
7699 {
7700 	OSReturn        result = kOSReturnError;
7701 	unsigned int    index;
7702 	uint32_t        num_kmod_refs = 0;
7703 	OSKextAccount * freeAccount;
7704 	bool            in_fileset = false;
7705 
7706 	if (!sUnloadEnabled) {
7707 		OSKextLog(this,
7708 		    kOSKextLogErrorLevel |
7709 		    kOSKextLogLoadFlag,
7710 		    "Kext unloading is disabled (%s).",
7711 		    this->getIdentifierCString());
7712 
7713 		result = kOSKextReturnDisabled;
7714 		goto finish;
7715 	}
7716 
7717 	// cache this result so we don't need to access the kmod_info after
7718 	// it's been potentially free'd
7719 	in_fileset = isInFileset();
7720 
7721 	/* Refuse to unload if we have clients or instances. It is up to
7722 	 * the caller to make sure those aren't true.
7723 	 */
7724 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
7725 		// xxx - Don't log under errors? this is more of an info thing
7726 		OSKextLog(this,
7727 		    kOSKextLogErrorLevel |
7728 		    kOSKextLogKextBookkeepingFlag,
7729 		    "Can't unload kext %s; outstanding references (linkage or tracking object).",
7730 		    getIdentifierCString());
7731 		result = kOSKextReturnInUse;
7732 		goto finish;
7733 	}
7734 
7735 	if (isDriverKit()) {
7736 		index = sLoadedKexts->getNextIndexOfObject(this, 0);
7737 		if (index != (unsigned int)-1) {
7738 			sLoadedDriverKitKexts->removeObject(index);
7739 			OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
7740 			loadTag = 0;
7741 		}
7742 	}
7743 
7744 	if (!isLoaded()) {
7745 		result = kOSReturnSuccess;
7746 		goto finish;
7747 	}
7748 
7749 	if (isKernelComponent()) {
7750 		result = kOSKextReturnInvalidArgument;
7751 		goto finish;
7752 	}
7753 
7754 	if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) {
7755 		OSKextLog(this,
7756 		    kOSKextLogErrorLevel |
7757 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
7758 		    "Can't unload kext %s; classes have instances:",
7759 		    getIdentifierCString());
7760 		reportOSMetaClassInstances(kOSKextLogErrorLevel |
7761 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
7762 		result = kOSKextReturnInUse;
7763 		goto finish;
7764 	}
7765 
7766 	/* Note that the kext is unloading before running any code that
7767 	 * might be in the kext (request callbacks, module stop function).
7768 	 * We will deny certain requests made against a kext in the process
7769 	 * of unloading.
7770 	 */
7771 	flags.unloading = 1;
7772 
7773 	/* Update the string describing the last kext to unload in case we panic.
7774 	 */
7775 	savePanicString(/* isLoading */ false);
7776 
7777 	if (isStarted()) {
7778 		result = stop();
7779 		if (result != KERN_SUCCESS) {
7780 			OSKextLog(this,
7781 			    kOSKextLogErrorLevel |
7782 			    kOSKextLogLoadFlag,
7783 			    "Kext %s can't unload - module stop returned 0x%x.",
7784 			    getIdentifierCString(), (unsigned)result);
7785 			result = kOSKextReturnStartStopError;
7786 			goto finish;
7787 		}
7788 	}
7789 
7790 	OSKextLog(this,
7791 	    kOSKextLogProgressLevel |
7792 	    kOSKextLogLoadFlag,
7793 	    "Kext %s unloading.",
7794 	    getIdentifierCString());
7795 
7796 	{
7797 		struct list_head *p;
7798 		struct list_head *prev;
7799 		struct list_head *next;
7800 		for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
7801 			OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
7802 			s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
7803 			prev = p->prev;
7804 			next = p->next;
7805 			prev->next = next;
7806 			next->prev = prev;
7807 			p->prev = p;
7808 			p->next = p;
7809 			IORecursiveLockWakeup(sKextLock, s, false);
7810 		}
7811 	}
7812 
7813 
7814 	/* Even if we don't call the stop function, we want to be sure we
7815 	 * have no OSMetaClass references before unloading the kext executable
7816 	 * from memory. OSMetaClasses may have pointers into the kext executable
7817 	 * and that would cause a panic on OSKext::free() when metaClasses is freed.
7818 	 */
7819 	if (metaClasses) {
7820 		metaClasses->flushCollection();
7821 	}
7822 	(void) OSRuntimeFinalizeCPP(this);
7823 
7824 	/* Remove the kext from the list of loaded kexts, patch the gap
7825 	 * in the kmod_info_t linked list, and reset "kmod" to point to the
7826 	 * last loaded kext that isn't the fake kernel kext (sKernelKext).
7827 	 */
7828 	index = sLoadedKexts->getNextIndexOfObject(this, 0);
7829 	if (index != (unsigned int)-1) {
7830 		sLoadedKexts->removeObject(index);
7831 
7832 		OSKext * nextKext = OSDynamicCast(OSKext,
7833 		    sLoadedKexts->getObject(index));
7834 
7835 		if (nextKext) {
7836 			if (index > 0) {
7837 				OSKext * gapKext = OSDynamicCast(OSKext,
7838 				    sLoadedKexts->getObject(index - 1));
7839 
7840 				nextKext->kmod_info->next = gapKext->kmod_info;
7841 			} else {         /* index == 0 */
7842 				nextKext->kmod_info->next = NULL;
7843 			}
7844 		}
7845 
7846 		OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
7847 		if (lastKext && !lastKext->isKernel()) {
7848 			kmod = lastKext->kmod_info;
7849 		} else {
7850 			kmod = NULL;         // clear the global kmod variable
7851 		}
7852 	}
7853 
7854 	/* Clear out the kmod references that we're keeping for compatibility
7855 	 * with current panic backtrace code & kgmacros.
7856 	 * xxx - will want to update those bits sometime and remove this.
7857 	 */
7858 	num_kmod_refs = getNumDependencies();
7859 	if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
7860 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
7861 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
7862 			ref->info->reference_count--;
7863 		}
7864 		kfree_type(kmod_reference_t, num_kmod_refs,
7865 		    kmod_info->reference_list);
7866 	}
7867 
7868 #if CONFIG_DTRACE
7869 	unregisterWithDTrace();
7870 #endif /* CONFIG_DTRACE */
7871 
7872 	notifyKextUnloadObservers(this);
7873 
7874 	freeAccount = NULL;
7875 	IOSimpleLockLock(sKextAccountsLock);
7876 	account->kext = NULL;
7877 	if (account->site.tag) {
7878 		account->site.flags |= VM_TAG_UNLOAD;
7879 	} else {
7880 		freeAccount = account;
7881 	}
7882 
7883 #if DEVELOPMENT || DEBUG
7884 	assertf(account->task_refgrp.grp_count == 0,
7885 	    "unloading a kext with active task references");
7886 #endif /* DEVELOPMENT || DEBUG */
7887 
7888 	IOSimpleLockUnlock(sKextAccountsLock);
7889 	if (freeAccount) {
7890 		IOFreeType(freeAccount, OSKextAccount);
7891 	}
7892 
7893 	/* Unwire and free the linked executable.
7894 	 */
7895 	if (linkedExecutable) {
7896 #if KASAN
7897 		kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
7898 #endif
7899 
7900 #if VM_MAPPED_KEXTS
7901 		if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) {
7902 			kernel_segment_command_t *seg = NULL;
7903 			vm_map_t kext_map = kext_get_vm_map(kmod_info);
7904 
7905 			if (!kext_map) {
7906 				OSKextLog(this,
7907 				    kOSKextLogErrorLevel |
7908 				    kOSKextLogLoadFlag,
7909 				    "Failed to free kext %s; couldn't find the kext map.",
7910 				    getIdentifierCString());
7911 				result = kOSKextReturnInternalError;
7912 				goto finish;
7913 			}
7914 
7915 			OSKextLog(this,
7916 			    kOSKextLogProgressLevel |
7917 			    kOSKextLogLoadFlag,
7918 			    "Kext %s unwiring and unmapping linked executable.",
7919 			    getIdentifierCString());
7920 
7921 			seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7922 			while (seg) {
7923 				if (segmentShouldBeWired(seg)) {
7924 					vm_map_offset_t start_wire = trunc_page(seg->vmaddr);
7925 					vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize);
7926 
7927 					result = vm_map_unwire(kext_map, start_wire,
7928 					    end_wire, FALSE);
7929 					if (result != KERN_SUCCESS) {
7930 						OSKextLog(this,
7931 						    kOSKextLogErrorLevel |
7932 						    kOSKextLogLoadFlag,
7933 						    "Failed to unwire kext %s.",
7934 						    getIdentifierCString());
7935 						result = kOSKextReturnInternalError;
7936 						goto finish;
7937 					}
7938 				}
7939 
7940 				seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7941 			}
7942 #if defined(__x86_64__) || defined(__i386__)
7943 			if (in_fileset && flags.resetSegmentsFromVnode) {
7944 				IORecursiveLockLock(sKextLock);
7945 				resetKCFileSetSegments();
7946 				IORecursiveLockUnlock(sKextLock);
7947 			}
7948 #endif // (__x86_64__) || defined(__i386__)
7949 		}
7950 #endif /* VM_MAPPED_KEXTS */
7951 		if (flags.resetSegmentsFromImmutableCopy) {
7952 			result = resetMutableSegments();
7953 			if (result != kOSReturnSuccess) {
7954 				OSKextLog(this,
7955 				    kOSKextLogErrorLevel |
7956 				    kOSKextLogLoadFlag,
7957 				    "Failed to reset kext %s.",
7958 				    getIdentifierCString());
7959 				result = kOSKextReturnInternalError;
7960 				goto finish;
7961 			}
7962 		}
7963 		if (kc_type == KCKindUnknown) {
7964 			linkedExecutable.reset();
7965 		}
7966 	}
7967 
7968 	/* An interface kext has a fake kmod_info that was allocated,
7969 	 * so we have to free it.
7970 	 */
7971 	if (isInterface()) {
7972 		kfree_type(kmod_info_t, kmod_info);
7973 		kmod_info = NULL;
7974 	}
7975 
7976 	if (!in_fileset) {
7977 		kmod_info = NULL;
7978 	}
7979 
7980 	flags.loaded = false;
7981 	flushDependencies();
7982 
7983 	/* save a copy of the bundle ID for us to check when deciding to
7984 	 * rebuild the kernel cache file.  If a kext was already in the kernel
7985 	 * cache and unloaded then later loaded we do not need to rebuild the
7986 	 * kernel cache.  9055303
7987 	 */
7988 	if (isPrelinked()) {
7989 		if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) {
7990 			IORecursiveLockLock(sKextLock);
7991 			if (sUnloadedPrelinkedKexts) {
7992 				sUnloadedPrelinkedKexts->setObject(bundleID.get());
7993 			}
7994 			IORecursiveLockUnlock(sKextLock);
7995 		}
7996 	}
7997 
7998 	OSKextLog(this,
7999 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8000 	    "Kext %s unloaded.", getIdentifierCString());
8001 
8002 	queueKextNotification(kKextRequestPredicateUnloadNotification,
8003 	    OSDynamicCast(OSString, bundleID.get()));
8004 
8005 finish:
8006 	OSKext::saveLoadedKextPanicList();
8007 	OSKext::updateLoadedKextSummaries();
8008 
8009 	flags.unloading = 0;
8010 	return result;
8011 }
8012 
8013 /*********************************************************************
8014 * Assumes sKextLock is held.
8015 *********************************************************************/
8016 /* static */
8017 OSReturn
8018 OSKext::queueKextNotification(
8019 	const char * notificationName,
8020 	OSString   * kextIdentifier)
8021 {
8022 	OSReturn          result               = kOSReturnError;
8023 	OSSharedPtr<OSDictionary>    loadRequest;
8024 
8025 	if (!kextIdentifier) {
8026 		result = kOSKextReturnInvalidArgument;
8027 		goto finish;
8028 	}
8029 
8030 	/* Create a new request unless one is already sitting
8031 	 * in sKernelRequests for this bundle identifier
8032 	 */
8033 	result = _OSKextCreateRequest(notificationName, loadRequest);
8034 	if (result != kOSReturnSuccess) {
8035 		goto finish;
8036 	}
8037 	if (!_OSKextSetRequestArgument(loadRequest.get(),
8038 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
8039 		result = kOSKextReturnNoMemory;
8040 		goto finish;
8041 	}
8042 	if (!sKernelRequests->setObject(loadRequest.get())) {
8043 		result = kOSKextReturnNoMemory;
8044 		goto finish;
8045 	}
8046 
8047 	/* We might want to only queue the notification if the IOKit daemon is active,
8048 	 * but that wouldn't work for embedded. Note that we don't care if
8049 	 * the ping immediately succeeds here so don't do anything with the
8050 	 * result of this call.
8051 	 */
8052 	OSKext::pingIOKitDaemon();
8053 
8054 	result = kOSReturnSuccess;
8055 
8056 finish:
8057 	return result;
8058 }
8059 
8060 
8061 #if CONFIG_KXLD
8062 /*********************************************************************
8063 *********************************************************************/
8064 static void
8065 _OSKextConsiderDestroyingLinkContext(
8066 	__unused thread_call_param_t p0,
8067 	__unused thread_call_param_t p1)
8068 {
8069 	/* Take multiple locks in the correct order.
8070 	 */
8071 	IORecursiveLockLock(sKextLock);
8072 	IORecursiveLockLock(sKextInnerLock);
8073 
8074 	/* The first time we destroy the kxldContext is in the first
8075 	 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
8076 	 * before calling this function. Thereafter any call to this function
8077 	 * will actually destroy the context.
8078 	 */
8079 	if (sConsiderUnloadsCalled && sKxldContext) {
8080 		kxld_destroy_context(sKxldContext);
8081 		sKxldContext = NULL;
8082 	}
8083 
8084 	/* Free the thread_call that was allocated to execute this function.
8085 	 */
8086 	if (sDestroyLinkContextThread) {
8087 		if (!thread_call_free(sDestroyLinkContextThread)) {
8088 			OSKextLog(/* kext */ NULL,
8089 			    kOSKextLogErrorLevel |
8090 			    kOSKextLogGeneralFlag,
8091 			    "thread_call_free() failed for kext link context.");
8092 		}
8093 		sDestroyLinkContextThread = NULL;
8094 	}
8095 
8096 	IORecursiveLockUnlock(sKextInnerLock);
8097 	IORecursiveLockUnlock(sKextLock);
8098 
8099 	return;
8100 }
8101 
8102 /*********************************************************************
8103 * Destroying the kxldContext requires checking variables under both
8104 * sKextInnerLock and sKextLock, so we do it on a separate thread
8105 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
8106 * call relationship.
8107 *
8108 * This function must be invoked with sKextInnerLock held.
8109 * Do not call any function that takes sKextLock here!
8110 *********************************************************************/
8111 /* static */
8112 void
8113 OSKext::considerDestroyingLinkContext(void)
8114 {
8115 	IORecursiveLockLock(sKextInnerLock);
8116 
8117 	/* If we have already queued a thread to destroy the link context,
8118 	 * don't bother resetting; that thread will take care of it.
8119 	 */
8120 	if (sDestroyLinkContextThread) {
8121 		goto finish;
8122 	}
8123 
8124 	/* The function to be invoked in the thread will deallocate
8125 	 * this thread_call, so don't share it around.
8126 	 */
8127 	sDestroyLinkContextThread = thread_call_allocate(
8128 		&_OSKextConsiderDestroyingLinkContext, NULL);
8129 	if (!sDestroyLinkContextThread) {
8130 		OSKextLog(/* kext */ NULL,
8131 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
8132 		    "Can't create thread to destroy kext link context.");
8133 		goto finish;
8134 	}
8135 
8136 	thread_call_enter(sDestroyLinkContextThread);
8137 
8138 finish:
8139 	IORecursiveLockUnlock(sKextInnerLock);
8140 	return;
8141 }
8142 
8143 #else // !CONFIG_KXLD
8144 
8145 /* static */
8146 void
8147 OSKext::considerDestroyingLinkContext(void)
8148 {
8149 	return;
8150 }
8151 
8152 #endif // CONFIG_KXLD
8153 
8154 #if PRAGMA_MARK
8155 #pragma mark Autounload
8156 #endif
8157 /*********************************************************************
8158 * This is a static method because the kext will be deallocated if it
8159 * does unload!
8160 *********************************************************************/
8161 /* static */
8162 OSReturn
8163 OSKext::autounloadKext(OSKext * aKext)
8164 {
8165 	OSReturn result = kOSKextReturnInUse;
8166 
8167 #if NO_KEXTD
8168 	/*
8169 	 * Do not unload prelinked kexts on platforms that do not have an
8170 	 * IOKit daemon as there is no way to reload the kext or restart
8171 	 * matching.
8172 	 */
8173 	if (aKext->isPrelinked()) {
8174 		goto finish;
8175 	}
8176 #endif /* defined(__x86_64__) */
8177 
8178 	/* Check for external references to this kext (usu. dependents),
8179 	 * instances of defined classes (or classes derived from them),
8180 	 * outstanding requests.
8181 	 */
8182 	if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
8183 	    !aKext->flags.autounloadEnabled ||
8184 	    aKext->isKernelComponent()) {
8185 		goto finish;
8186 	}
8187 
8188 	/* Skip a delay-autounload kext, once.
8189 	 */
8190 	if (aKext->flags.delayAutounload) {
8191 		OSKextLog(aKext,
8192 		    kOSKextLogProgressLevel |
8193 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8194 		    "Kext %s has delayed autounload set; skipping and clearing flag.",
8195 		    aKext->getIdentifierCString());
8196 		aKext->flags.delayAutounload = 0;
8197 		goto finish;
8198 	}
8199 
8200 	if (aKext->hasOSMetaClassInstances() ||
8201 	    aKext->countRequestCallbacks()) {
8202 		goto finish;
8203 	}
8204 
8205 	result = OSKext::removeKext(aKext);
8206 
8207 finish:
8208 	return result;
8209 }
8210 
8211 /*********************************************************************
8212 *********************************************************************/
8213 void
8214 _OSKextConsiderUnloads(
8215 	__unused thread_call_param_t p0,
8216 	__unused thread_call_param_t p1)
8217 {
8218 	bool         didUnload = false;
8219 	unsigned int count, i;
8220 
8221 	/* Take multiple locks in the correct order
8222 	 * (note also sKextSummaries lock further down).
8223 	 */
8224 	IORecursiveLockLock(sKextLock);
8225 	IORecursiveLockLock(sKextInnerLock);
8226 
8227 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
8228 
8229 	/* If the system is powering down, don't try to unload anything.
8230 	 */
8231 	if (sSystemSleep) {
8232 		goto finish;
8233 	}
8234 
8235 	OSKextLog(/* kext */ NULL,
8236 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8237 	    "Checking for unused kexts to autounload.");
8238 
8239 	/*****
8240 	 * Remove any request callbacks marked as stale,
8241 	 * and mark as stale any currently in flight.
8242 	 */
8243 	count = sRequestCallbackRecords->getCount();
8244 	if (count) {
8245 		i = count - 1;
8246 		do {
8247 			OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
8248 			    sRequestCallbackRecords->getObject(i));
8249 			if (callbackRecord) {
8250 				OSBoolean * stale = OSDynamicCast(OSBoolean,
8251 				    callbackRecord->getObject(kKextRequestStaleKey));
8252 
8253 				if (stale == kOSBooleanTrue) {
8254 					OSKext::invokeRequestCallback(callbackRecord,
8255 					    kOSKextReturnTimeout);
8256 				} else {
8257 					callbackRecord->setObject(kKextRequestStaleKey,
8258 					    kOSBooleanTrue);
8259 				}
8260 			}
8261 		} while (i--);
8262 	}
8263 
8264 	/*****
8265 	 * Make multiple passes through the array of loaded kexts until
8266 	 * we don't unload any. This handles unwinding of dependency
8267 	 * chains. We have to go *backwards* through the array because
8268 	 * kexts are removed from it when unloaded, and we cannot make
8269 	 * a copy or we'll mess up the retain counts we rely on to
8270 	 * check whether a kext will unload. If only we could have
8271 	 * nonretaining collections like CF has....
8272 	 */
8273 	do {
8274 		didUnload = false;
8275 
8276 		count = sLoadedKexts->getCount();
8277 		if (count) {
8278 			i = count - 1;
8279 			do {
8280 				OSKext * thisKext = OSDynamicCast(OSKext,
8281 				    sLoadedKexts->getObject(i));
8282 				didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
8283 			} while (i--);
8284 		}
8285 	} while (didUnload);
8286 
8287 finish:
8288 	sConsiderUnloadsPending = false;
8289 	sConsiderUnloadsExecuted = true;
8290 
8291 	(void) OSKext::considerRebuildOfPrelinkedKernel();
8292 
8293 	IORecursiveLockUnlock(sKextInnerLock);
8294 	IORecursiveLockUnlock(sKextLock);
8295 
8296 	return;
8297 }
8298 
8299 /*********************************************************************
8300 * Do not call any function that takes sKextLock here!
8301 *********************************************************************/
8302 void
8303 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
8304 {
8305 	AbsoluteTime when;
8306 
8307 	IORecursiveLockLock(sKextInnerLock);
8308 
8309 	if (!sUnloadCallout) {
8310 		sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
8311 	}
8312 
8313 	/* we only reset delay value for unloading if we already have something
8314 	 * pending.  rescheduleOnlyFlag should not start the count down.
8315 	 */
8316 	if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
8317 		goto finish;
8318 	}
8319 
8320 	thread_call_cancel(sUnloadCallout);
8321 	if (OSKext::getAutounloadEnabled() && !sSystemSleep
8322 #if !NO_KEXTD
8323 	    && sIOKitDaemonActive
8324 #endif
8325 	    ) {
8326 		clock_interval_to_deadline(sConsiderUnloadDelay,
8327 		    1000 * 1000 * 1000, &when);
8328 
8329 		OSKextLog(/* kext */ NULL,
8330 		    kOSKextLogProgressLevel |
8331 		    kOSKextLogLoadFlag,
8332 		    "%scheduling %sscan for unused kexts in %lu seconds.",
8333 		    sConsiderUnloadsPending ? "Res" : "S",
8334 		    sConsiderUnloadsCalled ? "" : "initial ",
8335 		    (unsigned long)sConsiderUnloadDelay);
8336 
8337 		sConsiderUnloadsPending = true;
8338 		thread_call_enter_delayed(sUnloadCallout, when);
8339 	}
8340 
8341 finish:
8342 	/* The kxld context should be reused throughout boot.  We mark the end of
8343 	 * period as the first time considerUnloads() is called, and we destroy
8344 	 * the first kxld context in that function.  Afterwards, it will be
8345 	 * destroyed in flushNonloadedKexts.
8346 	 */
8347 	if (!sConsiderUnloadsCalled) {
8348 		sConsiderUnloadsCalled = true;
8349 		OSKext::considerDestroyingLinkContext();
8350 	}
8351 
8352 	IORecursiveLockUnlock(sKextInnerLock);
8353 	return;
8354 }
8355 
8356 /*********************************************************************
8357 * Do not call any function that takes sKextLock here!
8358 *********************************************************************/
8359 extern "C" {
8360 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
8361 IOReturn
8362 OSKextSystemSleepOrWake(UInt32 messageType)
8363 {
8364 	IORecursiveLockLock(sKextInnerLock);
8365 
8366 	/* If the system is going to sleep, cancel the reaper thread timer,
8367 	 * and note that we're in a sleep state in case it just fired but hasn't
8368 	 * taken the lock yet. If we are coming back from sleep, just
8369 	 * clear the sleep flag; IOService's normal operation will cause
8370 	 * unloads to be considered soon enough.
8371 	 */
8372 	if (messageType == kIOMessageSystemWillSleep) {
8373 		if (sUnloadCallout) {
8374 			thread_call_cancel(sUnloadCallout);
8375 		}
8376 		sSystemSleep = true;
8377 		AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
8378 	} else if (messageType == kIOMessageSystemHasPoweredOn) {
8379 		sSystemSleep = false;
8380 		clock_get_uptime(&sLastWakeTime);
8381 	}
8382 	IORecursiveLockUnlock(sKextInnerLock);
8383 
8384 	return kIOReturnSuccess;
8385 }
8386 };
8387 
8388 
8389 #if PRAGMA_MARK
8390 #pragma mark Prelinked Kernel
8391 #endif
8392 
8393 #ifdef CONFIG_KXLD
8394 /*********************************************************************
8395 * Do not access sConsiderUnloads... variables other than
8396 * sConsiderUnloadsExecuted in this function. They are guarded by a
8397 * different lock.
8398 *********************************************************************/
8399 /* static */
8400 void
8401 OSKext::considerRebuildOfPrelinkedKernel(void)
8402 {
8403 	static bool     requestedPrelink        = false;
8404 	OSReturn        checkResult             = kOSReturnError;
8405 	OSSharedPtr<OSDictionary>         prelinkRequest;
8406 	OSSharedPtr<OSCollectionIterator> kextIterator;
8407 	const OSSymbol * thisID                 = NULL;        // do not release
8408 	bool            doRebuild               = false;
8409 	AbsoluteTime    my_abstime;
8410 	UInt64          my_ns;
8411 	SInt32          delta_secs;
8412 
8413 	/* Only one auto rebuild per boot and only on boot from prelinked kernel */
8414 	if (requestedPrelink || !sPrelinkBoot) {
8415 		return;
8416 	}
8417 
8418 	/* no direct return from this point */
8419 	IORecursiveLockLock(sKextLock);
8420 
8421 	/* We need to wait for the IOKit daemon to get up and running with unloads already done
8422 	 * and any new startup kexts loaded.
8423 	 */
8424 	if (!sConsiderUnloadsExecuted ||
8425 	    !sDeferredLoadSucceeded) {
8426 		goto finish;
8427 	}
8428 
8429 	/* we really only care about boot / system start up related kexts so bail
8430 	 * if we're here after REBUILD_MAX_TIME.
8431 	 */
8432 	if (!_OSKextInPrelinkRebuildWindow()) {
8433 		OSKextLog(/* kext */ NULL,
8434 		    kOSKextLogArchiveFlag,
8435 		    "%s prebuild rebuild has expired",
8436 		    __FUNCTION__);
8437 		requestedPrelink = true;
8438 		goto finish;
8439 	}
8440 
8441 	/* we do not want to trigger a rebuild if we get here too close to waking
8442 	 * up.  (see radar 10233768)
8443 	 */
8444 	IORecursiveLockLock(sKextInnerLock);
8445 
8446 	clock_get_uptime(&my_abstime);
8447 	delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
8448 	if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
8449 		SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
8450 		absolutetime_to_nanoseconds(my_abstime, &my_ns);
8451 		delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
8452 	}
8453 	IORecursiveLockUnlock(sKextInnerLock);
8454 
8455 	if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
8456 		/* too close to time of last wake from sleep */
8457 		goto finish;
8458 	}
8459 	requestedPrelink = true;
8460 
8461 	/* Now it's time to see if we have a reason to rebuild.  We may have done
8462 	 * some loads and unloads but the kernel cache didn't actually change.
8463 	 * We will rebuild if any kext is not marked prelinked AND is not in our
8464 	 * list of prelinked kexts that got unloaded.  (see radar 9055303)
8465 	 */
8466 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
8467 	if (!kextIterator) {
8468 		goto finish;
8469 	}
8470 
8471 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
8472 		OSKext *    thisKext;        // do not release
8473 
8474 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
8475 		if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
8476 			continue;
8477 		}
8478 
8479 		if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) {
8480 			continue;
8481 		}
8482 		/* kext is loaded and was not in current kernel cache so let's rebuild
8483 		 */
8484 		doRebuild = true;
8485 		OSKextLog(/* kext */ NULL,
8486 		    kOSKextLogArchiveFlag,
8487 		    "considerRebuildOfPrelinkedKernel %s triggered rebuild",
8488 		    thisKext->bundleID->getCStringNoCopy());
8489 		break;
8490 	}
8491 	sUnloadedPrelinkedKexts->flushCollection();
8492 
8493 	if (!doRebuild) {
8494 		goto finish;
8495 	}
8496 
8497 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
8498 	    prelinkRequest);
8499 	if (checkResult != kOSReturnSuccess) {
8500 		goto finish;
8501 	}
8502 
8503 	if (!sKernelRequests->setObject(prelinkRequest.get())) {
8504 		goto finish;
8505 	}
8506 
8507 	OSKext::pingIOKitDaemon();
8508 
8509 finish:
8510 	IORecursiveLockUnlock(sKextLock);
8511 
8512 	return;
8513 }
8514 
8515 #else /* !CONFIG_KXLD */
8516 
8517 void
8518 OSKext::considerRebuildOfPrelinkedKernel(void)
8519 {
8520 	/* in a non-dynamic kext loading world, there is never a reason to rebuild */
8521 	return;
8522 }
8523 
8524 #endif /* CONFIG_KXLD */
8525 
8526 #if PRAGMA_MARK
8527 #pragma mark Dependencies
8528 #endif
8529 /*********************************************************************
8530 *********************************************************************/
8531 bool
8532 OSKext::resolveDependencies(
8533 	OSArray * loopStack)
8534 {
8535 	bool                   result                   = false;
8536 	OSSharedPtr<OSArray>   localLoopStack;
8537 	bool                   addedToLoopStack         = false;
8538 	OSDictionary         * libraries                = NULL;        // do not release
8539 	OSSharedPtr<OSCollectionIterator> libraryIterator;
8540 	OSString             * libraryID                = NULL;        // do not release
8541 	OSKext               * libraryKext              = NULL;        // do not release
8542 	bool                   hasRawKernelDependency   = false;
8543 	bool                   hasKernelDependency      = false;
8544 	bool                   hasKPIDependency         = false;
8545 	bool                   hasPrivateKPIDependency  = false;
8546 	unsigned int           count;
8547 
8548 #if CONFIG_KXLD
8549 	OSString             * infoString               = NULL;        // do not release
8550 	OSString             * readableString           = NULL;        // do not release
8551 #endif // CONFIG_KXLD
8552 
8553 	/* A kernel component will automatically have this flag set,
8554 	 * and a loaded kext should also have it set (as should all its
8555 	 * loaded dependencies).
8556 	 */
8557 	if (flags.hasAllDependencies) {
8558 		result = true;
8559 		goto finish;
8560 	}
8561 
8562 	/* Check for loops in the dependency graph.
8563 	 */
8564 	if (loopStack) {
8565 		if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
8566 			OSKextLog(this,
8567 			    kOSKextLogErrorLevel |
8568 			    kOSKextLogDependenciesFlag,
8569 			    "Kext %s has a dependency loop; can't resolve dependencies.",
8570 			    getIdentifierCString());
8571 			goto finish;
8572 		}
8573 	} else {
8574 		OSKextLog(this,
8575 		    kOSKextLogStepLevel |
8576 		    kOSKextLogDependenciesFlag,
8577 		    "Kext %s resolving dependencies.",
8578 		    getIdentifierCString());
8579 
8580 		localLoopStack = OSArray::withCapacity(6);         // any small capacity will do
8581 		if (!localLoopStack) {
8582 			OSKextLog(this,
8583 			    kOSKextLogErrorLevel |
8584 			    kOSKextLogDependenciesFlag,
8585 			    "Kext %s can't create bookkeeping stack to resolve dependencies.",
8586 			    getIdentifierCString());
8587 			goto finish;
8588 		}
8589 		loopStack = localLoopStack.get();
8590 	}
8591 	if (!loopStack->setObject(this)) {
8592 		OSKextLog(this,
8593 		    kOSKextLogErrorLevel |
8594 		    kOSKextLogDependenciesFlag,
8595 		    "Kext %s - internal error resolving dependencies.",
8596 		    getIdentifierCString());
8597 		goto finish;
8598 	}
8599 	addedToLoopStack = true;
8600 
8601 	/* Purge any existing kexts in the dependency list and start over.
8602 	 */
8603 	flushDependencies();
8604 	if (dependencies) {
8605 		OSKextLog(this,
8606 		    kOSKextLogErrorLevel |
8607 		    kOSKextLogDependenciesFlag,
8608 		    "Kext %s - internal error resolving dependencies.",
8609 		    getIdentifierCString());
8610 	}
8611 
8612 	libraries = OSDynamicCast(OSDictionary,
8613 	    getPropertyForHostArch(kOSBundleLibrariesKey));
8614 	if (libraries == NULL || libraries->getCount() == 0) {
8615 		OSKextLog(this,
8616 		    kOSKextLogErrorLevel |
8617 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8618 		    "Kext %s - can't resolve dependencies; %s missing/invalid type.",
8619 		    getIdentifierCString(), kOSBundleLibrariesKey);
8620 		goto finish;
8621 	}
8622 
8623 	/* Make a new array to hold the dependencies (flush freed the old one).
8624 	 */
8625 	dependencies = OSArray::withCapacity(libraries->getCount());
8626 	if (!dependencies) {
8627 		OSKextLog(this,
8628 		    kOSKextLogErrorLevel |
8629 		    kOSKextLogDependenciesFlag,
8630 		    "Kext %s - can't allocate dependencies array.",
8631 		    getIdentifierCString());
8632 		goto finish;
8633 	}
8634 
8635 	// xxx - compat: We used to add an implicit dependency on kernel 6.0
8636 	// xxx - compat: if none were declared.
8637 
8638 	libraryIterator = OSCollectionIterator::withCollection(libraries);
8639 	if (!libraryIterator) {
8640 		OSKextLog(this,
8641 		    kOSKextLogErrorLevel |
8642 		    kOSKextLogDependenciesFlag,
8643 		    "Kext %s - can't allocate dependencies iterator.",
8644 		    getIdentifierCString());
8645 		goto finish;
8646 	}
8647 
8648 	while ((libraryID = OSDynamicCast(OSString,
8649 	    libraryIterator->getNextObject()))) {
8650 		const char * library_id = libraryID->getCStringNoCopy();
8651 
8652 		OSString * libraryVersion = OSDynamicCast(OSString,
8653 		    libraries->getObject(libraryID));
8654 		if (libraryVersion == NULL) {
8655 			OSKextLog(this,
8656 			    kOSKextLogErrorLevel |
8657 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8658 			    "Kext %s - illegal type in OSBundleLibraries.",
8659 			    getIdentifierCString());
8660 			goto finish;
8661 		}
8662 
8663 		OSKextVersion libraryVers =
8664 		    OSKextParseVersionString(libraryVersion->getCStringNoCopy());
8665 		if (libraryVers == -1) {
8666 			OSKextLog(this,
8667 			    kOSKextLogErrorLevel |
8668 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8669 			    "Kext %s - invalid library version %s.",
8670 			    getIdentifierCString(),
8671 			    libraryVersion->getCStringNoCopy());
8672 			goto finish;
8673 		}
8674 
8675 		libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
8676 		if (libraryKext == NULL) {
8677 			OSKextLog(this,
8678 			    kOSKextLogErrorLevel |
8679 			    kOSKextLogDependenciesFlag,
8680 			    "Kext %s - library kext %s not found.",
8681 			    getIdentifierCString(), library_id);
8682 			goto finish;
8683 		}
8684 
8685 		if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
8686 			OSKextLog(this,
8687 			    kOSKextLogErrorLevel |
8688 			    kOSKextLogDependenciesFlag,
8689 			    "Kext %s - library kext %s not compatible "
8690 			    "with requested version %s.",
8691 			    getIdentifierCString(), library_id,
8692 			    libraryVersion->getCStringNoCopy());
8693 			goto finish;
8694 		}
8695 
8696 		/* If a nonprelinked library somehow got into the mix for a
8697 		 * prelinked kext, at any point in the chain, we must fail
8698 		 * because the prelinked relocs for the library will be all wrong.
8699 		 */
8700 		if (this->isPrelinked() &&
8701 		    libraryKext->declaresExecutable() &&
8702 		    !libraryKext->isPrelinked()) {
8703 			OSKextLog(this,
8704 			    kOSKextLogErrorLevel |
8705 			    kOSKextLogDependenciesFlag,
8706 			    "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
8707 			    getIdentifierCString(), library_id,
8708 			    libraryVersion->getCStringNoCopy());
8709 			goto finish;
8710 		}
8711 
8712 		if (!libraryKext->resolveDependencies(loopStack)) {
8713 			goto finish;
8714 		}
8715 
8716 		/* Add the library directly only if it has an executable to link.
8717 		 * Otherwise it's just used to collect other dependencies, so put
8718 		 * *its* dependencies on the list for this kext.
8719 		 */
8720 		// xxx - We are losing info here; would like to make fake entries or
8721 		// xxx - keep these in the dependency graph for loaded kexts.
8722 		// xxx - I really want to make kernel components not a special case!
8723 		if (libraryKext->declaresExecutable() ||
8724 		    libraryKext->isInterface()) {
8725 			if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
8726 				dependencies->setObject(libraryKext);
8727 
8728 				OSKextLog(this,
8729 				    kOSKextLogDetailLevel |
8730 				    kOSKextLogDependenciesFlag,
8731 				    "Kext %s added dependency %s.",
8732 				    getIdentifierCString(),
8733 				    libraryKext->getIdentifierCString());
8734 			}
8735 		} else {
8736 			int       numLibDependencies  = libraryKext->getNumDependencies();
8737 			OSArray * libraryDependencies = libraryKext->getDependencies();
8738 			int       index;
8739 
8740 			if (numLibDependencies) {
8741 				// xxx - this msg level should be 1 lower than the per-kext one
8742 				OSKextLog(this,
8743 				    kOSKextLogDetailLevel |
8744 				    kOSKextLogDependenciesFlag,
8745 				    "Kext %s pulling %d dependencies from codeless library %s.",
8746 				    getIdentifierCString(),
8747 				    numLibDependencies,
8748 				    libraryKext->getIdentifierCString());
8749 			}
8750 			for (index = 0; index < numLibDependencies; index++) {
8751 				OSKext * thisLibDependency = OSDynamicCast(OSKext,
8752 				    libraryDependencies->getObject(index));
8753 				if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
8754 					dependencies->setObject(thisLibDependency);
8755 					OSKextLog(this,
8756 					    kOSKextLogDetailLevel |
8757 					    kOSKextLogDependenciesFlag,
8758 					    "Kext %s added dependency %s from codeless library %s.",
8759 					    getIdentifierCString(),
8760 					    thisLibDependency->getIdentifierCString(),
8761 					    libraryKext->getIdentifierCString());
8762 				}
8763 			}
8764 		}
8765 
8766 		if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
8767 		    0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
8768 			hasRawKernelDependency = true;
8769 		} else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
8770 			hasKernelDependency = true;
8771 		} else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
8772 			hasKPIDependency = true;
8773 			if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
8774 				hasPrivateKPIDependency = true;
8775 			}
8776 		}
8777 	}
8778 
8779 	if (hasRawKernelDependency) {
8780 		OSKextLog(this,
8781 		    kOSKextLogErrorLevel |
8782 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8783 		    "Error - kext %s declares a dependency on %s, which is not permitted.",
8784 		    getIdentifierCString(), KERNEL_LIB);
8785 		goto finish;
8786 	}
8787 #if __LP64__
8788 	if (hasKernelDependency) {
8789 		OSKextLog(this,
8790 		    kOSKextLogErrorLevel |
8791 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
8792 		    "Error - kext %s declares %s dependencies. "
8793 		    "Only %s* dependencies are supported for 64-bit kexts.",
8794 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
8795 		goto finish;
8796 	}
8797 	if (!hasKPIDependency) {
8798 		OSKextLog(this,
8799 		    kOSKextLogWarningLevel |
8800 		    kOSKextLogDependenciesFlag,
8801 		    "Warning - kext %s declares no %s* dependencies. "
8802 		    "If it uses any KPIs, the link may fail with undefined symbols.",
8803 		    getIdentifierCString(), KPI_LIB_PREFIX);
8804 	}
8805 #else /* __LP64__ */
8806 	// xxx - will change to flatly disallow "kernel" dependencies at some point
8807 	// xxx - is it invalid to do both "com.apple.kernel" and any
8808 	// xxx - "com.apple.kernel.*"?
8809 
8810 	if (hasKernelDependency && hasKPIDependency) {
8811 		OSKextLog(this,
8812 		    kOSKextLogWarningLevel |
8813 		    kOSKextLogDependenciesFlag,
8814 		    "Warning - kext %s has immediate dependencies on both "
8815 		    "%s* and %s* components; use only one style.",
8816 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
8817 	}
8818 
8819 	if (!hasKernelDependency && !hasKPIDependency) {
8820 		// xxx - do we want to use validation flag for these too?
8821 		OSKextLog(this,
8822 		    kOSKextLogWarningLevel |
8823 		    kOSKextLogDependenciesFlag,
8824 		    "Warning - %s declares no kernel dependencies; using %s.",
8825 		    getIdentifierCString(), KERNEL6_LIB);
8826 		OSKext * kernelKext = OSDynamicCast(OSKext,
8827 		    sKextsByID->getObject(KERNEL6_LIB));
8828 		if (kernelKext) {
8829 			dependencies->setObject(kernelKext);
8830 		} else {
8831 			OSKextLog(this,
8832 			    kOSKextLogErrorLevel |
8833 			    kOSKextLogDependenciesFlag,
8834 			    "Error - Library %s not found for %s.",
8835 			    KERNEL6_LIB, getIdentifierCString());
8836 		}
8837 	}
8838 
8839 	/* If the kext doesn't have a raw kernel or KPI dependency, then add all of
8840 	 * its indirect dependencies to simulate old-style linking.  XXX - Should
8841 	 * check for duplicates.
8842 	 */
8843 	if (!hasKPIDependency) {
8844 		unsigned int i;
8845 
8846 		flags.hasBleedthrough = true;
8847 
8848 		count = getNumDependencies();
8849 
8850 		/* We add to the dependencies array in this loop, but do not iterate
8851 		 * past its original count.
8852 		 */
8853 		for (i = 0; i < count; i++) {
8854 			OSKext * dependencyKext = OSDynamicCast(OSKext,
8855 			    dependencies->getObject(i));
8856 			dependencyKext->addBleedthroughDependencies(dependencies.get());
8857 		}
8858 	}
8859 #endif /* __LP64__ */
8860 
8861 #if CONFIG_KXLD
8862 	/*
8863 	 * If we're not dynamically linking kexts, then we don't need to check
8864 	 * copyright strings. The linker in user space has already done this.
8865 	 */
8866 	if (hasPrivateKPIDependency) {
8867 		bool hasApplePrefix = false;
8868 		bool infoCopyrightIsValid = false;
8869 		bool readableCopyrightIsValid = false;
8870 
8871 		hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
8872 		    APPLE_KEXT_PREFIX);
8873 
8874 		infoString = OSDynamicCast(OSString,
8875 		    getPropertyForHostArch("CFBundleGetInfoString"));
8876 		if (infoString) {
8877 			infoCopyrightIsValid =
8878 			    kxld_validate_copyright_string(infoString->getCStringNoCopy());
8879 		}
8880 
8881 		readableString = OSDynamicCast(OSString,
8882 		    getPropertyForHostArch("NSHumanReadableCopyright"));
8883 		if (readableString) {
8884 			readableCopyrightIsValid =
8885 			    kxld_validate_copyright_string(readableString->getCStringNoCopy());
8886 		}
8887 
8888 		if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
8889 			OSKextLog(this,
8890 			    kOSKextLogErrorLevel |
8891 			    kOSKextLogDependenciesFlag,
8892 			    "Error - kext %s declares a dependency on %s. "
8893 			    "Only Apple kexts may declare a dependency on %s.",
8894 			    getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
8895 			goto finish;
8896 		}
8897 	}
8898 #endif // CONFIG_KXLD
8899 
8900 	result = true;
8901 	flags.hasAllDependencies = 1;
8902 
8903 finish:
8904 
8905 	if (addedToLoopStack) {
8906 		count = loopStack->getCount();
8907 		if (count > 0 && (this == loopStack->getObject(count - 1))) {
8908 			loopStack->removeObject(count - 1);
8909 		} else {
8910 			OSKextLog(this,
8911 			    kOSKextLogErrorLevel |
8912 			    kOSKextLogDependenciesFlag,
8913 			    "Kext %s - internal error resolving dependencies.",
8914 			    getIdentifierCString());
8915 		}
8916 	}
8917 
8918 	if (result && localLoopStack) {
8919 		OSKextLog(this,
8920 		    kOSKextLogStepLevel |
8921 		    kOSKextLogDependenciesFlag,
8922 		    "Kext %s successfully resolved dependencies.",
8923 		    getIdentifierCString());
8924 	}
8925 
8926 	return result;
8927 }
8928 
8929 /*********************************************************************
8930 *********************************************************************/
8931 bool
8932 OSKext::addBleedthroughDependencies(OSArray * anArray)
8933 {
8934 	bool result = false;
8935 	unsigned int dependencyIndex, dependencyCount;
8936 
8937 	dependencyCount = getNumDependencies();
8938 
8939 	for (dependencyIndex = 0;
8940 	    dependencyIndex < dependencyCount;
8941 	    dependencyIndex++) {
8942 		OSKext * dependency = OSDynamicCast(OSKext,
8943 		    dependencies->getObject(dependencyIndex));
8944 		if (!dependency) {
8945 			OSKextLog(this,
8946 			    kOSKextLogErrorLevel |
8947 			    kOSKextLogDependenciesFlag,
8948 			    "Kext %s - internal error propagating compatibility dependencies.",
8949 			    getIdentifierCString());
8950 			goto finish;
8951 		}
8952 		if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
8953 			anArray->setObject(dependency);
8954 		}
8955 		dependency->addBleedthroughDependencies(anArray);
8956 	}
8957 
8958 	result = true;
8959 
8960 finish:
8961 	return result;
8962 }
8963 
8964 /*********************************************************************
8965 *********************************************************************/
8966 bool
8967 OSKext::flushDependencies(bool forceFlag)
8968 {
8969 	bool result = false;
8970 
8971 	/* Only clear the dependencies if the kext isn't loaded;
8972 	 * we need the info for loaded kexts to track references.
8973 	 */
8974 	if (!isLoaded() || forceFlag) {
8975 		if (dependencies) {
8976 			// xxx - check level
8977 			OSKextLog(this,
8978 			    kOSKextLogProgressLevel |
8979 			    kOSKextLogDependenciesFlag,
8980 			    "Kext %s flushing dependencies.",
8981 			    getIdentifierCString());
8982 			dependencies.reset();
8983 		}
8984 		if (!isKernelComponent()) {
8985 			flags.hasAllDependencies = 0;
8986 		}
8987 		result = true;
8988 	}
8989 
8990 	return result;
8991 }
8992 
8993 /*********************************************************************
8994 *********************************************************************/
8995 uint32_t
8996 OSKext::getNumDependencies(void)
8997 {
8998 	if (!dependencies) {
8999 		return 0;
9000 	}
9001 	return dependencies->getCount();
9002 }
9003 
9004 /*********************************************************************
9005 *********************************************************************/
9006 OSArray *
9007 OSKext::getDependencies(void)
9008 {
9009 	return dependencies.get();
9010 }
9011 
9012 bool
9013 OSKext::hasDependency(const OSSymbol * depID)
9014 {
9015 	bool result __block;
9016 
9017 	if (depID == getIdentifier()) {
9018 		return true;
9019 	}
9020 	if (!dependencies) {
9021 		return false;
9022 	}
9023 	result = false;
9024 	dependencies->iterateObjects(^bool (OSObject * obj) {
9025 		OSKext * kext;
9026 		kext = OSDynamicCast(OSKext, obj);
9027 		if (!kext) {
9028 		        return false;
9029 		}
9030 		result = (depID == kext->getIdentifier());
9031 		return result;
9032 	});
9033 	return result;
9034 }
9035 
9036 #if PRAGMA_MARK
9037 #pragma mark OSMetaClass Support
9038 #endif
9039 /*********************************************************************
9040 *********************************************************************/
9041 OSReturn
9042 OSKext::addClass(
9043 	OSMetaClass * aClass,
9044 	uint32_t      numClasses)
9045 {
9046 	OSReturn result = kOSMetaClassNoInsKModSet;
9047 
9048 	if (!metaClasses) {
9049 		metaClasses = OSSet::withCapacity(numClasses);
9050 		if (!metaClasses) {
9051 			goto finish;
9052 		}
9053 	}
9054 
9055 	if (metaClasses->containsObject(aClass)) {
9056 		OSKextLog(this,
9057 		    kOSKextLogWarningLevel |
9058 		    kOSKextLogLoadFlag,
9059 		    "Notice - kext %s has already registered class %s.",
9060 		    getIdentifierCString(),
9061 		    aClass->getClassName());
9062 		result = kOSReturnSuccess;
9063 		goto finish;
9064 	}
9065 
9066 	if (!metaClasses->setObject(aClass)) {
9067 		goto finish;
9068 	} else {
9069 		OSKextLog(this,
9070 		    kOSKextLogDetailLevel |
9071 		    kOSKextLogLoadFlag,
9072 		    "Kext %s registered class %s.",
9073 		    getIdentifierCString(),
9074 		    aClass->getClassName());
9075 	}
9076 
9077 	if (!flags.autounloadEnabled) {
9078 		const OSMetaClass * metaScan  = NULL;        // do not release
9079 
9080 		for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
9081 			if (metaScan == OSTypeID(IOService)) {
9082 				OSKextLog(this,
9083 				    kOSKextLogProgressLevel |
9084 				    kOSKextLogLoadFlag,
9085 				    "Kext %s has IOService subclass %s; enabling autounload.",
9086 				    getIdentifierCString(),
9087 				    aClass->getClassName());
9088 
9089 				flags.autounloadEnabled = (0 == flags.unloadUnsupported);
9090 				break;
9091 			}
9092 		}
9093 	}
9094 
9095 	notifyAddClassObservers(this, aClass, flags);
9096 
9097 	result = kOSReturnSuccess;
9098 
9099 finish:
9100 	if (result != kOSReturnSuccess) {
9101 		OSKextLog(this,
9102 		    kOSKextLogErrorLevel |
9103 		    kOSKextLogLoadFlag,
9104 		    "Kext %s failed to register class %s.",
9105 		    getIdentifierCString(),
9106 		    aClass->getClassName());
9107 	}
9108 
9109 	return result;
9110 }
9111 
9112 /*********************************************************************
9113 *********************************************************************/
9114 OSReturn
9115 OSKext::removeClass(
9116 	OSMetaClass * aClass)
9117 {
9118 	OSReturn result = kOSMetaClassNoKModSet;
9119 
9120 	if (!metaClasses) {
9121 		goto finish;
9122 	}
9123 
9124 	if (!metaClasses->containsObject(aClass)) {
9125 		OSKextLog(this,
9126 		    kOSKextLogWarningLevel |
9127 		    kOSKextLogLoadFlag,
9128 		    "Notice - kext %s asked to unregister unknown class %s.",
9129 		    getIdentifierCString(),
9130 		    aClass->getClassName());
9131 		result = kOSReturnSuccess;
9132 		goto finish;
9133 	}
9134 
9135 	OSKextLog(this,
9136 	    kOSKextLogDetailLevel |
9137 	    kOSKextLogLoadFlag,
9138 	    "Kext %s unregistering class %s.",
9139 	    getIdentifierCString(),
9140 	    aClass->getClassName());
9141 
9142 	metaClasses->removeObject(aClass);
9143 
9144 	notifyRemoveClassObservers(this, aClass, flags);
9145 
9146 	result = kOSReturnSuccess;
9147 
9148 finish:
9149 	if (result != kOSReturnSuccess) {
9150 		OSKextLog(this,
9151 		    kOSKextLogErrorLevel |
9152 		    kOSKextLogLoadFlag,
9153 		    "Failed to unregister kext %s class %s.",
9154 		    getIdentifierCString(),
9155 		    aClass->getClassName());
9156 	}
9157 	return result;
9158 }
9159 
9160 /*********************************************************************
9161 *********************************************************************/
9162 OSSet *
9163 OSKext::getMetaClasses(void)
9164 {
9165 	return metaClasses.get();
9166 }
9167 
9168 /*********************************************************************
9169 *********************************************************************/
9170 bool
9171 OSKext::hasOSMetaClassInstances(void)
9172 {
9173 	bool                   result        = false;
9174 	OSSharedPtr<OSCollectionIterator> classIterator;
9175 	OSMetaClass          * checkClass    = NULL;        // do not release
9176 
9177 	if (!metaClasses) {
9178 		goto finish;
9179 	}
9180 
9181 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9182 	if (!classIterator) {
9183 		// xxx - log alloc failure?
9184 		goto finish;
9185 	}
9186 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9187 		if (checkClass->getInstanceCount()) {
9188 			result = true;
9189 			goto finish;
9190 		}
9191 	}
9192 
9193 finish:
9194 	return result;
9195 }
9196 
9197 /*********************************************************************
9198 *********************************************************************/
9199 /* static */
9200 void
9201 OSKext::reportOSMetaClassInstances(
9202 	const char     * kextIdentifier,
9203 	OSKextLogSpec    msgLogSpec)
9204 {
9205 	OSSharedPtr<OSKext> theKext;
9206 
9207 	theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
9208 	if (!theKext) {
9209 		goto finish;
9210 	}
9211 
9212 	theKext->reportOSMetaClassInstances(msgLogSpec);
9213 finish:
9214 	return;
9215 }
9216 
9217 /*********************************************************************
9218 *********************************************************************/
9219 void
9220 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
9221 {
9222 	OSSharedPtr<OSCollectionIterator> classIterator;
9223 	OSMetaClass          * checkClass    = NULL;        // do not release
9224 
9225 	if (!metaClasses) {
9226 		goto finish;
9227 	}
9228 
9229 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9230 	if (!classIterator) {
9231 		goto finish;
9232 	}
9233 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9234 		if (checkClass->getInstanceCount()) {
9235 			OSKextLog(this,
9236 			    msgLogSpec,
9237 			    "    Kext %s class %s has %d instance%s.",
9238 			    getIdentifierCString(),
9239 			    checkClass->getClassName(),
9240 			    checkClass->getInstanceCount(),
9241 			    checkClass->getInstanceCount() == 1 ? "" : "s");
9242 		}
9243 	}
9244 
9245 finish:
9246 	return;
9247 }
9248 
9249 #if PRAGMA_MARK
9250 #pragma mark User-Space Requests
9251 #endif
9252 
9253 static kern_return_t
9254 patchDextLaunchRequests(task_t calling_task, OSArray *requests)
9255 {
9256 	OSReturn result = kOSReturnSuccess;
9257 	for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) {
9258 		OSDictionary * request = NULL;         //do not release
9259 		IOUserServerCheckInToken * token = NULL;         //do not release
9260 		OSString * requestPredicate = NULL;         //do not release
9261 		OSSharedPtr<OSNumber> portNameNumber;
9262 		mach_port_name_t portName = 0;
9263 		request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex));
9264 		if (!request) {
9265 			OSKextLog(/* kext */ NULL,
9266 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9267 			    "Elements of request should be of type OSDictionary");
9268 			result = kOSKextReturnInternalError;
9269 			goto finish;
9270 		}
9271 		requestPredicate = _OSKextGetRequestPredicate(request);
9272 		if (!requestPredicate) {
9273 			OSKextLog(/* kext */ NULL,
9274 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9275 			    "Failed to get request predicate");
9276 			result = kOSKextReturnInternalError;
9277 			goto finish;
9278 		}
9279 		// is this a dext launch?
9280 		if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) {
9281 			token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken));
9282 			if (!token) {
9283 				OSKextLog(/* kext */ NULL,
9284 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9285 				    "Could not find a IOUserServerCheckInToken in daemon launch request.");
9286 				result = kOSKextReturnInternalError;
9287 				goto finish;
9288 			}
9289 			portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT);
9290 			if (portName == 0 || portName == MACH_PORT_DEAD) {
9291 				OSKextLog(/* kext */ NULL,
9292 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9293 				    "Could not create send right for object.");
9294 				result = kOSKextReturnInternalError;
9295 				goto finish;
9296 			}
9297 			// Store the mach port name as a OSNumber
9298 			portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName));
9299 			if (!portNameNumber) {
9300 				OSKextLog(/* kext */ NULL,
9301 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9302 				    "Could not create OSNumber object.");
9303 				result = kOSKextReturnNoMemory;
9304 				goto finish;
9305 			}
9306 			if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) {
9307 				OSKextLog(/* kext */ NULL,
9308 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9309 				    "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken);
9310 				result = kOSKextReturnNoMemory;
9311 				goto finish;
9312 			}
9313 		}
9314 finish:
9315 		if (result != kOSReturnSuccess) {
9316 			break;
9317 		}
9318 	}
9319 	return result;
9320 }
9321 
9322 /*********************************************************************
9323 * XXX - this function is a big ugly mess
9324 *********************************************************************/
9325 /* static */
9326 OSReturn
9327 OSKext::handleRequest(
9328 	host_priv_t     hostPriv,
9329 	OSKextLogSpec   clientLogFilter,
9330 	char          * requestBuffer,
9331 	uint32_t        requestLength,
9332 	char         ** responseOut,
9333 	uint32_t      * responseLengthOut,
9334 	char         ** logInfoOut,
9335 	uint32_t      * logInfoLengthOut)
9336 {
9337 	OSReturn       result             = kOSReturnError;
9338 	kern_return_t  kmem_result        = KERN_FAILURE;
9339 
9340 	char         * response           = NULL;        // returned by reference
9341 	uint32_t       responseLength     = 0;
9342 
9343 	bool           taskCanManageAllKCs   = false;
9344 	bool           taskOnlyManagesBootKC = false;
9345 
9346 	OSSharedPtr<OSObject>     parsedXML;
9347 	OSDictionary            * requestDict    = NULL;        // do not release
9348 	OSSharedPtr<OSString>     errorString;
9349 
9350 	OSSharedPtr<OSObject>     responseObject;
9351 
9352 	OSSharedPtr<OSSerialize>  serializer;
9353 
9354 	OSSharedPtr<OSArray>      logInfoArray;
9355 
9356 	OSString     * predicate          = NULL;        // do not release
9357 	OSString     * kextIdentifier     = NULL;        // do not release
9358 	OSArray      * kextIdentifiers    = NULL;        // do not release
9359 	OSKext       * theKext            = NULL;        // do not release
9360 	OSBoolean    * boolArg            = NULL;        // do not release
9361 
9362 	IORecursiveLockLock(sKextLock);
9363 
9364 	if (responseOut) {
9365 		*responseOut = NULL;
9366 		*responseLengthOut = 0;
9367 	}
9368 	if (logInfoOut) {
9369 		*logInfoOut = NULL;
9370 		*logInfoLengthOut = 0;
9371 	}
9372 
9373 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
9374 
9375 	/* XML must be nul-terminated.
9376 	 */
9377 	if (requestBuffer[requestLength - 1] != '\0') {
9378 		OSKextLog(/* kext */ NULL,
9379 		    kOSKextLogErrorLevel |
9380 		    kOSKextLogIPCFlag,
9381 		    "Invalid request from user space (not nul-terminated).");
9382 		result = kOSKextReturnBadData;
9383 		goto finish;
9384 	}
9385 	parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString);
9386 	if (parsedXML) {
9387 		requestDict = OSDynamicCast(OSDictionary, parsedXML.get());
9388 	}
9389 	if (!requestDict) {
9390 		const char * errorCString = "(unknown error)";
9391 
9392 		if (errorString && errorString->getCStringNoCopy()) {
9393 			errorCString = errorString->getCStringNoCopy();
9394 		} else if (parsedXML) {
9395 			errorCString = "not a dictionary";
9396 		}
9397 		OSKextLog(/* kext */ NULL,
9398 		    kOSKextLogErrorLevel |
9399 		    kOSKextLogIPCFlag,
9400 		    "Error unserializing request from user space: %s.",
9401 		    errorCString);
9402 		result = kOSKextReturnSerialization;
9403 		goto finish;
9404 	}
9405 
9406 	predicate = _OSKextGetRequestPredicate(requestDict);
9407 	if (!predicate) {
9408 		OSKextLog(/* kext */ NULL,
9409 		    kOSKextLogErrorLevel |
9410 		    kOSKextLogIPCFlag,
9411 		    "Recieved kext request from user space with no predicate.");
9412 		result = kOSKextReturnInvalidArgument;
9413 		goto finish;
9414 	}
9415 
9416 	OSKextLog(/* kext */ NULL,
9417 	    kOSKextLogDebugLevel |
9418 	    kOSKextLogIPCFlag,
9419 	    "Received '%s' request from user space.",
9420 	    predicate->getCStringNoCopy());
9421 
9422 	/*
9423 	 * All management of file sets requires an entitlement
9424 	 */
9425 	result = kOSKextReturnNotPrivileged;
9426 	if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
9427 	    predicate->isEqualTo(kKextRequestPredicateStart) ||
9428 	    predicate->isEqualTo(kKextRequestPredicateStop) ||
9429 	    predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
9430 	    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
9431 	    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
9432 	    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
9433 	    predicate->isEqualTo(kKextRequestPredicateLoadFromKC) ||
9434 	    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
9435 	    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
9436 	    predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
9437 		if (hostPriv == HOST_PRIV_NULL) {
9438 			OSKextLog(/* kext */ NULL,
9439 			    kOSKextLogErrorLevel |
9440 			    kOSKextLogIPCFlag,
9441 			    "Access Failure - must be root user.");
9442 			goto finish;
9443 		}
9444 		taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE;
9445 		taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE;
9446 
9447 		if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) {
9448 			OSKextLog(/* kext */ NULL,
9449 			    kOSKextLogErrorLevel |
9450 			    kOSKextLogIPCFlag,
9451 			    "Access Failure - client not entitled to manage file sets.");
9452 			goto finish;
9453 		}
9454 
9455 		/*
9456 		 * The OnlyBootKC entitlement restricts the
9457 		 * collection-management entitlement to only managing kexts in
9458 		 * the BootKC. All other predicates that alter global state or
9459 		 * add new KCs are disallowed.
9460 		 */
9461 		if (taskOnlyManagesBootKC &&
9462 		    (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
9463 		    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
9464 		    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
9465 		    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
9466 		    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
9467 		    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
9468 		    predicate->isEqualTo(kKextRequestPredicateDaemonReady))) {
9469 			OSKextLog(/* kext */ NULL,
9470 			    kOSKextLogErrorLevel |
9471 			    kOSKextLogIPCFlag,
9472 			    "Access Failure - client not entitled to manage non-primary KCs");
9473 			goto finish;
9474 		}
9475 
9476 		/*
9477 		 * If we get here, then the process either has the full KC
9478 		 * management entitlement, or it has the BootKC-only
9479 		 * entitlement and the request is about the BootKC.
9480 		 */
9481 	}
9482 
9483 	/* Get common args in anticipation of use.
9484 	 */
9485 	kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
9486 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
9487 	kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
9488 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
9489 	if (kextIdentifier) {
9490 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
9491 	}
9492 	boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
9493 		    requestDict, kKextRequestArgumentValueKey));
9494 
9495 	if (taskOnlyManagesBootKC &&
9496 	    theKext &&
9497 	    theKext->isInFileset() &&
9498 	    theKext->kc_type != KCKindPrimary) {
9499 		OSKextLog(/* kext */ NULL,
9500 		    kOSKextLogErrorLevel |
9501 		    kOSKextLogIPCFlag,
9502 		    "Access Failure - client not entitled to manage kext in non-primary KC");
9503 		result = kOSKextReturnNotPrivileged;
9504 		goto finish;
9505 	}
9506 
9507 	result = kOSKextReturnInvalidArgument;
9508 
9509 	if (predicate->isEqualTo(kKextRequestPredicateStart)) {
9510 		if (!kextIdentifier) {
9511 			OSKextLog(/* kext */ NULL,
9512 			    kOSKextLogErrorLevel |
9513 			    kOSKextLogIPCFlag,
9514 			    "Invalid arguments to kext start request.");
9515 		} else if (!theKext) {
9516 			OSKextLog(/* kext */ NULL,
9517 			    kOSKextLogErrorLevel |
9518 			    kOSKextLogIPCFlag,
9519 			    "Kext %s not found for start request.",
9520 			    kextIdentifier->getCStringNoCopy());
9521 			result = kOSKextReturnNotFound;
9522 		} else {
9523 			result = theKext->start();
9524 		}
9525 	} else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
9526 		if (!kextIdentifier) {
9527 			OSKextLog(/* kext */ NULL,
9528 			    kOSKextLogErrorLevel |
9529 			    kOSKextLogIPCFlag,
9530 			    "Invalid arguments to kext stop request.");
9531 		} else if (!theKext) {
9532 			OSKextLog(/* kext */ NULL,
9533 			    kOSKextLogErrorLevel |
9534 			    kOSKextLogIPCFlag,
9535 			    "Kext %s not found for stop request.",
9536 			    kextIdentifier->getCStringNoCopy());
9537 			result = kOSKextReturnNotFound;
9538 		} else {
9539 			result = theKext->stop();
9540 		}
9541 	} else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) {
9542 		result = OSKext::setMissingAuxKCBundles(requestDict);
9543 	} else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) {
9544 		if (!kextIdentifier) {
9545 			OSKextLog(/* kext */ NULL,
9546 			    kOSKextLogErrorLevel |
9547 			    kOSKextLogIPCFlag,
9548 			    "Invalid arguments to AuxKC Bundle Available request.");
9549 		} else {
9550 			result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict);
9551 		}
9552 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) {
9553 		if (!kextIdentifier) {
9554 			OSKextLog(/* kext */ NULL,
9555 			    kOSKextLogErrorLevel |
9556 			    kOSKextLogIPCFlag,
9557 			    "Invalid arguments to kext load from KC request.");
9558 		} else if (!theKext) {
9559 			OSKextLog(/* kext */ NULL,
9560 			    kOSKextLogErrorLevel |
9561 			    kOSKextLogIPCFlag,
9562 			    "Kext %s not found for load from KC request.",
9563 			    kextIdentifier->getCStringNoCopy());
9564 			result = kOSKextReturnNotFound;
9565 		} else if (!theKext->isInFileset()) {
9566 			OSKextLog(/* kext */ NULL,
9567 			    kOSKextLogErrorLevel |
9568 			    kOSKextLogIPCFlag,
9569 			    "Kext %s does not exist in a KC: refusing to load.",
9570 			    kextIdentifier->getCStringNoCopy());
9571 			result = kOSKextReturnNotLoadable;
9572 		} else {
9573 			result = OSKext::loadKextFromKC(theKext, requestDict);
9574 		}
9575 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) {
9576 		if (!kextIdentifier) {
9577 			OSKextLog(/* kext */ NULL,
9578 			    kOSKextLogErrorLevel |
9579 			    kOSKextLogIPCFlag,
9580 			    "Invalid arguments to codeless kext load interface (missing identifier).");
9581 		} else {
9582 			result = OSKext::loadCodelessKext(kextIdentifier, requestDict);
9583 		}
9584 	} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
9585 		if (!kextIdentifier) {
9586 			OSKextLog(/* kext */ NULL,
9587 			    kOSKextLogErrorLevel |
9588 			    kOSKextLogIPCFlag,
9589 			    "Invalid arguments to kext unload request.");
9590 		} else if (!theKext) {
9591 			OSKextLog(/* kext */ NULL,
9592 			    kOSKextLogErrorLevel |
9593 			    kOSKextLogIPCFlag,
9594 			    "Kext %s not found for unload request.",
9595 			    kextIdentifier->getCStringNoCopy());
9596 			result = kOSKextReturnNotFound;
9597 		} else {
9598 			OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
9599 			    _OSKextGetRequestArgument(requestDict,
9600 			    kKextRequestArgumentTerminateIOServicesKey));
9601 			result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
9602 		}
9603 	} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
9604 		result = OSKext::dispatchResource(requestDict);
9605 	} else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
9606 		OSNumber     *lookupNum   = NULL;
9607 		lookupNum = OSDynamicCast(OSNumber,
9608 		    _OSKextGetRequestArgument(requestDict,
9609 		    kKextRequestArgumentLookupAddressKey));
9610 
9611 		responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
9612 		if (responseObject) {
9613 			result = kOSReturnSuccess;
9614 		} else {
9615 			goto finish;
9616 		}
9617 	} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
9618 	    predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) ||
9619 	    predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
9620 		OSBoolean    * delayAutounloadBool = NULL;
9621 		OSObject     * infoKeysRaw         = NULL;
9622 		OSArray      * infoKeys            = NULL;
9623 		uint32_t       infoKeysCount       = 0;
9624 
9625 		delayAutounloadBool = OSDynamicCast(OSBoolean,
9626 		    _OSKextGetRequestArgument(requestDict,
9627 		    kKextRequestArgumentDelayAutounloadKey));
9628 
9629 		/* If asked to delay autounload, reset the timer if it's currently set.
9630 		 * (That is, don't schedule an unload if one isn't already pending.
9631 		 */
9632 		if (delayAutounloadBool == kOSBooleanTrue) {
9633 			OSKext::considerUnloads(/* rescheduleOnly? */ true);
9634 		}
9635 
9636 		infoKeysRaw = _OSKextGetRequestArgument(requestDict,
9637 		    kKextRequestArgumentInfoKeysKey);
9638 		infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
9639 		if (infoKeysRaw && !infoKeys) {
9640 			OSKextLog(/* kext */ NULL,
9641 			    kOSKextLogErrorLevel |
9642 			    kOSKextLogIPCFlag,
9643 			    "Invalid arguments to kext info request.");
9644 			goto finish;
9645 		}
9646 
9647 		if (infoKeys) {
9648 			infoKeysCount = infoKeys->getCount();
9649 			for (uint32_t i = 0; i < infoKeysCount; i++) {
9650 				if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
9651 					OSKextLog(/* kext */ NULL,
9652 					    kOSKextLogErrorLevel |
9653 					    kOSKextLogIPCFlag,
9654 					    "Invalid arguments to kext info request.");
9655 					goto finish;
9656 				}
9657 			}
9658 		}
9659 
9660 		if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
9661 			responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
9662 		} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
9663 			responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
9664 		} else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
9665 			responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys);
9666 		}
9667 
9668 		if (!responseObject) {
9669 			result = kOSKextReturnInternalError;
9670 		} else {
9671 			OSKextLog(/* kext */ NULL,
9672 			    kOSKextLogDebugLevel |
9673 			    kOSKextLogIPCFlag,
9674 			    "Returning loaded kext info.");
9675 			result = kOSReturnSuccess;
9676 		}
9677 	} else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
9678 		/* Hand the current sKernelRequests array to the caller
9679 		 * (who must release it), and make a new one.
9680 		 */
9681 		responseObject = os::move(sKernelRequests);
9682 		sKernelRequests = OSArray::withCapacity(0);
9683 		sPostedKextLoadIdentifiers->flushCollection();
9684 		OSKextLog(/* kext */ NULL,
9685 		    kOSKextLogDebugLevel |
9686 		    kOSKextLogIPCFlag,
9687 		    "Returning kernel requests.");
9688 		result = kOSReturnSuccess;
9689 	} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
9690 		/* Return the set of all requested bundle identifiers */
9691 		responseObject = sAllKextLoadIdentifiers;
9692 		OSKextLog(/* kext */ NULL,
9693 		    kOSKextLogDebugLevel |
9694 		    kOSKextLogIPCFlag,
9695 		    "Returning load requests.");
9696 		result = kOSReturnSuccess;
9697 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) {
9698 		printf("KextLog: Loading FileSet KC(s)\n");
9699 		result = OSKext::loadFileSetKexts(requestDict);
9700 	} else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
9701 		printf("KextLog: " kIOKitDaemonName " is %s\n", sIOKitDaemonActive ? "active" : "not active");
9702 		result = (sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot) ? kOSReturnSuccess : kIOReturnNotReady;
9703 	} else {
9704 		OSKextLog(/* kext */ NULL,
9705 		    kOSKextLogDebugLevel |
9706 		    kOSKextLogIPCFlag,
9707 		    "Received '%s' invalid request from user space.",
9708 		    predicate->getCStringNoCopy());
9709 		goto finish;
9710 	}
9711 
9712 	/**********
9713 	 * Now we have handle the request, or not. Gather up the response & logging
9714 	 * info to ship to user space.
9715 	 *********/
9716 
9717 	/* Note: Nothing in OSKext is supposed to retain requestDict,
9718 	 * but you never know....
9719 	 */
9720 	if (requestDict->getRetainCount() > 1) {
9721 		OSKextLog(/* kext */ NULL,
9722 		    kOSKextLogWarningLevel |
9723 		    kOSKextLogIPCFlag,
9724 		    "Request from user space still retained by a kext; "
9725 		    "probable memory leak.");
9726 	}
9727 
9728 	if (responseOut && responseObject) {
9729 		serializer = OSSerialize::withCapacity(0);
9730 		if (!serializer) {
9731 			result = kOSKextReturnNoMemory;
9732 			goto finish;
9733 		}
9734 		/*
9735 		 * Before serializing the kernel requests, patch the dext launch requests so
9736 		 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the
9737 		 * IOUserServerCheckInToken kernel object.
9738 		 */
9739 		if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
9740 			OSArray * requests = OSDynamicCast(OSArray, responseObject.get());
9741 			task_t calling_task = current_task();
9742 			if (!requests) {
9743 				OSKextLog(/* kext */ NULL,
9744 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9745 				    "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests);
9746 				result = kOSKextReturnInternalError;
9747 				goto finish;
9748 			}
9749 			result = patchDextLaunchRequests(calling_task, requests);
9750 			if (result != kOSReturnSuccess) {
9751 				OSKextLog(/* kext */ NULL,
9752 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9753 				    "Failed to patch dext launch requests.");
9754 				goto finish;
9755 			}
9756 		}
9757 
9758 		if (!responseObject->serialize(serializer.get())) {
9759 			OSKextLog(/* kext */ NULL,
9760 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9761 			    "Failed to serialize response to request from user space.");
9762 			result = kOSKextReturnSerialization;
9763 			goto finish;
9764 		}
9765 
9766 		response = (char *)serializer->text();
9767 		responseLength = serializer->getLength();
9768 	}
9769 
9770 	if (responseOut && response) {
9771 		char * buffer;
9772 
9773 		/* This kmem_alloc sets the return value of the function.
9774 		 */
9775 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
9776 		    round_page(responseLength), VM_KERN_MEMORY_OSKEXT);
9777 		if (kmem_result != KERN_SUCCESS) {
9778 			OSKextLog(/* kext */ NULL,
9779 			    kOSKextLogErrorLevel |
9780 			    kOSKextLogIPCFlag,
9781 			    "Failed to copy response to request from user space.");
9782 			result = kmem_result;
9783 			goto finish;
9784 		} else {
9785 			/* 11981737 - clear uninitialized data in last page */
9786 			bzero((void *)(buffer + responseLength),
9787 			    (round_page(responseLength) - responseLength));
9788 			memcpy(buffer, response, responseLength);
9789 			*responseOut = buffer;
9790 			*responseLengthOut = responseLength;
9791 		}
9792 	}
9793 
9794 finish:
9795 
9796 	/* Gather up the collected log messages for user space. Any messages
9797 	 * messages past this call will not make it up as log messages but
9798 	 * will be in the system log. Note that we ignore the return of the
9799 	 * serialize; it has no bearing on the operation at hand even if we
9800 	 * fail to get the log messages.
9801 	 */
9802 	logInfoArray = OSKext::clearUserSpaceLogFilter();
9803 
9804 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
9805 		(void)OSKext::serializeLogInfo(logInfoArray.get(),
9806 		    logInfoOut, logInfoLengthOut);
9807 	}
9808 
9809 	IORecursiveLockUnlock(sKextLock);
9810 
9811 	return result;
9812 }
9813 
9814 #if PRAGMA_MARK
9815 #pragma mark Linked Kext Collection Support
9816 #endif
9817 
9818 static int
9819 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount)
9820 {
9821 	for (int i = 0; i < segCount; i++) {
9822 		vm_offset_t segStart = segAddrs[i];
9823 		vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i];
9824 
9825 		if (theAddr >= segStart && theAddr < segEnd) {
9826 			return i;
9827 		}
9828 	}
9829 	return -1;
9830 }
9831 
9832 static void
9833 __slideOldKaslrOffsets(kernel_mach_header_t *mh,
9834     kernel_segment_command_t *kextTextSeg,
9835     OSData *kaslrOffsets)
9836 {
9837 	static const char *plk_segNames[] = {
9838 		"__TEXT",
9839 		"__TEXT_EXEC",
9840 		"__DATA",
9841 		"__DATA_CONST",
9842 		"__LINKEDIT",
9843 		"__PRELINK_TEXT",
9844 		"__PLK_TEXT_EXEC",
9845 		"__PRELINK_DATA",
9846 		"__PLK_DATA_CONST",
9847 		"__PLK_LLVM_COV",
9848 		"__PLK_LINKEDIT",
9849 		"__PRELINK_INFO"
9850 	};
9851 	static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0]));
9852 
9853 	unsigned long plk_segSizes[num_plk_seg];
9854 	vm_offset_t   plk_segAddrs[num_plk_seg];
9855 
9856 	for (size_t i = 0; i < num_plk_seg; i++) {
9857 		plk_segSizes[i] = 0;
9858 		plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]);
9859 	}
9860 
9861 	uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr;
9862 
9863 	int slidKextAddrCount = 0;
9864 	int badSlideAddr = 0;
9865 	int badSlideTarget = 0;
9866 
9867 	struct kaslrPackedOffsets {
9868 		uint32_t    count;          /* number of offsets */
9869 		uint32_t    offsetsArray[];        /* offsets to slide */
9870 	};
9871 	const struct kaslrPackedOffsets *myOffsets = NULL;
9872 	myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy();
9873 
9874 	for (uint32_t j = 0; j < myOffsets->count; j++) {
9875 		uint64_t   slideOffset = (uint64_t)myOffsets->offsetsArray[j];
9876 		vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset);
9877 		int        slideAddrSegIndex = -1;
9878 		int        addrToSlideSegIndex = -1;
9879 
9880 		slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
9881 		if (slideAddrSegIndex >= 0) {
9882 			addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
9883 			if (addrToSlideSegIndex < 0) {
9884 				badSlideTarget++;
9885 				continue;
9886 			}
9887 		} else {
9888 			badSlideAddr++;
9889 			continue;
9890 		}
9891 
9892 		slidKextAddrCount++;
9893 		*slideAddr = ml_static_slide(*slideAddr);
9894 	}         // for ...
9895 }
9896 
9897 
9898 
9899 /********************************************************************
9900 * addKextsFromKextCollection
9901 *
9902 * Input: MachO header of kext collection. The MachO is assumed to
9903 *        have a section named 'info_seg_name,info_sect_name' that
9904 *        contains a serialized XML info dictionary. This dictionary
9905 *        contains a UUID, possibly a set of relocations (for older
9906 *        kxld-built binaries), and an array of kext personalities.
9907 *
9908 ********************************************************************/
9909 bool
9910 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
9911     OSDictionary *infoDict, const char *text_seg_name,
9912     OSData **kcUUID, kc_kind_t type)
9913 {
9914 	bool result = false;
9915 
9916 	OSArray *kextArray     = NULL;        // do not release
9917 	OSData *infoDictKCUUID = NULL;         // do not release
9918 	OSData *kaslrOffsets   = NULL;        // do not release
9919 
9920 	IORegistryEntry *registryRoot = NULL;         // do not release
9921 	OSSharedPtr<OSNumber> kcKextCount;
9922 
9923 	/* extract the KC UUID from the dictionary */
9924 	infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
9925 	if (infoDictKCUUID) {
9926 		if (infoDictKCUUID->getLength() != sizeof(uuid_t)) {
9927 			panic("kcUUID length is %d, expected %lu",
9928 			    infoDictKCUUID->getLength(), sizeof(uuid_t));
9929 		}
9930 	}
9931 
9932 	/* locate the array of kext dictionaries */
9933 	kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey));
9934 	if (!kextArray) {
9935 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9936 		    "The given KC has no kext info dictionaries");
9937 		goto finish;
9938 	}
9939 
9940 	/*
9941 	 * old-style KASLR offsets may be present in the info dictionary. If
9942 	 * we find them, use them and eventually slide them.
9943 	 */
9944 	kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey));
9945 
9946 	/*
9947 	 * Before processing any kexts, locate the special kext bundle which
9948 	 * contains a list of kexts that we are to prevent from loading.
9949 	 */
9950 	createExcludeListFromPrelinkInfo(kextArray);
9951 
9952 	/*
9953 	 * Create OSKext objects for each kext we find in the array of kext
9954 	 * info plist dictionaries.
9955 	 */
9956 	for (int i = 0; i < (int)kextArray->getCount(); ++i) {
9957 		OSDictionary *kextDict = NULL;
9958 		kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i));
9959 		if (!kextDict) {
9960 			OSKextLog(/* kext */ NULL,
9961 			    kOSKextLogErrorLevel |
9962 			    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
9963 			    "Kext info dictionary for kext #%d isn't a dictionary?", i);
9964 			continue;
9965 		}
9966 
9967 		/*
9968 		 * Create the kext for the entry, then release it, because the
9969 		 * kext system keeps a reference around until the kext is
9970 		 * explicitly removed.  Any creation/registration failures are
9971 		 * already logged for us.
9972 		 */
9973 		withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type);
9974 	}
9975 
9976 	/*
9977 	 * slide old-style kxld relocations
9978 	 * NOTE: this is still used on embedded KCs built with kcgen
9979 	 * TODO: Remove this once we use the new kext linker everywhere!
9980 	 */
9981 	if (kaslrOffsets && vm_kernel_slide > 0) {
9982 		kernel_segment_command_t *text_segment = NULL;
9983 		text_segment = getsegbynamefromheader(mh, text_seg_name);
9984 		if (!text_segment) {
9985 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
9986 			    "Can't find a TEXT segment named '%s' in macho header", text_seg_name);
9987 			goto finish;
9988 		}
9989 
9990 		__slideOldKaslrOffsets(mh, text_segment, kaslrOffsets);
9991 		/* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */
9992 		setAllVMAttributes();
9993 	}
9994 
9995 	/* Store the number of prelinked kexts in the registry so we can tell
9996 	 * when the system has been started from a prelinked kernel.
9997 	 */
9998 	registryRoot = IORegistryEntry::getRegistryRoot();
9999 	assert(registryRoot);
10000 
10001 	kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t));
10002 	assert(kcKextCount);
10003 	if (kcKextCount) {
10004 		OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey);
10005 		OSNumber *num;
10006 		num = OSDynamicCast(OSNumber, prop.get());
10007 		if (num) {
10008 			kcKextCount->addValue(num->unsigned64BitValue());
10009 		}
10010 		registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get());
10011 	}
10012 
10013 	OSKextLog(/* kext */ NULL,
10014 	    kOSKextLogProgressLevel |
10015 	    kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
10016 	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10017 	    "%u prelinked kexts", infoDict->getCount());
10018 
10019 
10020 	if (kcUUID && infoDictKCUUID) {
10021 		*kcUUID = OSData::withData(infoDictKCUUID).detach();
10022 	}
10023 
10024 	result = true;
10025 
10026 finish:
10027 	return result;
10028 }
10029 
10030 bool
10031 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10032     OSDictionary *infoDict, const char *text_seg_name,
10033     OSSharedPtr<OSData> &kcUUID, kc_kind_t type)
10034 {
10035 	OSData  *result = NULL;
10036 	bool success = addKextsFromKextCollection(mh,
10037 	    infoDict,
10038 	    text_seg_name,
10039 	    &result,
10040 	    type);
10041 	if (success) {
10042 		kcUUID.reset(result, OSNoRetain);
10043 	}
10044 	return success;
10045 }
10046 
10047 static OSSharedPtr<OSObject> deferredAuxKCXML;
10048 bool
10049 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh,
10050     OSSharedPtr<OSObject> &parsedXML, kc_kind_t type)
10051 {
10052 	if (type != KCKindAuxiliary) {
10053 		return false;
10054 	}
10055 
10056 	kernel_mach_header_t *_mh;
10057 	_mh = (kernel_mach_header_t*)PE_get_kc_header(type);
10058 	if (!_mh || _mh != mh) {
10059 		return false;
10060 	}
10061 
10062 	if (deferredAuxKCXML) {
10063 		/* only allow this to be called once */
10064 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10065 		    "An Aux KC has already been registered for deferred processing.");
10066 		return false;
10067 	}
10068 
10069 	OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
10070 	if (!infoDict) {
10071 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10072 		    "The Aux KC has info dictionary");
10073 		return false;
10074 	}
10075 
10076 	OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10077 	if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) {
10078 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10079 		    "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey);
10080 		return false;
10081 	}
10082 
10083 	/*
10084 	 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid
10085 	 * sysctl can return the UUID to user space which will check this
10086 	 * value for errors.
10087 	 */
10088 	memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(),
10089 	    kcUUID->getLength());
10090 	uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
10091 	auxkc_uuid_valid = TRUE;
10092 
10093 	deferredAuxKCXML = parsedXML;
10094 
10095 	return true;
10096 }
10097 
10098 OSSharedPtr<OSObject>
10099 OSKext::consumeDeferredKextCollection(kc_kind_t type)
10100 {
10101 	if (type != KCKindAuxiliary || !deferredAuxKCXML) {
10102 		return NULL;
10103 	}
10104 
10105 	return os::move(deferredAuxKCXML);
10106 }
10107 
10108 #if PRAGMA_MARK
10109 #pragma mark Profile-Guided-Optimization Support
10110 #endif
10111 
10112 // #include <InstrProfiling.h>
10113 extern "C" {
10114 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
10115     const char *DataEnd,
10116     const char *CountersBegin,
10117     const char *CountersEnd,
10118     const char *NamesBegin,
10119     const char *NamesEnd);
10120 int __llvm_profile_write_buffer_internal(char *Buffer,
10121     const char *DataBegin,
10122     const char *DataEnd,
10123     const char *CountersBegin,
10124     const char *CountersEnd,
10125     const char *NamesBegin,
10126     const char *NamesEnd);
10127 }
10128 
10129 
10130 static
10131 void
10132 OSKextPgoMetadataPut(char *pBuffer,
10133     size_t *position,
10134     size_t bufferSize,
10135     uint32_t *num_pairs,
10136     const char *key,
10137     const char *value)
10138 {
10139 	size_t strlen_key = strlen(key);
10140 	size_t strlen_value = strlen(value);
10141 	size_t len = strlen(key) + 1 + strlen(value) + 1;
10142 	char *pos = pBuffer + *position;
10143 	*position += len;
10144 	if (pBuffer && bufferSize && *position <= bufferSize) {
10145 		memcpy(pos, key, strlen_key); pos += strlen_key;
10146 		*(pos++) = '=';
10147 		memcpy(pos, value, strlen_value); pos += strlen_value;
10148 		*(pos++) = 0;
10149 		if (num_pairs) {
10150 			(*num_pairs)++;
10151 		}
10152 	}
10153 }
10154 
10155 
10156 static
10157 void
10158 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
10159 {
10160 	*position += strlen(key) + 1 + value_max + 1;
10161 }
10162 
10163 
10164 static
10165 void
10166 OSKextPgoMetadataPutAll(OSKext *kext,
10167     uuid_t instance_uuid,
10168     char *pBuffer,
10169     size_t *position,
10170     size_t bufferSize,
10171     uint32_t *num_pairs)
10172 {
10173 	_static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
10174 	//log_10 2^16 ≈ 4.82
10175 	const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
10176 	const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
10177 
10178 	if (!pBuffer) {
10179 		OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
10180 		OSKextPgoMetadataPutMax(position, "UUID", 36);
10181 		OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
10182 	} else {
10183 		uuid_string_t instance_uuid_string;
10184 		uuid_unparse(instance_uuid, instance_uuid_string);
10185 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10186 		    "INSTANCE", instance_uuid_string);
10187 
10188 		OSSharedPtr<OSData> uuid_data;
10189 		uuid_t uuid;
10190 		uuid_string_t uuid_string;
10191 		uuid_data = kext->copyUUID();
10192 		if (uuid_data) {
10193 			memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
10194 			uuid_unparse(uuid, uuid_string);
10195 			OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10196 			    "UUID", uuid_string);
10197 		}
10198 
10199 		clock_sec_t secs;
10200 		clock_usec_t usecs;
10201 		clock_get_calendar_microtime(&secs, &usecs);
10202 		assert(usecs < 1000000);
10203 		char timestamp[max_timestamp_string_size + 1];
10204 		_static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
10205 		snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
10206 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10207 		    "TIMESTAMP", timestamp);
10208 	}
10209 
10210 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10211 	    "NAME", kext->getIdentifierCString());
10212 
10213 	char versionCString[kOSKextVersionMaxLength];
10214 	OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
10215 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10216 	    "VERSION", versionCString);
10217 }
10218 
10219 static
10220 size_t
10221 OSKextPgoMetadataSize(OSKext *kext)
10222 {
10223 	size_t position = 0;
10224 	uuid_t fakeuuid = {};
10225 	OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
10226 	return position;
10227 }
10228 
10229 int
10230 OSKextGrabPgoDataLocked(OSKext *kext,
10231     bool metadata,
10232     uuid_t instance_uuid,
10233     uint64_t *pSize,
10234     char *pBuffer,
10235     uint64_t bufferSize)
10236 {
10237 	int err = 0;
10238 
10239 	kernel_section_t *sect_prf_data = NULL;
10240 	kernel_section_t *sect_prf_name = NULL;
10241 	kernel_section_t *sect_prf_cnts = NULL;
10242 	uint64_t size;
10243 	size_t metadata_size = 0;
10244 	size_t offset_to_pairs = 0;
10245 
10246 	sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
10247 	sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
10248 	if (!sect_prf_name) {
10249 		// kextcache sometimes truncates the section name to 15 chars
10250 		// <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
10251 		sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
10252 	}
10253 	sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
10254 
10255 	if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
10256 		err = ENOTSUP;
10257 		goto out;
10258 	}
10259 
10260 	size = __llvm_profile_get_size_for_buffer_internal(
10261 		(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
10262 		(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
10263 		(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
10264 
10265 	if (metadata) {
10266 		metadata_size = OSKextPgoMetadataSize(kext);
10267 		size += metadata_size;
10268 		size += sizeof(pgo_metadata_footer);
10269 	}
10270 
10271 
10272 	if (pSize) {
10273 		*pSize = size;
10274 	}
10275 
10276 	if (pBuffer && bufferSize) {
10277 		if (bufferSize < size) {
10278 			err = ERANGE;
10279 			goto out;
10280 		}
10281 
10282 		err = __llvm_profile_write_buffer_internal(
10283 			pBuffer,
10284 			(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
10285 			(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
10286 			(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
10287 
10288 		if (err) {
10289 			err = EIO;
10290 			goto out;
10291 		}
10292 
10293 		if (metadata) {
10294 			offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size;
10295 			if (offset_to_pairs > UINT32_MAX) {
10296 				err = E2BIG;
10297 				goto out;
10298 			}
10299 
10300 			char *end_of_buffer = pBuffer + size;
10301 			struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
10302 			char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
10303 
10304 			size_t metadata_position = 0;
10305 			uint32_t num_pairs = 0;
10306 			OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
10307 			while (metadata_position < metadata_size) {
10308 				metadata_buffer[metadata_position++] = 0;
10309 			}
10310 
10311 			struct pgo_metadata_footer footer;
10312 			footer.magic = htonl(0x6d657461);
10313 			footer.number_of_pairs = htonl( num_pairs );
10314 			footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs );
10315 			memcpy(footerp, &footer, sizeof(footer));
10316 		}
10317 	}
10318 
10319 out:
10320 	return err;
10321 }
10322 
10323 
10324 int
10325 OSKextGrabPgoData(uuid_t uuid,
10326     uint64_t *pSize,
10327     char *pBuffer,
10328     uint64_t bufferSize,
10329     int wait_for_unload,
10330     int metadata)
10331 {
10332 	int err = 0;
10333 	OSSharedPtr<OSKext> kext;
10334 
10335 
10336 	IORecursiveLockLock(sKextLock);
10337 
10338 	kext = OSKext::lookupKextWithUUID(uuid);
10339 	if (!kext) {
10340 		err = ENOENT;
10341 		goto out;
10342 	}
10343 
10344 	if (wait_for_unload) {
10345 		OSKextGrabPgoStruct s;
10346 
10347 		s.metadata = metadata;
10348 		s.pSize = pSize;
10349 		s.pBuffer = pBuffer;
10350 		s.bufferSize = bufferSize;
10351 		s.err = EINTR;
10352 
10353 		struct list_head *prev = &kext->pendingPgoHead;
10354 		struct list_head *next = kext->pendingPgoHead.next;
10355 
10356 		s.list_head.prev = prev;
10357 		s.list_head.next = next;
10358 
10359 		prev->next = &s.list_head;
10360 		next->prev = &s.list_head;
10361 
10362 		kext.reset();
10363 
10364 		IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
10365 
10366 		prev = s.list_head.prev;
10367 		next = s.list_head.next;
10368 
10369 		prev->next = next;
10370 		next->prev = prev;
10371 
10372 		err = s.err;
10373 	} else {
10374 		err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
10375 	}
10376 
10377 out:
10378 
10379 	IORecursiveLockUnlock(sKextLock);
10380 
10381 	return err;
10382 }
10383 
10384 void
10385 OSKextResetPgoCountersLock()
10386 {
10387 	IORecursiveLockLock(sKextLock);
10388 }
10389 
10390 void
10391 OSKextResetPgoCountersUnlock()
10392 {
10393 	IORecursiveLockUnlock(sKextLock);
10394 }
10395 
10396 
10397 extern unsigned int not_in_kdp;
10398 
10399 void
10400 OSKextResetPgoCounters()
10401 {
10402 	assert(!not_in_kdp);
10403 	uint32_t count = sLoadedKexts->getCount();
10404 	for (uint32_t i = 0; i < count; i++) {
10405 		OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
10406 		kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
10407 		if (!sect_prf_cnts) {
10408 			continue;
10409 		}
10410 		memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
10411 	}
10412 }
10413 
10414 OSSharedPtr<OSDictionary>
10415 OSKext::copyLoadedKextInfoByUUID(
10416 	OSArray * kextIdentifiers,
10417 	OSArray * infoKeys)
10418 {
10419 	OSSharedPtr<OSDictionary> result;
10420 	OSSharedPtr<OSDictionary> kextInfo;
10421 	uint32_t       max_count, i, j;
10422 	uint32_t       idCount = 0;
10423 	uint32_t       idIndex = 0;
10424 	IORecursiveLockLock(sKextLock);
10425 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
10426 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
10427 
10428 #if CONFIG_MACF
10429 	/* Is the calling process allowed to query kext info? */
10430 	if (current_task() != kernel_task) {
10431 		int                 macCheckResult      = 0;
10432 		kauth_cred_t        cred                = NULL;
10433 
10434 		cred = kauth_cred_get_with_ref();
10435 		macCheckResult = mac_kext_check_query(cred);
10436 		kauth_cred_unref(&cred);
10437 
10438 		if (macCheckResult != 0) {
10439 			OSKextLog(/* kext */ NULL,
10440 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10441 			    "Failed to query kext info (MAC policy error 0x%x).",
10442 			    macCheckResult);
10443 			goto finish;
10444 		}
10445 	}
10446 #endif
10447 
10448 	/* Empty list of UUIDs is equivalent to no list (get all).
10449 	 */
10450 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
10451 		kextIdentifiers = NULL;
10452 	} else if (kextIdentifiers) {
10453 		idCount = kextIdentifiers->getCount();
10454 	}
10455 
10456 	/* Same for keys.
10457 	 */
10458 	if (infoKeys && !infoKeys->getCount()) {
10459 		infoKeys = NULL;
10460 	}
10461 
10462 	max_count = count[0] + count[1];
10463 	result = OSDictionary::withCapacity(max_count);
10464 	if (!result) {
10465 		goto finish;
10466 	}
10467 
10468 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
10469 		for (i = 0; i < count[j]; i++) {
10470 			OSKext       *thisKext     = NULL;        // do not release
10471 			Boolean       includeThis  = true;
10472 			uuid_t        thisKextUUID;
10473 			uuid_t        thisKextTextUUID;
10474 			OSSharedPtr<OSData> uuid_data;
10475 			uuid_string_t uuid_key;
10476 
10477 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
10478 			if (!thisKext) {
10479 				continue;
10480 			}
10481 
10482 			uuid_data = thisKext->copyUUID();
10483 			if (!uuid_data) {
10484 				continue;
10485 			}
10486 
10487 			memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
10488 
10489 			uuid_unparse(thisKextUUID, uuid_key);
10490 
10491 			uuid_data = thisKext->copyTextUUID();
10492 			if (!uuid_data) {
10493 				continue;
10494 			}
10495 			memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
10496 
10497 			/* Skip current kext if we have a list of UUIDs and
10498 			 * it isn't in the list.
10499 			 */
10500 			if (kextIdentifiers) {
10501 				includeThis = false;
10502 
10503 				for (idIndex = 0; idIndex < idCount; idIndex++) {
10504 					const OSString* wantedUUID = OSDynamicCast(OSString,
10505 					    kextIdentifiers->getObject(idIndex));
10506 
10507 					uuid_t uuid;
10508 					uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
10509 
10510 					if ((0 == uuid_compare(uuid, thisKextUUID))
10511 					    || (0 == uuid_compare(uuid, thisKextTextUUID))) {
10512 						includeThis = true;
10513 						/* Only need to find the first kext if multiple match,
10514 						 * ie. asking for the kernel uuid does not need to find
10515 						 * interface kexts or builtin static kexts.
10516 						 */
10517 						kextIdentifiers->removeObject(idIndex);
10518 						uuid_unparse(uuid, uuid_key);
10519 						break;
10520 					}
10521 				}
10522 			}
10523 
10524 			if (!includeThis) {
10525 				continue;
10526 			}
10527 
10528 			kextInfo = thisKext->copyInfo(infoKeys);
10529 			if (kextInfo) {
10530 				result->setObject(uuid_key, kextInfo.get());
10531 			}
10532 
10533 			if (kextIdentifiers && !kextIdentifiers->getCount()) {
10534 				goto finish;
10535 			}
10536 		}
10537 	}
10538 
10539 finish:
10540 	IORecursiveLockUnlock(sKextLock);
10541 
10542 	return result;
10543 }
10544 
10545 /*********************************************************************
10546 *********************************************************************/
10547 /* static */
10548 OSSharedPtr<OSDictionary>
10549 OSKext::copyKextCollectionInfo(
10550 	OSDictionary *requestDict,
10551 	OSArray  *infoKeys)
10552 {
10553 	OSSharedPtr<OSDictionary> result;
10554 	OSString *collectionType = NULL;
10555 	OSObject *rawLoadedState = NULL;
10556 	OSString *loadedState    = NULL;
10557 
10558 	kc_kind_t kc_request_kind = KCKindUnknown;
10559 	bool onlyLoaded = false;
10560 	bool onlyUnloaded = false;
10561 
10562 #if CONFIG_MACF
10563 	/* Is the calling process allowed to query kext info? */
10564 	if (current_task() != kernel_task) {
10565 		int                 macCheckResult      = 0;
10566 		kauth_cred_t        cred                = NULL;
10567 
10568 		cred = kauth_cred_get_with_ref();
10569 		macCheckResult = mac_kext_check_query(cred);
10570 		kauth_cred_unref(&cred);
10571 
10572 		if (macCheckResult != 0) {
10573 			OSKextLog(/* kext */ NULL,
10574 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10575 			    "Failed to query kext info (MAC policy error 0x%x).",
10576 			    macCheckResult);
10577 			goto finish;
10578 		}
10579 	}
10580 #endif
10581 
10582 	if (infoKeys && !infoKeys->getCount()) {
10583 		infoKeys = NULL;
10584 	}
10585 
10586 	collectionType = OSDynamicCast(OSString,
10587 	    _OSKextGetRequestArgument(requestDict,
10588 	    kKextRequestArgumentCollectionTypeKey));
10589 	if (!collectionType) {
10590 		OSKextLog(/* kext */ NULL,
10591 		    kOSKextLogErrorLevel |
10592 		    kOSKextLogIPCFlag,
10593 		    "Invalid '%s' argument to kext collection info request.",
10594 		    kKextRequestArgumentCollectionTypeKey);
10595 		goto finish;
10596 	}
10597 	if (collectionType->isEqualTo(kKCTypePrimary)) {
10598 		kc_request_kind = KCKindPrimary;
10599 	} else if (collectionType->isEqualTo(kKCTypeSystem)) {
10600 		kc_request_kind = KCKindPageable;
10601 	} else if (collectionType->isEqualTo(kKCTypeAuxiliary)) {
10602 		kc_request_kind = KCKindAuxiliary;
10603 	} else if (collectionType->isEqualTo(kKCTypeCodeless)) {
10604 		kc_request_kind = KCKindNone;
10605 	} else if (!collectionType->isEqualTo(kKCTypeAny)) {
10606 		OSKextLog(/* kext */ NULL,
10607 		    kOSKextLogErrorLevel |
10608 		    kOSKextLogIPCFlag,
10609 		    "Invalid '%s' argument value '%s' to kext collection info request.",
10610 		    kKextRequestArgumentCollectionTypeKey,
10611 		    collectionType->getCStringNoCopy());
10612 		goto finish;
10613 	}
10614 
10615 	rawLoadedState = _OSKextGetRequestArgument(requestDict,
10616 	    kKextRequestArgumentLoadedStateKey);
10617 	if (rawLoadedState) {
10618 		loadedState = OSDynamicCast(OSString, rawLoadedState);
10619 		if (!loadedState) {
10620 			OSKextLog(/* kext */ NULL,
10621 			    kOSKextLogErrorLevel |
10622 			    kOSKextLogIPCFlag,
10623 			    "Invalid '%s' argument to kext collection info request.",
10624 			    kKextRequestArgumentLoadedStateKey);
10625 			goto finish;
10626 		}
10627 	}
10628 	if (loadedState) {
10629 		if (loadedState->isEqualTo("Loaded")) {
10630 			onlyLoaded = true;
10631 		} else if (loadedState->isEqualTo("Unloaded")) {
10632 			onlyUnloaded = true;
10633 		} else if (!loadedState->isEqualTo("Any")) {
10634 			OSKextLog(/* kext */ NULL,
10635 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10636 			    "Invalid '%s' argument value '%s' for '%s' collection info",
10637 			    kKextRequestArgumentLoadedStateKey,
10638 			    loadedState->getCStringNoCopy(),
10639 			    collectionType->getCStringNoCopy());
10640 			goto finish;
10641 		}
10642 	}
10643 
10644 	result = OSDictionary::withCapacity(sKextsByID->getCount());
10645 	if (!result) {
10646 		goto finish;
10647 	}
10648 
10649 	IORecursiveLockLock(sKextLock);
10650 	{         // start block scope
10651 		sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
10652 		{
10653 			OSKext       *thisKext    = NULL;  // do not release
10654 			OSSharedPtr<OSDictionary> kextInfo;
10655 
10656 			(void)thisKextID;
10657 
10658 			thisKext = OSDynamicCast(OSKext, obj);
10659 			if (!thisKext) {
10660 			        return false;
10661 			}
10662 
10663 			/*
10664 			 * skip the kext if it came from the wrong collection type
10665 			 * (and the caller requested a specific type)
10666 			 */
10667 			if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) {
10668 			        return false;
10669 			}
10670 
10671 			/*
10672 			 * respect the caller's desire to find only loaded or
10673 			 * unloaded kexts
10674 			 */
10675 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10676 			        return false;
10677 			}
10678 			if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10679 			        return false;
10680 			}
10681 
10682 			kextInfo = thisKext->copyInfo(infoKeys);
10683 			if (kextInfo) {
10684 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
10685 			}
10686 			return false;
10687 		});
10688 	} // end block scope
10689 	IORecursiveLockUnlock(sKextLock);
10690 
10691 finish:
10692 	return result;
10693 }
10694 
10695 /*********************************************************************
10696 *********************************************************************/
10697 /* static */
10698 OSSharedPtr<OSDictionary>
10699 OSKext::copyLoadedKextInfo(
10700 	OSArray * kextIdentifiers,
10701 	OSArray * infoKeys)
10702 {
10703 	OSSharedPtr<OSDictionary> result;
10704 	uint32_t       idCount = 0;
10705 	bool           onlyLoaded;
10706 
10707 	IORecursiveLockLock(sKextLock);
10708 
10709 #if CONFIG_MACF
10710 	/* Is the calling process allowed to query kext info? */
10711 	if (current_task() != kernel_task) {
10712 		int                 macCheckResult      = 0;
10713 		kauth_cred_t        cred                = NULL;
10714 
10715 		cred = kauth_cred_get_with_ref();
10716 		macCheckResult = mac_kext_check_query(cred);
10717 		kauth_cred_unref(&cred);
10718 
10719 		if (macCheckResult != 0) {
10720 			OSKextLog(/* kext */ NULL,
10721 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
10722 			    "Failed to query kext info (MAC policy error 0x%x).",
10723 			    macCheckResult);
10724 			goto finish;
10725 		}
10726 	}
10727 #endif
10728 
10729 	/* Empty list of bundle ids is equivalent to no list (get all).
10730 	 */
10731 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
10732 		kextIdentifiers = NULL;
10733 	} else if (kextIdentifiers) {
10734 		idCount = kextIdentifiers->getCount();
10735 	}
10736 
10737 	/* Same for keys.
10738 	 */
10739 	if (infoKeys && !infoKeys->getCount()) {
10740 		infoKeys = NULL;
10741 	}
10742 
10743 	onlyLoaded =  (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
10744 
10745 	result = OSDictionary::withCapacity(128);
10746 	if (!result) {
10747 		goto finish;
10748 	}
10749 
10750 #if 0
10751 	OSKextLog(/* kext */ NULL,
10752 	    kOSKextLogErrorLevel |
10753 	    kOSKextLogGeneralFlag,
10754 	    "kaslr: vm_kernel_slide 0x%lx \n",
10755 	    vm_kernel_slide);
10756 	OSKextLog(/* kext */ NULL,
10757 	    kOSKextLogErrorLevel |
10758 	    kOSKextLogGeneralFlag,
10759 	    "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
10760 	    vm_kernel_stext, vm_kernel_etext);
10761 	OSKextLog(/* kext */ NULL,
10762 	    kOSKextLogErrorLevel |
10763 	    kOSKextLogGeneralFlag,
10764 	    "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
10765 	    vm_kernel_base, vm_kernel_top);
10766 	OSKextLog(/* kext */ NULL,
10767 	    kOSKextLogErrorLevel |
10768 	    kOSKextLogGeneralFlag,
10769 	    "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
10770 	    vm_kext_base, vm_kext_top);
10771 	OSKextLog(/* kext */ NULL,
10772 	    kOSKextLogErrorLevel |
10773 	    kOSKextLogGeneralFlag,
10774 	    "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
10775 	    vm_prelink_stext, vm_prelink_etext);
10776 	OSKextLog(/* kext */ NULL,
10777 	    kOSKextLogErrorLevel |
10778 	    kOSKextLogGeneralFlag,
10779 	    "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
10780 	    vm_prelink_sinfo, vm_prelink_einfo);
10781 	OSKextLog(/* kext */ NULL,
10782 	    kOSKextLogErrorLevel |
10783 	    kOSKextLogGeneralFlag,
10784 	    "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
10785 	    vm_slinkedit, vm_elinkedit);
10786 #endif
10787 	{         // start block scope
10788 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
10789 		{
10790 			OSKext       * thisKext     = NULL;        // do not release
10791 			Boolean        includeThis  = true;
10792 			OSSharedPtr<OSDictionary> kextInfo;
10793 
10794 			thisKext = OSDynamicCast(OSKext, obj);
10795 			if (!thisKext) {
10796 			        return false;
10797 			}
10798 
10799 			/* Skip current kext if not yet started and caller didn't request all.
10800 			 */
10801 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
10802 			        return false;
10803 			}
10804 
10805 			/* Skip current kext if we have a list of bundle IDs and
10806 			 * it isn't in the list.
10807 			 */
10808 			if (kextIdentifiers) {
10809 			        includeThis = false;
10810 
10811 			        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
10812 			                const OSString * thisRequestID = OSDynamicCast(OSString,
10813 			                kextIdentifiers->getObject(idIndex));
10814 			                if (thisKextID->isEqualTo(thisRequestID)) {
10815 			                        includeThis = true;
10816 			                        break;
10817 					}
10818 				}
10819 			}
10820 
10821 			if (!includeThis) {
10822 			        return false;
10823 			}
10824 
10825 			kextInfo = thisKext->copyInfo(infoKeys);
10826 			if (kextInfo) {
10827 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
10828 			}
10829 			return false;
10830 		});
10831 	}         // end block scope
10832 
10833 finish:
10834 	IORecursiveLockUnlock(sKextLock);
10835 
10836 	return result;
10837 }
10838 
10839 /*********************************************************************
10840 * Any info that needs to do allocations must goto finish on alloc
10841 * failure. Info that is just a lookup should just not set the object
10842 * if the info does not exist.
10843 *********************************************************************/
10844 #define _OSKextLoadInfoDictCapacity   (12)
10845 
10846 OSSharedPtr<OSDictionary>
10847 OSKext::copyInfo(OSArray * infoKeys)
10848 {
10849 	OSSharedPtr<OSDictionary>  result;
10850 	bool                       success                     = false;
10851 	OSSharedPtr<OSData>        headerData;
10852 	OSSharedPtr<OSData>        logData;
10853 	OSSharedPtr<OSNumber>      cpuTypeNumber;
10854 	OSSharedPtr<OSNumber>      cpuSubtypeNumber;
10855 	OSString                 * versionString               = NULL;        // do not release
10856 	OSString                 * bundleType                  = NULL;        // do not release
10857 	uint32_t                   executablePathCStringSize   = 0;
10858 	char                     * executablePathCString       = NULL;        // must kfree
10859 	OSSharedPtr<OSString>      executablePathString;
10860 	OSSharedPtr<OSData>        uuid;
10861 	OSSharedPtr<OSArray>       dependencyLoadTags;
10862 	OSSharedPtr<OSCollectionIterator>      metaClassIterator;
10863 	OSSharedPtr<OSArray>       metaClassInfo;
10864 	OSSharedPtr<OSDictionary>  metaClassDict;
10865 	OSMetaClass              * thisMetaClass               = NULL;        // do not release
10866 	OSSharedPtr<OSString>      metaClassName;
10867 	OSSharedPtr<OSString>      superclassName;
10868 	kc_format_t                kcformat;
10869 	uint32_t                   count, i;
10870 
10871 	result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
10872 	if (!result) {
10873 		goto finish;
10874 	}
10875 
10876 
10877 	/* Empty keys means no keys, but NULL is quicker to check.
10878 	 */
10879 	if (infoKeys && !infoKeys->getCount()) {
10880 		infoKeys = NULL;
10881 	}
10882 
10883 	if (!PE_get_primary_kc_format(&kcformat)) {
10884 		goto finish;
10885 	}
10886 
10887 	/* Headers, CPU type, and CPU subtype.
10888 	 */
10889 	if (!infoKeys ||
10890 	    _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
10891 	    _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
10892 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
10893 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
10894 		if (linkedExecutable && !isInterface()) {
10895 			kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
10896 			    linkedExecutable->getBytesNoCopy();
10897 
10898 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX
10899 			// do not return macho header info on shipping embedded - 19095897
10900 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
10901 				kernel_mach_header_t *  temp_kext_mach_hdr;
10902 				struct load_command *   lcp;
10903 
10904 				headerData = OSData::withBytes(kext_mach_hdr,
10905 				    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
10906 				if (!headerData) {
10907 					goto finish;
10908 				}
10909 
10910 				// unslide any vmaddrs we return to userspace - 10726716
10911 				temp_kext_mach_hdr = (kernel_mach_header_t *)
10912 				    headerData->getBytesNoCopy();
10913 				if (temp_kext_mach_hdr == NULL) {
10914 					goto finish;
10915 				}
10916 
10917 				lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
10918 				for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
10919 					if (lcp->cmd == LC_SEGMENT_KERNEL) {
10920 						kernel_segment_command_t *  segp;
10921 						kernel_section_t *          secp;
10922 
10923 						segp = (kernel_segment_command_t *) lcp;
10924 						// 10543468 - if we jettisoned __LINKEDIT clear size info
10925 						if (flags.jettisonLinkeditSeg) {
10926 							if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
10927 								segp->vmsize = 0;
10928 								segp->fileoff = 0;
10929 								segp->filesize = 0;
10930 							}
10931 						}
10932 
10933 #if __arm__ || __arm64__
10934 						// iBoot disregards zero-size segments, just set their addresses to gVirtBase
10935 						// and unslide them to avoid vm assertion failures / kernel logging breakage.
10936 						if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) {
10937 							segp->vmaddr = gVirtBase;
10938 							for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
10939 								secp->size = 0; // paranoia :)
10940 								secp->addr = gVirtBase;
10941 							}
10942 						}
10943 #endif
10944 
10945 #if 0
10946 						OSKextLog(/* kext */ NULL,
10947 						    kOSKextLogErrorLevel |
10948 						    kOSKextLogGeneralFlag,
10949 						    "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
10950 						    __FUNCTION__, segp->segname, segp->vmaddr,
10951 						    VM_KERNEL_UNSLIDE(segp->vmaddr),
10952 						    segp->vmsize, segp->nsects);
10953 						if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
10954 						    (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
10955 						    (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
10956 						    (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
10957 						    (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
10958 							OSKextLog(/* kext */ NULL,
10959 							    kOSKextLogErrorLevel |
10960 							    kOSKextLogGeneralFlag,
10961 							    "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
10962 							    __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
10963 						}
10964 #endif
10965 						segp->vmaddr = ml_static_unslide(segp->vmaddr);
10966 
10967 						for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
10968 							secp->addr = ml_static_unslide(secp->addr);
10969 						}
10970 					}
10971 					lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
10972 				}
10973 				result->setObject(kOSBundleMachOHeadersKey, headerData.get());
10974 			}
10975 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX
10976 
10977 			if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
10978 				osLogDataHeaderRef *header;
10979 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
10980 
10981 				void *os_log_data               = NULL;
10982 				void *cstring_data              = NULL;
10983 				void *asan_cstring_data         = NULL;
10984 				unsigned long os_log_size       = 0;
10985 				unsigned long cstring_size      = 0;
10986 				unsigned long asan_cstring_size = 0;
10987 				uint32_t os_log_offset          = 0;
10988 				uint32_t cstring_offset         = 0;
10989 				uint32_t asan_cstring_offset    = 0;
10990 				bool res;
10991 
10992 				os_log_data         = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
10993 				os_log_offset       = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr;
10994 				cstring_data        = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
10995 				cstring_offset      = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr;
10996 				asan_cstring_data   = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size);
10997 				asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr;
10998 
10999 				header             = (osLogDataHeaderRef *) headerBytes;
11000 				header->version    = OS_LOG_HDR_VERSION;
11001 				header->sect_count = NUM_OS_LOG_SECTIONS;
11002 				header->sections[OS_LOG_SECT_IDX].sect_offset       = os_log_offset;
11003 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) os_log_size;
11004 				header->sections[CSTRING_SECT_IDX].sect_offset      = cstring_offset;
11005 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) cstring_size;
11006 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset;
11007 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) asan_cstring_size;
11008 
11009 
11010 				logData = OSData::withValue(*header);
11011 				if (!logData) {
11012 					goto finish;
11013 				}
11014 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
11015 				if (!res) {
11016 					goto finish;
11017 				}
11018 				if (os_log_data) {
11019 					res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
11020 					if (!res) {
11021 						goto finish;
11022 					}
11023 				}
11024 				if (cstring_data) {
11025 					res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
11026 					if (!res) {
11027 						goto finish;
11028 					}
11029 				}
11030 				if (asan_cstring_data) {
11031 					res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size);
11032 					if (!res) {
11033 						goto finish;
11034 					}
11035 				}
11036 				result->setObject(kOSBundleLogStringsKey, logData.get());
11037 			}
11038 
11039 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
11040 				cpuTypeNumber = OSNumber::withNumber(
11041 					(uint64_t) kext_mach_hdr->cputype,
11042 					8 * sizeof(kext_mach_hdr->cputype));
11043 				if (!cpuTypeNumber) {
11044 					goto finish;
11045 				}
11046 				result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get());
11047 			}
11048 
11049 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
11050 				cpuSubtypeNumber = OSNumber::withNumber(
11051 					(uint64_t) kext_mach_hdr->cpusubtype,
11052 					8 * sizeof(kext_mach_hdr->cpusubtype));
11053 				if (!cpuSubtypeNumber) {
11054 					goto finish;
11055 				}
11056 				result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get());
11057 			}
11058 		} else {
11059 			if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
11060 				osLogDataHeaderRef *header;
11061 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
11062 				bool res;
11063 
11064 				header             = (osLogDataHeaderRef *) headerBytes;
11065 				header->version    = OS_LOG_HDR_VERSION;
11066 				header->sect_count = NUM_OS_LOG_SECTIONS;
11067 				header->sections[OS_LOG_SECT_IDX].sect_offset       = 0;
11068 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) 0;
11069 				header->sections[CSTRING_SECT_IDX].sect_offset      = 0;
11070 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) 0;
11071 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0;
11072 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) 0;
11073 
11074 				logData = OSData::withValue(*header);
11075 				if (!logData) {
11076 					goto finish;
11077 				}
11078 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
11079 				if (!res) {
11080 					goto finish;
11081 				}
11082 				result->setObject(kOSBundleLogStringsKey, logData.get());
11083 			}
11084 		}
11085 	}
11086 
11087 	/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
11088 	 */
11089 	result->setObject(kCFBundleIdentifierKey, bundleID.get());
11090 
11091 	/* CFBundlePackageType
11092 	 */
11093 	bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL;
11094 	if (bundleType) {
11095 		result->setObject(kCFBundlePackageTypeKey, bundleType);
11096 	}
11097 
11098 	/* CFBundleVersion.
11099 	 */
11100 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
11101 		versionString = OSDynamicCast(OSString,
11102 		    getPropertyForHostArch(kCFBundleVersionKey));
11103 		if (versionString) {
11104 			result->setObject(kCFBundleVersionKey, versionString);
11105 		}
11106 	}
11107 
11108 	/* OSBundleCompatibleVersion.
11109 	 */
11110 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
11111 		versionString = OSDynamicCast(OSString,
11112 		    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
11113 		if (versionString) {
11114 			result->setObject(kOSBundleCompatibleVersionKey, versionString);
11115 		}
11116 	}
11117 
11118 	/* Path.
11119 	 */
11120 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
11121 		if (path) {
11122 			result->setObject(kOSBundlePathKey, path.get());
11123 		}
11124 	}
11125 
11126 
11127 	/* OSBundleExecutablePath.
11128 	 */
11129 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
11130 		if (path && executableRelPath) {
11131 			uint32_t pathLength = path->getLength();         // gets incremented below
11132 
11133 			// +1 for slash, +1 for \0
11134 			executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
11135 
11136 			executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
11137 			    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);         // +1 for \0
11138 			if (!executablePathCString) {
11139 				goto finish;
11140 			}
11141 			strlcpy(executablePathCString, path->getCStringNoCopy(),
11142 			    executablePathCStringSize);
11143 			executablePathCString[pathLength++] = '/';
11144 			executablePathCString[pathLength++] = '\0';
11145 			strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
11146 			    executablePathCStringSize);
11147 
11148 			executablePathString = OSString::withCString(executablePathCString);
11149 
11150 			if (!executablePathString) {
11151 				goto finish;
11152 			}
11153 
11154 			result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
11155 		} else if (flags.builtin) {
11156 			result->setObject(kOSBundleExecutablePathKey, bundleID.get());
11157 		} else if (isDriverKit()) {
11158 			if (path) {
11159 				// +1 for slash, +1 for \0
11160 				uint32_t pathLength = path->getLength();
11161 				executablePathCStringSize = pathLength + 2;
11162 
11163 				executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
11164 				    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
11165 				if (!executablePathCString) {
11166 					goto finish;
11167 				}
11168 				strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
11169 				executablePathCString[pathLength++] = '/';
11170 				executablePathCString[pathLength++] = '\0';
11171 
11172 				executablePathString = OSString::withCString(executablePathCString);
11173 
11174 				if (!executablePathString) {
11175 					goto finish;
11176 				}
11177 
11178 				result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
11179 			}
11180 		}
11181 	}
11182 
11183 	/* UUID, if the kext has one.
11184 	 */
11185 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
11186 		uuid = copyUUID();
11187 		if (uuid) {
11188 			result->setObject(kOSBundleUUIDKey, uuid.get());
11189 		}
11190 	}
11191 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
11192 		uuid = copyTextUUID();
11193 		if (uuid) {
11194 			result->setObject(kOSBundleTextUUIDKey, uuid.get());
11195 		}
11196 	}
11197 
11198 	/*
11199 	 * Info.plist digest
11200 	 */
11201 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) {
11202 		OSData *digest;
11203 		digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL;
11204 		if (digest) {
11205 			result->setObject(kOSKextInfoPlistDigestKey, digest);
11206 		}
11207 	}
11208 
11209 	/*
11210 	 * Collection type
11211 	 */
11212 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) {
11213 		result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString()));
11214 	}
11215 
11216 	/*
11217 	 * Collection availability
11218 	 */
11219 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) {
11220 		result->setObject(kOSKextAuxKCAvailabilityKey,
11221 		    isLoadable() ? kOSBooleanTrue : kOSBooleanFalse);
11222 	}
11223 
11224 	/*
11225 	 * Allows user load
11226 	 */
11227 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) {
11228 		OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey));
11229 		if (allowUserLoad) {
11230 			result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad);
11231 		}
11232 	}
11233 
11234 	/*
11235 	 * Bundle Dependencies (OSBundleLibraries)
11236 	 */
11237 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) {
11238 		OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey));
11239 		if (libraries) {
11240 			result->setObject(kOSBundleLibrariesKey, libraries);
11241 		}
11242 	}
11243 
11244 	/*****
11245 	 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
11246 	 */
11247 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
11248 		result->setObject(kOSKernelResourceKey,
11249 		    isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
11250 	}
11251 
11252 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
11253 		result->setObject(kOSBundleIsInterfaceKey,
11254 		    isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
11255 	}
11256 
11257 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
11258 		result->setObject(kOSBundlePrelinkedKey,
11259 		    isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
11260 	}
11261 
11262 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
11263 		result->setObject(kOSBundleStartedKey,
11264 		    isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
11265 	}
11266 
11267 	/* LoadTag (Index).
11268 	 */
11269 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
11270 		OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
11271 		    /* numBits */ 8 * sizeof(loadTag));
11272 		if (!scratchNumber) {
11273 			goto finish;
11274 		}
11275 		result->setObject(kOSBundleLoadTagKey, scratchNumber.get());
11276 	}
11277 
11278 	/* LoadAddress, LoadSize.
11279 	 */
11280 	if (!infoKeys ||
11281 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
11282 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
11283 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
11284 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
11285 	    _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
11286 		bool is_dext = isDriverKit();
11287 		if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
11288 			/* These go to userspace via serialization, so we don't want any doubts
11289 			 * about their size.
11290 			 */
11291 			uint64_t    loadAddress     = 0;
11292 			uint32_t    loadSize        = 0;
11293 			uint32_t    wiredSize       = 0;
11294 			uint64_t    execLoadAddress = 0;
11295 			uint32_t    execLoadSize    = 0;
11296 
11297 			/* Interfaces always report 0 load address & size.
11298 			 * Just the way they roll.
11299 			 *
11300 			 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
11301 			 * xxx - shouldn't have one!
11302 			 */
11303 
11304 			if (flags.builtin || linkedExecutable) {
11305 				kernel_mach_header_t     *mh  = NULL;
11306 				kernel_segment_command_t *seg = NULL;
11307 
11308 				if (flags.builtin) {
11309 					loadAddress = kmod_info->address;
11310 					loadSize    = (uint32_t)kmod_info->size;
11311 				} else {
11312 					loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
11313 					loadSize = linkedExecutable->getLength();
11314 				}
11315 				mh = (kernel_mach_header_t *)loadAddress;
11316 				loadAddress = ml_static_unslide(loadAddress);
11317 
11318 				/* Walk through the kext, looking for the first executable
11319 				 * segment in case we were asked for its size/address.
11320 				 */
11321 				for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
11322 					if (seg->initprot & VM_PROT_EXECUTE) {
11323 						execLoadAddress = ml_static_unslide(seg->vmaddr);
11324 						execLoadSize = (uint32_t)seg->vmsize;
11325 						break;
11326 					}
11327 				}
11328 
11329 				/* If we have a kmod_info struct, calculated the wired size
11330 				 * from that. Otherwise it's the full load size.
11331 				 */
11332 				if (kmod_info) {
11333 					wiredSize = loadSize - (uint32_t)kmod_info->hdr_size;
11334 				} else {
11335 					wiredSize = loadSize;
11336 				}
11337 			} else if (is_dext) {
11338 				/*
11339 				 * DriverKit userspace executables do not have a kernel linkedExecutable,
11340 				 * so we "fake" their address range with the LoadTag.
11341 				 */
11342 				if (loadTag) {
11343 					loadAddress = execLoadAddress = loadTag;
11344 					loadSize = execLoadSize = 1;
11345 				}
11346 			}
11347 
11348 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
11349 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11350 					(unsigned long long)(loadAddress),
11351 					/* numBits */ 8 * sizeof(loadAddress));
11352 				if (!scratchNumber) {
11353 					goto finish;
11354 				}
11355 				result->setObject(kOSBundleLoadAddressKey, scratchNumber.get());
11356 			}
11357 			if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) {
11358 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
11359 				    && loadAddress && loadSize) {
11360 					void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary);
11361 					if (!baseAddress) {
11362 						goto finish;
11363 					}
11364 
11365 					OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11366 						(unsigned long long)ml_static_unslide((vm_offset_t)baseAddress),
11367 						/* numBits */ 8 * sizeof(loadAddress));
11368 					if (!scratchNumber) {
11369 						goto finish;
11370 					}
11371 					result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get());
11372 				}
11373 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
11374 				    && (this == sKernelKext) && gBuiltinKmodsCount) {
11375 					result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
11376 				}
11377 			}
11378 
11379 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
11380 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11381 					(unsigned long long)(execLoadAddress),
11382 					/* numBits */ 8 * sizeof(execLoadAddress));
11383 				if (!scratchNumber) {
11384 					goto finish;
11385 				}
11386 				result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get());
11387 			}
11388 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
11389 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11390 					(unsigned long long)(loadSize),
11391 					/* numBits */ 8 * sizeof(loadSize));
11392 				if (!scratchNumber) {
11393 					goto finish;
11394 				}
11395 				result->setObject(kOSBundleLoadSizeKey, scratchNumber.get());
11396 			}
11397 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
11398 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11399 					(unsigned long long)(execLoadSize),
11400 					/* numBits */ 8 * sizeof(execLoadSize));
11401 				if (!scratchNumber) {
11402 					goto finish;
11403 				}
11404 				result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get());
11405 			}
11406 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
11407 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11408 					(unsigned long long)(wiredSize),
11409 					/* numBits */ 8 * sizeof(wiredSize));
11410 				if (!scratchNumber) {
11411 					goto finish;
11412 				}
11413 				result->setObject(kOSBundleWiredSizeKey, scratchNumber.get());
11414 			}
11415 		}
11416 	}
11417 
11418 	/* OSBundleDependencies. In descending order for
11419 	 * easy compatibility with kextstat(8).
11420 	 */
11421 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
11422 		if ((count = getNumDependencies())) {
11423 			dependencyLoadTags = OSArray::withCapacity(count);
11424 			result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get());
11425 
11426 			i = count - 1;
11427 			do {
11428 				OSKext * dependency = OSDynamicCast(OSKext,
11429 				    dependencies->getObject(i));
11430 
11431 				if (!dependency) {
11432 					continue;
11433 				}
11434 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11435 					(unsigned long long)dependency->getLoadTag(),
11436 					/* numBits*/ 8 * sizeof(loadTag));
11437 				if (!scratchNumber) {
11438 					goto finish;
11439 				}
11440 				dependencyLoadTags->setObject(scratchNumber.get());
11441 			} while (i--);
11442 		}
11443 	}
11444 
11445 	/* OSBundleMetaClasses.
11446 	 */
11447 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
11448 		if (metaClasses && metaClasses->getCount()) {
11449 			metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get());
11450 			metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
11451 			if (!metaClassIterator || !metaClassInfo) {
11452 				goto finish;
11453 			}
11454 			result->setObject(kOSBundleClassesKey, metaClassInfo.get());
11455 
11456 			while ((thisMetaClass = OSDynamicCast(OSMetaClass,
11457 			    metaClassIterator->getNextObject()))) {
11458 				metaClassDict = OSDictionary::withCapacity(3);
11459 				if (!metaClassDict) {
11460 					goto finish;
11461 				}
11462 
11463 				metaClassName = OSString::withCString(thisMetaClass->getClassName());
11464 				if (thisMetaClass->getSuperClass()) {
11465 					superclassName = OSString::withCString(
11466 						thisMetaClass->getSuperClass()->getClassName());
11467 				}
11468 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
11469 				    8 * sizeof(unsigned int));
11470 
11471 				/* Bail if any of the essentials is missing. The root class lacks a superclass,
11472 				 * of course.
11473 				 */
11474 				if (!metaClassDict || !metaClassName || !scratchNumber) {
11475 					goto finish;
11476 				}
11477 
11478 				metaClassInfo->setObject(metaClassDict.get());
11479 				metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get());
11480 				if (superclassName) {
11481 					metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get());
11482 				}
11483 				metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get());
11484 			}
11485 		}
11486 	}
11487 
11488 	/* OSBundleRetainCount.
11489 	 */
11490 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
11491 		{
11492 			int kextRetainCount = getRetainCount() - 1;
11493 			if (isLoaded()) {
11494 				kextRetainCount--;
11495 			}
11496 			OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
11497 				(int)kextRetainCount,
11498 				/* numBits*/ 8 * sizeof(int));
11499 			if (scratchNumber) {
11500 				result->setObject(kOSBundleRetainCountKey, scratchNumber.get());
11501 			}
11502 		}
11503 	}
11504 
11505 	success = true;
11506 
11507 finish:
11508 	if (executablePathCString) {
11509 		kfree_data(executablePathCString, executablePathCStringSize);
11510 	}
11511 	if (!success) {
11512 		result.reset();
11513 	}
11514 	return result;
11515 }
11516 
11517 /*********************************************************************
11518 *********************************************************************/
11519 /* static */
11520 bool
11521 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
11522 {
11523 	bool ok;
11524 	OSSharedPtr<OSKext> kext;
11525 
11526 	IORecursiveLockLock(sKextLock);
11527 	kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain);
11528 	IORecursiveLockUnlock(sKextLock);
11529 
11530 	if (!kext || !kext->path || !kext->userExecutableRelPath) {
11531 		return false;
11532 	}
11533 	snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
11534 	    kext->path->getCStringNoCopy(),
11535 	    kext->userExecutableRelPath->getCStringNoCopy());
11536 	ok = true;
11537 
11538 	return ok;
11539 }
11540 
11541 /*********************************************************************
11542 *********************************************************************/
11543 /* static */
11544 OSReturn
11545 OSKext::requestResource(
11546 	const char                    * kextIdentifierCString,
11547 	const char                    * resourceNameCString,
11548 	OSKextRequestResourceCallback   callback,
11549 	void                          * context,
11550 	OSKextRequestTag              * requestTagOut)
11551 {
11552 	OSReturn                        result = kOSReturnError;
11553 	OSSharedPtr<OSKext>             callbackKext;        // looked up
11554 
11555 	OSKextRequestTag   requestTag      = -1;
11556 	OSSharedPtr<OSNumber>           requestTagNum;
11557 	OSSharedPtr<OSDictionary>       requestDict;
11558 	OSSharedPtr<OSString>           kextIdentifier;
11559 	OSSharedPtr<OSString>           resourceName;
11560 
11561 	OSSharedPtr<OSDictionary>       callbackRecord;
11562 	OSSharedPtr<OSValueObject<OSKextRequestResourceCallback> > callbackWrapper;
11563 
11564 	OSSharedPtr<OSValueObject<void *> > contextWrapper;
11565 
11566 	IORecursiveLockLock(sKextLock);
11567 
11568 	if (requestTagOut) {
11569 		*requestTagOut = kOSKextRequestTagInvalid;
11570 	}
11571 
11572 	/* If requests to user space are disabled, don't go any further */
11573 	if (!sKernelRequestsEnabled) {
11574 		OSKextLog(/* kext */ NULL,
11575 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11576 		    "Can't request resource %s for %s - requests to user space are disabled.",
11577 		    resourceNameCString,
11578 		    kextIdentifierCString);
11579 		result = kOSKextReturnDisabled;
11580 		goto finish;
11581 	}
11582 
11583 	if (!kextIdentifierCString || !resourceNameCString || !callback) {
11584 		result = kOSKextReturnInvalidArgument;
11585 		goto finish;
11586 	}
11587 
11588 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
11589 	if (!callbackKext) {
11590 		OSKextLog(/* kext */ NULL,
11591 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11592 		    "Resource request has bad callback address.");
11593 		result = kOSKextReturnInvalidArgument;
11594 		goto finish;
11595 	}
11596 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
11597 		OSKextLog(/* kext */ NULL,
11598 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11599 		    "Resource request callback is in a kext that is not started.");
11600 		result = kOSKextReturnInvalidArgument;
11601 		goto finish;
11602 	}
11603 
11604 	/* Do not allow any new requests to be made on a kext that is unloading.
11605 	 */
11606 	if (callbackKext->flags.stopping) {
11607 		result = kOSKextReturnStopping;
11608 		goto finish;
11609 	}
11610 
11611 	/* If we're wrapped the next available request tag around to the negative
11612 	 * numbers, we can't service any more requests.
11613 	 */
11614 	if (sNextRequestTag == kOSKextRequestTagInvalid) {
11615 		OSKextLog(/* kext */ NULL,
11616 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11617 		    "No more request tags available; restart required.");
11618 		result = kOSKextReturnNoResources;
11619 		goto finish;
11620 	}
11621 	requestTag = sNextRequestTag++;
11622 
11623 	result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
11624 	    requestDict);
11625 	if (result != kOSReturnSuccess) {
11626 		goto finish;
11627 	}
11628 
11629 	kextIdentifier = OSString::withCString(kextIdentifierCString);
11630 	resourceName   = OSString::withCString(resourceNameCString);
11631 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
11632 	    8 * sizeof(requestTag));
11633 	if (!kextIdentifier ||
11634 	    !resourceName ||
11635 	    !requestTagNum ||
11636 	    !_OSKextSetRequestArgument(requestDict.get(),
11637 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) ||
11638 	    !_OSKextSetRequestArgument(requestDict.get(),
11639 	    kKextRequestArgumentNameKey, resourceName.get()) ||
11640 	    !_OSKextSetRequestArgument(requestDict.get(),
11641 	    kKextRequestArgumentRequestTagKey, requestTagNum.get())) {
11642 		result = kOSKextReturnNoMemory;
11643 		goto finish;
11644 	}
11645 
11646 	callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection());
11647 	if (!callbackRecord) {
11648 		result = kOSKextReturnNoMemory;
11649 		goto finish;
11650 	}
11651 	// we validate callback address at call time
11652 	callbackWrapper = OSValueObjectWithValue(callback);
11653 	if (context) {
11654 		contextWrapper = OSValueObjectWithValue(context);
11655 	}
11656 	if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
11657 	    kKextRequestArgumentCallbackKey, callbackWrapper.get())) {
11658 		result = kOSKextReturnNoMemory;
11659 		goto finish;
11660 	}
11661 
11662 	if (context) {
11663 		if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
11664 		    kKextRequestArgumentContextKey, contextWrapper.get())) {
11665 			result = kOSKextReturnNoMemory;
11666 			goto finish;
11667 		}
11668 	}
11669 
11670 	/* Only post the requests after all the other potential failure points
11671 	 * have been passed.
11672 	 */
11673 	if (!sKernelRequests->setObject(requestDict.get()) ||
11674 	    !sRequestCallbackRecords->setObject(callbackRecord.get())) {
11675 		result = kOSKextReturnNoMemory;
11676 		goto finish;
11677 	}
11678 
11679 	OSKext::pingIOKitDaemon();
11680 
11681 	result = kOSReturnSuccess;
11682 	if (requestTagOut) {
11683 		*requestTagOut = requestTag;
11684 	}
11685 
11686 finish:
11687 
11688 	/* If we didn't succeed, yank the request & callback
11689 	 * from their holding arrays.
11690 	 */
11691 	if (result != kOSReturnSuccess) {
11692 		unsigned int index;
11693 
11694 		index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0);
11695 		if (index != (unsigned int)-1) {
11696 			sKernelRequests->removeObject(index);
11697 		}
11698 		index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0);
11699 		if (index != (unsigned int)-1) {
11700 			sRequestCallbackRecords->removeObject(index);
11701 		}
11702 	}
11703 
11704 	OSKext::considerUnloads(/* rescheduleOnly? */ true);
11705 
11706 	IORecursiveLockUnlock(sKextLock);
11707 
11708 	return result;
11709 }
11710 
11711 OSReturn
11712 OSKext::requestDaemonLaunch(
11713 	OSString *kextIdentifier,
11714 	OSString *serverName,
11715 	OSNumber *serverTag,
11716 	IOUserServerCheckInToken * checkInToken)
11717 {
11718 	OSReturn       result        = kOSReturnError;
11719 	OSSharedPtr<OSDictionary> requestDict;
11720 
11721 	if (!kextIdentifier || !serverName || !serverTag || !checkInToken) {
11722 		return kOSKextReturnInvalidArgument;
11723 	}
11724 
11725 	IORecursiveLockLock(sKextLock);
11726 
11727 	OSKextLog(/* kext */ NULL,
11728 	    kOSKextLogDebugLevel |
11729 	    kOSKextLogGeneralFlag,
11730 	    "Requesting daemon launch for %s with serverName %s and tag %llu",
11731 	    kextIdentifier->getCStringNoCopy(),
11732 	    serverName->getCStringNoCopy(),
11733 	    serverTag->unsigned64BitValue()
11734 	    );
11735 
11736 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict);
11737 	if (result != kOSReturnSuccess) {
11738 		goto finish;
11739 	}
11740 
11741 	if (!_OSKextSetRequestArgument(requestDict.get(),
11742 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
11743 	    !_OSKextSetRequestArgument(requestDict.get(),
11744 	    kKextRequestArgumentDriverExtensionServerName, serverName) ||
11745 	    !_OSKextSetRequestArgument(requestDict.get(),
11746 	    kKextRequestArgumentDriverExtensionServerTag, serverTag) ||
11747 	    !_OSKextSetRequestArgument(requestDict.get(),
11748 	    kKextRequestArgumentCheckInToken, checkInToken)) {
11749 		result = kOSKextReturnNoMemory;
11750 		goto finish;
11751 	}
11752 
11753 	/* Only post the requests after all the other potential failure points
11754 	 * have been passed.
11755 	 */
11756 	if (!sKernelRequests->setObject(requestDict.get())) {
11757 		result = kOSKextReturnNoMemory;
11758 		goto finish;
11759 	}
11760 	OSKext::pingIOKitDaemon();
11761 
11762 	result = kOSReturnSuccess;
11763 finish:
11764 	IORecursiveLockUnlock(sKextLock);
11765 	return result;
11766 }
11767 
11768 /*********************************************************************
11769 * Assumes sKextLock is held.
11770 *********************************************************************/
11771 /* static */
11772 OSReturn
11773 OSKext::dequeueCallbackForRequestTag(
11774 	OSKextRequestTag    requestTag,
11775 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
11776 {
11777 	OSDictionary * callbackRecordOutRaw = NULL;
11778 	OSReturn result;
11779 
11780 	result = dequeueCallbackForRequestTag(requestTag,
11781 	    &callbackRecordOutRaw);
11782 
11783 	if (kOSReturnSuccess == result) {
11784 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
11785 	}
11786 
11787 	return result;
11788 }
11789 OSReturn
11790 OSKext::dequeueCallbackForRequestTag(
11791 	OSKextRequestTag    requestTag,
11792 	OSDictionary     ** callbackRecordOut)
11793 {
11794 	OSReturn   result = kOSReturnError;
11795 	OSSharedPtr<OSNumber> requestTagNum;
11796 
11797 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
11798 	    8 * sizeof(requestTag));
11799 	if (!requestTagNum) {
11800 		goto finish;
11801 	}
11802 
11803 	result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(),
11804 	    callbackRecordOut);
11805 
11806 finish:
11807 	return result;
11808 }
11809 
11810 /*********************************************************************
11811 * Assumes sKextLock is held.
11812 *********************************************************************/
11813 /* static */
11814 OSReturn
11815 OSKext::dequeueCallbackForRequestTag(
11816 	OSNumber     *    requestTagNum,
11817 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
11818 {
11819 	OSDictionary * callbackRecordOutRaw = NULL;
11820 	OSReturn result;
11821 
11822 	result = dequeueCallbackForRequestTag(requestTagNum,
11823 	    &callbackRecordOutRaw);
11824 
11825 	if (kOSReturnSuccess == result) {
11826 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
11827 	}
11828 
11829 	return result;
11830 }
11831 OSReturn
11832 OSKext::dequeueCallbackForRequestTag(
11833 	OSNumber     *    requestTagNum,
11834 	OSDictionary ** callbackRecordOut)
11835 {
11836 	OSReturn        result          = kOSKextReturnInvalidArgument;
11837 	OSDictionary  * callbackRecord  = NULL;        // retain if matched!
11838 	OSNumber      * callbackTagNum  = NULL;        // do not release
11839 	unsigned int    count, i;
11840 
11841 	result = kOSReturnError;
11842 	count = sRequestCallbackRecords->getCount();
11843 	for (i = 0; i < count; i++) {
11844 		callbackRecord = OSDynamicCast(OSDictionary,
11845 		    sRequestCallbackRecords->getObject(i));
11846 		if (!callbackRecord) {
11847 			goto finish;
11848 		}
11849 
11850 		/* If we don't find a tag, we basically have a leak here. Maybe
11851 		 * we should just remove it.
11852 		 */
11853 		callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
11854 			    callbackRecord, kKextRequestArgumentRequestTagKey));
11855 		if (!callbackTagNum) {
11856 			goto finish;
11857 		}
11858 
11859 		/* We could be even more paranoid and check that all the incoming
11860 		 * args match what's in the callback record.
11861 		 */
11862 		if (callbackTagNum->isEqualTo(requestTagNum)) {
11863 			if (callbackRecordOut) {
11864 				*callbackRecordOut = callbackRecord;
11865 				callbackRecord->retain();
11866 			}
11867 			sRequestCallbackRecords->removeObject(i);
11868 			result = kOSReturnSuccess;
11869 			goto finish;
11870 		}
11871 	}
11872 	result = kOSKextReturnNotFound;
11873 
11874 finish:
11875 	return result;
11876 }
11877 
11878 
11879 /*********************************************************************
11880 * Busy timeout triage
11881 *********************************************************************/
11882 /* static */
11883 bool
11884 OSKext::pendingIOKitDaemonRequests(void)
11885 {
11886 	return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
11887 }
11888 
11889 extern "C" int vm_enable_driverkit_shared_region;
11890 
11891 /*********************************************************************
11892 * Acquires and releases sKextLock
11893 *
11894 * This function is designed to be called exactly once on boot by
11895 * the IOKit management daemon, kernelmanagerd. It gathers all codeless
11896 * kext and dext personalities, and then attempts to map a System
11897 * (pageable) KC and an Auxiliary (aux) KC.
11898 *
11899 * Even if the pageable or aux KC fail to load - this function will
11900 * not allow a second call. This avoids security issues where
11901 * kernelmanagerd has been compromised or the pageable kc has been
11902 * tampered with and the attacker attempts to re-load a malicious
11903 * variant.
11904 *
11905 * Return: if a KC fails to load the return value will contain:
11906 *         kOSKextReturnKCLoadFailure. If the pageable KC fails,
11907 *         the return value will contain kOSKextReturnKCLoadFailureSystemKC.
11908 *         Similarly, if the aux kc load fails, the return value will
11909 *         contain kOSKextReturnKCLoadFailureAuxKC. The two values
11910 *         compose with each other and with kOSKextReturnKCLoadFailure.
11911 *********************************************************************/
11912 /* static */
11913 OSReturn
11914 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused)
11915 {
11916 	static bool daemon_ready = false;
11917 
11918 	OSReturn ret = kOSKextReturnInvalidArgument;
11919 	OSReturn kcerr = 0;
11920 	bool start_matching = false;
11921 
11922 	bool allow_fileset_load = !daemon_ready;
11923 #if !(defined(__x86_64__) || defined(__i386__))
11924 	/* never allow KCs full of kexts on non-x86 machines */
11925 	allow_fileset_load = false;
11926 #endif
11927 
11928 	/*
11929 	 * Change with 70582300
11930 	 */
11931 #if 0 || !defined(VM_MAPPED_KEXTS)
11932 	/*
11933 	 * On platforms that don't support the SystemKC or a file-backed
11934 	 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter
11935 	 * needs to be queried before we load any codeless kexts or release
11936 	 * any 3rd party kexts to run. On platforms that support a file-backed
11937 	 * AuxKC, this process is done via the kext audit mechanism.
11938 	 */
11939 
11940 	printf("KextLog: waiting for kext receipt to be queried.\n");
11941 	while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) {
11942 		IOSleep(30);
11943 	}
11944 #endif /* !VM_MAPPED_KEXTS */
11945 
11946 	/*
11947 	 * Get the args from the request. Right now we need the file
11948 	 * name for the pageable and the aux kext collection file sets.
11949 	 */
11950 	OSDictionary * requestArgs                = NULL;        // do not release
11951 	OSString     * pageable_filepath          = NULL;        // do not release
11952 	OSString     * aux_filepath               = NULL;        // do not release
11953 	OSArray      * codeless_kexts             = NULL;        // do not release
11954 	OSNumber     * enable_dk_shared_region    = NULL;        // do not release
11955 
11956 	kernel_mach_header_t *akc_mh              = NULL;
11957 
11958 	requestArgs = OSDynamicCast(OSDictionary,
11959 	    requestDict->getObject(kKextRequestArgumentsKey));
11960 
11961 	if (requestArgs == NULL) {
11962 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
11963 		    "KextLog: No arguments in plist for loading fileset kext\n");
11964 		printf("KextLog: No arguments in plist for loading fileset kext\n");
11965 		return ret;
11966 	}
11967 
11968 	ret = kOSKextReturnDisabled;
11969 
11970 	IORecursiveLockLock(sKextLock);
11971 
11972 	if (!sLoadEnabled) {
11973 		OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
11974 		    "KextLog: Kext loading is disabled (attempt to load KCs).");
11975 		IORecursiveLockUnlock(sKextLock);
11976 		return ret;
11977 	}
11978 
11979 	pageable_filepath = OSDynamicCast(OSString,
11980 	    requestArgs->getObject(kKextRequestArgumentPageableKCFilename));
11981 
11982 	if (allow_fileset_load && pageable_filepath != NULL) {
11983 		printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy());
11984 
11985 		ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable);
11986 		if (ret) {
11987 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
11988 			    "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
11989 
11990 			printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
11991 			ret = kOSKextReturnKCLoadFailure;
11992 			kcerr |= kOSKextReturnKCLoadFailureSystemKC;
11993 			goto try_auxkc;
11994 		}
11995 		/*
11996 		 * Even if the AuxKC fails to load, we still want to send
11997 		 * the System KC personalities to the catalog for matching
11998 		 */
11999 		start_matching = true;
12000 	} else if (pageable_filepath != NULL) {
12001 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
12002 		    "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy());
12003 		ret = kOSKextReturnUnsupported;
12004 	}
12005 
12006 try_auxkc:
12007 	akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
12008 	if (akc_mh) {
12009 		/*
12010 		 * If we try to load a deferred AuxKC, then don't ever attempt
12011 		 * a filesystem map of a file
12012 		 */
12013 		allow_fileset_load = false;
12014 
12015 		/*
12016 		 * This function is only called once per boot, so we haven't
12017 		 * yet loaded an AuxKC. If we have registered the AuxKC mach
12018 		 * header, that means that the kext collection has been placed
12019 		 * in memory for us by the booter, and is waiting for us to
12020 		 * process it.  Grab the deferred XML plist of info
12021 		 * dictionaries and add all the kexts.
12022 		 */
12023 		OSSharedPtr<OSObject>  parsedXML;
12024 		OSSharedPtr<OSData>    loaded_kcUUID;
12025 		OSDictionary          *infoDict;
12026 		parsedXML = consumeDeferredKextCollection(KCKindAuxiliary);
12027 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
12028 #if !defined(VM_MAPPED_KEXTS)
12029 		/*
12030 		 * On platforms where we don't dynamically wire-down / page-in
12031 		 * kext memory, we need to maintain the invariant that if the
12032 		 * AuxKC in memory does not contain a kext receipt, then we
12033 		 * should not load any of the kexts.
12034 		 */
12035 		size_t receipt_sz = 0;
12036 		if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) {
12037 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12038 			    "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt");
12039 			ret = kOSKextReturnKCLoadFailure;
12040 			goto try_codeless;
12041 		}
12042 #endif
12043 		if (infoDict) {
12044 			bool added;
12045 			printf("KextLog: Adding kexts from in-memory AuxKC\n");
12046 			added = OSKext::addKextsFromKextCollection(akc_mh, infoDict,
12047 			    kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary);
12048 			if (!loaded_kcUUID) {
12049 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12050 				    "KextLog: WARNING: did not find UUID in deferred Aux KC!");
12051 			} else if (!added) {
12052 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12053 				    "KextLog: WARNING: Failed to load AuxKC from memory.");
12054 			}
12055 			/* only return success if the pageable load (above) was successful */
12056 			if (ret != kOSKextReturnKCLoadFailure) {
12057 				ret = kOSReturnSuccess;
12058 			}
12059 			/* the registration of the AuxKC parsed out the KC's UUID already */
12060 		} else {
12061 			if (daemon_ready) {
12062 				/*
12063 				 * Complain, but don't return an error if this isn't the first time the
12064 				 * IOKit daemon is checking in. If the daemon ever restarts, we will
12065 				 * hit this case because we've already consumed the deferred personalities.
12066 				 * We return success here so that a call to this function from a restarted
12067 				 * daemon with no codeless kexts will succeed.
12068 				 */
12069 				OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
12070 				    "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart");
12071 				if (ret != kOSKextReturnKCLoadFailure) {
12072 					ret = kOSReturnSuccess;
12073 				}
12074 			} else {
12075 				/* this is a real error case */
12076 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12077 				    "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary");
12078 				printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n");
12079 				ret = kOSKextReturnKCLoadFailure;
12080 				kcerr |= kOSKextReturnKCLoadFailureAuxKC;
12081 			}
12082 		}
12083 	}
12084 
12085 	aux_filepath = OSDynamicCast(OSString,
12086 	    requestArgs->getObject(kKextRequestArgumentAuxKCFilename));
12087 	if (allow_fileset_load && aux_filepath != NULL) {
12088 		printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy());
12089 
12090 		ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary);
12091 		if (ret) {
12092 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12093 			    "KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
12094 
12095 			printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
12096 			ret = kOSKextReturnKCLoadFailure;
12097 			kcerr |= kOSKextReturnKCLoadFailureAuxKC;
12098 			goto try_codeless;
12099 		}
12100 		start_matching = true;
12101 	} else if (aux_filepath != NULL) {
12102 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
12103 		    "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy());
12104 		if (ret != kOSKextReturnKCLoadFailure) {
12105 			ret = kOSKextReturnUnsupported;
12106 		}
12107 	}
12108 
12109 try_codeless:
12110 	/*
12111 	 * Load codeless kexts last so that there is no possibilty of a
12112 	 * codeless kext bundle ID preventing a kext in the system KC from
12113 	 * loading
12114 	 */
12115 	codeless_kexts = OSDynamicCast(OSArray,
12116 	    requestArgs->getObject(kKextRequestArgumentCodelessPersonalities));
12117 	if (codeless_kexts != NULL) {
12118 		uint32_t count = codeless_kexts->getCount();
12119 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12120 		    "KextLog: loading %d codeless kexts/dexts", count);
12121 		for (uint32_t i = 0; i < count; i++) {
12122 			OSDictionary *infoDict;
12123 			infoDict = OSDynamicCast(OSDictionary,
12124 			    codeless_kexts->getObject(i));
12125 			if (!infoDict) {
12126 				continue;
12127 			}
12128 			// instantiate a new kext, and don't hold a reference
12129 			// (the kext subsystem will hold one implicitly)
12130 			OSKext::withCodelessInfo(infoDict);
12131 		}
12132 		/* ignore errors that are not KC load failures */
12133 		if (ret != kOSKextReturnKCLoadFailure) {
12134 			ret = kOSReturnSuccess;
12135 		}
12136 		start_matching = true;
12137 	}
12138 
12139 	enable_dk_shared_region = OSDynamicCast(OSNumber,
12140 	    requestArgs->getObject(kKextRequestEnableDriverKitSharedRegionKey));
12141 	if (enable_dk_shared_region != NULL && enable_dk_shared_region->unsigned64BitValue() == 1) {
12142 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12143 		    "KextLog: Enabling DriverKit shared region.");
12144 		vm_enable_driverkit_shared_region = 1;
12145 	}
12146 
12147 	/* send personalities to the IOCatalog once */
12148 	if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) {
12149 		OSKext::sendAllKextPersonalitiesToCatalog(true);
12150 		/*
12151 		 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark
12152 		 * things as active and start all the delayed matching: the
12153 		 * dext and codeless kext personalities should have all been
12154 		 * delivered via this one call.
12155 		 */
12156 		if (!daemon_ready) {
12157 			OSKext::setIOKitDaemonActive();
12158 			OSKext::setDeferredLoadSucceeded(TRUE);
12159 			IOService::iokitDaemonLaunched();
12160 		}
12161 		if (sOSKextWasResetAfterUserspaceReboot) {
12162 			sOSKextWasResetAfterUserspaceReboot = false;
12163 			OSKext::setIOKitDaemonActive();
12164 			IOService::startDeferredMatches();
12165 		}
12166 	}
12167 
12168 	if (ret == kOSKextReturnKCLoadFailure) {
12169 		ret |= kcerr;
12170 	}
12171 
12172 	/*
12173 	 * Only allow this function to attempt to load the pageable and
12174 	 * aux KCs once per boot.
12175 	 */
12176 	daemon_ready = true;
12177 
12178 	IORecursiveLockUnlock(sKextLock);
12179 
12180 	return ret;
12181 }
12182 
12183 OSReturn
12184 OSKext::resetMutableSegments(void)
12185 {
12186 	kernel_segment_command_t *seg = NULL;
12187 	kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
12188 	u_int index = 0;
12189 	OSKextSavedMutableSegment *savedSegment = NULL;
12190 	uintptr_t kext_slide = PE_get_kc_slide(kc_type);
12191 	OSReturn err;
12192 
12193 	if (!savedMutableSegments) {
12194 		OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
12195 		    "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString());
12196 		err = kOSKextReturnInternalError;
12197 		goto finish;
12198 	}
12199 
12200 	for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) {
12201 		if (!segmentIsMutable(seg)) {
12202 			continue;
12203 		}
12204 		uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
12205 		uint64_t vmsize = seg->vmsize;
12206 		err = kOSKextReturnInternalError;
12207 		for (index = 0; index < savedMutableSegments->getCount(); index++) {
12208 			savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index));
12209 			assert(savedSegment);
12210 			if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) {
12211 				OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
12212 				    "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12213 				err = savedSegment->restoreContents(seg);
12214 				if (err != kOSReturnSuccess) {
12215 					panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12216 				}
12217 			}
12218 		}
12219 		if (err != kOSReturnSuccess) {
12220 			panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
12221 		}
12222 	}
12223 	err = kOSReturnSuccess;
12224 finish:
12225 	return err;
12226 }
12227 
12228 
12229 /*********************************************************************
12230 * Assumes sKextLock is held.
12231 *********************************************************************/
12232 /* static */
12233 OSReturn
12234 OSKext::loadKCFileSet(
12235 	const char *filepath,
12236 	kc_kind_t   type)
12237 {
12238 #if VM_MAPPED_KEXTS
12239 	/* we only need to load filesets on systems that support VM_MAPPED kexts */
12240 	OSReturn err;
12241 	struct vnode *vp = NULL;
12242 	void *fileset_control;
12243 	off_t fsize;
12244 	bool pageable = (type == KCKindPageable);
12245 
12246 	if ((pageable && pageableKCloaded) ||
12247 	    (!pageable && auxKCloaded)) {
12248 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12249 		    "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux"));
12250 
12251 		return kOSKextReturnInvalidArgument;
12252 	}
12253 
12254 	/* Do not allow AuxKC to load if Pageable KC is not loaded */
12255 	if (!pageable && !pageableKCloaded) {
12256 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12257 		    "Trying to load the Aux KC without loading the Pageable KC");
12258 		return kOSKextReturnInvalidArgument;
12259 	}
12260 
12261 	fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize);
12262 
12263 	if (fileset_control == NULL) {
12264 		printf("Could not get memory control object for file %s", filepath);
12265 
12266 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12267 		    "Could not get memory control object for file %s", filepath);
12268 		return kOSKextReturnInvalidArgument;
12269 	}
12270 	if (vp == NULL) {
12271 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12272 		    "Could not find vnode for file %s", filepath);
12273 		return kOSKextReturnInvalidArgument;
12274 	}
12275 
12276 	kernel_mach_header_t *mh = NULL;
12277 	uintptr_t slide = 0;
12278 
12279 #if CONFIG_CSR
12280 	/*
12281 	 * When SIP is enabled, the KC we map must be SIP-protected
12282 	 */
12283 	if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) {
12284 		struct vnode_attr va;
12285 		int error;
12286 		VATTR_INIT(&va);
12287 		VATTR_WANTED(&va, va_flags);
12288 		error = vnode_getattr(vp, &va, vfs_context_current());
12289 		if (error) {
12290 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12291 			    "vnode_getattr(%s) failed (error=%d)", filepath, error);
12292 			err = kOSKextReturnInternalError;
12293 			goto finish;
12294 		}
12295 		if (!(va.va_flags & SF_RESTRICTED)) {
12296 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12297 			    "Path to KC '%s' is not SIP-protected", filepath);
12298 			err = kOSKextReturnInvalidArgument;
12299 			goto finish;
12300 		}
12301 	}
12302 #endif
12303 
12304 	err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL);
12305 	if (err) {
12306 		printf("KextLog: mapKCFileSet returned %d\n", err);
12307 
12308 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12309 		    "mapKCFileSet returned %d\n", err);
12310 
12311 		err = kOSKextReturnInvalidArgument;
12312 	}
12313 
12314 #if CONFIG_CSR
12315 finish:
12316 #endif
12317 	/* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */
12318 	assert(vp != NULL);
12319 	if (err == kOSReturnSuccess) {
12320 		PE_set_kc_vp(type, vp);
12321 		if (pageable) {
12322 			pageableKCloaded = true;
12323 		} else {
12324 			auxKCloaded = true;
12325 		}
12326 	} else {
12327 		vnode_put(vp);
12328 	}
12329 
12330 	return err;
12331 #else
12332 	(void)filepath;
12333 	(void)type;
12334 	return kOSKextReturnUnsupported;
12335 #endif // VM_MAPPED_KEXTS
12336 }
12337 
12338 #if defined(__x86_64__) || defined(__i386__)
12339 /*********************************************************************
12340 * Assumes sKextLock is held.
12341 *********************************************************************/
12342 /* static */
12343 OSReturn
12344 OSKext::mapKCFileSet(
12345 	void                 *control,
12346 	vm_size_t            fsize,
12347 	kernel_mach_header_t **mhp,
12348 	off_t                file_offset,
12349 	uintptr_t            *slidep,
12350 	bool                 pageable,
12351 	void                 *map_entry_list)
12352 {
12353 	bool fileset_load = false;
12354 	kern_return_t ret;
12355 	OSReturn err;
12356 	kernel_section_t *infoPlistSection = NULL;
12357 	OSDictionary *infoDict = NULL;
12358 
12359 	OSSharedPtr<OSObject> parsedXML;
12360 	OSSharedPtr<OSString> errorString;
12361 	OSSharedPtr<OSData> loaded_kcUUID;
12362 
12363 	/* Check if initial load for file set */
12364 	if (*mhp == NULL) {
12365 		fileset_load = true;
12366 
12367 		/* Get a page aligned address from kext map to map the file */
12368 		vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize);
12369 		if (pagealigned_addr == 0) {
12370 			return kOSKextReturnNoMemory;
12371 		}
12372 
12373 		*mhp = (kernel_mach_header_t *)pagealigned_addr;
12374 
12375 		/* Allocate memory for bailout mechanism */
12376 		map_entry_list = allocate_kcfileset_map_entry_list();
12377 		if (map_entry_list == NULL) {
12378 			return kOSKextReturnNoMemory;
12379 		}
12380 	}
12381 
12382 	uintptr_t *slideptr = fileset_load ? slidep : NULL;
12383 	err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list);
12384 	/* mhp and slideptr are updated by mapKCTextSegment */
12385 	if (err) {
12386 		if (fileset_load) {
12387 			deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12388 		}
12389 		return err;
12390 	}
12391 
12392 	/* Initialize the kc header globals */
12393 	if (fileset_load) {
12394 		if (pageable) {
12395 			PE_set_kc_header(KCKindPageable, *mhp, *slidep);
12396 		} else {
12397 			PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep);
12398 		}
12399 	}
12400 
12401 	/* Iterate through all the segments and map necessary segments */
12402 	struct load_command *lcp = (struct load_command *) (*mhp + 1);
12403 	for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) {
12404 		vm_map_offset_t start;
12405 		kernel_mach_header_t *k_mh = NULL;
12406 		kernel_segment_command_t * seg = NULL;
12407 		struct fileset_entry_command *fse = NULL;
12408 
12409 		if (lcp->cmd == LC_SEGMENT_KERNEL) {
12410 			seg = (kernel_segment_command_t *)lcp;
12411 			start = ((uintptr_t)(seg->vmaddr)) + *slidep;
12412 		} else if (lcp->cmd == LC_FILESET_ENTRY) {
12413 			fse = (struct fileset_entry_command *)lcp;
12414 			k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep);
12415 
12416 			/* Map the segments of the mach-o binary */
12417 			err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list);
12418 			if (err) {
12419 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12420 				return kOSKextReturnInvalidArgument;
12421 			}
12422 			continue;
12423 		} else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) {
12424 			/* Check if the Aux KC is built pageable style */
12425 			if (!pageable && !fileset_load && !auxKCloaded) {
12426 				resetAuxKCSegmentOnUnload = true;
12427 			}
12428 			continue;
12429 		} else {
12430 			continue;
12431 		}
12432 
12433 		if (fileset_load) {
12434 			if (seg->vmsize == 0) {
12435 				continue;
12436 			}
12437 
12438 			/* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */
12439 			if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 &&
12440 			    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 &&
12441 			    strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 &&
12442 			    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) {
12443 				continue;
12444 			}
12445 		} else {
12446 			if (seg->vmsize == 0) {
12447 				continue;
12448 			}
12449 
12450 			/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
12451 			if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
12452 			    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
12453 			    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
12454 				continue;
12455 			}
12456 		}
12457 
12458 		ret = vm_map_kcfileset_segment(
12459 			&start, seg->vmsize,
12460 			(memory_object_control_t)control, seg->fileoff, seg->maxprot);
12461 
12462 		if (ret != KERN_SUCCESS) {
12463 			if (fileset_load) {
12464 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12465 			}
12466 			return kOSKextReturnInvalidArgument;
12467 		}
12468 		add_kcfileset_map_entry(map_entry_list, start, seg->vmsize);
12469 	}
12470 
12471 	/* Return if regular mach-o */
12472 	if (!fileset_load) {
12473 		return 0;
12474 	}
12475 
12476 	/*
12477 	 * Fixup for the Pageable KC and the Aux KC is done by
12478 	 * i386_slide_kext_collection_mh_addrs, but it differs in
12479 	 * following ways:
12480 	 *
12481 	 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands.
12482 	 * The fixup of kext segments and kext load commands are done at kext
12483 	 * load time by calling i386_slide_individual_kext.
12484 	 *
12485 	 * AuxKC old style: Fixup all the segments and all the load commands.
12486 	 *
12487 	 * AuxKC pageable style: Same as the Pageable KC.
12488 	 */
12489 	bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false));
12490 	ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header);
12491 	if (ret != KERN_SUCCESS) {
12492 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12493 		return kOSKextReturnInvalidArgument;
12494 	}
12495 
12496 	/* Get the prelink info dictionary */
12497 	infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection);
12498 	parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
12499 	if (parsedXML) {
12500 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
12501 	}
12502 
12503 	if (!infoDict) {
12504 		const char *errorCString = "(unknown error)";
12505 
12506 		if (errorString && errorString->getCStringNoCopy()) {
12507 			errorCString = errorString->getCStringNoCopy();
12508 		} else if (parsedXML) {
12509 			errorCString = "not a dictionary";
12510 		}
12511 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12512 		    "Error unserializing kext info plist section: %s.", errorCString);
12513 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12514 		return kOSKextReturnInvalidArgument;
12515 	}
12516 
12517 	/* Validate that the Kext Collection is prelinked to the loaded KC */
12518 	err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary);
12519 	if (err) {
12520 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
12521 		return kOSKextReturnInvalidArgument;
12522 	}
12523 
12524 	/* Set Protection of Segments */
12525 	OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary);
12526 
12527 	OSKext::addKextsFromKextCollection(*mhp,
12528 	    infoDict, kPrelinkTextSegment,
12529 	    loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary);
12530 
12531 	/* Copy in the KC UUID */
12532 	if (!loaded_kcUUID) {
12533 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12534 		    "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux");
12535 	} else if (pageable) {
12536 		pageablekc_uuid_valid = TRUE;
12537 		memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
12538 		uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string);
12539 	} else {
12540 		auxkc_uuid_valid = TRUE;
12541 		memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
12542 		uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
12543 	}
12544 
12545 	deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable);
12546 
12547 	return 0;
12548 }
12549 
12550 /*********************************************************************
12551 * Assumes sKextLock is held.
12552 *********************************************************************/
12553 /* static */
12554 OSReturn
12555 OSKext::mapKCTextSegment(
12556 	void                 *control,
12557 	kernel_mach_header_t **mhp,
12558 	off_t                file_offset,
12559 	uintptr_t            *slidep,
12560 	void                 *map_entry_list)
12561 {
12562 	kern_return_t ret;
12563 	vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t),
12564 	    PAGE_MASK);
12565 	vm_map_offset_t load_command_map_size = 0;
12566 	kernel_mach_header_t *base_mh = *mhp;
12567 
12568 	/* Map the mach header at start of fileset for now (vmaddr = 0) */
12569 	ret = vm_map_kcfileset_segment(
12570 		(vm_map_offset_t *)&base_mh, mach_header_map_size,
12571 		(memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE));
12572 
12573 	if (ret != KERN_SUCCESS) {
12574 		printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret);
12575 
12576 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12577 		    "Failed to map mach header of kc fileset with error %d", ret);
12578 		return kOSKextReturnInvalidArgument;
12579 	}
12580 
12581 	if (slidep) {
12582 		/* Verify that it's an MH_FILESET */
12583 		if (base_mh->filetype != MH_FILESET) {
12584 			printf("Kext Log: mapKCTextSegment mach header filetype"
12585 			    " is not an MH_FILESET, it is %x", base_mh->filetype);
12586 
12587 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12588 			    "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype);
12589 
12590 			/* Unmap the mach header */
12591 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12592 			return kOSKextReturnInvalidArgument;
12593 		}
12594 	}
12595 
12596 	/* Map the remaining pages of load commands */
12597 	if (base_mh->sizeofcmds > mach_header_map_size) {
12598 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
12599 		load_command_map_size = base_mh->sizeofcmds - mach_header_map_size;
12600 
12601 		/* Map the load commands */
12602 		ret = vm_map_kcfileset_segment(
12603 			&load_command_addr, load_command_map_size,
12604 			(memory_object_control_t)control, file_offset + mach_header_map_size,
12605 			(VM_PROT_READ | VM_PROT_WRITE));
12606 
12607 		if (ret != KERN_SUCCESS) {
12608 			printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret);
12609 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12610 			    "Failed to map load commands of kc fileset with error %d", ret);
12611 
12612 			/* Unmap the mach header */
12613 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12614 			return kOSKextReturnInvalidArgument;
12615 		}
12616 	}
12617 
12618 	kernel_segment_command_t *text_seg;
12619 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT);
12620 
12621 	/* Calculate the slide and vm addr of mach header */
12622 	if (slidep) {
12623 		*mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr);
12624 		*slidep = ((uintptr_t)*mhp) - text_seg->vmaddr;
12625 	}
12626 
12627 	/* Cache the text segment size and file offset before unmapping */
12628 	vm_map_offset_t text_segment_size = text_seg->vmsize;
12629 	vm_object_offset_t text_segment_fileoff = text_seg->fileoff;
12630 	vm_prot_t text_maxprot = text_seg->maxprot;
12631 
12632 	/* Unmap the first page and loadcommands and map the text segment */
12633 	ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
12634 	assert(ret == KERN_SUCCESS);
12635 
12636 	if (load_command_map_size) {
12637 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
12638 		ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size);
12639 		assert(ret == KERN_SUCCESS);
12640 	}
12641 
12642 	/* Map the text segment at actual vm addr specified in fileset */
12643 	ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size,
12644 	    (memory_object_control_t)control, text_segment_fileoff, text_maxprot);
12645 	if (ret != KERN_SUCCESS) {
12646 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12647 		    "Failed to map Text segment of kc fileset with error %d", ret);
12648 		return kOSKextReturnInvalidArgument;
12649 	}
12650 
12651 	add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size);
12652 	return 0;
12653 }
12654 
12655 /*********************************************************************
12656 * Assumes sKextLock is held.
12657 *********************************************************************/
12658 /* static */
12659 OSReturn
12660 OSKext::protectKCFileSet(
12661 	kernel_mach_header_t *mh,
12662 	kc_kind_t            type)
12663 {
12664 	vm_map_t                    kext_map        = g_kext_map;
12665 	kernel_segment_command_t  * seg             = NULL;
12666 	vm_map_offset_t             start           = 0;
12667 	vm_map_offset_t             end             = 0;
12668 	OSReturn                    ret             = 0;
12669 
12670 	/* Set VM permissions */
12671 	seg = firstsegfromheader((kernel_mach_header_t *)mh);
12672 	while (seg) {
12673 		start = round_page(seg->vmaddr);
12674 		end = trunc_page(seg->vmaddr + seg->vmsize);
12675 
12676 		/*
12677 		 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS
12678 		 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT
12679 		 * for the Aux KC as well.
12680 		 */
12681 		if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 ||
12682 		    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 ||
12683 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 ||
12684 		    (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload &&
12685 		    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) {
12686 			ret = OSKext_protect((kernel_mach_header_t *)mh,
12687 			    kext_map, start, end, seg->maxprot, TRUE, type);
12688 			if (ret != KERN_SUCCESS) {
12689 				printf("OSKext protect failed with error %d", ret);
12690 				return kOSKextReturnInvalidArgument;
12691 			}
12692 
12693 			ret = OSKext_protect((kernel_mach_header_t *)mh,
12694 			    kext_map, start, end, seg->initprot, FALSE, type);
12695 			if (ret != KERN_SUCCESS) {
12696 				printf("OSKext protect failed with error %d", ret);
12697 				return kOSKextReturnInvalidArgument;
12698 			}
12699 
12700 			ret = OSKext_wire((kernel_mach_header_t *)mh,
12701 			    kext_map, start, end, seg->initprot, FALSE, type);
12702 			if (ret != KERN_SUCCESS) {
12703 				printf("OSKext wire failed with error %d", ret);
12704 				return kOSKextReturnInvalidArgument;
12705 			}
12706 		}
12707 
12708 		seg = nextsegfromheader((kernel_mach_header_t *) mh, seg);
12709 	}
12710 
12711 	return 0;
12712 }
12713 
12714 /*********************************************************************
12715 * Assumes sKextLock is held.
12716 *********************************************************************/
12717 /* static */
12718 void
12719 OSKext::freeKCFileSetcontrol(void)
12720 {
12721 	PE_reset_all_kc_vp();
12722 }
12723 
12724 /*********************************************************************
12725 * Assumes sKextLock is held.
12726 *
12727 * resetKCFileSetSegments: Kext start function expects data segment to
12728 * be pristine on every load, unmap the dirty segments on unload and
12729 * remap them from FileSet on disk. Remap all segments of kext since
12730 * fixups are done per kext and not per segment.
12731 *********************************************************************/
12732 OSReturn
12733 OSKext::resetKCFileSetSegments(void)
12734 {
12735 	kernel_segment_command_t *seg = NULL;
12736 	kernel_segment_command_t *text_seg;
12737 	uint32_t text_fileoff;
12738 	kernel_mach_header_t *k_mh = NULL;
12739 	uintptr_t slide;
12740 	struct vnode *vp = NULL;
12741 	void *fileset_control = NULL;
12742 	bool pageable = (kc_type == KCKindPageable);
12743 	OSReturn err;
12744 	kern_return_t kr;
12745 
12746 	/* Check the vnode reference is still available */
12747 	vp = (struct vnode *)PE_get_kc_vp(kc_type);
12748 	if (vp == NULL) {
12749 		OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
12750 		    "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString());
12751 		return kOSKextReturnInternalError;
12752 	}
12753 
12754 	fileset_control = ubc_getobject(vp, 0);
12755 	assert(fileset_control != NULL);
12756 
12757 	OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
12758 	    "Kext %s resetting all segments", getIdentifierCString());
12759 
12760 	k_mh = (kernel_mach_header_t *)kmod_info->address;
12761 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT);
12762 	text_fileoff = text_seg->fileoff;
12763 	slide = PE_get_kc_slide(kc_type);
12764 
12765 	seg = firstsegfromheader((kernel_mach_header_t *)k_mh);
12766 	while (seg) {
12767 		if (seg->vmsize == 0) {
12768 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12769 			continue;
12770 		}
12771 
12772 		/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
12773 		if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
12774 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
12775 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
12776 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12777 			continue;
12778 		}
12779 
12780 		kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize);
12781 		assert(kr == KERN_SUCCESS);
12782 		seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
12783 	}
12784 
12785 	/* Unmap the text segment */
12786 	kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize);
12787 	assert(kr == KERN_SUCCESS);
12788 
12789 	/* Map all the segments of the kext */
12790 	err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL);
12791 	if (err) {
12792 		panic("Could not reset segments of a mapped kext, error %x", err);
12793 	}
12794 
12795 	/* Update address in kmod_info, since it has been reset */
12796 	if (kmod_info->address) {
12797 		kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide);
12798 	}
12799 
12800 	return 0;
12801 }
12802 
12803 /*********************************************************************
12804 * Mechanism to track all segment mapping while mapping KC fileset.
12805 *********************************************************************/
12806 
12807 struct kcfileset_map_entry {
12808 	vm_map_offset_t me_start;
12809 	vm_map_offset_t me_size;
12810 };
12811 
12812 struct kcfileset_map_entry_list {
12813 	int                        kme_list_count;
12814 	int                        kme_list_index;
12815 	struct kcfileset_map_entry kme_list[];
12816 };
12817 
12818 #define KCFILESET_MAP_ENTRY_MAX (16380)
12819 
12820 static void *
12821 allocate_kcfileset_map_entry_list(void)
12822 {
12823 	struct kcfileset_map_entry_list *entry_list;
12824 
12825 	entry_list = kalloc_type(struct kcfileset_map_entry_list,
12826 	    struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO);
12827 
12828 	entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX;
12829 	entry_list->kme_list_index = 0;
12830 	return entry_list;
12831 }
12832 
12833 static void
12834 add_kcfileset_map_entry(
12835 	void            *map_entry_list,
12836 	vm_map_offset_t start,
12837 	vm_map_offset_t size)
12838 {
12839 	if (map_entry_list == NULL) {
12840 		return;
12841 	}
12842 
12843 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
12844 
12845 	if (entry_list->kme_list_index >= entry_list->kme_list_count) {
12846 		panic("Ran out of map kc fileset list");
12847 	}
12848 
12849 	entry_list->kme_list[entry_list->kme_list_index].me_start = start;
12850 	entry_list->kme_list[entry_list->kme_list_index].me_size = size;
12851 
12852 	entry_list->kme_list_index++;
12853 }
12854 
12855 static void
12856 deallocate_kcfileset_map_entry_list_and_unmap_entries(
12857 	void      *map_entry_list,
12858 	boolean_t unmap_entries,
12859 	bool      pageable)
12860 {
12861 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
12862 
12863 	if (unmap_entries) {
12864 		for (int i = 0; i < entry_list->kme_list_index; i++) {
12865 			kern_return_t ret;
12866 			ret = vm_unmap_kcfileset_segment(
12867 				&(entry_list->kme_list[i].me_start),
12868 				entry_list->kme_list[i].me_size);
12869 			assert(ret == KERN_SUCCESS);
12870 		}
12871 
12872 		PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary);
12873 	}
12874 
12875 	kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry,
12876 	    KCFILESET_MAP_ENTRY_MAX, entry_list);
12877 }
12878 
12879 /*********************************************************************
12880 * Mechanism to map kext segment.
12881 *********************************************************************/
12882 
12883 kern_return_t
12884 vm_map_kcfileset_segment(
12885 	vm_map_offset_t    *start,
12886 	vm_map_offset_t    size,
12887 	void               *control,
12888 	vm_object_offset_t fileoffset,
12889 	vm_prot_t          max_prot)
12890 {
12891 	vm_map_kernel_flags_t vmk_flags = VM_MAP_KERNEL_FLAGS_NONE;
12892 	vmk_flags.vmkf_no_copy_on_read = 1;
12893 	vmk_flags.vmkf_cs_enforcement = 0;
12894 	vmk_flags.vmkf_cs_enforcement_override = 1;
12895 	kern_return_t ret;
12896 
12897 	/* Add Write to max prot to allow fixups */
12898 	max_prot = max_prot | VM_PROT_WRITE;
12899 
12900 	/*
12901 	 * Map the segments from file as COPY mappings to
12902 	 * make sure changes on disk to the file does not affect
12903 	 * mapped segments.
12904 	 */
12905 	ret = vm_map_enter_mem_object_control(
12906 		g_kext_map,
12907 		start,
12908 		size,
12909 		(mach_vm_offset_t)0,
12910 		VM_FLAGS_FIXED,
12911 		vmk_flags,
12912 		VM_KERN_MEMORY_OSKEXT,
12913 		(memory_object_control_t)control,
12914 		fileoffset,
12915 		TRUE,         /* copy */
12916 		(VM_PROT_READ | VM_PROT_WRITE), max_prot,
12917 		VM_INHERIT_NONE);
12918 
12919 	return ret;
12920 }
12921 
12922 kern_return_t
12923 vm_unmap_kcfileset_segment(
12924 	vm_map_offset_t    *start,
12925 	vm_map_offset_t    size)
12926 {
12927 	return mach_vm_deallocate(g_kext_map, *start, size);
12928 }
12929 
12930 #endif //(__x86_64__) || defined(__i386__)
12931 
12932 /*********************************************************************
12933 * Assumes sKextLock is held.
12934 *********************************************************************/
12935 /* static */
12936 OSReturn
12937 OSKext::validateKCFileSetUUID(
12938 	OSDictionary         *infoDict,
12939 	kc_kind_t            type)
12940 {
12941 	OSReturn ret           = kOSReturnSuccess;
12942 
12943 	if (!kernelcache_uuid_valid) {
12944 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12945 		    "validateKCFileSetUUID Boot KC UUID was not set at boot.");
12946 		ret = kOSKextReturnInvalidArgument;
12947 		goto finish;
12948 	}
12949 	ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey);
12950 	if (ret != 0) {
12951 		goto finish;
12952 	}
12953 
12954 #if defined(__x86_64__) || defined(__i386__)
12955 	/* Check if the Aux KC is prelinked to correct Pageable KC */
12956 	if (type == KCKindAuxiliary) {
12957 		if (!pageablekc_uuid_valid) {
12958 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12959 			    "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC.");
12960 			ret = kOSKextReturnInvalidArgument;
12961 			goto finish;
12962 		}
12963 		ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey);
12964 		if (ret != 0) {
12965 			goto finish;
12966 		}
12967 	}
12968 #endif //(__x86_64__) || defined(__i386__)
12969 
12970 	printf("KextLog: Collection UUID matches with loaded KCs.\n");
12971 finish:
12972 	return ret;
12973 }
12974 
12975 /*********************************************************************
12976 * Assumes sKextLock is held.
12977 *********************************************************************/
12978 /* static */
12979 OSReturn
12980 OSKext::validateKCUUIDfromPrelinkInfo(
12981 	uuid_t               *loaded_kcuuid,
12982 	kc_kind_t             type,
12983 	OSDictionary         *infoDict,
12984 	const char           *uuid_key)
12985 {
12986 	/* extract the UUID from the dictionary */
12987 	OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key));
12988 	if (!prelinkinfoKCUUID) {
12989 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12990 		    "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key);
12991 		return kOSKextReturnInvalidArgument;
12992 	}
12993 
12994 	if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) {
12995 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
12996 		    "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength());
12997 		return kOSKextReturnInvalidArgument;
12998 	}
12999 
13000 	if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(),
13001 	    prelinkinfoKCUUID->getLength())) {
13002 		OSData       *info_dict_uuid;
13003 		uuid_string_t info_dict_uuid_str = {};
13004 		uuid_string_t expected_uuid_str = {};
13005 		uuid_string_t given_uuid_str = {};
13006 		uuid_t        given_uuid;
13007 
13008 		/* extract the KC UUID from the dictionary */
13009 		info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
13010 		if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) {
13011 			uuid_t tmp_uuid;
13012 			memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid));
13013 			uuid_unparse(tmp_uuid, info_dict_uuid_str);
13014 		}
13015 
13016 		uuid_unparse(*loaded_kcuuid, expected_uuid_str);
13017 		memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid));
13018 		uuid_unparse(given_uuid, given_uuid_str);
13019 
13020 		printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
13021 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
13022 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13023 		    "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
13024 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
13025 		if (type == KCKindPageable && sPanicOnKCMismatch) {
13026 			panic("System KC UUID %s linked against %s, but %s is loaded",
13027 			    info_dict_uuid_str, given_uuid_str, expected_uuid_str);
13028 		}
13029 		return kOSKextReturnInvalidArgument;
13030 	}
13031 
13032 	return 0;
13033 }
13034 
13035 /*********************************************************************
13036 * Assumes sKextLock is held.
13037 *********************************************************************/
13038 /* static */
13039 OSReturn
13040 OSKext::dispatchResource(OSDictionary * requestDict)
13041 {
13042 	OSReturn                        result          = kOSReturnError;
13043 	OSSharedPtr<OSDictionary>       callbackRecord;
13044 	OSNumber                      * requestTag      = NULL;        // do not release
13045 	OSNumber                      * requestResult   = NULL;        // do not release
13046 	OSData                        * dataObj         = NULL;        // do not release
13047 	uint32_t                        dataLength      = 0;
13048 	const void                    * dataPtr         = NULL;        // do not free
13049 	OSValueObject<OSKextRequestResourceCallback> * callbackWrapper = nullptr; // do not release
13050 	OSKextRequestResourceCallback   callback        = NULL;
13051 	OSValueObject<void *>         * contextWrapper  = nullptr;     // do not release
13052 	void                          * context         = NULL;        // do not free
13053 	OSSharedPtr<OSKext>             callbackKext;
13054 
13055 	/* Get the args from the request. Right now we need the tag
13056 	 * to look up the callback record, and the result for invoking the callback.
13057 	 */
13058 	requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
13059 	    kKextRequestArgumentRequestTagKey));
13060 	requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
13061 	    kKextRequestArgumentResultKey));
13062 	if (!requestTag || !requestResult) {
13063 		result = kOSKextReturnInvalidArgument;
13064 		goto finish;
13065 	}
13066 
13067 	/* Look for a callback record matching this request's tag.
13068 	 */
13069 	result = dequeueCallbackForRequestTag(requestTag, callbackRecord);
13070 	if (result != kOSReturnSuccess) {
13071 		goto finish;
13072 	}
13073 
13074 	/*****
13075 	 * Get the context pointer of the callback record (if there is one).
13076 	 */
13077 	contextWrapper = OSDynamicCast(OSValueObject<void *>, _OSKextGetRequestArgument(
13078 		    callbackRecord.get(), kKextRequestArgumentContextKey));
13079 	context = _OSKextExtractPointer(contextWrapper);
13080 	if (contextWrapper && !context) {
13081 		goto finish;
13082 	}
13083 
13084 	callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
13085 	    _OSKextGetRequestArgument(callbackRecord.get(),
13086 	    kKextRequestArgumentCallbackKey));
13087 	callback = _OSKextExtractCallbackPointer(callbackWrapper);
13088 	if (!callback) {
13089 		goto finish;
13090 	}
13091 
13092 	/* Check for a data obj. We might not have one and that's ok, that means
13093 	 * we didn't find the requested resource, and we still have to tell the
13094 	 * caller that via the callback.
13095 	 */
13096 	dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
13097 	    kKextRequestArgumentValueKey));
13098 	if (dataObj) {
13099 		dataPtr = dataObj->getBytesNoCopy();
13100 		dataLength = dataObj->getLength();
13101 	}
13102 
13103 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
13104 	if (!callbackKext) {
13105 		OSKextLog(/* kext */ NULL,
13106 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13107 		    "Can't invoke callback for resource request; ");
13108 		goto finish;
13109 	}
13110 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
13111 		OSKextLog(/* kext */ NULL,
13112 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13113 		    "Can't invoke kext resource callback; ");
13114 		goto finish;
13115 	}
13116 
13117 	(void)callback(requestTag->unsigned32BitValue(),
13118 	    (OSReturn)requestResult->unsigned32BitValue(),
13119 	    dataPtr, dataLength, context);
13120 
13121 	result = kOSReturnSuccess;
13122 
13123 finish:
13124 	return result;
13125 }
13126 
13127 /*********************************************************************
13128 * Assumes sKextLock is held.
13129 *********************************************************************/
13130 /* static */
13131 OSReturn
13132 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict)
13133 {
13134 	OSSharedPtr<OSDictionary> missingIDs;
13135 	OSArray *bundleIDList     = NULL; // do not release
13136 
13137 	bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
13138 		    requestDict, kKextRequestArgumentMissingBundleIDs));
13139 	if (!bundleIDList) {
13140 		return kOSKextReturnInvalidArgument;
13141 	}
13142 
13143 	missingIDs = OSDictionary::withCapacity(bundleIDList->getCount());
13144 	if (!missingIDs) {
13145 		return kOSKextReturnNoMemory;
13146 	}
13147 
13148 	uint32_t count, i;
13149 	count = bundleIDList->getCount();
13150 	for (i = 0; i < count; i++) {
13151 		OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i));
13152 		if (thisID) {
13153 			missingIDs->setObject(thisID, kOSBooleanFalse);
13154 		}
13155 	}
13156 
13157 	sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain);
13158 
13159 	return kOSReturnSuccess;
13160 }
13161 
13162 /*********************************************************************
13163 * Assumes sKextLock is held.
13164 *********************************************************************/
13165 /* static */
13166 OSReturn
13167 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict)
13168 {
13169 	bool loadable = true;
13170 	if (!kextIdentifier) {
13171 		return kOSKextReturnInvalidArgument;
13172 	}
13173 
13174 	if (requestDict) {
13175 		OSBoolean *loadableArg;
13176 		loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
13177 			    requestDict, kKextRequestArgumentBundleAvailability));
13178 		/* If we find the "Bundle Available" arg, and it's false, then
13179 		 * mark the bundle ID as _not_ loadable
13180 		 */
13181 		if (loadableArg && !loadableArg->getValue()) {
13182 			loadable = false;
13183 		}
13184 	}
13185 
13186 	if (!sNonLoadableKextsByID) {
13187 		sNonLoadableKextsByID = OSDictionary::withCapacity(1);
13188 	}
13189 
13190 	sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable));
13191 
13192 	OSKextLog(/* kext */ NULL,
13193 	    kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13194 	    "KextLog: AuxKC bundle %s marked as %s",
13195 	    kextIdentifier->getCStringNoCopy(),
13196 	    (loadable ? "loadable" : "NOT loadable"));
13197 
13198 	return kOSReturnSuccess;
13199 }
13200 
13201 /*********************************************************************
13202 *********************************************************************/
13203 /* static */
13204 void
13205 OSKext::invokeRequestCallback(
13206 	OSDictionary * callbackRecord,
13207 	OSReturn       callbackResult)
13208 {
13209 	OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
13210 	OSSharedPtr<OSNumber> resultNum;
13211 
13212 	if (!predicate) {
13213 		goto finish;
13214 	}
13215 
13216 	resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
13217 	    8 * sizeof(callbackResult));
13218 	if (!resultNum) {
13219 		goto finish;
13220 	}
13221 
13222 	/* Insert the result into the callback record and dispatch it as if it
13223 	 * were the reply coming down from user space.
13224 	 */
13225 	_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
13226 	    resultNum.get());
13227 
13228 	if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
13229 		/* This removes the pending callback record.
13230 		 */
13231 		OSKext::dispatchResource(callbackRecord);
13232 	}
13233 
13234 finish:
13235 	return;
13236 }
13237 
13238 /*********************************************************************
13239 * Assumes sKextLock is held.
13240 *********************************************************************/
13241 /* static */
13242 OSReturn
13243 OSKext::cancelRequest(
13244 	OSKextRequestTag    requestTag,
13245 	void             ** contextOut)
13246 {
13247 	OSReturn       result         = kOSKextReturnNoMemory;
13248 	OSSharedPtr<OSDictionary> callbackRecord;
13249 	OSValueObject<void *> * contextWrapper = nullptr; // do not release
13250 
13251 	IORecursiveLockLock(sKextLock);
13252 	result = OSKext::dequeueCallbackForRequestTag(requestTag,
13253 	    callbackRecord);
13254 	IORecursiveLockUnlock(sKextLock);
13255 
13256 	if (result == kOSReturnSuccess && contextOut) {
13257 		contextWrapper = OSDynamicCast(OSValueObject<void *>,
13258 		    _OSKextGetRequestArgument(callbackRecord.get(),
13259 		    kKextRequestArgumentContextKey));
13260 		*contextOut = _OSKextExtractPointer(contextWrapper);
13261 	}
13262 
13263 	return result;
13264 }
13265 
13266 /*********************************************************************
13267 * Assumes sKextLock is held.
13268 *********************************************************************/
13269 void
13270 OSKext::invokeOrCancelRequestCallbacks(
13271 	OSReturn callbackResult,
13272 	bool     invokeFlag)
13273 {
13274 	unsigned int count, i;
13275 
13276 	count = sRequestCallbackRecords->getCount();
13277 	if (!count) {
13278 		goto finish;
13279 	}
13280 
13281 	i = count - 1;
13282 	do {
13283 		OSDictionary * request = OSDynamicCast(OSDictionary,
13284 		    sRequestCallbackRecords->getObject(i));
13285 
13286 		if (!request) {
13287 			continue;
13288 		}
13289 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
13290 		    _OSKextGetRequestArgument(request,
13291 		    kKextRequestArgumentCallbackKey));
13292 
13293 		if (!callbackWrapper) {
13294 			sRequestCallbackRecords->removeObject(i);
13295 			continue;
13296 		}
13297 
13298 		vm_address_t callbackAddress = (vm_address_t)
13299 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
13300 
13301 		if ((kmod_info->address <= callbackAddress) &&
13302 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
13303 			if (invokeFlag) {
13304 				/* This removes the callback record.
13305 				 */
13306 				invokeRequestCallback(request, callbackResult);
13307 			} else {
13308 				sRequestCallbackRecords->removeObject(i);
13309 			}
13310 		}
13311 	} while (i--);
13312 
13313 finish:
13314 	return;
13315 }
13316 
13317 /*********************************************************************
13318 * Assumes sKextLock is held.
13319 *********************************************************************/
13320 uint32_t
13321 OSKext::countRequestCallbacks(void)
13322 {
13323 	uint32_t     result = 0;
13324 	unsigned int count, i;
13325 
13326 	count = sRequestCallbackRecords->getCount();
13327 	if (!count) {
13328 		goto finish;
13329 	}
13330 
13331 	i = count - 1;
13332 	do {
13333 		OSDictionary * request = OSDynamicCast(OSDictionary,
13334 		    sRequestCallbackRecords->getObject(i));
13335 
13336 		if (!request) {
13337 			continue;
13338 		}
13339 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
13340 		    _OSKextGetRequestArgument(request,
13341 		    kKextRequestArgumentCallbackKey));
13342 
13343 		if (!callbackWrapper) {
13344 			continue;
13345 		}
13346 
13347 		vm_address_t callbackAddress = (vm_address_t)
13348 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
13349 
13350 		if ((kmod_info->address <= callbackAddress) &&
13351 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
13352 			result++;
13353 		}
13354 	} while (i--);
13355 
13356 finish:
13357 	return result;
13358 }
13359 
13360 /*********************************************************************
13361 *********************************************************************/
13362 static OSReturn
13363 _OSKextCreateRequest(
13364 	const char    * predicate,
13365 	OSSharedPtr<OSDictionary> & requestR)
13366 {
13367 	OSReturn result = kOSKextReturnNoMemory;
13368 	OSSharedPtr<OSDictionary> request;
13369 
13370 	request = OSDictionary::withCapacity(2);
13371 	if (!request) {
13372 		goto finish;
13373 	}
13374 	result = _OSDictionarySetCStringValue(request.get(),
13375 	    kKextRequestPredicateKey, predicate);
13376 	if (result != kOSReturnSuccess) {
13377 		goto finish;
13378 	}
13379 	result = kOSReturnSuccess;
13380 
13381 finish:
13382 	if (result == kOSReturnSuccess) {
13383 		requestR = os::move(request);
13384 	}
13385 
13386 	return result;
13387 }
13388 
13389 /*********************************************************************
13390 *********************************************************************/
13391 static OSString *
13392 _OSKextGetRequestPredicate(OSDictionary * requestDict)
13393 {
13394 	return OSDynamicCast(OSString,
13395 	           requestDict->getObject(kKextRequestPredicateKey));
13396 }
13397 
13398 /*********************************************************************
13399 *********************************************************************/
13400 static OSObject *
13401 _OSKextGetRequestArgument(
13402 	OSDictionary * requestDict,
13403 	const char   * argName)
13404 {
13405 	OSDictionary * args = OSDynamicCast(OSDictionary,
13406 	    requestDict->getObject(kKextRequestArgumentsKey));
13407 	if (args) {
13408 		return args->getObject(argName);
13409 	}
13410 	return NULL;
13411 }
13412 
13413 /*********************************************************************
13414 *********************************************************************/
13415 static bool
13416 _OSKextSetRequestArgument(
13417 	OSDictionary    * requestDict,
13418 	const char      * argName,
13419 	OSMetaClassBase * value)
13420 {
13421 	OSDictionary * args = OSDynamicCast(OSDictionary,
13422 	    requestDict->getObject(kKextRequestArgumentsKey));
13423 	OSSharedPtr<OSDictionary> newArgs;
13424 	if (!args) {
13425 		newArgs = OSDictionary::withCapacity(2);
13426 		args = newArgs.get();
13427 		if (!args) {
13428 			goto finish;
13429 		}
13430 		requestDict->setObject(kKextRequestArgumentsKey, args);
13431 	}
13432 	if (args) {
13433 		return args->setObject(argName, value);
13434 	}
13435 finish:
13436 	return false;
13437 }
13438 
13439 /*********************************************************************
13440 *********************************************************************/
13441 template <typename T>
13442 static T *
13443 _OSKextExtractPointer(OSValueObject<T *> * wrapper)
13444 {
13445 	if (!wrapper) {
13446 		return nullptr;
13447 	}
13448 	return wrapper->getRef();
13449 }
13450 
13451 /*********************************************************************
13452 *********************************************************************/
13453 static OSKextRequestResourceCallback
13454 _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper)
13455 {
13456 	if (!wrapper) {
13457 		return nullptr;
13458 	}
13459 	return wrapper->getRef();
13460 }
13461 
13462 
13463 /*********************************************************************
13464 *********************************************************************/
13465 static OSReturn
13466 _OSDictionarySetCStringValue(
13467 	OSDictionary * dict,
13468 	const char   * cKey,
13469 	const char   * cValue)
13470 {
13471 	OSReturn result = kOSKextReturnNoMemory;
13472 	OSSharedPtr<const OSSymbol> key;
13473 	OSSharedPtr<OSString> value;
13474 
13475 	key = OSSymbol::withCString(cKey);
13476 	value = OSString::withCString(cValue);
13477 	if (!key || !value) {
13478 		goto finish;
13479 	}
13480 	if (dict->setObject(key.get(), value.get())) {
13481 		result = kOSReturnSuccess;
13482 	}
13483 
13484 finish:
13485 	return result;
13486 }
13487 
13488 /*********************************************************************
13489 *********************************************************************/
13490 static bool
13491 _OSArrayContainsCString(
13492 	OSArray    * array,
13493 	const char * cString)
13494 {
13495 	bool             result = false;
13496 	OSSharedPtr<const OSSymbol> symbol;
13497 	uint32_t         count, i;
13498 
13499 	if (!array || !cString) {
13500 		goto finish;
13501 	}
13502 
13503 	symbol = OSSymbol::withCStringNoCopy(cString);
13504 	if (!symbol) {
13505 		goto finish;
13506 	}
13507 
13508 	count = array->getCount();
13509 	for (i = 0; i < count; i++) {
13510 		OSObject * thisObject = array->getObject(i);
13511 		if (symbol->isEqualTo(thisObject)) {
13512 			result = true;
13513 			goto finish;
13514 		}
13515 	}
13516 
13517 finish:
13518 	return result;
13519 }
13520 
13521 #if CONFIG_KXLD
13522 /*********************************************************************
13523 * We really only care about boot / system start up related kexts.
13524 * We return true if we're less than REBUILD_MAX_TIME since start up,
13525 * otherwise return false.
13526 *********************************************************************/
13527 bool
13528 _OSKextInPrelinkRebuildWindow(void)
13529 {
13530 	static bool     outside_the_window = false;
13531 	AbsoluteTime    my_abstime;
13532 	UInt64          my_ns;
13533 	SInt32          my_secs;
13534 
13535 	if (outside_the_window) {
13536 		return false;
13537 	}
13538 	clock_get_uptime(&my_abstime);
13539 	absolutetime_to_nanoseconds(my_abstime, &my_ns);
13540 	my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
13541 	if (my_secs > REBUILD_MAX_TIME) {
13542 		outside_the_window = true;
13543 		return false;
13544 	}
13545 	return true;
13546 }
13547 #endif /* CONFIG_KXLD */
13548 
13549 /*********************************************************************
13550 *********************************************************************/
13551 bool
13552 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
13553 {
13554 	int unLoadedCount, i;
13555 	bool result = false;
13556 
13557 	IORecursiveLockLock(sKextLock);
13558 
13559 	if (sUnloadedPrelinkedKexts == NULL) {
13560 		goto finish;
13561 	}
13562 	unLoadedCount = sUnloadedPrelinkedKexts->getCount();
13563 	if (unLoadedCount == 0) {
13564 		goto finish;
13565 	}
13566 
13567 	for (i = 0; i < unLoadedCount; i++) {
13568 		const OSSymbol *    myBundleID;        // do not release
13569 
13570 		myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
13571 		if (!myBundleID) {
13572 			continue;
13573 		}
13574 		if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
13575 			result = true;
13576 			break;
13577 		}
13578 	}
13579 finish:
13580 	IORecursiveLockUnlock(sKextLock);
13581 	return result;
13582 }
13583 
13584 #if PRAGMA_MARK
13585 #pragma mark Personalities (IOKit Drivers)
13586 #endif
13587 /*********************************************************************
13588 *********************************************************************/
13589 /* static */
13590 OSSharedPtr<OSArray>
13591 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
13592 {
13593 	OSSharedPtr<OSArray>              result;
13594 	OSSharedPtr<OSCollectionIterator> kextIterator;
13595 	OSSharedPtr<OSArray>              personalities;
13596 
13597 	OSString             * kextID                = NULL;        // do not release
13598 	OSKext               * theKext               = NULL;        // do not release
13599 
13600 	IORecursiveLockLock(sKextLock);
13601 
13602 	/* Let's conservatively guess that any given kext has around 3
13603 	 * personalities for now.
13604 	 */
13605 	result = OSArray::withCapacity(sKextsByID->getCount() * 3);
13606 	if (!result) {
13607 		goto finish;
13608 	}
13609 
13610 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
13611 	if (!kextIterator) {
13612 		goto finish;
13613 	}
13614 
13615 	while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
13616 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
13617 		if (theKext->flags.requireExplicitLoad) {
13618 			OSKextLog(theKext,
13619 			    kOSKextLogDebugLevel |
13620 			    kOSKextLogLoadFlag,
13621 			    "Kext %s requires an explicit kextload; "
13622 			    "omitting its personalities.",
13623 			    theKext->getIdentifierCString());
13624 		} else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
13625 			personalities = theKext->copyPersonalitiesArray();
13626 			if (!personalities) {
13627 				continue;
13628 			}
13629 			result->merge(personalities.get());
13630 		} else {
13631 			// xxx - check for better place to put this log msg
13632 			OSKextLog(theKext,
13633 			    kOSKextLogWarningLevel |
13634 			    kOSKextLogLoadFlag,
13635 			    "Kext %s is not loadable during safe boot; "
13636 			    "omitting its personalities.",
13637 			    theKext->getIdentifierCString());
13638 		}
13639 	}
13640 
13641 finish:
13642 	IORecursiveLockUnlock(sKextLock);
13643 
13644 	return result;
13645 }
13646 
13647 /*********************************************************************
13648 *********************************************************************/
13649 /* static */
13650 void
13651 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
13652 {
13653 	int numPersonalities = 0;
13654 
13655 	OSKextLog(/* kext */ NULL,
13656 	    kOSKextLogStepLevel |
13657 	    kOSKextLogLoadFlag,
13658 	    "Sending all eligible registered kexts' personalities "
13659 	    "to the IOCatalogue %s.",
13660 	    startMatching ? "and starting matching" : "but not starting matching");
13661 
13662 	OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities(
13663 		/* filterSafeBootFlag */ true);
13664 
13665 	if (personalities) {
13666 		gIOCatalogue->addDrivers(personalities.get(), startMatching);
13667 		numPersonalities = personalities->getCount();
13668 	}
13669 
13670 	OSKextLog(/* kext */ NULL,
13671 	    kOSKextLogStepLevel |
13672 	    kOSKextLogLoadFlag,
13673 	    "%d kext personalit%s sent to the IOCatalogue; %s.",
13674 	    numPersonalities, numPersonalities > 0 ? "ies" : "y",
13675 	    startMatching ? "matching started" : "matching not started");
13676 	return;
13677 }
13678 
13679 /*********************************************************************
13680 * Do not make a deep copy, just convert the IOKitPersonalities dict
13681 * to an array for sending to the IOCatalogue.
13682 *********************************************************************/
13683 OSSharedPtr<OSArray>
13684 OSKext::copyPersonalitiesArray(void)
13685 {
13686 	OSSharedPtr<OSArray>              result;
13687 	OSDictionary         * personalities               = NULL;        // do not release
13688 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
13689 
13690 	OSString             * personalityName             = NULL;        // do not release
13691 	OSString             * personalityBundleIdentifier = NULL;        // do not release
13692 
13693 	personalities = OSDynamicCast(OSDictionary,
13694 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
13695 	if (!personalities) {
13696 		goto finish;
13697 	}
13698 
13699 	result = OSArray::withCapacity(personalities->getCount());
13700 	if (!result) {
13701 		goto finish;
13702 	}
13703 
13704 	personalitiesIterator =
13705 	    OSCollectionIterator::withCollection(personalities);
13706 	if (!personalitiesIterator) {
13707 		goto finish;
13708 	}
13709 	while ((personalityName = OSDynamicCast(OSString,
13710 	    personalitiesIterator->getNextObject()))) {
13711 		OSDictionary * personality = OSDynamicCast(OSDictionary,
13712 		    personalities->getObject(personalityName));
13713 
13714 		if (personality) {
13715 			/******
13716 			 * If the personality doesn't have a CFBundleIdentifier, or if it
13717 			 * differs from the kext's, insert the kext's ID so we can find it.
13718 			 * The publisher ID is used to remove personalities from bundles
13719 			 * correctly.
13720 			 */
13721 			personalityBundleIdentifier = OSDynamicCast(OSString,
13722 			    personality->getObject(kCFBundleIdentifierKey));
13723 
13724 			if (!personalityBundleIdentifier) {
13725 				personality->setObject(kCFBundleIdentifierKey, bundleID.get());
13726 			} else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) {
13727 				personality->setObject(kIOPersonalityPublisherKey, bundleID.get());
13728 			}
13729 		}
13730 
13731 		result->setObject(personality);
13732 	}
13733 
13734 finish:
13735 	return result;
13736 }
13737 
13738 /*********************************************************************
13739 *   Might want to change this to a bool return?
13740 *********************************************************************/
13741 OSReturn
13742 OSKext::sendPersonalitiesToCatalog(
13743 	bool      startMatching,
13744 	OSArray * personalityNames)
13745 {
13746 	OSReturn       result              = kOSReturnSuccess;
13747 	OSSharedPtr<OSArray> personalitiesToSend;
13748 	OSDictionary * kextPersonalities   = NULL;        // do not release
13749 	int            count, i;
13750 
13751 	if (!sLoadEnabled) {
13752 		OSKextLog(this,
13753 		    kOSKextLogErrorLevel |
13754 		    kOSKextLogLoadFlag,
13755 		    "Kext loading is disabled (attempt to start matching for kext %s).",
13756 		    getIdentifierCString());
13757 		result = kOSKextReturnDisabled;
13758 		goto finish;
13759 	}
13760 
13761 	if (sSafeBoot && !isLoadableInSafeBoot()) {
13762 		OSKextLog(this,
13763 		    kOSKextLogErrorLevel |
13764 		    kOSKextLogLoadFlag,
13765 		    "Kext %s is not loadable during safe boot; "
13766 		    "not sending personalities to the IOCatalogue.",
13767 		    getIdentifierCString());
13768 		result = kOSKextReturnNotLoadable;
13769 		goto finish;
13770 	}
13771 
13772 	if (!personalityNames || !personalityNames->getCount()) {
13773 		personalitiesToSend = copyPersonalitiesArray();
13774 	} else {
13775 		kextPersonalities = OSDynamicCast(OSDictionary,
13776 		    getPropertyForHostArch(kIOKitPersonalitiesKey));
13777 		if (!kextPersonalities || !kextPersonalities->getCount()) {
13778 			// not an error
13779 			goto finish;
13780 		}
13781 		personalitiesToSend = OSArray::withCapacity(0);
13782 		if (!personalitiesToSend) {
13783 			result = kOSKextReturnNoMemory;
13784 			goto finish;
13785 		}
13786 		count = personalityNames->getCount();
13787 		for (i = 0; i < count; i++) {
13788 			OSString * name = OSDynamicCast(OSString,
13789 			    personalityNames->getObject(i));
13790 			if (!name) {
13791 				continue;
13792 			}
13793 			OSDictionary * personality = OSDynamicCast(OSDictionary,
13794 			    kextPersonalities->getObject(name));
13795 			if (personality) {
13796 				personalitiesToSend->setObject(personality);
13797 			}
13798 		}
13799 	}
13800 	if (personalitiesToSend) {
13801 		unsigned numPersonalities = personalitiesToSend->getCount();
13802 		OSKextLog(this,
13803 		    kOSKextLogStepLevel |
13804 		    kOSKextLogLoadFlag,
13805 		    "Kext %s sending %d personalit%s to the IOCatalogue%s.",
13806 		    getIdentifierCString(),
13807 		    numPersonalities,
13808 		    numPersonalities > 1 ? "ies" : "y",
13809 		    startMatching ? " and starting matching" : " but not starting matching");
13810 		gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching);
13811 	}
13812 finish:
13813 	return result;
13814 }
13815 
13816 /*********************************************************************
13817 * xxx - We should allow removing the kext's declared personalities,
13818 * xxx - even with other bundle identifiers.
13819 *********************************************************************/
13820 void
13821 OSKext::removePersonalitiesFromCatalog(void)
13822 {
13823 	OSSharedPtr<OSDictionary> personality;
13824 
13825 	personality = OSDictionary::withCapacity(1);
13826 	if (!personality) {
13827 		goto finish;
13828 	}
13829 	personality->setObject(kCFBundleIdentifierKey, getIdentifier());
13830 
13831 	OSKextLog(this,
13832 	    kOSKextLogStepLevel |
13833 	    kOSKextLogLoadFlag,
13834 	    "Kext %s removing all personalities naming it from the IOCatalogue.",
13835 	    getIdentifierCString());
13836 
13837 	/* Have the IOCatalog remove all personalities matching this kext's
13838 	 * bundle ID and trigger matching anew.
13839 	 */
13840 	gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true);
13841 
13842 finish:
13843 	return;
13844 }
13845 
13846 
13847 #if PRAGMA_MARK
13848 #pragma mark Logging
13849 #endif
13850 /*********************************************************************
13851 * Do not call any function that takes sKextLock here!
13852 *********************************************************************/
13853 /* static */
13854 OSKextLogSpec
13855 OSKext::setUserSpaceLogFilter(
13856 	OSKextLogSpec   newUserLogFilter,
13857 	bool            captureFlag)
13858 {
13859 	OSKextLogSpec result;
13860 	bool          allocError = false;
13861 
13862 	/* Do not call any function that takes sKextLoggingLock during
13863 	 * this critical block. That means do logging after.
13864 	 */
13865 	IOLockLock(sKextLoggingLock);
13866 
13867 	result = sUserSpaceKextLogFilter;
13868 	sUserSpaceKextLogFilter = newUserLogFilter;
13869 
13870 	if (newUserLogFilter && captureFlag &&
13871 	    !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
13872 		// xxx - do some measurements for a good initial capacity?
13873 		sUserSpaceLogSpecArray = OSArray::withCapacity(0);
13874 		sUserSpaceLogMessageArray = OSArray::withCapacity(0);
13875 
13876 		if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
13877 			allocError = true;
13878 		}
13879 	}
13880 
13881 	IOLockUnlock(sKextLoggingLock);
13882 
13883 	/* If the config flag itself is changing, log the state change
13884 	 * going both ways, before setting up the user-space log arrays,
13885 	 * so that this is only logged in the kernel.
13886 	 */
13887 	if (result != newUserLogFilter) {
13888 		OSKextLog(/* kext */ NULL,
13889 		    kOSKextLogDebugLevel |
13890 		    kOSKextLogGeneralFlag,
13891 		    "User-space log flags changed from 0x%x to 0x%x.",
13892 		    result, newUserLogFilter);
13893 	}
13894 	if (allocError) {
13895 		OSKextLog(/* kext */ NULL,
13896 		    kOSKextLogErrorLevel |
13897 		    kOSKextLogGeneralFlag,
13898 		    "Failed to allocate user-space log message arrays.");
13899 	}
13900 
13901 	return result;
13902 }
13903 
13904 /*********************************************************************
13905 * Do not call any function that takes sKextLock here!
13906 *********************************************************************/
13907 /* static */
13908 OSSharedPtr<OSArray>
13909 OSKext::clearUserSpaceLogFilter(void)
13910 {
13911 	OSSharedPtr<OSArray>       result;
13912 	OSKextLogSpec   oldLogFilter;
13913 	OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
13914 
13915 	/* Do not call any function that takes sKextLoggingLock during
13916 	 * this critical block. That means do logging after.
13917 	 */
13918 	IOLockLock(sKextLoggingLock);
13919 
13920 	result = OSArray::withCapacity(2);
13921 	if (result) {
13922 		result->setObject(sUserSpaceLogSpecArray.get());
13923 		result->setObject(sUserSpaceLogMessageArray.get());
13924 	}
13925 	sUserSpaceLogSpecArray.reset();
13926 	sUserSpaceLogMessageArray.reset();
13927 
13928 	oldLogFilter = sUserSpaceKextLogFilter;
13929 	sUserSpaceKextLogFilter = newLogFilter;
13930 
13931 	IOLockUnlock(sKextLoggingLock);
13932 
13933 	/* If the config flag itself is changing, log the state change
13934 	 * going both ways, after tearing down the user-space log
13935 	 * arrays, so this is only logged within the kernel.
13936 	 */
13937 	if (oldLogFilter != newLogFilter) {
13938 		OSKextLog(/* kext */ NULL,
13939 		    kOSKextLogDebugLevel |
13940 		    kOSKextLogGeneralFlag,
13941 		    "User-space log flags changed from 0x%x to 0x%x.",
13942 		    oldLogFilter, newLogFilter);
13943 	}
13944 
13945 	return result;
13946 }
13947 
13948 
13949 /*********************************************************************
13950 * Do not call any function that takes sKextLock here!
13951 *********************************************************************/
13952 /* static */
13953 OSKextLogSpec
13954 OSKext::getUserSpaceLogFilter(void)
13955 {
13956 	OSKextLogSpec result;
13957 
13958 	IOLockLock(sKextLoggingLock);
13959 	result = sUserSpaceKextLogFilter;
13960 	IOLockUnlock(sKextLoggingLock);
13961 
13962 	return result;
13963 }
13964 
13965 /*********************************************************************
13966 * This function is called by OSMetaClass during kernel C++ setup.
13967 * Be careful what you access here; assume only OSKext::initialize()
13968 * has been called.
13969 *
13970 * Do not call any function that takes sKextLock here!
13971 *********************************************************************/
13972 #define VTRESET   "\033[0m"
13973 
13974 #define VTBOLD    "\033[1m"
13975 #define VTUNDER   "\033[4m"
13976 
13977 #define VTRED     "\033[31m"
13978 #define VTGREEN   "\033[32m"
13979 #define VTYELLOW  "\033[33m"
13980 #define VTBLUE    "\033[34m"
13981 #define VTMAGENTA "\033[35m"
13982 #define VTCYAN    "\033[36m"
13983 
13984 inline const char *
13985 colorForFlags(OSKextLogSpec flags)
13986 {
13987 	OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
13988 
13989 	switch (logLevel) {
13990 	case kOSKextLogErrorLevel:
13991 		return VTRED VTBOLD;
13992 	case kOSKextLogWarningLevel:
13993 		return VTRED;
13994 	case kOSKextLogBasicLevel:
13995 		return VTYELLOW VTUNDER;
13996 	case kOSKextLogProgressLevel:
13997 		return VTYELLOW;
13998 	case kOSKextLogStepLevel:
13999 		return VTGREEN;
14000 	case kOSKextLogDetailLevel:
14001 		return VTCYAN;
14002 	case kOSKextLogDebugLevel:
14003 		return VTMAGENTA;
14004 	default:
14005 		return "";         // white
14006 	}
14007 }
14008 
14009 inline bool
14010 logSpecMatch(
14011 	OSKextLogSpec msgLogSpec,
14012 	OSKextLogSpec logFilter)
14013 {
14014 	OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
14015 	OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
14016 	OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
14017 
14018 	OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
14019 	OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
14020 	OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
14021 
14022 	/* Explicit messages always get logged.
14023 	 */
14024 	if (msgLevel == kOSKextLogExplicitLevel) {
14025 		return true;
14026 	}
14027 
14028 	/* Warnings and errors are logged regardless of the flags.
14029 	 */
14030 	if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
14031 		return true;
14032 	}
14033 
14034 	/* A verbose message that isn't for a logging-enabled kext and isn't global
14035 	 * does *not* get logged.
14036 	 */
14037 	if (!msgKextGlobal && !filterKextGlobal) {
14038 		return false;
14039 	}
14040 
14041 	/* Warnings and errors are logged regardless of the flags.
14042 	 * All other messages must fit the flags and
14043 	 * have a level at or below the filter.
14044 	 *
14045 	 */
14046 	if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
14047 		return true;
14048 	}
14049 	return false;
14050 }
14051 
14052 extern "C" {
14053 void
14054 OSKextLog(
14055 	OSKext         * aKext,
14056 	OSKextLogSpec    msgLogSpec,
14057 	const char     * format, ...)
14058 {
14059 	va_list argList;
14060 
14061 	va_start(argList, format);
14062 	OSKextVLog(aKext, msgLogSpec, format, argList);
14063 	va_end(argList);
14064 }
14065 
14066 void
14067 OSKextVLog(
14068 	OSKext         * aKext,
14069 	OSKextLogSpec    msgLogSpec,
14070 	const char     * format,
14071 	va_list          srcArgList)
14072 {
14073 	extern int       disableConsoleOutput;
14074 
14075 	bool             logForKernel       = false;
14076 	bool             logForUser         = false;
14077 	va_list          argList;
14078 	char             stackBuffer[120];
14079 	uint32_t         length            = 0;
14080 	char           * allocBuffer       = NULL;        // must kfree
14081 	OSSharedPtr<OSNumber> logSpecNum;
14082 	OSSharedPtr<OSString> logString;
14083 	char           * buffer            = stackBuffer;        // do not free
14084 
14085 	IOLockLock(sKextLoggingLock);
14086 
14087 	/* Set the kext/global bit in the message spec if we have no
14088 	 * kext or if the kext requests logging.
14089 	 */
14090 	if (!aKext || aKext->flags.loggingEnabled) {
14091 		msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
14092 	}
14093 
14094 	logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
14095 	if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
14096 		logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
14097 	}
14098 
14099 	if (!(logForKernel || logForUser)) {
14100 		goto finish;
14101 	}
14102 
14103 	/* No goto from here until past va_end()!
14104 	 */
14105 	va_copy(argList, srcArgList);
14106 	length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
14107 	va_end(argList);
14108 
14109 	if (length + 1 >= sizeof(stackBuffer)) {
14110 		allocBuffer = (char *)kalloc_data_tag(length + 1,
14111 		    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
14112 		if (!allocBuffer) {
14113 			goto finish;
14114 		}
14115 
14116 		/* No goto from here until past va_end()!
14117 		 */
14118 		va_copy(argList, srcArgList);
14119 		vsnprintf(allocBuffer, length + 1, format, argList);
14120 		va_end(argList);
14121 
14122 		buffer = allocBuffer;
14123 	}
14124 
14125 	/* If user space wants the log message, queue it up.
14126 	 */
14127 	if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
14128 		logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
14129 		logString = OSString::withCString(buffer);
14130 		if (logSpecNum && logString) {
14131 			sUserSpaceLogSpecArray->setObject(logSpecNum.get());
14132 			sUserSpaceLogMessageArray->setObject(logString.get());
14133 		}
14134 	}
14135 
14136 	/* Always log messages from the kernel according to the kernel's
14137 	 * log flags.
14138 	 */
14139 	if (logForKernel) {
14140 		/* If we are in console mode and have a custom log filter,
14141 		 * colorize the log message.
14142 		 */
14143 		if (!disableConsoleOutput && sBootArgLogFilterFound) {
14144 			const char * color = "";         // do not free
14145 			color = colorForFlags(msgLogSpec);
14146 			printf("%s%s%s\n", colorForFlags(msgLogSpec),
14147 			    buffer, color[0] ? VTRESET : "");
14148 		} else {
14149 			printf("%s\n", buffer);
14150 		}
14151 	}
14152 
14153 finish:
14154 	IOLockUnlock(sKextLoggingLock);
14155 
14156 	if (allocBuffer) {
14157 		kfree_data(allocBuffer, length + 1);
14158 	}
14159 	return;
14160 }
14161 
14162 #if KASLR_IOREG_DEBUG
14163 
14164 #define IOLOG_INDENT( the_indention ) \
14165 { \
14166     int     i; \
14167     for ( i = 0; i < (the_indention); i++ ) { \
14168 	IOLog(" "); \
14169     } \
14170 }
14171 
14172 extern vm_offset_t       vm_kernel_stext;
14173 extern vm_offset_t       vm_kernel_etext;
14174 extern mach_vm_offset_t kext_alloc_base;
14175 extern mach_vm_offset_t kext_alloc_max;
14176 
14177 bool ScanForAddrInObject(OSObject * theObject,
14178     int indent );
14179 
14180 bool
14181 ScanForAddrInObject(OSObject * theObject,
14182     int indent)
14183 {
14184 	const OSMetaClass *     myTypeID;
14185 	OSSharedPtr<OSCollectionIterator>  myIter;
14186 	OSSymbol *              myKey;
14187 	OSObject *              myValue;
14188 	bool                    myResult = false;
14189 
14190 	if (theObject == NULL) {
14191 		IOLog("%s: theObject is NULL \n",
14192 		    __FUNCTION__);
14193 		return myResult;
14194 	}
14195 
14196 	myTypeID = OSTypeIDInst(theObject);
14197 
14198 	if (myTypeID == OSTypeID(OSDictionary)) {
14199 		OSDictionary *      myDictionary;
14200 
14201 		myDictionary = OSDynamicCast(OSDictionary, theObject);
14202 		myIter = OSCollectionIterator::withCollection( myDictionary );
14203 		if (myIter == NULL) {
14204 			return myResult;
14205 		}
14206 
14207 		// !! reset the iterator
14208 		myIter->reset();
14209 
14210 		while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
14211 			bool    myTempResult;
14212 
14213 			myValue = myDictionary->getObject(myKey);
14214 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
14215 			if (myTempResult) {
14216 				// if we ever get a true result return true
14217 				myResult = true;
14218 				IOLOG_INDENT(indent);
14219 				IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
14220 			}
14221 		}
14222 
14223 		// !! release the iterator
14224 		myIter.reset();
14225 	} else if (myTypeID == OSTypeID(OSArray)) {
14226 		OSArray *   myArray;
14227 
14228 		myArray = OSDynamicCast(OSArray, theObject);
14229 		myIter = OSCollectionIterator::withCollection(myArray);
14230 		if (myIter == NULL) {
14231 			return myResult;
14232 		}
14233 		// !! reset the iterator
14234 		myIter->reset();
14235 
14236 		while ((myValue = myIter->getNextObject())) {
14237 			bool        myTempResult;
14238 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
14239 			if (myTempResult) {
14240 				// if we ever get a true result return true
14241 				myResult = true;
14242 				IOLOG_INDENT(indent);
14243 				IOLog("OSArray: \n");
14244 			}
14245 		}
14246 		// !! release the iterator
14247 		myIter.reset();
14248 	} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
14249 		// should we look for addresses in strings?
14250 	} else if (myTypeID == OSTypeID(OSData)) {
14251 		void * *        myPtrPtr;
14252 		unsigned int    myLen;
14253 		OSData *        myDataObj;
14254 
14255 		myDataObj =    OSDynamicCast(OSData, theObject);
14256 		myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
14257 		myLen = myDataObj->getLength();
14258 
14259 		if (myPtrPtr && myLen && myLen > 7) {
14260 			int     i;
14261 			int     myPtrCount = (myLen / sizeof(void *));
14262 
14263 			for (i = 0; i < myPtrCount; i++) {
14264 				UInt64 numberValue = (UInt64) * (myPtrPtr);
14265 
14266 				if (kext_alloc_max != 0 &&
14267 				    numberValue >= kext_alloc_base &&
14268 				    numberValue < kext_alloc_max) {
14269 					OSSharedPtr<OSKext> myKext;
14270 					// IOLog("found OSData %p in kext map %p to %p  \n",
14271 					//       *(myPtrPtr),
14272 					//       (void *) kext_alloc_base,
14273 					//       (void *) kext_alloc_max);
14274 
14275 					myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
14276 					if (myKext) {
14277 						IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
14278 						    *(myPtrPtr),
14279 						    myKext->getIdentifierCString());
14280 					}
14281 					myResult = true;
14282 				}
14283 				if (vm_kernel_etext != 0 &&
14284 				    numberValue >= vm_kernel_stext &&
14285 				    numberValue < vm_kernel_etext) {
14286 					IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
14287 					    *(myPtrPtr),
14288 					    (void *) vm_kernel_stext,
14289 					    (void *) vm_kernel_etext);
14290 					myResult = true;
14291 				}
14292 				myPtrPtr++;
14293 			}
14294 		}
14295 	} else if (myTypeID == OSTypeID(OSBoolean)) {
14296 		// do nothing here...
14297 	} else if (myTypeID == OSTypeID(OSNumber)) {
14298 		OSNumber * number = OSDynamicCast(OSNumber, theObject);
14299 
14300 		UInt64 numberValue = number->unsigned64BitValue();
14301 
14302 		if (kext_alloc_max != 0 &&
14303 		    numberValue >= kext_alloc_base &&
14304 		    numberValue < kext_alloc_max) {
14305 			OSSharedPtr<OSKext> myKext;
14306 			IOLog("found OSNumber in kext map %p to %p  \n",
14307 			    (void *) kext_alloc_base,
14308 			    (void *) kext_alloc_max);
14309 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
14310 
14311 			myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
14312 			if (myKext) {
14313 				IOLog("found in kext \"%s\"  \n",
14314 				    myKext->getIdentifierCString());
14315 			}
14316 
14317 			myResult = true;
14318 		}
14319 		if (vm_kernel_etext != 0 &&
14320 		    numberValue >= vm_kernel_stext &&
14321 		    numberValue < vm_kernel_etext) {
14322 			IOLog("found OSNumber in kernel text segment %p to %p  \n",
14323 			    (void *) vm_kernel_stext,
14324 			    (void *) vm_kernel_etext);
14325 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
14326 			myResult = true;
14327 		}
14328 	}
14329 #if 0
14330 	else {
14331 		const OSMetaClass* myMetaClass = NULL;
14332 
14333 		myMetaClass = theObject->getMetaClass();
14334 		if (myMetaClass) {
14335 			IOLog("class %s \n", myMetaClass->getClassName());
14336 		} else {
14337 			IOLog("Unknown object \n" );
14338 		}
14339 	}
14340 #endif
14341 
14342 	return myResult;
14343 }
14344 #endif // KASLR_KEXT_DEBUG
14345 };         /* extern "C" */
14346 
14347 #if PRAGMA_MARK
14348 #pragma mark Backtrace Dump & kmod_get_info() support
14349 #endif
14350 /*********************************************************************
14351 * This function must be safe to call in panic context.
14352 *********************************************************************/
14353 /* static */
14354 void
14355 OSKext::printKextsInBacktrace(
14356 	vm_offset_t  * addr __unused,
14357 	unsigned int   cnt __unused,
14358 	int         (* printf_func)(const char *fmt, ...) __unused,
14359 	uint32_t       flags __unused)
14360 {
14361 	addr64_t    summary_page = 0;
14362 	addr64_t    last_summary_page = 0;
14363 	bool        found_kmod = false;
14364 	u_int       i = 0;
14365 
14366 	if (kPrintKextsLock & flags) {
14367 		if (!sKextSummariesLock) {
14368 			return;
14369 		}
14370 		IOLockLock(sKextSummariesLock);
14371 	}
14372 
14373 	if (!gLoadedKextSummaries) {
14374 		(*printf_func)("         can't perform kext scan: no kext summary");
14375 		goto finish;
14376 	}
14377 
14378 	summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
14379 	last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
14380 	for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
14381 		if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
14382 			(*printf_func)("         can't perform kext scan: "
14383 			    "missing kext summary page %p", summary_page);
14384 			goto finish;
14385 		}
14386 	}
14387 
14388 	for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14389 		OSKextLoadedKextSummary * summary;
14390 
14391 		summary = gLoadedKextSummaries->summaries + i;
14392 		if (!summary->address) {
14393 			continue;
14394 		}
14395 
14396 		if (!summaryIsInBacktrace(summary, addr, cnt)) {
14397 			continue;
14398 		}
14399 
14400 		if (!found_kmod) {
14401 			if (!(kPrintKextsTerse & flags)) {
14402 				(*printf_func)("      Kernel Extensions in backtrace:\n");
14403 			}
14404 			found_kmod = true;
14405 		}
14406 
14407 		printSummary(summary, printf_func, flags);
14408 	}
14409 
14410 finish:
14411 	if (kPrintKextsLock & flags) {
14412 		IOLockUnlock(sKextSummariesLock);
14413 	}
14414 
14415 	return;
14416 }
14417 
14418 /*********************************************************************
14419 * This function must be safe to call in panic context.
14420 *********************************************************************/
14421 /* static */
14422 boolean_t
14423 OSKext::summaryIsInBacktrace(
14424 	OSKextLoadedKextSummary   * summary,
14425 	vm_offset_t               * addr,
14426 	unsigned int                cnt)
14427 {
14428 	u_int i = 0;
14429 
14430 	for (i = 0; i < cnt; i++) {
14431 		vm_offset_t kscan_addr = addr[i];
14432 #if  __has_feature(ptrauth_calls)
14433 		kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr);
14434 #endif /*  __has_feature(ptrauth_calls) */
14435 		if ((kscan_addr >= summary->text_exec_address) &&
14436 		    (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) {
14437 			return TRUE;
14438 		}
14439 	}
14440 
14441 	return FALSE;
14442 }
14443 
14444 /*
14445  * Get the kext summary object for the kext where 'addr' lies. Must be called with
14446  * sKextSummariesLock held.
14447  */
14448 OSKextLoadedKextSummary *
14449 OSKext::summaryForAddress(uintptr_t addr)
14450 {
14451 #if  __has_feature(ptrauth_calls)
14452 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
14453 #endif /*  __has_feature(ptrauth_calls) */
14454 	for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14455 		OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
14456 		if (!summary->address) {
14457 			continue;
14458 		}
14459 
14460 #if VM_MAPPED_KEXTS
14461 		/* On our platforms that use VM_MAPPED_KEXTS, we currently do not
14462 		 * support split kexts, but we also may unmap the kexts, which can
14463 		 * race with the above codepath (see OSKext::unload).  As such,
14464 		 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
14465 		 */
14466 		if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
14467 			return summary;
14468 		}
14469 #else
14470 		kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
14471 		kernel_segment_command_t *seg;
14472 
14473 		for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
14474 			if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
14475 				return summary;
14476 			}
14477 		}
14478 #endif
14479 	}
14480 
14481 	/* addr did not map to any kext */
14482 	return NULL;
14483 }
14484 
14485 /* static */
14486 void *
14487 OSKext::kextForAddress(const void *address)
14488 {
14489 	void                * image = NULL;
14490 	OSKextActiveAccount * active;
14491 	OSKext              * kext = NULL;
14492 	uint32_t              baseIdx;
14493 	uint32_t              lim;
14494 	uintptr_t             addr = (uintptr_t) address;
14495 	size_t                i;
14496 
14497 	if (!addr) {
14498 		return NULL;
14499 	}
14500 #if  __has_feature(ptrauth_calls)
14501 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
14502 #endif /*  __has_feature(ptrauth_calls) */
14503 
14504 	if (sKextAccountsCount) {
14505 		IOSimpleLockLock(sKextAccountsLock);
14506 		// bsearch sKextAccounts list
14507 		for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
14508 			active = &sKextAccounts[baseIdx + (lim >> 1)];
14509 			if ((addr >= active->address) && (addr < active->address_end)) {
14510 				kext = active->account->kext;
14511 				if (kext && kext->kmod_info) {
14512 					image = (void *) kext->kmod_info->address;
14513 				}
14514 				break;
14515 			} else if (addr > active->address) {
14516 				// move right
14517 				baseIdx += (lim >> 1) + 1;
14518 				lim--;
14519 			}
14520 			// else move left
14521 		}
14522 		IOSimpleLockUnlock(sKextAccountsLock);
14523 	}
14524 	if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) {
14525 		image = (void *) &_mh_execute_header;
14526 	}
14527 	if (!image && gLoadedKextSummaries) {
14528 		IOLockLock(sKextSummariesLock);
14529 		for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) {
14530 			OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
14531 			if (addr >= summary->address && addr < summary->address + summary->size) {
14532 				image = (void *)summary->address;
14533 			}
14534 		}
14535 		IOLockUnlock(sKextSummariesLock);
14536 	}
14537 
14538 	return image;
14539 }
14540 
14541 /*
14542  * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t *
14543  * Safe to call in panic context.
14544  */
14545 static OSKextLoadedKextSummary *
14546 findSummary(uint32_t tagID)
14547 {
14548 	OSKextLoadedKextSummary * summary;
14549 	for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
14550 		summary = gLoadedKextSummaries->summaries + i;
14551 		if (summary->loadTag == tagID) {
14552 			return summary;
14553 		}
14554 	}
14555 	return NULL;
14556 }
14557 
14558 /*********************************************************************
14559 * This function must be safe to call in panic context.
14560 *********************************************************************/
14561 void
14562 OSKext::printSummary(
14563 	OSKextLoadedKextSummary * summary,
14564 	int                    (* printf_func)(const char *fmt, ...),
14565 	uint32_t                  flags)
14566 {
14567 	kmod_reference_t * kmod_ref = NULL;
14568 	uuid_string_t uuid;
14569 	char version[kOSKextVersionMaxLength];
14570 	uint64_t tmpAddr;
14571 	uint64_t tmpSize;
14572 	OSKextLoadedKextSummary *dependencySummary;
14573 
14574 	if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
14575 		strlcpy(version, "unknown version", sizeof(version));
14576 	}
14577 	(void) uuid_unparse(summary->uuid, uuid);
14578 
14579 #if defined(__arm__) || defined(__arm64__)
14580 	tmpAddr = summary->text_exec_address;
14581 	tmpSize = summary->text_exec_size;
14582 #else
14583 	tmpAddr = summary->address;
14584 	tmpSize = summary->size;
14585 #endif
14586 	if (kPrintKextsUnslide & flags) {
14587 		tmpAddr = ml_static_unslide(tmpAddr);
14588 	}
14589 	(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
14590 	    (kPrintKextsTerse & flags) ? "" : "         ",
14591 	    summary->name, version, uuid,
14592 	    tmpAddr, tmpAddr + tmpSize - 1);
14593 
14594 	if (kPrintKextsTerse & flags) {
14595 		return;
14596 	}
14597 
14598 	/* print dependency info */
14599 	for (kmod_ref = (kmod_reference_t *) summary->reference_list;
14600 	    kmod_ref;
14601 	    kmod_ref = kmod_ref->next) {
14602 		kmod_info_t * rinfo;
14603 
14604 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
14605 			(*printf_func)("            kmod dependency scan stopped "
14606 			    "due to missing dependency page: %p\n",
14607 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
14608 			break;
14609 		}
14610 		rinfo = kmod_ref->info;
14611 
14612 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
14613 			(*printf_func)("            kmod dependency scan stopped "
14614 			    "due to missing kmod page: %p\n",
14615 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
14616 			break;
14617 		}
14618 
14619 		if (!rinfo->address) {
14620 			continue;         // skip fake entries for built-ins
14621 		}
14622 
14623 		dependencySummary = findSummary(rinfo->id);
14624 		uuid[0] = 0x00;
14625 		tmpAddr = rinfo->address;
14626 		tmpSize = rinfo->size;
14627 		if (dependencySummary) {
14628 			(void) uuid_unparse(dependencySummary->uuid, uuid);
14629 #if defined(__arm__) || defined(__arm64__)
14630 			tmpAddr = dependencySummary->text_exec_address;
14631 			tmpSize = dependencySummary->text_exec_size;
14632 #endif
14633 		}
14634 
14635 		if (kPrintKextsUnslide & flags) {
14636 			tmpAddr = ml_static_unslide(tmpAddr);
14637 		}
14638 		(*printf_func)("            dependency: %s(%s)[%s]@%p->%p\n",
14639 		    rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1);
14640 	}
14641 	return;
14642 }
14643 
14644 
14645 #if !defined(__arm__) && !defined(__arm64__)
14646 /*******************************************************************************
14647 * substitute() looks at an input string (a pointer within a larger buffer)
14648 * for a match to a substring, and on match it writes the marker & substitution
14649 * character to an output string, updating the scan (from) and
14650 * output (to) indexes as appropriate.
14651 *******************************************************************************/
14652 static int substitute(
14653 	const char * scan_string,
14654 	char       * string_out,
14655 	uint32_t   * to_index,
14656 	uint32_t   * from_index,
14657 	const char * substring,
14658 	char         marker,
14659 	char         substitution);
14660 
14661 /* string_out must be at least KMOD_MAX_NAME bytes.
14662  */
14663 static int
14664 substitute(
14665 	const char * scan_string,
14666 	char       * string_out,
14667 	uint32_t   * to_index,
14668 	uint32_t   * from_index,
14669 	const char * substring,
14670 	char         marker,
14671 	char         substitution)
14672 {
14673 	size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
14674 
14675 	/* On a substring match, append the marker (if there is one) and then
14676 	 * the substitution character, updating the output (to) index accordingly.
14677 	 * Then update the input (from) length by the length of the substring
14678 	 * that got replaced.
14679 	 */
14680 	if (!strncmp(scan_string, substring, substring_length)) {
14681 		if (marker) {
14682 			string_out[(*to_index)++] = marker;
14683 		}
14684 		string_out[(*to_index)++] = substitution;
14685 		(*from_index) += substring_length;
14686 		return 1;
14687 	}
14688 	return 0;
14689 }
14690 
14691 /*******************************************************************************
14692 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
14693 * KMOD_MAX_NAME characters and performs various substitutions of common
14694 * prefixes & substrings as defined by tables in kext_panic_report.h.
14695 *******************************************************************************/
14696 static void compactIdentifier(
14697 	const char * identifier,
14698 	char       * identifier_out,
14699 	char      ** identifier_out_end);
14700 
14701 static void
14702 compactIdentifier(
14703 	const char * identifier,
14704 	char       * identifier_out,
14705 	char      ** identifier_out_end)
14706 {
14707 	uint32_t       from_index, to_index;
14708 	uint32_t       scan_from_index = 0;
14709 	uint32_t       scan_to_index   = 0;
14710 	subs_entry_t * subs_entry    = NULL;
14711 	int            did_sub       = 0;
14712 
14713 	from_index = to_index = 0;
14714 	identifier_out[0] = '\0';
14715 
14716 	/* Replace certain identifier prefixes with shorter @+character sequences.
14717 	 * Check the return value of substitute() so we only replace the prefix.
14718 	 */
14719 	for (subs_entry = &kext_identifier_prefix_subs[0];
14720 	    subs_entry->substring && !did_sub;
14721 	    subs_entry++) {
14722 		did_sub = substitute(identifier, identifier_out,
14723 		    &scan_to_index, &scan_from_index,
14724 		    subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
14725 	}
14726 	did_sub = 0;
14727 
14728 	/* Now scan through the identifier looking for the common substrings
14729 	 * and replacing them with shorter !+character sequences via substitute().
14730 	 */
14731 	for (/* see above */;
14732 	    scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
14733 	    /* see loop */) {
14734 		const char   * scan_string = &identifier[scan_from_index];
14735 
14736 		did_sub = 0;
14737 
14738 		if (scan_from_index) {
14739 			for (subs_entry = &kext_identifier_substring_subs[0];
14740 			    subs_entry->substring && !did_sub;
14741 			    subs_entry++) {
14742 				did_sub = substitute(scan_string, identifier_out,
14743 				    &scan_to_index, &scan_from_index,
14744 				    subs_entry->substring, '!', subs_entry->substitute);
14745 			}
14746 		}
14747 
14748 		/* If we didn't substitute, copy the input character to the output.
14749 		 */
14750 		if (!did_sub) {
14751 			identifier_out[scan_to_index++] = identifier[scan_from_index++];
14752 		}
14753 	}
14754 
14755 	identifier_out[scan_to_index] = '\0';
14756 	if (identifier_out_end) {
14757 		*identifier_out_end = &identifier_out[scan_to_index];
14758 	}
14759 
14760 	return;
14761 }
14762 #endif /* !defined(__arm__) && !defined(__arm64__) */
14763 
14764 /*******************************************************************************
14765 * assemble_identifier_and_version() adds to a string buffer a compacted
14766 * bundle identifier followed by a version string.
14767 *******************************************************************************/
14768 
14769 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
14770  */
14771 static size_t assemble_identifier_and_version(
14772 	kmod_info_t * kmod_info,
14773 	char        * identPlusVers,
14774 	size_t        bufSize);
14775 
14776 static size_t
14777 assemble_identifier_and_version(
14778 	kmod_info_t * kmod_info,
14779 	char        * identPlusVers,
14780 	size_t        bufSize)
14781 {
14782 	size_t result = 0;
14783 
14784 #if defined(__arm__) || defined(__arm64__)
14785 	result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME);
14786 #else
14787 	compactIdentifier(kmod_info->name, identPlusVers, NULL);
14788 	result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
14789 #endif
14790 	identPlusVers[result++] = '\t';         // increment for real char
14791 	identPlusVers[result] = '\0';         // don't increment for nul char
14792 	result = strlcat(identPlusVers, kmod_info->version, bufSize);
14793 	if (result >= bufSize) {
14794 		identPlusVers[bufSize - 1] = '\0';
14795 		result = bufSize - 1;
14796 	}
14797 
14798 	return result;
14799 }
14800 
14801 /*******************************************************************************
14802 * Assumes sKextLock is held.
14803 *******************************************************************************/
14804 /* static */
14805 int
14806 OSKext::saveLoadedKextPanicListTyped(
14807 	const char * prefix,
14808 	int          invertFlag,
14809 	int          libsFlag,
14810 	char       * paniclist,
14811 	uint32_t     list_size)
14812 {
14813 	int             result = -1;
14814 	unsigned int    count, i;
14815 
14816 	count = sLoadedKexts->getCount();
14817 	if (!count) {
14818 		goto finish;
14819 	}
14820 
14821 	i = count - 1;
14822 	do {
14823 		OSObject    * rawKext = sLoadedKexts->getObject(i);
14824 		OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
14825 		int           match;
14826 		size_t        identPlusVersLength;
14827 		size_t        tempLen;
14828 		char          identPlusVers[2 * KMOD_MAX_NAME];
14829 
14830 		if (!rawKext) {
14831 			printf("OSKext::saveLoadedKextPanicListTyped - "
14832 			    "NULL kext in loaded kext list; continuing\n");
14833 			continue;
14834 		}
14835 
14836 		if (!theKext) {
14837 			printf("OSKext::saveLoadedKextPanicListTyped - "
14838 			    "Kext type cast failed in loaded kext list; continuing\n");
14839 			continue;
14840 		}
14841 
14842 		/* Skip all built-in kexts.
14843 		 */
14844 		if (theKext->isKernelComponent()) {
14845 			continue;
14846 		}
14847 
14848 		kmod_info_t * kmod_info = theKext->kmod_info;
14849 
14850 		/* Filter for kmod name (bundle identifier).
14851 		 */
14852 		match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
14853 		if ((match && invertFlag) || (!match && !invertFlag)) {
14854 			continue;
14855 		}
14856 
14857 		/* Filter for libraries (kexts that have a compatible version).
14858 		 */
14859 		if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
14860 		    (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
14861 			continue;
14862 		}
14863 
14864 		if (!kmod_info ||
14865 		    !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
14866 			printf("kext scan stopped due to missing kmod_info page: %p\n",
14867 			    kmod_info);
14868 			goto finish;
14869 		}
14870 
14871 		identPlusVersLength = assemble_identifier_and_version(kmod_info,
14872 		    identPlusVers,
14873 		    sizeof(identPlusVers));
14874 		if (!identPlusVersLength) {
14875 			printf("error saving loaded kext info\n");
14876 			goto finish;
14877 		}
14878 
14879 		/* make sure everything fits and we null terminate.
14880 		 */
14881 		tempLen = strlcat(paniclist, identPlusVers, list_size);
14882 		if (tempLen >= list_size) {
14883 			// panic list is full, keep it and null terminate
14884 			paniclist[list_size - 1] = 0x00;
14885 			result = 0;
14886 			goto finish;
14887 		}
14888 		tempLen = strlcat(paniclist, "\n", list_size);
14889 		if (tempLen >= list_size) {
14890 			// panic list is full, keep it and null terminate
14891 			paniclist[list_size - 1] = 0x00;
14892 			result = 0;
14893 			goto finish;
14894 		}
14895 	} while (i--);
14896 
14897 	result = 0;
14898 finish:
14899 
14900 	return result;
14901 }
14902 
14903 /*********************************************************************
14904 *********************************************************************/
14905 /* static */
14906 void
14907 OSKext::saveLoadedKextPanicList(void)
14908 {
14909 	char     * newlist        = NULL;
14910 	uint32_t   newlist_size   = 0;
14911 
14912 	newlist_size = KEXT_PANICLIST_SIZE;
14913 	newlist = (char *)kalloc_data_tag(newlist_size,
14914 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
14915 
14916 	if (!newlist) {
14917 		OSKextLog(/* kext */ NULL,
14918 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
14919 		    "Couldn't allocate kext panic log buffer.");
14920 		goto finish;
14921 	}
14922 
14923 	newlist[0] = '\0';
14924 
14925 	// non-"com.apple." kexts
14926 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
14927 	    /* libs? */ -1, newlist, newlist_size) != 0) {
14928 		goto finish;
14929 	}
14930 	// "com.apple." nonlibrary kexts
14931 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
14932 	    /* libs? */ 0, newlist, newlist_size) != 0) {
14933 		goto finish;
14934 	}
14935 	// "com.apple." library kexts
14936 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
14937 	    /* libs? */ 1, newlist, newlist_size) != 0) {
14938 		goto finish;
14939 	}
14940 
14941 	if (loaded_kext_paniclist) {
14942 		kfree_data(loaded_kext_paniclist, loaded_kext_paniclist_size);
14943 	}
14944 	loaded_kext_paniclist = newlist;
14945 	newlist = NULL;
14946 	loaded_kext_paniclist_size = newlist_size;
14947 
14948 finish:
14949 	if (newlist) {
14950 		kfree_data(newlist, newlist_size);
14951 	}
14952 	return;
14953 }
14954 
14955 /*********************************************************************
14956 * Assumes sKextLock is held.
14957 *********************************************************************/
14958 void
14959 OSKext::savePanicString(bool isLoading)
14960 {
14961 	u_long len;
14962 
14963 	if (!kmod_info) {
14964 		return;         // do not goto finish here b/c of lock
14965 	}
14966 
14967 	len = assemble_identifier_and_version( kmod_info,
14968 	    (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
14969 	    (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
14970 	if (!len) {
14971 		printf("error saving unloaded kext info\n");
14972 		goto finish;
14973 	}
14974 
14975 	if (isLoading) {
14976 		last_loaded_strlen = len;
14977 		last_loaded_address = (void *)kmod_info->address;
14978 		last_loaded_size = kmod_info->size;
14979 		clock_get_uptime(&last_loaded_timestamp);
14980 	} else {
14981 		last_unloaded_strlen = len;
14982 		last_unloaded_address = (void *)kmod_info->address;
14983 		last_unloaded_size = kmod_info->size;
14984 		clock_get_uptime(&last_unloaded_timestamp);
14985 	}
14986 
14987 finish:
14988 	return;
14989 }
14990 
14991 /*********************************************************************
14992 *********************************************************************/
14993 /* static */
14994 void
14995 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
14996 {
14997 	if (last_loaded_strlen) {
14998 		printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n",
14999 		    AbsoluteTime_to_scalar(&last_loaded_timestamp),
15000 		    last_loaded_strlen, last_loaded_str_buf,
15001 		    last_loaded_address, last_loaded_size);
15002 	}
15003 
15004 	if (last_unloaded_strlen) {
15005 		printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n",
15006 		    AbsoluteTime_to_scalar(&last_unloaded_timestamp),
15007 		    last_unloaded_strlen, last_unloaded_str_buf,
15008 		    last_unloaded_address, last_unloaded_size);
15009 	}
15010 
15011 	printf_func("loaded kexts:\n");
15012 	if (loaded_kext_paniclist &&
15013 	    pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
15014 	    loaded_kext_paniclist[0]) {
15015 		printf_func("%.*s",
15016 		    strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
15017 		    loaded_kext_paniclist);
15018 	} else {
15019 		printf_func("(none)\n");
15020 	}
15021 	return;
15022 }
15023 
15024 /*********************************************************************
15025 * Assumes sKextLock is held.
15026 *********************************************************************/
15027 /* static */
15028 void
15029 OSKext::updateLoadedKextSummaries(void)
15030 {
15031 	kern_return_t result = KERN_FAILURE;
15032 	OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
15033 	OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
15034 	OSKext *aKext;
15035 	vm_map_offset_t start, end;
15036 	size_t summarySize = 0;
15037 	size_t size;
15038 	u_int count;
15039 	u_int maxKexts;
15040 	u_int i, j;
15041 	OSKextActiveAccount * accountingList;
15042 	OSKextActiveAccount * prevAccountingList;
15043 	uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
15044 
15045 	prevAccountingList = NULL;
15046 	prevAccountingListCount = 0;
15047 
15048 #if DEVELOPMENT || DEBUG
15049 	if (IORecursiveLockHaveLock(sKextLock) == false) {
15050 		panic("sKextLock must be held");
15051 	}
15052 #endif
15053 
15054 	IOLockLock(sKextSummariesLock);
15055 
15056 	count = sLoadedKexts->getCount();
15057 	for (i = 0, maxKexts = 0; i < count; ++i) {
15058 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
15059 		maxKexts += (aKext && aKext->isExecutable());
15060 	}
15061 
15062 	if (!maxKexts) {
15063 		goto finish;
15064 	}
15065 	if (maxKexts < kOSKextTypicalLoadCount) {
15066 		maxKexts = kOSKextTypicalLoadCount;
15067 	}
15068 
15069 	/* Calculate the size needed for the new summary headers.
15070 	 */
15071 
15072 	size = sizeof(*gLoadedKextSummaries);
15073 	size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
15074 	size = round_page(size);
15075 
15076 	if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
15077 		if (gLoadedKextSummaries) {
15078 			kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
15079 			gLoadedKextSummaries = NULL;
15080 			gLoadedKextSummariesTimestamp = mach_absolute_time();
15081 			sLoadedKextSummariesAllocSize = 0;
15082 		}
15083 		result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, VM_KERN_MEMORY_OSKEXT);
15084 		if (result != KERN_SUCCESS) {
15085 			goto finish;
15086 		}
15087 		summaryHeader = summaryHeaderAlloc;
15088 		summarySize = size;
15089 	} else {
15090 		summaryHeader = gLoadedKextSummaries;
15091 		summarySize = sLoadedKextSummariesAllocSize;
15092 
15093 		start = (vm_map_offset_t) summaryHeader;
15094 		end = start + summarySize;
15095 		result = vm_map_protect(kernel_map,
15096 		    start,
15097 		    end,
15098 		    VM_PROT_DEFAULT,
15099 		    FALSE);
15100 		if (result != KERN_SUCCESS) {
15101 			goto finish;
15102 		}
15103 	}
15104 
15105 	/* Populate the summary header.
15106 	 */
15107 
15108 	bzero(summaryHeader, summarySize);
15109 	summaryHeader->version = kOSKextLoadedKextSummaryVersion;
15110 	summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
15111 
15112 	/* Populate each kext summary.
15113 	 */
15114 
15115 	count = sLoadedKexts->getCount();
15116 	accountingListAlloc = 0;
15117 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
15118 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
15119 		if (!aKext || !aKext->isExecutable()) {
15120 			continue;
15121 		}
15122 
15123 		aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
15124 		summaryHeader->numSummaries++;
15125 		accountingListAlloc++;
15126 	}
15127 
15128 	accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
15129 	accountingListCount = 0;
15130 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
15131 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
15132 		if (!aKext || !aKext->isExecutable()) {
15133 			continue;
15134 		}
15135 
15136 		OSKextActiveAccount activeAccount;
15137 		aKext->updateActiveAccount(&activeAccount);
15138 		// order by address
15139 		for (idx = 0; idx < accountingListCount; idx++) {
15140 			if (activeAccount.address < accountingList[idx].address) {
15141 				break;
15142 			}
15143 		}
15144 		bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
15145 		accountingList[idx] = activeAccount;
15146 		accountingListCount++;
15147 	}
15148 	assert(accountingListCount == accountingListAlloc);
15149 	/* Write protect the buffer and move it into place.
15150 	 */
15151 
15152 	start = (vm_map_offset_t) summaryHeader;
15153 	end = start + summarySize;
15154 
15155 	result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
15156 	if (result != KERN_SUCCESS) {
15157 		goto finish;
15158 	}
15159 
15160 	gLoadedKextSummaries = summaryHeader;
15161 	gLoadedKextSummariesTimestamp = mach_absolute_time();
15162 	sLoadedKextSummariesAllocSize = summarySize;
15163 	summaryHeaderAlloc = NULL;
15164 
15165 	/* Call the magic breakpoint function through a static function pointer so
15166 	 * the compiler can't optimize the function away.
15167 	 */
15168 	if (sLoadedKextSummariesUpdated) {
15169 		(*sLoadedKextSummariesUpdated)();
15170 	}
15171 
15172 	IOSimpleLockLock(sKextAccountsLock);
15173 	prevAccountingList      = sKextAccounts;
15174 	prevAccountingListCount = sKextAccountsCount;
15175 	sKextAccounts           = accountingList;
15176 	sKextAccountsCount      = accountingListCount;
15177 	IOSimpleLockUnlock(sKextAccountsLock);
15178 
15179 finish:
15180 	IOLockUnlock(sKextSummariesLock);
15181 
15182 	/* If we had to allocate a new buffer but failed to generate the summaries,
15183 	 * free that now.
15184 	 */
15185 	if (summaryHeaderAlloc) {
15186 		kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
15187 	}
15188 	if (prevAccountingList) {
15189 		IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
15190 	}
15191 
15192 	return;
15193 }
15194 
15195 /*********************************************************************
15196 *********************************************************************/
15197 void
15198 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
15199 {
15200 	OSSharedPtr<OSData> uuid;
15201 
15202 	strlcpy(summary->name, getIdentifierCString(),
15203 	    sizeof(summary->name));
15204 
15205 	uuid = copyUUID();
15206 	if (uuid) {
15207 		memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
15208 	}
15209 
15210 	if (flags.builtin) {
15211 //      this value will stop lldb from parsing the mach-o header
15212 //      summary->address = UINT64_MAX;
15213 //      summary->size = 0;
15214 		summary->address = kmod_info->address;
15215 		summary->size = kmod_info->size;
15216 	} else {
15217 		summary->address = kmod_info->address;
15218 		summary->size = kmod_info->size;
15219 	}
15220 	summary->version = getVersion();
15221 	summary->loadTag = kmod_info->id;
15222 	summary->flags = 0;
15223 	summary->reference_list = (uint64_t) kmod_info->reference_list;
15224 
15225 	summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size);
15226 	if (summary->text_exec_address == 0) {
15227 		// Fallback to __TEXT
15228 		summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size);
15229 	}
15230 	return;
15231 }
15232 
15233 /*********************************************************************
15234 *********************************************************************/
15235 
15236 void
15237 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
15238 {
15239 	kernel_mach_header_t     *hdr = NULL;
15240 	kernel_segment_command_t *seg = NULL;
15241 
15242 	bzero(accountp, sizeof(*accountp));
15243 
15244 	hdr = (kernel_mach_header_t *)kmod_info->address;
15245 	if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) {
15246 		/*
15247 		 * If this kext supports split segments (or is in a new
15248 		 * MH_FILESET kext collection), use the first
15249 		 * executable segment as the range for instructions
15250 		 * (and thus for backtracing.
15251 		 */
15252 		for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
15253 			if (seg->initprot & VM_PROT_EXECUTE) {
15254 				break;
15255 			}
15256 		}
15257 	}
15258 	if (seg) {
15259 		accountp->address = seg->vmaddr;
15260 		if (accountp->address) {
15261 			accountp->address_end = seg->vmaddr + seg->vmsize;
15262 		}
15263 	} else {
15264 		/* For non-split kexts and for kexts without executable
15265 		 * segments, just use the kmod_info range (as the kext
15266 		 * is either all in one range or should not show up in
15267 		 * instruction backtraces).
15268 		 */
15269 		accountp->address = kmod_info->address;
15270 		if (accountp->address) {
15271 			accountp->address_end = kmod_info->address + kmod_info->size;
15272 		}
15273 	}
15274 
15275 	accountp->account = this->account;
15276 }
15277 
15278 bool
15279 OSKext::isDriverKit(void)
15280 {
15281 	OSString *bundleType;
15282 
15283 	if (infoDict) {
15284 		bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
15285 		if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
15286 			return TRUE;
15287 		}
15288 	}
15289 	return FALSE;
15290 }
15291 
15292 bool
15293 OSKext::isInFileset(void)
15294 {
15295 	if (!kmod_info) {
15296 		goto check_prelinked;
15297 	}
15298 
15299 	if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) {
15300 		return true;
15301 	}
15302 
15303 check_prelinked:
15304 	if (isPrelinked()) {
15305 		/*
15306 		 * If we haven't setup kmod_info yet, but we know
15307 		 * we're loading a prelinked kext in an MH_FILESET KC,
15308 		 * then return true
15309 		 */
15310 		kc_format_t kc_format;
15311 		if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
15312 			return true;
15313 		}
15314 	}
15315 	return false;
15316 }
15317 
15318 bool
15319 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg)
15320 {
15321 	kern_return_t result;
15322 	if (!super::init()) {
15323 		return false;
15324 	}
15325 	if (seg == nullptr) {
15326 		return false;
15327 	}
15328 	result = kmem_alloc_pageable(kernel_map, (vm_offset_t *)&data, seg->vmsize, VM_KERN_MEMORY_KEXT);
15329 	if (result != KERN_SUCCESS) {
15330 		return false;
15331 	}
15332 	memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize);
15333 	savedSegment = seg;
15334 	vmsize = seg->vmsize;
15335 	vmaddr = seg->vmaddr;
15336 	return true;
15337 }
15338 
15339 OSSharedPtr<OSKextSavedMutableSegment>
15340 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg)
15341 {
15342 	OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>();
15343 	if (me && !me->initWithSegment(seg)) {
15344 		return nullptr;
15345 	}
15346 	return me;
15347 }
15348 
15349 void
15350 OSKextSavedMutableSegment::free(void)
15351 {
15352 	if (data) {
15353 		kmem_free(kernel_map, (vm_offset_t)data, vmsize);
15354 	}
15355 }
15356 
15357 vm_offset_t
15358 OSKextSavedMutableSegment::getVMAddr() const
15359 {
15360 	return vmaddr;
15361 }
15362 
15363 vm_offset_t
15364 OSKextSavedMutableSegment::getVMSize() const
15365 {
15366 	return vmsize;
15367 }
15368 
15369 OSReturn
15370 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg)
15371 {
15372 	if (seg != savedSegment) {
15373 		return kOSKextReturnInvalidArgument;
15374 	}
15375 	if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) {
15376 		return kOSKextReturnInvalidArgument;
15377 	}
15378 	memcpy((void *)seg->vmaddr, data, vmsize);
15379 	return kOSReturnSuccess;
15380 }
15381 
15382 extern "C" kern_return_t
15383 OSKextSetReceiptQueried(void)
15384 {
15385 	OSKextLog(/* kext */ NULL,
15386 	    kOSKextLogStepLevel | kOSKextLogGeneralFlag,
15387 	    "Setting kext receipt as queried");
15388 
15389 	IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue);
15390 	return KERN_SUCCESS;
15391 }
15392 
15393 extern "C" const vm_allocation_site_t *
15394 OSKextGetAllocationSiteForCaller(uintptr_t address)
15395 {
15396 	OSKextActiveAccount *  active;
15397 	vm_allocation_site_t * site;
15398 	vm_allocation_site_t * releasesite;
15399 
15400 	uint32_t baseIdx;
15401 	uint32_t lim;
15402 #if  __has_feature(ptrauth_calls)
15403 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
15404 #endif /*  __has_feature(ptrauth_calls) */
15405 
15406 	IOSimpleLockLock(sKextAccountsLock);
15407 	site = releasesite = NULL;
15408 
15409 	// bsearch sKextAccounts list
15410 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15411 		active = &sKextAccounts[baseIdx + (lim >> 1)];
15412 		if ((address >= active->address) && (address < active->address_end)) {
15413 			site = &active->account->site;
15414 			if (!site->tag) {
15415 				vm_tag_alloc_locked(site, &releasesite);
15416 			}
15417 			break;
15418 		} else if (address > active->address) {
15419 			// move right
15420 			baseIdx += (lim >> 1) + 1;
15421 			lim--;
15422 		}
15423 		// else move left
15424 	}
15425 	IOSimpleLockUnlock(sKextAccountsLock);
15426 	if (releasesite) {
15427 		kern_allocation_name_release(releasesite);
15428 	}
15429 
15430 	return site;
15431 }
15432 
15433 #if DEVELOPMENT || DEBUG
15434 extern "C" void
15435 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *))
15436 {
15437 	OSKextActiveAccount *  active;
15438 
15439 	uint32_t baseIdx;
15440 	uint32_t lim;
15441 #if  __has_feature(ptrauth_calls)
15442 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
15443 #endif /*  __has_feature(ptrauth_calls) */
15444 
15445 	IOSimpleLockLock(sKextAccountsLock);
15446 
15447 	// bsearch sKextAccounts list
15448 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15449 		active = &sKextAccounts[baseIdx + (lim >> 1)];
15450 		if ((address >= active->address) && (address < active->address_end)) {
15451 			cb(&active->account->task_refgrp);
15452 			break;
15453 		} else if (address > active->address) {
15454 			// move right
15455 			baseIdx += (lim >> 1) + 1;
15456 			lim--;
15457 		}
15458 		// else move left
15459 	}
15460 	IOSimpleLockUnlock(sKextAccountsLock);
15461 }
15462 #endif /* DEVELOPMENT || DEBUG */
15463 
15464 extern "C" uint32_t
15465 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
15466 {
15467 	OSKextAccount * account = (typeof(account))site;
15468 	const char    * kname;
15469 
15470 	if (name) {
15471 		if (account->kext) {
15472 			kname = account->kext->getIdentifierCString();
15473 		} else {
15474 			kname = "<>";
15475 		}
15476 		strlcpy(name, kname, namelen);
15477 	}
15478 
15479 	return account->loadTag;
15480 }
15481 
15482 extern "C" void
15483 OSKextFreeSite(vm_allocation_site_t * site)
15484 {
15485 	OSKextAccount * freeAccount = (typeof(freeAccount))site;
15486 	IOFreeType(freeAccount, OSKextAccount);
15487 }
15488 
15489 /*********************************************************************
15490 *********************************************************************/
15491 
15492 #if CONFIG_IMAGEBOOT
15493 int
15494 OSKextGetUUIDForName(const char *name, uuid_t uuid)
15495 {
15496 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name);
15497 	if (!kext) {
15498 		return 1;
15499 	}
15500 
15501 	OSSharedPtr<OSData> uuid_data = kext->copyUUID();
15502 	if (uuid_data) {
15503 		memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
15504 		return 0;
15505 	}
15506 
15507 	return 1;
15508 }
15509 #endif
15510 
15511 static int
15512 sysctl_willuserspacereboot
15513 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
15514 {
15515 	int new_value = 0, old_value = 0, changed = 0;
15516 	int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
15517 	if (error) {
15518 		return error;
15519 	}
15520 	if (changed) {
15521 		OSKext::willUserspaceReboot();
15522 	}
15523 	return 0;
15524 }
15525 
15526 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot,
15527     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
15528     NULL, 0, sysctl_willuserspacereboot, "I", "");
15529